]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: pin Inode during readahead
authorSage Weil <sage@inktank.com>
Thu, 27 Mar 2014 04:52:00 +0000 (21:52 -0700)
committerSage Weil <sage@inktank.com>
Fri, 28 Mar 2014 22:56:40 +0000 (15:56 -0700)
Make sure the Inode does not go away while a readahead is in progress.  In
particular:

 - read_async
   - start a readahead
   - get actual read from cache, return
 - close/release
   - call ObjectCacher::release_set() and get unclean > 0, assert

Fixes: #7867
Backport: emperor, dumpling
Signed-off-by: Sage Weil <sage@inktank.com>
(cherry picked from commit f1c7b4ef0cd064a9cb86757f17118d17913850db)

src/client/Client.cc
src/client/Client.h

index e4dd8c0668c1d5b936fcb4b2941eac72ddb9a670..afa089913e44ae79fdfebf3cf996b79c571a3f99 100644 (file)
@@ -5883,8 +5883,17 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl)
       if (objectcacher->file_is_cached(&in->oset, &in->layout, in->snapid, off, min))
        ldout(cct, 20) << "readahead already have min" << dendl;
       else {
-       objectcacher->file_read(&in->oset, &in->layout, in->snapid, off, l, NULL, 0, 0);
-       ldout(cct, 20) << "readahead initiated" << dendl;
+       Context *onfinish = new C_Readahead(this, in);
+       int r = objectcacher->file_read(&in->oset, &in->layout, in->snapid,
+                                       off, l,
+                                       NULL, 0, onfinish);
+       if (r == 0) {
+         ldout(cct, 20) << "readahead initiated, c " << onfinish << dendl;
+         in->get();
+       } else {
+         ldout(cct, 20) << "readahead was no-op, already cached" << dendl;
+         delete onfinish;
+       }
       }
     }
   }
index 649bacc5ba69461a03e08551715709051424c0b9..6b24f9ad0a918116e600cc91c824abf805fc6212 100644 (file)
@@ -542,6 +542,19 @@ private:
   Fh *_create_fh(Inode *in, int flags, int cmode);
   int _release_fh(Fh *fh);
 
+
+  struct C_Readahead : public Context {
+    Client *client;
+    Inode *inode;
+    C_Readahead(Client *c, Inode *i)
+      : client(c),
+       inode(i) { }
+    void finish(int r) {
+      lsubdout(client->cct, client, 20) << "C_Readahead on " << inode << dendl;
+      client->put_inode(inode, 1);
+    }
+  };
+
   int _read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl);
   int _read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl);