summaryrefslogtreecommitdiffstats
path: root/fs/afs/fsclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/fsclient.c')
-rw-r--r--fs/afs/fsclient.c272
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 */
277static int afs_deliver_fs_fetch_status(struct afs_call *call) 277static 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 */
303static const struct afs_call_type afs_RXFSFetchStatus = { 303static 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 */
1955static 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 */
1990static 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 */
2000int 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 */
2041static 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 */
2155static 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 */
2165int 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}