Commit 6c073a7ee250118b8be3a2379c96fd7f78382b06
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: rbd: fix safety of rbd_put_client() rbd: fix a memory leak in rbd_get_client() ceph: create a new session lock to avoid lock inversion ceph: fix length validation in parse_reply_info() ceph: initialize client debugfs outside of monc->mutex ceph: change "ceph.layout" xattr to be "ceph.file.layout"
Showing 8 changed files Side-by-side Diff
drivers/block/rbd.c
... | ... | @@ -380,6 +380,7 @@ |
380 | 380 | rbdc = __rbd_client_find(opt); |
381 | 381 | if (rbdc) { |
382 | 382 | ceph_destroy_options(opt); |
383 | + kfree(rbd_opts); | |
383 | 384 | |
384 | 385 | /* using an existing client */ |
385 | 386 | kref_get(&rbdc->kref); |
386 | 387 | |
387 | 388 | |
... | ... | @@ -406,15 +407,15 @@ |
406 | 407 | |
407 | 408 | /* |
408 | 409 | * Destroy ceph client |
410 | + * | |
411 | + * Caller must hold node_lock. | |
409 | 412 | */ |
410 | 413 | static void rbd_client_release(struct kref *kref) |
411 | 414 | { |
412 | 415 | struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref); |
413 | 416 | |
414 | 417 | dout("rbd_release_client %p\n", rbdc); |
415 | - spin_lock(&node_lock); | |
416 | 418 | list_del(&rbdc->node); |
417 | - spin_unlock(&node_lock); | |
418 | 419 | |
419 | 420 | ceph_destroy_client(rbdc->client); |
420 | 421 | kfree(rbdc->rbd_opts); |
421 | 422 | |
... | ... | @@ -427,7 +428,9 @@ |
427 | 428 | */ |
428 | 429 | static void rbd_put_client(struct rbd_device *rbd_dev) |
429 | 430 | { |
431 | + spin_lock(&node_lock); | |
430 | 432 | kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); |
433 | + spin_unlock(&node_lock); | |
431 | 434 | rbd_dev->rbd_client = NULL; |
432 | 435 | rbd_dev->client = NULL; |
433 | 436 | } |
fs/ceph/caps.c
... | ... | @@ -641,10 +641,10 @@ |
641 | 641 | unsigned long ttl; |
642 | 642 | u32 gen; |
643 | 643 | |
644 | - spin_lock(&cap->session->s_cap_lock); | |
644 | + spin_lock(&cap->session->s_gen_ttl_lock); | |
645 | 645 | gen = cap->session->s_cap_gen; |
646 | 646 | ttl = cap->session->s_cap_ttl; |
647 | - spin_unlock(&cap->session->s_cap_lock); | |
647 | + spin_unlock(&cap->session->s_gen_ttl_lock); | |
648 | 648 | |
649 | 649 | if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) { |
650 | 650 | dout("__cap_is_valid %p cap %p issued %s " |
fs/ceph/dir.c
... | ... | @@ -975,10 +975,10 @@ |
975 | 975 | di = ceph_dentry(dentry); |
976 | 976 | if (di->lease_session) { |
977 | 977 | s = di->lease_session; |
978 | - spin_lock(&s->s_cap_lock); | |
978 | + spin_lock(&s->s_gen_ttl_lock); | |
979 | 979 | gen = s->s_cap_gen; |
980 | 980 | ttl = s->s_cap_ttl; |
981 | - spin_unlock(&s->s_cap_lock); | |
981 | + spin_unlock(&s->s_gen_ttl_lock); | |
982 | 982 | |
983 | 983 | if (di->lease_gen == gen && |
984 | 984 | time_before(jiffies, dentry->d_time) && |
fs/ceph/mds_client.c
... | ... | @@ -262,6 +262,7 @@ |
262 | 262 | /* trace */ |
263 | 263 | ceph_decode_32_safe(&p, end, len, bad); |
264 | 264 | if (len > 0) { |
265 | + ceph_decode_need(&p, end, len, bad); | |
265 | 266 | err = parse_reply_info_trace(&p, p+len, info, features); |
266 | 267 | if (err < 0) |
267 | 268 | goto out_bad; |
... | ... | @@ -270,6 +271,7 @@ |
270 | 271 | /* extra */ |
271 | 272 | ceph_decode_32_safe(&p, end, len, bad); |
272 | 273 | if (len > 0) { |
274 | + ceph_decode_need(&p, end, len, bad); | |
273 | 275 | err = parse_reply_info_extra(&p, p+len, info, features); |
274 | 276 | if (err < 0) |
275 | 277 | goto out_bad; |
276 | 278 | |
... | ... | @@ -398,9 +400,11 @@ |
398 | 400 | s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; |
399 | 401 | s->s_con.peer_name.num = cpu_to_le64(mds); |
400 | 402 | |
401 | - spin_lock_init(&s->s_cap_lock); | |
403 | + spin_lock_init(&s->s_gen_ttl_lock); | |
402 | 404 | s->s_cap_gen = 0; |
403 | 405 | s->s_cap_ttl = 0; |
406 | + | |
407 | + spin_lock_init(&s->s_cap_lock); | |
404 | 408 | s->s_renew_requested = 0; |
405 | 409 | s->s_renew_seq = 0; |
406 | 410 | INIT_LIST_HEAD(&s->s_caps); |
407 | 411 | |
... | ... | @@ -2326,10 +2330,10 @@ |
2326 | 2330 | case CEPH_SESSION_STALE: |
2327 | 2331 | pr_info("mds%d caps went stale, renewing\n", |
2328 | 2332 | session->s_mds); |
2329 | - spin_lock(&session->s_cap_lock); | |
2333 | + spin_lock(&session->s_gen_ttl_lock); | |
2330 | 2334 | session->s_cap_gen++; |
2331 | 2335 | session->s_cap_ttl = 0; |
2332 | - spin_unlock(&session->s_cap_lock); | |
2336 | + spin_unlock(&session->s_gen_ttl_lock); | |
2333 | 2337 | send_renew_caps(mdsc, session); |
2334 | 2338 | break; |
2335 | 2339 |
fs/ceph/mds_client.h
... | ... | @@ -117,10 +117,13 @@ |
117 | 117 | void *s_authorizer_buf, *s_authorizer_reply_buf; |
118 | 118 | size_t s_authorizer_buf_len, s_authorizer_reply_buf_len; |
119 | 119 | |
120 | - /* protected by s_cap_lock */ | |
121 | - spinlock_t s_cap_lock; | |
120 | + /* protected by s_gen_ttl_lock */ | |
121 | + spinlock_t s_gen_ttl_lock; | |
122 | 122 | u32 s_cap_gen; /* inc each time we get mds stale msg */ |
123 | 123 | unsigned long s_cap_ttl; /* when session caps expire */ |
124 | + | |
125 | + /* protected by s_cap_lock */ | |
126 | + spinlock_t s_cap_lock; | |
124 | 127 | struct list_head s_caps; /* all caps issued by this session */ |
125 | 128 | int s_nr_caps, s_trim_caps; |
126 | 129 | int s_num_cap_releases; |
fs/ceph/xattr.c
... | ... | @@ -111,8 +111,10 @@ |
111 | 111 | } |
112 | 112 | |
113 | 113 | static struct ceph_vxattr_cb ceph_file_vxattrs[] = { |
114 | + { true, "ceph.file.layout", ceph_vxattrcb_layout}, | |
115 | + /* The following extended attribute name is deprecated */ | |
114 | 116 | { true, "ceph.layout", ceph_vxattrcb_layout}, |
115 | - { NULL, NULL } | |
117 | + { true, NULL, NULL } | |
116 | 118 | }; |
117 | 119 | |
118 | 120 | static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode) |
net/ceph/ceph_common.c
net/ceph/mon_client.c
... | ... | @@ -8,8 +8,8 @@ |
8 | 8 | |
9 | 9 | #include <linux/ceph/mon_client.h> |
10 | 10 | #include <linux/ceph/libceph.h> |
11 | +#include <linux/ceph/debugfs.h> | |
11 | 12 | #include <linux/ceph/decode.h> |
12 | - | |
13 | 13 | #include <linux/ceph/auth.h> |
14 | 14 | |
15 | 15 | /* |
16 | 16 | |
... | ... | @@ -340,8 +340,19 @@ |
340 | 340 | client->monc.monmap = monmap; |
341 | 341 | kfree(old); |
342 | 342 | |
343 | + if (!client->have_fsid) { | |
344 | + client->have_fsid = true; | |
345 | + mutex_unlock(&monc->mutex); | |
346 | + /* | |
347 | + * do debugfs initialization without mutex to avoid | |
348 | + * creating a locking dependency | |
349 | + */ | |
350 | + ceph_debugfs_client_init(client); | |
351 | + goto out_unlocked; | |
352 | + } | |
343 | 353 | out: |
344 | 354 | mutex_unlock(&monc->mutex); |
355 | +out_unlocked: | |
345 | 356 | wake_up_all(&client->auth_wq); |
346 | 357 | } |
347 | 358 |