#include <linux/ceph/ceph_debug.h> #include <linux/module.h>#include <linux/slab.h>#include <asm/div64.h> #include <linux/ceph/libceph.h>#include <linux/ceph/osdmap.h>#include <linux/ceph/decode.h>#include <linux/crush/hash.h>#include <linux/crush/mapper.h> char *ceph_osdmap_state_str(char *str, int len, int state){ int flag = 0; if (!len) goto done; *str = '\0'; if (state) { if (state & CEPH_OSD_EXISTS) { snprintf(str, len, "exists"); flag = 1; } if (state & CEPH_OSD_UP) { snprintf(str, len, "%s%s%s", str, (flag ? ", " : ""), "up"); flag = 1; } } else { snprintf(str, len, "doesn't exist"); }done: return str;} /* maps */ static int calc_bits_of(unsigned int t){ int b = 0; while (t) { t = t >> 1; b++; } return b;} /* * the foo_mask is the smallest value 2^n-1 that is >= foo. */static void calc_pg_masks(struct ceph_pg_pool_info *pi){ pi->pg_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.pg_num)-1)) - 1; pi->pgp_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.pgp_num)-1)) - 1; pi->lpg_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.lpg_num)-1)) - 1; pi->lpgp_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.lpgp_num)-1)) - 1;} /* * decode crush map */static int crush_decode_uniform_bucket(void **p, void *end, struct crush_bucket_uniform *b){ dout("crush_decode_uniform_bucket %p to %p\n", *p, end); ceph_decode_need(p, end, (1+b->h.size) * sizeof(u32), bad); b->item_weight = ceph_decode_32(p); return 0;bad: return -EINVAL;} static int crush_decode_list_bucket(void **p, void *end, struct crush_bucket_list *b){ int j; dout("crush_decode_list_bucket %p to %p\n", *p, end); b->item_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS); if (b->item_weights == NULL) return -ENOMEM; b->sum_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS); if (b->sum_weights == NULL) return -ENOMEM; ceph_decode_need(p, end, 2 * b->h.size * sizeof(u32), bad); for (j = 0; j < b->h.size; j++) { b->item_weights[j] = ceph_decode_32(p); b->sum_weights[j] = ceph_decode_32(p); } return 0;bad: return -EINVAL;} static int crush_decode_tree_bucket(void **p, void *end, struct crush_bucket_tree *b){ int j; dout("crush_decode_tree_bucket %p to %p\n", *p, end); ceph_decode_32_safe(p, end, b->num_nodes, bad); b->node_weights = kcalloc(b->num_nodes, sizeof(u32), GFP_NOFS); if (b->node_weights == NULL) return -ENOMEM; ceph_decode_need(p, end, b->num_nodes * sizeof(u32), bad); for (j = 0; j < b->num_nodes; j++) b->node_weights[j] = ceph_decode_32(p); return 0;bad: return -EINVAL;} static int crush_decode_straw_bucket(void **p, void *end, struct crush_bucket_straw *b){ int j; dout("crush_decode_straw_bucket %p to %p\n", *p, end); b->item_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS); if (b->item_weights == NULL) return -ENOMEM; b->straws = kcalloc(b->h.size, sizeof(u32), GFP_NOFS); if (b->straws == NULL) return -ENOMEM; ceph_decode_need(p, end, 2 * b->h.size * sizeof(u32), bad); for (j = 0; j < b->h.size; j++) { b->item_weights[j] = ceph_decode_32(p); b->straws[j] = ceph_decode_32(p); } return 0;bad: return -EINVAL;} static struct crush_map *crush_decode(void *pbyval, void *end){ struct crush_map *c; int err = -EINVAL; int i, j; void **p = &pbyval; void *start = pbyval; u32 magic; dout("crush_decode %p to %p len %d\n", *p, end, (int)(end - *p)); c = kzalloc(sizeof(*c), GFP_NOFS); if (c == NULL) return ERR_PTR(-ENOMEM); ceph_decode_need(p, end, 4*sizeof(u32), bad); magic = ceph_decode_32(p); if (magic != CRUSH_MAGIC) { pr_err("crush_decode magic %x != current %x\n", (unsigned int)magic, (unsigned int)CRUSH_MAGIC); goto bad; } c->max_buckets = ceph_decode_32(p); c->max_rules = ceph_decode_32(p); c->max_devices = ceph_decode_32(p); c->buckets = kcalloc(c->max_buckets, sizeof(*c->buckets), GFP_NOFS); if (c->buckets == NULL) goto badmem; c->rules = kcalloc(c->max_rules, sizeof(*c->rules), GFP_NOFS); if (c->rules == NULL) goto badmem; /* buckets */ for (i = 0; i < c->max_buckets; i++) { int size = 0; u32 alg; struct crush_bucket *b; ceph_decode_32_safe(p, end, alg, bad); if (alg == 0) { c->buckets[i] = NULL; continue; } dout("crush_decode bucket %d off %x %p to %p\n", i, (int)(*p-start), *p, end); switch (alg) { case CRUSH_BUCKET_UNIFORM: size = sizeof(struct crush_bucket_uniform); break; case CRUSH_BUCKET_LIST: size = sizeof(struct crush_bucket_list); break; case CRUSH_BUCKET_TREE: size = sizeof(struct crush_bucket_tree); break; case CRUSH_BUCKET_STRAW: size = sizeof(struct crush_bucket_straw); break; default: err = -EINVAL; goto bad; } BUG_ON(size == 0); b = c->buckets[i] = kzalloc(size, GFP_NOFS); if (b == NULL) goto badmem; ceph_decode_need(p, end, 4*sizeof(u32), bad); b->id = ceph_decode_32(p); b->type = ceph_decode_16(p); b->alg = ceph_decode_8(p); b->hash = ceph_decode_8(p); b->weight = ceph_decode_32(p); b->size = ceph_decode_32(p); dout("crush_decode bucket size %d off %x %p to %p\n", b->size, (int)(*p-start), *p, end); b->items = kcalloc(b->size, sizeof(__s32), GFP_NOFS); if (b->items == NULL) goto badmem; b->perm = kcalloc(b->size, sizeof(u32), GFP_NOFS); if (b->perm == NULL) goto badmem; b->perm_n = 0; ceph_decode_need(p, end, b->size*sizeof(u32), bad); for (j = 0; j < b->size; j++) b->items[j] = ceph_decode_32(p); switch (b->alg) { case CRUSH_BUCKET_UNIFORM: err = crush_decode_uniform_bucket(p, end, (struct crush_bucket_uniform *)b); if (err < 0) goto bad; break; case CRUSH_BUCKET_LIST: err = crush_decode_list_bucket(p, end, (struct crush_bucket_list *)b); if (err < 0) goto bad; break; case CRUSH_BUCKET_TREE: err = crush_decode_tree_bucket(p, end, (struct crush_bucket_tree *)b); if (err < 0) goto bad; break; case CRUSH_BUCKET_STRAW: err = crush_decode_straw_bucket(p, end, (struct crush_bucket_straw *)b); if (err < 0) goto bad; break; } } /* rules */ dout("rule vec is %p\n", c->rules); for (i = 0; i < c->max_rules; i++) { u32 yes; struct crush_rule *r; ceph_decode_32_safe(p, end, yes, bad); if (!yes) { dout("crush_decode NO rule %d off %x %p to %p\n", i, (int)(*p-start), *p, end); c->rules[i] = NULL; continue; } dout("crush_decode rule %d off %x %p to %p\n", i, (int)(*p-start), *p, end); /* len */ ceph_decode_32_safe(p, end, yes, bad);#if BITS_PER_LONG == 32 err = -EINVAL; if (yes > (ULONG_MAX - sizeof(*r)) / sizeof(struct crush_rule_step)) goto bad;#endif r = c->rules[i] = kmalloc(sizeof(*r) + yes*sizeof(struct crush_rule_step), GFP_NOFS); if (r == NULL) goto badmem; dout(" rule %d is at %p\n", i, r); r->len = yes; ceph_decode_copy_safe(p, end, &r->mask, 4, bad); /* 4 u8's */ ceph_decode_need(p, end, r->len*3*sizeof(u32), bad); for (j = 0; j < r->len; j++) { r->steps[j].op = ceph_decode_32(p); r->steps[j].arg1 = ceph_decode_32(p); r->steps[j].arg2 = ceph_decode_32(p); } } /* ignore trailing name maps. */ dout("crush_decode success\n"); return c; badmem: err = -ENOMEM;bad: dout("crush_decode fail %d\n", err); crush_destroy(c); return ERR_PTR(err);} /* * rbtree of pg_mapping for handling pg_temp (explicit mapping of pgid * to a set of osds) */static int pgid_cmp(struct ceph_pg l, struct ceph_pg r){ u64 a = *(u64 *)&l; u64 b = *(u64 *)&r; if (a < b) return -1; if (a > b) return 1; return 0;} static int __insert_pg_mapping(struct ceph_pg_mapping *new, struct rb_root *root){ struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct ceph_pg_mapping *pg = NULL; int c; dout("__insert_pg_mapping %llx %p\n", *(u64 *)&new->pgid, new); while (*p) { parent = *p; pg = rb_entry(parent, struct ceph_pg_mapping, node); c = pgid_cmp(new->pgid, pg->pgid); if (c < 0) p = &(*p)->rb_left; else if (c > 0) p = &(*p)->rb_right; else return -EEXIST; } rb_link_node(&new->node, parent, p); rb_insert_color(&new->node, root); return 0;} static struct ceph_pg_mapping *__lookup_pg_mapping(struct rb_root *root, struct ceph_pg pgid){ struct rb_node *n = root->rb_node; struct ceph_pg_mapping *pg; int c; while (n) { pg = rb_entry(n, struct ceph_pg_mapping, node); c = pgid_cmp(pgid, pg->pgid); if (c < 0) { n = n->rb_left; } else if (c > 0) { n = n->rb_right; } else { dout("__lookup_pg_mapping %llx got %p\n", *(u64 *)&pgid, pg); return pg; } } return NULL;} static int __remove_pg_mapping(struct rb_root *root, struct ceph_pg pgid){ struct ceph_pg_mapping *pg = __lookup_pg_mapping(root, pgid); if (pg) { dout("__remove_pg_mapping %llx %p\n", *(u64 *)&pgid, pg); rb_erase(&pg->node, root); kfree(pg); return 0; } dout("__remove_pg_mapping %llx dne\n", *(u64 *)&pgid); return -ENOENT;} /* * rbtree of pg pool info */static int __insert_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *new){ struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct ceph_pg_pool_info *pi = NULL; while (*p) { parent = *p; pi = rb_entry(parent, struct ceph_pg_pool_info, node); if (new->id < pi->id) p = &(*p)->rb_left; else if (new->id > pi->id) p = &(*p)->rb_right; else return -EEXIST; } rb_link_node(&new->node, parent, p); rb_insert_color(&new->node, root); return 0;} static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, int id){ struct ceph_pg_pool_info *pi; struct rb_node *n = root->rb_node; while (n) { pi = rb_entry(n, struct ceph_pg_pool_info, node); if (id < pi->id) n = n->rb_left; else if (id > pi->id) n = n->rb_right; else return pi; } return NULL;} int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name){ struct rb_node *rbp; for (rbp = rb_first(&map->pg_pools); rbp; rbp = rb_next(rbp)) { struct ceph_pg_pool_info *pi = rb_entry(rbp, struct ceph_pg_pool_info, node); if (pi->name && strcmp(pi->name, name) == 0) return pi->id; } return -ENOENT;}EXPORT_SYMBOL(ceph_pg_poolid_by_name); static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi){ rb_erase(&pi->node, root); kfree(pi->name); kfree(pi);} static int __decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi){ unsigned int n, m; ceph_decode_copy(p, &pi->v, sizeof(pi->v)); calc_pg_masks(pi); /* num_snaps * snap_info_t */ n = le32_to_cpu(pi->v.num_snaps); while (n--) { ceph_decode_need(p, end, sizeof(u64) + 1 + sizeof(u64) + sizeof(struct ceph_timespec), bad); *p += sizeof(u64) + /* key */ 1 + sizeof(u64) + /* u8, snapid */ sizeof(struct ceph_timespec); m = ceph_decode_32(p); /* snap name */ *p += m; } *p += le32_to_cpu(pi->v.num_removed_snap_intervals) * sizeof(u64) * 2; return 0; bad: return -EINVAL;} static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map){ struct ceph_pg_pool_info *pi; u32 num, len, pool; ceph_decode_32_safe(p, end, num, bad); dout(" %d pool names\n", num); while (num--) { ceph_decode_32_safe(p, end, pool, bad); ceph_decode_32_safe(p, end, len, bad); dout(" pool %d len %d\n", pool, len); pi = __lookup_pg_pool(&map->pg_pools, pool); if (pi) { kfree(pi->name); pi->name = kmalloc(len + 1, GFP_NOFS); if (pi->name) { memcpy(pi->name, *p, len); pi->name[len] = '\0'; dout(" name is %s\n", pi->name); } }Lines 1–500 of 1119. Load more
#include <linux/ceph/ceph_debug.h> #include <linux/module.h> #include <linux/slab.h> #include <asm/div64.h> #include <linux/ceph/libceph.h> #include <linux/ceph/osdmap.h> #include <linux/ceph/decode.h> #include <linux/crush/hash.h> #include <linux/crush/mapper.h> char *ceph_osdmap_state_str(char *str, int len, int state) { int flag = 0; if (!len) goto done; *str = '\0'; if (state) { if (state & CEPH_OSD_EXISTS) { snprintf(str, len, "exists"); flag = 1; } if (state & CEPH_OSD_UP) { snprintf(str, len, "%s%s%s", str, (flag ? ", " : ""), "up"); flag = 1; } } else { snprintf(str, len, "doesn't exist"); } done: return str; } /* maps */ static int calc_bits_of(unsigned int t) { int b = 0; while (t) { t = t >> 1; b++; } return b; } /* * the foo_mask is the smallest value 2^n-1 that is >= foo. */ static void calc_pg_masks(struct ceph_pg_pool_info *pi) { pi->pg_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.pg_num)-1)) - 1; pi->pgp_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.pgp_num)-1)) - 1; pi->lpg_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.lpg_num)-1)) - 1; pi->lpgp_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.lpgp_num)-1)) - 1; } /* * decode crush map */ static int crush_decode_uniform_bucket(void **p, void *end, struct crush_bucket_uniform *b) { dout("crush_decode_uniform_bucket %p to %p\n", *p, end); ceph_decode_need(p, end, (1+b->h.size) * sizeof(u32), bad); b->item_weight = ceph_decode_32(p); return 0; bad: return -EINVAL; } static int crush_decode_list_bucket(void **p, void *end, struct crush_bucket_list *b) { int j; dout("crush_decode_list_bucket %p to %p\n", *p, end); b->item_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS); if (b->item_weights == NULL) return -ENOMEM; b->sum_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS); if (b->sum_weights == NULL) return -ENOMEM; ceph_decode_need(p, end, 2 * b->h.size * sizeof(u32), bad); for (j = 0; j < b->h.size; j++) { b->item_weights[j] = ceph_decode_32(p); b->sum_weights[j] = ceph_decode_32(p); } return 0; bad: return -EINVAL; } static int crush_decode_tree_bucket(void **p, void *end, struct crush_bucket_tree *b) { int j; dout("crush_decode_tree_bucket %p to %p\n", *p, end); ceph_decode_32_safe(p, end, b->num_nodes, bad); b->node_weights = kcalloc(b->num_nodes, sizeof(u32), GFP_NOFS); if (b->node_weights == NULL) return -ENOMEM; ceph_decode_need(p, end, b->num_nodes * sizeof(u32), bad); for (j = 0; j < b->num_nodes; j++) b->node_weights[j] = ceph_decode_32(p); return 0; bad: return -EINVAL; } static int crush_decode_straw_bucket(void **p, void *end, struct crush_bucket_straw *b) { int j; dout("crush_decode_straw_bucket %p to %p\n", *p, end); b->item_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS); if (b->item_weights == NULL) return -ENOMEM; b->straws = kcalloc(b->h.size, sizeof(u32), GFP_NOFS); if (b->straws == NULL) return -ENOMEM; ceph_decode_need(p, end, 2 * b->h.size * sizeof(u32), bad); for (j = 0; j < b->h.size; j++) { b->item_weights[j] = ceph_decode_32(p); b->straws[j] = ceph_decode_32(p); } return 0; bad: return -EINVAL; } static struct crush_map *crush_decode(void *pbyval, void *end) { struct crush_map *c; int err = -EINVAL; int i, j; void **p = &pbyval; void *start = pbyval; u32 magic; dout("crush_decode %p to %p len %d\n", *p, end, (int)(end - *p)); c = kzalloc(sizeof(*c), GFP_NOFS); if (c == NULL) return ERR_PTR(-ENOMEM); ceph_decode_need(p, end, 4*sizeof(u32), bad); magic = ceph_decode_32(p); if (magic != CRUSH_MAGIC) { pr_err("crush_decode magic %x != current %x\n", (unsigned int)magic, (unsigned int)CRUSH_MAGIC); goto bad; } c->max_buckets = ceph_decode_32(p); c->max_rules = ceph_decode_32(p); c->max_devices = ceph_decode_32(p); c->buckets = kcalloc(c->max_buckets, sizeof(*c->buckets), GFP_NOFS); if (c->buckets == NULL) goto badmem; c->rules = kcalloc(c->max_rules, sizeof(*c->rules), GFP_NOFS); if (c->rules == NULL) goto badmem; /* buckets */ for (i = 0; i < c->max_buckets; i++) { int size = 0; u32 alg; struct crush_bucket *b; ceph_decode_32_safe(p, end, alg, bad); if (alg == 0) { c->buckets[i] = NULL; continue; } dout("crush_decode bucket %d off %x %p to %p\n", i, (int)(*p-start), *p, end); switch (alg) { case CRUSH_BUCKET_UNIFORM: size = sizeof(struct crush_bucket_uniform); break; case CRUSH_BUCKET_LIST: size = sizeof(struct crush_bucket_list); break; case CRUSH_BUCKET_TREE: size = sizeof(struct crush_bucket_tree); break; case CRUSH_BUCKET_STRAW: size = sizeof(struct crush_bucket_straw); break; default: err = -EINVAL; goto bad; } BUG_ON(size == 0); b = c->buckets[i] = kzalloc(size, GFP_NOFS); if (b == NULL) goto badmem; ceph_decode_need(p, end, 4*sizeof(u32), bad); b->id = ceph_decode_32(p); b->type = ceph_decode_16(p); b->alg = ceph_decode_8(p); b->hash = ceph_decode_8(p); b->weight = ceph_decode_32(p); b->size = ceph_decode_32(p); dout("crush_decode bucket size %d off %x %p to %p\n", b->size, (int)(*p-start), *p, end); b->items = kcalloc(b->size, sizeof(__s32), GFP_NOFS); if (b->items == NULL) goto badmem; b->perm = kcalloc(b->size, sizeof(u32), GFP_NOFS); if (b->perm == NULL) goto badmem; b->perm_n = 0; ceph_decode_need(p, end, b->size*sizeof(u32), bad); for (j = 0; j < b->size; j++) b->items[j] = ceph_decode_32(p); switch (b->alg) { case CRUSH_BUCKET_UNIFORM: err = crush_decode_uniform_bucket(p, end, (struct crush_bucket_uniform *)b); if (err < 0) goto bad; break; case CRUSH_BUCKET_LIST: err = crush_decode_list_bucket(p, end, (struct crush_bucket_list *)b); if (err < 0) goto bad; break; case CRUSH_BUCKET_TREE: err = crush_decode_tree_bucket(p, end, (struct crush_bucket_tree *)b); if (err < 0) goto bad; break; case CRUSH_BUCKET_STRAW: err = crush_decode_straw_bucket(p, end, (struct crush_bucket_straw *)b); if (err < 0) goto bad; break; } } /* rules */ dout("rule vec is %p\n", c->rules); for (i = 0; i < c->max_rules; i++) { u32 yes; struct crush_rule *r; ceph_decode_32_safe(p, end, yes, bad); if (!yes) { dout("crush_decode NO rule %d off %x %p to %p\n", i, (int)(*p-start), *p, end); c->rules[i] = NULL; continue; } dout("crush_decode rule %d off %x %p to %p\n", i, (int)(*p-start), *p, end); /* len */ ceph_decode_32_safe(p, end, yes, bad); #if BITS_PER_LONG == 32 err = -EINVAL; if (yes > (ULONG_MAX - sizeof(*r)) / sizeof(struct crush_rule_step)) goto bad; #endif r = c->rules[i] = kmalloc(sizeof(*r) + yes*sizeof(struct crush_rule_step), GFP_NOFS); if (r == NULL) goto badmem; dout(" rule %d is at %p\n", i, r); r->len = yes; ceph_decode_copy_safe(p, end, &r->mask, 4, bad); /* 4 u8's */ ceph_decode_need(p, end, r->len*3*sizeof(u32), bad); for (j = 0; j < r->len; j++) { r->steps[j].op = ceph_decode_32(p); r->steps[j].arg1 = ceph_decode_32(p); r->steps[j].arg2 = ceph_decode_32(p); } } /* ignore trailing name maps. */ dout("crush_decode success\n"); return c; badmem: err = -ENOMEM; bad: dout("crush_decode fail %d\n", err); crush_destroy(c); return ERR_PTR(err); } /* * rbtree of pg_mapping for handling pg_temp (explicit mapping of pgid * to a set of osds) */ static int pgid_cmp(struct ceph_pg l, struct ceph_pg r) { u64 a = *(u64 *)&l; u64 b = *(u64 *)&r; if (a < b) return -1; if (a > b) return 1; return 0; } static int __insert_pg_mapping(struct ceph_pg_mapping *new, struct rb_root *root) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct ceph_pg_mapping *pg = NULL; int c; dout("__insert_pg_mapping %llx %p\n", *(u64 *)&new->pgid, new); while (*p) { parent = *p; pg = rb_entry(parent, struct ceph_pg_mapping, node); c = pgid_cmp(new->pgid, pg->pgid); if (c < 0) p = &(*p)->rb_left; else if (c > 0) p = &(*p)->rb_right; else return -EEXIST; } rb_link_node(&new->node, parent, p); rb_insert_color(&new->node, root); return 0; } static struct ceph_pg_mapping *__lookup_pg_mapping(struct rb_root *root, struct ceph_pg pgid) { struct rb_node *n = root->rb_node; struct ceph_pg_mapping *pg; int c; while (n) { pg = rb_entry(n, struct ceph_pg_mapping, node); c = pgid_cmp(pgid, pg->pgid); if (c < 0) { n = n->rb_left; } else if (c > 0) { n = n->rb_right; } else { dout("__lookup_pg_mapping %llx got %p\n", *(u64 *)&pgid, pg); return pg; } } return NULL; } static int __remove_pg_mapping(struct rb_root *root, struct ceph_pg pgid) { struct ceph_pg_mapping *pg = __lookup_pg_mapping(root, pgid); if (pg) { dout("__remove_pg_mapping %llx %p\n", *(u64 *)&pgid, pg); rb_erase(&pg->node, root); kfree(pg); return 0; } dout("__remove_pg_mapping %llx dne\n", *(u64 *)&pgid); return -ENOENT; } /* * rbtree of pg pool info */ static int __insert_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *new) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct ceph_pg_pool_info *pi = NULL; while (*p) { parent = *p; pi = rb_entry(parent, struct ceph_pg_pool_info, node); if (new->id < pi->id) p = &(*p)->rb_left; else if (new->id > pi->id) p = &(*p)->rb_right; else return -EEXIST; } rb_link_node(&new->node, parent, p); rb_insert_color(&new->node, root); return 0; } static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, int id) { struct ceph_pg_pool_info *pi; struct rb_node *n = root->rb_node; while (n) { pi = rb_entry(n, struct ceph_pg_pool_info, node); if (id < pi->id) n = n->rb_left; else if (id > pi->id) n = n->rb_right; else return pi; } return NULL; } int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name) { struct rb_node *rbp; for (rbp = rb_first(&map->pg_pools); rbp; rbp = rb_next(rbp)) { struct ceph_pg_pool_info *pi = rb_entry(rbp, struct ceph_pg_pool_info, node); if (pi->name && strcmp(pi->name, name) == 0) return pi->id; } return -ENOENT; } EXPORT_SYMBOL(ceph_pg_poolid_by_name); static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi) { rb_erase(&pi->node, root); kfree(pi->name); kfree(pi); } static int __decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi) { unsigned int n, m; ceph_decode_copy(p, &pi->v, sizeof(pi->v)); calc_pg_masks(pi); /* num_snaps * snap_info_t */ n = le32_to_cpu(pi->v.num_snaps); while (n--) { ceph_decode_need(p, end, sizeof(u64) + 1 + sizeof(u64) + sizeof(struct ceph_timespec), bad); *p += sizeof(u64) + /* key */ 1 + sizeof(u64) + /* u8, snapid */ sizeof(struct ceph_timespec); m = ceph_decode_32(p); /* snap name */ *p += m; } *p += le32_to_cpu(pi->v.num_removed_snap_intervals) * sizeof(u64) * 2; return 0; bad: return -EINVAL; } static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map) { struct ceph_pg_pool_info *pi; u32 num, len, pool; ceph_decode_32_safe(p, end, num, bad); dout(" %d pool names\n", num); while (num--) { ceph_decode_32_safe(p, end, pool, bad); ceph_decode_32_safe(p, end, len, bad); dout(" pool %d len %d\n", pool, len); pi = __lookup_pg_pool(&map->pg_pools, pool); if (pi) { kfree(pi->name); pi->name = kmalloc(len + 1, GFP_NOFS); if (pi->name) { memcpy(pi->name, *p, len); pi->name[len] = '\0'; dout(" name is %s\n", pi->name); } }