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:
  ceph: do not include cap/dentry releases in replayed messages
  ceph: reuse request message when replaying against recovering mds
  ceph: fix creation of ipv6 sockets
  ceph: fix parsing of ipv6 addresses
  ceph: fix printing of ipv6 addrs
  ceph: add kfree() to error path
  ceph: fix leak of mon authorizer
  ceph: fix message revocation
This commit is contained in:
Linus Torvalds 2010-07-20 16:27:58 -07:00
commit e0959371b4
5 changed files with 72 additions and 39 deletions

View File

@ -613,6 +613,9 @@ static void ceph_x_destroy(struct ceph_auth_client *ac)
remove_ticket_handler(ac, th); remove_ticket_handler(ac, th);
} }
if (xi->auth_authorizer.buf)
ceph_buffer_put(xi->auth_authorizer.buf);
kfree(ac->private); kfree(ac->private);
ac->private = NULL; ac->private = NULL;
} }

View File

@ -1514,6 +1514,9 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
ceph_encode_filepath(&p, end, ino1, path1); ceph_encode_filepath(&p, end, ino1, path1);
ceph_encode_filepath(&p, end, ino2, path2); ceph_encode_filepath(&p, end, ino2, path2);
/* make note of release offset, in case we need to replay */
req->r_request_release_offset = p - msg->front.iov_base;
/* cap releases */ /* cap releases */
releases = 0; releases = 0;
if (req->r_inode_drop) if (req->r_inode_drop)
@ -1580,6 +1583,32 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
dout("prepare_send_request %p tid %lld %s (attempt %d)\n", req, dout("prepare_send_request %p tid %lld %s (attempt %d)\n", req,
req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts); req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts);
if (req->r_got_unsafe) {
/*
* Replay. Do not regenerate message (and rebuild
* paths, etc.); just use the original message.
* Rebuilding paths will break for renames because
* d_move mangles the src name.
*/
msg = req->r_request;
rhead = msg->front.iov_base;
flags = le32_to_cpu(rhead->flags);
flags |= CEPH_MDS_FLAG_REPLAY;
rhead->flags = cpu_to_le32(flags);
if (req->r_target_inode)
rhead->ino = cpu_to_le64(ceph_ino(req->r_target_inode));
rhead->num_retry = req->r_attempts - 1;
/* remove cap/dentry releases from message */
rhead->num_releases = 0;
msg->hdr.front_len = cpu_to_le32(req->r_request_release_offset);
msg->front.iov_len = req->r_request_release_offset;
return 0;
}
if (req->r_request) { if (req->r_request) {
ceph_msg_put(req->r_request); ceph_msg_put(req->r_request);
req->r_request = NULL; req->r_request = NULL;
@ -1601,13 +1630,9 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
rhead->flags = cpu_to_le32(flags); rhead->flags = cpu_to_le32(flags);
rhead->num_fwd = req->r_num_fwd; rhead->num_fwd = req->r_num_fwd;
rhead->num_retry = req->r_attempts - 1; rhead->num_retry = req->r_attempts - 1;
rhead->ino = 0;
dout(" r_locked_dir = %p\n", req->r_locked_dir); dout(" r_locked_dir = %p\n", req->r_locked_dir);
if (req->r_target_inode && req->r_got_unsafe)
rhead->ino = cpu_to_le64(ceph_ino(req->r_target_inode));
else
rhead->ino = 0;
return 0; return 0;
} }

View File

@ -188,6 +188,7 @@ struct ceph_mds_request {
int r_old_inode_drop, r_old_inode_unless; int r_old_inode_drop, r_old_inode_unless;
struct ceph_msg *r_request; /* original request */ struct ceph_msg *r_request; /* original request */
int r_request_release_offset;
struct ceph_msg *r_reply; struct ceph_msg *r_reply;
struct ceph_mds_reply_info_parsed r_reply_info; struct ceph_mds_reply_info_parsed r_reply_info;
int r_err; int r_err;

View File

@ -43,7 +43,8 @@ static void ceph_fault(struct ceph_connection *con);
* nicely render a sockaddr as a string. * nicely render a sockaddr as a string.
*/ */
#define MAX_ADDR_STR 20 #define MAX_ADDR_STR 20
static char addr_str[MAX_ADDR_STR][40]; #define MAX_ADDR_STR_LEN 60
static char addr_str[MAX_ADDR_STR][MAX_ADDR_STR_LEN];
static DEFINE_SPINLOCK(addr_str_lock); static DEFINE_SPINLOCK(addr_str_lock);
static int last_addr_str; static int last_addr_str;
@ -52,7 +53,6 @@ const char *pr_addr(const struct sockaddr_storage *ss)
int i; int i;
char *s; char *s;
struct sockaddr_in *in4 = (void *)ss; struct sockaddr_in *in4 = (void *)ss;
unsigned char *quad = (void *)&in4->sin_addr.s_addr;
struct sockaddr_in6 *in6 = (void *)ss; struct sockaddr_in6 *in6 = (void *)ss;
spin_lock(&addr_str_lock); spin_lock(&addr_str_lock);
@ -64,25 +64,13 @@ const char *pr_addr(const struct sockaddr_storage *ss)
switch (ss->ss_family) { switch (ss->ss_family) {
case AF_INET: case AF_INET:
sprintf(s, "%u.%u.%u.%u:%u", snprintf(s, MAX_ADDR_STR_LEN, "%pI4:%u", &in4->sin_addr,
(unsigned int)quad[0], (unsigned int)ntohs(in4->sin_port));
(unsigned int)quad[1],
(unsigned int)quad[2],
(unsigned int)quad[3],
(unsigned int)ntohs(in4->sin_port));
break; break;
case AF_INET6: case AF_INET6:
sprintf(s, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%u", snprintf(s, MAX_ADDR_STR_LEN, "[%pI6c]:%u", &in6->sin6_addr,
in6->sin6_addr.s6_addr16[0], (unsigned int)ntohs(in6->sin6_port));
in6->sin6_addr.s6_addr16[1],
in6->sin6_addr.s6_addr16[2],
in6->sin6_addr.s6_addr16[3],
in6->sin6_addr.s6_addr16[4],
in6->sin6_addr.s6_addr16[5],
in6->sin6_addr.s6_addr16[6],
in6->sin6_addr.s6_addr16[7],
(unsigned int)ntohs(in6->sin6_port));
break; break;
default: default:
@ -215,12 +203,13 @@ static void set_sock_callbacks(struct socket *sock,
*/ */
static struct socket *ceph_tcp_connect(struct ceph_connection *con) static struct socket *ceph_tcp_connect(struct ceph_connection *con)
{ {
struct sockaddr *paddr = (struct sockaddr *)&con->peer_addr.in_addr; struct sockaddr_storage *paddr = &con->peer_addr.in_addr;
struct socket *sock; struct socket *sock;
int ret; int ret;
BUG_ON(con->sock); BUG_ON(con->sock);
ret = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); ret = sock_create_kern(con->peer_addr.in_addr.ss_family, SOCK_STREAM,
IPPROTO_TCP, &sock);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
con->sock = sock; con->sock = sock;
@ -234,7 +223,8 @@ static struct socket *ceph_tcp_connect(struct ceph_connection *con)
dout("connect %s\n", pr_addr(&con->peer_addr.in_addr)); dout("connect %s\n", pr_addr(&con->peer_addr.in_addr));
ret = sock->ops->connect(sock, paddr, sizeof(*paddr), O_NONBLOCK); ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr),
O_NONBLOCK);
if (ret == -EINPROGRESS) { if (ret == -EINPROGRESS) {
dout("connect %s EINPROGRESS sk_state = %u\n", dout("connect %s EINPROGRESS sk_state = %u\n",
pr_addr(&con->peer_addr.in_addr), pr_addr(&con->peer_addr.in_addr),
@ -1009,19 +999,32 @@ int ceph_parse_ips(const char *c, const char *end,
struct sockaddr_in *in4 = (void *)ss; struct sockaddr_in *in4 = (void *)ss;
struct sockaddr_in6 *in6 = (void *)ss; struct sockaddr_in6 *in6 = (void *)ss;
int port; int port;
char delim = ',';
if (*p == '[') {
delim = ']';
p++;
}
memset(ss, 0, sizeof(*ss)); memset(ss, 0, sizeof(*ss));
if (in4_pton(p, end - p, (u8 *)&in4->sin_addr.s_addr, if (in4_pton(p, end - p, (u8 *)&in4->sin_addr.s_addr,
',', &ipend)) { delim, &ipend))
ss->ss_family = AF_INET; ss->ss_family = AF_INET;
} else if (in6_pton(p, end - p, (u8 *)&in6->sin6_addr.s6_addr, else if (in6_pton(p, end - p, (u8 *)&in6->sin6_addr.s6_addr,
',', &ipend)) { delim, &ipend))
ss->ss_family = AF_INET6; ss->ss_family = AF_INET6;
} else { else
goto bad; goto bad;
}
p = ipend; p = ipend;
if (delim == ']') {
if (*p != ']') {
dout("missing matching ']'\n");
goto bad;
}
p++;
}
/* port? */ /* port? */
if (p < end && *p == ':') { if (p < end && *p == ':') {
port = 0; port = 0;
@ -1055,7 +1058,7 @@ int ceph_parse_ips(const char *c, const char *end,
return 0; return 0;
bad: bad:
pr_err("parse_ips bad ip '%s'\n", c); pr_err("parse_ips bad ip '%.*s'\n", (int)(end - c), c);
return -EINVAL; return -EINVAL;
} }
@ -2015,20 +2018,20 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg)
{ {
mutex_lock(&con->mutex); mutex_lock(&con->mutex);
if (!list_empty(&msg->list_head)) { if (!list_empty(&msg->list_head)) {
dout("con_revoke %p msg %p\n", con, msg); dout("con_revoke %p msg %p - was on queue\n", con, msg);
list_del_init(&msg->list_head); list_del_init(&msg->list_head);
ceph_msg_put(msg); ceph_msg_put(msg);
msg->hdr.seq = 0; msg->hdr.seq = 0;
if (con->out_msg == msg) { }
ceph_msg_put(con->out_msg); if (con->out_msg == msg) {
con->out_msg = NULL; dout("con_revoke %p msg %p - was sending\n", con, msg);
} con->out_msg = NULL;
if (con->out_kvec_is_msg) { if (con->out_kvec_is_msg) {
con->out_skip = con->out_kvec_bytes; con->out_skip = con->out_kvec_bytes;
con->out_kvec_is_msg = false; con->out_kvec_is_msg = false;
} }
} else { ceph_msg_put(msg);
dout("con_revoke %p msg %p - not queued (sent?)\n", con, msg); msg->hdr.seq = 0;
} }
mutex_unlock(&con->mutex); mutex_unlock(&con->mutex);
} }

View File

@ -568,6 +568,7 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
if (ev > CEPH_PG_POOL_VERSION) { if (ev > CEPH_PG_POOL_VERSION) {
pr_warning("got unknown v %d > %d of ceph_pg_pool\n", pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
ev, CEPH_PG_POOL_VERSION); ev, CEPH_PG_POOL_VERSION);
kfree(pi);
goto bad; goto bad;
} }
__decode_pool(p, pi); __decode_pool(p, pi);