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/inode.c | |
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/inode.c')
-rw-r--r-- | fs/ceph/inode.c | 70 |
1 files changed, 39 insertions, 31 deletions
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 */ |