Commit 03550fac06c4f0c39a1885d46015c28794413c82

Authored by J. Bruce Fields
1 parent c3bb257d2d

nfsd: move most of fh_verify to separate function

Move the code that actually parses the filehandle and looks up the
dentry and export to a separate function.  This simplifies the reference
counting a little and moves fh_verify() a little closer to the kernel
ideal of small, minimally-indentended functions.  Clean up a few other
minor style sins along the way.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Cc: Neil Brown <neilb@suse.de>

Showing 1 changed file with 123 additions and 105 deletions Side-by-side Diff

... ... @@ -113,6 +113,124 @@
113 113 }
114 114  
115 115 /*
  116 + * Use the given filehandle to look up the corresponding export and
  117 + * dentry. On success, the results are used to set fh_export and
  118 + * fh_dentry.
  119 + */
  120 +static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
  121 +{
  122 + struct knfsd_fh *fh = &fhp->fh_handle;
  123 + struct fid *fid = NULL, sfid;
  124 + struct svc_export *exp;
  125 + struct dentry *dentry;
  126 + int fileid_type;
  127 + int data_left = fh->fh_size/4;
  128 + __be32 error;
  129 +
  130 + error = nfserr_stale;
  131 + if (rqstp->rq_vers > 2)
  132 + error = nfserr_badhandle;
  133 + if (rqstp->rq_vers == 4 && fh->fh_size == 0)
  134 + return nfserr_nofilehandle;
  135 +
  136 + if (fh->fh_version == 1) {
  137 + int len;
  138 +
  139 + if (--data_left < 0)
  140 + return error;
  141 + if (fh->fh_auth_type != 0)
  142 + return error;
  143 + len = key_len(fh->fh_fsid_type) / 4;
  144 + if (len == 0)
  145 + return error;
  146 + if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
  147 + /* deprecated, convert to type 3 */
  148 + len = key_len(FSID_ENCODE_DEV)/4;
  149 + fh->fh_fsid_type = FSID_ENCODE_DEV;
  150 + fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
  151 + fh->fh_fsid[1] = fh->fh_fsid[2];
  152 + }
  153 + data_left -= len;
  154 + if (data_left < 0)
  155 + return error;
  156 + exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_auth);
  157 + fid = (struct fid *)(fh->fh_auth + len);
  158 + } else {
  159 + __u32 tfh[2];
  160 + dev_t xdev;
  161 + ino_t xino;
  162 +
  163 + if (fh->fh_size != NFS_FHSIZE)
  164 + return error;
  165 + /* assume old filehandle format */
  166 + xdev = old_decode_dev(fh->ofh_xdev);
  167 + xino = u32_to_ino_t(fh->ofh_xino);
  168 + mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
  169 + exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
  170 + }
  171 +
  172 + error = nfserr_stale;
  173 + if (PTR_ERR(exp) == -ENOENT)
  174 + return error;
  175 +
  176 + if (IS_ERR(exp))
  177 + return nfserrno(PTR_ERR(exp));
  178 +
  179 + error = nfsd_setuser_and_check_port(rqstp, exp);
  180 + if (error)
  181 + goto out;
  182 +
  183 + /*
  184 + * Look up the dentry using the NFS file handle.
  185 + */
  186 + error = nfserr_stale;
  187 + if (rqstp->rq_vers > 2)
  188 + error = nfserr_badhandle;
  189 +
  190 + if (fh->fh_version != 1) {
  191 + sfid.i32.ino = fh->ofh_ino;
  192 + sfid.i32.gen = fh->ofh_generation;
  193 + sfid.i32.parent_ino = fh->ofh_dirino;
  194 + fid = &sfid;
  195 + data_left = 3;
  196 + if (fh->ofh_dirino == 0)
  197 + fileid_type = FILEID_INO32_GEN;
  198 + else
  199 + fileid_type = FILEID_INO32_GEN_PARENT;
  200 + } else
  201 + fileid_type = fh->fh_fileid_type;
  202 +
  203 + if (fileid_type == FILEID_ROOT)
  204 + dentry = dget(exp->ex_path.dentry);
  205 + else {
  206 + dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
  207 + data_left, fileid_type,
  208 + nfsd_acceptable, exp);
  209 + }
  210 + if (dentry == NULL)
  211 + goto out;
  212 + if (IS_ERR(dentry)) {
  213 + if (PTR_ERR(dentry) != -EINVAL)
  214 + error = nfserrno(PTR_ERR(dentry));
  215 + goto out;
  216 + }
  217 +
  218 + if (S_ISDIR(dentry->d_inode->i_mode) &&
  219 + (dentry->d_flags & DCACHE_DISCONNECTED)) {
  220 + printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
  221 + dentry->d_parent->d_name.name, dentry->d_name.name);
  222 + }
  223 +
  224 + fhp->fh_dentry = dentry;
  225 + fhp->fh_export = exp;
  226 + nfsd_nr_verified++;
  227 + return 0;
  228 +out:
  229 + exp_put(exp);
  230 + return error;
  231 +}
  232 +
  233 +/*
116 234 * Perform sanity checks on the dentry in a client's file handle.
117 235 *
118 236 * Note that the file handle dentry may need to be freed even after
119 237  
120 238  
121 239  
... ... @@ -124,115 +242,18 @@
124 242 __be32
125 243 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
126 244 {
127   - struct knfsd_fh *fh = &fhp->fh_handle;
128   - struct svc_export *exp = NULL;
  245 + struct svc_export *exp;
129 246 struct dentry *dentry;
130   - __be32 error = 0;
  247 + __be32 error;
131 248  
132 249 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
133 250  
134 251 if (!fhp->fh_dentry) {
135   - struct fid *fid = NULL, sfid;
136   - int fileid_type;
137   - int data_left = fh->fh_size/4;
138   -
139   - error = nfserr_stale;
140   - if (rqstp->rq_vers > 2)
141   - error = nfserr_badhandle;
142   - if (rqstp->rq_vers == 4 && fh->fh_size == 0)
143   - return nfserr_nofilehandle;
144   -
145   - if (fh->fh_version == 1) {
146   - int len;
147   - if (--data_left<0) goto out;
148   - switch (fh->fh_auth_type) {
149   - case 0: break;
150   - default: goto out;
151   - }
152   - len = key_len(fh->fh_fsid_type) / 4;
153   - if (len == 0) goto out;
154   - if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
155   - /* deprecated, convert to type 3 */
156   - len = key_len(FSID_ENCODE_DEV)/4;
157   - fh->fh_fsid_type = FSID_ENCODE_DEV;
158   - fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
159   - fh->fh_fsid[1] = fh->fh_fsid[2];
160   - }
161   - if ((data_left -= len)<0) goto out;
162   - exp = rqst_exp_find(rqstp, fh->fh_fsid_type,
163   - fh->fh_auth);
164   - fid = (struct fid *)(fh->fh_auth + len);
165   - } else {
166   - __u32 tfh[2];
167   - dev_t xdev;
168   - ino_t xino;
169   - if (fh->fh_size != NFS_FHSIZE)
170   - goto out;
171   - /* assume old filehandle format */
172   - xdev = old_decode_dev(fh->ofh_xdev);
173   - xino = u32_to_ino_t(fh->ofh_xino);
174   - mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
175   - exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
176   - }
177   -
178   - error = nfserr_stale;
179   - if (PTR_ERR(exp) == -ENOENT)
180   - goto out;
181   -
182   - if (IS_ERR(exp)) {
183   - error = nfserrno(PTR_ERR(exp));
184   - goto out;
185   - }
186   -
187   - error = nfsd_setuser_and_check_port(rqstp, exp);
  252 + error = nfsd_set_fh_dentry(rqstp, fhp);
188 253 if (error)
189 254 goto out;
190   -
191   - /*
192   - * Look up the dentry using the NFS file handle.
193   - */
194   - error = nfserr_stale;
195   - if (rqstp->rq_vers > 2)
196   - error = nfserr_badhandle;
197   -
198   - if (fh->fh_version != 1) {
199   - sfid.i32.ino = fh->ofh_ino;
200   - sfid.i32.gen = fh->ofh_generation;
201   - sfid.i32.parent_ino = fh->ofh_dirino;
202   - fid = &sfid;
203   - data_left = 3;
204   - if (fh->ofh_dirino == 0)
205   - fileid_type = FILEID_INO32_GEN;
206   - else
207   - fileid_type = FILEID_INO32_GEN_PARENT;
208   - } else
209   - fileid_type = fh->fh_fileid_type;
210   -
211   - if (fileid_type == FILEID_ROOT)
212   - dentry = dget(exp->ex_path.dentry);
213   - else {
214   - dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
215   - data_left, fileid_type,
216   - nfsd_acceptable, exp);
217   - }
218   - if (dentry == NULL)
219   - goto out;
220   - if (IS_ERR(dentry)) {
221   - if (PTR_ERR(dentry) != -EINVAL)
222   - error = nfserrno(PTR_ERR(dentry));
223   - goto out;
224   - }
225   -
226   - if (S_ISDIR(dentry->d_inode->i_mode) &&
227   - (dentry->d_flags & DCACHE_DISCONNECTED)) {
228   - printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
229   - dentry->d_parent->d_name.name, dentry->d_name.name);
230   - }
231   -
232   - fhp->fh_dentry = dentry;
233   - fhp->fh_export = exp;
234   - nfsd_nr_verified++;
235   - cache_get(&exp->h);
  255 + dentry = fhp->fh_dentry;
  256 + exp = fhp->fh_export;
236 257 } else {
237 258 /*
238 259 * just rechecking permissions
... ... @@ -242,7 +263,6 @@
242 263 dprintk("nfsd: fh_verify - just checking\n");
243 264 dentry = fhp->fh_dentry;
244 265 exp = fhp->fh_export;
245   - cache_get(&exp->h);
246 266 /*
247 267 * Set user creds for this exportpoint; necessary even
248 268 * in the "just checking" case because this may be a
... ... @@ -281,8 +301,6 @@
281 301 access, ntohl(error));
282 302 }
283 303 out:
284   - if (exp && !IS_ERR(exp))
285   - exp_put(exp);
286 304 if (error == nfserr_stale)
287 305 nfsdstats.fh_stale++;
288 306 return error;