diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-04-16 20:55:50 -0400 |
---|---|---|
committer | Yan, Zheng <zheng.z.yan@intel.com> | 2014-06-05 21:29:52 -0400 |
commit | f98a128a55ff85d0087de89f304f10bd75e792aa (patch) | |
tree | bdaa64075f36354d7f221a8b7d93fbc4bdb8f322 /fs/ceph | |
parent | 461f758ac0bad40fe8e0959f415dae38efa16c12 (diff) |
ceph: update inode fields according to issued caps
Cap message and request reply from non-auth MDS may carry stale
information (corresponding locks are in LOCK states) even they
have the newest inode version. So client should update inode fields
according to issued caps.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/caps.c | 58 | ||||
-rw-r--r-- | fs/ceph/inode.c | 70 |
2 files changed, 71 insertions, 57 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index de39a03f5b71..5f6d24ede794 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -2476,7 +2476,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2476 | 2476 | ||
2477 | __check_cap_issue(ci, cap, newcaps); | 2477 | __check_cap_issue(ci, cap, newcaps); |
2478 | 2478 | ||
2479 | if ((issued & CEPH_CAP_AUTH_EXCL) == 0) { | 2479 | if ((newcaps & CEPH_CAP_AUTH_SHARED) && |
2480 | (issued & CEPH_CAP_AUTH_EXCL) == 0) { | ||
2480 | inode->i_mode = le32_to_cpu(grant->mode); | 2481 | inode->i_mode = le32_to_cpu(grant->mode); |
2481 | inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid)); | 2482 | inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid)); |
2482 | inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid)); | 2483 | inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid)); |
@@ -2485,7 +2486,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2485 | from_kgid(&init_user_ns, inode->i_gid)); | 2486 | from_kgid(&init_user_ns, inode->i_gid)); |
2486 | } | 2487 | } |
2487 | 2488 | ||
2488 | if ((issued & CEPH_CAP_LINK_EXCL) == 0) { | 2489 | if ((newcaps & CEPH_CAP_AUTH_SHARED) && |
2490 | (issued & CEPH_CAP_LINK_EXCL) == 0) { | ||
2489 | set_nlink(inode, le32_to_cpu(grant->nlink)); | 2491 | set_nlink(inode, le32_to_cpu(grant->nlink)); |
2490 | if (inode->i_nlink == 0 && | 2492 | if (inode->i_nlink == 0 && |
2491 | (newcaps & (CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL))) | 2493 | (newcaps & (CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL))) |
@@ -2512,31 +2514,35 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2512 | if ((issued & CEPH_CAP_FILE_CACHE) && ci->i_rdcache_gen > 1) | 2514 | if ((issued & CEPH_CAP_FILE_CACHE) && ci->i_rdcache_gen > 1) |
2513 | queue_revalidate = 1; | 2515 | queue_revalidate = 1; |
2514 | 2516 | ||
2515 | /* size/ctime/mtime/atime? */ | 2517 | if (newcaps & CEPH_CAP_ANY_RD) { |
2516 | queue_trunc = ceph_fill_file_size(inode, issued, | 2518 | /* ctime/mtime/atime? */ |
2517 | le32_to_cpu(grant->truncate_seq), | 2519 | ceph_decode_timespec(&mtime, &grant->mtime); |
2518 | le64_to_cpu(grant->truncate_size), | 2520 | ceph_decode_timespec(&atime, &grant->atime); |
2519 | size); | 2521 | ceph_decode_timespec(&ctime, &grant->ctime); |
2520 | ceph_decode_timespec(&mtime, &grant->mtime); | 2522 | ceph_fill_file_time(inode, issued, |
2521 | ceph_decode_timespec(&atime, &grant->atime); | 2523 | le32_to_cpu(grant->time_warp_seq), |
2522 | ceph_decode_timespec(&ctime, &grant->ctime); | 2524 | &ctime, &mtime, &atime); |
2523 | ceph_fill_file_time(inode, issued, | 2525 | } |
2524 | le32_to_cpu(grant->time_warp_seq), &ctime, &mtime, | 2526 | |
2525 | &atime); | 2527 | if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) { |
2526 | 2528 | /* file layout may have changed */ | |
2527 | 2529 | ci->i_layout = grant->layout; | |
2528 | /* file layout may have changed */ | 2530 | /* size/truncate_seq? */ |
2529 | ci->i_layout = grant->layout; | 2531 | queue_trunc = ceph_fill_file_size(inode, issued, |
2530 | 2532 | le32_to_cpu(grant->truncate_seq), | |
2531 | /* max size increase? */ | 2533 | le64_to_cpu(grant->truncate_size), |
2532 | if (ci->i_auth_cap == cap && max_size != ci->i_max_size) { | 2534 | size); |
2533 | dout("max_size %lld -> %llu\n", ci->i_max_size, max_size); | 2535 | /* max size increase? */ |
2534 | ci->i_max_size = max_size; | 2536 | if (ci->i_auth_cap == cap && max_size != ci->i_max_size) { |
2535 | if (max_size >= ci->i_wanted_max_size) { | 2537 | dout("max_size %lld -> %llu\n", |
2536 | ci->i_wanted_max_size = 0; /* reset */ | 2538 | ci->i_max_size, max_size); |
2537 | ci->i_requested_max_size = 0; | 2539 | ci->i_max_size = max_size; |
2540 | if (max_size >= ci->i_wanted_max_size) { | ||
2541 | ci->i_wanted_max_size = 0; /* reset */ | ||
2542 | ci->i_requested_max_size = 0; | ||
2543 | } | ||
2544 | wake = 1; | ||
2538 | } | 2545 | } |
2539 | wake = 1; | ||
2540 | } | 2546 | } |
2541 | 2547 | ||
2542 | /* check cap bits */ | 2548 | /* check cap bits */ |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 233c6f96910a..f9e7399877d6 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -585,14 +585,15 @@ static int fill_inode(struct inode *inode, | |||
585 | struct ceph_mds_reply_inode *info = iinfo->in; | 585 | struct ceph_mds_reply_inode *info = iinfo->in; |
586 | struct ceph_inode_info *ci = ceph_inode(inode); | 586 | struct ceph_inode_info *ci = ceph_inode(inode); |
587 | int i; | 587 | int i; |
588 | int issued = 0, implemented; | 588 | int issued = 0, implemented, new_issued; |
589 | struct timespec mtime, atime, ctime; | 589 | struct timespec mtime, atime, ctime; |
590 | u32 nsplits; | 590 | u32 nsplits; |
591 | struct ceph_inode_frag *frag; | 591 | struct ceph_inode_frag *frag; |
592 | struct rb_node *rb_node; | 592 | struct rb_node *rb_node; |
593 | struct ceph_buffer *xattr_blob = NULL; | 593 | struct ceph_buffer *xattr_blob = NULL; |
594 | int err = 0; | 594 | int err = 0; |
595 | int queue_trunc = 0; | 595 | bool queue_trunc = false; |
596 | bool new_version = false; | ||
596 | 597 | ||
597 | dout("fill_inode %p ino %llx.%llx v %llu had %llu\n", | 598 | dout("fill_inode %p ino %llx.%llx v %llu had %llu\n", |
598 | inode, ceph_vinop(inode), le64_to_cpu(info->version), | 599 | inode, ceph_vinop(inode), le64_to_cpu(info->version), |
@@ -623,19 +624,23 @@ static int fill_inode(struct inode *inode, | |||
623 | * 3 2 skip | 624 | * 3 2 skip |
624 | * 3 3 update | 625 | * 3 3 update |
625 | */ | 626 | */ |
626 | if (le64_to_cpu(info->version) > 0 && | 627 | if (ci->i_version == 0 || |
627 | (ci->i_version & ~1) >= le64_to_cpu(info->version)) | 628 | ((info->cap.flags & CEPH_CAP_FLAG_AUTH) && |
628 | goto no_change; | 629 | le64_to_cpu(info->version) > (ci->i_version & ~1))) |
629 | 630 | new_version = true; | |
631 | |||
630 | issued = __ceph_caps_issued(ci, &implemented); | 632 | issued = __ceph_caps_issued(ci, &implemented); |
631 | issued |= implemented | __ceph_caps_dirty(ci); | 633 | issued |= implemented | __ceph_caps_dirty(ci); |
634 | new_issued = ~issued & le32_to_cpu(info->cap.caps); | ||
632 | 635 | ||
633 | /* update inode */ | 636 | /* update inode */ |
634 | ci->i_version = le64_to_cpu(info->version); | 637 | ci->i_version = le64_to_cpu(info->version); |
635 | inode->i_version++; | 638 | inode->i_version++; |
636 | inode->i_rdev = le32_to_cpu(info->rdev); | 639 | inode->i_rdev = le32_to_cpu(info->rdev); |
640 | inode->i_blkbits = fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1; | ||
637 | 641 | ||
638 | if ((issued & CEPH_CAP_AUTH_EXCL) == 0) { | 642 | if ((new_version || (new_issued & CEPH_CAP_AUTH_SHARED)) && |
643 | (issued & CEPH_CAP_AUTH_EXCL) == 0) { | ||
639 | inode->i_mode = le32_to_cpu(info->mode); | 644 | inode->i_mode = le32_to_cpu(info->mode); |
640 | inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(info->uid)); | 645 | inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(info->uid)); |
641 | inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(info->gid)); | 646 | inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(info->gid)); |
@@ -644,23 +649,35 @@ static int fill_inode(struct inode *inode, | |||
644 | from_kgid(&init_user_ns, inode->i_gid)); | 649 | from_kgid(&init_user_ns, inode->i_gid)); |
645 | } | 650 | } |
646 | 651 | ||
647 | if ((issued & CEPH_CAP_LINK_EXCL) == 0) | 652 | if ((new_version || (new_issued & CEPH_CAP_LINK_SHARED)) && |
653 | (issued & CEPH_CAP_LINK_EXCL) == 0) | ||
648 | set_nlink(inode, le32_to_cpu(info->nlink)); | 654 | set_nlink(inode, le32_to_cpu(info->nlink)); |
649 | 655 | ||
650 | /* be careful with mtime, atime, size */ | 656 | if (new_version || (new_issued & CEPH_CAP_ANY_RD)) { |
651 | ceph_decode_timespec(&atime, &info->atime); | 657 | /* be careful with mtime, atime, size */ |
652 | ceph_decode_timespec(&mtime, &info->mtime); | 658 | ceph_decode_timespec(&atime, &info->atime); |
653 | ceph_decode_timespec(&ctime, &info->ctime); | 659 | ceph_decode_timespec(&mtime, &info->mtime); |
654 | queue_trunc = ceph_fill_file_size(inode, issued, | 660 | ceph_decode_timespec(&ctime, &info->ctime); |
655 | le32_to_cpu(info->truncate_seq), | 661 | ceph_fill_file_time(inode, issued, |
656 | le64_to_cpu(info->truncate_size), | 662 | le32_to_cpu(info->time_warp_seq), |
657 | le64_to_cpu(info->size)); | 663 | &ctime, &mtime, &atime); |
658 | ceph_fill_file_time(inode, issued, | 664 | } |
659 | le32_to_cpu(info->time_warp_seq), | 665 | |
660 | &ctime, &mtime, &atime); | 666 | if (new_version || |
661 | 667 | (new_issued & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR))) { | |
662 | ci->i_layout = info->layout; | 668 | ci->i_layout = info->layout; |
663 | inode->i_blkbits = fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1; | 669 | queue_trunc = ceph_fill_file_size(inode, issued, |
670 | le32_to_cpu(info->truncate_seq), | ||
671 | le64_to_cpu(info->truncate_size), | ||
672 | le64_to_cpu(info->size)); | ||
673 | /* only update max_size on auth cap */ | ||
674 | if ((info->cap.flags & CEPH_CAP_FLAG_AUTH) && | ||
675 | ci->i_max_size != le64_to_cpu(info->max_size)) { | ||
676 | dout("max_size %lld -> %llu\n", ci->i_max_size, | ||
677 | le64_to_cpu(info->max_size)); | ||
678 | ci->i_max_size = le64_to_cpu(info->max_size); | ||
679 | } | ||
680 | } | ||
664 | 681 | ||
665 | /* xattrs */ | 682 | /* xattrs */ |
666 | /* note that if i_xattrs.len <= 4, i_xattrs.data will still be NULL. */ | 683 | /* note that if i_xattrs.len <= 4, i_xattrs.data will still be NULL. */ |
@@ -745,15 +762,6 @@ static int fill_inode(struct inode *inode, | |||
745 | dout(" marking %p complete (empty)\n", inode); | 762 | dout(" marking %p complete (empty)\n", inode); |
746 | __ceph_dir_set_complete(ci, atomic_read(&ci->i_release_count)); | 763 | __ceph_dir_set_complete(ci, atomic_read(&ci->i_release_count)); |
747 | } | 764 | } |
748 | no_change: | ||
749 | /* only update max_size on auth cap */ | ||
750 | if ((info->cap.flags & CEPH_CAP_FLAG_AUTH) && | ||
751 | ci->i_max_size != le64_to_cpu(info->max_size)) { | ||
752 | dout("max_size %lld -> %llu\n", ci->i_max_size, | ||
753 | le64_to_cpu(info->max_size)); | ||
754 | ci->i_max_size = le64_to_cpu(info->max_size); | ||
755 | } | ||
756 | |||
757 | spin_unlock(&ci->i_ceph_lock); | 765 | spin_unlock(&ci->i_ceph_lock); |
758 | 766 | ||
759 | /* queue truncate if we saw i_size decrease */ | 767 | /* queue truncate if we saw i_size decrease */ |