diff options
| author | J. Bruce Fields <bfields@citi.umich.edu> | 2009-09-26 20:32:24 -0400 |
|---|---|---|
| committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-09-28 12:07:53 -0400 |
| commit | 289ede453e5a621de19c61e630302b1845cc1d59 (patch) | |
| tree | 0935cb943ed716441e22cea668ef60bc3bb2e3cf | |
| parent | fed83811269d0f559d2da9139e12c5e5d9874d5c (diff) | |
nfsd: minor nfsd_lookup cleanup
Break out some of nfsd_lookup_dentry into helper functions.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
| -rw-r--r-- | fs/nfsd/vfs.c | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index b8ed58bab8b1..638573968dcf 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -141,6 +141,40 @@ out: | |||
| 141 | return err; | 141 | return err; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | static void follow_to_parent(struct path *path) | ||
| 145 | { | ||
| 146 | struct dentry *dp; | ||
| 147 | |||
| 148 | while (path->dentry == path->mnt->mnt_root && follow_up(path)) | ||
| 149 | ; | ||
| 150 | dp = dget_parent(path->dentry); | ||
| 151 | dput(path->dentry); | ||
| 152 | path->dentry = dp; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, struct svc_export **exp, struct dentry **dentryp) | ||
| 156 | { | ||
| 157 | struct svc_export *exp2; | ||
| 158 | struct path path = {.mnt = mntget((*exp)->ex_path.mnt), | ||
| 159 | .dentry = dget(dparent)}; | ||
| 160 | |||
| 161 | follow_to_parent(&path); | ||
| 162 | |||
| 163 | exp2 = rqst_exp_parent(rqstp, &path); | ||
| 164 | if (PTR_ERR(exp2) == -ENOENT) { | ||
| 165 | *dentryp = dget(dparent); | ||
| 166 | } else if (IS_ERR(exp2)) { | ||
| 167 | path_put(&path); | ||
| 168 | return PTR_ERR(exp2); | ||
| 169 | } else { | ||
| 170 | *dentryp = dget(path.dentry); | ||
| 171 | exp_put(*exp); | ||
| 172 | *exp = exp2; | ||
| 173 | } | ||
| 174 | path_put(&path); | ||
| 175 | return 0; | ||
| 176 | } | ||
| 177 | |||
| 144 | __be32 | 178 | __be32 |
| 145 | nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, | 179 | nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, |
| 146 | const char *name, unsigned int len, | 180 | const char *name, unsigned int len, |
| @@ -173,31 +207,9 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 173 | dentry = dget(dparent); /* .. == . just like at / */ | 207 | dentry = dget(dparent); /* .. == . just like at / */ |
| 174 | else { | 208 | else { |
| 175 | /* checking mountpoint crossing is very different when stepping up */ | 209 | /* checking mountpoint crossing is very different when stepping up */ |
| 176 | struct svc_export *exp2 = NULL; | 210 | host_err = nfsd_lookup_parent(rqstp, dparent, &exp, &dentry); |
| 177 | struct dentry *dp; | 211 | if (host_err) |
| 178 | struct path path = {.mnt = mntget(exp->ex_path.mnt), | ||
| 179 | .dentry = dget(dparent)}; | ||
| 180 | |||
| 181 | while (path.dentry == path.mnt->mnt_root && | ||
| 182 | follow_up(&path)) | ||
| 183 | ; | ||
| 184 | dp = dget_parent(path.dentry); | ||
| 185 | dput(path.dentry); | ||
| 186 | path.dentry = dp; | ||
| 187 | |||
| 188 | exp2 = rqst_exp_parent(rqstp, &path); | ||
| 189 | if (PTR_ERR(exp2) == -ENOENT) { | ||
| 190 | dentry = dget(dparent); | ||
| 191 | } else if (IS_ERR(exp2)) { | ||
| 192 | host_err = PTR_ERR(exp2); | ||
| 193 | path_put(&path); | ||
| 194 | goto out_nfserr; | 212 | goto out_nfserr; |
| 195 | } else { | ||
| 196 | dentry = dget(path.dentry); | ||
| 197 | exp_put(exp); | ||
| 198 | exp = exp2; | ||
| 199 | } | ||
| 200 | path_put(&path); | ||
| 201 | } | 213 | } |
| 202 | } else { | 214 | } else { |
| 203 | fh_lock(fhp); | 215 | fh_lock(fhp); |
