From d6ebc26215dea19c91980ab9b312b316c46f28fe Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 21 Jan 2008 17:27:48 -0800 Subject: [PATCH] silly_write --- src/kernel/addr.c | 2 +- src/kernel/client.c | 2 +- src/kernel/file.c | 36 ++++++++++---- src/kernel/inode.c | 13 +++-- src/kernel/mds_client.c | 2 +- src/kernel/messenger.c | 6 +-- src/kernel/osd_client.c | 102 +++++++++++++++++++++++++++++++++++++++- src/kernel/osd_client.h | 4 ++ 8 files changed, 146 insertions(+), 21 deletions(-) diff --git a/src/kernel/addr.c b/src/kernel/addr.c index b569473577556..3392bdcc113a0 100644 --- a/src/kernel/addr.c +++ b/src/kernel/addr.c @@ -57,5 +57,5 @@ out_unlock: const struct address_space_operations ceph_aops = { .readpage = ceph_readpage, // .readpages = ceph_readpages - .writepage = ceph_writepage, +// .writepage = ceph_writepage, }; diff --git a/src/kernel/client.c b/src/kernel/client.c index 1d07e8a3c4b92..3339bb6ea51bb 100644 --- a/src/kernel/client.c +++ b/src/kernel/client.c @@ -321,7 +321,7 @@ void ceph_dispatch(void *p, struct ceph_msg *msg) struct ceph_client *client = p; int had; - dout(5, "dispatch from %s%d type %d len %d+%d\n", + dout(5, "===== %p ===== from %s%d type %d len %d+%d\n", msg, ceph_name_type_str(msg->hdr.src.name.type), msg->hdr.src.name.num, msg->hdr.type, msg->hdr.front_len, msg->hdr.data_len); diff --git a/src/kernel/file.c b/src/kernel/file.c index 1d7df9ee25859..b377fac1fa19e 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -115,25 +115,41 @@ const struct inode_operations ceph_file_iops = { /* * totally naive write. just to get things sort of working. + * ugly hack! */ -int ceph_silly_write(struct file *filp, const char __user * data, +ssize_t ceph_silly_write(struct file *file, const char __user * data, size_t count, loff_t * offset) { - struct inode *inode = filp->f_path.dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_file_info *cf = file->private_data; + struct ceph_osd_client *osdc = &ceph_inode_to_client(inode)->osdc; int ret = 0; - - dout(10, "silly_write on file %p %lld~%u\n", filp, offset, count); + int did = 0; - /* ignore caps, for now. */ + dout(10, "silly_write on file %p %lld~%lu\n", file, *offset, count); - if (ret > 0) - *offset += ret; + /* ignore caps, for now. */ + /* this is an ugly hack */ + + while (count > 0) { + ret = ceph_osdc_silly_write(osdc, inode->i_ino, &ci->i_layout, count, *offset, data); + dout(10, "ret is %d\n", ret); + if (ret > 0) { + did += ret; + *offset += ret; + data += ret; + count -= ret; + dout(10, "did %d bytes, ret now %d, %lu left\n", did, ret, count); + } else if (did) + break; + else + return ret; + } if (*offset > inode->i_size) { - inode->i_size = *offset; + ci->i_wr_size = inode->i_size = *offset; inode->i_blocks = (inode->i_size + 512 - 1) >> 9; + dout(10, "extending file size to %d\n", (int)inode->i_size); } invalidate_inode_pages2(inode->i_mapping); return ret; @@ -144,7 +160,7 @@ const struct file_operations ceph_file_fops = { .release = ceph_release, .llseek = generic_file_llseek, .read = do_sync_read, - .write = do_sync_write, + .write = ceph_silly_write,//do_sync_write, .aio_read = generic_file_aio_read, .aio_write = generic_file_aio_write, .mmap = generic_file_mmap, diff --git a/src/kernel/inode.c b/src/kernel/inode.c index 6a1f1b9de175d..4c724fd4c5f2b 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -391,22 +391,29 @@ int ceph_handle_cap_grant(struct inode *inode, struct ceph_mds_file_caps *grant, int seq = le32_to_cpu(grant->seq); int newcaps; int used; + int wanted = ceph_caps_wanted(ci); + int ret = 0; dout(10, "handle_cap_grant inode %p ci %p mds%d seq %d\n", inode, ci, mds, seq); + dout(10, " my wanted = %d\n", wanted); /* unwanted? */ - if (ceph_caps_wanted(ci) == 0) { + if (wanted == 0) { dout(10, "wanted=0, reminding mds\n"); grant->wanted = cpu_to_le32(0); return 1; /* ack */ } + if (wanted != le32_to_cpu(grant->wanted)) { + dout(10, "wanted %d -> %d\n", le32_to_cpu(grant->wanted), wanted); + grant->wanted = cpu_to_le32(wanted); + } /* new cap? */ cap = get_cap_for_mds(inode, mds); if (!cap) { dout(10, "adding new cap inode %p for mds%d\n", inode, mds); cap = ceph_add_cap(inode, session, le32_to_cpu(grant->caps), le32_to_cpu(grant->seq)); - return 0; + return ret; } /* revocation? */ @@ -429,7 +436,7 @@ int ceph_handle_cap_grant(struct inode *inode, struct ceph_mds_file_caps *grant, dout(10, "grant: %d -> %d\n", cap->caps, newcaps); cap->caps = newcaps; } - return 0; + return ret; } diff --git a/src/kernel/mds_client.c b/src/kernel/mds_client.c index 75f083198ac07..0a94574ef8315 100644 --- a/src/kernel/mds_client.c +++ b/src/kernel/mds_client.c @@ -1009,7 +1009,7 @@ void send_cap_ack(struct ceph_mds_client *mdsc, __u64 ino, int caps, int wanted, fc->wanted = cpu_to_le32(wanted); fc->ino = cpu_to_le64(ino); fc->size = cpu_to_le64(size); - + send_msg_mds(mdsc, msg, mds); } diff --git a/src/kernel/messenger.c b/src/kernel/messenger.c index fcd0dcbb1a6c2..d831812379e35 100644 --- a/src/kernel/messenger.c +++ b/src/kernel/messenger.c @@ -305,13 +305,10 @@ static int write_partial_kvec(struct ceph_connection *con) { int ret; - dout(30, "write_partial_kvec %p : %d vec, %d bytes left\n", con, - con->out_kvec_left, con->out_kvec_bytes); while (con->out_kvec_bytes > 0) { ret = ceph_tcp_sendmsg(con->sock, con->out_kvec_cur, con->out_kvec_left, con->out_kvec_bytes); if (ret <= 0) goto out; - dout(30, "write_partial_kvec %p : wrote %d\n", con, ret); con->out_kvec_bytes -= ret; if (con->out_kvec_bytes == 0) break; /* done */ @@ -1102,6 +1099,9 @@ int ceph_msg_send(struct ceph_messenger *msgr, struct ceph_msg *msg, unsigned lo /* queue */ spin_lock(&con->out_queue_lock); msg->hdr.seq = ++con->out_seq; + dout(1, "----- %p ----- to %s%d type %d len %d+%d\n", msg, + ceph_name_type_str(msg->hdr.src.name.type), msg->hdr.src.name.num, + msg->hdr.type, msg->hdr.front_len, msg->hdr.data_len); dout(1, "ceph_msg_send queuing %p seq %u for %s%d on %p\n", msg, msg->hdr.seq, ceph_name_type_str(msg->hdr.dst.name.type), msg->hdr.dst.name.num, con); ceph_msg_get(msg); diff --git a/src/kernel/osd_client.c b/src/kernel/osd_client.c index 555e3e4e47978..e3525476bfbdc 100644 --- a/src/kernel/osd_client.c +++ b/src/kernel/osd_client.c @@ -1,5 +1,7 @@ #include #include +#include +#include int ceph_debug_osdc = 50; #define DOUT_VAR ceph_debug_osdc @@ -168,7 +170,7 @@ struct ceph_osd_request *register_request(struct ceph_osd_client *osdc, init_completion(&req->r_completion); req->r_nr_pages = nr_pages; - dout(30, "register_request %p tid %lld\n", req, req->r_tid); + dout(30, "register_request %p tid %lld with %d pages\n", req, req->r_tid, nr_pages); radix_tree_insert(&osdc->request_tree, req->r_tid, (void*)req); return req; } @@ -198,7 +200,7 @@ static void send_request(struct ceph_osd_client *osdc, struct ceph_osd_request * break; } if (i < nr_osds) { - dout(10, "send_request %p tid %llu to osd%d\n", req, req->r_tid, osds[i]); + dout(10, "send_request %p tid %llu to osd%d flags %d\n", req, req->r_tid, osds[i], req->r_flags); req->r_request->hdr.dst.name.type = CEPH_ENTITY_TYPE_OSD; req->r_request->hdr.dst.name.num = osds[i]; req->r_request->hdr.dst.addr = osdc->osdmap->osd_addr[osds[i]]; @@ -429,3 +431,99 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc, ceph_ino_t ino, } #endif + + +/* + * silly hack. + */ +static int calc_bits_of(unsigned t) +{ + int b = 0; + while (t) { + t = t >> 1; + b++; + } + return b; +} + +int ceph_osdc_silly_write(struct ceph_osd_client *osdc, ceph_ino_t ino, + struct ceph_file_layout *layout, + __u64 len, __u64 off, const char __user *data) +{ + struct ceph_msg *reqm, *reply; + struct ceph_osd_request_head *reqhead; + struct ceph_osd_request *req; + struct ceph_osd_reply_head *replyhead; + __u64 toff = off, tlen = len; + int nrp, i, po, l, left; + + dout(10, "silly_write on ino %llx at %llu~%llu\n", ino, off, len); + + /* request msg */ + reqm = new_request_msg(osdc, CEPH_OSD_OP_WRITE); + if (IS_ERR(reqm)) + return PTR_ERR(reqm); + reqhead = reqm->front.iov_base; + reqhead->oid.ino = ino; + reqhead->oid.rev = 0; + reqhead->flags = CEPH_OSD_OP_ACK|CEPH_OSD_OP_SAFE; /* want them both */ + calc_file_object_mapping(layout, &toff, &tlen, &reqhead->oid, + &reqhead->offset, &reqhead->length); + if (tlen != 0) { + dout(10, "not writing complete bit.. skipping last %llu, doing %llu~%llu\n", tlen, off, len); + len -= tlen; + } + calc_object_layout(&reqhead->layout, &reqhead->oid, layout, osdc->osdmap); + dout(10, "silly_write object block %u %llu~%llu\n", reqhead->oid.bno, reqhead->offset, reqhead->length); + + /* how many pages? */ + nrp = calc_pages_for(len, off); + dout(10, "%d~%d -> %d pages\n", (int)off, (int)len, nrp); + + /* register+send request */ + spin_lock(&osdc->lock); + req = register_request(osdc, reqm, nrp); + if (IS_ERR(req)) { + ceph_msg_put(reqm); + spin_unlock(&osdc->lock); + return PTR_ERR(req); + } + + /* data into a set of pages */ + req->r_pages[0] = alloc_pages(GFP_KERNEL, calc_bits_of(nrp)); + for (i=1; ir_pages[i] = req->r_pages[i-1]+1; + left = len; + po = off & ~PAGE_MASK; + for (i=0; ir_pages[i]) + po, data, l); + data += l; + left -= l; + po = 0; + } + req->r_request->pages = req->r_pages; + req->r_request->nr_pages = req->r_nr_pages; + req->r_request->hdr.data_len = len; + req->r_request->hdr.data_off = off; + + reqhead->osdmap_epoch = osdc->osdmap->epoch; + send_request(osdc, req); + spin_unlock(&osdc->lock); + + /* wait */ + dout(10, "silly_write tid %llu waiting for reply on %p\n", req->r_tid, req); + wait_for_completion(&req->r_completion); + dout(10, "silly_write tid %llu got reply on %p\n", req->r_tid, req); + + spin_lock(&osdc->lock); + unregister_request(osdc, req); + spin_unlock(&osdc->lock); + + reply = req->r_reply; + replyhead = reply->front.iov_base; + dout(10, "silly_write result %d, returning %d\n", replyhead->result, (int)len); + ceph_msg_put(reply); + put_request(req); + return (int)len; +} diff --git a/src/kernel/osd_client.h b/src/kernel/osd_client.h index fe3c108b57795..67d61087a1dda 100644 --- a/src/kernel/osd_client.h +++ b/src/kernel/osd_client.h @@ -56,5 +56,9 @@ extern int ceph_osdc_readpages(struct ceph_osd_client *osdc, ceph_ino_t ino, struct ceph_file_layout *layout, struct list_head *pagels, int nr_pages); +extern int ceph_osdc_silly_write(struct ceph_osd_client *osdc, ceph_ino_t ino, + struct ceph_file_layout *layout, + __u64 count, __u64 offset, const char __user *data); + #endif -- 2.39.5