From d174b8079ff3ed526c067969893ae910887c478e Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 14 Oct 2008 12:34:18 -0700 Subject: [PATCH] kclient: fix race condition --- src/kernel/dir.c | 2 +- src/kernel/inode.c | 11 +++++++++-- src/kernel/mds_client.c | 11 +++++++++-- src/kernel/super.h | 3 ++- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/kernel/dir.c b/src/kernel/dir.c index b0c2256f93e1b..f15c24816f1f8 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -153,7 +153,7 @@ nextfrag: int op = ceph_snap(inode) == CEPH_SNAPDIR ? CEPH_MDS_OP_LSSNAP:CEPH_MDS_OP_READDIR; - frag = ceph_choose_frag(ceph_inode(inode), frag, 0); + frag = ceph_choose_frag(ceph_inode(inode), frag, 0, 0); /* query mds */ dout(10, "dir_readdir querying mds for ino %llx.%llx frag %x\n", diff --git a/src/kernel/inode.c b/src/kernel/inode.c index 732c2ecfe4735..f7fccb6a5f776 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -133,13 +133,17 @@ out: } __u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, - struct ceph_inode_frag **pfrag) + struct ceph_inode_frag *pfrag, + int *found) { u32 t = frag_make(0, 0); struct ceph_inode_frag *frag; unsigned nway, i; u32 n; + if (found) + *found = 0; + mutex_lock(&ci->i_fragtree_mutex); while (1) { WARN_ON(!frag_contains_value(t, v)); @@ -148,7 +152,10 @@ __u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, break; /* t is a leaf */ if (frag->split_by == 0) { if (pfrag) - *pfrag = frag; + memcpy(pfrag, frag, sizeof(struct ceph_inode_frag)); + + if (found) + *found = 1; break; } diff --git a/src/kernel/mds_client.c b/src/kernel/mds_client.c index a4253a608ce20..efb670ac05a50 100644 --- a/src/kernel/mds_client.c +++ b/src/kernel/mds_client.c @@ -486,9 +486,15 @@ static int choose_mds(struct ceph_mds_client *mdsc, if (is_hash && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { + int found; ci = ceph_inode(dentry->d_inode); - ceph_choose_frag(ci, hash, &frag); - if (frag) { + frag = kmalloc(sizeof(struct ceph_inode_frag), GFP_KERNEL); + + if (!frag) + return -ENOMEM; + + ceph_choose_frag(ci, hash, frag, &found); + if (found) { /* avoid hitting dir replicas on dir * auth delegation point.. mds will * likely forward anyway to avoid @@ -518,6 +524,7 @@ static int choose_mds(struct ceph_mds_client *mdsc, return mds; } } + kfree(frag); } if (IS_ROOT(dentry)) break; diff --git a/src/kernel/super.h b/src/kernel/super.h index d4ad676ed0028..a4769a56e7198 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -322,7 +322,8 @@ __ceph_find_frag(struct ceph_inode_info *ci, u32 f) } extern __u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, - struct ceph_inode_frag **pfrag); + struct ceph_inode_frag *pfrag, + int *found); struct ceph_dentry_info { struct dentry *dentry; -- 2.39.5