diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-22 12:58:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-22 12:58:05 -0400 |
commit | f753c4ec151c5c385fa0508a29aa793dee966325 (patch) | |
tree | 934e16b1aaa6c16a73e0c1d94d36997ef7ad419d | |
parent | ad746be96941ddd2fb31fad7a629de7912051c8d (diff) | |
parent | 45f2e081f573526977abfa781a12728f83e9641f (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull ceph fixes from Sage Weil:
"Jim's fix closes a narrow race introduced with the msgr changes. One
fix resolves problems with debugfs initialization that Yan found when
multiple client instances are created (e.g., two clusters mounted, or
rbd + cephfs), another one fixes problems with mounting a nonexistent
server subdirectory, and the last one fixes a divide by zero error
from unsanitized ioctl input that Dan Carpenter found."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
ceph: avoid divide by zero in __validate_layout()
libceph: avoid truncation due to racing banners
ceph: tolerate (and warn on) extraneous dentry from mds
libceph: delay debugfs initialization until we learn global_id
-rw-r--r-- | fs/ceph/debugfs.c | 1 | ||||
-rw-r--r-- | fs/ceph/inode.c | 15 | ||||
-rw-r--r-- | fs/ceph/ioctl.c | 3 | ||||
-rw-r--r-- | net/ceph/ceph_common.c | 1 | ||||
-rw-r--r-- | net/ceph/debugfs.c | 4 | ||||
-rw-r--r-- | net/ceph/messenger.c | 11 | ||||
-rw-r--r-- | net/ceph/mon_client.c | 51 |
7 files changed, 72 insertions, 14 deletions
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index fb962efdace..6d59006bfa2 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c | |||
@@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) | |||
201 | int err = -ENOMEM; | 201 | int err = -ENOMEM; |
202 | 202 | ||
203 | dout("ceph_fs_debugfs_init\n"); | 203 | dout("ceph_fs_debugfs_init\n"); |
204 | BUG_ON(!fsc->client->debugfs_dir); | ||
204 | fsc->debugfs_congestion_kb = | 205 | fsc->debugfs_congestion_kb = |
205 | debugfs_create_file("writeback_congestion_kb", | 206 | debugfs_create_file("writeback_congestion_kb", |
206 | 0600, | 207 | 0600, |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 9fff9f3b17e..4b5762ef7c2 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -992,11 +992,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
992 | if (rinfo->head->is_dentry) { | 992 | if (rinfo->head->is_dentry) { |
993 | struct inode *dir = req->r_locked_dir; | 993 | struct inode *dir = req->r_locked_dir; |
994 | 994 | ||
995 | err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, | 995 | if (dir) { |
996 | session, req->r_request_started, -1, | 996 | err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, |
997 | &req->r_caps_reservation); | 997 | session, req->r_request_started, -1, |
998 | if (err < 0) | 998 | &req->r_caps_reservation); |
999 | return err; | 999 | if (err < 0) |
1000 | return err; | ||
1001 | } else { | ||
1002 | WARN_ON_ONCE(1); | ||
1003 | } | ||
1000 | } | 1004 | } |
1001 | 1005 | ||
1002 | /* | 1006 | /* |
@@ -1004,6 +1008,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
1004 | * will have trouble splicing in the virtual snapdir later | 1008 | * will have trouble splicing in the virtual snapdir later |
1005 | */ | 1009 | */ |
1006 | if (rinfo->head->is_dentry && !req->r_aborted && | 1010 | if (rinfo->head->is_dentry && !req->r_aborted && |
1011 | req->r_locked_dir && | ||
1007 | (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, | 1012 | (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, |
1008 | fsc->mount_options->snapdir_name, | 1013 | fsc->mount_options->snapdir_name, |
1009 | req->r_dentry->d_name.len))) { | 1014 | req->r_dentry->d_name.len))) { |
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c index 8e3fb69fbe6..1396ceb4679 100644 --- a/fs/ceph/ioctl.c +++ b/fs/ceph/ioctl.c | |||
@@ -42,7 +42,8 @@ static long __validate_layout(struct ceph_mds_client *mdsc, | |||
42 | /* validate striping parameters */ | 42 | /* validate striping parameters */ |
43 | if ((l->object_size & ~PAGE_MASK) || | 43 | if ((l->object_size & ~PAGE_MASK) || |
44 | (l->stripe_unit & ~PAGE_MASK) || | 44 | (l->stripe_unit & ~PAGE_MASK) || |
45 | ((unsigned)l->object_size % (unsigned)l->stripe_unit)) | 45 | (l->stripe_unit != 0 && |
46 | ((unsigned)l->object_size % (unsigned)l->stripe_unit))) | ||
46 | return -EINVAL; | 47 | return -EINVAL; |
47 | 48 | ||
48 | /* make sure it's a valid data pool */ | 49 | /* make sure it's a valid data pool */ |
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 69e38db28e5..a8020293f34 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -84,7 +84,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) | |||
84 | return -1; | 84 | return -1; |
85 | } | 85 | } |
86 | } else { | 86 | } else { |
87 | pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); | ||
88 | memcpy(&client->fsid, fsid, sizeof(*fsid)); | 87 | memcpy(&client->fsid, fsid, sizeof(*fsid)); |
89 | } | 88 | } |
90 | return 0; | 89 | return 0; |
diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index 54b531a0112..38b5dc1823d 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c | |||
@@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph_client *client) | |||
189 | snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, | 189 | snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, |
190 | client->monc.auth->global_id); | 190 | client->monc.auth->global_id); |
191 | 191 | ||
192 | dout("ceph_debugfs_client_init %p %s\n", client, name); | ||
193 | |||
194 | BUG_ON(client->debugfs_dir); | ||
192 | client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); | 195 | client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); |
193 | if (!client->debugfs_dir) | 196 | if (!client->debugfs_dir) |
194 | goto out; | 197 | goto out; |
@@ -234,6 +237,7 @@ out: | |||
234 | 237 | ||
235 | void ceph_debugfs_client_cleanup(struct ceph_client *client) | 238 | void ceph_debugfs_client_cleanup(struct ceph_client *client) |
236 | { | 239 | { |
240 | dout("ceph_debugfs_client_cleanup %p\n", client); | ||
237 | debugfs_remove(client->debugfs_osdmap); | 241 | debugfs_remove(client->debugfs_osdmap); |
238 | debugfs_remove(client->debugfs_monmap); | 242 | debugfs_remove(client->debugfs_monmap); |
239 | debugfs_remove(client->osdc.debugfs_file); | 243 | debugfs_remove(client->osdc.debugfs_file); |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index b9796750034..24c5eea8c45 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -915,7 +915,6 @@ static int prepare_write_connect(struct ceph_connection *con) | |||
915 | con->out_connect.authorizer_len = auth ? | 915 | con->out_connect.authorizer_len = auth ? |
916 | cpu_to_le32(auth->authorizer_buf_len) : 0; | 916 | cpu_to_le32(auth->authorizer_buf_len) : 0; |
917 | 917 | ||
918 | con_out_kvec_reset(con); | ||
919 | con_out_kvec_add(con, sizeof (con->out_connect), | 918 | con_out_kvec_add(con, sizeof (con->out_connect), |
920 | &con->out_connect); | 919 | &con->out_connect); |
921 | if (auth && auth->authorizer_buf_len) | 920 | if (auth && auth->authorizer_buf_len) |
@@ -1557,6 +1556,7 @@ static int process_connect(struct ceph_connection *con) | |||
1557 | return -1; | 1556 | return -1; |
1558 | } | 1557 | } |
1559 | con->auth_retry = 1; | 1558 | con->auth_retry = 1; |
1559 | con_out_kvec_reset(con); | ||
1560 | ret = prepare_write_connect(con); | 1560 | ret = prepare_write_connect(con); |
1561 | if (ret < 0) | 1561 | if (ret < 0) |
1562 | return ret; | 1562 | return ret; |
@@ -1577,6 +1577,7 @@ static int process_connect(struct ceph_connection *con) | |||
1577 | ENTITY_NAME(con->peer_name), | 1577 | ENTITY_NAME(con->peer_name), |
1578 | ceph_pr_addr(&con->peer_addr.in_addr)); | 1578 | ceph_pr_addr(&con->peer_addr.in_addr)); |
1579 | reset_connection(con); | 1579 | reset_connection(con); |
1580 | con_out_kvec_reset(con); | ||
1580 | ret = prepare_write_connect(con); | 1581 | ret = prepare_write_connect(con); |
1581 | if (ret < 0) | 1582 | if (ret < 0) |
1582 | return ret; | 1583 | return ret; |
@@ -1601,6 +1602,7 @@ static int process_connect(struct ceph_connection *con) | |||
1601 | le32_to_cpu(con->out_connect.connect_seq), | 1602 | le32_to_cpu(con->out_connect.connect_seq), |
1602 | le32_to_cpu(con->in_reply.connect_seq)); | 1603 | le32_to_cpu(con->in_reply.connect_seq)); |
1603 | con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); | 1604 | con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); |
1605 | con_out_kvec_reset(con); | ||
1604 | ret = prepare_write_connect(con); | 1606 | ret = prepare_write_connect(con); |
1605 | if (ret < 0) | 1607 | if (ret < 0) |
1606 | return ret; | 1608 | return ret; |
@@ -1617,6 +1619,7 @@ static int process_connect(struct ceph_connection *con) | |||
1617 | le32_to_cpu(con->in_reply.global_seq)); | 1619 | le32_to_cpu(con->in_reply.global_seq)); |
1618 | get_global_seq(con->msgr, | 1620 | get_global_seq(con->msgr, |
1619 | le32_to_cpu(con->in_reply.global_seq)); | 1621 | le32_to_cpu(con->in_reply.global_seq)); |
1622 | con_out_kvec_reset(con); | ||
1620 | ret = prepare_write_connect(con); | 1623 | ret = prepare_write_connect(con); |
1621 | if (ret < 0) | 1624 | if (ret < 0) |
1622 | return ret; | 1625 | return ret; |
@@ -2135,7 +2138,11 @@ more: | |||
2135 | BUG_ON(con->state != CON_STATE_CONNECTING); | 2138 | BUG_ON(con->state != CON_STATE_CONNECTING); |
2136 | con->state = CON_STATE_NEGOTIATING; | 2139 | con->state = CON_STATE_NEGOTIATING; |
2137 | 2140 | ||
2138 | /* Banner is good, exchange connection info */ | 2141 | /* |
2142 | * Received banner is good, exchange connection info. | ||
2143 | * Do not reset out_kvec, as sending our banner raced | ||
2144 | * with receiving peer banner after connect completed. | ||
2145 | */ | ||
2139 | ret = prepare_write_connect(con); | 2146 | ret = prepare_write_connect(con); |
2140 | if (ret < 0) | 2147 | if (ret < 0) |
2141 | goto out; | 2148 | goto out; |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 105d533b55f..900ea0f043f 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -311,6 +311,17 @@ int ceph_monc_open_session(struct ceph_mon_client *monc) | |||
311 | EXPORT_SYMBOL(ceph_monc_open_session); | 311 | EXPORT_SYMBOL(ceph_monc_open_session); |
312 | 312 | ||
313 | /* | 313 | /* |
314 | * We require the fsid and global_id in order to initialize our | ||
315 | * debugfs dir. | ||
316 | */ | ||
317 | static bool have_debugfs_info(struct ceph_mon_client *monc) | ||
318 | { | ||
319 | dout("have_debugfs_info fsid %d globalid %lld\n", | ||
320 | (int)monc->client->have_fsid, monc->auth->global_id); | ||
321 | return monc->client->have_fsid && monc->auth->global_id > 0; | ||
322 | } | ||
323 | |||
324 | /* | ||
314 | * The monitor responds with mount ack indicate mount success. The | 325 | * The monitor responds with mount ack indicate mount success. The |
315 | * included client ticket allows the client to talk to MDSs and OSDs. | 326 | * included client ticket allows the client to talk to MDSs and OSDs. |
316 | */ | 327 | */ |
@@ -320,9 +331,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, | |||
320 | struct ceph_client *client = monc->client; | 331 | struct ceph_client *client = monc->client; |
321 | struct ceph_monmap *monmap = NULL, *old = monc->monmap; | 332 | struct ceph_monmap *monmap = NULL, *old = monc->monmap; |
322 | void *p, *end; | 333 | void *p, *end; |
334 | int had_debugfs_info, init_debugfs = 0; | ||
323 | 335 | ||
324 | mutex_lock(&monc->mutex); | 336 | mutex_lock(&monc->mutex); |
325 | 337 | ||
338 | had_debugfs_info = have_debugfs_info(monc); | ||
339 | |||
326 | dout("handle_monmap\n"); | 340 | dout("handle_monmap\n"); |
327 | p = msg->front.iov_base; | 341 | p = msg->front.iov_base; |
328 | end = p + msg->front.iov_len; | 342 | end = p + msg->front.iov_len; |
@@ -344,12 +358,22 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, | |||
344 | 358 | ||
345 | if (!client->have_fsid) { | 359 | if (!client->have_fsid) { |
346 | client->have_fsid = true; | 360 | client->have_fsid = true; |
361 | if (!had_debugfs_info && have_debugfs_info(monc)) { | ||
362 | pr_info("client%lld fsid %pU\n", | ||
363 | ceph_client_id(monc->client), | ||
364 | &monc->client->fsid); | ||
365 | init_debugfs = 1; | ||
366 | } | ||
347 | mutex_unlock(&monc->mutex); | 367 | mutex_unlock(&monc->mutex); |
348 | /* | 368 | |
349 | * do debugfs initialization without mutex to avoid | 369 | if (init_debugfs) { |
350 | * creating a locking dependency | 370 | /* |
351 | */ | 371 | * do debugfs initialization without mutex to avoid |
352 | ceph_debugfs_client_init(client); | 372 | * creating a locking dependency |
373 | */ | ||
374 | ceph_debugfs_client_init(monc->client); | ||
375 | } | ||
376 | |||
353 | goto out_unlocked; | 377 | goto out_unlocked; |
354 | } | 378 | } |
355 | out: | 379 | out: |
@@ -865,8 +889,10 @@ static void handle_auth_reply(struct ceph_mon_client *monc, | |||
865 | { | 889 | { |
866 | int ret; | 890 | int ret; |
867 | int was_auth = 0; | 891 | int was_auth = 0; |
892 | int had_debugfs_info, init_debugfs = 0; | ||
868 | 893 | ||
869 | mutex_lock(&monc->mutex); | 894 | mutex_lock(&monc->mutex); |
895 | had_debugfs_info = have_debugfs_info(monc); | ||
870 | if (monc->auth->ops) | 896 | if (monc->auth->ops) |
871 | was_auth = monc->auth->ops->is_authenticated(monc->auth); | 897 | was_auth = monc->auth->ops->is_authenticated(monc->auth); |
872 | monc->pending_auth = 0; | 898 | monc->pending_auth = 0; |
@@ -889,7 +915,22 @@ static void handle_auth_reply(struct ceph_mon_client *monc, | |||
889 | __send_subscribe(monc); | 915 | __send_subscribe(monc); |
890 | __resend_generic_request(monc); | 916 | __resend_generic_request(monc); |
891 | } | 917 | } |
918 | |||
919 | if (!had_debugfs_info && have_debugfs_info(monc)) { | ||
920 | pr_info("client%lld fsid %pU\n", | ||
921 | ceph_client_id(monc->client), | ||
922 | &monc->client->fsid); | ||
923 | init_debugfs = 1; | ||
924 | } | ||
892 | mutex_unlock(&monc->mutex); | 925 | mutex_unlock(&monc->mutex); |
926 | |||
927 | if (init_debugfs) { | ||
928 | /* | ||
929 | * do debugfs initialization without mutex to avoid | ||
930 | * creating a locking dependency | ||
931 | */ | ||
932 | ceph_debugfs_client_init(monc->client); | ||
933 | } | ||
893 | } | 934 | } |
894 | 935 | ||
895 | static int __validate_auth(struct ceph_mon_client *monc) | 936 | static int __validate_auth(struct ceph_mon_client *monc) |