diff options
| -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: |
