Commit f753c4ec authored by Linus Torvalds's avatar Linus Torvalds

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
parents ad746be9 45f2e081
...@@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) ...@@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
int err = -ENOMEM; int err = -ENOMEM;
dout("ceph_fs_debugfs_init\n"); dout("ceph_fs_debugfs_init\n");
BUG_ON(!fsc->client->debugfs_dir);
fsc->debugfs_congestion_kb = fsc->debugfs_congestion_kb =
debugfs_create_file("writeback_congestion_kb", debugfs_create_file("writeback_congestion_kb",
0600, 0600,
......
...@@ -992,11 +992,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, ...@@ -992,11 +992,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
if (rinfo->head->is_dentry) { if (rinfo->head->is_dentry) {
struct inode *dir = req->r_locked_dir; struct inode *dir = req->r_locked_dir;
if (dir) {
err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag,
session, req->r_request_started, -1, session, req->r_request_started, -1,
&req->r_caps_reservation); &req->r_caps_reservation);
if (err < 0) if (err < 0)
return err; return err;
} else {
WARN_ON_ONCE(1);
}
} }
/* /*
...@@ -1004,6 +1008,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, ...@@ -1004,6 +1008,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
* will have trouble splicing in the virtual snapdir later * will have trouble splicing in the virtual snapdir later
*/ */
if (rinfo->head->is_dentry && !req->r_aborted && if (rinfo->head->is_dentry && !req->r_aborted &&
req->r_locked_dir &&
(rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name,
fsc->mount_options->snapdir_name, fsc->mount_options->snapdir_name,
req->r_dentry->d_name.len))) { req->r_dentry->d_name.len))) {
......
...@@ -42,7 +42,8 @@ static long __validate_layout(struct ceph_mds_client *mdsc, ...@@ -42,7 +42,8 @@ static long __validate_layout(struct ceph_mds_client *mdsc,
/* validate striping parameters */ /* validate striping parameters */
if ((l->object_size & ~PAGE_MASK) || if ((l->object_size & ~PAGE_MASK) ||
(l->stripe_unit & ~PAGE_MASK) || (l->stripe_unit & ~PAGE_MASK) ||
((unsigned)l->object_size % (unsigned)l->stripe_unit)) (l->stripe_unit != 0 &&
((unsigned)l->object_size % (unsigned)l->stripe_unit)))
return -EINVAL; return -EINVAL;
/* make sure it's a valid data pool */ /* make sure it's a valid data pool */
......
...@@ -84,7 +84,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) ...@@ -84,7 +84,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
return -1; return -1;
} }
} else { } else {
pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
memcpy(&client->fsid, fsid, sizeof(*fsid)); memcpy(&client->fsid, fsid, sizeof(*fsid));
} }
return 0; return 0;
......
...@@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph_client *client) ...@@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph_client *client)
snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid,
client->monc.auth->global_id); client->monc.auth->global_id);
dout("ceph_debugfs_client_init %p %s\n", client, name);
BUG_ON(client->debugfs_dir);
client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);
if (!client->debugfs_dir) if (!client->debugfs_dir)
goto out; goto out;
...@@ -234,6 +237,7 @@ int ceph_debugfs_client_init(struct ceph_client *client) ...@@ -234,6 +237,7 @@ int ceph_debugfs_client_init(struct ceph_client *client)
void ceph_debugfs_client_cleanup(struct ceph_client *client) void ceph_debugfs_client_cleanup(struct ceph_client *client)
{ {
dout("ceph_debugfs_client_cleanup %p\n", client);
debugfs_remove(client->debugfs_osdmap); debugfs_remove(client->debugfs_osdmap);
debugfs_remove(client->debugfs_monmap); debugfs_remove(client->debugfs_monmap);
debugfs_remove(client->osdc.debugfs_file); debugfs_remove(client->osdc.debugfs_file);
......
...@@ -915,7 +915,6 @@ static int prepare_write_connect(struct ceph_connection *con) ...@@ -915,7 +915,6 @@ static int prepare_write_connect(struct ceph_connection *con)
con->out_connect.authorizer_len = auth ? con->out_connect.authorizer_len = auth ?
cpu_to_le32(auth->authorizer_buf_len) : 0; cpu_to_le32(auth->authorizer_buf_len) : 0;
con_out_kvec_reset(con);
con_out_kvec_add(con, sizeof (con->out_connect), con_out_kvec_add(con, sizeof (con->out_connect),
&con->out_connect); &con->out_connect);
if (auth && auth->authorizer_buf_len) if (auth && auth->authorizer_buf_len)
...@@ -1557,6 +1556,7 @@ static int process_connect(struct ceph_connection *con) ...@@ -1557,6 +1556,7 @@ static int process_connect(struct ceph_connection *con)
return -1; return -1;
} }
con->auth_retry = 1; con->auth_retry = 1;
con_out_kvec_reset(con);
ret = prepare_write_connect(con); ret = prepare_write_connect(con);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1577,6 +1577,7 @@ static int process_connect(struct ceph_connection *con) ...@@ -1577,6 +1577,7 @@ static int process_connect(struct ceph_connection *con)
ENTITY_NAME(con->peer_name), ENTITY_NAME(con->peer_name),
ceph_pr_addr(&con->peer_addr.in_addr)); ceph_pr_addr(&con->peer_addr.in_addr));
reset_connection(con); reset_connection(con);
con_out_kvec_reset(con);
ret = prepare_write_connect(con); ret = prepare_write_connect(con);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1601,6 +1602,7 @@ static int process_connect(struct ceph_connection *con) ...@@ -1601,6 +1602,7 @@ static int process_connect(struct ceph_connection *con)
le32_to_cpu(con->out_connect.connect_seq), le32_to_cpu(con->out_connect.connect_seq),
le32_to_cpu(con->in_reply.connect_seq)); le32_to_cpu(con->in_reply.connect_seq));
con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); con->connect_seq = le32_to_cpu(con->in_reply.connect_seq);
con_out_kvec_reset(con);
ret = prepare_write_connect(con); ret = prepare_write_connect(con);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1617,6 +1619,7 @@ static int process_connect(struct ceph_connection *con) ...@@ -1617,6 +1619,7 @@ static int process_connect(struct ceph_connection *con)
le32_to_cpu(con->in_reply.global_seq)); le32_to_cpu(con->in_reply.global_seq));
get_global_seq(con->msgr, get_global_seq(con->msgr,
le32_to_cpu(con->in_reply.global_seq)); le32_to_cpu(con->in_reply.global_seq));
con_out_kvec_reset(con);
ret = prepare_write_connect(con); ret = prepare_write_connect(con);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -2135,7 +2138,11 @@ static int try_read(struct ceph_connection *con) ...@@ -2135,7 +2138,11 @@ static int try_read(struct ceph_connection *con)
BUG_ON(con->state != CON_STATE_CONNECTING); BUG_ON(con->state != CON_STATE_CONNECTING);
con->state = CON_STATE_NEGOTIATING; con->state = CON_STATE_NEGOTIATING;
/* Banner is good, exchange connection info */ /*
* Received banner is good, exchange connection info.
* Do not reset out_kvec, as sending our banner raced
* with receiving peer banner after connect completed.
*/
ret = prepare_write_connect(con); ret = prepare_write_connect(con);
if (ret < 0) if (ret < 0)
goto out; goto out;
......
...@@ -310,6 +310,17 @@ int ceph_monc_open_session(struct ceph_mon_client *monc) ...@@ -310,6 +310,17 @@ int ceph_monc_open_session(struct ceph_mon_client *monc)
} }
EXPORT_SYMBOL(ceph_monc_open_session); EXPORT_SYMBOL(ceph_monc_open_session);
/*
* We require the fsid and global_id in order to initialize our
* debugfs dir.
*/
static bool have_debugfs_info(struct ceph_mon_client *monc)
{
dout("have_debugfs_info fsid %d globalid %lld\n",
(int)monc->client->have_fsid, monc->auth->global_id);
return monc->client->have_fsid && monc->auth->global_id > 0;
}
/* /*
* The monitor responds with mount ack indicate mount success. The * The monitor responds with mount ack indicate mount success. The
* included client ticket allows the client to talk to MDSs and OSDs. * included client ticket allows the client to talk to MDSs and OSDs.
...@@ -320,9 +331,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, ...@@ -320,9 +331,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
struct ceph_client *client = monc->client; struct ceph_client *client = monc->client;
struct ceph_monmap *monmap = NULL, *old = monc->monmap; struct ceph_monmap *monmap = NULL, *old = monc->monmap;
void *p, *end; void *p, *end;
int had_debugfs_info, init_debugfs = 0;
mutex_lock(&monc->mutex); mutex_lock(&monc->mutex);
had_debugfs_info = have_debugfs_info(monc);
dout("handle_monmap\n"); dout("handle_monmap\n");
p = msg->front.iov_base; p = msg->front.iov_base;
end = p + msg->front.iov_len; end = p + msg->front.iov_len;
...@@ -344,12 +358,22 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, ...@@ -344,12 +358,22 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
if (!client->have_fsid) { if (!client->have_fsid) {
client->have_fsid = true; client->have_fsid = true;
if (!had_debugfs_info && have_debugfs_info(monc)) {
pr_info("client%lld fsid %pU\n",
ceph_client_id(monc->client),
&monc->client->fsid);
init_debugfs = 1;
}
mutex_unlock(&monc->mutex); mutex_unlock(&monc->mutex);
if (init_debugfs) {
/* /*
* do debugfs initialization without mutex to avoid * do debugfs initialization without mutex to avoid
* creating a locking dependency * creating a locking dependency
*/ */
ceph_debugfs_client_init(client); ceph_debugfs_client_init(monc->client);
}
goto out_unlocked; goto out_unlocked;
} }
out: out:
...@@ -865,8 +889,10 @@ static void handle_auth_reply(struct ceph_mon_client *monc, ...@@ -865,8 +889,10 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
{ {
int ret; int ret;
int was_auth = 0; int was_auth = 0;
int had_debugfs_info, init_debugfs = 0;
mutex_lock(&monc->mutex); mutex_lock(&monc->mutex);
had_debugfs_info = have_debugfs_info(monc);
if (monc->auth->ops) if (monc->auth->ops)
was_auth = monc->auth->ops->is_authenticated(monc->auth); was_auth = monc->auth->ops->is_authenticated(monc->auth);
monc->pending_auth = 0; monc->pending_auth = 0;
...@@ -889,7 +915,22 @@ static void handle_auth_reply(struct ceph_mon_client *monc, ...@@ -889,7 +915,22 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
__send_subscribe(monc); __send_subscribe(monc);
__resend_generic_request(monc); __resend_generic_request(monc);
} }
if (!had_debugfs_info && have_debugfs_info(monc)) {
pr_info("client%lld fsid %pU\n",
ceph_client_id(monc->client),
&monc->client->fsid);
init_debugfs = 1;
}
mutex_unlock(&monc->mutex); mutex_unlock(&monc->mutex);
if (init_debugfs) {
/*
* do debugfs initialization without mutex to avoid
* creating a locking dependency
*/
ceph_debugfs_client_init(monc->client);
}
} }
static int __validate_auth(struct ceph_mon_client *monc) static int __validate_auth(struct ceph_mon_client *monc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment