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

+1
fs/ceph/debugfs.c
··· 201 201 int err = -ENOMEM; 202 202 203 203 dout("ceph_fs_debugfs_init\n"); 204 + BUG_ON(!fsc->client->debugfs_dir); 204 205 fsc->debugfs_congestion_kb = 205 206 debugfs_create_file("writeback_congestion_kb", 206 207 0600,
+10 -5
fs/ceph/inode.c
··· 992 992 if (rinfo->head->is_dentry) { 993 993 struct inode *dir = req->r_locked_dir; 994 994 995 - err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, 996 - session, req->r_request_started, -1, 997 - &req->r_caps_reservation); 998 - if (err < 0) 999 - return err; 995 + if (dir) { 996 + err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, 997 + session, req->r_request_started, -1, 998 + &req->r_caps_reservation); 999 + if (err < 0) 1000 + return err; 1001 + } else { 1002 + WARN_ON_ONCE(1); 1003 + } 1000 1004 } 1001 1005 1002 1006 /* ··· 1008 1004 * will have trouble splicing in the virtual snapdir later 1009 1005 */ 1010 1006 if (rinfo->head->is_dentry && !req->r_aborted && 1007 + req->r_locked_dir && 1011 1008 (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, 1012 1009 fsc->mount_options->snapdir_name, 1013 1010 req->r_dentry->d_name.len))) {
+2 -1
fs/ceph/ioctl.c
··· 42 42 /* validate striping parameters */ 43 43 if ((l->object_size & ~PAGE_MASK) || 44 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 47 return -EINVAL; 47 48 48 49 /* make sure it's a valid data pool */
-1
net/ceph/ceph_common.c
··· 84 84 return -1; 85 85 } 86 86 } else { 87 - pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); 88 87 memcpy(&client->fsid, fsid, sizeof(*fsid)); 89 88 } 90 89 return 0;
+4
net/ceph/debugfs.c
··· 189 189 snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, 190 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 195 client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); 193 196 if (!client->debugfs_dir) 194 197 goto out; ··· 237 234 238 235 void ceph_debugfs_client_cleanup(struct ceph_client *client) 239 236 { 237 + dout("ceph_debugfs_client_cleanup %p\n", client); 240 238 debugfs_remove(client->debugfs_osdmap); 241 239 debugfs_remove(client->debugfs_monmap); 242 240 debugfs_remove(client->osdc.debugfs_file);
+9 -2
net/ceph/messenger.c
··· 915 915 con->out_connect.authorizer_len = auth ? 916 916 cpu_to_le32(auth->authorizer_buf_len) : 0; 917 917 918 - con_out_kvec_reset(con); 919 918 con_out_kvec_add(con, sizeof (con->out_connect), 920 919 &con->out_connect); 921 920 if (auth && auth->authorizer_buf_len) ··· 1556 1557 return -1; 1557 1558 } 1558 1559 con->auth_retry = 1; 1560 + con_out_kvec_reset(con); 1559 1561 ret = prepare_write_connect(con); 1560 1562 if (ret < 0) 1561 1563 return ret; ··· 1577 1577 ENTITY_NAME(con->peer_name), 1578 1578 ceph_pr_addr(&con->peer_addr.in_addr)); 1579 1579 reset_connection(con); 1580 + con_out_kvec_reset(con); 1580 1581 ret = prepare_write_connect(con); 1581 1582 if (ret < 0) 1582 1583 return ret; ··· 1602 1601 le32_to_cpu(con->out_connect.connect_seq), 1603 1602 le32_to_cpu(con->in_reply.connect_seq)); 1604 1603 con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); 1604 + con_out_kvec_reset(con); 1605 1605 ret = prepare_write_connect(con); 1606 1606 if (ret < 0) 1607 1607 return ret; ··· 1619 1617 le32_to_cpu(con->in_reply.global_seq)); 1620 1618 get_global_seq(con->msgr, 1621 1619 le32_to_cpu(con->in_reply.global_seq)); 1620 + con_out_kvec_reset(con); 1622 1621 ret = prepare_write_connect(con); 1623 1622 if (ret < 0) 1624 1623 return ret; ··· 2138 2135 BUG_ON(con->state != CON_STATE_CONNECTING); 2139 2136 con->state = CON_STATE_NEGOTIATING; 2140 2137 2141 - /* Banner is good, exchange connection info */ 2138 + /* 2139 + * Received banner is good, exchange connection info. 2140 + * Do not reset out_kvec, as sending our banner raced 2141 + * with receiving peer banner after connect completed. 2142 + */ 2142 2143 ret = prepare_write_connect(con); 2143 2144 if (ret < 0) 2144 2145 goto out;
+46 -5
net/ceph/mon_client.c
··· 311 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 325 * The monitor responds with mount ack indicate mount success. The 315 326 * included client ticket allows the client to talk to MDSs and OSDs. 316 327 */ ··· 331 320 struct ceph_client *client = monc->client; 332 321 struct ceph_monmap *monmap = NULL, *old = monc->monmap; 333 322 void *p, *end; 323 + int had_debugfs_info, init_debugfs = 0; 334 324 335 325 mutex_lock(&monc->mutex); 326 + 327 + had_debugfs_info = have_debugfs_info(monc); 336 328 337 329 dout("handle_monmap\n"); 338 330 p = msg->front.iov_base; ··· 358 344 359 345 if (!client->have_fsid) { 360 346 client->have_fsid = true; 347 + if (!had_debugfs_info && have_debugfs_info(monc)) { 348 + pr_info("client%lld fsid %pU\n", 349 + ceph_client_id(monc->client), 350 + &monc->client->fsid); 351 + init_debugfs = 1; 352 + } 361 353 mutex_unlock(&monc->mutex); 362 - /* 363 - * do debugfs initialization without mutex to avoid 364 - * creating a locking dependency 365 - */ 366 - ceph_debugfs_client_init(client); 354 + 355 + if (init_debugfs) { 356 + /* 357 + * do debugfs initialization without mutex to avoid 358 + * creating a locking dependency 359 + */ 360 + ceph_debugfs_client_init(monc->client); 361 + } 362 + 367 363 goto out_unlocked; 368 364 } 369 365 out: ··· 889 865 { 890 866 int ret; 891 867 int was_auth = 0; 868 + int had_debugfs_info, init_debugfs = 0; 892 869 893 870 mutex_lock(&monc->mutex); 871 + had_debugfs_info = have_debugfs_info(monc); 894 872 if (monc->auth->ops) 895 873 was_auth = monc->auth->ops->is_authenticated(monc->auth); 896 874 monc->pending_auth = 0; ··· 915 889 __send_subscribe(monc); 916 890 __resend_generic_request(monc); 917 891 } 892 + 893 + if (!had_debugfs_info && have_debugfs_info(monc)) { 894 + pr_info("client%lld fsid %pU\n", 895 + ceph_client_id(monc->client), 896 + &monc->client->fsid); 897 + init_debugfs = 1; 898 + } 918 899 mutex_unlock(&monc->mutex); 900 + 901 + if (init_debugfs) { 902 + /* 903 + * do debugfs initialization without mutex to avoid 904 + * creating a locking dependency 905 + */ 906 + ceph_debugfs_client_init(monc->client); 907 + } 919 908 } 920 909 921 910 static int __validate_auth(struct ceph_mon_client *monc)