aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 17:33:41 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 17:33:41 -0400
commit3e1f900bff40460d7bbab0ccd1a9efc3c70aee49 (patch)
treed0e2138ff61bdc9d1bd5b7ae5a1e75267d709afc /fs
parent12795067cfa595434be0236b102a8eb20d578741 (diff)
parent0a87cf128f3d3bc6aa7b1040e73109c974ed875a (diff)
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6: NFSv4: handle lack of clientaddr in option string NFSv4: debug print ntohl(status) in nfs client callback xdr code SUNRPC: Clean up the sillyrename code NFS: Introduce struct nfs_removeargs+nfs_removeres NFS: Use dentry->d_time to store the parent directory verifier. SUNRPC: move bkl locking and xdr proc invocation into a common helper NFSv4: Fix the nfsv4 readlink reply buffer alignment NFSv4: Fix the readdir reply buffer alignment NFSv4: More NFSv4 xdr cleanups NFSv4: Try to recover from getfh failures in nfs4_xdr_dec_open NFSv4: 'constify' lookup arguments. NFSv4: Don't fail nfs4_xdr_dec_open if decode_restorefh() failed NFSv4: Fix open state recovery NFSD/SUNRPC: Fix the automatic selection of RPCSEC_GSS
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig2
-rw-r--r--fs/nfs/callback_xdr.c10
-rw-r--r--fs/nfs/dir.c8
-rw-r--r--fs/nfs/nfs2xdr.c19
-rw-r--r--fs/nfs/nfs3proc.c60
-rw-r--r--fs/nfs/nfs3xdr.c24
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c122
-rw-r--r--fs/nfs/nfs4xdr.c274
-rw-r--r--fs/nfs/proc.c40
-rw-r--r--fs/nfs/super.c7
-rw-r--r--fs/nfs/unlink.c195
12 files changed, 400 insertions, 363 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 6a649902c5ac..58a0650293e1 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1674,7 +1674,7 @@ config NFSD_V3_ACL
1674 1674
1675config NFSD_V4 1675config NFSD_V4
1676 bool "Provide NFSv4 server support (EXPERIMENTAL)" 1676 bool "Provide NFSv4 server support (EXPERIMENTAL)"
1677 depends on NFSD_V3 && EXPERIMENTAL 1677 depends on NFSD && NFSD_V3 && EXPERIMENTAL
1678 select RPCSEC_GSS_KRB5 1678 select RPCSEC_GSS_KRB5
1679 help 1679 help
1680 If you would like to include the NFSv4 server as well as the NFSv2 1680 If you would like to include the NFSv4 server as well as the NFSv2
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 849a2029975d..058ade7efe79 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -179,7 +179,7 @@ static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr
179 args->addr = svc_addr_in(rqstp); 179 args->addr = svc_addr_in(rqstp);
180 status = decode_bitmap(xdr, args->bitmap); 180 status = decode_bitmap(xdr, args->bitmap);
181out: 181out:
182 dprintk("%s: exit with status = %d\n", __FUNCTION__, status); 182 dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(status));
183 return status; 183 return status;
184} 184}
185 185
@@ -200,7 +200,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
200 args->truncate = ntohl(*p); 200 args->truncate = ntohl(*p);
201 status = decode_fh(xdr, &args->fh); 201 status = decode_fh(xdr, &args->fh);
202out: 202out:
203 dprintk("%s: exit with status = %d\n", __FUNCTION__, status); 203 dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(status));
204 return status; 204 return status;
205} 205}
206 206
@@ -349,7 +349,7 @@ static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr,
349 status = encode_attr_mtime(xdr, res->bitmap, &res->mtime); 349 status = encode_attr_mtime(xdr, res->bitmap, &res->mtime);
350 *savep = htonl((unsigned int)((char *)xdr->p - (char *)(savep+1))); 350 *savep = htonl((unsigned int)((char *)xdr->p - (char *)(savep+1)));
351out: 351out:
352 dprintk("%s: exit with status = %d\n", __FUNCTION__, status); 352 dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(status));
353 return status; 353 return status;
354} 354}
355 355
@@ -392,7 +392,7 @@ static __be32 process_op(struct svc_rqst *rqstp,
392 status = res; 392 status = res;
393 if (op->encode_res != NULL && status == 0) 393 if (op->encode_res != NULL && status == 0)
394 status = op->encode_res(rqstp, xdr_out, resp); 394 status = op->encode_res(rqstp, xdr_out, resp);
395 dprintk("%s: done, status = %d\n", __FUNCTION__, status); 395 dprintk("%s: done, status = %d\n", __FUNCTION__, ntohl(status));
396 return status; 396 return status;
397} 397}
398 398
@@ -431,7 +431,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
431 } 431 }
432 *hdr_res.status = status; 432 *hdr_res.status = status;
433 *hdr_res.nops = htonl(nops); 433 *hdr_res.nops = htonl(nops);
434 dprintk("%s: done, status = %u\n", __FUNCTION__, status); 434 dprintk("%s: done, status = %u\n", __FUNCTION__, ntohl(status));
435 return rpc_success; 435 return rpc_success;
436} 436}
437 437
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 322141f4ab48..ea97408e423e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -654,7 +654,7 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
654 654
655 if (IS_ROOT(dentry)) 655 if (IS_ROOT(dentry))
656 return 1; 656 return 1;
657 verf = (unsigned long)dentry->d_fsdata; 657 verf = dentry->d_time;
658 if (nfs_caches_unstable(dir) 658 if (nfs_caches_unstable(dir)
659 || verf != NFS_I(dir)->cache_change_attribute) 659 || verf != NFS_I(dir)->cache_change_attribute)
660 return 0; 660 return 0;
@@ -663,7 +663,7 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
663 663
664static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) 664static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf)
665{ 665{
666 dentry->d_fsdata = (void *)verf; 666 dentry->d_time = verf;
667} 667}
668 668
669static void nfs_refresh_verifier(struct dentry * dentry, unsigned long verf) 669static void nfs_refresh_verifier(struct dentry * dentry, unsigned long verf)
@@ -869,7 +869,7 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
869 if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { 869 if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
870 lock_kernel(); 870 lock_kernel();
871 drop_nlink(inode); 871 drop_nlink(inode);
872 nfs_complete_unlink(dentry); 872 nfs_complete_unlink(dentry, inode);
873 unlock_kernel(); 873 unlock_kernel();
874 } 874 }
875 /* When creating a negative dentry, we want to renew d_time */ 875 /* When creating a negative dentry, we want to renew d_time */
@@ -1411,7 +1411,7 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
1411 nfs_renew_times(dentry); 1411 nfs_renew_times(dentry);
1412 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1412 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
1413 d_move(dentry, sdentry); 1413 d_move(dentry, sdentry);
1414 error = nfs_async_unlink(dentry); 1414 error = nfs_async_unlink(dir, dentry);
1415 /* If we return 0 we don't unlink */ 1415 /* If we return 0 we don't unlink */
1416 } 1416 }
1417 dput(sdentry); 1417 dput(sdentry);
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 7fcc78f2aa71..c5fce7567200 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -43,6 +43,7 @@
43#define NFS_entry_sz (NFS_filename_sz+3) 43#define NFS_entry_sz (NFS_filename_sz+3)
44 44
45#define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz) 45#define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz)
46#define NFS_removeargs_sz (NFS_fhandle_sz+NFS_filename_sz)
46#define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz) 47#define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz)
47#define NFS_readlinkargs_sz (NFS_fhandle_sz) 48#define NFS_readlinkargs_sz (NFS_fhandle_sz)
48#define NFS_readargs_sz (NFS_fhandle_sz+3) 49#define NFS_readargs_sz (NFS_fhandle_sz+3)
@@ -66,7 +67,7 @@
66 * Common NFS XDR functions as inlines 67 * Common NFS XDR functions as inlines
67 */ 68 */
68static inline __be32 * 69static inline __be32 *
69xdr_encode_fhandle(__be32 *p, struct nfs_fh *fhandle) 70xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fhandle)
70{ 71{
71 memcpy(p, fhandle->data, NFS2_FHSIZE); 72 memcpy(p, fhandle->data, NFS2_FHSIZE);
72 return p + XDR_QUADLEN(NFS2_FHSIZE); 73 return p + XDR_QUADLEN(NFS2_FHSIZE);
@@ -204,7 +205,7 @@ nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args)
204 205
205/* 206/*
206 * Encode directory ops argument 207 * Encode directory ops argument
207 * LOOKUP, REMOVE, RMDIR 208 * LOOKUP, RMDIR
208 */ 209 */
209static int 210static int
210nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args) 211nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
@@ -216,6 +217,18 @@ nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
216} 217}
217 218
218/* 219/*
220 * Encode REMOVE argument
221 */
222static int
223nfs_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
224{
225 p = xdr_encode_fhandle(p, args->fh);
226 p = xdr_encode_array(p, args->name.name, args->name.len);
227 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
228 return 0;
229}
230
231/*
219 * Arguments to a READ call. Since we read data directly into the page 232 * Arguments to a READ call. Since we read data directly into the page
220 * cache, we also set up the reply iovec here so that iov[1] points 233 * cache, we also set up the reply iovec here so that iov[1] points
221 * exactly to the page we want to fetch. 234 * exactly to the page we want to fetch.
@@ -705,7 +718,7 @@ struct rpc_procinfo nfs_procedures[] = {
705 PROC(READ, readargs, readres, 3), 718 PROC(READ, readargs, readres, 3),
706 PROC(WRITE, writeargs, writeres, 4), 719 PROC(WRITE, writeargs, writeres, 4),
707 PROC(CREATE, createargs, diropres, 0), 720 PROC(CREATE, createargs, diropres, 0),
708 PROC(REMOVE, diropargs, stat, 0), 721 PROC(REMOVE, removeargs, stat, 0),
709 PROC(RENAME, renameargs, stat, 0), 722 PROC(RENAME, renameargs, stat, 0),
710 PROC(LINK, linkargs, stat, 0), 723 PROC(LINK, linkargs, stat, 0),
711 PROC(SYMLINK, symlinkargs, stat, 0), 724 PROC(SYMLINK, symlinkargs, stat, 0),
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 814d886b6aa4..c7ca5d70870b 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -349,62 +349,42 @@ out:
349static int 349static int
350nfs3_proc_remove(struct inode *dir, struct qstr *name) 350nfs3_proc_remove(struct inode *dir, struct qstr *name)
351{ 351{
352 struct nfs_fattr dir_attr; 352 struct nfs_removeargs arg = {
353 struct nfs3_diropargs arg = { 353 .fh = NFS_FH(dir),
354 .fh = NFS_FH(dir), 354 .name.len = name->len,
355 .name = name->name, 355 .name.name = name->name,
356 .len = name->len
357 }; 356 };
358 struct rpc_message msg = { 357 struct nfs_removeres res;
359 .rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE], 358 struct rpc_message msg = {
360 .rpc_argp = &arg, 359 .rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE],
361 .rpc_resp = &dir_attr, 360 .rpc_argp = &arg,
361 .rpc_resp = &res,
362 }; 362 };
363 int status; 363 int status;
364 364
365 dprintk("NFS call remove %s\n", name->name); 365 dprintk("NFS call remove %s\n", name->name);
366 nfs_fattr_init(&dir_attr); 366 nfs_fattr_init(&res.dir_attr);
367 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 367 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
368 nfs_post_op_update_inode(dir, &dir_attr); 368 nfs_post_op_update_inode(dir, &res.dir_attr);
369 dprintk("NFS reply remove: %d\n", status); 369 dprintk("NFS reply remove: %d\n", status);
370 return status; 370 return status;
371} 371}
372 372
373static int 373static void
374nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name) 374nfs3_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
375{ 375{
376 struct unlinkxdr {
377 struct nfs3_diropargs arg;
378 struct nfs_fattr res;
379 } *ptr;
380
381 ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);
382 if (!ptr)
383 return -ENOMEM;
384 ptr->arg.fh = NFS_FH(dir->d_inode);
385 ptr->arg.name = name->name;
386 ptr->arg.len = name->len;
387 nfs_fattr_init(&ptr->res);
388 msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE]; 376 msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
389 msg->rpc_argp = &ptr->arg;
390 msg->rpc_resp = &ptr->res;
391 return 0;
392} 377}
393 378
394static int 379static int
395nfs3_proc_unlink_done(struct dentry *dir, struct rpc_task *task) 380nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
396{ 381{
397 struct rpc_message *msg = &task->tk_msg; 382 struct nfs_removeres *res;
398 struct nfs_fattr *dir_attr; 383 if (nfs3_async_handle_jukebox(task, dir))
399 384 return 0;
400 if (nfs3_async_handle_jukebox(task, dir->d_inode)) 385 res = task->tk_msg.rpc_resp;
401 return 1; 386 nfs_post_op_update_inode(dir, &res->dir_attr);
402 if (msg->rpc_argp) { 387 return 1;
403 dir_attr = (struct nfs_fattr*)msg->rpc_resp;
404 nfs_post_op_update_inode(dir->d_inode, dir_attr);
405 kfree(msg->rpc_argp);
406 }
407 return 0;
408} 388}
409 389
410static int 390static int
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index b4647a22f349..d9e08f0cf2a0 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -50,6 +50,7 @@
50 50
51#define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3) 51#define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
52#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz) 52#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
53#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
53#define NFS3_accessargs_sz (NFS3_fh_sz+1) 54#define NFS3_accessargs_sz (NFS3_fh_sz+1)
54#define NFS3_readlinkargs_sz (NFS3_fh_sz) 55#define NFS3_readlinkargs_sz (NFS3_fh_sz)
55#define NFS3_readargs_sz (NFS3_fh_sz+3) 56#define NFS3_readargs_sz (NFS3_fh_sz+3)
@@ -65,6 +66,7 @@
65 66
66#define NFS3_attrstat_sz (1+NFS3_fattr_sz) 67#define NFS3_attrstat_sz (1+NFS3_fattr_sz)
67#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz) 68#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
69#define NFS3_removeres_sz (NFS3_wccstat_sz)
68#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)) 70#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
69#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1) 71#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
70#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) 72#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
@@ -106,7 +108,7 @@ static struct {
106 * Common NFS XDR functions as inlines 108 * Common NFS XDR functions as inlines
107 */ 109 */
108static inline __be32 * 110static inline __be32 *
109xdr_encode_fhandle(__be32 *p, struct nfs_fh *fh) 111xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh)
110{ 112{
111 return xdr_encode_array(p, fh->data, fh->size); 113 return xdr_encode_array(p, fh->data, fh->size);
112} 114}
@@ -300,6 +302,18 @@ nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
300} 302}
301 303
302/* 304/*
305 * Encode REMOVE argument
306 */
307static int
308nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
309{
310 p = xdr_encode_fhandle(p, args->fh);
311 p = xdr_encode_array(p, args->name.name, args->name.len);
312 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
313 return 0;
314}
315
316/*
303 * Encode access() argument 317 * Encode access() argument
304 */ 318 */
305static int 319static int
@@ -736,6 +750,12 @@ nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
736 return status; 750 return status;
737} 751}
738 752
753static int
754nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
755{
756 return nfs3_xdr_wccstat(req, p, &res->dir_attr);
757}
758
739/* 759/*
740 * Decode LOOKUP reply 760 * Decode LOOKUP reply
741 */ 761 */
@@ -1126,7 +1146,7 @@ struct rpc_procinfo nfs3_procedures[] = {
1126 PROC(MKDIR, mkdirargs, createres, 0), 1146 PROC(MKDIR, mkdirargs, createres, 0),
1127 PROC(SYMLINK, symlinkargs, createres, 0), 1147 PROC(SYMLINK, symlinkargs, createres, 0),
1128 PROC(MKNOD, mknodargs, createres, 0), 1148 PROC(MKNOD, mknodargs, createres, 0),
1129 PROC(REMOVE, diropargs, wccstat, 0), 1149 PROC(REMOVE, removeargs, removeres, 0),
1130 PROC(RMDIR, diropargs, wccstat, 0), 1150 PROC(RMDIR, diropargs, wccstat, 0),
1131 PROC(RENAME, renameargs, renameres, 0), 1151 PROC(RENAME, renameargs, renameres, 0),
1132 PROC(LINK, linkargs, linkres, 0), 1152 PROC(LINK, linkargs, linkres, 0),
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 6c028e734fe6..d2802b1ca3b9 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -182,7 +182,7 @@ extern int nfs4_do_close(struct path *path, struct nfs4_state *state);
182extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); 182extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
183extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); 183extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
184extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); 184extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
185extern int nfs4_proc_fs_locations(struct inode *dir, struct qstr *name, 185extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
186 struct nfs4_fs_locations *fs_locations, struct page *page); 186 struct nfs4_fs_locations *fs_locations, struct page *page);
187 187
188extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; 188extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index fee2da856c95..6ca2795ccd9c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -66,6 +66,8 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
66static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); 66static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
67static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); 67static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
68static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags); 68static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
69static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
70static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
69 71
70/* Prevent leaks of NFSv4 errors into userland */ 72/* Prevent leaks of NFSv4 errors into userland */
71int nfs4_map_errors(int err) 73int nfs4_map_errors(int err)
@@ -552,6 +554,18 @@ static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *
552 return ERR_PTR(-ENOENT); 554 return ERR_PTR(-ENOENT);
553} 555}
554 556
557static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context *ctx, struct nfs4_state *state)
558{
559 struct nfs4_opendata *opendata;
560
561 opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
562 if (opendata == NULL)
563 return ERR_PTR(-ENOMEM);
564 opendata->state = state;
565 atomic_inc(&state->count);
566 return opendata;
567}
568
555static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res) 569static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res)
556{ 570{
557 struct nfs4_state *newstate; 571 struct nfs4_state *newstate;
@@ -626,12 +640,11 @@ static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
626 int delegation_type = 0; 640 int delegation_type = 0;
627 int status; 641 int status;
628 642
629 opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); 643 opendata = nfs4_open_recoverdata_alloc(ctx, state);
630 if (opendata == NULL) 644 if (IS_ERR(opendata))
631 return -ENOMEM; 645 return PTR_ERR(opendata);
632 opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; 646 opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS;
633 opendata->o_arg.fh = NFS_FH(state->inode); 647 opendata->o_arg.fh = NFS_FH(state->inode);
634 nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh);
635 rcu_read_lock(); 648 rcu_read_lock();
636 delegation = rcu_dereference(NFS_I(state->inode)->delegation); 649 delegation = rcu_dereference(NFS_I(state->inode)->delegation);
637 if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0) 650 if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0)
@@ -672,13 +685,12 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
672 685
673static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) 686static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
674{ 687{
675 struct nfs4_state_owner *sp = state->owner;
676 struct nfs4_opendata *opendata; 688 struct nfs4_opendata *opendata;
677 int ret; 689 int ret;
678 690
679 opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL); 691 opendata = nfs4_open_recoverdata_alloc(ctx, state);
680 if (opendata == NULL) 692 if (IS_ERR(opendata))
681 return -ENOMEM; 693 return PTR_ERR(opendata);
682 opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR; 694 opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
683 memcpy(opendata->o_arg.u.delegation.data, stateid->data, 695 memcpy(opendata->o_arg.u.delegation.data, stateid->data,
684 sizeof(opendata->o_arg.u.delegation.data)); 696 sizeof(opendata->o_arg.u.delegation.data));
@@ -823,8 +835,10 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
823 /* Update sequence id. */ 835 /* Update sequence id. */
824 data->o_arg.id = sp->so_owner_id.id; 836 data->o_arg.id = sp->so_owner_id.id;
825 data->o_arg.clientid = sp->so_client->cl_clientid; 837 data->o_arg.clientid = sp->so_client->cl_clientid;
826 if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) 838 if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
827 msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; 839 msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
840 nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
841 }
828 data->timestamp = jiffies; 842 data->timestamp = jiffies;
829 rpc_call_setup(task, &msg, 0); 843 rpc_call_setup(task, &msg, 0);
830 return; 844 return;
@@ -918,6 +932,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
918 if (status != 0 || !data->rpc_done) 932 if (status != 0 || !data->rpc_done)
919 return status; 933 return status;
920 934
935 if (o_res->fh.size == 0)
936 _nfs4_proc_lookup(dir, o_arg->name, &o_res->fh, o_res->f_attr);
937
921 if (o_arg->open_flags & O_CREAT) { 938 if (o_arg->open_flags & O_CREAT) {
922 update_changeattr(dir, &o_res->cinfo); 939 update_changeattr(dir, &o_res->cinfo);
923 nfs_post_op_update_inode(dir, o_res->dir_attr); 940 nfs_post_op_update_inode(dir, o_res->dir_attr);
@@ -929,7 +946,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
929 return status; 946 return status;
930 } 947 }
931 if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) 948 if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
932 return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); 949 _nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr);
933 return 0; 950 return 0;
934} 951}
935 952
@@ -989,9 +1006,9 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
989 struct nfs4_opendata *opendata; 1006 struct nfs4_opendata *opendata;
990 int ret; 1007 int ret;
991 1008
992 opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); 1009 opendata = nfs4_open_recoverdata_alloc(ctx, state);
993 if (opendata == NULL) 1010 if (IS_ERR(opendata))
994 return -ENOMEM; 1011 return PTR_ERR(opendata);
995 ret = nfs4_open_recover(opendata, state); 1012 ret = nfs4_open_recover(opendata, state);
996 if (ret == -ESTALE) { 1013 if (ret == -ESTALE) {
997 /* Invalidate the state owner so we don't ever use it again */ 1014 /* Invalidate the state owner so we don't ever use it again */
@@ -1553,7 +1570,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
1553 * Note that we'll actually follow the referral later when 1570 * Note that we'll actually follow the referral later when
1554 * we detect fsid mismatch in inode revalidation 1571 * we detect fsid mismatch in inode revalidation
1555 */ 1572 */
1556static int nfs4_get_referral(struct inode *dir, struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle) 1573static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle)
1557{ 1574{
1558 int status = -ENOMEM; 1575 int status = -ENOMEM;
1559 struct page *page = NULL; 1576 struct page *page = NULL;
@@ -1668,8 +1685,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
1668 return status; 1685 return status;
1669} 1686}
1670 1687
1671static int _nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, 1688static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh,
1672 struct qstr *name, struct nfs_fh *fhandle, 1689 const struct qstr *name, struct nfs_fh *fhandle,
1673 struct nfs_fattr *fattr) 1690 struct nfs_fattr *fattr)
1674{ 1691{
1675 int status; 1692 int status;
@@ -1715,7 +1732,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
1715 return err; 1732 return err;
1716} 1733}
1717 1734
1718static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name, 1735static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
1719 struct nfs_fh *fhandle, struct nfs_fattr *fattr) 1736 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
1720{ 1737{
1721 int status; 1738 int status;
@@ -1908,28 +1925,27 @@ out:
1908static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) 1925static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
1909{ 1926{
1910 struct nfs_server *server = NFS_SERVER(dir); 1927 struct nfs_server *server = NFS_SERVER(dir);
1911 struct nfs4_remove_arg args = { 1928 struct nfs_removeargs args = {
1912 .fh = NFS_FH(dir), 1929 .fh = NFS_FH(dir),
1913 .name = name, 1930 .name.len = name->len,
1931 .name.name = name->name,
1914 .bitmask = server->attr_bitmask, 1932 .bitmask = server->attr_bitmask,
1915 }; 1933 };
1916 struct nfs_fattr dir_attr; 1934 struct nfs_removeres res = {
1917 struct nfs4_remove_res res = {
1918 .server = server, 1935 .server = server,
1919 .dir_attr = &dir_attr,
1920 }; 1936 };
1921 struct rpc_message msg = { 1937 struct rpc_message msg = {
1922 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE], 1938 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
1923 .rpc_argp = &args, 1939 .rpc_argp = &args,
1924 .rpc_resp = &res, 1940 .rpc_resp = &res,
1925 }; 1941 };
1926 int status; 1942 int status;
1927 1943
1928 nfs_fattr_init(res.dir_attr); 1944 nfs_fattr_init(&res.dir_attr);
1929 status = rpc_call_sync(server->client, &msg, 0); 1945 status = rpc_call_sync(server->client, &msg, 0);
1930 if (status == 0) { 1946 if (status == 0) {
1931 update_changeattr(dir, &res.cinfo); 1947 update_changeattr(dir, &res.cinfo);
1932 nfs_post_op_update_inode(dir, res.dir_attr); 1948 nfs_post_op_update_inode(dir, &res.dir_attr);
1933 } 1949 }
1934 return status; 1950 return status;
1935} 1951}
@@ -1946,48 +1962,26 @@ static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
1946 return err; 1962 return err;
1947} 1963}
1948 1964
1949struct unlink_desc { 1965static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
1950 struct nfs4_remove_arg args;
1951 struct nfs4_remove_res res;
1952 struct nfs_fattr dir_attr;
1953};
1954
1955static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir,
1956 struct qstr *name)
1957{ 1966{
1958 struct nfs_server *server = NFS_SERVER(dir->d_inode); 1967 struct nfs_server *server = NFS_SERVER(dir);
1959 struct unlink_desc *up; 1968 struct nfs_removeargs *args = msg->rpc_argp;
1969 struct nfs_removeres *res = msg->rpc_resp;
1960 1970
1961 up = kmalloc(sizeof(*up), GFP_KERNEL); 1971 args->bitmask = server->attr_bitmask;
1962 if (!up) 1972 res->server = server;
1963 return -ENOMEM;
1964
1965 up->args.fh = NFS_FH(dir->d_inode);
1966 up->args.name = name;
1967 up->args.bitmask = server->attr_bitmask;
1968 up->res.server = server;
1969 up->res.dir_attr = &up->dir_attr;
1970
1971 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; 1973 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
1972 msg->rpc_argp = &up->args;
1973 msg->rpc_resp = &up->res;
1974 return 0;
1975} 1974}
1976 1975
1977static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task) 1976static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
1978{ 1977{
1979 struct rpc_message *msg = &task->tk_msg; 1978 struct nfs_removeres *res = task->tk_msg.rpc_resp;
1980 struct unlink_desc *up; 1979
1981 1980 if (nfs4_async_handle_error(task, res->server) == -EAGAIN)
1982 if (msg->rpc_resp != NULL) { 1981 return 0;
1983 up = container_of(msg->rpc_resp, struct unlink_desc, res); 1982 update_changeattr(dir, &res->cinfo);
1984 update_changeattr(dir->d_inode, &up->res.cinfo); 1983 nfs_post_op_update_inode(dir, &res->dir_attr);
1985 nfs_post_op_update_inode(dir->d_inode, up->res.dir_attr); 1984 return 1;
1986 kfree(up);
1987 msg->rpc_resp = NULL;
1988 msg->rpc_argp = NULL;
1989 }
1990 return 0;
1991} 1985}
1992 1986
1993static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, 1987static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
@@ -3672,7 +3666,7 @@ ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
3672 return len; 3666 return len;
3673} 3667}
3674 3668
3675int nfs4_proc_fs_locations(struct inode *dir, struct qstr *name, 3669int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
3676 struct nfs4_fs_locations *fs_locations, struct page *page) 3670 struct nfs4_fs_locations *fs_locations, struct page *page)
3677{ 3671{
3678 struct nfs_server *server = NFS_SERVER(dir); 3672 struct nfs_server *server = NFS_SERVER(dir);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index c08738441f73..badd73b7ca12 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -72,10 +72,15 @@ static int nfs4_stat_to_errno(int);
72 */ 72 */
73#define open_owner_id_maxsz (1 + 4) 73#define open_owner_id_maxsz (1 + 4)
74#define lock_owner_id_maxsz (1 + 4) 74#define lock_owner_id_maxsz (1 + 4)
75#define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
75#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) 76#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
76#define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) 77#define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
77#define op_encode_hdr_maxsz (1) 78#define op_encode_hdr_maxsz (1)
78#define op_decode_hdr_maxsz (2) 79#define op_decode_hdr_maxsz (2)
80#define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
81#define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
82#define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
83#define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
79#define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \ 84#define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \
80 (NFS4_FHSIZE >> 2)) 85 (NFS4_FHSIZE >> 2))
81#define decode_putfh_maxsz (op_decode_hdr_maxsz) 86#define decode_putfh_maxsz (op_decode_hdr_maxsz)
@@ -96,6 +101,11 @@ static int nfs4_stat_to_errno(int);
96#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ 101#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
97 nfs4_fattr_value_maxsz) 102 nfs4_fattr_value_maxsz)
98#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) 103#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
104#define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \
105 1 + 2 + 1 + \
106 nfs4_owner_maxsz + \
107 nfs4_group_maxsz + \
108 4 + 4)
99#define encode_savefh_maxsz (op_encode_hdr_maxsz) 109#define encode_savefh_maxsz (op_encode_hdr_maxsz)
100#define decode_savefh_maxsz (op_decode_hdr_maxsz) 110#define decode_savefh_maxsz (op_decode_hdr_maxsz)
101#define encode_restorefh_maxsz (op_encode_hdr_maxsz) 111#define encode_restorefh_maxsz (op_encode_hdr_maxsz)
@@ -123,7 +133,7 @@ static int nfs4_stat_to_errno(int);
123#define decode_lookup_maxsz (op_decode_hdr_maxsz) 133#define decode_lookup_maxsz (op_decode_hdr_maxsz)
124#define encode_share_access_maxsz \ 134#define encode_share_access_maxsz \
125 (2) 135 (2)
126#define encode_createmode_maxsz (1 + nfs4_fattr_maxsz) 136#define encode_createmode_maxsz (1 + encode_attrs_maxsz)
127#define encode_opentype_maxsz (1 + encode_createmode_maxsz) 137#define encode_opentype_maxsz (1 + encode_createmode_maxsz)
128#define encode_claim_null_maxsz (1 + nfs4_name_maxsz) 138#define encode_claim_null_maxsz (1 + nfs4_name_maxsz)
129#define encode_open_maxsz (op_encode_hdr_maxsz + \ 139#define encode_open_maxsz (op_encode_hdr_maxsz + \
@@ -132,14 +142,52 @@ static int nfs4_stat_to_errno(int);
132 encode_opentype_maxsz + \ 142 encode_opentype_maxsz + \
133 encode_claim_null_maxsz) 143 encode_claim_null_maxsz)
134#define decode_ace_maxsz (3 + nfs4_owner_maxsz) 144#define decode_ace_maxsz (3 + nfs4_owner_maxsz)
135#define decode_delegation_maxsz (1 + XDR_QUADLEN(NFS4_STATEID_SIZE) + 1 + \ 145#define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \
136 decode_ace_maxsz) 146 decode_ace_maxsz)
137#define decode_change_info_maxsz (5) 147#define decode_change_info_maxsz (5)
138#define decode_open_maxsz (op_decode_hdr_maxsz + \ 148#define decode_open_maxsz (op_decode_hdr_maxsz + \
139 XDR_QUADLEN(NFS4_STATEID_SIZE) + \ 149 decode_stateid_maxsz + \
140 decode_change_info_maxsz + 1 + \ 150 decode_change_info_maxsz + 1 + \
141 nfs4_fattr_bitmap_maxsz + \ 151 nfs4_fattr_bitmap_maxsz + \
142 decode_delegation_maxsz) 152 decode_delegation_maxsz)
153#define encode_open_confirm_maxsz \
154 (op_encode_hdr_maxsz + \
155 encode_stateid_maxsz + 1)
156#define decode_open_confirm_maxsz \
157 (op_decode_hdr_maxsz + \
158 decode_stateid_maxsz)
159#define encode_open_downgrade_maxsz \
160 (op_encode_hdr_maxsz + \
161 encode_stateid_maxsz + 1 + \
162 encode_share_access_maxsz)
163#define decode_open_downgrade_maxsz \
164 (op_decode_hdr_maxsz + \
165 decode_stateid_maxsz)
166#define encode_close_maxsz (op_encode_hdr_maxsz + \
167 1 + encode_stateid_maxsz)
168#define decode_close_maxsz (op_decode_hdr_maxsz + \
169 decode_stateid_maxsz)
170#define encode_setattr_maxsz (op_encode_hdr_maxsz + \
171 encode_stateid_maxsz + \
172 encode_attrs_maxsz)
173#define decode_setattr_maxsz (op_decode_hdr_maxsz + \
174 nfs4_fattr_bitmap_maxsz)
175#define encode_read_maxsz (op_encode_hdr_maxsz + \
176 encode_stateid_maxsz + 3)
177#define decode_read_maxsz (op_decode_hdr_maxsz + 2)
178#define encode_readdir_maxsz (op_encode_hdr_maxsz + \
179 2 + encode_verifier_maxsz + 5)
180#define decode_readdir_maxsz (op_decode_hdr_maxsz + \
181 decode_verifier_maxsz)
182#define encode_readlink_maxsz (op_encode_hdr_maxsz)
183#define decode_readlink_maxsz (op_decode_hdr_maxsz + 1)
184#define encode_write_maxsz (op_encode_hdr_maxsz + \
185 encode_stateid_maxsz + 4)
186#define decode_write_maxsz (op_decode_hdr_maxsz + \
187 2 + decode_verifier_maxsz)
188#define encode_commit_maxsz (op_encode_hdr_maxsz + 3)
189#define decode_commit_maxsz (op_decode_hdr_maxsz + \
190 decode_verifier_maxsz)
143#define encode_remove_maxsz (op_encode_hdr_maxsz + \ 191#define encode_remove_maxsz (op_encode_hdr_maxsz + \
144 nfs4_name_maxsz) 192 nfs4_name_maxsz)
145#define encode_rename_maxsz (op_encode_hdr_maxsz + \ 193#define encode_rename_maxsz (op_encode_hdr_maxsz + \
@@ -148,19 +196,44 @@ static int nfs4_stat_to_errno(int);
148#define encode_link_maxsz (op_encode_hdr_maxsz + \ 196#define encode_link_maxsz (op_encode_hdr_maxsz + \
149 nfs4_name_maxsz) 197 nfs4_name_maxsz)
150#define decode_link_maxsz (op_decode_hdr_maxsz + 5) 198#define decode_link_maxsz (op_decode_hdr_maxsz + 5)
199#define encode_lock_maxsz (op_encode_hdr_maxsz + \
200 7 + \
201 1 + encode_stateid_maxsz + 8)
202#define decode_lock_denied_maxsz \
203 (8 + decode_lockowner_maxsz)
204#define decode_lock_maxsz (op_decode_hdr_maxsz + \
205 decode_lock_denied_maxsz)
206#define encode_lockt_maxsz (op_encode_hdr_maxsz + 12)
207#define decode_lockt_maxsz (op_decode_hdr_maxsz + \
208 decode_lock_denied_maxsz)
209#define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \
210 encode_stateid_maxsz + \
211 4)
212#define decode_locku_maxsz (op_decode_hdr_maxsz + \
213 decode_stateid_maxsz)
214#define encode_access_maxsz (op_encode_hdr_maxsz + 1)
215#define decode_access_maxsz (op_decode_hdr_maxsz + 2)
151#define encode_symlink_maxsz (op_encode_hdr_maxsz + \ 216#define encode_symlink_maxsz (op_encode_hdr_maxsz + \
152 1 + nfs4_name_maxsz + \ 217 1 + nfs4_name_maxsz + \
153 1 + \ 218 1 + \
154 nfs4_fattr_maxsz) 219 nfs4_fattr_maxsz)
155#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) 220#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8)
156#define encode_create_maxsz (op_encode_hdr_maxsz + \ 221#define encode_create_maxsz (op_encode_hdr_maxsz + \
157 2 + nfs4_name_maxsz + \ 222 1 + 2 + nfs4_name_maxsz + \
158 nfs4_fattr_maxsz) 223 encode_attrs_maxsz)
159#define decode_create_maxsz (op_decode_hdr_maxsz + \ 224#define decode_create_maxsz (op_decode_hdr_maxsz + \
160 decode_change_info_maxsz + \ 225 decode_change_info_maxsz + \
161 nfs4_fattr_bitmap_maxsz) 226 nfs4_fattr_bitmap_maxsz)
227#define encode_statfs_maxsz (encode_getattr_maxsz)
228#define decode_statfs_maxsz (decode_getattr_maxsz)
162#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) 229#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
163#define decode_delegreturn_maxsz (op_decode_hdr_maxsz) 230#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
231#define encode_getacl_maxsz (encode_getattr_maxsz)
232#define decode_getacl_maxsz (op_decode_hdr_maxsz + \
233 nfs4_fattr_bitmap_maxsz + 1)
234#define encode_setacl_maxsz (op_encode_hdr_maxsz + \
235 encode_stateid_maxsz + 3)
236#define decode_setacl_maxsz (decode_setattr_maxsz)
164#define encode_fs_locations_maxsz \ 237#define encode_fs_locations_maxsz \
165 (encode_getattr_maxsz) 238 (encode_getattr_maxsz)
166#define decode_fs_locations_maxsz \ 239#define decode_fs_locations_maxsz \
@@ -169,37 +242,37 @@ static int nfs4_stat_to_errno(int);
169#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ 242#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
170#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ 243#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
171 encode_putfh_maxsz + \ 244 encode_putfh_maxsz + \
172 op_encode_hdr_maxsz + 7) 245 encode_read_maxsz)
173#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ 246#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
174 decode_putfh_maxsz + \ 247 decode_putfh_maxsz + \
175 op_decode_hdr_maxsz + 2) 248 decode_read_maxsz)
176#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ 249#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
177 encode_putfh_maxsz + \ 250 encode_putfh_maxsz + \
178 op_encode_hdr_maxsz) 251 encode_readlink_maxsz)
179#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ 252#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
180 decode_putfh_maxsz + \ 253 decode_putfh_maxsz + \
181 op_decode_hdr_maxsz) 254 decode_readlink_maxsz)
182#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ 255#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
183 encode_putfh_maxsz + \ 256 encode_putfh_maxsz + \
184 op_encode_hdr_maxsz + 9) 257 encode_readdir_maxsz)
185#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ 258#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
186 decode_putfh_maxsz + \ 259 decode_putfh_maxsz + \
187 op_decode_hdr_maxsz + 2) 260 decode_readdir_maxsz)
188#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ 261#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
189 encode_putfh_maxsz + \ 262 encode_putfh_maxsz + \
190 op_encode_hdr_maxsz + 8 + \ 263 encode_write_maxsz + \
191 encode_getattr_maxsz) 264 encode_getattr_maxsz)
192#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ 265#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
193 decode_putfh_maxsz + \ 266 decode_putfh_maxsz + \
194 op_decode_hdr_maxsz + 4 + \ 267 decode_write_maxsz + \
195 decode_getattr_maxsz) 268 decode_getattr_maxsz)
196#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ 269#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
197 encode_putfh_maxsz + \ 270 encode_putfh_maxsz + \
198 op_encode_hdr_maxsz + 3 + \ 271 encode_commit_maxsz + \
199 encode_getattr_maxsz) 272 encode_getattr_maxsz)
200#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ 273#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
201 decode_putfh_maxsz + \ 274 decode_putfh_maxsz + \
202 op_decode_hdr_maxsz + 2 + \ 275 decode_commit_maxsz + \
203 decode_getattr_maxsz) 276 decode_getattr_maxsz)
204#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ 277#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
205 encode_putfh_maxsz + \ 278 encode_putfh_maxsz + \
@@ -217,13 +290,14 @@ static int nfs4_stat_to_errno(int);
217 decode_getattr_maxsz + \ 290 decode_getattr_maxsz + \
218 decode_restorefh_maxsz + \ 291 decode_restorefh_maxsz + \
219 decode_getattr_maxsz) 292 decode_getattr_maxsz)
220#define NFS4_enc_open_confirm_sz \ 293#define NFS4_enc_open_confirm_sz \
221 (compound_encode_hdr_maxsz + \ 294 (compound_encode_hdr_maxsz + \
222 encode_putfh_maxsz + \ 295 encode_putfh_maxsz + \
223 op_encode_hdr_maxsz + 5) 296 encode_open_confirm_maxsz)
224#define NFS4_dec_open_confirm_sz (compound_decode_hdr_maxsz + \ 297#define NFS4_dec_open_confirm_sz \
225 decode_putfh_maxsz + \ 298 (compound_decode_hdr_maxsz + \
226 op_decode_hdr_maxsz + 4) 299 decode_putfh_maxsz + \
300 decode_open_confirm_maxsz)
227#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ 301#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
228 encode_putfh_maxsz + \ 302 encode_putfh_maxsz + \
229 encode_open_maxsz + \ 303 encode_open_maxsz + \
@@ -234,31 +308,30 @@ static int nfs4_stat_to_errno(int);
234 decode_getattr_maxsz) 308 decode_getattr_maxsz)
235#define NFS4_enc_open_downgrade_sz \ 309#define NFS4_enc_open_downgrade_sz \
236 (compound_encode_hdr_maxsz + \ 310 (compound_encode_hdr_maxsz + \
237 encode_putfh_maxsz + \ 311 encode_putfh_maxsz + \
238 op_encode_hdr_maxsz + 7 + \ 312 encode_open_downgrade_maxsz + \
239 encode_getattr_maxsz) 313 encode_getattr_maxsz)
240#define NFS4_dec_open_downgrade_sz \ 314#define NFS4_dec_open_downgrade_sz \
241 (compound_decode_hdr_maxsz + \ 315 (compound_decode_hdr_maxsz + \
242 decode_putfh_maxsz + \ 316 decode_putfh_maxsz + \
243 op_decode_hdr_maxsz + 4 + \ 317 decode_open_downgrade_maxsz + \
244 decode_getattr_maxsz) 318 decode_getattr_maxsz)
245#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ 319#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
246 encode_putfh_maxsz + \ 320 encode_putfh_maxsz + \
247 op_encode_hdr_maxsz + 5 + \ 321 encode_close_maxsz + \
248 encode_getattr_maxsz) 322 encode_getattr_maxsz)
249#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ 323#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
250 decode_putfh_maxsz + \ 324 decode_putfh_maxsz + \
251 op_decode_hdr_maxsz + 4 + \ 325 decode_close_maxsz + \
252 decode_getattr_maxsz) 326 decode_getattr_maxsz)
253#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ 327#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
254 encode_putfh_maxsz + \ 328 encode_putfh_maxsz + \
255 op_encode_hdr_maxsz + 4 + \ 329 encode_setattr_maxsz + \
256 nfs4_fattr_maxsz + \ 330 encode_getattr_maxsz)
257 encode_getattr_maxsz) 331#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
258#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ 332 decode_putfh_maxsz + \
259 decode_putfh_maxsz + \ 333 decode_setattr_maxsz + \
260 op_decode_hdr_maxsz + 3 + \ 334 decode_getattr_maxsz)
261 nfs4_fattr_maxsz)
262#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ 335#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
263 encode_putfh_maxsz + \ 336 encode_putfh_maxsz + \
264 encode_fsinfo_maxsz) 337 encode_fsinfo_maxsz)
@@ -285,39 +358,28 @@ static int nfs4_stat_to_errno(int);
285 decode_fsinfo_maxsz) 358 decode_fsinfo_maxsz)
286#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ 359#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
287 encode_putfh_maxsz + \ 360 encode_putfh_maxsz + \
288 encode_getattr_maxsz + \ 361 encode_lock_maxsz)
289 op_encode_hdr_maxsz + \
290 1 + 1 + 2 + 2 + \
291 1 + 4 + 1 + 2 + \
292 lock_owner_id_maxsz)
293#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ 362#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
294 decode_putfh_maxsz + \ 363 decode_putfh_maxsz + \
295 decode_getattr_maxsz + \ 364 decode_lock_maxsz)
296 op_decode_hdr_maxsz + \
297 2 + 2 + 1 + 2 + \
298 lock_owner_id_maxsz)
299#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ 365#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
300 encode_putfh_maxsz + \ 366 encode_putfh_maxsz + \
301 encode_getattr_maxsz + \ 367 encode_lockt_maxsz)
302 op_encode_hdr_maxsz + \ 368#define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \
303 1 + 2 + 2 + 2 + \ 369 decode_putfh_maxsz + \
304 lock_owner_id_maxsz) 370 decode_lockt_maxsz)
305#define NFS4_dec_lockt_sz (NFS4_dec_lock_sz)
306#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ 371#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
307 encode_putfh_maxsz + \ 372 encode_putfh_maxsz + \
308 encode_getattr_maxsz + \ 373 encode_locku_maxsz)
309 op_encode_hdr_maxsz + \
310 1 + 1 + 4 + 2 + 2)
311#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ 374#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
312 decode_putfh_maxsz + \ 375 decode_putfh_maxsz + \
313 decode_getattr_maxsz + \ 376 decode_locku_maxsz)
314 op_decode_hdr_maxsz + 4)
315#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ 377#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
316 encode_putfh_maxsz + \ 378 encode_putfh_maxsz + \
317 op_encode_hdr_maxsz + 1) 379 encode_access_maxsz)
318#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ 380#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
319 decode_putfh_maxsz + \ 381 decode_putfh_maxsz + \
320 op_decode_hdr_maxsz + 2) 382 decode_access_maxsz)
321#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ 383#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
322 encode_putfh_maxsz + \ 384 encode_putfh_maxsz + \
323 encode_getattr_maxsz) 385 encode_getattr_maxsz)
@@ -416,10 +478,10 @@ static int nfs4_stat_to_errno(int);
416 decode_getattr_maxsz) 478 decode_getattr_maxsz)
417#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ 479#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
418 encode_putfh_maxsz + \ 480 encode_putfh_maxsz + \
419 encode_getattr_maxsz) 481 encode_statfs_maxsz)
420#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ 482#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \
421 decode_putfh_maxsz + \ 483 decode_putfh_maxsz + \
422 op_decode_hdr_maxsz + 12) 484 decode_statfs_maxsz)
423#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ 485#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
424 encode_putfh_maxsz + \ 486 encode_putfh_maxsz + \
425 encode_getattr_maxsz) 487 encode_getattr_maxsz)
@@ -435,18 +497,16 @@ static int nfs4_stat_to_errno(int);
435 decode_getattr_maxsz) 497 decode_getattr_maxsz)
436#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ 498#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
437 encode_putfh_maxsz + \ 499 encode_putfh_maxsz + \
438 encode_getattr_maxsz) 500 encode_getacl_maxsz)
439#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ 501#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
440 decode_putfh_maxsz + \ 502 decode_putfh_maxsz + \
441 op_decode_hdr_maxsz + \ 503 decode_getacl_maxsz)
442 nfs4_fattr_bitmap_maxsz + 1)
443#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ 504#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
444 encode_putfh_maxsz + \ 505 encode_putfh_maxsz + \
445 op_encode_hdr_maxsz + 4 + \ 506 encode_setacl_maxsz)
446 nfs4_fattr_bitmap_maxsz + 1)
447#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ 507#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
448 decode_putfh_maxsz + \ 508 decode_putfh_maxsz + \
449 op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) 509 decode_setacl_maxsz)
450#define NFS4_enc_fs_locations_sz \ 510#define NFS4_enc_fs_locations_sz \
451 (compound_encode_hdr_maxsz + \ 511 (compound_encode_hdr_maxsz + \
452 encode_putfh_maxsz + \ 512 encode_putfh_maxsz + \
@@ -1108,12 +1168,10 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
1108 1168
1109static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req) 1169static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
1110{ 1170{
1111 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1112 uint32_t attrs[2] = { 1171 uint32_t attrs[2] = {
1113 FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID, 1172 FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
1114 FATTR4_WORD1_MOUNTED_ON_FILEID, 1173 FATTR4_WORD1_MOUNTED_ON_FILEID,
1115 }; 1174 };
1116 int replen;
1117 __be32 *p; 1175 __be32 *p;
1118 1176
1119 RESERVE_SPACE(12+NFS4_VERIFIER_SIZE+20); 1177 RESERVE_SPACE(12+NFS4_VERIFIER_SIZE+20);
@@ -1138,37 +1196,16 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
1138 attrs[0] & readdir->bitmask[0], 1196 attrs[0] & readdir->bitmask[0],
1139 attrs[1] & readdir->bitmask[1]); 1197 attrs[1] & readdir->bitmask[1]);
1140 1198
1141 /* set up reply kvec
1142 * toplevel_status + taglen + rescount + OP_PUTFH + status
1143 * + OP_READDIR + status + verifer(2) = 9
1144 */
1145 replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2;
1146 xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->pages,
1147 readdir->pgbase, readdir->count);
1148 dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
1149 __FUNCTION__, replen, readdir->pages,
1150 readdir->pgbase, readdir->count);
1151
1152 return 0; 1199 return 0;
1153} 1200}
1154 1201
1155static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req) 1202static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
1156{ 1203{
1157 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1158 unsigned int replen;
1159 __be32 *p; 1204 __be32 *p;
1160 1205
1161 RESERVE_SPACE(4); 1206 RESERVE_SPACE(4);
1162 WRITE32(OP_READLINK); 1207 WRITE32(OP_READLINK);
1163 1208
1164 /* set up reply kvec
1165 * toplevel_status + taglen + rescount + OP_PUTFH + status
1166 * + OP_READLINK + status + string length = 8
1167 */
1168 replen = (RPC_REPHDRSIZE + auth->au_rslack + 8) << 2;
1169 xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->pages,
1170 readlink->pgbase, readlink->pglen);
1171
1172 return 0; 1209 return 0;
1173} 1210}
1174 1211
@@ -1398,7 +1435,7 @@ out:
1398/* 1435/*
1399 * Encode REMOVE request 1436 * Encode REMOVE request
1400 */ 1437 */
1401static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs4_remove_arg *args) 1438static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
1402{ 1439{
1403 struct xdr_stream xdr; 1440 struct xdr_stream xdr;
1404 struct compound_hdr hdr = { 1441 struct compound_hdr hdr = {
@@ -1410,7 +1447,7 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs
1410 encode_compound_hdr(&xdr, &hdr); 1447 encode_compound_hdr(&xdr, &hdr);
1411 if ((status = encode_putfh(&xdr, args->fh)) != 0) 1448 if ((status = encode_putfh(&xdr, args->fh)) != 0)
1412 goto out; 1449 goto out;
1413 if ((status = encode_remove(&xdr, args->name)) != 0) 1450 if ((status = encode_remove(&xdr, &args->name)) != 0)
1414 goto out; 1451 goto out;
1415 status = encode_getfattr(&xdr, args->bitmask); 1452 status = encode_getfattr(&xdr, args->bitmask);
1416out: 1453out:
@@ -1734,6 +1771,8 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
1734 struct compound_hdr hdr = { 1771 struct compound_hdr hdr = {
1735 .nops = 2, 1772 .nops = 2,
1736 }; 1773 };
1774 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1775 unsigned int replen;
1737 int status; 1776 int status;
1738 1777
1739 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1778 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
@@ -1742,6 +1781,15 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
1742 if(status) 1781 if(status)
1743 goto out; 1782 goto out;
1744 status = encode_readlink(&xdr, args, req); 1783 status = encode_readlink(&xdr, args, req);
1784
1785 /* set up reply kvec
1786 * toplevel_status + taglen + rescount + OP_PUTFH + status
1787 * + OP_READLINK + status + string length = 8
1788 */
1789 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_readlink_sz) << 2;
1790 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages,
1791 args->pgbase, args->pglen);
1792
1745out: 1793out:
1746 return status; 1794 return status;
1747} 1795}
@@ -1755,6 +1803,8 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
1755 struct compound_hdr hdr = { 1803 struct compound_hdr hdr = {
1756 .nops = 2, 1804 .nops = 2,
1757 }; 1805 };
1806 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1807 int replen;
1758 int status; 1808 int status;
1759 1809
1760 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1810 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
@@ -1763,6 +1813,18 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
1763 if(status) 1813 if(status)
1764 goto out; 1814 goto out;
1765 status = encode_readdir(&xdr, args, req); 1815 status = encode_readdir(&xdr, args, req);
1816
1817 /* set up reply kvec
1818 * toplevel_status + taglen + rescount + OP_PUTFH + status
1819 * + OP_READDIR + status + verifer(2) = 9
1820 */
1821 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_readdir_sz) << 2;
1822 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages,
1823 args->pgbase, args->count);
1824 dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
1825 __FUNCTION__, replen, args->pages,
1826 args->pgbase, args->count);
1827
1766out: 1828out:
1767 return status; 1829 return status;
1768} 1830}
@@ -3161,11 +3223,12 @@ static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
3161 uint32_t len; 3223 uint32_t len;
3162 int status; 3224 int status;
3163 3225
3226 /* Zero handle first to allow comparisons */
3227 memset(fh, 0, sizeof(*fh));
3228
3164 status = decode_op_hdr(xdr, OP_GETFH); 3229 status = decode_op_hdr(xdr, OP_GETFH);
3165 if (status) 3230 if (status)
3166 return status; 3231 return status;
3167 /* Zero handle first to allow comparisons */
3168 memset(fh, 0, sizeof(*fh));
3169 3232
3170 READ_BUF(4); 3233 READ_BUF(4);
3171 READ32(len); 3234 READ32(len);
@@ -3772,7 +3835,7 @@ out:
3772/* 3835/*
3773 * Decode REMOVE response 3836 * Decode REMOVE response
3774 */ 3837 */
3775static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_remove_res *res) 3838static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_removeres *res)
3776{ 3839{
3777 struct xdr_stream xdr; 3840 struct xdr_stream xdr;
3778 struct compound_hdr hdr; 3841 struct compound_hdr hdr;
@@ -3785,7 +3848,7 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_re
3785 goto out; 3848 goto out;
3786 if ((status = decode_remove(&xdr, &res->cinfo)) != 0) 3849 if ((status = decode_remove(&xdr, &res->cinfo)) != 0)
3787 goto out; 3850 goto out;
3788 decode_getfattr(&xdr, res->dir_attr, res->server); 3851 decode_getfattr(&xdr, &res->dir_attr, res->server);
3789out: 3852out:
3790 return status; 3853 return status;
3791} 3854}
@@ -4030,12 +4093,11 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openr
4030 status = decode_open(&xdr, res); 4093 status = decode_open(&xdr, res);
4031 if (status) 4094 if (status)
4032 goto out; 4095 goto out;
4033 status = decode_getfh(&xdr, &res->fh); 4096 if (decode_getfh(&xdr, &res->fh) != 0)
4034 if (status)
4035 goto out; 4097 goto out;
4036 if (decode_getfattr(&xdr, res->f_attr, res->server) != 0) 4098 if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
4037 goto out; 4099 goto out;
4038 if ((status = decode_restorefh(&xdr)) != 0) 4100 if (decode_restorefh(&xdr) != 0)
4039 goto out; 4101 goto out;
4040 decode_getfattr(&xdr, res->dir_attr, res->server); 4102 decode_getfattr(&xdr, res->dir_attr, res->server);
4041out: 4103out:
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 7be0ee2782cb..845cdde1d8b7 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -272,14 +272,14 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
272static int 272static int
273nfs_proc_remove(struct inode *dir, struct qstr *name) 273nfs_proc_remove(struct inode *dir, struct qstr *name)
274{ 274{
275 struct nfs_diropargs arg = { 275 struct nfs_removeargs arg = {
276 .fh = NFS_FH(dir), 276 .fh = NFS_FH(dir),
277 .name = name->name, 277 .name.len = name->len,
278 .len = name->len 278 .name.name = name->name,
279 }; 279 };
280 struct rpc_message msg = { 280 struct rpc_message msg = {
281 .rpc_proc = &nfs_procedures[NFSPROC_REMOVE], 281 .rpc_proc = &nfs_procedures[NFSPROC_REMOVE],
282 .rpc_argp = &arg, 282 .rpc_argp = &arg,
283 }; 283 };
284 int status; 284 int status;
285 285
@@ -291,32 +291,16 @@ nfs_proc_remove(struct inode *dir, struct qstr *name)
291 return status; 291 return status;
292} 292}
293 293
294static int 294static void
295nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name) 295nfs_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
296{ 296{
297 struct nfs_diropargs *arg;
298
299 arg = kmalloc(sizeof(*arg), GFP_KERNEL);
300 if (!arg)
301 return -ENOMEM;
302 arg->fh = NFS_FH(dir->d_inode);
303 arg->name = name->name;
304 arg->len = name->len;
305 msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE]; 297 msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE];
306 msg->rpc_argp = arg;
307 return 0;
308} 298}
309 299
310static int 300static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
311nfs_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
312{ 301{
313 struct rpc_message *msg = &task->tk_msg; 302 nfs_mark_for_revalidate(dir);
314 303 return 1;
315 if (msg->rpc_argp) {
316 nfs_mark_for_revalidate(dir->d_inode);
317 kfree(msg->rpc_argp);
318 }
319 return 0;
320} 304}
321 305
322static int 306static int
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index adffe1615c51..b34b7a711d5b 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1685,6 +1685,9 @@ static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
1685 1685
1686 dprintk("MNTPATH: %s\n", *mntpath); 1686 dprintk("MNTPATH: %s\n", *mntpath);
1687 1687
1688 if (args.client_address == NULL)
1689 goto out_no_client_address;
1690
1688 *ip_addr = args.client_address; 1691 *ip_addr = args.client_address;
1689 1692
1690 break; 1693 break;
@@ -1705,6 +1708,10 @@ out_inval_auth:
1705out_no_address: 1708out_no_address:
1706 dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n"); 1709 dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
1707 return -EINVAL; 1710 return -EINVAL;
1711
1712out_no_client_address:
1713 dfprintk(MOUNT, "NFS4: mount program didn't pass callback address\n");
1714 return -EINVAL;
1708} 1715}
1709 1716
1710/* 1717/*
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 0e28189c2151..045ab805c17f 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -3,7 +3,6 @@
3 * 3 *
4 * nfs sillydelete handling 4 * nfs sillydelete handling
5 * 5 *
6 * NOTE: we rely on holding the BKL for list manipulation protection.
7 */ 6 */
8 7
9#include <linux/slab.h> 8#include <linux/slab.h>
@@ -15,46 +14,23 @@
15 14
16 15
17struct nfs_unlinkdata { 16struct nfs_unlinkdata {
18 struct nfs_unlinkdata *next; 17 struct nfs_removeargs args;
19 struct dentry *dir, *dentry; 18 struct nfs_removeres res;
20 struct qstr name; 19 struct inode *dir;
21 struct rpc_task task;
22 struct rpc_cred *cred; 20 struct rpc_cred *cred;
23 unsigned int count;
24}; 21};
25 22
26static struct nfs_unlinkdata *nfs_deletes;
27static RPC_WAITQ(nfs_delete_queue, "nfs_delete_queue");
28
29/**
30 * nfs_detach_unlinkdata - Remove asynchronous unlink from global list
31 * @data: pointer to descriptor
32 */
33static inline void
34nfs_detach_unlinkdata(struct nfs_unlinkdata *data)
35{
36 struct nfs_unlinkdata **q;
37
38 for (q = &nfs_deletes; *q != NULL; q = &((*q)->next)) {
39 if (*q == data) {
40 *q = data->next;
41 break;
42 }
43 }
44}
45
46/** 23/**
47 * nfs_put_unlinkdata - release data from a sillydelete operation. 24 * nfs_free_unlinkdata - release data from a sillydelete operation.
48 * @data: pointer to unlink structure. 25 * @data: pointer to unlink structure.
49 */ 26 */
50static void 27static void
51nfs_put_unlinkdata(struct nfs_unlinkdata *data) 28nfs_free_unlinkdata(struct nfs_unlinkdata *data)
52{ 29{
53 if (--data->count == 0) { 30 iput(data->dir);
54 nfs_detach_unlinkdata(data); 31 put_rpccred(data->cred);
55 kfree(data->name.name); 32 kfree(data->args.name.name);
56 kfree(data); 33 kfree(data);
57 }
58} 34}
59 35
60#define NAME_ALLOC_LEN(len) ((len+16) & ~15) 36#define NAME_ALLOC_LEN(len) ((len+16) & ~15)
@@ -63,50 +39,36 @@ nfs_put_unlinkdata(struct nfs_unlinkdata *data)
63 * @dentry: pointer to dentry 39 * @dentry: pointer to dentry
64 * @data: nfs_unlinkdata 40 * @data: nfs_unlinkdata
65 */ 41 */
66static inline void 42static int nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data)
67nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data)
68{ 43{
69 char *str; 44 char *str;
70 int len = dentry->d_name.len; 45 int len = dentry->d_name.len;
71 46
72 str = kmalloc(NAME_ALLOC_LEN(len), GFP_KERNEL); 47 str = kmemdup(dentry->d_name.name, NAME_ALLOC_LEN(len), GFP_KERNEL);
73 if (!str) 48 if (!str)
74 return; 49 return -ENOMEM;
75 memcpy(str, dentry->d_name.name, len); 50 data->args.name.len = len;
76 if (!data->name.len) { 51 data->args.name.name = str;
77 data->name.len = len; 52 return 0;
78 data->name.name = str;
79 } else
80 kfree(str);
81} 53}
82 54
83/** 55/**
84 * nfs_async_unlink_init - Initialize the RPC info 56 * nfs_async_unlink_init - Initialize the RPC info
85 * @task: rpc_task of the sillydelete 57 * task: rpc_task of the sillydelete
86 *
87 * We delay initializing RPC info until after the call to dentry_iput()
88 * in order to minimize races against rename().
89 */ 58 */
90static void nfs_async_unlink_init(struct rpc_task *task, void *calldata) 59static void nfs_async_unlink_init(struct rpc_task *task, void *calldata)
91{ 60{
92 struct nfs_unlinkdata *data = calldata; 61 struct nfs_unlinkdata *data = calldata;
93 struct dentry *dir = data->dir; 62 struct inode *dir = data->dir;
94 struct rpc_message msg = { 63 struct rpc_message msg = {
95 .rpc_cred = data->cred, 64 .rpc_argp = &data->args,
65 .rpc_resp = &data->res,
66 .rpc_cred = data->cred,
96 }; 67 };
97 int status = -ENOENT;
98
99 if (!data->name.len)
100 goto out_err;
101 68
102 status = NFS_PROTO(dir->d_inode)->unlink_setup(&msg, dir, &data->name); 69 nfs_begin_data_update(dir);
103 if (status < 0) 70 NFS_PROTO(dir)->unlink_setup(&msg, dir);
104 goto out_err;
105 nfs_begin_data_update(dir->d_inode);
106 rpc_call_setup(task, &msg, 0); 71 rpc_call_setup(task, &msg, 0);
107 return;
108 out_err:
109 rpc_exit(task, status);
110} 72}
111 73
112/** 74/**
@@ -117,19 +79,13 @@ static void nfs_async_unlink_init(struct rpc_task *task, void *calldata)
117 */ 79 */
118static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) 80static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
119{ 81{
120 struct nfs_unlinkdata *data = calldata; 82 struct nfs_unlinkdata *data = calldata;
121 struct dentry *dir = data->dir; 83 struct inode *dir = data->dir;
122 struct inode *dir_i; 84
123 85 if (!NFS_PROTO(dir)->unlink_done(task, dir))
124 if (!dir) 86 rpc_restart_call(task);
125 return; 87 else
126 dir_i = dir->d_inode; 88 nfs_end_data_update(dir);
127 nfs_end_data_update(dir_i);
128 if (NFS_PROTO(dir_i)->unlink_done(dir, task))
129 return;
130 put_rpccred(data->cred);
131 data->cred = NULL;
132 dput(dir);
133} 89}
134 90
135/** 91/**
@@ -142,7 +98,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
142static void nfs_async_unlink_release(void *calldata) 98static void nfs_async_unlink_release(void *calldata)
143{ 99{
144 struct nfs_unlinkdata *data = calldata; 100 struct nfs_unlinkdata *data = calldata;
145 nfs_put_unlinkdata(data); 101 nfs_free_unlinkdata(data);
146} 102}
147 103
148static const struct rpc_call_ops nfs_unlink_ops = { 104static const struct rpc_call_ops nfs_unlink_ops = {
@@ -151,73 +107,94 @@ static const struct rpc_call_ops nfs_unlink_ops = {
151 .rpc_release = nfs_async_unlink_release, 107 .rpc_release = nfs_async_unlink_release,
152}; 108};
153 109
110static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
111{
112 struct rpc_task *task;
113 struct dentry *parent;
114 struct inode *dir;
115
116 if (nfs_copy_dname(dentry, data) < 0)
117 goto out_free;
118
119 parent = dget_parent(dentry);
120 if (parent == NULL)
121 goto out_free;
122 dir = igrab(parent->d_inode);
123 dput(parent);
124 if (dir == NULL)
125 goto out_free;
126
127 data->dir = dir;
128 data->args.fh = NFS_FH(dir);
129 nfs_fattr_init(&data->res.dir_attr);
130
131 task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data);
132 if (!IS_ERR(task))
133 rpc_put_task(task);
134 return 1;
135out_free:
136 return 0;
137}
138
154/** 139/**
155 * nfs_async_unlink - asynchronous unlinking of a file 140 * nfs_async_unlink - asynchronous unlinking of a file
141 * @dir: parent directory of dentry
156 * @dentry: dentry to unlink 142 * @dentry: dentry to unlink
157 */ 143 */
158int 144int
159nfs_async_unlink(struct dentry *dentry) 145nfs_async_unlink(struct inode *dir, struct dentry *dentry)
160{ 146{
161 struct dentry *dir = dentry->d_parent; 147 struct nfs_unlinkdata *data;
162 struct nfs_unlinkdata *data; 148 int status = -ENOMEM;
163 struct rpc_clnt *clnt = NFS_CLIENT(dir->d_inode);
164 int status = -ENOMEM;
165 149
166 data = kzalloc(sizeof(*data), GFP_KERNEL); 150 data = kzalloc(sizeof(*data), GFP_KERNEL);
167 if (!data) 151 if (data == NULL)
168 goto out; 152 goto out;
169 153
170 data->cred = rpcauth_lookupcred(clnt->cl_auth, 0); 154 data->cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
171 if (IS_ERR(data->cred)) { 155 if (IS_ERR(data->cred)) {
172 status = PTR_ERR(data->cred); 156 status = PTR_ERR(data->cred);
173 goto out_free; 157 goto out_free;
174 } 158 }
175 data->dir = dget(dir);
176 data->dentry = dentry;
177
178 data->next = nfs_deletes;
179 nfs_deletes = data;
180 data->count = 1;
181
182 rpc_init_task(&data->task, clnt, RPC_TASK_ASYNC, &nfs_unlink_ops, data);
183 159
160 status = -EBUSY;
184 spin_lock(&dentry->d_lock); 161 spin_lock(&dentry->d_lock);
162 if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
163 goto out_unlock;
185 dentry->d_flags |= DCACHE_NFSFS_RENAMED; 164 dentry->d_flags |= DCACHE_NFSFS_RENAMED;
165 dentry->d_fsdata = data;
186 spin_unlock(&dentry->d_lock); 166 spin_unlock(&dentry->d_lock);
187 167 return 0;
188 rpc_sleep_on(&nfs_delete_queue, &data->task, NULL, NULL); 168out_unlock:
189 status = 0; 169 spin_unlock(&dentry->d_lock);
190 out: 170 put_rpccred(data->cred);
191 return status;
192out_free: 171out_free:
193 kfree(data); 172 kfree(data);
173out:
194 return status; 174 return status;
195} 175}
196 176
197/** 177/**
198 * nfs_complete_unlink - Initialize completion of the sillydelete 178 * nfs_complete_unlink - Initialize completion of the sillydelete
199 * @dentry: dentry to delete 179 * @dentry: dentry to delete
180 * @inode: inode
200 * 181 *
201 * Since we're most likely to be called by dentry_iput(), we 182 * Since we're most likely to be called by dentry_iput(), we
202 * only use the dentry to find the sillydelete. We then copy the name 183 * only use the dentry to find the sillydelete. We then copy the name
203 * into the qstr. 184 * into the qstr.
204 */ 185 */
205void 186void
206nfs_complete_unlink(struct dentry *dentry) 187nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
207{ 188{
208 struct nfs_unlinkdata *data; 189 struct nfs_unlinkdata *data = NULL;
209 190
210 for(data = nfs_deletes; data != NULL; data = data->next) {
211 if (dentry == data->dentry)
212 break;
213 }
214 if (!data)
215 return;
216 data->count++;
217 nfs_copy_dname(dentry, data);
218 spin_lock(&dentry->d_lock); 191 spin_lock(&dentry->d_lock);
219 dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; 192 if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
193 dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
194 data = dentry->d_fsdata;
195 }
220 spin_unlock(&dentry->d_lock); 196 spin_unlock(&dentry->d_lock);
221 rpc_wake_up_task(&data->task); 197
222 nfs_put_unlinkdata(data); 198 if (data != NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)))
199 nfs_free_unlinkdata(data);
223} 200}