Browse Source

ceph: introduce an inode flag to indicates if snapflush is needed

Signed-off-by: Yan, Zheng <zyan@redhat.com>
Yan, Zheng 9 years ago
parent
commit
70220ac8c2
3 changed files with 36 additions and 15 deletions
  1. 33 15
      fs/ceph/caps.c
  2. 2 0
      fs/ceph/snap.c
  3. 1 0
      fs/ceph/super.h

+ 33 - 15
fs/ceph/caps.c

@@ -1368,6 +1368,7 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci)
 {
 {
 	spin_lock(&ci->i_ceph_lock);
 	spin_lock(&ci->i_ceph_lock);
 	__ceph_flush_snaps(ci, NULL);
 	__ceph_flush_snaps(ci, NULL);
+	ci->i_ceph_flags &= ~CEPH_I_FLUSH_SNAPS;
 	spin_unlock(&ci->i_ceph_lock);
 	spin_unlock(&ci->i_ceph_lock);
 }
 }
 
 
@@ -1563,8 +1564,10 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
 		flags |= CHECK_CAPS_FLUSH;
 		flags |= CHECK_CAPS_FLUSH;
 
 
 	/* flush snaps first time around only */
 	/* flush snaps first time around only */
-	if (!list_empty(&ci->i_cap_snaps))
+	if (ci->i_ceph_flags & CEPH_I_FLUSH_SNAPS) {
 		__ceph_flush_snaps(ci, &session);
 		__ceph_flush_snaps(ci, &session);
+		ci->i_ceph_flags &= ~CEPH_I_FLUSH_SNAPS;
+	}
 	goto retry_locked;
 	goto retry_locked;
 retry:
 retry:
 	spin_lock(&ci->i_ceph_lock);
 	spin_lock(&ci->i_ceph_lock);
@@ -2498,7 +2501,8 @@ void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps)
  * drop cap_snap that is not associated with any snapshot.
  * drop cap_snap that is not associated with any snapshot.
  * we don't need to send FLUSHSNAP message for it.
  * we don't need to send FLUSHSNAP message for it.
  */
  */
-static int ceph_try_drop_cap_snap(struct ceph_cap_snap *capsnap)
+static int ceph_try_drop_cap_snap(struct ceph_inode_info *ci,
+				  struct ceph_cap_snap *capsnap)
 {
 {
 	if (!capsnap->need_flush &&
 	if (!capsnap->need_flush &&
 	    !capsnap->writing && !capsnap->dirty_pages) {
 	    !capsnap->writing && !capsnap->dirty_pages) {
@@ -2506,6 +2510,9 @@ static int ceph_try_drop_cap_snap(struct ceph_cap_snap *capsnap)
 		     capsnap, capsnap->follows);
 		     capsnap, capsnap->follows);
 		BUG_ON(capsnap->cap_flush.tid > 0);
 		BUG_ON(capsnap->cap_flush.tid > 0);
 		ceph_put_snap_context(capsnap->context);
 		ceph_put_snap_context(capsnap->context);
+		if (!list_is_last(&capsnap->ci_item, &ci->i_cap_snaps))
+			ci->i_ceph_flags |= CEPH_I_FLUSH_SNAPS;
+
 		list_del(&capsnap->ci_item);
 		list_del(&capsnap->ci_item);
 		ceph_put_cap_snap(capsnap);
 		ceph_put_cap_snap(capsnap);
 		return 1;
 		return 1;
@@ -2553,7 +2560,7 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had)
 							struct ceph_cap_snap,
 							struct ceph_cap_snap,
 							ci_item);
 							ci_item);
 				capsnap->writing = 0;
 				capsnap->writing = 0;
-				if (ceph_try_drop_cap_snap(capsnap))
+				if (ceph_try_drop_cap_snap(ci, capsnap))
 					put++;
 					put++;
 				else if (__ceph_finish_cap_snap(ci, capsnap))
 				else if (__ceph_finish_cap_snap(ci, capsnap))
 					flushsnaps = 1;
 					flushsnaps = 1;
@@ -2596,15 +2603,19 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
 				struct ceph_snap_context *snapc)
 				struct ceph_snap_context *snapc)
 {
 {
 	struct inode *inode = &ci->vfs_inode;
 	struct inode *inode = &ci->vfs_inode;
-	int last = 0;
-	int complete_capsnap = 0;
-	int drop_capsnap = 0;
-	int found = 0;
 	struct ceph_cap_snap *capsnap = NULL;
 	struct ceph_cap_snap *capsnap = NULL;
+	int put = 0;
+	bool last = false;
+	bool found = false;
+	bool flush_snaps = false;
+	bool complete_capsnap = false;
 
 
 	spin_lock(&ci->i_ceph_lock);
 	spin_lock(&ci->i_ceph_lock);
 	ci->i_wrbuffer_ref -= nr;
 	ci->i_wrbuffer_ref -= nr;
-	last = !ci->i_wrbuffer_ref;
+	if (ci->i_wrbuffer_ref == 0) {
+		last = true;
+		put++;
+	}
 
 
 	if (ci->i_head_snapc == snapc) {
 	if (ci->i_head_snapc == snapc) {
 		ci->i_wrbuffer_ref_head -= nr;
 		ci->i_wrbuffer_ref_head -= nr;
@@ -2624,15 +2635,22 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
 	} else {
 	} else {
 		list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) {
 		list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) {
 			if (capsnap->context == snapc) {
 			if (capsnap->context == snapc) {
-				found = 1;
+				found = true;
 				break;
 				break;
 			}
 			}
 		}
 		}
 		BUG_ON(!found);
 		BUG_ON(!found);
 		capsnap->dirty_pages -= nr;
 		capsnap->dirty_pages -= nr;
 		if (capsnap->dirty_pages == 0) {
 		if (capsnap->dirty_pages == 0) {
-			complete_capsnap = 1;
-			drop_capsnap = ceph_try_drop_cap_snap(capsnap);
+			complete_capsnap = true;
+			if (!capsnap->writing) {
+				if (ceph_try_drop_cap_snap(ci, capsnap)) {
+					put++;
+				} else {
+					ci->i_ceph_flags |= CEPH_I_FLUSH_SNAPS;
+					flush_snaps = true;
+				}
+			}
 		}
 		}
 		dout("put_wrbuffer_cap_refs on %p cap_snap %p "
 		dout("put_wrbuffer_cap_refs on %p cap_snap %p "
 		     " snap %lld %d/%d -> %d/%d %s%s\n",
 		     " snap %lld %d/%d -> %d/%d %s%s\n",
@@ -2647,12 +2665,12 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
 
 
 	if (last) {
 	if (last) {
 		ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);
 		ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);
-		iput(inode);
-	} else if (complete_capsnap) {
+	} else if (flush_snaps) {
 		ceph_flush_snaps(ci);
 		ceph_flush_snaps(ci);
-		wake_up_all(&ci->i_cap_wq);
 	}
 	}
-	if (drop_capsnap)
+	if (complete_capsnap)
+		wake_up_all(&ci->i_cap_wq);
+	while (put-- > 0)
 		iput(inode);
 		iput(inode);
 }
 }
 
 

+ 2 - 0
fs/ceph/snap.c

@@ -601,6 +601,8 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
 		     capsnap->dirty_pages);
 		     capsnap->dirty_pages);
 		return 0;
 		return 0;
 	}
 	}
+
+	ci->i_ceph_flags |= CEPH_I_FLUSH_SNAPS;
 	dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu\n",
 	dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu\n",
 	     inode, capsnap, capsnap->context,
 	     inode, capsnap, capsnap->context,
 	     capsnap->context->seq, ceph_cap_string(capsnap->dirty),
 	     capsnap->context->seq, ceph_cap_string(capsnap->dirty),

+ 1 - 0
fs/ceph/super.h

@@ -469,6 +469,7 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
 #define CEPH_I_SEC_INITED	(1 << 7)  /* security initialized */
 #define CEPH_I_SEC_INITED	(1 << 7)  /* security initialized */
 #define CEPH_I_CAP_DROPPED	(1 << 8)  /* caps were forcibly dropped */
 #define CEPH_I_CAP_DROPPED	(1 << 8)  /* caps were forcibly dropped */
 #define CEPH_I_KICK_FLUSH	(1 << 9)  /* kick flushing caps */
 #define CEPH_I_KICK_FLUSH	(1 << 9)  /* kick flushing caps */
+#define CEPH_I_FLUSH_SNAPS	(1 << 10) /* need flush snapss */
 
 
 static inline void __ceph_dir_set_complete(struct ceph_inode_info *ci,
 static inline void __ceph_dir_set_complete(struct ceph_inode_info *ci,
 					   long long release_count,
 					   long long release_count,