From: Yehuda Sadeh Date: Tue, 14 Oct 2008 19:34:18 +0000 (-0700) Subject: kclient: fix race condition X-Git-Tag: v0.5~325 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d174b8079ff3ed526c067969893ae910887c478e;p=ceph.git kclient: fix race condition --- diff --git a/src/kernel/dir.c b/src/kernel/dir.c index b0c2256f93e1..f15c24816f1f 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 732c2ecfe473..f7fccb6a5f77 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 a4253a608ce2..efb670ac05a5 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 d4ad676ed002..a4769a56e719 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;