From: Sage Weil Date: Fri, 17 Aug 2012 16:02:10 +0000 (-0700) Subject: mds: do not return null dentry lease on getattr X-Git-Tag: v0.51~11 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5e761b4e1545a713e1409fa3bcca578071edff7d;p=ceph.git mds: do not return null dentry lease on getattr Specifically, /foo may exist and client may try to mount /foo/bar. That GETATTR request is on #1/foo/bar, but we cannot return a null dentry on bar because the client is not prepared to handle it and will crash in fill_trace(). Fixes: #2959 Reported-by: Yan Zheng Signed-off-by: Sage Weil --- diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 1e55e6b74615..e35dc730143c 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -1124,8 +1124,11 @@ void Server::dispatch_client_request(MDRequest *mdr) // inodes ops. case CEPH_MDS_OP_LOOKUP: case CEPH_MDS_OP_LOOKUPSNAP: + handle_client_getattr(mdr, true); + break; + case CEPH_MDS_OP_GETATTR: - handle_client_stat(mdr); + handle_client_getattr(mdr, false); break; case CEPH_MDS_OP_LOOKUPPARENT: @@ -1859,7 +1862,8 @@ CInode* Server::rdlock_path_pin_ref(MDRequest *mdr, int n, bool want_auth, bool no_want_auth, /* for readdir, who doesn't want auth _even_if_ it's a snapped dir */ - ceph_file_layout **layout) + ceph_file_layout **layout, + bool no_lookup) // true if we cannot return a null dentry lease { MClientRequest *req = mdr->client_request; const filepath& refpath = n ? req->get_filepath2() : req->get_filepath(); @@ -1874,7 +1878,7 @@ CInode* Server::rdlock_path_pin_ref(MDRequest *mdr, int n, if (r > 0) return false; // delayed if (r < 0) { // error if (r == -ENOENT && n == 0 && mdr->dn[n].size()) { - reply_request(mdr, r, NULL, mdr->dn[n][mdr->dn[n].size()-1]); + reply_request(mdr, r, NULL, no_lookup ? NULL : mdr->dn[n][mdr->dn[n].size()-1]); } else if (r == -ESTALE) { dout(10) << "FAIL on ESTALE but attempting recovery" << dendl; Context *c = new C_MDS_TryFindInode(this, mdr); @@ -2086,11 +2090,11 @@ CDir* Server::try_open_auth_dirfrag(CInode *diri, frag_t fg, MDRequest *mdr) // =============================================================================== // STAT -void Server::handle_client_stat(MDRequest *mdr) +void Server::handle_client_getattr(MDRequest *mdr, bool is_lookup) { MClientRequest *req = mdr->client_request; set rdlocks, wrlocks, xlocks; - CInode *ref = rdlock_path_pin_ref(mdr, 0, rdlocks, false); + CInode *ref = rdlock_path_pin_ref(mdr, 0, rdlocks, false, false, NULL, !is_lookup); if (!ref) return; /* @@ -2123,7 +2127,7 @@ void Server::handle_client_stat(MDRequest *mdr) // reply dout(10) << "reply to stat on " << *req << dendl; reply_request(mdr, 0, ref, - req->get_op() == CEPH_MDS_OP_LOOKUP ? mdr->dn[0].back() : 0); + is_lookup ? mdr->dn[0].back() : 0); } /* This function will clean up the passed mdr*/ diff --git a/src/mds/Server.h b/src/mds/Server.h index ad8dced8691e..0611e3bbf26d 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -126,7 +126,8 @@ public: CInode* rdlock_path_pin_ref(MDRequest *mdr, int n, set& rdlocks, bool want_auth, bool no_want_auth=false, - ceph_file_layout **layout=NULL); + ceph_file_layout **layout=NULL, + bool no_lookup=false); CDentry* rdlock_path_xlock_dentry(MDRequest *mdr, int n, set& rdlocks, set& wrlocks, set& xlocks, bool okexist, bool mustexist, bool alwaysxlock, ceph_file_layout **layout=NULL); @@ -135,7 +136,7 @@ public: // requests on existing inodes. - void handle_client_stat(MDRequest *mdr); + void handle_client_getattr(MDRequest *mdr, bool is_lookup); void handle_client_lookup_parent(MDRequest *mdr); void handle_client_lookup_hash(MDRequest *mdr); void _lookup_hash_2(MDRequest *mdr, int r);