aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2014-04-17 21:57:11 -0400
committerYan, Zheng <zheng.z.yan@intel.com>2014-06-05 21:29:53 -0400
commitd9df2783507943316b305e177e5b1c157200c76f (patch)
treea351bc67fc9ae0b3d367d232657cf28136888f66 /fs
parentf98a128a55ff85d0087de89f304f10bd75e792aa (diff)
ceph: pre-allocate ceph_cap struct for ceph_add_cap()
So that ceph_add_cap() can be used while i_ceph_lock is locked. This simplifies the code that handle cap import/export. Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ceph/caps.c81
-rw-r--r--fs/ceph/inode.c70
-rw-r--r--fs/ceph/super.h13
3 files changed, 85 insertions, 79 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 5f6d24ede794..73a42f504357 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -221,8 +221,8 @@ int ceph_unreserve_caps(struct ceph_mds_client *mdsc,
221 return 0; 221 return 0;
222} 222}
223 223
224static struct ceph_cap *get_cap(struct ceph_mds_client *mdsc, 224struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc,
225 struct ceph_cap_reservation *ctx) 225 struct ceph_cap_reservation *ctx)
226{ 226{
227 struct ceph_cap *cap = NULL; 227 struct ceph_cap *cap = NULL;
228 228
@@ -508,15 +508,14 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
508 * it is < 0. (This is so we can atomically add the cap and add an 508 * it is < 0. (This is so we can atomically add the cap and add an
509 * open file reference to it.) 509 * open file reference to it.)
510 */ 510 */
511int ceph_add_cap(struct inode *inode, 511void ceph_add_cap(struct inode *inode,
512 struct ceph_mds_session *session, u64 cap_id, 512 struct ceph_mds_session *session, u64 cap_id,
513 int fmode, unsigned issued, unsigned wanted, 513 int fmode, unsigned issued, unsigned wanted,
514 unsigned seq, unsigned mseq, u64 realmino, int flags, 514 unsigned seq, unsigned mseq, u64 realmino, int flags,
515 struct ceph_cap_reservation *caps_reservation) 515 struct ceph_cap **new_cap)
516{ 516{
517 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; 517 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
518 struct ceph_inode_info *ci = ceph_inode(inode); 518 struct ceph_inode_info *ci = ceph_inode(inode);
519 struct ceph_cap *new_cap = NULL;
520 struct ceph_cap *cap; 519 struct ceph_cap *cap;
521 int mds = session->s_mds; 520 int mds = session->s_mds;
522 int actual_wanted; 521 int actual_wanted;
@@ -531,20 +530,10 @@ int ceph_add_cap(struct inode *inode,
531 if (fmode >= 0) 530 if (fmode >= 0)
532 wanted |= ceph_caps_for_mode(fmode); 531 wanted |= ceph_caps_for_mode(fmode);
533 532
534retry:
535 spin_lock(&ci->i_ceph_lock);
536 cap = __get_cap_for_mds(ci, mds); 533 cap = __get_cap_for_mds(ci, mds);
537 if (!cap) { 534 if (!cap) {
538 if (new_cap) { 535 cap = *new_cap;
539 cap = new_cap; 536 *new_cap = NULL;
540 new_cap = NULL;
541 } else {
542 spin_unlock(&ci->i_ceph_lock);
543 new_cap = get_cap(mdsc, caps_reservation);
544 if (new_cap == NULL)
545 return -ENOMEM;
546 goto retry;
547 }
548 537
549 cap->issued = 0; 538 cap->issued = 0;
550 cap->implemented = 0; 539 cap->implemented = 0;
@@ -562,9 +551,6 @@ retry:
562 session->s_nr_caps++; 551 session->s_nr_caps++;
563 spin_unlock(&session->s_cap_lock); 552 spin_unlock(&session->s_cap_lock);
564 } else { 553 } else {
565 if (new_cap)
566 ceph_put_cap(mdsc, new_cap);
567
568 /* 554 /*
569 * auth mds of the inode changed. we received the cap export 555 * auth mds of the inode changed. we received the cap export
570 * message, but still haven't received the cap import message. 556 * message, but still haven't received the cap import message.
@@ -626,7 +612,6 @@ retry:
626 ci->i_auth_cap = cap; 612 ci->i_auth_cap = cap;
627 cap->mds_wanted = wanted; 613 cap->mds_wanted = wanted;
628 } 614 }
629 ci->i_cap_exporting_issued = 0;
630 } else { 615 } else {
631 WARN_ON(ci->i_auth_cap == cap); 616 WARN_ON(ci->i_auth_cap == cap);
632 } 617 }
@@ -648,9 +633,6 @@ retry:
648 633
649 if (fmode >= 0) 634 if (fmode >= 0)
650 __ceph_get_fmode(ci, fmode); 635 __ceph_get_fmode(ci, fmode);
651 spin_unlock(&ci->i_ceph_lock);
652 wake_up_all(&ci->i_cap_wq);
653 return 0;
654} 636}
655 637
656/* 638/*
@@ -685,7 +667,7 @@ static int __cap_is_valid(struct ceph_cap *cap)
685 */ 667 */
686int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented) 668int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented)
687{ 669{
688 int have = ci->i_snap_caps | ci->i_cap_exporting_issued; 670 int have = ci->i_snap_caps;
689 struct ceph_cap *cap; 671 struct ceph_cap *cap;
690 struct rb_node *p; 672 struct rb_node *p;
691 673
@@ -900,7 +882,7 @@ int __ceph_caps_mds_wanted(struct ceph_inode_info *ci)
900 */ 882 */
901static int __ceph_is_any_caps(struct ceph_inode_info *ci) 883static int __ceph_is_any_caps(struct ceph_inode_info *ci)
902{ 884{
903 return !RB_EMPTY_ROOT(&ci->i_caps) || ci->i_cap_exporting_issued; 885 return !RB_EMPTY_ROOT(&ci->i_caps);
904} 886}
905 887
906int ceph_is_any_caps(struct inode *inode) 888int ceph_is_any_caps(struct inode *inode)
@@ -2796,7 +2778,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
2796{ 2778{
2797 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; 2779 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
2798 struct ceph_mds_session *tsession = NULL; 2780 struct ceph_mds_session *tsession = NULL;
2799 struct ceph_cap *cap, *tcap; 2781 struct ceph_cap *cap, *tcap, *new_cap = NULL;
2800 struct ceph_inode_info *ci = ceph_inode(inode); 2782 struct ceph_inode_info *ci = ceph_inode(inode);
2801 u64 t_cap_id; 2783 u64 t_cap_id;
2802 unsigned mseq = le32_to_cpu(ex->migrate_seq); 2784 unsigned mseq = le32_to_cpu(ex->migrate_seq);
@@ -2858,15 +2840,14 @@ retry:
2858 } 2840 }
2859 __ceph_remove_cap(cap, false); 2841 __ceph_remove_cap(cap, false);
2860 goto out_unlock; 2842 goto out_unlock;
2861 } 2843 } else if (tsession) {
2862
2863 if (tsession) {
2864 int flag = (cap == ci->i_auth_cap) ? CEPH_CAP_FLAG_AUTH : 0;
2865 spin_unlock(&ci->i_ceph_lock);
2866 /* add placeholder for the export tagert */ 2844 /* add placeholder for the export tagert */
2845 int flag = (cap == ci->i_auth_cap) ? CEPH_CAP_FLAG_AUTH : 0;
2867 ceph_add_cap(inode, tsession, t_cap_id, -1, issued, 0, 2846 ceph_add_cap(inode, tsession, t_cap_id, -1, issued, 0,
2868 t_seq - 1, t_mseq, (u64)-1, flag, NULL); 2847 t_seq - 1, t_mseq, (u64)-1, flag, &new_cap);
2869 goto retry; 2848
2849 __ceph_remove_cap(cap, false);
2850 goto out_unlock;
2870 } 2851 }
2871 2852
2872 spin_unlock(&ci->i_ceph_lock); 2853 spin_unlock(&ci->i_ceph_lock);
@@ -2885,6 +2866,7 @@ retry:
2885 SINGLE_DEPTH_NESTING); 2866 SINGLE_DEPTH_NESTING);
2886 } 2867 }
2887 ceph_add_cap_releases(mdsc, tsession); 2868 ceph_add_cap_releases(mdsc, tsession);
2869 new_cap = ceph_get_cap(mdsc, NULL);
2888 } else { 2870 } else {
2889 WARN_ON(1); 2871 WARN_ON(1);
2890 tsession = NULL; 2872 tsession = NULL;
@@ -2899,6 +2881,8 @@ out_unlock:
2899 mutex_unlock(&tsession->s_mutex); 2881 mutex_unlock(&tsession->s_mutex);
2900 ceph_put_mds_session(tsession); 2882 ceph_put_mds_session(tsession);
2901 } 2883 }
2884 if (new_cap)
2885 ceph_put_cap(mdsc, new_cap);
2902} 2886}
2903 2887
2904/* 2888/*
@@ -2914,7 +2898,7 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
2914 void *snaptrace, int snaptrace_len) 2898 void *snaptrace, int snaptrace_len)
2915{ 2899{
2916 struct ceph_inode_info *ci = ceph_inode(inode); 2900 struct ceph_inode_info *ci = ceph_inode(inode);
2917 struct ceph_cap *cap; 2901 struct ceph_cap *cap, *new_cap = NULL;
2918 int mds = session->s_mds; 2902 int mds = session->s_mds;
2919 unsigned issued = le32_to_cpu(im->caps); 2903 unsigned issued = le32_to_cpu(im->caps);
2920 unsigned wanted = le32_to_cpu(im->wanted); 2904 unsigned wanted = le32_to_cpu(im->wanted);
@@ -2936,7 +2920,20 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
2936 dout("handle_cap_import inode %p ci %p mds%d mseq %d peer %d\n", 2920 dout("handle_cap_import inode %p ci %p mds%d mseq %d peer %d\n",
2937 inode, ci, mds, mseq, peer); 2921 inode, ci, mds, mseq, peer);
2938 2922
2923retry:
2939 spin_lock(&ci->i_ceph_lock); 2924 spin_lock(&ci->i_ceph_lock);
2925 cap = __get_cap_for_mds(ci, mds);
2926 if (!cap) {
2927 if (!new_cap) {
2928 spin_unlock(&ci->i_ceph_lock);
2929 new_cap = ceph_get_cap(mdsc, NULL);
2930 goto retry;
2931 }
2932 }
2933
2934 ceph_add_cap(inode, session, cap_id, -1, issued, wanted, seq, mseq,
2935 realmino, CEPH_CAP_FLAG_AUTH, &new_cap);
2936
2940 cap = peer >= 0 ? __get_cap_for_mds(ci, peer) : NULL; 2937 cap = peer >= 0 ? __get_cap_for_mds(ci, peer) : NULL;
2941 if (cap && cap->cap_id == p_cap_id) { 2938 if (cap && cap->cap_id == p_cap_id) {
2942 dout(" remove export cap %p mds%d flags %d\n", 2939 dout(" remove export cap %p mds%d flags %d\n",
@@ -2951,7 +2948,6 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
2951 cap->mseq, mds, le32_to_cpu(ph->seq), 2948 cap->mseq, mds, le32_to_cpu(ph->seq),
2952 le32_to_cpu(ph->mseq)); 2949 le32_to_cpu(ph->mseq));
2953 } 2950 }
2954 ci->i_cap_exporting_issued = cap->issued;
2955 __ceph_remove_cap(cap, (ph->flags & CEPH_CAP_FLAG_RELEASE)); 2951 __ceph_remove_cap(cap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
2956 } 2952 }
2957 2953
@@ -2960,16 +2956,17 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
2960 ci->i_requested_max_size = 0; 2956 ci->i_requested_max_size = 0;
2961 spin_unlock(&ci->i_ceph_lock); 2957 spin_unlock(&ci->i_ceph_lock);
2962 2958
2959 wake_up_all(&ci->i_cap_wq);
2960
2963 down_write(&mdsc->snap_rwsem); 2961 down_write(&mdsc->snap_rwsem);
2964 ceph_update_snap_trace(mdsc, snaptrace, snaptrace+snaptrace_len, 2962 ceph_update_snap_trace(mdsc, snaptrace, snaptrace+snaptrace_len,
2965 false); 2963 false);
2966 downgrade_write(&mdsc->snap_rwsem); 2964 downgrade_write(&mdsc->snap_rwsem);
2967 ceph_add_cap(inode, session, cap_id, -1,
2968 issued, wanted, seq, mseq, realmino, CEPH_CAP_FLAG_AUTH,
2969 NULL /* no caps context */);
2970 kick_flushing_inode_caps(mdsc, session, inode); 2965 kick_flushing_inode_caps(mdsc, session, inode);
2971 up_read(&mdsc->snap_rwsem); 2966 up_read(&mdsc->snap_rwsem);
2972 2967
2968 if (new_cap)
2969 ceph_put_cap(mdsc, new_cap);
2973} 2970}
2974 2971
2975/* 2972/*
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index f9e7399877d6..8ad50a30808e 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -341,7 +341,6 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
341 INIT_LIST_HEAD(&ci->i_cap_snaps); 341 INIT_LIST_HEAD(&ci->i_cap_snaps);
342 ci->i_head_snapc = NULL; 342 ci->i_head_snapc = NULL;
343 ci->i_snap_caps = 0; 343 ci->i_snap_caps = 0;
344 ci->i_cap_exporting_issued = 0;
345 344
346 for (i = 0; i < CEPH_FILE_MODE_NUM; i++) 345 for (i = 0; i < CEPH_FILE_MODE_NUM; i++)
347 ci->i_nr_by_mode[i] = 0; 346 ci->i_nr_by_mode[i] = 0;
@@ -407,7 +406,7 @@ void ceph_destroy_inode(struct inode *inode)
407 406
408 /* 407 /*
409 * we may still have a snap_realm reference if there are stray 408 * we may still have a snap_realm reference if there are stray
410 * caps in i_cap_exporting_issued or i_snap_caps. 409 * caps in i_snap_caps.
411 */ 410 */
412 if (ci->i_snap_realm) { 411 if (ci->i_snap_realm) {
413 struct ceph_mds_client *mdsc = 412 struct ceph_mds_client *mdsc =
@@ -582,6 +581,7 @@ static int fill_inode(struct inode *inode,
582 unsigned long ttl_from, int cap_fmode, 581 unsigned long ttl_from, int cap_fmode,
583 struct ceph_cap_reservation *caps_reservation) 582 struct ceph_cap_reservation *caps_reservation)
584{ 583{
584 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
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;
@@ -591,7 +591,9 @@ static int fill_inode(struct inode *inode,
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 struct ceph_cap *new_cap = NULL;
594 int err = 0; 595 int err = 0;
596 bool wake = false;
595 bool queue_trunc = false; 597 bool queue_trunc = false;
596 bool new_version = false; 598 bool new_version = false;
597 599
@@ -599,6 +601,10 @@ static int fill_inode(struct inode *inode,
599 inode, ceph_vinop(inode), le64_to_cpu(info->version), 601 inode, ceph_vinop(inode), le64_to_cpu(info->version),
600 ci->i_version); 602 ci->i_version);
601 603
604 /* prealloc new cap struct */
605 if (info->cap.caps && ceph_snap(inode) == CEPH_NOSNAP)
606 new_cap = ceph_get_cap(mdsc, caps_reservation);
607
602 /* 608 /*
603 * prealloc xattr data, if it looks like we'll need it. only 609 * prealloc xattr data, if it looks like we'll need it. only
604 * if len > 4 (meaning there are actually xattrs; the first 4 610 * if len > 4 (meaning there are actually xattrs; the first 4
@@ -762,8 +768,37 @@ static int fill_inode(struct inode *inode,
762 dout(" marking %p complete (empty)\n", inode); 768 dout(" marking %p complete (empty)\n", inode);
763 __ceph_dir_set_complete(ci, atomic_read(&ci->i_release_count)); 769 __ceph_dir_set_complete(ci, atomic_read(&ci->i_release_count));
764 } 770 }
771
772 /* were we issued a capability? */
773 if (info->cap.caps) {
774 if (ceph_snap(inode) == CEPH_NOSNAP) {
775 ceph_add_cap(inode, session,
776 le64_to_cpu(info->cap.cap_id),
777 cap_fmode,
778 le32_to_cpu(info->cap.caps),
779 le32_to_cpu(info->cap.wanted),
780 le32_to_cpu(info->cap.seq),
781 le32_to_cpu(info->cap.mseq),
782 le64_to_cpu(info->cap.realm),
783 info->cap.flags, &new_cap);
784 wake = true;
785 } else {
786 dout(" %p got snap_caps %s\n", inode,
787 ceph_cap_string(le32_to_cpu(info->cap.caps)));
788 ci->i_snap_caps |= le32_to_cpu(info->cap.caps);
789 if (cap_fmode >= 0)
790 __ceph_get_fmode(ci, cap_fmode);
791 }
792 } else if (cap_fmode >= 0) {
793 pr_warning("mds issued no caps on %llx.%llx\n",
794 ceph_vinop(inode));
795 __ceph_get_fmode(ci, cap_fmode);
796 }
765 spin_unlock(&ci->i_ceph_lock); 797 spin_unlock(&ci->i_ceph_lock);
766 798
799 if (wake)
800 wake_up_all(&ci->i_cap_wq);
801
767 /* queue truncate if we saw i_size decrease */ 802 /* queue truncate if we saw i_size decrease */
768 if (queue_trunc) 803 if (queue_trunc)
769 ceph_queue_vmtruncate(inode); 804 ceph_queue_vmtruncate(inode);
@@ -806,41 +841,14 @@ static int fill_inode(struct inode *inode,
806 } 841 }
807 mutex_unlock(&ci->i_fragtree_mutex); 842 mutex_unlock(&ci->i_fragtree_mutex);
808 843
809 /* were we issued a capability? */
810 if (info->cap.caps) {
811 if (ceph_snap(inode) == CEPH_NOSNAP) {
812 ceph_add_cap(inode, session,
813 le64_to_cpu(info->cap.cap_id),
814 cap_fmode,
815 le32_to_cpu(info->cap.caps),
816 le32_to_cpu(info->cap.wanted),
817 le32_to_cpu(info->cap.seq),
818 le32_to_cpu(info->cap.mseq),
819 le64_to_cpu(info->cap.realm),
820 info->cap.flags,
821 caps_reservation);
822 } else {
823 spin_lock(&ci->i_ceph_lock);
824 dout(" %p got snap_caps %s\n", inode,
825 ceph_cap_string(le32_to_cpu(info->cap.caps)));
826 ci->i_snap_caps |= le32_to_cpu(info->cap.caps);
827 if (cap_fmode >= 0)
828 __ceph_get_fmode(ci, cap_fmode);
829 spin_unlock(&ci->i_ceph_lock);
830 }
831 } else if (cap_fmode >= 0) {
832 pr_warning("mds issued no caps on %llx.%llx\n",
833 ceph_vinop(inode));
834 __ceph_get_fmode(ci, cap_fmode);
835 }
836
837 /* update delegation info? */ 844 /* update delegation info? */
838 if (dirinfo) 845 if (dirinfo)
839 ceph_fill_dirfrag(inode, dirinfo); 846 ceph_fill_dirfrag(inode, dirinfo);
840 847
841 err = 0; 848 err = 0;
842
843out: 849out:
850 if (new_cap)
851 ceph_put_cap(mdsc, new_cap);
844 if (xattr_blob) 852 if (xattr_blob)
845 ceph_buffer_put(xattr_blob); 853 ceph_buffer_put(xattr_blob);
846 return err; 854 return err;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index ead05cc1f447..12b20744e386 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -292,7 +292,6 @@ struct ceph_inode_info {
292 struct ceph_snap_context *i_head_snapc; /* set if wr_buffer_head > 0 or 292 struct ceph_snap_context *i_head_snapc; /* set if wr_buffer_head > 0 or
293 dirty|flushing caps */ 293 dirty|flushing caps */
294 unsigned i_snap_caps; /* cap bits for snapped files */ 294 unsigned i_snap_caps; /* cap bits for snapped files */
295 unsigned i_cap_exporting_issued;
296 295
297 int i_nr_by_mode[CEPH_FILE_MODE_NUM]; /* open file counts */ 296 int i_nr_by_mode[CEPH_FILE_MODE_NUM]; /* open file counts */
298 297
@@ -775,11 +774,13 @@ static inline void ceph_forget_all_cached_acls(struct inode *inode)
775extern const char *ceph_cap_string(int c); 774extern const char *ceph_cap_string(int c);
776extern void ceph_handle_caps(struct ceph_mds_session *session, 775extern void ceph_handle_caps(struct ceph_mds_session *session,
777 struct ceph_msg *msg); 776 struct ceph_msg *msg);
778extern int ceph_add_cap(struct inode *inode, 777extern struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc,
779 struct ceph_mds_session *session, u64 cap_id, 778 struct ceph_cap_reservation *ctx);
780 int fmode, unsigned issued, unsigned wanted, 779extern void ceph_add_cap(struct inode *inode,
781 unsigned cap, unsigned seq, u64 realmino, int flags, 780 struct ceph_mds_session *session, u64 cap_id,
782 struct ceph_cap_reservation *caps_reservation); 781 int fmode, unsigned issued, unsigned wanted,
782 unsigned cap, unsigned seq, u64 realmino, int flags,
783 struct ceph_cap **new_cap);
783extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release); 784extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
784extern void ceph_put_cap(struct ceph_mds_client *mdsc, 785extern void ceph_put_cap(struct ceph_mds_client *mdsc,
785 struct ceph_cap *cap); 786 struct ceph_cap *cap);