Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 214376
b: refs/heads/master
c: fc44508
h: refs/heads/master
v: v3
  • Loading branch information
Andy Grover committed Sep 9, 2010
1 parent 71a2170 commit da747fd
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3ef13f3c22aaea28aff383cb0883481d24885456
refs/heads/master: fc445084f185cdd877bec323bfe724a361e2292a
51 changes: 30 additions & 21 deletions trunk/net/rds/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,17 +214,22 @@ int rds_message_add_rdma_dest_extension(struct rds_header *hdr, u32 r_key, u32 o
}
EXPORT_SYMBOL_GPL(rds_message_add_rdma_dest_extension);

struct rds_message *rds_message_alloc(unsigned int nents, gfp_t gfp)
/*
* Each rds_message is allocated with extra space for the scatterlist entries
* rds ops will need. This is to minimize memory allocation count. Then, each rds op
* can grab SGs when initializing its part of the rds_message.
*/
struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp)
{
struct rds_message *rm;

rm = kzalloc(sizeof(struct rds_message) +
(nents * sizeof(struct scatterlist)), gfp);
rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp);
if (!rm)
goto out;

if (nents)
sg_init_table(rm->data.m_sg, nents);
rm->m_used_sgs = 0;
rm->m_total_sgs = extra_len / sizeof(struct scatterlist);

atomic_set(&rm->m_refcount, 1);
INIT_LIST_HEAD(&rm->m_sock_item);
INIT_LIST_HEAD(&rm->m_conn_item);
Expand All @@ -234,6 +239,23 @@ struct rds_message *rds_message_alloc(unsigned int nents, gfp_t gfp)
return rm;
}

/*
* RDS ops use this to grab SG entries from the rm's sg pool.
*/
struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents)
{
struct scatterlist *sg_first = (struct scatterlist *) &rm[1];
struct scatterlist *sg_ret;

WARN_ON(rm->m_used_sgs + nents > rm->m_total_sgs);

sg_ret = &sg_first[rm->m_used_sgs];

rm->m_used_sgs += nents;

return sg_ret;
}

struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned int total_len)
{
struct rds_message *rm;
Expand All @@ -256,22 +278,15 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
return rm;
}

struct rds_message *rds_message_copy_from_user(struct iovec *first_iov,
int rds_message_copy_from_user(struct rds_message *rm, struct iovec *first_iov,
size_t total_len)
{
unsigned long to_copy;
unsigned long iov_off;
unsigned long sg_off;
struct rds_message *rm;
struct iovec *iov;
struct scatterlist *sg;
int ret;

rm = rds_message_alloc(ceil(total_len, PAGE_SIZE), GFP_KERNEL);
if (rm == NULL) {
ret = -ENOMEM;
goto out;
}
int ret = 0;

rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);

Expand Down Expand Up @@ -320,14 +335,8 @@ struct rds_message *rds_message_copy_from_user(struct iovec *first_iov,
sg++;
}

ret = 0;
out:
if (ret) {
if (rm)
rds_message_put(rm);
rm = ERR_PTR(ret);
}
return rm;
return ret;
}

int rds_message_inc_copy_to_user(struct rds_incoming *inc,
Expand Down
7 changes: 5 additions & 2 deletions trunk/net/rds/rds.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,11 @@ struct rds_message {
struct {
unsigned int m_nents;
unsigned int m_count;
struct scatterlist m_sg[0];
struct scatterlist *m_sg;
} data;
};
unsigned int m_used_sgs;
unsigned int m_total_sgs;
};

/*
Expand Down Expand Up @@ -573,7 +575,8 @@ rds_conn_connecting(struct rds_connection *conn)

/* message.c */
struct rds_message *rds_message_alloc(unsigned int nents, gfp_t gfp);
struct rds_message *rds_message_copy_from_user(struct iovec *first_iov,
struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents);
int rds_message_copy_from_user(struct rds_message *rm, struct iovec *first_iov,
size_t total_len);
struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned int total_len);
void rds_message_populate_header(struct rds_header *hdr, __be16 sport,
Expand Down
31 changes: 27 additions & 4 deletions trunk/net/rds/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,19 @@ static int rds_send_queue_rm(struct rds_sock *rs, struct rds_connection *conn,
return *queued;
}

/*
* rds_message is getting to be quite complicated, and we'd like to allocate
* it all in one go. This figures out how big it needs to be up front.
*/
static int rds_rm_size(struct msghdr *msg, int data_len)
{
int size = 0;

size += ceil(data_len, PAGE_SIZE) * sizeof(struct scatterlist);

return size;
}

static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm,
struct msghdr *msg, int *allocated_mr)
{
Expand Down Expand Up @@ -845,13 +858,23 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
goto out;
}

rm = rds_message_copy_from_user(msg->msg_iov, payload_len);
if (IS_ERR(rm)) {
ret = PTR_ERR(rm);
rm = NULL;
/* size of rm including all sgs */
ret = rds_rm_size(msg, payload_len);
if (ret < 0)
goto out;

rm = rds_message_alloc(ret, GFP_KERNEL);
if (!rm) {
ret = -ENOMEM;
goto out;
}

rm->data.m_sg = rds_message_alloc_sgs(rm, ceil(payload_len, PAGE_SIZE));
/* XXX fix this to not allocate memory */
ret = rds_message_copy_from_user(rm, msg->msg_iov, payload_len);
if (ret)
goto out;

rm->m_daddr = daddr;

/* rds_conn_create has a spinlock that runs with IRQ off.
Expand Down

0 comments on commit da747fd

Please sign in to comment.