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;
}