Commit 6c073a7ee250118b8be3a2379c96fd7f78382b06

Authored by Linus Torvalds

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

... ... @@ -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 }
... ... @@ -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 "
... ... @@ -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;
... ... @@ -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
... ... @@ -85,8 +85,6 @@
85 85 } else {
86 86 pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
87 87 memcpy(&client->fsid, fsid, sizeof(*fsid));
88   - ceph_debugfs_client_init(client);
89   - client->have_fsid = true;
90 88 }
91 89 return 0;
92 90 }
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