diff options
author | J. Bruce Fields <bfields@puzzle.fieldses.org> | 2007-07-17 07:04:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-17 13:23:07 -0400 |
commit | 2d3bb25209c1f9a27ea9535c7fd2f6729a5e7db1 (patch) | |
tree | 487ccec9aaf60298d4cb7b2fc5f4d76072bcc60b | |
parent | 47f9940c55c0bdc65188749cae4e841601f513bb (diff) |
knfsd: nfsd: make all exp_finding functions return -errno's on err
Currently exp_find(), exp_get_by_name(), and friends, return an export on
success, and on failure return:
errors -EAGAIN (drop this request pending an upcall) or
-ETIMEDOUT (an upcall has timed out), or
return NULL, which can mean either that there was a memory allocation
failure, or that an export was not found, or that a passed-in
export lacks an auth_domain.
Many callers seem to assume that NULL means that an export was not found,
which may lead to bugs in the case of a memory allocation failure.
Modify these functions to distinguish between the two NULL cases by returning
either -ENOENT or -ENOMEM. They now never return NULL. We get to simplify
some code in the process.
We return -ENOENT in the case of a missing auth_domain. This case should
probably be removed (or converted to a bug) after confirming that it can never
happen.
Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/nfsd/export.c | 58 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 11 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 9 |
3 files changed, 32 insertions, 46 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index c518421a9355..d4accdcb53a2 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -739,16 +739,18 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) | |||
739 | int err; | 739 | int err; |
740 | 740 | ||
741 | if (!clp) | 741 | if (!clp) |
742 | return NULL; | 742 | return ERR_PTR(-ENOENT); |
743 | 743 | ||
744 | key.ek_client = clp; | 744 | key.ek_client = clp; |
745 | key.ek_fsidtype = fsid_type; | 745 | key.ek_fsidtype = fsid_type; |
746 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); | 746 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); |
747 | 747 | ||
748 | ek = svc_expkey_lookup(&key); | 748 | ek = svc_expkey_lookup(&key); |
749 | if (ek != NULL) | 749 | if (ek == NULL) |
750 | if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) | 750 | return ERR_PTR(-ENOMEM); |
751 | ek = ERR_PTR(err); | 751 | err = cache_check(&svc_expkey_cache, &ek->h, reqp); |
752 | if (err) | ||
753 | return ERR_PTR(err); | ||
752 | return ek; | 754 | return ek; |
753 | } | 755 | } |
754 | 756 | ||
@@ -809,30 +811,21 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, | |||
809 | struct cache_req *reqp) | 811 | struct cache_req *reqp) |
810 | { | 812 | { |
811 | struct svc_export *exp, key; | 813 | struct svc_export *exp, key; |
814 | int err; | ||
812 | 815 | ||
813 | if (!clp) | 816 | if (!clp) |
814 | return NULL; | 817 | return ERR_PTR(-ENOENT); |
815 | 818 | ||
816 | key.ex_client = clp; | 819 | key.ex_client = clp; |
817 | key.ex_mnt = mnt; | 820 | key.ex_mnt = mnt; |
818 | key.ex_dentry = dentry; | 821 | key.ex_dentry = dentry; |
819 | 822 | ||
820 | exp = svc_export_lookup(&key); | 823 | exp = svc_export_lookup(&key); |
821 | if (exp != NULL) { | 824 | if (exp == NULL) |
822 | int err; | 825 | return ERR_PTR(-ENOMEM); |
823 | 826 | err = cache_check(&svc_export_cache, &exp->h, reqp); | |
824 | err = cache_check(&svc_export_cache, &exp->h, reqp); | 827 | if (err) |
825 | switch (err) { | 828 | return ERR_PTR(err); |
826 | case 0: break; | ||
827 | case -EAGAIN: | ||
828 | case -ETIMEDOUT: | ||
829 | exp = ERR_PTR(err); | ||
830 | break; | ||
831 | default: | ||
832 | exp = NULL; | ||
833 | } | ||
834 | } | ||
835 | |||
836 | return exp; | 829 | return exp; |
837 | } | 830 | } |
838 | 831 | ||
@@ -848,7 +841,7 @@ exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, | |||
848 | dget(dentry); | 841 | dget(dentry); |
849 | exp = exp_get_by_name(clp, mnt, dentry, reqp); | 842 | exp = exp_get_by_name(clp, mnt, dentry, reqp); |
850 | 843 | ||
851 | while (exp == NULL && !IS_ROOT(dentry)) { | 844 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) { |
852 | struct dentry *parent; | 845 | struct dentry *parent; |
853 | 846 | ||
854 | parent = dget_parent(dentry); | 847 | parent = dget_parent(dentry); |
@@ -901,7 +894,7 @@ static void exp_fsid_unhash(struct svc_export *exp) | |||
901 | return; | 894 | return; |
902 | 895 | ||
903 | ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); | 896 | ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); |
904 | if (ek && !IS_ERR(ek)) { | 897 | if (!IS_ERR(ek)) { |
905 | ek->h.expiry_time = get_seconds()-1; | 898 | ek->h.expiry_time = get_seconds()-1; |
906 | cache_put(&ek->h, &svc_expkey_cache); | 899 | cache_put(&ek->h, &svc_expkey_cache); |
907 | } | 900 | } |
@@ -939,7 +932,7 @@ static void exp_unhash(struct svc_export *exp) | |||
939 | struct inode *inode = exp->ex_dentry->d_inode; | 932 | struct inode *inode = exp->ex_dentry->d_inode; |
940 | 933 | ||
941 | ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); | 934 | ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); |
942 | if (ek && !IS_ERR(ek)) { | 935 | if (!IS_ERR(ek)) { |
943 | ek->h.expiry_time = get_seconds()-1; | 936 | ek->h.expiry_time = get_seconds()-1; |
944 | cache_put(&ek->h, &svc_expkey_cache); | 937 | cache_put(&ek->h, &svc_expkey_cache); |
945 | } | 938 | } |
@@ -990,13 +983,12 @@ exp_export(struct nfsctl_export *nxp) | |||
990 | 983 | ||
991 | /* must make sure there won't be an ex_fsid clash */ | 984 | /* must make sure there won't be an ex_fsid clash */ |
992 | if ((nxp->ex_flags & NFSEXP_FSID) && | 985 | if ((nxp->ex_flags & NFSEXP_FSID) && |
993 | (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && | 986 | (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) && |
994 | !IS_ERR(fsid_key) && | ||
995 | fsid_key->ek_mnt && | 987 | fsid_key->ek_mnt && |
996 | (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) | 988 | (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) |
997 | goto finish; | 989 | goto finish; |
998 | 990 | ||
999 | if (exp) { | 991 | if (!IS_ERR(exp)) { |
1000 | /* just a flags/id/fsid update */ | 992 | /* just a flags/id/fsid update */ |
1001 | 993 | ||
1002 | exp_fsid_unhash(exp); | 994 | exp_fsid_unhash(exp); |
@@ -1105,7 +1097,7 @@ exp_unexport(struct nfsctl_export *nxp) | |||
1105 | err = -EINVAL; | 1097 | err = -EINVAL; |
1106 | exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); | 1098 | exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); |
1107 | path_release(&nd); | 1099 | path_release(&nd); |
1108 | if (!exp) | 1100 | if (IS_ERR(exp)) |
1109 | goto out_domain; | 1101 | goto out_domain; |
1110 | 1102 | ||
1111 | exp_do_unexport(exp); | 1103 | exp_do_unexport(exp); |
@@ -1150,10 +1142,6 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize) | |||
1150 | err = PTR_ERR(exp); | 1142 | err = PTR_ERR(exp); |
1151 | goto out; | 1143 | goto out; |
1152 | } | 1144 | } |
1153 | if (!exp) { | ||
1154 | dprintk("nfsd: exp_rootfh export not found.\n"); | ||
1155 | goto out; | ||
1156 | } | ||
1157 | 1145 | ||
1158 | /* | 1146 | /* |
1159 | * fh must be initialized before calling fh_compose | 1147 | * fh must be initialized before calling fh_compose |
@@ -1177,13 +1165,13 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, | |||
1177 | { | 1165 | { |
1178 | struct svc_export *exp; | 1166 | struct svc_export *exp; |
1179 | struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); | 1167 | struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); |
1180 | if (!ek || IS_ERR(ek)) | 1168 | if (IS_ERR(ek)) |
1181 | return ERR_PTR(PTR_ERR(ek)); | 1169 | return ERR_PTR(PTR_ERR(ek)); |
1182 | 1170 | ||
1183 | exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); | 1171 | exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); |
1184 | cache_put(&ek->h, &svc_expkey_cache); | 1172 | cache_put(&ek->h, &svc_expkey_cache); |
1185 | 1173 | ||
1186 | if (!exp || IS_ERR(exp)) | 1174 | if (IS_ERR(exp)) |
1187 | return ERR_PTR(PTR_ERR(exp)); | 1175 | return ERR_PTR(PTR_ERR(exp)); |
1188 | return exp; | 1176 | return exp; |
1189 | } | 1177 | } |
@@ -1205,10 +1193,10 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
1205 | mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); | 1193 | mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); |
1206 | 1194 | ||
1207 | exp = exp_find(clp, FSID_NUM, fsidv, creq); | 1195 | exp = exp_find(clp, FSID_NUM, fsidv, creq); |
1196 | if (PTR_ERR(exp) == -ENOENT) | ||
1197 | return nfserr_perm; | ||
1208 | if (IS_ERR(exp)) | 1198 | if (IS_ERR(exp)) |
1209 | return nfserrno(PTR_ERR(exp)); | 1199 | return nfserrno(PTR_ERR(exp)); |
1210 | if (exp == NULL) | ||
1211 | return nfserr_perm; | ||
1212 | rv = fh_compose(fhp, exp, exp->ex_dentry, NULL); | 1200 | rv = fh_compose(fhp, exp, exp->ex_dentry, NULL); |
1213 | exp_put(exp); | 1201 | exp_put(exp); |
1214 | return rv; | 1202 | return rv; |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index ecf9c361b3f5..89f9041a7782 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -160,15 +160,14 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
160 | &rqstp->rq_chandle); | 160 | &rqstp->rq_chandle); |
161 | } | 161 | } |
162 | 162 | ||
163 | if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN | 163 | error = nfserr_stale; |
164 | || PTR_ERR(exp) == -ETIMEDOUT)) { | 164 | if (PTR_ERR(exp) == -ENOENT) |
165 | error = nfserrno(PTR_ERR(exp)); | ||
166 | goto out; | 165 | goto out; |
167 | } | ||
168 | 166 | ||
169 | error = nfserr_stale; | 167 | if (IS_ERR(exp)) { |
170 | if (!exp || IS_ERR(exp)) | 168 | error = nfserrno(PTR_ERR(exp)); |
171 | goto out; | 169 | goto out; |
170 | } | ||
172 | 171 | ||
173 | /* Check if the request originated from a secure port. */ | 172 | /* Check if the request originated from a secure port. */ |
174 | error = nfserr_perm; | 173 | error = nfserr_perm; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 8d6b5c483ae1..0a18149ce963 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -192,15 +192,14 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, | |||
192 | 192 | ||
193 | exp2 = exp_parent(exp->ex_client, mnt, dentry, | 193 | exp2 = exp_parent(exp->ex_client, mnt, dentry, |
194 | &rqstp->rq_chandle); | 194 | &rqstp->rq_chandle); |
195 | if (IS_ERR(exp2)) { | 195 | if (PTR_ERR(exp2) == -ENOENT) { |
196 | dput(dentry); | ||
197 | dentry = dget(dparent); | ||
198 | } else if (IS_ERR(exp2)) { | ||
196 | host_err = PTR_ERR(exp2); | 199 | host_err = PTR_ERR(exp2); |
197 | dput(dentry); | 200 | dput(dentry); |
198 | mntput(mnt); | 201 | mntput(mnt); |
199 | goto out_nfserr; | 202 | goto out_nfserr; |
200 | } | ||
201 | if (!exp2) { | ||
202 | dput(dentry); | ||
203 | dentry = dget(dparent); | ||
204 | } else { | 203 | } else { |
205 | exp_put(exp); | 204 | exp_put(exp); |
206 | exp = exp2; | 205 | exp = exp2; |