Commit a76d0a9c authored by Xiubo Li's avatar Xiubo Li Committed by Ilya Dryomov
Browse files

ceph: don't WARN if we're forcibly removing the session caps



For example in the case of a forced umount, we'll remove all the session
caps even if they are dirty. Move the warning to a wrapper function and
make most of the callers use it. Call the core function when removing
caps due to a forced umount.

Signed-off-by: default avatarXiubo Li <xiubli@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent 42ad631b
Loading
Loading
Loading
Loading
+30 −9
Original line number Diff line number Diff line
@@ -1114,17 +1114,16 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
		return;
	}

	lockdep_assert_held(&ci->i_ceph_lock);

	dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode);

	mdsc = ceph_inode_to_client(&ci->vfs_inode)->mdsc;

	/* remove from inode's cap rbtree, and clear auth cap */
	rb_erase(&cap->ci_node, &ci->i_caps);
	if (ci->i_auth_cap == cap) {
		WARN_ON_ONCE(!list_empty(&ci->i_dirty_item) &&
			     !mdsc->fsc->blocklisted);
	if (ci->i_auth_cap == cap)
		ci->i_auth_cap = NULL;
	}

	/* remove from session list */
	spin_lock(&session->s_cap_lock);
@@ -1176,6 +1175,28 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
	}
}

void ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
{
	struct ceph_inode_info *ci = cap->ci;
	struct ceph_fs_client *fsc;

	/* 'ci' being NULL means the remove have already occurred */
	if (!ci) {
		dout("%s: cap inode is NULL\n", __func__);
		return;
	}

	lockdep_assert_held(&ci->i_ceph_lock);

	fsc = ceph_sb_to_client(ci->vfs_inode.i_sb);
	WARN_ON_ONCE(ci->i_auth_cap == cap &&
		     !list_empty(&ci->i_dirty_item) &&
		     !fsc->blocklisted &&
		     READ_ONCE(fsc->mount_state) != CEPH_MOUNT_SHUTDOWN);

	__ceph_remove_cap(cap, queue_release);
}

struct cap_msg_args {
	struct ceph_mds_session	*session;
	u64			ino, cid, follows;
@@ -1304,7 +1325,7 @@ void __ceph_remove_caps(struct ceph_inode_info *ci)
	while (p) {
		struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
		p = rb_next(p);
		__ceph_remove_cap(cap, true);
		ceph_remove_cap(cap, true);
	}
	spin_unlock(&ci->i_ceph_lock);
}
@@ -3822,7 +3843,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
		goto out_unlock;

	if (target < 0) {
		__ceph_remove_cap(cap, false);
		ceph_remove_cap(cap, false);
		goto out_unlock;
	}

@@ -3857,7 +3878,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
				change_auth_cap_ses(ci, tcap->session);
			}
		}
		__ceph_remove_cap(cap, false);
		ceph_remove_cap(cap, false);
		goto out_unlock;
	} else if (tsession) {
		/* add placeholder for the export tagert */
@@ -3874,7 +3895,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
			spin_unlock(&mdsc->cap_dirty_lock);
		}

		__ceph_remove_cap(cap, false);
		ceph_remove_cap(cap, false);
		goto out_unlock;
	}

@@ -3985,7 +4006,7 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
					ocap->mseq, mds, le32_to_cpu(ph->seq),
					le32_to_cpu(ph->mseq));
		}
		__ceph_remove_cap(ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
		ceph_remove_cap(ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
	}

	*old_issued = issued;
+1 −1
Original line number Diff line number Diff line
@@ -2016,7 +2016,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)

	if (oissued) {
		/* we aren't the only cap.. just remove us */
		__ceph_remove_cap(cap, true);
		ceph_remove_cap(cap, true);
		(*remaining)--;
	} else {
		struct dentry *dentry;
+1 −0
Original line number Diff line number Diff line
@@ -1138,6 +1138,7 @@ extern void ceph_add_cap(struct inode *inode,
			 unsigned cap, unsigned seq, u64 realmino, int flags,
			 struct ceph_cap **new_cap);
extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
extern void ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
extern void __ceph_remove_caps(struct ceph_inode_info *ci);
extern void ceph_put_cap(struct ceph_mds_client *mdsc,
			 struct ceph_cap *cap);