diff options
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r-- | fs/ceph/caps.c | 73 |
1 files changed, 39 insertions, 34 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index db122bb357b8..7d0a0d0adc18 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -1407,6 +1407,7 @@ static int try_nonblocking_invalidate(struct inode *inode) | |||
1407 | */ | 1407 | */ |
1408 | void ceph_check_caps(struct ceph_inode_info *ci, int flags, | 1408 | void ceph_check_caps(struct ceph_inode_info *ci, int flags, |
1409 | struct ceph_mds_session *session) | 1409 | struct ceph_mds_session *session) |
1410 | __releases(session->s_mutex) | ||
1410 | { | 1411 | { |
1411 | struct ceph_client *client = ceph_inode_to_client(&ci->vfs_inode); | 1412 | struct ceph_client *client = ceph_inode_to_client(&ci->vfs_inode); |
1412 | struct ceph_mds_client *mdsc = &client->mdsc; | 1413 | struct ceph_mds_client *mdsc = &client->mdsc; |
@@ -1414,7 +1415,6 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, | |||
1414 | struct ceph_cap *cap; | 1415 | struct ceph_cap *cap; |
1415 | int file_wanted, used; | 1416 | int file_wanted, used; |
1416 | int took_snap_rwsem = 0; /* true if mdsc->snap_rwsem held */ | 1417 | int took_snap_rwsem = 0; /* true if mdsc->snap_rwsem held */ |
1417 | int drop_session_lock = session ? 0 : 1; | ||
1418 | int issued, implemented, want, retain, revoking, flushing = 0; | 1418 | int issued, implemented, want, retain, revoking, flushing = 0; |
1419 | int mds = -1; /* keep track of how far we've gone through i_caps list | 1419 | int mds = -1; /* keep track of how far we've gone through i_caps list |
1420 | to avoid an infinite loop on retry */ | 1420 | to avoid an infinite loop on retry */ |
@@ -1639,7 +1639,7 @@ ack: | |||
1639 | if (queue_invalidate) | 1639 | if (queue_invalidate) |
1640 | ceph_queue_invalidate(inode); | 1640 | ceph_queue_invalidate(inode); |
1641 | 1641 | ||
1642 | if (session && drop_session_lock) | 1642 | if (session) |
1643 | mutex_unlock(&session->s_mutex); | 1643 | mutex_unlock(&session->s_mutex); |
1644 | if (took_snap_rwsem) | 1644 | if (took_snap_rwsem) |
1645 | up_read(&mdsc->snap_rwsem); | 1645 | up_read(&mdsc->snap_rwsem); |
@@ -2195,18 +2195,19 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, | |||
2195 | * Handle a cap GRANT message from the MDS. (Note that a GRANT may | 2195 | * Handle a cap GRANT message from the MDS. (Note that a GRANT may |
2196 | * actually be a revocation if it specifies a smaller cap set.) | 2196 | * actually be a revocation if it specifies a smaller cap set.) |
2197 | * | 2197 | * |
2198 | * caller holds s_mutex. | 2198 | * caller holds s_mutex and i_lock, we drop both. |
2199 | * | ||
2199 | * return value: | 2200 | * return value: |
2200 | * 0 - ok | 2201 | * 0 - ok |
2201 | * 1 - check_caps on auth cap only (writeback) | 2202 | * 1 - check_caps on auth cap only (writeback) |
2202 | * 2 - check_caps (ack revoke) | 2203 | * 2 - check_caps (ack revoke) |
2203 | */ | 2204 | */ |
2204 | static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | 2205 | static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, |
2205 | struct ceph_mds_session *session, | 2206 | struct ceph_mds_session *session, |
2206 | struct ceph_cap *cap, | 2207 | struct ceph_cap *cap, |
2207 | struct ceph_buffer *xattr_buf) | 2208 | struct ceph_buffer *xattr_buf) |
2208 | __releases(inode->i_lock) | 2209 | __releases(inode->i_lock) |
2209 | 2210 | __releases(session->s_mutex) | |
2210 | { | 2211 | { |
2211 | struct ceph_inode_info *ci = ceph_inode(inode); | 2212 | struct ceph_inode_info *ci = ceph_inode(inode); |
2212 | int mds = session->s_mds; | 2213 | int mds = session->s_mds; |
@@ -2216,7 +2217,7 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2216 | u64 size = le64_to_cpu(grant->size); | 2217 | u64 size = le64_to_cpu(grant->size); |
2217 | u64 max_size = le64_to_cpu(grant->max_size); | 2218 | u64 max_size = le64_to_cpu(grant->max_size); |
2218 | struct timespec mtime, atime, ctime; | 2219 | struct timespec mtime, atime, ctime; |
2219 | int reply = 0; | 2220 | int check_caps = 0; |
2220 | int wake = 0; | 2221 | int wake = 0; |
2221 | int writeback = 0; | 2222 | int writeback = 0; |
2222 | int revoked_rdcache = 0; | 2223 | int revoked_rdcache = 0; |
@@ -2329,11 +2330,12 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2329 | if ((used & ~newcaps) & CEPH_CAP_FILE_BUFFER) | 2330 | if ((used & ~newcaps) & CEPH_CAP_FILE_BUFFER) |
2330 | writeback = 1; /* will delay ack */ | 2331 | writeback = 1; /* will delay ack */ |
2331 | else if (dirty & ~newcaps) | 2332 | else if (dirty & ~newcaps) |
2332 | reply = 1; /* initiate writeback in check_caps */ | 2333 | check_caps = 1; /* initiate writeback in check_caps */ |
2333 | else if (((used & ~newcaps) & CEPH_CAP_FILE_CACHE) == 0 || | 2334 | else if (((used & ~newcaps) & CEPH_CAP_FILE_CACHE) == 0 || |
2334 | revoked_rdcache) | 2335 | revoked_rdcache) |
2335 | reply = 2; /* send revoke ack in check_caps */ | 2336 | check_caps = 2; /* send revoke ack in check_caps */ |
2336 | cap->issued = newcaps; | 2337 | cap->issued = newcaps; |
2338 | cap->implemented |= newcaps; | ||
2337 | } else if (cap->issued == newcaps) { | 2339 | } else if (cap->issued == newcaps) { |
2338 | dout("caps unchanged: %s -> %s\n", | 2340 | dout("caps unchanged: %s -> %s\n", |
2339 | ceph_cap_string(cap->issued), ceph_cap_string(newcaps)); | 2341 | ceph_cap_string(cap->issued), ceph_cap_string(newcaps)); |
@@ -2346,6 +2348,7 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2346 | * pending revocation */ | 2348 | * pending revocation */ |
2347 | wake = 1; | 2349 | wake = 1; |
2348 | } | 2350 | } |
2351 | BUG_ON(cap->issued & ~cap->implemented); | ||
2349 | 2352 | ||
2350 | spin_unlock(&inode->i_lock); | 2353 | spin_unlock(&inode->i_lock); |
2351 | if (writeback) | 2354 | if (writeback) |
@@ -2359,7 +2362,14 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2359 | ceph_queue_invalidate(inode); | 2362 | ceph_queue_invalidate(inode); |
2360 | if (wake) | 2363 | if (wake) |
2361 | wake_up(&ci->i_cap_wq); | 2364 | wake_up(&ci->i_cap_wq); |
2362 | return reply; | 2365 | |
2366 | if (check_caps == 1) | ||
2367 | ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_AUTHONLY, | ||
2368 | session); | ||
2369 | else if (check_caps == 2) | ||
2370 | ceph_check_caps(ci, CHECK_CAPS_NODELAY, session); | ||
2371 | else | ||
2372 | mutex_unlock(&session->s_mutex); | ||
2363 | } | 2373 | } |
2364 | 2374 | ||
2365 | /* | 2375 | /* |
@@ -2548,9 +2558,8 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, | |||
2548 | ci->i_cap_exporting_issued = cap->issued; | 2558 | ci->i_cap_exporting_issued = cap->issued; |
2549 | } | 2559 | } |
2550 | __ceph_remove_cap(cap); | 2560 | __ceph_remove_cap(cap); |
2551 | } else { | ||
2552 | WARN_ON(!cap); | ||
2553 | } | 2561 | } |
2562 | /* else, we already released it */ | ||
2554 | 2563 | ||
2555 | spin_unlock(&inode->i_lock); | 2564 | spin_unlock(&inode->i_lock); |
2556 | } | 2565 | } |
@@ -2621,9 +2630,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2621 | u64 cap_id; | 2630 | u64 cap_id; |
2622 | u64 size, max_size; | 2631 | u64 size, max_size; |
2623 | u64 tid; | 2632 | u64 tid; |
2624 | int check_caps = 0; | ||
2625 | void *snaptrace; | 2633 | void *snaptrace; |
2626 | int r; | ||
2627 | 2634 | ||
2628 | dout("handle_caps from mds%d\n", mds); | 2635 | dout("handle_caps from mds%d\n", mds); |
2629 | 2636 | ||
@@ -2668,8 +2675,9 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2668 | case CEPH_CAP_OP_IMPORT: | 2675 | case CEPH_CAP_OP_IMPORT: |
2669 | handle_cap_import(mdsc, inode, h, session, | 2676 | handle_cap_import(mdsc, inode, h, session, |
2670 | snaptrace, le32_to_cpu(h->snap_trace_len)); | 2677 | snaptrace, le32_to_cpu(h->snap_trace_len)); |
2671 | check_caps = 1; /* we may have sent a RELEASE to the old auth */ | 2678 | ceph_check_caps(ceph_inode(inode), CHECK_CAPS_NODELAY, |
2672 | goto done; | 2679 | session); |
2680 | goto done_unlocked; | ||
2673 | } | 2681 | } |
2674 | 2682 | ||
2675 | /* the rest require a cap */ | 2683 | /* the rest require a cap */ |
@@ -2686,16 +2694,8 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2686 | switch (op) { | 2694 | switch (op) { |
2687 | case CEPH_CAP_OP_REVOKE: | 2695 | case CEPH_CAP_OP_REVOKE: |
2688 | case CEPH_CAP_OP_GRANT: | 2696 | case CEPH_CAP_OP_GRANT: |
2689 | r = handle_cap_grant(inode, h, session, cap, msg->middle); | 2697 | handle_cap_grant(inode, h, session, cap, msg->middle); |
2690 | if (r == 1) | 2698 | goto done_unlocked; |
2691 | ceph_check_caps(ceph_inode(inode), | ||
2692 | CHECK_CAPS_NODELAY|CHECK_CAPS_AUTHONLY, | ||
2693 | session); | ||
2694 | else if (r == 2) | ||
2695 | ceph_check_caps(ceph_inode(inode), | ||
2696 | CHECK_CAPS_NODELAY, | ||
2697 | session); | ||
2698 | break; | ||
2699 | 2699 | ||
2700 | case CEPH_CAP_OP_FLUSH_ACK: | 2700 | case CEPH_CAP_OP_FLUSH_ACK: |
2701 | handle_cap_flush_ack(inode, tid, h, session, cap); | 2701 | handle_cap_flush_ack(inode, tid, h, session, cap); |
@@ -2713,9 +2713,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2713 | 2713 | ||
2714 | done: | 2714 | done: |
2715 | mutex_unlock(&session->s_mutex); | 2715 | mutex_unlock(&session->s_mutex); |
2716 | 2716 | done_unlocked: | |
2717 | if (check_caps) | ||
2718 | ceph_check_caps(ceph_inode(inode), CHECK_CAPS_NODELAY, NULL); | ||
2719 | if (inode) | 2717 | if (inode) |
2720 | iput(inode); | 2718 | iput(inode); |
2721 | return; | 2719 | return; |
@@ -2838,11 +2836,18 @@ int ceph_encode_inode_release(void **p, struct inode *inode, | |||
2838 | struct ceph_cap *cap; | 2836 | struct ceph_cap *cap; |
2839 | struct ceph_mds_request_release *rel = *p; | 2837 | struct ceph_mds_request_release *rel = *p; |
2840 | int ret = 0; | 2838 | int ret = 0; |
2841 | 2839 | int used = 0; | |
2842 | dout("encode_inode_release %p mds%d drop %s unless %s\n", inode, | ||
2843 | mds, ceph_cap_string(drop), ceph_cap_string(unless)); | ||
2844 | 2840 | ||
2845 | spin_lock(&inode->i_lock); | 2841 | spin_lock(&inode->i_lock); |
2842 | used = __ceph_caps_used(ci); | ||
2843 | |||
2844 | dout("encode_inode_release %p mds%d used %s drop %s unless %s\n", inode, | ||
2845 | mds, ceph_cap_string(used), ceph_cap_string(drop), | ||
2846 | ceph_cap_string(unless)); | ||
2847 | |||
2848 | /* only drop unused caps */ | ||
2849 | drop &= ~used; | ||
2850 | |||
2846 | cap = __get_cap_for_mds(ci, mds); | 2851 | cap = __get_cap_for_mds(ci, mds); |
2847 | if (cap && __cap_is_valid(cap)) { | 2852 | if (cap && __cap_is_valid(cap)) { |
2848 | if (force || | 2853 | if (force || |