]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: drop Fr cap before gettattr CEPH_STAT_CAP_SIZE
authorYan, Zheng <zheng.z.yan@intel.com>
Fri, 4 Apr 2014 01:06:27 +0000 (09:06 +0800)
committerYan, Zheng <zheng.z.yan@intel.com>
Fri, 4 Apr 2014 16:48:47 +0000 (00:48 +0800)
When MDS receives the getattr request, corresponding inode's filelock
can be in unstable state which waits for client's Fr cap.

Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
src/client/Client.cc
src/client/Client.h

index 332d2d28ac3bb4b25f5848b8ce0c748ade76e49f..f6fa1225879cd8bd8ce9b727389b3e74aeb61fbf 100644 (file)
@@ -6026,6 +6026,14 @@ int Client::_read(Fh *f, int64_t offset, uint64_t size, bufferlist *bl)
 
   //bool lazy = f->mode == CEPH_FILE_MODE_LAZY;
 
+  bool movepos = false;
+  if (offset < 0) {
+    lock_fh_pos(f);
+    offset = f->pos;
+    movepos = true;
+  }
+  loff_t start_pos = offset;
+
   if (in->inline_version == 0) {
     int r = _getattr(in, CEPH_STAT_CAP_INLINE_DATA, -1, -1, true);
     if (r < 0)
@@ -6033,18 +6041,12 @@ int Client::_read(Fh *f, int64_t offset, uint64_t size, bufferlist *bl)
     assert(in->inline_version > 0);
   }
 
+retry:
   int have;
   int r = get_caps(in, CEPH_CAP_FILE_RD, CEPH_CAP_FILE_CACHE, &have, -1);
   if (r < 0)
     return r;
 
-  bool movepos = false;
-  if (offset < 0) {
-    lock_fh_pos(f);
-    offset = f->pos;
-    movepos = true;
-  }
-
   Mutex uninline_flock("Clinet::_read_uninline_data flock");
   Cond uninline_cond;
   bool uninline_done = false;
@@ -6087,25 +6089,33 @@ int Client::_read(Fh *f, int64_t offset, uint64_t size, bufferlist *bl)
       _flush_range(in, offset, size);
     }
     r = _read_async(f, offset, size, bl);
+    if (r < 0)
+      goto done;
   } else {
-    r = _read_sync(f, offset, size, bl);
-  }
-
-  // don't move pointer if the read failed
-  if (r < 0) {
-    goto done;
-  }
+    bool checkeof = false;
+    r = _read_sync(f, offset, size, bl, &checkeof);
+    if (r < 0)
+      goto done;
+    if (checkeof) {
+      offset += r;
+      size -= r;
 
-success:
+      put_cap_ref(in, CEPH_CAP_FILE_RD);
+      have = 0;
+      // reverify size
+      r = _getattr(in, CEPH_STAT_CAP_SIZE);
+      if (r < 0)
+       goto done;
 
-  if (movepos) {
-    // adjust fd pos
-    f->pos = offset+bl->length();
-    unlock_fh_pos(f);
+      // eof?  short read.
+      if ((uint64_t)offset < in->size)
+       goto retry;
+    }
   }
 
+success:
   // adjust readahead state
-  if (f->last_pos != offset) {
+  if (f->last_pos != start_pos) {
     f->nr_consec_read = f->consec_read_bytes = 0;
   } else {
     f->nr_consec_read++;
@@ -6113,9 +6123,15 @@ success:
   f->consec_read_bytes += bl->length();
   ldout(cct, 10) << "readahead nr_consec_read " << f->nr_consec_read
           << " for " << f->consec_read_bytes << " bytes" 
-          << " .. last_pos " << f->last_pos << " .. offset " << offset
-          << dendl;
-  f->last_pos = offset+bl->length();
+          << " .. last_pos " << f->last_pos << " .. offset "
+          << start_pos << dendl;
+
+  f->last_pos = start_pos + bl->length();
+  if (movepos) {
+    // adjust fd pos
+    f->pos = f->last_pos;
+    unlock_fh_pos(f);
+  }
 
 done:
   // done!
@@ -6137,8 +6153,9 @@ done:
       r = uninline_ret;
   }
 
-  put_cap_ref(in, CEPH_CAP_FILE_RD);
-  return r;
+  if (have)
+    put_cap_ref(in, CEPH_CAP_FILE_RD);
+  return r < 0 ? r : bl->length();
 }
 
 int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl)
@@ -6238,7 +6255,8 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl)
   return r;
 }
 
-int Client::_read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl)
+int Client::_read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl,
+                      bool *checkeof)
 {
   Inode *in = f->inode;
   uint64_t pos = off;
@@ -6297,14 +6315,8 @@ int Client::_read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl)
          return read;
       }
 
-      // reverify size
-      r = _getattr(in, CEPH_STAT_CAP_SIZE);
-      if (r < 0)
-       return r;
-
-      // eof?  short read.
-      if (pos >= in->size)
-       return read;
+      *checkeof = true;
+      return read;
     }
   }
   return read;
index df13b6febfc5b2c0790c64f010ff4250f895f6a7..c67522d4926793755302b92e63258bdeea028f46 100644 (file)
@@ -570,7 +570,7 @@ private:
     }
   };
 
-  int _read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl);
+  int _read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, bool *checkeof);
   int _read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl);
 
   // internal interface