aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-04-16 16:22:47 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-05-14 15:09:23 -0400
commite1fb4d05d5a3265f1f6769bee034175f91ecc2dd (patch)
treeb5a1d30b2f57e0b9c1d021ed653030fb5c699147 /fs/nfs
parent364d015e5208e4669a4ae9fab2ab104ff26bc159 (diff)
NFS: Reduce the stack footprint of nfs_lookup
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/dir.c45
-rw-r--r--fs/nfs/nfs3proc.c10
2 files changed, 41 insertions, 14 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a7bb5c694aa3..1debc09eb55f 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -776,9 +776,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
776 struct inode *dir; 776 struct inode *dir;
777 struct inode *inode; 777 struct inode *inode;
778 struct dentry *parent; 778 struct dentry *parent;
779 struct nfs_fh *fhandle = NULL;
780 struct nfs_fattr *fattr = NULL;
779 int error; 781 int error;
780 struct nfs_fh fhandle;
781 struct nfs_fattr fattr;
782 782
783 parent = dget_parent(dentry); 783 parent = dget_parent(dentry);
784 dir = parent->d_inode; 784 dir = parent->d_inode;
@@ -811,14 +811,22 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
811 if (NFS_STALE(inode)) 811 if (NFS_STALE(inode))
812 goto out_bad; 812 goto out_bad;
813 813
814 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); 814 error = -ENOMEM;
815 fhandle = nfs_alloc_fhandle();
816 fattr = nfs_alloc_fattr();
817 if (fhandle == NULL || fattr == NULL)
818 goto out_error;
819
820 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
815 if (error) 821 if (error)
816 goto out_bad; 822 goto out_bad;
817 if (nfs_compare_fh(NFS_FH(inode), &fhandle)) 823 if (nfs_compare_fh(NFS_FH(inode), fhandle))
818 goto out_bad; 824 goto out_bad;
819 if ((error = nfs_refresh_inode(inode, &fattr)) != 0) 825 if ((error = nfs_refresh_inode(inode, fattr)) != 0)
820 goto out_bad; 826 goto out_bad;
821 827
828 nfs_free_fattr(fattr);
829 nfs_free_fhandle(fhandle);
822out_set_verifier: 830out_set_verifier:
823 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 831 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
824 out_valid: 832 out_valid:
@@ -842,11 +850,21 @@ out_zap_parent:
842 shrink_dcache_parent(dentry); 850 shrink_dcache_parent(dentry);
843 } 851 }
844 d_drop(dentry); 852 d_drop(dentry);
853 nfs_free_fattr(fattr);
854 nfs_free_fhandle(fhandle);
845 dput(parent); 855 dput(parent);
846 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", 856 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
847 __func__, dentry->d_parent->d_name.name, 857 __func__, dentry->d_parent->d_name.name,
848 dentry->d_name.name); 858 dentry->d_name.name);
849 return 0; 859 return 0;
860out_error:
861 nfs_free_fattr(fattr);
862 nfs_free_fhandle(fhandle);
863 dput(parent);
864 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n",
865 __func__, dentry->d_parent->d_name.name,
866 dentry->d_name.name, error);
867 return error;
850} 868}
851 869
852/* 870/*
@@ -911,9 +929,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
911 struct dentry *res; 929 struct dentry *res;
912 struct dentry *parent; 930 struct dentry *parent;
913 struct inode *inode = NULL; 931 struct inode *inode = NULL;
932 struct nfs_fh *fhandle = NULL;
933 struct nfs_fattr *fattr = NULL;
914 int error; 934 int error;
915 struct nfs_fh fhandle;
916 struct nfs_fattr fattr;
917 935
918 dfprintk(VFS, "NFS: lookup(%s/%s)\n", 936 dfprintk(VFS, "NFS: lookup(%s/%s)\n",
919 dentry->d_parent->d_name.name, dentry->d_name.name); 937 dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -923,7 +941,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
923 if (dentry->d_name.len > NFS_SERVER(dir)->namelen) 941 if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
924 goto out; 942 goto out;
925 943
926 res = ERR_PTR(-ENOMEM);
927 dentry->d_op = NFS_PROTO(dir)->dentry_ops; 944 dentry->d_op = NFS_PROTO(dir)->dentry_ops;
928 945
929 /* 946 /*
@@ -936,17 +953,23 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
936 goto out; 953 goto out;
937 } 954 }
938 955
956 res = ERR_PTR(-ENOMEM);
957 fhandle = nfs_alloc_fhandle();
958 fattr = nfs_alloc_fattr();
959 if (fhandle == NULL || fattr == NULL)
960 goto out;
961
939 parent = dentry->d_parent; 962 parent = dentry->d_parent;
940 /* Protect against concurrent sillydeletes */ 963 /* Protect against concurrent sillydeletes */
941 nfs_block_sillyrename(parent); 964 nfs_block_sillyrename(parent);
942 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); 965 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
943 if (error == -ENOENT) 966 if (error == -ENOENT)
944 goto no_entry; 967 goto no_entry;
945 if (error < 0) { 968 if (error < 0) {
946 res = ERR_PTR(error); 969 res = ERR_PTR(error);
947 goto out_unblock_sillyrename; 970 goto out_unblock_sillyrename;
948 } 971 }
949 inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); 972 inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
950 res = (struct dentry *)inode; 973 res = (struct dentry *)inode;
951 if (IS_ERR(res)) 974 if (IS_ERR(res))
952 goto out_unblock_sillyrename; 975 goto out_unblock_sillyrename;
@@ -962,6 +985,8 @@ no_entry:
962out_unblock_sillyrename: 985out_unblock_sillyrename:
963 nfs_unblock_sillyrename(parent); 986 nfs_unblock_sillyrename(parent);
964out: 987out:
988 nfs_free_fattr(fattr);
989 nfs_free_fhandle(fhandle);
965 return res; 990 return res;
966} 991}
967 992
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index e701002694e5..72334c19d481 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -144,14 +144,12 @@ static int
144nfs3_proc_lookup(struct inode *dir, struct qstr *name, 144nfs3_proc_lookup(struct inode *dir, struct qstr *name,
145 struct nfs_fh *fhandle, struct nfs_fattr *fattr) 145 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
146{ 146{
147 struct nfs_fattr dir_attr;
148 struct nfs3_diropargs arg = { 147 struct nfs3_diropargs arg = {
149 .fh = NFS_FH(dir), 148 .fh = NFS_FH(dir),
150 .name = name->name, 149 .name = name->name,
151 .len = name->len 150 .len = name->len
152 }; 151 };
153 struct nfs3_diropres res = { 152 struct nfs3_diropres res = {
154 .dir_attr = &dir_attr,
155 .fh = fhandle, 153 .fh = fhandle,
156 .fattr = fattr 154 .fattr = fattr
157 }; 155 };
@@ -163,16 +161,20 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
163 int status; 161 int status;
164 162
165 dprintk("NFS call lookup %s\n", name->name); 163 dprintk("NFS call lookup %s\n", name->name);
166 nfs_fattr_init(&dir_attr); 164 res.dir_attr = nfs_alloc_fattr();
165 if (res.dir_attr == NULL)
166 return -ENOMEM;
167
167 nfs_fattr_init(fattr); 168 nfs_fattr_init(fattr);
168 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 169 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
169 nfs_refresh_inode(dir, &dir_attr); 170 nfs_refresh_inode(dir, res.dir_attr);
170 if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) { 171 if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
171 msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; 172 msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
172 msg.rpc_argp = fhandle; 173 msg.rpc_argp = fhandle;
173 msg.rpc_resp = fattr; 174 msg.rpc_resp = fattr;
174 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 175 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
175 } 176 }
177 nfs_free_fattr(res.dir_attr);
176 dprintk("NFS reply lookup: %d\n", status); 178 dprintk("NFS reply lookup: %d\n", status);
177 return status; 179 return status;
178} 180}