* [PATCH] ceph: fix freeing inode vs removing session caps race
@ 2013-07-24 5:48 Yan, Zheng
2013-07-24 6:38 ` Yan, Zheng
0 siblings, 1 reply; 2+ messages in thread
From: Yan, Zheng @ 2013-07-24 5:48 UTC (permalink / raw)
To: ceph-devel; +Cc: sage, Yan, Zheng
From: "Yan, Zheng" <zheng.z.yan@intel.com>
remove_session_caps() uses iterate_session_caps() to remove caps,
but iterate_session_caps() skips inodes that are being deleted.
So session->s_nr_caps can be non-zero after iterate_session_caps()
return.
We can fix the issue by waiting until deletions are complete.
__wait_on_freeing_inode() is designed for the job, but it is not
exported, so we use lookup inode function to access it.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
---
fs/ceph/inode.c | 8 ++++++++
fs/ceph/mds_client.c | 28 ++++++++++++++++++++++++++++
fs/ceph/super.h | 2 ++
3 files changed, 38 insertions(+)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 5437e76..de839f4 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -61,6 +61,14 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
return inode;
}
+struct inode *ceph_lookup_inode(struct super_block *sb, struct ceph_vino vino)
+{
+ struct inode *inode;
+ ino_t t = ceph_vino_to_ino(vino);
+ inode = ilookup5_nowait(sb, t, ceph_ino_compare, &vino);
+ return inode;
+}
+
/*
* get/constuct snapdir inode for a given directory
*/
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 3eb1b44..8e9d29a 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1028,6 +1028,34 @@ static void remove_session_caps(struct ceph_mds_session *session)
{
dout("remove_session_caps on %p\n", session);
iterate_session_caps(session, remove_session_caps_cb, NULL);
+
+ spin_lock(&session->s_cap_lock);
+ if (session->s_nr_caps > 0) {
+ struct super_block *sb = session->s_mdsc->fsc->sb;
+ struct inode *inode;
+ struct ceph_cap *cap;
+ struct ceph_vino vino;
+ /*
+ * iterate_session_caps() skips inodes that are being
+ * deleted, we need to wait until deletions are complete.
+ * __wait_on_freeing_inode() is designed for the job,
+ * but it is not exported, so use lookup inode function
+ * to access it.
+ */
+ while (list_empty(&session->s_caps)) {
+ cap = list_entry(session->s_caps.next,
+ struct ceph_cap, session_caps);
+ vino = cap->ci->i_vino;
+ spin_unlock(&session->s_cap_lock);
+
+ inode = ceph_lookup_inode(sb, vino);
+ iput(inode);
+
+ spin_lock(&session->s_cap_lock);
+ }
+ }
+ spin_unlock(&session->s_cap_lock);
+
BUG_ON(session->s_nr_caps > 0);
BUG_ON(!list_empty(&session->s_cap_flushing));
cleanup_cap_releases(session);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index e81c0b6..f1e4e47 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -678,6 +678,8 @@ extern void ceph_destroy_inode(struct inode *inode);
extern struct inode *ceph_get_inode(struct super_block *sb,
struct ceph_vino vino);
+extern struct inode *ceph_lookup_inode(struct super_block *sb,
+ struct ceph_vino vino);
extern struct inode *ceph_get_snapdir(struct inode *parent);
extern int ceph_fill_file_size(struct inode *inode, int issued,
u32 truncate_seq, u64 truncate_size, u64 size);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] ceph: fix freeing inode vs removing session caps race
2013-07-24 5:48 [PATCH] ceph: fix freeing inode vs removing session caps race Yan, Zheng
@ 2013-07-24 6:38 ` Yan, Zheng
0 siblings, 0 replies; 2+ messages in thread
From: Yan, Zheng @ 2013-07-24 6:38 UTC (permalink / raw)
To: ceph-devel; +Cc: sage
previous patch is buggy, please ignore it. here is updated version.
---
From dfe2517bcb40046dbd0c8993558fc3e083d028d5 Mon Sep 17 00:00:00 2001
From: "Yan, Zheng" <zheng.z.yan@intel.com>
Date: Wed, 24 Jul 2013 12:22:11 +0800
Subject: [PATCH] ceph: fix freeing inode vs removing session caps race
remove_session_caps() uses iterate_session_caps() to remove caps,
but iterate_session_caps() skips inodes that are being deleted.
So session->s_nr_caps can be non-zero after iterate_session_caps()
return.
We can fix the issue by waiting until deletions are complete.
__wait_on_freeing_inode() is designed for the job, but it is not
exported, so we use lookup inode function to access it.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
---
fs/ceph/inode.c | 8 ++++++++
fs/ceph/mds_client.c | 31 +++++++++++++++++++++++++++++++
fs/ceph/super.h | 2 ++
3 files changed, 41 insertions(+)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 5437e76..de839f4 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -61,6 +61,14 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
return inode;
}
+struct inode *ceph_lookup_inode(struct super_block *sb, struct ceph_vino vino)
+{
+ struct inode *inode;
+ ino_t t = ceph_vino_to_ino(vino);
+ inode = ilookup5_nowait(sb, t, ceph_ino_compare, &vino);
+ return inode;
+}
+
/*
* get/constuct snapdir inode for a given directory
*/
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 3eb1b44..40e9856 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1028,6 +1028,37 @@ static void remove_session_caps(struct ceph_mds_session *session)
{
dout("remove_session_caps on %p\n", session);
iterate_session_caps(session, remove_session_caps_cb, NULL);
+
+ spin_lock(&session->s_cap_lock);
+ if (session->s_nr_caps > 0) {
+ struct super_block *sb = session->s_mdsc->fsc->sb;
+ struct inode *inode;
+ struct ceph_cap *cap, *prev = NULL;
+ struct ceph_vino vino;
+ /*
+ * iterate_session_caps() skips inodes that are being
+ * deleted, we need to wait until deletions are complete.
+ * __wait_on_freeing_inode() is designed for the job,
+ * but it is not exported, so use lookup inode function
+ * to access it.
+ */
+ while (!list_empty(&session->s_caps)) {
+ cap = list_entry(session->s_caps.next,
+ struct ceph_cap, session_caps);
+ if (cap == prev)
+ break;
+ prev = cap;
+ vino = cap->ci->i_vino;
+ spin_unlock(&session->s_cap_lock);
+
+ inode = ceph_lookup_inode(sb, vino);
+ iput(inode);
+
+ spin_lock(&session->s_cap_lock);
+ }
+ }
+ spin_unlock(&session->s_cap_lock);
+
BUG_ON(session->s_nr_caps > 0);
BUG_ON(!list_empty(&session->s_cap_flushing));
cleanup_cap_releases(session);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index e81c0b6..f1e4e47 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -678,6 +678,8 @@ extern void ceph_destroy_inode(struct inode *inode);
extern struct inode *ceph_get_inode(struct super_block *sb,
struct ceph_vino vino);
+extern struct inode *ceph_lookup_inode(struct super_block *sb,
+ struct ceph_vino vino);
extern struct inode *ceph_get_snapdir(struct inode *parent);
extern int ceph_fill_file_size(struct inode *inode, int issued,
u32 truncate_seq, u64 truncate_size, u64 size);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-07-24 6:38 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-24 5:48 [PATCH] ceph: fix freeing inode vs removing session caps race Yan, Zheng
2013-07-24 6:38 ` Yan, Zheng
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.