changeset 246:a3bdecfe2560

{common,client,objstore}: define and implement WRITE RPC Closes #68. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Thu, 14 Apr 2016 22:35:26 -0400
parents a43d127ecfce
children aba404338d73
files docs/fs-protocol.md src/client/cmd_obj.c src/client/cmds.c src/client/cmds.h src/common/include/nomad/rpc_fs.h src/common/rpc_fs.x src/objstore/include/nomad/objstore.h src/objstore/include/nomad/objstore_impl.h src/objstore/obj.c src/objstore/vg.c
diffstat 10 files changed, 100 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/docs/fs-protocol.md	Thu Apr 14 22:35:17 2016 -0400
+++ b/docs/fs-protocol.md	Thu Apr 14 22:35:26 2016 -0400
@@ -225,10 +225,32 @@
 Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.
 
 
+WRITE (0x0009)
+==============
+
+Write a portion of an open object.  Trying to write to a directory fails with
+`EISDIR`.  Writing past the end of the object succeeds and the object length is
+updated automatically.
+
+Inputs
+------
+* open file handle
+* offset into the object version's data
+* length (in bytes) to write
+* data
+
+Outputs
+-------
+None.
+
+Limitations
+-----------
+Fails with `EPROTO` if the client hasn't gotten a successful LOGIN.
+
+
 Other RPCs that may end up useful
 =================================
 
 * RENAME - rename a "file"
 * LINK - create a symlink or a hardlink
 * GETDENTS - list contents of a directory
-* WRITE - write an open file
--- a/src/client/cmd_obj.c	Thu Apr 14 22:35:17 2016 -0400
+++ b/src/client/cmd_obj.c	Thu Apr 14 22:35:26 2016 -0400
@@ -104,6 +104,26 @@
 	return 0;
 }
 
+int cmd_write(struct fsconn *conn, union cmd *cmd)
+{
+	struct rpc_write_req *req = &cmd->write.req;
+	struct ohandle *oh;
+	ssize_t ret;
+
+	oh = ohandle_find(conn, req->handle);
+	if (!oh)
+		return -EINVAL;
+
+	/* TODO: should we limit the requested write size? */
+
+	ret = objstore_write(conn->vg, oh->cookie, req->data.data_val,
+			     req->data.data_len, req->offset);
+
+	VERIFY3S(ret, ==, req->data.data_len);
+
+	return (ret < 0) ? ret : 0;
+}
+
 int cmd_stat(struct fsconn *conn, union cmd *cmd)
 {
 	struct rpc_stat_req *req = &cmd->stat.req;
--- a/src/client/cmds.c	Thu Apr 14 22:35:17 2016 -0400
+++ b/src/client/cmds.c	Thu Apr 14 22:35:26 2016 -0400
@@ -83,6 +83,7 @@
 	CMD_ARG_RET(NRPC_READ,          read,          cmd_read,        true),
 	CMD_ARG    (NRPC_REMOVE,        remove,        cmd_remove,      true),
 	CMD_ARG_RET(NRPC_STAT,          stat,          cmd_stat,        true),
+	CMD_ARG    (NRPC_WRITE,         write,         cmd_write,       true),
 };
 
 static bool send_response(XDR *xdr, int fd, int err)
--- a/src/client/cmds.h	Thu Apr 14 22:35:17 2016 -0400
+++ b/src/client/cmds.h	Thu Apr 14 22:35:26 2016 -0400
@@ -77,6 +77,11 @@
 		struct rpc_stat_req req;
 		struct rpc_stat_res res;
 	} stat;
+
+	/* write */
+	struct {
+		struct rpc_write_req req;
+	} write;
 };
 
 struct fsconn {
@@ -98,5 +103,6 @@
 extern int cmd_read(struct fsconn *conn, union cmd *cmd);
 extern int cmd_remove(struct fsconn *conn, union cmd *cmd);
 extern int cmd_stat(struct fsconn *conn, union cmd *cmd);
+extern int cmd_write(struct fsconn *conn, union cmd *cmd);
 
 #endif
--- a/src/common/include/nomad/rpc_fs.h	Thu Apr 14 22:35:17 2016 -0400
+++ b/src/common/include/nomad/rpc_fs.h	Thu Apr 14 22:35:26 2016 -0400
@@ -35,5 +35,6 @@
 #define NRPC_OPEN	0x0006
 #define NRPC_CLOSE	0x0007
 #define NRPC_READ	0x0008
+#define NRPC_WRITE	0x0009
 
 #endif
--- a/src/common/rpc_fs.x	Thu Apr 14 22:35:17 2016 -0400
+++ b/src/common/rpc_fs.x	Thu Apr 14 22:35:26 2016 -0400
@@ -112,3 +112,11 @@
 	/* length is sent as part of data */
 	opaque data<4294967295>;
 };
+
+%/***** WRITE *****/
+struct rpc_write_req {
+	HANDLE(handle);
+	uint64_t offset;
+	/* length is sent as part of data */
+	opaque data<4294967295>;
+};
--- a/src/objstore/include/nomad/objstore.h	Thu Apr 14 22:35:17 2016 -0400
+++ b/src/objstore/include/nomad/objstore.h	Thu Apr 14 22:35:26 2016 -0400
@@ -85,6 +85,8 @@
 			    struct nattr *attr);
 extern ssize_t objstore_read(struct objstore *vg, void *cookie, void *buf,
 			     size_t len, uint64_t offset);
+extern ssize_t objstore_write(struct objstore *vg, void *cookie,
+			      const void *buf, size_t len, uint64_t offset);
 extern int objstore_lookup(struct objstore *vg, void *dircookie,
 			   const char *name, struct noid *child);
 extern int objstore_create(struct objstore *vg, void *dircookie,
--- a/src/objstore/include/nomad/objstore_impl.h	Thu Apr 14 22:35:17 2016 -0400
+++ b/src/objstore/include/nomad/objstore_impl.h	Thu Apr 14 22:35:26 2016 -0400
@@ -54,7 +54,8 @@
 	int (*setattr)();	/* set attributes of an object */
 	ssize_t (*read)(struct objstore_vol *store, void *cookie,
 			void *buf, size_t len, uint64_t offset);
-	ssize_t (*write)();	/* write portion of an object */
+	ssize_t (*write)(struct objstore_vol *store, void *cookie,
+			 const void *buf, size_t len, uint64_t offset);
 
 	int (*lookup)(struct objstore_vol *vol, void *dircookie,
 		      const char *name, struct noid *child);
@@ -85,6 +86,8 @@
 		       struct nattr *attr);
 extern ssize_t vol_read(struct objstore_vol *vol, void *cookie, void *buf,
 			size_t len, uint64_t offset);
+extern ssize_t vol_write(struct objstore_vol *vol, void *cookie,
+			 const void *buf, size_t len, uint64_t offset);
 extern int vol_lookup(struct objstore_vol *vol, void *dircookie,
 		      const char *name, struct noid *child);
 extern int vol_create(struct objstore_vol *vol, void *dircookie,
--- a/src/objstore/obj.c	Thu Apr 14 22:35:17 2016 -0400
+++ b/src/objstore/obj.c	Thu Apr 14 22:35:26 2016 -0400
@@ -71,6 +71,18 @@
 	return vol->def->obj_ops->read(vol, cookie, buf, len, offset);
 }
 
+ssize_t vol_write(struct objstore_vol *vol, void *cookie, const void *buf,
+		  size_t len, uint64_t offset)
+{
+	if (!vol || !buf)
+		return -EINVAL;
+
+	if (!vol->def->obj_ops || !vol->def->obj_ops->write)
+		return -ENOTSUP;
+
+	return vol->def->obj_ops->write(vol, cookie, buf, len, offset);
+}
+
 int vol_lookup(struct objstore_vol *vol, void *dircookie,
 	       const char *name, struct noid *child)
 {
--- a/src/objstore/vg.c	Thu Apr 14 22:35:17 2016 -0400
+++ b/src/objstore/vg.c	Thu Apr 14 22:35:26 2016 -0400
@@ -214,6 +214,29 @@
 	return ret;
 }
 
+ssize_t objstore_write(struct objstore *vg, void *cookie, const void *buf,
+		       size_t len, uint64_t offset)
+{
+	struct objstore_vol *vol;
+	ssize_t ret;
+
+	if (!vg || !buf)
+		return -EINVAL;
+
+	if (len > (SIZE_MAX / 2))
+		return -EOVERFLOW;
+
+	vol = findvol(vg);
+	if (!vol)
+		return -ENXIO;
+
+	ret = vol_write(vol, cookie, buf, len, offset);
+
+	vol_putref(vol);
+
+	return ret;
+}
+
 int objstore_lookup(struct objstore *vg, void *dircookie, const char *name,
 		    struct noid *child)
 {