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