NFS: Reduce the stack footprint of nfs_link()
Trond Myklebust [Fri, 16 Apr 2010 20:22:49 +0000 (16:22 -0400)]
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c

index 1c5bfb3..982a81b 100644 (file)
@@ -468,30 +468,32 @@ out:
 static int
 nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 {
-       struct nfs_fattr        dir_attr, fattr;
        struct nfs3_linkargs    arg = {
                .fromfh         = NFS_FH(inode),
                .tofh           = NFS_FH(dir),
                .toname         = name->name,
                .tolen          = name->len
        };
-       struct nfs3_linkres     res = {
-               .dir_attr       = &dir_attr,
-               .fattr          = &fattr
-       };
+       struct nfs3_linkres     res;
        struct rpc_message msg = {
                .rpc_proc       = &nfs3_procedures[NFS3PROC_LINK],
                .rpc_argp       = &arg,
                .rpc_resp       = &res,
        };
-       int                     status;
+       int status = -ENOMEM;
 
        dprintk("NFS call  link %s\n", name->name);
-       nfs_fattr_init(&dir_attr);
-       nfs_fattr_init(&fattr);
+       res.fattr = nfs_alloc_fattr();
+       res.dir_attr = nfs_alloc_fattr();
+       if (res.fattr == NULL || res.dir_attr == NULL)
+               goto out;
+
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-       nfs_post_op_update_inode(dir, &dir_attr);
-       nfs_post_op_update_inode(inode, &fattr);
+       nfs_post_op_update_inode(dir, res.dir_attr);
+       nfs_post_op_update_inode(inode, res.fattr);
+out:
+       nfs_free_fattr(res.dir_attr);
+       nfs_free_fattr(res.fattr);
        dprintk("NFS reply link: %d\n", status);
        return status;
 }
index 14cde99..0ffd4cf 100644 (file)
@@ -2707,28 +2707,30 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
                .name   = name,
                .bitmask = server->attr_bitmask,
        };
-       struct nfs_fattr fattr, dir_attr;
        struct nfs4_link_res res = {
                .server = server,
-               .fattr = &fattr,
-               .dir_attr = &dir_attr,
        };
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
                .rpc_argp = &arg,
                .rpc_resp = &res,
        };
-       int                     status;
+       int status = -ENOMEM;
+
+       res.fattr = nfs_alloc_fattr();
+       res.dir_attr = nfs_alloc_fattr();
+       if (res.fattr == NULL || res.dir_attr == NULL)
+               goto out;
 
-       nfs_fattr_init(res.fattr);
-       nfs_fattr_init(res.dir_attr);
        status = nfs4_call_sync(server, &msg, &arg, &res, 1);
        if (!status) {
                update_changeattr(dir, &res.cinfo);
                nfs_post_op_update_inode(dir, res.dir_attr);
                nfs_post_op_update_inode(inode, res.fattr);
        }
-
+out:
+       nfs_free_fattr(res.dir_attr);
+       nfs_free_fattr(res.fattr);
        return status;
 }