Blob Blame History Raw
commit dfa1f714caaed32ebe64ae9c4f8678e6c56bce5d
Author: Dan Muntz <dmuntz@netapp.com>
Date:   Tue May 6 16:45:09 2008 -0700

    Add read/write-through-MDS for spNFS
    
    Signed-off-by: Dan Muntz <dmuntz@netapp.com>

diff --git a/utils/spnfsd/nfsd4_spnfs.h b/utils/spnfsd/nfsd4_spnfs.h
index 6516ab3..fc6bd9a 100644
--- a/utils/spnfsd/nfsd4_spnfs.h
+++ b/utils/spnfsd/nfsd4_spnfs.h
@@ -55,9 +55,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define SPNFS_TYPE_CREATE		0x09
 #define SPNFS_TYPE_REMOVE		0x0a
 #define SPNFS_TYPE_COMMIT		0x0b
+#define SPNFS_TYPE_READ			0x0c
+#define SPNFS_TYPE_WRITE		0x0d
 
 #define	SPNFS_MAX_DEVICES		1
 #define	SPNFS_MAX_DATA_SERVERS		2
+#define SPNFS_MAX_IO			2048
 
 /* layout */
 struct spnfs_msg_layoutget_args {
@@ -198,6 +201,30 @@ struct spnfs_msg_commit_res {
 };
 */
 
+/* read */
+struct spnfs_msg_read_args {
+	unsigned long inode;
+	loff_t offset;
+	unsigned long len;
+};
+
+struct spnfs_msg_read_res {
+	int status;
+	char data[SPNFS_MAX_IO];
+};
+
+/* write */
+struct spnfs_msg_write_args {
+	unsigned long inode;
+	loff_t offset;
+	unsigned long len;
+	char data[SPNFS_MAX_IO];
+};
+
+struct spnfs_msg_write_res {
+	int status;
+};
+
 /* bundle args and responses */
 union spnfs_msg_args {
 	struct spnfs_msg_layoutget_args		layoutget_args;
@@ -217,6 +244,8 @@ union spnfs_msg_args {
 /*
 	struct spnfs_msg_commit_args		commit_args;
 */
+	struct spnfs_msg_read_args		read_args;
+	struct spnfs_msg_write_args		write_args;
 };
 
 union spnfs_msg_res {
@@ -237,6 +266,8 @@ union spnfs_msg_res {
 /*
 	struct spnfs_msg_commit_res		commit_res;
 */
+	struct spnfs_msg_read_res		read_res;
+	struct spnfs_msg_write_res		write_res;
 };
 
 /* a spnfs message, args and response */
@@ -268,7 +299,9 @@ int spnfs_getdeviceinfo(struct super_block *, struct pnfs_devinfo_arg *);
 int spnfs_setattr(void);
 int spnfs_open(struct inode *, void *);
 int spnfs_get_state(struct inode *, void *, void *);
-int spnfs_remove(unsigned long ino);
+int spnfs_remove(unsigned long);
+int spnfs_read(unsigned long, loff_t, unsigned long *, int, struct svc_rqst *);
+int spnfs_write(unsigned long, loff_t, size_t, int, struct svc_rqst *);
 
 int nfsd_spnfs_new(void);
 void nfsd_spnfs_delete(void);
diff --git a/utils/spnfsd/spnfsd.c b/utils/spnfsd/spnfsd.c
index f7bae84..fc9113d 100644
--- a/utils/spnfsd/spnfsd.c
+++ b/utils/spnfsd/spnfsd.c
@@ -40,6 +40,8 @@
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/poll.h>
@@ -340,6 +342,12 @@ spnfs_msg_handler(struct spnfs_client *scp, struct spnfs_msg *im)
 	case SPNFS_TYPE_COMMIT:
 		err = spnfsd_commit(im);
 		break;
+	case SPNFS_TYPE_READ:
+		err = spnfsd_read(im);
+		break;
+	case SPNFS_TYPE_WRITE:
+		err = spnfsd_write(im);
+		break;
 	default:
 		spnfsd_warnx("spnfs_msg_handler: Invalid msg type (%d) in message",
 			     im->im_type);
diff --git a/utils/spnfsd/spnfsd.h b/utils/spnfsd/spnfsd.h
index e8527e7..e05c272 100644
--- a/utils/spnfsd/spnfsd.h
+++ b/utils/spnfsd/spnfsd.h
@@ -65,4 +65,6 @@ int spnfsd_close(struct spnfs_msg *);
 int spnfsd_create(struct spnfs_msg *);
 int spnfsd_remove(struct spnfs_msg *);
 int spnfsd_commit(struct spnfs_msg *);
+int spnfsd_read(struct spnfs_msg *);
+int spnfsd_write(struct spnfs_msg *);
 int spnfsd_getfh(char *, unsigned char *, unsigned int *);
diff --git a/utils/spnfsd/spnfsd_ops.c b/utils/spnfsd/spnfsd_ops.c
index e3adadd..5099c00 100644
--- a/utils/spnfsd/spnfsd_ops.c
+++ b/utils/spnfsd/spnfsd_ops.c
@@ -20,6 +20,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
 
+#define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
 #include "nfsd4_spnfs.h"
 #include "spnfsd.h"
 #include "nfs/nfs.h"
@@ -265,6 +267,130 @@ spnfsd_remove(struct spnfs_msg *im)
 int
 spnfsd_commit(struct spnfs_msg *im)
 {
+	im->im_status = SPNFS_STATUS_SUCCESS;
+	return 0;
+}
+
+int
+min (unsigned int x, unsigned int y)
+{
+	if (x<y) return x; else return y;
+}
+
+/* DMXXX: for read and write, there's an issue with partially completed i/o */
+int
+spnfsd_read(struct spnfs_msg *im)
+{
+	unsigned long inode = im->im_args.read_args.inode;
+	loff_t offset = im->im_args.read_args.offset;
+	unsigned long len = im->im_args.read_args.len;
+	int ds, iolen;
+	loff_t soffset;
+	int bufoffset = 0;
+	char fullpath[1024]; /* DMXXX */
+	int fd, err;
+	int completed = 0;
+
+	im->im_status = SPNFS_STATUS_SUCCESS;
+	im->im_res.read_res.status = 0;
+	if (len > SPNFS_MAX_IO) {
+		im->im_res.read_res.status = -1;
+		return 0;
+	}
+	while (len > 0) {
+		ds = (offset / stripesize) % num_ds;
+		if (densestriping == 0)
+			soffset = offset;
+		else
+			soffset = (offset / num_ds) + (offset % stripesize);
+		iolen = min(len, stripesize - (offset % stripesize));
+
+		sprintf(fullpath, "%s/%s/%ld", dsmountdir,
+			dataservers[ds].ds_ip, inode);
+		fd = open(fullpath, O_RDONLY);
+		if (fd < 0) {
+			perror(fullpath);
+			im->im_res.read_res.status = -errno;
+			return 0; /* DMXXX */
+		}
+		/* DM: add some error checking */
+		lseek64(fd, offset, SEEK_SET);
+		err = read(fd,
+			(void *)(im->im_res.read_res.data+bufoffset), iolen);
+		close(fd);
+		if (err < 0) {
+			perror("read");
+			im->im_res.read_res.status = -errno;
+			return 0; /* DMXXX */
+		}
+
+		if (err == 0)
+			break;
+		iolen = err; /* number of bytes read */
+		completed += iolen;
+		len -= iolen;
+		offset += iolen;
+		bufoffset += iolen;
+	}
+	im->im_res.read_res.status = completed;
+
+	return 0;
+}
+
+int
+spnfsd_write(struct spnfs_msg *im)
+{
+	unsigned long inode = im->im_args.write_args.inode;
+	loff_t offset = im->im_args.write_args.offset;
+	size_t len = im->im_args.write_args.len;
+	char *wbuf = im->im_args.write_args.data;
+	int ds, iolen;
+	loff_t soffset;
+	int bufoffset = 0;
+	char fullpath[1024]; /* DMXXX */
+	int fd, err;
+	int completed = 0;
+
+	im->im_status = SPNFS_STATUS_SUCCESS;
+	im->im_res.write_res.status = 0;
+	if (len > SPNFS_MAX_IO) {
+		printf("write length > SPNFS_MAX_IO\n");
+		im->im_res.write_res.status = -1;
+		return 0;
+	}
+	while (len > 0) {
+		ds = (offset / stripesize) % num_ds;
+		if (densestriping == 0)
+			soffset = offset;
+		else
+			soffset = (offset / num_ds) + (offset % stripesize);
+		iolen = min(len, stripesize - (offset % stripesize));
+
+		sprintf(fullpath, "%s/%s/%ld", dsmountdir,
+			dataservers[ds].ds_ip, inode);
+		fd = open(fullpath, O_WRONLY);
+		if (fd < 0) {
+			perror(fullpath);
+			im->im_res.write_res.status = -errno;
+			return 0; /* DMXXX */
+		}
+		/* DM: add some error checking */
+		lseek64(fd, offset, SEEK_SET);
+		err = write(fd, (void *)(wbuf+bufoffset), iolen);
+		close(fd);
+		if (err < 0) {
+			perror("write");
+			im->im_res.write_res.status = -errno;
+			return 0; /* DMXXX */
+		}
+
+		iolen = err; /* number of bytes read */
+		completed += iolen;
+		len -= iolen;
+		offset += iolen;
+		bufoffset += iolen;
+	}
+	im->im_res.write_res.status = completed;
 	return 0;
 }