diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-04-16 16:22:47 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-14 15:09:23 -0400 |
commit | e1fb4d05d5a3265f1f6769bee034175f91ecc2dd (patch) | |
tree | b5a1d30b2f57e0b9c1d021ed653030fb5c699147 /fs | |
parent | 364d015e5208e4669a4ae9fab2ab104ff26bc159 (diff) |
NFS: Reduce the stack footprint of nfs_lookup
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/dir.c | 45 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 10 |
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); | ||
822 | out_set_verifier: | 830 | out_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; |
860 | out_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: | |||
962 | out_unblock_sillyrename: | 985 | out_unblock_sillyrename: |
963 | nfs_unblock_sillyrename(parent); | 986 | nfs_unblock_sillyrename(parent); |
964 | out: | 987 | out: |
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 | |||
144 | nfs3_proc_lookup(struct inode *dir, struct qstr *name, | 144 | nfs3_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 | } |