diff options
Diffstat (limited to 'fs/afs/fsclient.c')
-rw-r--r-- | fs/afs/fsclient.c | 272 |
1 files changed, 266 insertions, 6 deletions
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 88ec38c2d83c..75554ee98d02 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
@@ -94,7 +94,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, | |||
94 | data_version |= (u64) ntohl(*bp++) << 32; | 94 | data_version |= (u64) ntohl(*bp++) << 32; |
95 | EXTRACT(status->lock_count); | 95 | EXTRACT(status->lock_count); |
96 | size |= (u64) ntohl(*bp++) << 32; | 96 | size |= (u64) ntohl(*bp++) << 32; |
97 | bp++; /* spare 4 */ | 97 | EXTRACT(status->abort_code); /* spare 4 */ |
98 | *_bp = bp; | 98 | *_bp = bp; |
99 | 99 | ||
100 | if (size != status->size) { | 100 | if (size != status->size) { |
@@ -274,7 +274,7 @@ static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp, | |||
274 | /* | 274 | /* |
275 | * deliver reply data to an FS.FetchStatus | 275 | * deliver reply data to an FS.FetchStatus |
276 | */ | 276 | */ |
277 | static int afs_deliver_fs_fetch_status(struct afs_call *call) | 277 | static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) |
278 | { | 278 | { |
279 | struct afs_vnode *vnode = call->reply[0]; | 279 | struct afs_vnode *vnode = call->reply[0]; |
280 | const __be32 *bp; | 280 | const __be32 *bp; |
@@ -300,10 +300,10 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call) | |||
300 | /* | 300 | /* |
301 | * FS.FetchStatus operation type | 301 | * FS.FetchStatus operation type |
302 | */ | 302 | */ |
303 | static const struct afs_call_type afs_RXFSFetchStatus = { | 303 | static const struct afs_call_type afs_RXFSFetchStatus_vnode = { |
304 | .name = "FS.FetchStatus", | 304 | .name = "FS.FetchStatus(vnode)", |
305 | .op = afs_FS_FetchStatus, | 305 | .op = afs_FS_FetchStatus, |
306 | .deliver = afs_deliver_fs_fetch_status, | 306 | .deliver = afs_deliver_fs_fetch_status_vnode, |
307 | .destructor = afs_flat_call_destructor, | 307 | .destructor = afs_flat_call_destructor, |
308 | }; | 308 | }; |
309 | 309 | ||
@@ -320,7 +320,8 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
320 | _enter(",%x,{%x:%u},,", | 320 | _enter(",%x,{%x:%u},,", |
321 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 321 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
322 | 322 | ||
323 | call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); | 323 | call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus_vnode, |
324 | 16, (21 + 3 + 6) * 4); | ||
324 | if (!call) { | 325 | if (!call) { |
325 | fc->ac.error = -ENOMEM; | 326 | fc->ac.error = -ENOMEM; |
326 | return -ENOMEM; | 327 | return -ENOMEM; |
@@ -1947,3 +1948,262 @@ int afs_fs_get_capabilities(struct afs_net *net, | |||
1947 | trace_afs_make_fs_call(call, NULL); | 1948 | trace_afs_make_fs_call(call, NULL); |
1948 | return afs_make_call(ac, call, GFP_NOFS, false); | 1949 | return afs_make_call(ac, call, GFP_NOFS, false); |
1949 | } | 1950 | } |
1951 | |||
1952 | /* | ||
1953 | * Deliver reply data to an FS.FetchStatus with no vnode. | ||
1954 | */ | ||
1955 | static int afs_deliver_fs_fetch_status(struct afs_call *call) | ||
1956 | { | ||
1957 | struct afs_file_status *status = call->reply[1]; | ||
1958 | struct afs_callback *callback = call->reply[2]; | ||
1959 | struct afs_volsync *volsync = call->reply[3]; | ||
1960 | struct afs_vnode *vnode = call->reply[0]; | ||
1961 | const __be32 *bp; | ||
1962 | int ret; | ||
1963 | |||
1964 | ret = afs_transfer_reply(call); | ||
1965 | if (ret < 0) | ||
1966 | return ret; | ||
1967 | |||
1968 | _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); | ||
1969 | |||
1970 | /* unmarshall the reply once we've received all of it */ | ||
1971 | bp = call->buffer; | ||
1972 | xdr_decode_AFSFetchStatus(&bp, status, vnode, NULL); | ||
1973 | callback[call->count].version = ntohl(bp[0]); | ||
1974 | callback[call->count].expiry = ntohl(bp[1]); | ||
1975 | callback[call->count].type = ntohl(bp[2]); | ||
1976 | if (vnode) | ||
1977 | xdr_decode_AFSCallBack(call, vnode, &bp); | ||
1978 | else | ||
1979 | bp += 3; | ||
1980 | if (volsync) | ||
1981 | xdr_decode_AFSVolSync(&bp, volsync); | ||
1982 | |||
1983 | _leave(" = 0 [done]"); | ||
1984 | return 0; | ||
1985 | } | ||
1986 | |||
1987 | /* | ||
1988 | * FS.FetchStatus operation type | ||
1989 | */ | ||
1990 | static const struct afs_call_type afs_RXFSFetchStatus = { | ||
1991 | .name = "FS.FetchStatus", | ||
1992 | .op = afs_FS_FetchStatus, | ||
1993 | .deliver = afs_deliver_fs_fetch_status, | ||
1994 | .destructor = afs_flat_call_destructor, | ||
1995 | }; | ||
1996 | |||
1997 | /* | ||
1998 | * Fetch the status information for a fid without needing a vnode handle. | ||
1999 | */ | ||
2000 | int afs_fs_fetch_status(struct afs_fs_cursor *fc, | ||
2001 | struct afs_net *net, | ||
2002 | struct afs_fid *fid, | ||
2003 | struct afs_file_status *status, | ||
2004 | struct afs_callback *callback, | ||
2005 | struct afs_volsync *volsync) | ||
2006 | { | ||
2007 | struct afs_call *call; | ||
2008 | __be32 *bp; | ||
2009 | |||
2010 | _enter(",%x,{%x:%u},,", | ||
2011 | key_serial(fc->key), fid->vid, fid->vnode); | ||
2012 | |||
2013 | call = afs_alloc_flat_call(net, &afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); | ||
2014 | if (!call) { | ||
2015 | fc->ac.error = -ENOMEM; | ||
2016 | return -ENOMEM; | ||
2017 | } | ||
2018 | |||
2019 | call->key = fc->key; | ||
2020 | call->reply[0] = NULL; /* vnode for fid[0] */ | ||
2021 | call->reply[1] = status; | ||
2022 | call->reply[2] = callback; | ||
2023 | call->reply[3] = volsync; | ||
2024 | |||
2025 | /* marshall the parameters */ | ||
2026 | bp = call->request; | ||
2027 | bp[0] = htonl(FSFETCHSTATUS); | ||
2028 | bp[1] = htonl(fid->vid); | ||
2029 | bp[2] = htonl(fid->vnode); | ||
2030 | bp[3] = htonl(fid->unique); | ||
2031 | |||
2032 | call->cb_break = fc->cb_break; | ||
2033 | afs_use_fs_server(call, fc->cbi); | ||
2034 | trace_afs_make_fs_call(call, fid); | ||
2035 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
2036 | } | ||
2037 | |||
2038 | /* | ||
2039 | * Deliver reply data to an FS.InlineBulkStatus call | ||
2040 | */ | ||
2041 | static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | ||
2042 | { | ||
2043 | struct afs_file_status *statuses; | ||
2044 | struct afs_callback *callbacks; | ||
2045 | struct afs_vnode *vnode = call->reply[0]; | ||
2046 | const __be32 *bp; | ||
2047 | u32 tmp; | ||
2048 | int ret; | ||
2049 | |||
2050 | _enter("{%u}", call->unmarshall); | ||
2051 | |||
2052 | switch (call->unmarshall) { | ||
2053 | case 0: | ||
2054 | call->offset = 0; | ||
2055 | call->unmarshall++; | ||
2056 | |||
2057 | /* Extract the file status count and array in two steps */ | ||
2058 | case 1: | ||
2059 | _debug("extract status count"); | ||
2060 | ret = afs_extract_data(call, &call->tmp, 4, true); | ||
2061 | if (ret < 0) | ||
2062 | return ret; | ||
2063 | |||
2064 | tmp = ntohl(call->tmp); | ||
2065 | _debug("status count: %u/%u", tmp, call->count2); | ||
2066 | if (tmp != call->count2) | ||
2067 | return -EBADMSG; | ||
2068 | |||
2069 | call->count = 0; | ||
2070 | call->unmarshall++; | ||
2071 | more_counts: | ||
2072 | call->offset = 0; | ||
2073 | |||
2074 | case 2: | ||
2075 | _debug("extract status array %u", call->count); | ||
2076 | ret = afs_extract_data(call, call->buffer, 21 * 4, true); | ||
2077 | if (ret < 0) | ||
2078 | return ret; | ||
2079 | |||
2080 | bp = call->buffer; | ||
2081 | statuses = call->reply[1]; | ||
2082 | xdr_decode_AFSFetchStatus(&bp, &statuses[call->count], | ||
2083 | call->count == 0 ? vnode : NULL, | ||
2084 | NULL); | ||
2085 | |||
2086 | call->count++; | ||
2087 | if (call->count < call->count2) | ||
2088 | goto more_counts; | ||
2089 | |||
2090 | call->count = 0; | ||
2091 | call->unmarshall++; | ||
2092 | call->offset = 0; | ||
2093 | |||
2094 | /* Extract the callback count and array in two steps */ | ||
2095 | case 3: | ||
2096 | _debug("extract CB count"); | ||
2097 | ret = afs_extract_data(call, &call->tmp, 4, true); | ||
2098 | if (ret < 0) | ||
2099 | return ret; | ||
2100 | |||
2101 | tmp = ntohl(call->tmp); | ||
2102 | _debug("CB count: %u", tmp); | ||
2103 | if (tmp != call->count2) | ||
2104 | return -EBADMSG; | ||
2105 | call->count = 0; | ||
2106 | call->unmarshall++; | ||
2107 | more_cbs: | ||
2108 | call->offset = 0; | ||
2109 | |||
2110 | case 4: | ||
2111 | _debug("extract CB array"); | ||
2112 | ret = afs_extract_data(call, call->buffer, 3 * 4, true); | ||
2113 | if (ret < 0) | ||
2114 | return ret; | ||
2115 | |||
2116 | _debug("unmarshall CB array"); | ||
2117 | bp = call->buffer; | ||
2118 | callbacks = call->reply[2]; | ||
2119 | callbacks[call->count].version = ntohl(bp[0]); | ||
2120 | callbacks[call->count].expiry = ntohl(bp[1]); | ||
2121 | callbacks[call->count].type = ntohl(bp[2]); | ||
2122 | statuses = call->reply[1]; | ||
2123 | if (call->count == 0 && vnode && statuses[0].abort_code == 0) | ||
2124 | xdr_decode_AFSCallBack(call, vnode, &bp); | ||
2125 | call->count++; | ||
2126 | if (call->count < call->count2) | ||
2127 | goto more_cbs; | ||
2128 | |||
2129 | call->offset = 0; | ||
2130 | call->unmarshall++; | ||
2131 | |||
2132 | case 5: | ||
2133 | ret = afs_extract_data(call, call->buffer, 6 * 4, false); | ||
2134 | if (ret < 0) | ||
2135 | return ret; | ||
2136 | |||
2137 | bp = call->buffer; | ||
2138 | if (call->reply[3]) | ||
2139 | xdr_decode_AFSVolSync(&bp, call->reply[3]); | ||
2140 | |||
2141 | call->offset = 0; | ||
2142 | call->unmarshall++; | ||
2143 | |||
2144 | case 6: | ||
2145 | break; | ||
2146 | } | ||
2147 | |||
2148 | _leave(" = 0 [done]"); | ||
2149 | return 0; | ||
2150 | } | ||
2151 | |||
2152 | /* | ||
2153 | * FS.InlineBulkStatus operation type | ||
2154 | */ | ||
2155 | static const struct afs_call_type afs_RXFSInlineBulkStatus = { | ||
2156 | .name = "FS.InlineBulkStatus", | ||
2157 | .op = afs_FS_InlineBulkStatus, | ||
2158 | .deliver = afs_deliver_fs_inline_bulk_status, | ||
2159 | .destructor = afs_flat_call_destructor, | ||
2160 | }; | ||
2161 | |||
2162 | /* | ||
2163 | * Fetch the status information for up to 50 files | ||
2164 | */ | ||
2165 | int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | ||
2166 | struct afs_net *net, | ||
2167 | struct afs_fid *fids, | ||
2168 | struct afs_file_status *statuses, | ||
2169 | struct afs_callback *callbacks, | ||
2170 | unsigned int nr_fids, | ||
2171 | struct afs_volsync *volsync) | ||
2172 | { | ||
2173 | struct afs_call *call; | ||
2174 | __be32 *bp; | ||
2175 | int i; | ||
2176 | |||
2177 | _enter(",%x,{%x:%u},%u", | ||
2178 | key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids); | ||
2179 | |||
2180 | call = afs_alloc_flat_call(net, &afs_RXFSInlineBulkStatus, | ||
2181 | (2 + nr_fids * 3) * 4, | ||
2182 | 21 * 4); | ||
2183 | if (!call) { | ||
2184 | fc->ac.error = -ENOMEM; | ||
2185 | return -ENOMEM; | ||
2186 | } | ||
2187 | |||
2188 | call->key = fc->key; | ||
2189 | call->reply[0] = NULL; /* vnode for fid[0] */ | ||
2190 | call->reply[1] = statuses; | ||
2191 | call->reply[2] = callbacks; | ||
2192 | call->reply[3] = volsync; | ||
2193 | call->count2 = nr_fids; | ||
2194 | |||
2195 | /* marshall the parameters */ | ||
2196 | bp = call->request; | ||
2197 | *bp++ = htonl(FSINLINEBULKSTATUS); | ||
2198 | *bp++ = htonl(nr_fids); | ||
2199 | for (i = 0; i < nr_fids; i++) { | ||
2200 | *bp++ = htonl(fids[i].vid); | ||
2201 | *bp++ = htonl(fids[i].vnode); | ||
2202 | *bp++ = htonl(fids[i].unique); | ||
2203 | } | ||
2204 | |||
2205 | call->cb_break = fc->cb_break; | ||
2206 | afs_use_fs_server(call, fc->cbi); | ||
2207 | trace_afs_make_fs_call(call, &fids[0]); | ||
2208 | return afs_make_call(&fc->ac, call, GFP_NOFS, false); | ||
2209 | } | ||