]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/newstore: only ftruncate if i_size is incorrect
authorSage Weil <sage@redhat.com>
Wed, 29 Apr 2015 21:51:00 +0000 (14:51 -0700)
committerSage Weil <sage@redhat.com>
Tue, 1 Sep 2015 17:39:42 +0000 (13:39 -0400)
Even a no-op ftruncate can block in the kernel.  Prior to this change I
could frequently see ftruncate wait for an aio completion on the same
file.

Signed-off-by: Sage Weil <sage@redhat.com>
src/os/newstore/NewStore.cc
src/os/newstore/NewStore.h

index 33c322a2c2360fc62cfab7f51193e420bfbcb7e5..de2f893a628cd7741885e82146379bd3796a7b05 100644 (file)
@@ -3346,7 +3346,10 @@ int NewStore::_do_write(TransContext *txc,
        r = fd;
        goto out;
       }
-      ::ftruncate(fd, f.length);  // in case there is trailing crap
+      r = _clean_fid_tail_fd(f, fd); // in case there is trailing crap
+      if (r < 0) {
+       goto out;
+      }
       f.length = (offset + length) - f.offset;
       x_offset = offset - f.offset;
       dout(20) << __func__ << " append " << f.fid << " writing "
@@ -3458,12 +3461,8 @@ int NewStore::_do_write(TransContext *txc,
   return r;
 }
 
-int NewStore::_clean_fid_tail(TransContext *txc, const fragment_t& f)
+int NewStore::_clean_fid_tail_fd(const fragment_t& f, int fd)
 {
-  int fd = _open_fid(f.fid, O_RDWR);
-  if (fd < 0) {
-    return fd;
-  }
   struct stat st;
   int r = ::fstat(fd, &st);
   if (r < 0) {
@@ -3481,6 +3480,22 @@ int NewStore::_clean_fid_tail(TransContext *txc, const fragment_t& f)
           << cpp_strerror(r) << dendl;
       return r;
     }
+    return 1;
+  }
+  return 0;
+}
+
+int NewStore::_clean_fid_tail(TransContext *txc, const fragment_t& f)
+{
+  int fd = _open_fid(f.fid, O_RDWR);
+  if (fd < 0) {
+    return fd;
+  }
+  int r = _clean_fid_tail_fd(f, fd);
+  if (r < 0) {
+    return r;
+  }
+  if (r > 0) {
     txc->sync_fd(fd);
   } else {
     // all good!
index c4cdc2bd3f2e854e1f65d76841709c00449dcaee..6d6a28dabfe8050436fe64055851414fd4b12c7a 100644 (file)
@@ -544,6 +544,7 @@ private:
   int _recover_next_nid();
   void _assign_nid(TransContext *txc, OnodeRef o);
 
+  int _clean_fid_tail_fd(const fragment_t& f, int fd);
   int _clean_fid_tail(TransContext *txc, const fragment_t& f);
 
   TransContext *_txc_create(OpSequencer *osr);