]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
libcephfs: add ceph_p{read,write}v
authorJevon Qiao <qiaojianfeng@unitedstack.com>
Mon, 15 Jun 2015 02:15:45 +0000 (10:15 +0800)
committerJevon Qiao <qiaojianfeng@unitedstack.com>
Mon, 15 Jun 2015 02:15:45 +0000 (10:15 +0800)
Add interfaces in libcephfs to enable users to read/write data via iovec structure.

Signed-off-by: Jevon Qiao <qiaojianfeng@unitedstack.com>
src/client/Client.cc
src/client/Client.h
src/include/cephfs/libcephfs.h
src/libcephfs.cc

index a027528eb7cd8ea490f7d682cb95aa3ba171bc9c..02ea319bbfe8033ebe4587862d44ed96b16d6ee4 100644 (file)
@@ -22,6 +22,7 @@
 #include <sys/param.h>
 #include <fcntl.h>
 #include <sys/utsname.h>
+#include <sys/uio.h>
 
 #if defined(__linux__)
 #include <linux/falloc.h>
@@ -239,11 +240,6 @@ Client::~Client()
   delete logger;
 }
 
-
-
-
-
-
 void Client::tear_down_cache()
 {
   // fd's
@@ -7133,6 +7129,11 @@ int Client::read(int fd, char *buf, loff_t size, loff_t offset)
   return r;
 }
 
+int Client::preadv(int fd, const struct iovec *iov, int iovcnt, loff_t offset)
+{
+     return _preadv_pwritev(fd, iov, iovcnt, offset, false);
+}
+
 int Client::_read(Fh *f, int64_t offset, uint64_t size, bufferlist *bl)
 {
   const md_config_t *conf = cct->_conf;
@@ -7450,13 +7451,63 @@ int Client::write(int fd, const char *buf, loff_t size, loff_t offset)
   if (fh->flags & O_PATH)
     return -EBADF;
 #endif
-  int r = _write(fh, offset, size, buf);
+  int r = _write(fh, offset, size, buf, NULL, 0);
   ldout(cct, 3) << "write(" << fd << ", \"...\", " << size << ", " << offset << ") = " << r << dendl;
   return r;
 }
 
+int Client::pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset)
+{
+    return _preadv_pwritev(fd, iov, iovcnt, offset, true); 
+}
+
+int Client::_preadv_pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset, bool write)
+{
+    Mutex::Locker lock(client_lock);
+    tout(cct) << fd << std::endl;
+    tout(cct) << offset << std::endl;
+
+    Fh *fh = get_filehandle(fd);
+    if (!fh)
+        return -EBADF;
+#if defined(__linux__) && defined(O_PATH)
+    if (fh->flags & O_PATH)
+        return -EBADF;
+#endif
+    loff_t totallen = 0;
+    for (int i = 0; i < iovcnt; i++) {
+        totallen += iov[i].iov_len;
+    }
+    if (write) {
+        int w = _write(fh, offset, totallen, NULL, iov, iovcnt);
+        ldout(cct, 3) << "write(" << fd << ", \"...\", " << totallen << ", " << offset << ") = " << w << dendl;
+        return w;
+    } else {
+        bufferlist bl;
+        int r = _read(fh, offset, totallen, &bl);
+        ldout(cct, 3) << "read(" << fd << ", " <<  offset << ") = " << r << dendl;
+        int bufoff = 0;
+        uint32_t rlen = 0;
+        for (int j = 0, tmplen = r; j < iovcnt && tmplen > 0; j++) {
+               /*
+                * This piece of code aims to handle the case that bufferlist does no have enough data 
+                * to fill in the iov 
+                */
+               if (tmplen < iov[j].iov_len) {
+                    bl.copy(bufoff, tmplen, (char *)iov[j].iov_base);
+                    break;
+               } else {
+                    bl.copy(bufoff, iov[j].iov_len, (char *)iov[j].iov_base);
+               }
+               tmplen -= iov[j].iov_len;
+               bufoff += iov[j].iov_len;
+        }
+        return r;  
+    }
+}
 
-int Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf)
+int Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf,
+                  const struct iovec *iov, int iovcnt)
 {
   if ((uint64_t)(offset+size) > mdsmap->get_max_filesize()) //too large!
     return -EFBIG;
@@ -7508,10 +7559,20 @@ int Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf)
   }
 
   // copy into fresh buffer (since our write may be resub, async)
-  bufferptr bp;
-  if (size > 0) bp = buffer::copy(buf, size);
   bufferlist bl;
-  bl.push_back( bp );
+  bufferptr *bparr;
+  if (buf) {
+      bufferptr bp;
+      if (size > 0) bp = buffer::copy(buf, size);
+      bl.push_back( bp );
+  } else if (iov){
+      //iov case 
+      bparr = new bufferptr[iovcnt];
+      for (int i = 0; i < iovcnt; i++) {
+        if (iov[i].iov_len > 0) bparr[i] = buffer::copy((char*)iov[i].iov_base, iov[i].iov_len);
+        bl.push_back( bparr[i] );
+      }
+  }
 
   utime_t lat;
   uint64_t totalwritten;
@@ -7659,6 +7720,9 @@ done:
   }
 
   put_cap_ref(in, CEPH_CAP_FILE_WR);
+  if (buf == NULL && iov != NULL) {
+    delete[] bparr; 
+  }
   return r;
 }
 
@@ -10205,7 +10269,7 @@ int Client::ll_write(Fh *fh, loff_t off, loff_t len, const char *data)
   tout(cct) << off << std::endl;
   tout(cct) << len << std::endl;
 
-  int r = _write(fh, off, len, data);
+  int r = _write(fh, off, len, data, NULL, 0);
   ldout(cct, 3) << "ll_write " << fh << " " << off << "~" << len << " = " << r
                << dendl;
   return r;
index 4f1b77c775312f1a978eb69afa2620788169938a..a1ad18c417cd74c9e8436cf6e65c8ddb2faddf43 100644 (file)
@@ -678,7 +678,9 @@ private:
              bool *created = NULL, int uid=-1, int gid=-1);
   loff_t _lseek(Fh *fh, loff_t offset, int whence);
   int _read(Fh *fh, int64_t offset, uint64_t size, bufferlist *bl);
-  int _write(Fh *fh, int64_t offset, uint64_t size, const char *buf);
+  int _write(Fh *fh, int64_t offset, uint64_t size, const char *buf,
+          const struct iovec *iov, int iovcnt);
+  int _preadv_pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset, bool write);
   int _flush(Fh *fh);
   int _fsync(Fh *fh, bool syncdataonly);
   int _sync_fs();
@@ -846,7 +848,9 @@ public:
   int close(int fd);
   loff_t lseek(int fd, loff_t offset, int whence);
   int read(int fd, char *buf, loff_t size, loff_t offset=-1);
+  int preadv(int fd, const struct iovec *iov, int iovcnt, loff_t offset=-1);
   int write(int fd, const char *buf, loff_t size, loff_t offset=-1);
+  int pwritev(int fd, const struct iovec *iov, int iovcnt, loff_t offset=-1);
   int fake_write_size(int fd, loff_t size);
   int ftruncate(int fd, loff_t size);
   int fsync(int fd, bool syncdataonly);
index 26e09a288e77a114d101bd2de4334b87847793ef..45585f494be7e72cec119c7696ce675093d12a35 100644 (file)
@@ -799,6 +799,19 @@ int64_t ceph_lseek(struct ceph_mount_info *cmount, int fd, int64_t offset, int w
  */
 int ceph_read(struct ceph_mount_info *cmount, int fd, char *buf, int64_t size, int64_t offset);
 
+/**
+ * Read data from the file.
+ * @param cmount the ceph mount handle to use for performing the read.
+ * @param fd the file descriptor of the open file to read from.
+ * @param iov the iov structure to read data into
+ * @param iovcnt the number of items that iov includes
+ * @param offset the offset in the file to read from.  If this value is negative, the
+ *        function reads from the current offset of the file descriptor.
+ * @returns the number of bytes read into buf, or a negative error code on failure.
+ */
+int ceph_preadv(struct ceph_mount_info *cmount, int fd, const struct iovec *iov, int iovcnt,
+           int64_t offset);
+
 /**
  * Write data to a file.
  *
@@ -813,6 +826,20 @@ int ceph_read(struct ceph_mount_info *cmount, int fd, char *buf, int64_t size, i
 int ceph_write(struct ceph_mount_info *cmount, int fd, const char *buf, int64_t size,
               int64_t offset);
 
+/**
+ * Write data to a file.
+ *
+ * @param cmount the ceph mount handle to use for performing the write.
+ * @param fd the file descriptor of the open file to write to
+ * @param iov the iov structure to read data into
+ * @param iovcnt the number of items that iov includes
+ * @param offset the offset of the file write into.  If this value is negative, the
+ *        function writes to the current offset of the file descriptor.
+ * @returns the number of bytes written, or a negative error code
+ */
+int ceph_pwritev(struct ceph_mount_info *cmount, int fd, const struct iovec *iov, int iovcnt,
+           int64_t offset);
+
 /**
  * Truncate a file to the given size.
  *
index aa387ffd6948db3c669ede2d78ea5b40f4c84fa5..13d85c7e2814d880cf0d4a16df93a3178ebc10d3 100644 (file)
@@ -812,6 +812,14 @@ extern "C" int ceph_read(struct ceph_mount_info *cmount, int fd, char *buf,
   return cmount->get_client()->read(fd, buf, size, offset);
 }
 
+extern "C" int ceph_preadv(struct ceph_mount_info *cmount, int fd,
+              const struct iovec *iov, int iovcnt, int64_t offset)
+{
+  if (!cmount->is_mounted())
+      return -ENOTCONN;
+  return cmount->get_client()->preadv(fd, iov, iovcnt, offset);
+}
+
 extern "C" int ceph_write(struct ceph_mount_info *cmount, int fd, const char *buf,
                          int64_t size, int64_t offset)
 {
@@ -820,6 +828,14 @@ extern "C" int ceph_write(struct ceph_mount_info *cmount, int fd, const char *bu
   return cmount->get_client()->write(fd, buf, size, offset);
 }
 
+extern "C" int ceph_pwritev(struct ceph_mount_info *cmount, int fd,
+              const struct iovec *iov, int iovcnt, int64_t offset)
+{
+  if (!cmount->is_mounted())
+    return -ENOTCONN;
+  return cmount->get_client()->pwritev(fd, iov, iovcnt, offset);
+}
+
 extern "C" int ceph_ftruncate(struct ceph_mount_info *cmount, int fd, int64_t size)
 {
   if (!cmount->is_mounted())