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)) { | ||
