diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfsfh.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 739dd3c5c3b2..6ca2d24fc216 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -323,7 +323,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, | |||
323 | * | 323 | * |
324 | */ | 324 | */ |
325 | 325 | ||
326 | u8 version = 1; | 326 | u8 version; |
327 | u8 fsid_type = 0; | 327 | u8 fsid_type = 0; |
328 | struct inode * inode = dentry->d_inode; | 328 | struct inode * inode = dentry->d_inode; |
329 | struct dentry *parent = dentry->d_parent; | 329 | struct dentry *parent = dentry->d_parent; |
@@ -341,15 +341,59 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, | |||
341 | * the reference filehandle (if it is in the same export) | 341 | * the reference filehandle (if it is in the same export) |
342 | * or the export options. | 342 | * or the export options. |
343 | */ | 343 | */ |
344 | retry: | ||
345 | version = 1; | ||
344 | if (ref_fh && ref_fh->fh_export == exp) { | 346 | if (ref_fh && ref_fh->fh_export == exp) { |
345 | version = ref_fh->fh_handle.fh_version; | 347 | version = ref_fh->fh_handle.fh_version; |
346 | if (version == 0xca) | 348 | fsid_type = ref_fh->fh_handle.fh_fsid_type; |
349 | |||
350 | if (ref_fh == fhp) | ||
351 | fh_put(ref_fh); | ||
352 | ref_fh = NULL; | ||
353 | |||
354 | switch (version) { | ||
355 | case 0xca: | ||
347 | fsid_type = FSID_DEV; | 356 | fsid_type = FSID_DEV; |
348 | else | 357 | break; |
349 | fsid_type = ref_fh->fh_handle.fh_fsid_type; | 358 | case 1: |
350 | /* We know this version/type works for this export | 359 | break; |
351 | * so there is no need for further checks. | 360 | default: |
361 | goto retry; | ||
362 | } | ||
363 | |||
364 | /* Need to check that this type works for this | ||
365 | * export point. As the fsid -> filesystem mapping | ||
366 | * was guided by user-space, there is no guarantee | ||
367 | * that the filesystem actually supports that fsid | ||
368 | * type. If it doesn't we loop around again without | ||
369 | * ref_fh set. | ||
352 | */ | 370 | */ |
371 | switch(fsid_type) { | ||
372 | case FSID_DEV: | ||
373 | if (!old_valid_dev(ex_dev)) | ||
374 | goto retry; | ||
375 | /* FALL THROUGH */ | ||
376 | case FSID_MAJOR_MINOR: | ||
377 | case FSID_ENCODE_DEV: | ||
378 | if (!(exp->ex_dentry->d_inode->i_sb->s_type->fs_flags | ||
379 | & FS_REQUIRES_DEV)) | ||
380 | goto retry; | ||
381 | break; | ||
382 | case FSID_NUM: | ||
383 | if (! (exp->ex_flags & NFSEXP_FSID)) | ||
384 | goto retry; | ||
385 | break; | ||
386 | case FSID_UUID8: | ||
387 | case FSID_UUID16: | ||
388 | if (!root_export) | ||
389 | goto retry; | ||
390 | /* fall through */ | ||
391 | case FSID_UUID4_INUM: | ||
392 | case FSID_UUID16_INUM: | ||
393 | if (exp->ex_uuid == NULL) | ||
394 | goto retry; | ||
395 | break; | ||
396 | } | ||
353 | } else if (exp->ex_uuid) { | 397 | } else if (exp->ex_uuid) { |
354 | if (fhp->fh_maxsize >= 64) { | 398 | if (fhp->fh_maxsize >= 64) { |
355 | if (root_export) | 399 | if (root_export) |