Loading fs/ceph/inode.c +84 −45 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include <linux/writeback.h> #include <linux/vmalloc.h> #include <linux/posix_acl.h> #include <linux/random.h> #include "super.h" #include "mds_client.h" Loading Loading @@ -179,9 +180,8 @@ struct ceph_inode_frag *__ceph_find_frag(struct ceph_inode_info *ci, u32 f) * specified, copy the frag delegation info to the caller if * it is present. */ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, struct ceph_inode_frag *pfrag, int *found) static u32 __ceph_choose_frag(struct ceph_inode_info *ci, u32 v, struct ceph_inode_frag *pfrag, int *found) { u32 t = ceph_frag_make(0, 0); struct ceph_inode_frag *frag; Loading @@ -191,7 +191,6 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, if (found) *found = 0; mutex_lock(&ci->i_fragtree_mutex); while (1) { WARN_ON(!ceph_frag_contains_value(t, v)); frag = __ceph_find_frag(ci, t); Loading Loading @@ -220,10 +219,19 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, } dout("choose_frag(%x) = %x\n", v, t); mutex_unlock(&ci->i_fragtree_mutex); return t; } u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, struct ceph_inode_frag *pfrag, int *found) { u32 ret; mutex_lock(&ci->i_fragtree_mutex); ret = __ceph_choose_frag(ci, v, pfrag, found); mutex_unlock(&ci->i_fragtree_mutex); return ret; } /* * Process dirfrag (delegation) info from the mds. Include leaf * fragment in tree ONLY if ndist > 0. Otherwise, only Loading Loading @@ -286,6 +294,75 @@ static int ceph_fill_dirfrag(struct inode *inode, return err; } static int ceph_fill_fragtree(struct inode *inode, struct ceph_frag_tree_head *fragtree, struct ceph_mds_reply_dirfrag *dirinfo) { struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_frag *frag; struct rb_node *rb_node; int i; u32 id, nsplits; bool update = false; mutex_lock(&ci->i_fragtree_mutex); nsplits = le32_to_cpu(fragtree->nsplits); if (nsplits) { i = prandom_u32() % nsplits; id = le32_to_cpu(fragtree->splits[i].frag); if (!__ceph_find_frag(ci, id)) update = true; } else if (!RB_EMPTY_ROOT(&ci->i_fragtree)) { rb_node = rb_first(&ci->i_fragtree); frag = rb_entry(rb_node, struct ceph_inode_frag, node); if (frag->frag != ceph_frag_make(0, 0) || rb_next(rb_node)) update = true; } if (!update && dirinfo) { id = le32_to_cpu(dirinfo->frag); if (id != __ceph_choose_frag(ci, id, NULL, NULL)) update = true; } if (!update) goto out_unlock; dout("fill_fragtree %llx.%llx\n", ceph_vinop(inode)); rb_node = rb_first(&ci->i_fragtree); for (i = 0; i < nsplits; i++) { id = le32_to_cpu(fragtree->splits[i].frag); frag = NULL; while (rb_node) { frag = rb_entry(rb_node, struct ceph_inode_frag, node); if (ceph_frag_compare(frag->frag, id) >= 0) { if (frag->frag != id) frag = NULL; else rb_node = rb_next(rb_node); break; } rb_node = rb_next(rb_node); rb_erase(&frag->node, &ci->i_fragtree); kfree(frag); frag = NULL; } if (!frag) { frag = __get_or_create_frag(ci, id); if (IS_ERR(frag)) continue; } frag->split_by = le32_to_cpu(fragtree->splits[i].by); dout(" frag %x split by %d\n", frag->frag, frag->split_by); } while (rb_node) { frag = rb_entry(rb_node, struct ceph_inode_frag, node); rb_node = rb_next(rb_node); rb_erase(&frag->node, &ci->i_fragtree); kfree(frag); } out_unlock: mutex_unlock(&ci->i_fragtree_mutex); return 0; } /* * initialize a newly allocated inode. Loading Loading @@ -584,12 +661,8 @@ static int fill_inode(struct inode *inode, struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; struct ceph_mds_reply_inode *info = iinfo->in; struct ceph_inode_info *ci = ceph_inode(inode); int i; int issued = 0, implemented, new_issued; struct timespec mtime, atime, ctime; u32 nsplits; struct ceph_inode_frag *frag; struct rb_node *rb_node; struct ceph_buffer *xattr_blob = NULL; struct ceph_cap *new_cap = NULL; int err = 0; Loading Loading @@ -804,42 +877,8 @@ static int fill_inode(struct inode *inode, ceph_queue_vmtruncate(inode); /* populate frag tree */ /* FIXME: move me up, if/when version reflects fragtree changes */ nsplits = le32_to_cpu(info->fragtree.nsplits); mutex_lock(&ci->i_fragtree_mutex); rb_node = rb_first(&ci->i_fragtree); for (i = 0; i < nsplits; i++) { u32 id = le32_to_cpu(info->fragtree.splits[i].frag); frag = NULL; while (rb_node) { frag = rb_entry(rb_node, struct ceph_inode_frag, node); if (ceph_frag_compare(frag->frag, id) >= 0) { if (frag->frag != id) frag = NULL; else rb_node = rb_next(rb_node); break; } rb_node = rb_next(rb_node); rb_erase(&frag->node, &ci->i_fragtree); kfree(frag); frag = NULL; } if (!frag) { frag = __get_or_create_frag(ci, id); if (IS_ERR(frag)) continue; } frag->split_by = le32_to_cpu(info->fragtree.splits[i].by); dout(" frag %x split by %d\n", frag->frag, frag->split_by); } while (rb_node) { frag = rb_entry(rb_node, struct ceph_inode_frag, node); rb_node = rb_next(rb_node); rb_erase(&frag->node, &ci->i_fragtree); kfree(frag); } mutex_unlock(&ci->i_fragtree_mutex); if (S_ISDIR(inode->i_mode)) ceph_fill_fragtree(inode, &info->fragtree, dirinfo); /* update delegation info? */ if (dirinfo) Loading Loading
fs/ceph/inode.c +84 −45 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include <linux/writeback.h> #include <linux/vmalloc.h> #include <linux/posix_acl.h> #include <linux/random.h> #include "super.h" #include "mds_client.h" Loading Loading @@ -179,9 +180,8 @@ struct ceph_inode_frag *__ceph_find_frag(struct ceph_inode_info *ci, u32 f) * specified, copy the frag delegation info to the caller if * it is present. */ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, struct ceph_inode_frag *pfrag, int *found) static u32 __ceph_choose_frag(struct ceph_inode_info *ci, u32 v, struct ceph_inode_frag *pfrag, int *found) { u32 t = ceph_frag_make(0, 0); struct ceph_inode_frag *frag; Loading @@ -191,7 +191,6 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, if (found) *found = 0; mutex_lock(&ci->i_fragtree_mutex); while (1) { WARN_ON(!ceph_frag_contains_value(t, v)); frag = __ceph_find_frag(ci, t); Loading Loading @@ -220,10 +219,19 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, } dout("choose_frag(%x) = %x\n", v, t); mutex_unlock(&ci->i_fragtree_mutex); return t; } u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, struct ceph_inode_frag *pfrag, int *found) { u32 ret; mutex_lock(&ci->i_fragtree_mutex); ret = __ceph_choose_frag(ci, v, pfrag, found); mutex_unlock(&ci->i_fragtree_mutex); return ret; } /* * Process dirfrag (delegation) info from the mds. Include leaf * fragment in tree ONLY if ndist > 0. Otherwise, only Loading Loading @@ -286,6 +294,75 @@ static int ceph_fill_dirfrag(struct inode *inode, return err; } static int ceph_fill_fragtree(struct inode *inode, struct ceph_frag_tree_head *fragtree, struct ceph_mds_reply_dirfrag *dirinfo) { struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_frag *frag; struct rb_node *rb_node; int i; u32 id, nsplits; bool update = false; mutex_lock(&ci->i_fragtree_mutex); nsplits = le32_to_cpu(fragtree->nsplits); if (nsplits) { i = prandom_u32() % nsplits; id = le32_to_cpu(fragtree->splits[i].frag); if (!__ceph_find_frag(ci, id)) update = true; } else if (!RB_EMPTY_ROOT(&ci->i_fragtree)) { rb_node = rb_first(&ci->i_fragtree); frag = rb_entry(rb_node, struct ceph_inode_frag, node); if (frag->frag != ceph_frag_make(0, 0) || rb_next(rb_node)) update = true; } if (!update && dirinfo) { id = le32_to_cpu(dirinfo->frag); if (id != __ceph_choose_frag(ci, id, NULL, NULL)) update = true; } if (!update) goto out_unlock; dout("fill_fragtree %llx.%llx\n", ceph_vinop(inode)); rb_node = rb_first(&ci->i_fragtree); for (i = 0; i < nsplits; i++) { id = le32_to_cpu(fragtree->splits[i].frag); frag = NULL; while (rb_node) { frag = rb_entry(rb_node, struct ceph_inode_frag, node); if (ceph_frag_compare(frag->frag, id) >= 0) { if (frag->frag != id) frag = NULL; else rb_node = rb_next(rb_node); break; } rb_node = rb_next(rb_node); rb_erase(&frag->node, &ci->i_fragtree); kfree(frag); frag = NULL; } if (!frag) { frag = __get_or_create_frag(ci, id); if (IS_ERR(frag)) continue; } frag->split_by = le32_to_cpu(fragtree->splits[i].by); dout(" frag %x split by %d\n", frag->frag, frag->split_by); } while (rb_node) { frag = rb_entry(rb_node, struct ceph_inode_frag, node); rb_node = rb_next(rb_node); rb_erase(&frag->node, &ci->i_fragtree); kfree(frag); } out_unlock: mutex_unlock(&ci->i_fragtree_mutex); return 0; } /* * initialize a newly allocated inode. Loading Loading @@ -584,12 +661,8 @@ static int fill_inode(struct inode *inode, struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; struct ceph_mds_reply_inode *info = iinfo->in; struct ceph_inode_info *ci = ceph_inode(inode); int i; int issued = 0, implemented, new_issued; struct timespec mtime, atime, ctime; u32 nsplits; struct ceph_inode_frag *frag; struct rb_node *rb_node; struct ceph_buffer *xattr_blob = NULL; struct ceph_cap *new_cap = NULL; int err = 0; Loading Loading @@ -804,42 +877,8 @@ static int fill_inode(struct inode *inode, ceph_queue_vmtruncate(inode); /* populate frag tree */ /* FIXME: move me up, if/when version reflects fragtree changes */ nsplits = le32_to_cpu(info->fragtree.nsplits); mutex_lock(&ci->i_fragtree_mutex); rb_node = rb_first(&ci->i_fragtree); for (i = 0; i < nsplits; i++) { u32 id = le32_to_cpu(info->fragtree.splits[i].frag); frag = NULL; while (rb_node) { frag = rb_entry(rb_node, struct ceph_inode_frag, node); if (ceph_frag_compare(frag->frag, id) >= 0) { if (frag->frag != id) frag = NULL; else rb_node = rb_next(rb_node); break; } rb_node = rb_next(rb_node); rb_erase(&frag->node, &ci->i_fragtree); kfree(frag); frag = NULL; } if (!frag) { frag = __get_or_create_frag(ci, id); if (IS_ERR(frag)) continue; } frag->split_by = le32_to_cpu(info->fragtree.splits[i].by); dout(" frag %x split by %d\n", frag->frag, frag->split_by); } while (rb_node) { frag = rb_entry(rb_node, struct ceph_inode_frag, node); rb_node = rb_next(rb_node); rb_erase(&frag->node, &ci->i_fragtree); kfree(frag); } mutex_unlock(&ci->i_fragtree_mutex); if (S_ISDIR(inode->i_mode)) ceph_fill_fragtree(inode, &info->fragtree, dirinfo); /* update delegation info? */ if (dirinfo) Loading