diff options
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/caps.c | 24 | ||||
-rw-r--r-- | fs/ceph/mds_client.c | 9 | ||||
-rw-r--r-- | fs/ceph/snap.c | 54 | ||||
-rw-r--r-- | fs/ceph/super.h | 3 |
4 files changed, 63 insertions, 27 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index d0618e8412fd..8ed1192606d9 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -577,7 +577,6 @@ void ceph_add_cap(struct inode *inode, | |||
577 | struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc, | 577 | struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc, |
578 | realmino); | 578 | realmino); |
579 | if (realm) { | 579 | if (realm) { |
580 | ceph_get_snap_realm(mdsc, realm); | ||
581 | spin_lock(&realm->inodes_with_caps_lock); | 580 | spin_lock(&realm->inodes_with_caps_lock); |
582 | ci->i_snap_realm = realm; | 581 | ci->i_snap_realm = realm; |
583 | list_add(&ci->i_snap_realm_item, | 582 | list_add(&ci->i_snap_realm_item, |
@@ -2447,13 +2446,13 @@ static void invalidate_aliases(struct inode *inode) | |||
2447 | */ | 2446 | */ |
2448 | static void handle_cap_grant(struct ceph_mds_client *mdsc, | 2447 | static void handle_cap_grant(struct ceph_mds_client *mdsc, |
2449 | struct inode *inode, struct ceph_mds_caps *grant, | 2448 | struct inode *inode, struct ceph_mds_caps *grant, |
2450 | void *snaptrace, int snaptrace_len, | ||
2451 | u64 inline_version, | 2449 | u64 inline_version, |
2452 | void *inline_data, int inline_len, | 2450 | void *inline_data, int inline_len, |
2453 | struct ceph_buffer *xattr_buf, | 2451 | struct ceph_buffer *xattr_buf, |
2454 | struct ceph_mds_session *session, | 2452 | struct ceph_mds_session *session, |
2455 | struct ceph_cap *cap, int issued) | 2453 | struct ceph_cap *cap, int issued) |
2456 | __releases(ci->i_ceph_lock) | 2454 | __releases(ci->i_ceph_lock) |
2455 | __releases(mdsc->snap_rwsem) | ||
2457 | { | 2456 | { |
2458 | struct ceph_inode_info *ci = ceph_inode(inode); | 2457 | struct ceph_inode_info *ci = ceph_inode(inode); |
2459 | int mds = session->s_mds; | 2458 | int mds = session->s_mds; |
@@ -2654,10 +2653,6 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc, | |||
2654 | spin_unlock(&ci->i_ceph_lock); | 2653 | spin_unlock(&ci->i_ceph_lock); |
2655 | 2654 | ||
2656 | if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) { | 2655 | if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) { |
2657 | down_write(&mdsc->snap_rwsem); | ||
2658 | ceph_update_snap_trace(mdsc, snaptrace, | ||
2659 | snaptrace + snaptrace_len, false); | ||
2660 | downgrade_write(&mdsc->snap_rwsem); | ||
2661 | kick_flushing_inode_caps(mdsc, session, inode); | 2656 | kick_flushing_inode_caps(mdsc, session, inode); |
2662 | up_read(&mdsc->snap_rwsem); | 2657 | up_read(&mdsc->snap_rwsem); |
2663 | if (newcaps & ~issued) | 2658 | if (newcaps & ~issued) |
@@ -3067,6 +3062,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3067 | struct ceph_cap *cap; | 3062 | struct ceph_cap *cap; |
3068 | struct ceph_mds_caps *h; | 3063 | struct ceph_mds_caps *h; |
3069 | struct ceph_mds_cap_peer *peer = NULL; | 3064 | struct ceph_mds_cap_peer *peer = NULL; |
3065 | struct ceph_snap_realm *realm; | ||
3070 | int mds = session->s_mds; | 3066 | int mds = session->s_mds; |
3071 | int op, issued; | 3067 | int op, issued; |
3072 | u32 seq, mseq; | 3068 | u32 seq, mseq; |
@@ -3168,11 +3164,23 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3168 | goto done_unlocked; | 3164 | goto done_unlocked; |
3169 | 3165 | ||
3170 | case CEPH_CAP_OP_IMPORT: | 3166 | case CEPH_CAP_OP_IMPORT: |
3167 | realm = NULL; | ||
3168 | if (snaptrace_len) { | ||
3169 | down_write(&mdsc->snap_rwsem); | ||
3170 | ceph_update_snap_trace(mdsc, snaptrace, | ||
3171 | snaptrace + snaptrace_len, | ||
3172 | false, &realm); | ||
3173 | downgrade_write(&mdsc->snap_rwsem); | ||
3174 | } else { | ||
3175 | down_read(&mdsc->snap_rwsem); | ||
3176 | } | ||
3171 | handle_cap_import(mdsc, inode, h, peer, session, | 3177 | handle_cap_import(mdsc, inode, h, peer, session, |
3172 | &cap, &issued); | 3178 | &cap, &issued); |
3173 | handle_cap_grant(mdsc, inode, h, snaptrace, snaptrace_len, | 3179 | handle_cap_grant(mdsc, inode, h, |
3174 | inline_version, inline_data, inline_len, | 3180 | inline_version, inline_data, inline_len, |
3175 | msg->middle, session, cap, issued); | 3181 | msg->middle, session, cap, issued); |
3182 | if (realm) | ||
3183 | ceph_put_snap_realm(mdsc, realm); | ||
3176 | goto done_unlocked; | 3184 | goto done_unlocked; |
3177 | } | 3185 | } |
3178 | 3186 | ||
@@ -3192,7 +3200,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3192 | case CEPH_CAP_OP_GRANT: | 3200 | case CEPH_CAP_OP_GRANT: |
3193 | __ceph_caps_issued(ci, &issued); | 3201 | __ceph_caps_issued(ci, &issued); |
3194 | issued |= __ceph_caps_dirty(ci); | 3202 | issued |= __ceph_caps_dirty(ci); |
3195 | handle_cap_grant(mdsc, inode, h, NULL, 0, | 3203 | handle_cap_grant(mdsc, inode, h, |
3196 | inline_version, inline_data, inline_len, | 3204 | inline_version, inline_data, inline_len, |
3197 | msg->middle, session, cap, issued); | 3205 | msg->middle, session, cap, issued); |
3198 | goto done_unlocked; | 3206 | goto done_unlocked; |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index c6c33b411a2f..85c67ae03e46 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -2286,6 +2286,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2286 | struct ceph_mds_request *req; | 2286 | struct ceph_mds_request *req; |
2287 | struct ceph_mds_reply_head *head = msg->front.iov_base; | 2287 | struct ceph_mds_reply_head *head = msg->front.iov_base; |
2288 | struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */ | 2288 | struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */ |
2289 | struct ceph_snap_realm *realm; | ||
2289 | u64 tid; | 2290 | u64 tid; |
2290 | int err, result; | 2291 | int err, result; |
2291 | int mds = session->s_mds; | 2292 | int mds = session->s_mds; |
@@ -2401,11 +2402,13 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2401 | } | 2402 | } |
2402 | 2403 | ||
2403 | /* snap trace */ | 2404 | /* snap trace */ |
2405 | realm = NULL; | ||
2404 | if (rinfo->snapblob_len) { | 2406 | if (rinfo->snapblob_len) { |
2405 | down_write(&mdsc->snap_rwsem); | 2407 | down_write(&mdsc->snap_rwsem); |
2406 | ceph_update_snap_trace(mdsc, rinfo->snapblob, | 2408 | ceph_update_snap_trace(mdsc, rinfo->snapblob, |
2407 | rinfo->snapblob + rinfo->snapblob_len, | 2409 | rinfo->snapblob + rinfo->snapblob_len, |
2408 | le32_to_cpu(head->op) == CEPH_MDS_OP_RMSNAP); | 2410 | le32_to_cpu(head->op) == CEPH_MDS_OP_RMSNAP, |
2411 | &realm); | ||
2409 | downgrade_write(&mdsc->snap_rwsem); | 2412 | downgrade_write(&mdsc->snap_rwsem); |
2410 | } else { | 2413 | } else { |
2411 | down_read(&mdsc->snap_rwsem); | 2414 | down_read(&mdsc->snap_rwsem); |
@@ -2423,6 +2426,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2423 | mutex_unlock(&req->r_fill_mutex); | 2426 | mutex_unlock(&req->r_fill_mutex); |
2424 | 2427 | ||
2425 | up_read(&mdsc->snap_rwsem); | 2428 | up_read(&mdsc->snap_rwsem); |
2429 | if (realm) | ||
2430 | ceph_put_snap_realm(mdsc, realm); | ||
2426 | out_err: | 2431 | out_err: |
2427 | mutex_lock(&mdsc->mutex); | 2432 | mutex_lock(&mdsc->mutex); |
2428 | if (!req->r_aborted) { | 2433 | if (!req->r_aborted) { |
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index ce35fbd4ba5d..a97e39f09ba6 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
@@ -70,13 +70,11 @@ void ceph_get_snap_realm(struct ceph_mds_client *mdsc, | |||
70 | * safe. we do need to protect against concurrent empty list | 70 | * safe. we do need to protect against concurrent empty list |
71 | * additions, however. | 71 | * additions, however. |
72 | */ | 72 | */ |
73 | if (atomic_read(&realm->nref) == 0) { | 73 | if (atomic_inc_return(&realm->nref) == 1) { |
74 | spin_lock(&mdsc->snap_empty_lock); | 74 | spin_lock(&mdsc->snap_empty_lock); |
75 | list_del_init(&realm->empty_item); | 75 | list_del_init(&realm->empty_item); |
76 | spin_unlock(&mdsc->snap_empty_lock); | 76 | spin_unlock(&mdsc->snap_empty_lock); |
77 | } | 77 | } |
78 | |||
79 | atomic_inc(&realm->nref); | ||
80 | } | 78 | } |
81 | 79 | ||
82 | static void __insert_snap_realm(struct rb_root *root, | 80 | static void __insert_snap_realm(struct rb_root *root, |
@@ -116,7 +114,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm( | |||
116 | if (!realm) | 114 | if (!realm) |
117 | return ERR_PTR(-ENOMEM); | 115 | return ERR_PTR(-ENOMEM); |
118 | 116 | ||
119 | atomic_set(&realm->nref, 0); /* tree does not take a ref */ | 117 | atomic_set(&realm->nref, 1); /* for caller */ |
120 | realm->ino = ino; | 118 | realm->ino = ino; |
121 | INIT_LIST_HEAD(&realm->children); | 119 | INIT_LIST_HEAD(&realm->children); |
122 | INIT_LIST_HEAD(&realm->child_item); | 120 | INIT_LIST_HEAD(&realm->child_item); |
@@ -134,8 +132,8 @@ static struct ceph_snap_realm *ceph_create_snap_realm( | |||
134 | * | 132 | * |
135 | * caller must hold snap_rwsem for write. | 133 | * caller must hold snap_rwsem for write. |
136 | */ | 134 | */ |
137 | struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc, | 135 | static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc, |
138 | u64 ino) | 136 | u64 ino) |
139 | { | 137 | { |
140 | struct rb_node *n = mdsc->snap_realms.rb_node; | 138 | struct rb_node *n = mdsc->snap_realms.rb_node; |
141 | struct ceph_snap_realm *r; | 139 | struct ceph_snap_realm *r; |
@@ -154,6 +152,16 @@ struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc, | |||
154 | return NULL; | 152 | return NULL; |
155 | } | 153 | } |
156 | 154 | ||
155 | struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc, | ||
156 | u64 ino) | ||
157 | { | ||
158 | struct ceph_snap_realm *r; | ||
159 | r = __lookup_snap_realm(mdsc, ino); | ||
160 | if (r) | ||
161 | ceph_get_snap_realm(mdsc, r); | ||
162 | return r; | ||
163 | } | ||
164 | |||
157 | static void __put_snap_realm(struct ceph_mds_client *mdsc, | 165 | static void __put_snap_realm(struct ceph_mds_client *mdsc, |
158 | struct ceph_snap_realm *realm); | 166 | struct ceph_snap_realm *realm); |
159 | 167 | ||
@@ -273,7 +281,6 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, | |||
273 | } | 281 | } |
274 | realm->parent_ino = parentino; | 282 | realm->parent_ino = parentino; |
275 | realm->parent = parent; | 283 | realm->parent = parent; |
276 | ceph_get_snap_realm(mdsc, parent); | ||
277 | list_add(&realm->child_item, &parent->children); | 284 | list_add(&realm->child_item, &parent->children); |
278 | return 1; | 285 | return 1; |
279 | } | 286 | } |
@@ -631,12 +638,14 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm) | |||
631 | * Caller must hold snap_rwsem for write. | 638 | * Caller must hold snap_rwsem for write. |
632 | */ | 639 | */ |
633 | int ceph_update_snap_trace(struct ceph_mds_client *mdsc, | 640 | int ceph_update_snap_trace(struct ceph_mds_client *mdsc, |
634 | void *p, void *e, bool deletion) | 641 | void *p, void *e, bool deletion, |
642 | struct ceph_snap_realm **realm_ret) | ||
635 | { | 643 | { |
636 | struct ceph_mds_snap_realm *ri; /* encoded */ | 644 | struct ceph_mds_snap_realm *ri; /* encoded */ |
637 | __le64 *snaps; /* encoded */ | 645 | __le64 *snaps; /* encoded */ |
638 | __le64 *prior_parent_snaps; /* encoded */ | 646 | __le64 *prior_parent_snaps; /* encoded */ |
639 | struct ceph_snap_realm *realm; | 647 | struct ceph_snap_realm *realm = NULL; |
648 | struct ceph_snap_realm *first_realm = NULL; | ||
640 | int invalidate = 0; | 649 | int invalidate = 0; |
641 | int err = -ENOMEM; | 650 | int err = -ENOMEM; |
642 | LIST_HEAD(dirty_realms); | 651 | LIST_HEAD(dirty_realms); |
@@ -704,13 +713,18 @@ more: | |||
704 | dout("done with %llx %p, invalidated=%d, %p %p\n", realm->ino, | 713 | dout("done with %llx %p, invalidated=%d, %p %p\n", realm->ino, |
705 | realm, invalidate, p, e); | 714 | realm, invalidate, p, e); |
706 | 715 | ||
707 | if (p < e) | ||
708 | goto more; | ||
709 | |||
710 | /* invalidate when we reach the _end_ (root) of the trace */ | 716 | /* invalidate when we reach the _end_ (root) of the trace */ |
711 | if (invalidate) | 717 | if (invalidate && p >= e) |
712 | rebuild_snap_realms(realm); | 718 | rebuild_snap_realms(realm); |
713 | 719 | ||
720 | if (!first_realm) | ||
721 | first_realm = realm; | ||
722 | else | ||
723 | ceph_put_snap_realm(mdsc, realm); | ||
724 | |||
725 | if (p < e) | ||
726 | goto more; | ||
727 | |||
714 | /* | 728 | /* |
715 | * queue cap snaps _after_ we've built the new snap contexts, | 729 | * queue cap snaps _after_ we've built the new snap contexts, |
716 | * so that i_head_snapc can be set appropriately. | 730 | * so that i_head_snapc can be set appropriately. |
@@ -721,12 +735,21 @@ more: | |||
721 | queue_realm_cap_snaps(realm); | 735 | queue_realm_cap_snaps(realm); |
722 | } | 736 | } |
723 | 737 | ||
738 | if (realm_ret) | ||
739 | *realm_ret = first_realm; | ||
740 | else | ||
741 | ceph_put_snap_realm(mdsc, first_realm); | ||
742 | |||
724 | __cleanup_empty_realms(mdsc); | 743 | __cleanup_empty_realms(mdsc); |
725 | return 0; | 744 | return 0; |
726 | 745 | ||
727 | bad: | 746 | bad: |
728 | err = -EINVAL; | 747 | err = -EINVAL; |
729 | fail: | 748 | fail: |
749 | if (realm && !IS_ERR(realm)) | ||
750 | ceph_put_snap_realm(mdsc, realm); | ||
751 | if (first_realm) | ||
752 | ceph_put_snap_realm(mdsc, first_realm); | ||
730 | pr_err("update_snap_trace error %d\n", err); | 753 | pr_err("update_snap_trace error %d\n", err); |
731 | return err; | 754 | return err; |
732 | } | 755 | } |
@@ -844,7 +867,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, | |||
844 | if (IS_ERR(realm)) | 867 | if (IS_ERR(realm)) |
845 | goto out; | 868 | goto out; |
846 | } | 869 | } |
847 | ceph_get_snap_realm(mdsc, realm); | ||
848 | 870 | ||
849 | dout("splitting snap_realm %llx %p\n", realm->ino, realm); | 871 | dout("splitting snap_realm %llx %p\n", realm->ino, realm); |
850 | for (i = 0; i < num_split_inos; i++) { | 872 | for (i = 0; i < num_split_inos; i++) { |
@@ -905,7 +927,7 @@ skip_inode: | |||
905 | /* we may have taken some of the old realm's children. */ | 927 | /* we may have taken some of the old realm's children. */ |
906 | for (i = 0; i < num_split_realms; i++) { | 928 | for (i = 0; i < num_split_realms; i++) { |
907 | struct ceph_snap_realm *child = | 929 | struct ceph_snap_realm *child = |
908 | ceph_lookup_snap_realm(mdsc, | 930 | __lookup_snap_realm(mdsc, |
909 | le64_to_cpu(split_realms[i])); | 931 | le64_to_cpu(split_realms[i])); |
910 | if (!child) | 932 | if (!child) |
911 | continue; | 933 | continue; |
@@ -918,7 +940,7 @@ skip_inode: | |||
918 | * snap, we can avoid queueing cap_snaps. | 940 | * snap, we can avoid queueing cap_snaps. |
919 | */ | 941 | */ |
920 | ceph_update_snap_trace(mdsc, p, e, | 942 | ceph_update_snap_trace(mdsc, p, e, |
921 | op == CEPH_SNAP_OP_DESTROY); | 943 | op == CEPH_SNAP_OP_DESTROY, NULL); |
922 | 944 | ||
923 | if (op == CEPH_SNAP_OP_SPLIT) | 945 | if (op == CEPH_SNAP_OP_SPLIT) |
924 | /* we took a reference when we created the realm, above */ | 946 | /* we took a reference when we created the realm, above */ |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index e1aa32d0759d..72bc05a73b69 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -693,7 +693,8 @@ extern void ceph_get_snap_realm(struct ceph_mds_client *mdsc, | |||
693 | extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc, | 693 | extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc, |
694 | struct ceph_snap_realm *realm); | 694 | struct ceph_snap_realm *realm); |
695 | extern int ceph_update_snap_trace(struct ceph_mds_client *m, | 695 | extern int ceph_update_snap_trace(struct ceph_mds_client *m, |
696 | void *p, void *e, bool deletion); | 696 | void *p, void *e, bool deletion, |
697 | struct ceph_snap_realm **realm_ret); | ||
697 | extern void ceph_handle_snap(struct ceph_mds_client *mdsc, | 698 | extern void ceph_handle_snap(struct ceph_mds_client *mdsc, |
698 | struct ceph_mds_session *session, | 699 | struct ceph_mds_session *session, |
699 | struct ceph_msg *msg); | 700 | struct ceph_msg *msg); |