diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/callback.h | 19 | ||||
-rw-r--r-- | fs/nfs/callback_proc.c | 6 | ||||
-rw-r--r-- | fs/nfs/callback_xdr.c | 69 |
3 files changed, 93 insertions, 1 deletions
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index b678e3e15bd9..f6768ac09190 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h | |||
@@ -138,6 +138,25 @@ extern __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, | |||
138 | void *dummy, | 138 | void *dummy, |
139 | struct cb_process_state *cps); | 139 | struct cb_process_state *cps); |
140 | 140 | ||
141 | struct cb_layoutrecallargs { | ||
142 | struct sockaddr *cbl_addr; | ||
143 | uint32_t cbl_recall_type; | ||
144 | uint32_t cbl_layout_type; | ||
145 | uint32_t cbl_layoutchanged; | ||
146 | union { | ||
147 | struct { | ||
148 | struct nfs_fh cbl_fh; | ||
149 | struct pnfs_layout_range cbl_range; | ||
150 | nfs4_stateid cbl_stateid; | ||
151 | }; | ||
152 | struct nfs_fsid cbl_fsid; | ||
153 | }; | ||
154 | }; | ||
155 | |||
156 | extern unsigned nfs4_callback_layoutrecall( | ||
157 | struct cb_layoutrecallargs *args, | ||
158 | void *dummy, struct cb_process_state *cps); | ||
159 | |||
141 | extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses); | 160 | extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses); |
142 | extern void nfs4_cb_take_slot(struct nfs_client *clp); | 161 | extern void nfs4_cb_take_slot(struct nfs_client *clp); |
143 | #endif /* CONFIG_NFS_V4_1 */ | 162 | #endif /* CONFIG_NFS_V4_1 */ |
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index c1bead2f3e04..c1bb157e94bd 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -107,6 +107,12 @@ int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nf | |||
107 | 107 | ||
108 | #if defined(CONFIG_NFS_V4_1) | 108 | #if defined(CONFIG_NFS_V4_1) |
109 | 109 | ||
110 | __be32 nfs4_callback_layoutrecall(struct cb_layoutrecallargs *args, | ||
111 | void *dummy, struct cb_process_state *cps) | ||
112 | { | ||
113 | return cpu_to_be32(NFS4ERR_NOTSUPP); /* STUB */ | ||
114 | } | ||
115 | |||
110 | int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) | 116 | int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) |
111 | { | 117 | { |
112 | if (delegation == NULL) | 118 | if (delegation == NULL) |
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 7a2d6c5864ca..23112c263f81 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) | 24 | #define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) |
25 | 25 | ||
26 | #if defined(CONFIG_NFS_V4_1) | 26 | #if defined(CONFIG_NFS_V4_1) |
27 | #define CB_OP_LAYOUTRECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) | ||
27 | #define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \ | 28 | #define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \ |
28 | 4 + 1 + 3) | 29 | 4 + 1 + 3) |
29 | #define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) | 30 | #define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) |
@@ -223,6 +224,66 @@ out: | |||
223 | 224 | ||
224 | #if defined(CONFIG_NFS_V4_1) | 225 | #if defined(CONFIG_NFS_V4_1) |
225 | 226 | ||
227 | static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp, | ||
228 | struct xdr_stream *xdr, | ||
229 | struct cb_layoutrecallargs *args) | ||
230 | { | ||
231 | __be32 *p; | ||
232 | __be32 status = 0; | ||
233 | uint32_t iomode; | ||
234 | |||
235 | args->cbl_addr = svc_addr(rqstp); | ||
236 | p = read_buf(xdr, 4 * sizeof(uint32_t)); | ||
237 | if (unlikely(p == NULL)) { | ||
238 | status = htonl(NFS4ERR_BADXDR); | ||
239 | goto out; | ||
240 | } | ||
241 | |||
242 | args->cbl_layout_type = ntohl(*p++); | ||
243 | /* Depite the spec's xdr, iomode really belongs in the FILE switch, | ||
244 | * as it is unuseable and ignored with the other types. | ||
245 | */ | ||
246 | iomode = ntohl(*p++); | ||
247 | args->cbl_layoutchanged = ntohl(*p++); | ||
248 | args->cbl_recall_type = ntohl(*p++); | ||
249 | |||
250 | if (args->cbl_recall_type == RETURN_FILE) { | ||
251 | args->cbl_range.iomode = iomode; | ||
252 | status = decode_fh(xdr, &args->cbl_fh); | ||
253 | if (unlikely(status != 0)) | ||
254 | goto out; | ||
255 | |||
256 | p = read_buf(xdr, 2 * sizeof(uint64_t)); | ||
257 | if (unlikely(p == NULL)) { | ||
258 | status = htonl(NFS4ERR_BADXDR); | ||
259 | goto out; | ||
260 | } | ||
261 | p = xdr_decode_hyper(p, &args->cbl_range.offset); | ||
262 | p = xdr_decode_hyper(p, &args->cbl_range.length); | ||
263 | status = decode_stateid(xdr, &args->cbl_stateid); | ||
264 | if (unlikely(status != 0)) | ||
265 | goto out; | ||
266 | } else if (args->cbl_recall_type == RETURN_FSID) { | ||
267 | p = read_buf(xdr, 2 * sizeof(uint64_t)); | ||
268 | if (unlikely(p == NULL)) { | ||
269 | status = htonl(NFS4ERR_BADXDR); | ||
270 | goto out; | ||
271 | } | ||
272 | p = xdr_decode_hyper(p, &args->cbl_fsid.major); | ||
273 | p = xdr_decode_hyper(p, &args->cbl_fsid.minor); | ||
274 | } else if (args->cbl_recall_type != RETURN_ALL) { | ||
275 | status = htonl(NFS4ERR_BADXDR); | ||
276 | goto out; | ||
277 | } | ||
278 | dprintk("%s: ltype 0x%x iomode %d changed %d recall_type %d\n", | ||
279 | __func__, | ||
280 | args->cbl_layout_type, iomode, | ||
281 | args->cbl_layoutchanged, args->cbl_recall_type); | ||
282 | out: | ||
283 | dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); | ||
284 | return status; | ||
285 | } | ||
286 | |||
226 | static __be32 decode_sessionid(struct xdr_stream *xdr, | 287 | static __be32 decode_sessionid(struct xdr_stream *xdr, |
227 | struct nfs4_sessionid *sid) | 288 | struct nfs4_sessionid *sid) |
228 | { | 289 | { |
@@ -577,10 +638,10 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) | |||
577 | case OP_CB_SEQUENCE: | 638 | case OP_CB_SEQUENCE: |
578 | case OP_CB_RECALL_ANY: | 639 | case OP_CB_RECALL_ANY: |
579 | case OP_CB_RECALL_SLOT: | 640 | case OP_CB_RECALL_SLOT: |
641 | case OP_CB_LAYOUTRECALL: | ||
580 | *op = &callback_ops[op_nr]; | 642 | *op = &callback_ops[op_nr]; |
581 | break; | 643 | break; |
582 | 644 | ||
583 | case OP_CB_LAYOUTRECALL: | ||
584 | case OP_CB_NOTIFY_DEVICEID: | 645 | case OP_CB_NOTIFY_DEVICEID: |
585 | case OP_CB_NOTIFY: | 646 | case OP_CB_NOTIFY: |
586 | case OP_CB_PUSH_DELEG: | 647 | case OP_CB_PUSH_DELEG: |
@@ -783,6 +844,12 @@ static struct callback_op callback_ops[] = { | |||
783 | .res_maxsize = CB_OP_RECALL_RES_MAXSZ, | 844 | .res_maxsize = CB_OP_RECALL_RES_MAXSZ, |
784 | }, | 845 | }, |
785 | #if defined(CONFIG_NFS_V4_1) | 846 | #if defined(CONFIG_NFS_V4_1) |
847 | [OP_CB_LAYOUTRECALL] = { | ||
848 | .process_op = (callback_process_op_t)nfs4_callback_layoutrecall, | ||
849 | .decode_args = | ||
850 | (callback_decode_arg_t)decode_layoutrecall_args, | ||
851 | .res_maxsize = CB_OP_LAYOUTRECALL_RES_MAXSZ, | ||
852 | }, | ||
786 | [OP_CB_SEQUENCE] = { | 853 | [OP_CB_SEQUENCE] = { |
787 | .process_op = (callback_process_op_t)nfs4_callback_sequence, | 854 | .process_op = (callback_process_op_t)nfs4_callback_sequence, |
788 | .decode_args = (callback_decode_arg_t)decode_cb_sequence_args, | 855 | .decode_args = (callback_decode_arg_t)decode_cb_sequence_args, |