]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
FileStore:Use pwritev instead of writev
authorchangtao <changtao@hihuron.com>
Fri, 27 Nov 2015 13:54:27 +0000 (21:54 +0800)
committerHaomai Wang <haomai@xsky.com>
Mon, 25 Jan 2016 16:49:10 +0000 (00:49 +0800)
Signed-off-by: Tao Chang <changtao@hihuron.com>
src/common/buffer.cc
src/include/buffer.h
src/os/filestore/FileStore.cc
src/test/bufferlist.cc

index e2de936d8c43410e58234381c87de172244de46d..f3c6f6dfe62a5e916fb5380f6e0d65a3e6a2d027 100644 (file)
@@ -2007,6 +2007,59 @@ int buffer::list::write_fd(int fd) const
   return 0;
 }
 
+int buffer::list::write_fd(int fd, uint64_t offset) const
+{
+  // use writev!
+  iovec iov[IOV_MAX];
+  int iovlen = 0;
+  ssize_t bytes = 0;
+
+  std::list<ptr>::const_iterator p = _buffers.begin();
+  while (p != _buffers.end()) {
+    if (p->length() > 0) {
+      iov[iovlen].iov_base = (void *)p->c_str();
+      iov[iovlen].iov_len = p->length();
+      bytes += p->length();
+      iovlen++;
+    }
+    ++p;
+
+    if (iovlen == IOV_MAX-1 ||
+       p == _buffers.end()) {
+      iovec *start = iov;
+      int num = iovlen;
+      ssize_t wrote;
+    retry:
+      wrote = ::pwritev(fd, start, num, offset);
+      if (wrote < 0) {
+       int err = errno;
+       if (err == EINTR)
+         goto retry;
+       return -err;
+      }
+      offset += wrote;
+      if (wrote < bytes) {
+       // partial write, recover!
+       while ((size_t)wrote >= start[0].iov_len) {
+         wrote -= start[0].iov_len;
+         bytes -= start[0].iov_len;
+         start++;
+         num--;
+       }
+       if (wrote > 0) {
+         start[0].iov_len -= wrote;
+         start[0].iov_base = (char *)start[0].iov_base + wrote;
+         bytes -= wrote;
+       }
+       goto retry;
+      }
+      iovlen = 0;
+      bytes = 0;
+    }
+  }
+  return 0;
+}
+
 void buffer::list::prepare_iov(std::vector<iovec> *piov) const
 {
   piov->resize(_buffers.size());
index 5a8b05f5125f9b9bbd673a8f832fdaece25efb0a..428f0e3fcacb54a37f28d72c6c7ca969480bae6d 100644 (file)
@@ -528,6 +528,7 @@ namespace buffer CEPH_BUFFER_API {
     int read_fd_zero_copy(int fd, size_t len);
     int write_file(const char *fn, int mode=0644);
     int write_fd(int fd) const;
+    int write_fd(int fd, uint64_t offset) const;
     int write_fd_zero_copy(int fd) const;
     void prepare_iov(std::vector<iovec> *piov) const;
     uint32_t crc32c(uint32_t crc) const;
index 5cb73e7b01a3291b40ed321a7c0137c966bc192b..89d728e34a7a22311c7c48945eb05406a2f8bc43 100644 (file)
@@ -3188,8 +3188,6 @@ int FileStore::_write(coll_t cid, const ghobject_t& oid,
   dout(15) << "write " << cid << "/" << oid << " " << offset << "~" << len << dendl;
   int r;
 
-  int64_t actual;
-
   FDRef fd;
   r = lfn_open(cid, oid, true, &fd);
   if (r < 0) {
@@ -3199,23 +3197,8 @@ int FileStore::_write(coll_t cid, const ghobject_t& oid,
     goto out;
   }
 
-  // seek
-  actual = ::lseek64(**fd, offset, SEEK_SET);
-  if (actual < 0) {
-    r = -errno;
-    dout(0) << "write lseek64 to " << offset << " failed: " << cpp_strerror(r) << dendl;
-    lfn_close(fd);
-    goto out;
-  }
-  if (actual != (int64_t)offset) {
-    dout(0) << "write lseek64 to " << offset << " gave bad offset " << actual << dendl;
-    r = -EIO;
-    lfn_close(fd);
-    goto out;
-  }
-
   // write
-  r = bl.write_fd(**fd);
+  r = bl.write_fd(**fd, offset);
   if (r == 0)
     r = bl.length();
 
index 77ca3ec2750aae21b3cc60e353b8429c7446c290..06e100748771f1f191aca5adefcb3bef77fcfc7f 100644 (file)
@@ -2143,6 +2143,24 @@ TEST(BufferList, write_fd) {
   ::unlink(FILENAME);
 }
 
+TEST(BufferList, write_fd_offset) {
+  ::unlink(FILENAME);
+  int fd = ::open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600);
+  bufferlist bl;
+  for (unsigned i = 0; i < IOV_MAX * 2; i++) {
+    bufferptr ptr("A", 1);
+    bl.push_back(ptr);
+  }
+  uint64_t offset = 200;
+  EXPECT_EQ(0, bl.write_fd(fd, offset));
+  ::close(fd);
+  struct stat st;
+  memset(&st, 0, sizeof(st));
+  ::stat(FILENAME, &st);
+  EXPECT_EQ(IOV_MAX * 2 + offset, st.st_size);
+  ::unlink(FILENAME);
+}
+
 TEST(BufferList, crc32c) {
   bufferlist bl;
   __u32 crc = 0;