diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-02 19:39:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-02 19:39:09 -0400 |
commit | 72b5ac54d620b29cae23d25f0405f2765b466f72 (patch) | |
tree | 276e6313a16f0821cb3da7061372f37b0feb8ace /net | |
parent | c7fac299672ee98a1da90ea2e473180fc75d2c53 (diff) | |
parent | a0f2b65275413b3438e9f55b1427273cd893c3b2 (diff) |
Merge tag 'ceph-for-4.8-rc1' of git://github.com/ceph/ceph-client
Pull Ceph updates from Ilya Dryomov:
"The highlights are:
- RADOS namespace support in libceph and CephFS (Zheng Yan and
myself). The stopgaps added in 4.5 to deny access to inodes in
namespaces are removed and CEPH_FEATURE_FS_FILE_LAYOUT_V2 feature
bit is now fully supported
- A large rework of the MDS cap flushing code (Zheng Yan)
- Handle some of ->d_revalidate() in RCU mode (Jeff Layton). We were
overly pessimistic before, bailing at the first sight of LOOKUP_RCU
On top of that we've got a few CephFS bug fixes, a couple of cleanups
and Arnd's workaround for a weird genksyms issue"
* tag 'ceph-for-4.8-rc1' of git://github.com/ceph/ceph-client: (34 commits)
ceph: fix symbol versioning for ceph_monc_do_statfs
ceph: Correctly return NXIO errors from ceph_llseek
ceph: Mark the file cache as unreclaimable
ceph: optimize cap flush waiting
ceph: cleanup ceph_flush_snaps()
ceph: kick cap flushes before sending other cap message
ceph: introduce an inode flag to indicates if snapflush is needed
ceph: avoid sending duplicated cap flush message
ceph: unify cap flush and snapcap flush
ceph: use list instead of rbtree to track cap flushes
ceph: update types of some local varibles
ceph: include 'follows' of pending snapflush in cap reconnect message
ceph: update cap reconnect message to version 3
ceph: mount non-default filesystem by name
libceph: fsmap.user subscription support
ceph: handle LOOKUP_RCU in ceph_d_revalidate
ceph: allow dentry_lease_is_valid to work under RCU walk
ceph: clear d_fsinfo pointer under d_lock
ceph: remove ceph_mdsc_lease_release
ceph: don't use ->d_time
...
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/Makefile | 2 | ||||
-rw-r--r-- | net/ceph/ceph_common.c | 2 | ||||
-rw-r--r-- | net/ceph/ceph_fs.c | 30 | ||||
-rw-r--r-- | net/ceph/debugfs.c | 12 | ||||
-rw-r--r-- | net/ceph/mon_client.c | 4 | ||||
-rw-r--r-- | net/ceph/msgpool.c | 1 | ||||
-rw-r--r-- | net/ceph/osd_client.c | 49 | ||||
-rw-r--r-- | net/ceph/osdmap.c | 58 | ||||
-rw-r--r-- | net/ceph/string_table.c | 111 |
9 files changed, 245 insertions, 24 deletions
diff --git a/net/ceph/Makefile b/net/ceph/Makefile index 958d9856912c..84cbed630c4b 100644 --- a/net/ceph/Makefile +++ b/net/ceph/Makefile | |||
@@ -11,5 +11,5 @@ libceph-y := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \ | |||
11 | crypto.o armor.o \ | 11 | crypto.o armor.o \ |
12 | auth_x.o \ | 12 | auth_x.o \ |
13 | ceph_fs.o ceph_strings.o ceph_hash.o \ | 13 | ceph_fs.o ceph_strings.o ceph_hash.o \ |
14 | pagevec.o snapshot.o | 14 | pagevec.o snapshot.o string_table.o |
15 | 15 | ||
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 55d2bfee16d7..bddfcf6f09c2 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -747,6 +747,8 @@ out: | |||
747 | static void __exit exit_ceph_lib(void) | 747 | static void __exit exit_ceph_lib(void) |
748 | { | 748 | { |
749 | dout("exit_ceph_lib\n"); | 749 | dout("exit_ceph_lib\n"); |
750 | WARN_ON(!ceph_strings_empty()); | ||
751 | |||
750 | ceph_osdc_cleanup(); | 752 | ceph_osdc_cleanup(); |
751 | ceph_msgr_exit(); | 753 | ceph_msgr_exit(); |
752 | ceph_crypto_shutdown(); | 754 | ceph_crypto_shutdown(); |
diff --git a/net/ceph/ceph_fs.c b/net/ceph/ceph_fs.c index 41466ccb972a..7d54e944de5e 100644 --- a/net/ceph/ceph_fs.c +++ b/net/ceph/ceph_fs.c | |||
@@ -9,9 +9,9 @@ | |||
9 | */ | 9 | */ |
10 | int ceph_file_layout_is_valid(const struct ceph_file_layout *layout) | 10 | int ceph_file_layout_is_valid(const struct ceph_file_layout *layout) |
11 | { | 11 | { |
12 | __u32 su = le32_to_cpu(layout->fl_stripe_unit); | 12 | __u32 su = layout->stripe_unit; |
13 | __u32 sc = le32_to_cpu(layout->fl_stripe_count); | 13 | __u32 sc = layout->stripe_count; |
14 | __u32 os = le32_to_cpu(layout->fl_object_size); | 14 | __u32 os = layout->object_size; |
15 | 15 | ||
16 | /* stripe unit, object size must be non-zero, 64k increment */ | 16 | /* stripe unit, object size must be non-zero, 64k increment */ |
17 | if (!su || (su & (CEPH_MIN_STRIPE_UNIT-1))) | 17 | if (!su || (su & (CEPH_MIN_STRIPE_UNIT-1))) |
@@ -27,6 +27,30 @@ int ceph_file_layout_is_valid(const struct ceph_file_layout *layout) | |||
27 | return 1; | 27 | return 1; |
28 | } | 28 | } |
29 | 29 | ||
30 | void ceph_file_layout_from_legacy(struct ceph_file_layout *fl, | ||
31 | struct ceph_file_layout_legacy *legacy) | ||
32 | { | ||
33 | fl->stripe_unit = le32_to_cpu(legacy->fl_stripe_unit); | ||
34 | fl->stripe_count = le32_to_cpu(legacy->fl_stripe_count); | ||
35 | fl->object_size = le32_to_cpu(legacy->fl_object_size); | ||
36 | fl->pool_id = le32_to_cpu(legacy->fl_pg_pool); | ||
37 | if (fl->pool_id == 0) | ||
38 | fl->pool_id = -1; | ||
39 | } | ||
40 | EXPORT_SYMBOL(ceph_file_layout_from_legacy); | ||
41 | |||
42 | void ceph_file_layout_to_legacy(struct ceph_file_layout *fl, | ||
43 | struct ceph_file_layout_legacy *legacy) | ||
44 | { | ||
45 | legacy->fl_stripe_unit = cpu_to_le32(fl->stripe_unit); | ||
46 | legacy->fl_stripe_count = cpu_to_le32(fl->stripe_count); | ||
47 | legacy->fl_object_size = cpu_to_le32(fl->object_size); | ||
48 | if (fl->pool_id >= 0) | ||
49 | legacy->fl_pg_pool = cpu_to_le32(fl->pool_id); | ||
50 | else | ||
51 | legacy->fl_pg_pool = 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL(ceph_file_layout_to_legacy); | ||
30 | 54 | ||
31 | int ceph_flags_to_mode(int flags) | 55 | int ceph_flags_to_mode(int flags) |
32 | { | 56 | { |
diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index e77b04ca7802..c62b2b029a6e 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c | |||
@@ -156,8 +156,16 @@ static void dump_target(struct seq_file *s, struct ceph_osd_request_target *t) | |||
156 | seq_printf(s, "]/%d\t[", t->up.primary); | 156 | seq_printf(s, "]/%d\t[", t->up.primary); |
157 | for (i = 0; i < t->acting.size; i++) | 157 | for (i = 0; i < t->acting.size; i++) |
158 | seq_printf(s, "%s%d", (!i ? "" : ","), t->acting.osds[i]); | 158 | seq_printf(s, "%s%d", (!i ? "" : ","), t->acting.osds[i]); |
159 | seq_printf(s, "]/%d\t%*pE\t0x%x", t->acting.primary, | 159 | seq_printf(s, "]/%d\t", t->acting.primary); |
160 | t->target_oid.name_len, t->target_oid.name, t->flags); | 160 | if (t->target_oloc.pool_ns) { |
161 | seq_printf(s, "%*pE/%*pE\t0x%x", | ||
162 | (int)t->target_oloc.pool_ns->len, | ||
163 | t->target_oloc.pool_ns->str, | ||
164 | t->target_oid.name_len, t->target_oid.name, t->flags); | ||
165 | } else { | ||
166 | seq_printf(s, "%*pE\t0x%x", t->target_oid.name_len, | ||
167 | t->target_oid.name, t->flags); | ||
168 | } | ||
161 | if (t->paused) | 169 | if (t->paused) |
162 | seq_puts(s, "\tP"); | 170 | seq_puts(s, "\tP"); |
163 | } | 171 | } |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 37c38a7fb5c5..c83326c5ba58 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -227,9 +227,10 @@ static void __schedule_delayed(struct ceph_mon_client *monc) | |||
227 | } | 227 | } |
228 | 228 | ||
229 | const char *ceph_sub_str[] = { | 229 | const char *ceph_sub_str[] = { |
230 | [CEPH_SUB_MDSMAP] = "mdsmap", | ||
231 | [CEPH_SUB_MONMAP] = "monmap", | 230 | [CEPH_SUB_MONMAP] = "monmap", |
232 | [CEPH_SUB_OSDMAP] = "osdmap", | 231 | [CEPH_SUB_OSDMAP] = "osdmap", |
232 | [CEPH_SUB_FSMAP] = "fsmap.user", | ||
233 | [CEPH_SUB_MDSMAP] = "mdsmap", | ||
233 | }; | 234 | }; |
234 | 235 | ||
235 | /* | 236 | /* |
@@ -1193,6 +1194,7 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, | |||
1193 | case CEPH_MSG_MON_MAP: | 1194 | case CEPH_MSG_MON_MAP: |
1194 | case CEPH_MSG_MDS_MAP: | 1195 | case CEPH_MSG_MDS_MAP: |
1195 | case CEPH_MSG_OSD_MAP: | 1196 | case CEPH_MSG_OSD_MAP: |
1197 | case CEPH_MSG_FS_MAP_USER: | ||
1196 | m = ceph_msg_new(type, front_len, GFP_NOFS, false); | 1198 | m = ceph_msg_new(type, front_len, GFP_NOFS, false); |
1197 | if (!m) | 1199 | if (!m) |
1198 | return NULL; /* ENOMEM--return skip == 0 */ | 1200 | return NULL; /* ENOMEM--return skip == 0 */ |
diff --git a/net/ceph/msgpool.c b/net/ceph/msgpool.c index ddec1c10ac80..aaed59a47b1d 100644 --- a/net/ceph/msgpool.c +++ b/net/ceph/msgpool.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <linux/vmalloc.h> | 6 | #include <linux/vmalloc.h> |
7 | 7 | ||
8 | #include <linux/ceph/messenger.h> | ||
8 | #include <linux/ceph/msgpool.h> | 9 | #include <linux/ceph/msgpool.h> |
9 | 10 | ||
10 | static void *msgpool_alloc(gfp_t gfp_mask, void *arg) | 11 | static void *msgpool_alloc(gfp_t gfp_mask, void *arg) |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 89469592076c..b5ec09612ff7 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -387,7 +387,9 @@ static void target_copy(struct ceph_osd_request_target *dest, | |||
387 | static void target_destroy(struct ceph_osd_request_target *t) | 387 | static void target_destroy(struct ceph_osd_request_target *t) |
388 | { | 388 | { |
389 | ceph_oid_destroy(&t->base_oid); | 389 | ceph_oid_destroy(&t->base_oid); |
390 | ceph_oloc_destroy(&t->base_oloc); | ||
390 | ceph_oid_destroy(&t->target_oid); | 391 | ceph_oid_destroy(&t->target_oid); |
392 | ceph_oloc_destroy(&t->target_oloc); | ||
391 | } | 393 | } |
392 | 394 | ||
393 | /* | 395 | /* |
@@ -533,6 +535,11 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | |||
533 | } | 535 | } |
534 | EXPORT_SYMBOL(ceph_osdc_alloc_request); | 536 | EXPORT_SYMBOL(ceph_osdc_alloc_request); |
535 | 537 | ||
538 | static int ceph_oloc_encoding_size(struct ceph_object_locator *oloc) | ||
539 | { | ||
540 | return 8 + 4 + 4 + 4 + (oloc->pool_ns ? oloc->pool_ns->len : 0); | ||
541 | } | ||
542 | |||
536 | int ceph_osdc_alloc_messages(struct ceph_osd_request *req, gfp_t gfp) | 543 | int ceph_osdc_alloc_messages(struct ceph_osd_request *req, gfp_t gfp) |
537 | { | 544 | { |
538 | struct ceph_osd_client *osdc = req->r_osdc; | 545 | struct ceph_osd_client *osdc = req->r_osdc; |
@@ -540,11 +547,13 @@ int ceph_osdc_alloc_messages(struct ceph_osd_request *req, gfp_t gfp) | |||
540 | int msg_size; | 547 | int msg_size; |
541 | 548 | ||
542 | WARN_ON(ceph_oid_empty(&req->r_base_oid)); | 549 | WARN_ON(ceph_oid_empty(&req->r_base_oid)); |
550 | WARN_ON(ceph_oloc_empty(&req->r_base_oloc)); | ||
543 | 551 | ||
544 | /* create request message */ | 552 | /* create request message */ |
545 | msg_size = 4 + 4 + 4; /* client_inc, osdmap_epoch, flags */ | 553 | msg_size = 4 + 4 + 4; /* client_inc, osdmap_epoch, flags */ |
546 | msg_size += 4 + 4 + 4 + 8; /* mtime, reassert_version */ | 554 | msg_size += 4 + 4 + 4 + 8; /* mtime, reassert_version */ |
547 | msg_size += 2 + 4 + 8 + 4 + 4; /* oloc */ | 555 | msg_size += CEPH_ENCODING_START_BLK_LEN + |
556 | ceph_oloc_encoding_size(&req->r_base_oloc); /* oloc */ | ||
548 | msg_size += 1 + 8 + 4 + 4; /* pgid */ | 557 | msg_size += 1 + 8 + 4 + 4; /* pgid */ |
549 | msg_size += 4 + req->r_base_oid.name_len; /* oid */ | 558 | msg_size += 4 + req->r_base_oid.name_len; /* oid */ |
550 | msg_size += 2 + req->r_num_ops * sizeof(struct ceph_osd_op); | 559 | msg_size += 2 + req->r_num_ops * sizeof(struct ceph_osd_op); |
@@ -932,7 +941,7 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, | |||
932 | if (opcode == CEPH_OSD_OP_CREATE || opcode == CEPH_OSD_OP_DELETE) { | 941 | if (opcode == CEPH_OSD_OP_CREATE || opcode == CEPH_OSD_OP_DELETE) { |
933 | osd_req_op_init(req, which, opcode, 0); | 942 | osd_req_op_init(req, which, opcode, 0); |
934 | } else { | 943 | } else { |
935 | u32 object_size = le32_to_cpu(layout->fl_object_size); | 944 | u32 object_size = layout->object_size; |
936 | u32 object_base = off - objoff; | 945 | u32 object_base = off - objoff; |
937 | if (!(truncate_seq == 1 && truncate_size == -1ULL)) { | 946 | if (!(truncate_seq == 1 && truncate_size == -1ULL)) { |
938 | if (truncate_size <= object_base) { | 947 | if (truncate_size <= object_base) { |
@@ -948,7 +957,8 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, | |||
948 | } | 957 | } |
949 | 958 | ||
950 | req->r_flags = flags; | 959 | req->r_flags = flags; |
951 | req->r_base_oloc.pool = ceph_file_layout_pg_pool(*layout); | 960 | req->r_base_oloc.pool = layout->pool_id; |
961 | req->r_base_oloc.pool_ns = ceph_try_get_string(layout->pool_ns); | ||
952 | ceph_oid_printf(&req->r_base_oid, "%llx.%08llx", vino.ino, objnum); | 962 | ceph_oid_printf(&req->r_base_oid, "%llx.%08llx", vino.ino, objnum); |
953 | 963 | ||
954 | req->r_snapid = vino.snap; | 964 | req->r_snapid = vino.snap; |
@@ -1489,12 +1499,16 @@ static void encode_request(struct ceph_osd_request *req, struct ceph_msg *msg) | |||
1489 | p += sizeof(req->r_replay_version); | 1499 | p += sizeof(req->r_replay_version); |
1490 | 1500 | ||
1491 | /* oloc */ | 1501 | /* oloc */ |
1492 | ceph_encode_8(&p, 4); | 1502 | ceph_start_encoding(&p, 5, 4, |
1493 | ceph_encode_8(&p, 4); | 1503 | ceph_oloc_encoding_size(&req->r_t.target_oloc)); |
1494 | ceph_encode_32(&p, 8 + 4 + 4); | ||
1495 | ceph_encode_64(&p, req->r_t.target_oloc.pool); | 1504 | ceph_encode_64(&p, req->r_t.target_oloc.pool); |
1496 | ceph_encode_32(&p, -1); /* preferred */ | 1505 | ceph_encode_32(&p, -1); /* preferred */ |
1497 | ceph_encode_32(&p, 0); /* key len */ | 1506 | ceph_encode_32(&p, 0); /* key len */ |
1507 | if (req->r_t.target_oloc.pool_ns) | ||
1508 | ceph_encode_string(&p, end, req->r_t.target_oloc.pool_ns->str, | ||
1509 | req->r_t.target_oloc.pool_ns->len); | ||
1510 | else | ||
1511 | ceph_encode_32(&p, 0); | ||
1498 | 1512 | ||
1499 | /* pgid */ | 1513 | /* pgid */ |
1500 | ceph_encode_8(&p, 1); | 1514 | ceph_encode_8(&p, 1); |
@@ -2594,9 +2608,22 @@ static int ceph_oloc_decode(void **p, void *end, | |||
2594 | } | 2608 | } |
2595 | 2609 | ||
2596 | if (struct_v >= 5) { | 2610 | if (struct_v >= 5) { |
2611 | bool changed = false; | ||
2612 | |||
2597 | len = ceph_decode_32(p); | 2613 | len = ceph_decode_32(p); |
2598 | if (len > 0) { | 2614 | if (len > 0) { |
2599 | pr_warn("ceph_object_locator::nspace is set\n"); | 2615 | ceph_decode_need(p, end, len, e_inval); |
2616 | if (!oloc->pool_ns || | ||
2617 | ceph_compare_string(oloc->pool_ns, *p, len)) | ||
2618 | changed = true; | ||
2619 | *p += len; | ||
2620 | } else { | ||
2621 | if (oloc->pool_ns) | ||
2622 | changed = true; | ||
2623 | } | ||
2624 | if (changed) { | ||
2625 | /* redirect changes namespace */ | ||
2626 | pr_warn("ceph_object_locator::nspace is changed\n"); | ||
2600 | goto e_inval; | 2627 | goto e_inval; |
2601 | } | 2628 | } |
2602 | } | 2629 | } |
@@ -2806,7 +2833,9 @@ static void handle_reply(struct ceph_osd *osd, struct ceph_msg *msg) | |||
2806 | goto out_unlock_session; | 2833 | goto out_unlock_session; |
2807 | } | 2834 | } |
2808 | 2835 | ||
2836 | m.redirect.oloc.pool_ns = req->r_t.target_oloc.pool_ns; | ||
2809 | ret = decode_MOSDOpReply(msg, &m); | 2837 | ret = decode_MOSDOpReply(msg, &m); |
2838 | m.redirect.oloc.pool_ns = NULL; | ||
2810 | if (ret) { | 2839 | if (ret) { |
2811 | pr_err("failed to decode MOSDOpReply for tid %llu: %d\n", | 2840 | pr_err("failed to decode MOSDOpReply for tid %llu: %d\n", |
2812 | req->r_tid, ret); | 2841 | req->r_tid, ret); |
@@ -2835,7 +2864,11 @@ static void handle_reply(struct ceph_osd *osd, struct ceph_msg *msg) | |||
2835 | unlink_request(osd, req); | 2864 | unlink_request(osd, req); |
2836 | mutex_unlock(&osd->lock); | 2865 | mutex_unlock(&osd->lock); |
2837 | 2866 | ||
2838 | ceph_oloc_copy(&req->r_t.target_oloc, &m.redirect.oloc); | 2867 | /* |
2868 | * Not ceph_oloc_copy() - changing pool_ns is not | ||
2869 | * supported. | ||
2870 | */ | ||
2871 | req->r_t.target_oloc.pool = m.redirect.oloc.pool; | ||
2839 | req->r_flags |= CEPH_OSD_FLAG_REDIRECTED; | 2872 | req->r_flags |= CEPH_OSD_FLAG_REDIRECTED; |
2840 | req->r_tid = 0; | 2873 | req->r_tid = 0; |
2841 | __submit_request(req, false); | 2874 | __submit_request(req, false); |
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 7e480bf75bcf..d2436880b305 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
@@ -1510,6 +1510,24 @@ bad: | |||
1510 | return ERR_PTR(err); | 1510 | return ERR_PTR(err); |
1511 | } | 1511 | } |
1512 | 1512 | ||
1513 | void ceph_oloc_copy(struct ceph_object_locator *dest, | ||
1514 | const struct ceph_object_locator *src) | ||
1515 | { | ||
1516 | WARN_ON(!ceph_oloc_empty(dest)); | ||
1517 | WARN_ON(dest->pool_ns); /* empty() only covers ->pool */ | ||
1518 | |||
1519 | dest->pool = src->pool; | ||
1520 | if (src->pool_ns) | ||
1521 | dest->pool_ns = ceph_get_string(src->pool_ns); | ||
1522 | } | ||
1523 | EXPORT_SYMBOL(ceph_oloc_copy); | ||
1524 | |||
1525 | void ceph_oloc_destroy(struct ceph_object_locator *oloc) | ||
1526 | { | ||
1527 | ceph_put_string(oloc->pool_ns); | ||
1528 | } | ||
1529 | EXPORT_SYMBOL(ceph_oloc_destroy); | ||
1530 | |||
1513 | void ceph_oid_copy(struct ceph_object_id *dest, | 1531 | void ceph_oid_copy(struct ceph_object_id *dest, |
1514 | const struct ceph_object_id *src) | 1532 | const struct ceph_object_id *src) |
1515 | { | 1533 | { |
@@ -1770,9 +1788,9 @@ int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, | |||
1770 | u64 *ono, | 1788 | u64 *ono, |
1771 | u64 *oxoff, u64 *oxlen) | 1789 | u64 *oxoff, u64 *oxlen) |
1772 | { | 1790 | { |
1773 | u32 osize = le32_to_cpu(layout->fl_object_size); | 1791 | u32 osize = layout->object_size; |
1774 | u32 su = le32_to_cpu(layout->fl_stripe_unit); | 1792 | u32 su = layout->stripe_unit; |
1775 | u32 sc = le32_to_cpu(layout->fl_stripe_count); | 1793 | u32 sc = layout->stripe_count; |
1776 | u32 bl, stripeno, stripepos, objsetno; | 1794 | u32 bl, stripeno, stripepos, objsetno; |
1777 | u32 su_per_object; | 1795 | u32 su_per_object; |
1778 | u64 t, su_offset; | 1796 | u64 t, su_offset; |
@@ -1844,12 +1862,34 @@ int ceph_object_locator_to_pg(struct ceph_osdmap *osdmap, | |||
1844 | if (!pi) | 1862 | if (!pi) |
1845 | return -ENOENT; | 1863 | return -ENOENT; |
1846 | 1864 | ||
1847 | raw_pgid->pool = oloc->pool; | 1865 | if (!oloc->pool_ns) { |
1848 | raw_pgid->seed = ceph_str_hash(pi->object_hash, oid->name, | 1866 | raw_pgid->pool = oloc->pool; |
1849 | oid->name_len); | 1867 | raw_pgid->seed = ceph_str_hash(pi->object_hash, oid->name, |
1850 | 1868 | oid->name_len); | |
1851 | dout("%s %s -> raw_pgid %llu.%x\n", __func__, oid->name, | 1869 | dout("%s %s -> raw_pgid %llu.%x\n", __func__, oid->name, |
1852 | raw_pgid->pool, raw_pgid->seed); | 1870 | raw_pgid->pool, raw_pgid->seed); |
1871 | } else { | ||
1872 | char stack_buf[256]; | ||
1873 | char *buf = stack_buf; | ||
1874 | int nsl = oloc->pool_ns->len; | ||
1875 | size_t total = nsl + 1 + oid->name_len; | ||
1876 | |||
1877 | if (total > sizeof(stack_buf)) { | ||
1878 | buf = kmalloc(total, GFP_NOIO); | ||
1879 | if (!buf) | ||
1880 | return -ENOMEM; | ||
1881 | } | ||
1882 | memcpy(buf, oloc->pool_ns->str, nsl); | ||
1883 | buf[nsl] = '\037'; | ||
1884 | memcpy(buf + nsl + 1, oid->name, oid->name_len); | ||
1885 | raw_pgid->pool = oloc->pool; | ||
1886 | raw_pgid->seed = ceph_str_hash(pi->object_hash, buf, total); | ||
1887 | if (buf != stack_buf) | ||
1888 | kfree(buf); | ||
1889 | dout("%s %s ns %.*s -> raw_pgid %llu.%x\n", __func__, | ||
1890 | oid->name, nsl, oloc->pool_ns->str, | ||
1891 | raw_pgid->pool, raw_pgid->seed); | ||
1892 | } | ||
1853 | return 0; | 1893 | return 0; |
1854 | } | 1894 | } |
1855 | EXPORT_SYMBOL(ceph_object_locator_to_pg); | 1895 | EXPORT_SYMBOL(ceph_object_locator_to_pg); |
diff --git a/net/ceph/string_table.c b/net/ceph/string_table.c new file mode 100644 index 000000000000..ca53c8319209 --- /dev/null +++ b/net/ceph/string_table.c | |||
@@ -0,0 +1,111 @@ | |||
1 | #include <linux/slab.h> | ||
2 | #include <linux/gfp.h> | ||
3 | #include <linux/string.h> | ||
4 | #include <linux/spinlock.h> | ||
5 | #include <linux/ceph/string_table.h> | ||
6 | |||
7 | static DEFINE_SPINLOCK(string_tree_lock); | ||
8 | static struct rb_root string_tree = RB_ROOT; | ||
9 | |||
10 | struct ceph_string *ceph_find_or_create_string(const char* str, size_t len) | ||
11 | { | ||
12 | struct ceph_string *cs, *exist; | ||
13 | struct rb_node **p, *parent; | ||
14 | int ret; | ||
15 | |||
16 | exist = NULL; | ||
17 | spin_lock(&string_tree_lock); | ||
18 | p = &string_tree.rb_node; | ||
19 | while (*p) { | ||
20 | exist = rb_entry(*p, struct ceph_string, node); | ||
21 | ret = ceph_compare_string(exist, str, len); | ||
22 | if (ret > 0) | ||
23 | p = &(*p)->rb_left; | ||
24 | else if (ret < 0) | ||
25 | p = &(*p)->rb_right; | ||
26 | else | ||
27 | break; | ||
28 | exist = NULL; | ||
29 | } | ||
30 | if (exist && !kref_get_unless_zero(&exist->kref)) { | ||
31 | rb_erase(&exist->node, &string_tree); | ||
32 | RB_CLEAR_NODE(&exist->node); | ||
33 | exist = NULL; | ||
34 | } | ||
35 | spin_unlock(&string_tree_lock); | ||
36 | if (exist) | ||
37 | return exist; | ||
38 | |||
39 | cs = kmalloc(sizeof(*cs) + len + 1, GFP_NOFS); | ||
40 | if (!cs) | ||
41 | return NULL; | ||
42 | |||
43 | kref_init(&cs->kref); | ||
44 | cs->len = len; | ||
45 | memcpy(cs->str, str, len); | ||
46 | cs->str[len] = 0; | ||
47 | |||
48 | retry: | ||
49 | exist = NULL; | ||
50 | parent = NULL; | ||
51 | p = &string_tree.rb_node; | ||
52 | spin_lock(&string_tree_lock); | ||
53 | while (*p) { | ||
54 | parent = *p; | ||
55 | exist = rb_entry(*p, struct ceph_string, node); | ||
56 | ret = ceph_compare_string(exist, str, len); | ||
57 | if (ret > 0) | ||
58 | p = &(*p)->rb_left; | ||
59 | else if (ret < 0) | ||
60 | p = &(*p)->rb_right; | ||
61 | else | ||
62 | break; | ||
63 | exist = NULL; | ||
64 | } | ||
65 | ret = 0; | ||
66 | if (!exist) { | ||
67 | rb_link_node(&cs->node, parent, p); | ||
68 | rb_insert_color(&cs->node, &string_tree); | ||
69 | } else if (!kref_get_unless_zero(&exist->kref)) { | ||
70 | rb_erase(&exist->node, &string_tree); | ||
71 | RB_CLEAR_NODE(&exist->node); | ||
72 | ret = -EAGAIN; | ||
73 | } | ||
74 | spin_unlock(&string_tree_lock); | ||
75 | if (ret == -EAGAIN) | ||
76 | goto retry; | ||
77 | |||
78 | if (exist) { | ||
79 | kfree(cs); | ||
80 | cs = exist; | ||
81 | } | ||
82 | |||
83 | return cs; | ||
84 | } | ||
85 | EXPORT_SYMBOL(ceph_find_or_create_string); | ||
86 | |||
87 | static void ceph_free_string(struct rcu_head *head) | ||
88 | { | ||
89 | struct ceph_string *cs = container_of(head, struct ceph_string, rcu); | ||
90 | kfree(cs); | ||
91 | } | ||
92 | |||
93 | void ceph_release_string(struct kref *ref) | ||
94 | { | ||
95 | struct ceph_string *cs = container_of(ref, struct ceph_string, kref); | ||
96 | |||
97 | spin_lock(&string_tree_lock); | ||
98 | if (!RB_EMPTY_NODE(&cs->node)) { | ||
99 | rb_erase(&cs->node, &string_tree); | ||
100 | RB_CLEAR_NODE(&cs->node); | ||
101 | } | ||
102 | spin_unlock(&string_tree_lock); | ||
103 | |||
104 | call_rcu(&cs->rcu, ceph_free_string); | ||
105 | } | ||
106 | EXPORT_SYMBOL(ceph_release_string); | ||
107 | |||
108 | bool ceph_strings_empty(void) | ||
109 | { | ||
110 | return RB_EMPTY_ROOT(&string_tree); | ||
111 | } | ||