diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-04-18 04:00:30 -0400 |
---|---|---|
committer | Yan, Zheng <zheng.z.yan@intel.com> | 2014-06-05 21:29:54 -0400 |
commit | 3e7fbe9cebfdaac380419507908e10c499ddd25b (patch) | |
tree | 6352978e76ad863fb1c33a539f589ac83c0723e3 /fs | |
parent | 2cd698be9a3d3a0f8f3c66814eac34144c31954c (diff) |
ceph: introduce ceph_fill_fragtree()
Move the code that update the i_fragtree into a separate function.
Also add simple probabilistic test to decide whether the i_fragtree
should be updated
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/inode.c | 129 |
1 files changed, 84 insertions, 45 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 8ad50a30808e..850b26d2e601 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/writeback.h> | 10 | #include <linux/writeback.h> |
11 | #include <linux/vmalloc.h> | 11 | #include <linux/vmalloc.h> |
12 | #include <linux/posix_acl.h> | 12 | #include <linux/posix_acl.h> |
13 | #include <linux/random.h> | ||
13 | 14 | ||
14 | #include "super.h" | 15 | #include "super.h" |
15 | #include "mds_client.h" | 16 | #include "mds_client.h" |
@@ -179,9 +180,8 @@ struct ceph_inode_frag *__ceph_find_frag(struct ceph_inode_info *ci, u32 f) | |||
179 | * specified, copy the frag delegation info to the caller if | 180 | * specified, copy the frag delegation info to the caller if |
180 | * it is present. | 181 | * it is present. |
181 | */ | 182 | */ |
182 | u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, | 183 | static u32 __ceph_choose_frag(struct ceph_inode_info *ci, u32 v, |
183 | struct ceph_inode_frag *pfrag, | 184 | struct ceph_inode_frag *pfrag, int *found) |
184 | int *found) | ||
185 | { | 185 | { |
186 | u32 t = ceph_frag_make(0, 0); | 186 | u32 t = ceph_frag_make(0, 0); |
187 | struct ceph_inode_frag *frag; | 187 | struct ceph_inode_frag *frag; |
@@ -191,7 +191,6 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, | |||
191 | if (found) | 191 | if (found) |
192 | *found = 0; | 192 | *found = 0; |
193 | 193 | ||
194 | mutex_lock(&ci->i_fragtree_mutex); | ||
195 | while (1) { | 194 | while (1) { |
196 | WARN_ON(!ceph_frag_contains_value(t, v)); | 195 | WARN_ON(!ceph_frag_contains_value(t, v)); |
197 | frag = __ceph_find_frag(ci, t); | 196 | frag = __ceph_find_frag(ci, t); |
@@ -220,10 +219,19 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, | |||
220 | } | 219 | } |
221 | dout("choose_frag(%x) = %x\n", v, t); | 220 | dout("choose_frag(%x) = %x\n", v, t); |
222 | 221 | ||
223 | mutex_unlock(&ci->i_fragtree_mutex); | ||
224 | return t; | 222 | return t; |
225 | } | 223 | } |
226 | 224 | ||
225 | u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, | ||
226 | struct ceph_inode_frag *pfrag, int *found) | ||
227 | { | ||
228 | u32 ret; | ||
229 | mutex_lock(&ci->i_fragtree_mutex); | ||
230 | ret = __ceph_choose_frag(ci, v, pfrag, found); | ||
231 | mutex_unlock(&ci->i_fragtree_mutex); | ||
232 | return ret; | ||
233 | } | ||
234 | |||
227 | /* | 235 | /* |
228 | * Process dirfrag (delegation) info from the mds. Include leaf | 236 | * Process dirfrag (delegation) info from the mds. Include leaf |
229 | * fragment in tree ONLY if ndist > 0. Otherwise, only | 237 | * fragment in tree ONLY if ndist > 0. Otherwise, only |
@@ -286,6 +294,75 @@ out: | |||
286 | return err; | 294 | return err; |
287 | } | 295 | } |
288 | 296 | ||
297 | static int ceph_fill_fragtree(struct inode *inode, | ||
298 | struct ceph_frag_tree_head *fragtree, | ||
299 | struct ceph_mds_reply_dirfrag *dirinfo) | ||
300 | { | ||
301 | struct ceph_inode_info *ci = ceph_inode(inode); | ||
302 | struct ceph_inode_frag *frag; | ||
303 | struct rb_node *rb_node; | ||
304 | int i; | ||
305 | u32 id, nsplits; | ||
306 | bool update = false; | ||
307 | |||
308 | mutex_lock(&ci->i_fragtree_mutex); | ||
309 | nsplits = le32_to_cpu(fragtree->nsplits); | ||
310 | if (nsplits) { | ||
311 | i = prandom_u32() % nsplits; | ||
312 | id = le32_to_cpu(fragtree->splits[i].frag); | ||
313 | if (!__ceph_find_frag(ci, id)) | ||
314 | update = true; | ||
315 | } else if (!RB_EMPTY_ROOT(&ci->i_fragtree)) { | ||
316 | rb_node = rb_first(&ci->i_fragtree); | ||
317 | frag = rb_entry(rb_node, struct ceph_inode_frag, node); | ||
318 | if (frag->frag != ceph_frag_make(0, 0) || rb_next(rb_node)) | ||
319 | update = true; | ||
320 | } | ||
321 | if (!update && dirinfo) { | ||
322 | id = le32_to_cpu(dirinfo->frag); | ||
323 | if (id != __ceph_choose_frag(ci, id, NULL, NULL)) | ||
324 | update = true; | ||
325 | } | ||
326 | if (!update) | ||
327 | goto out_unlock; | ||
328 | |||
329 | dout("fill_fragtree %llx.%llx\n", ceph_vinop(inode)); | ||
330 | rb_node = rb_first(&ci->i_fragtree); | ||
331 | for (i = 0; i < nsplits; i++) { | ||
332 | id = le32_to_cpu(fragtree->splits[i].frag); | ||
333 | frag = NULL; | ||
334 | while (rb_node) { | ||
335 | frag = rb_entry(rb_node, struct ceph_inode_frag, node); | ||
336 | if (ceph_frag_compare(frag->frag, id) >= 0) { | ||
337 | if (frag->frag != id) | ||
338 | frag = NULL; | ||
339 | else | ||
340 | rb_node = rb_next(rb_node); | ||
341 | break; | ||
342 | } | ||
343 | rb_node = rb_next(rb_node); | ||
344 | rb_erase(&frag->node, &ci->i_fragtree); | ||
345 | kfree(frag); | ||
346 | frag = NULL; | ||
347 | } | ||
348 | if (!frag) { | ||
349 | frag = __get_or_create_frag(ci, id); | ||
350 | if (IS_ERR(frag)) | ||
351 | continue; | ||
352 | } | ||
353 | frag->split_by = le32_to_cpu(fragtree->splits[i].by); | ||
354 | dout(" frag %x split by %d\n", frag->frag, frag->split_by); | ||
355 | } | ||
356 | while (rb_node) { | ||
357 | frag = rb_entry(rb_node, struct ceph_inode_frag, node); | ||
358 | rb_node = rb_next(rb_node); | ||
359 | rb_erase(&frag->node, &ci->i_fragtree); | ||
360 | kfree(frag); | ||
361 | } | ||
362 | out_unlock: | ||
363 | mutex_unlock(&ci->i_fragtree_mutex); | ||
364 | return 0; | ||
365 | } | ||
289 | 366 | ||
290 | /* | 367 | /* |
291 | * initialize a newly allocated inode. | 368 | * initialize a newly allocated inode. |
@@ -584,12 +661,8 @@ static int fill_inode(struct inode *inode, | |||
584 | struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; | 661 | struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; |
585 | struct ceph_mds_reply_inode *info = iinfo->in; | 662 | struct ceph_mds_reply_inode *info = iinfo->in; |
586 | struct ceph_inode_info *ci = ceph_inode(inode); | 663 | struct ceph_inode_info *ci = ceph_inode(inode); |
587 | int i; | ||
588 | int issued = 0, implemented, new_issued; | 664 | int issued = 0, implemented, new_issued; |
589 | struct timespec mtime, atime, ctime; | 665 | struct timespec mtime, atime, ctime; |
590 | u32 nsplits; | ||
591 | struct ceph_inode_frag *frag; | ||
592 | struct rb_node *rb_node; | ||
593 | struct ceph_buffer *xattr_blob = NULL; | 666 | struct ceph_buffer *xattr_blob = NULL; |
594 | struct ceph_cap *new_cap = NULL; | 667 | struct ceph_cap *new_cap = NULL; |
595 | int err = 0; | 668 | int err = 0; |
@@ -804,42 +877,8 @@ static int fill_inode(struct inode *inode, | |||
804 | ceph_queue_vmtruncate(inode); | 877 | ceph_queue_vmtruncate(inode); |
805 | 878 | ||
806 | /* populate frag tree */ | 879 | /* populate frag tree */ |
807 | /* FIXME: move me up, if/when version reflects fragtree changes */ | 880 | if (S_ISDIR(inode->i_mode)) |
808 | nsplits = le32_to_cpu(info->fragtree.nsplits); | 881 | ceph_fill_fragtree(inode, &info->fragtree, dirinfo); |
809 | mutex_lock(&ci->i_fragtree_mutex); | ||
810 | rb_node = rb_first(&ci->i_fragtree); | ||
811 | for (i = 0; i < nsplits; i++) { | ||
812 | u32 id = le32_to_cpu(info->fragtree.splits[i].frag); | ||
813 | frag = NULL; | ||
814 | while (rb_node) { | ||
815 | frag = rb_entry(rb_node, struct ceph_inode_frag, node); | ||
816 | if (ceph_frag_compare(frag->frag, id) >= 0) { | ||
817 | if (frag->frag != id) | ||
818 | frag = NULL; | ||
819 | else | ||
820 | rb_node = rb_next(rb_node); | ||
821 | break; | ||
822 | } | ||
823 | rb_node = rb_next(rb_node); | ||
824 | rb_erase(&frag->node, &ci->i_fragtree); | ||
825 | kfree(frag); | ||
826 | frag = NULL; | ||
827 | } | ||
828 | if (!frag) { | ||
829 | frag = __get_or_create_frag(ci, id); | ||
830 | if (IS_ERR(frag)) | ||
831 | continue; | ||
832 | } | ||
833 | frag->split_by = le32_to_cpu(info->fragtree.splits[i].by); | ||
834 | dout(" frag %x split by %d\n", frag->frag, frag->split_by); | ||
835 | } | ||
836 | while (rb_node) { | ||
837 | frag = rb_entry(rb_node, struct ceph_inode_frag, node); | ||
838 | rb_node = rb_next(rb_node); | ||
839 | rb_erase(&frag->node, &ci->i_fragtree); | ||
840 | kfree(frag); | ||
841 | } | ||
842 | mutex_unlock(&ci->i_fragtree_mutex); | ||
843 | 882 | ||
844 | /* update delegation info? */ | 883 | /* update delegation info? */ |
845 | if (dirinfo) | 884 | if (dirinfo) |