diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/nfsfh.c | 83 |
1 files changed, 45 insertions, 38 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 8847f3fbfc1e..78d8ebf162ca 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -397,6 +397,40 @@ static inline void _fh_update_old(struct dentry *dentry, | |||
397 | fh->ofh_dirino = 0; | 397 | fh->ofh_dirino = 0; |
398 | } | 398 | } |
399 | 399 | ||
400 | static bool is_root_export(struct svc_export *exp) | ||
401 | { | ||
402 | return exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root; | ||
403 | } | ||
404 | |||
405 | static struct super_block *exp_sb(struct svc_export *exp) | ||
406 | { | ||
407 | return exp->ex_path.dentry->d_inode->i_sb; | ||
408 | } | ||
409 | |||
410 | static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp) | ||
411 | { | ||
412 | switch (fsid_type) { | ||
413 | case FSID_DEV: | ||
414 | if (!old_valid_dev(exp_sb(exp)->s_dev)) | ||
415 | return 0; | ||
416 | /* FALL THROUGH */ | ||
417 | case FSID_MAJOR_MINOR: | ||
418 | case FSID_ENCODE_DEV: | ||
419 | return exp_sb(exp)->s_type->fs_flags & FS_REQUIRES_DEV; | ||
420 | case FSID_NUM: | ||
421 | return exp->ex_flags & NFSEXP_FSID; | ||
422 | case FSID_UUID8: | ||
423 | case FSID_UUID16: | ||
424 | if (!is_root_export(exp)) | ||
425 | return 0; | ||
426 | /* fall through */ | ||
427 | case FSID_UUID4_INUM: | ||
428 | case FSID_UUID16_INUM: | ||
429 | return exp->ex_uuid != NULL; | ||
430 | } | ||
431 | return 1; | ||
432 | } | ||
433 | |||
400 | __be32 | 434 | __be32 |
401 | fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, | 435 | fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, |
402 | struct svc_fh *ref_fh) | 436 | struct svc_fh *ref_fh) |
@@ -414,8 +448,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, | |||
414 | struct inode * inode = dentry->d_inode; | 448 | struct inode * inode = dentry->d_inode; |
415 | struct dentry *parent = dentry->d_parent; | 449 | struct dentry *parent = dentry->d_parent; |
416 | __u32 *datap; | 450 | __u32 *datap; |
417 | dev_t ex_dev = exp->ex_path.dentry->d_inode->i_sb->s_dev; | 451 | dev_t ex_dev = exp_sb(exp)->s_dev; |
418 | int root_export = (exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root); | ||
419 | 452 | ||
420 | dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", | 453 | dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", |
421 | MAJOR(ex_dev), MINOR(ex_dev), | 454 | MAJOR(ex_dev), MINOR(ex_dev), |
@@ -447,49 +480,24 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, | |||
447 | goto retry; | 480 | goto retry; |
448 | } | 481 | } |
449 | 482 | ||
450 | /* Need to check that this type works for this | 483 | /* |
451 | * export point. As the fsid -> filesystem mapping | 484 | * As the fsid -> filesystem mapping was guided by |
452 | * was guided by user-space, there is no guarantee | 485 | * user-space, there is no guarantee that the filesystem |
453 | * that the filesystem actually supports that fsid | 486 | * actually supports that fsid type. If it doesn't we |
454 | * type. If it doesn't we loop around again without | 487 | * loop around again without ref_fh set. |
455 | * ref_fh set. | ||
456 | */ | 488 | */ |
457 | switch(fsid_type) { | 489 | if (!fsid_type_ok_for_exp(fsid_type, exp)) |
458 | case FSID_DEV: | 490 | goto retry; |
459 | if (!old_valid_dev(ex_dev)) | ||
460 | goto retry; | ||
461 | /* FALL THROUGH */ | ||
462 | case FSID_MAJOR_MINOR: | ||
463 | case FSID_ENCODE_DEV: | ||
464 | if (!(exp->ex_path.dentry->d_inode->i_sb->s_type->fs_flags | ||
465 | & FS_REQUIRES_DEV)) | ||
466 | goto retry; | ||
467 | break; | ||
468 | case FSID_NUM: | ||
469 | if (! (exp->ex_flags & NFSEXP_FSID)) | ||
470 | goto retry; | ||
471 | break; | ||
472 | case FSID_UUID8: | ||
473 | case FSID_UUID16: | ||
474 | if (!root_export) | ||
475 | goto retry; | ||
476 | /* fall through */ | ||
477 | case FSID_UUID4_INUM: | ||
478 | case FSID_UUID16_INUM: | ||
479 | if (exp->ex_uuid == NULL) | ||
480 | goto retry; | ||
481 | break; | ||
482 | } | ||
483 | } else if (exp->ex_flags & NFSEXP_FSID) { | 491 | } else if (exp->ex_flags & NFSEXP_FSID) { |
484 | fsid_type = FSID_NUM; | 492 | fsid_type = FSID_NUM; |
485 | } else if (exp->ex_uuid) { | 493 | } else if (exp->ex_uuid) { |
486 | if (fhp->fh_maxsize >= 64) { | 494 | if (fhp->fh_maxsize >= 64) { |
487 | if (root_export) | 495 | if (is_root_export(exp)) |
488 | fsid_type = FSID_UUID16; | 496 | fsid_type = FSID_UUID16; |
489 | else | 497 | else |
490 | fsid_type = FSID_UUID16_INUM; | 498 | fsid_type = FSID_UUID16_INUM; |
491 | } else { | 499 | } else { |
492 | if (root_export) | 500 | if (is_root_export(exp)) |
493 | fsid_type = FSID_UUID8; | 501 | fsid_type = FSID_UUID8; |
494 | else | 502 | else |
495 | fsid_type = FSID_UUID4_INUM; | 503 | fsid_type = FSID_UUID4_INUM; |
@@ -639,8 +647,7 @@ enum fsid_source fsid_source(struct svc_fh *fhp) | |||
639 | case FSID_DEV: | 647 | case FSID_DEV: |
640 | case FSID_ENCODE_DEV: | 648 | case FSID_ENCODE_DEV: |
641 | case FSID_MAJOR_MINOR: | 649 | case FSID_MAJOR_MINOR: |
642 | if (fhp->fh_export->ex_path.dentry->d_inode->i_sb->s_type->fs_flags | 650 | if (exp_sb(fhp->fh_export)->s_type->fs_flags & FS_REQUIRES_DEV) |
643 | & FS_REQUIRES_DEV) | ||
644 | return FSIDSOURCE_DEV; | 651 | return FSIDSOURCE_DEV; |
645 | break; | 652 | break; |
646 | case FSID_NUM: | 653 | case FSID_NUM: |