From: Yan, Zheng Date: Wed, 8 Jul 2015 02:11:43 +0000 (+0800) Subject: client: reference counting 'struct Fh' X-Git-Tag: v0.94.3~23^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F5222%2Fhead;p=ceph.git client: reference counting 'struct Fh' The async readahead finisher needs to reference 'struct Fh'. But it's possible user closes FD and free the corresponding 'struct Fh' before async readahead finishes. Fixes: #12088 Signed-off-by: Yan, Zheng (cherry picked from commit 34b939a81d38173b882c429b28dedce778504ba8) --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 63a9faa93a4ca..fc3b52a254273 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -254,8 +254,7 @@ void Client::tear_down_cache() ++it) { Fh *fh = it->second; ldout(cct, 1) << "tear_down_cache forcing close of fh " << it->first << " ino " << fh->inode->ino << dendl; - put_inode(fh->inode); - delete fh; + _release_fh(fh); } fd_map.clear(); @@ -6697,12 +6696,20 @@ int Client::_release_fh(Fh *f) ldout(cct, 10) << "_release_fh " << f << " on inode " << *in << " no async_err state" << dendl; } - put_inode(in); - delete f; + _put_fh(f); return err; } +void Client::_put_fh(Fh *f) +{ + int left = f->put(); + if (!left) { + put_inode(f->inode); + delete f; + } +} + int Client::_open(Inode *in, int flags, mode_t mode, Fh **fhp, int uid, int gid) { int cmode = ceph_flags_to_mode(flags); @@ -7042,10 +7049,16 @@ done: return r < 0 ? r : bl->length(); } +Client::C_Readahead::C_Readahead(Client *c, Fh *f) : + client(c), f(f) { + f->get(); +} + void Client::C_Readahead::finish(int r) { lgeneric_subdout(client->cct, client, 20) << "client." << client->get_nodeid() << " " << "C_Readahead on " << f->inode << dendl; client->put_cap_ref(f->inode, CEPH_CAP_FILE_RD | CEPH_CAP_FILE_CACHE); f->readahead.dec_pending(); + client->_put_fh(f); } int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl) diff --git a/src/client/Client.h b/src/client/Client.h index 074887d966041..14f47accae93b 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -628,14 +628,13 @@ private: Fh *_create_fh(Inode *in, int flags, int cmode); int _release_fh(Fh *fh); + void _put_fh(Fh *fh); struct C_Readahead : public Context { Client *client; Fh *f; - C_Readahead(Client *c, Fh *f) - : client(c), - f(f) { } + C_Readahead(Client *c, Fh *f); void finish(int r); }; diff --git a/src/client/Fh.h b/src/client/Fh.h index 6f0aebd5d941a..dcf70cdbbe991 100644 --- a/src/client/Fh.h +++ b/src/client/Fh.h @@ -11,7 +11,8 @@ class ceph_lock_state_t; // file handle for any open file state struct Fh { - Inode *inode; + int _ref; + Inode *inode; loff_t pos; int mds; // have to talk to mds we opened with (for now) int mode; // the mode i opened the file with @@ -26,8 +27,10 @@ struct Fh { ceph_lock_state_t *fcntl_locks; ceph_lock_state_t *flock_locks; - Fh() : inode(0), pos(0), mds(0), mode(0), flags(0), pos_locked(false), + Fh() : _ref(1), inode(0), pos(0), mds(0), mode(0), flags(0), pos_locked(false), readahead(), fcntl_locks(NULL), flock_locks(NULL) {} + void get() { ++_ref; } + int put() { return --_ref; } };