From: Yan, Zheng Date: Sat, 23 May 2015 12:01:46 +0000 (+0800) Subject: client: hold reference for returned inode X-Git-Tag: v9.1.0~442^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ad9c22a4ca56d7ad3c1666795bd8c9785eaccf70;p=ceph.git client: hold reference for returned inode CLient::make_request() returns pointer of target inode, but it does not increase reference count of the returned inode. The inode may get freed when CLient::make_request() releases MetaRequest. he fix is hold a reference for the returned inode. Since there are many of places use CLient::make_request() directly or indirectly, it's easy to leak reference. This patch uses intrusive_ptr to track the reference. Signed-off-by: Yan, Zheng --- diff --git a/src/client/Client.cc b/src/client/Client.cc index d4fb5a8cb95e..168eb37d52f6 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -742,7 +742,7 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, in = inode_map[st->vino]; ldout(cct, 12) << "add_update_inode had " << *in << " caps " << ccap_string(st->cap.caps) << dendl; } else { - in = new Inode(cct, st->vino, &st->layout); + in = new Inode(this, st->vino, &st->layout); inode_map[st->vino] = in; if (!root) { root = in; @@ -1361,7 +1361,7 @@ void Client::dump_mds_requests(Formatter *f) int Client::verify_reply_trace(int r, MetaRequest *request, MClientReply *reply, - Inode **ptarget, bool *pcreated, + InodeRef *ptarget, bool *pcreated, int uid, int gid) { // check whether this request actually did the create, and set created flag @@ -1384,17 +1384,17 @@ int Client::verify_reply_trace(int r, *pcreated = got_created_ino; if (request->target) { - *ptarget = request->target; - ldout(cct, 20) << "make_request target is " << *request->target << dendl; + (*ptarget) = request->target; + ldout(cct, 20) << "make_request target is " << *ptarget->get() << dendl; } else { if (got_created_ino && (p = inode_map.find(vinodeno_t(created_ino, CEPH_NOSNAP))) != inode_map.end()) { (*ptarget) = p->second; - ldout(cct, 20) << "make_request created, target is " << **ptarget << dendl; + ldout(cct, 20) << "make_request created, target is " << *ptarget->get() << dendl; } else { // we got a traceless reply, and need to look up what we just // created. for now, do this by name. someday, do this by the // ino... which we know! FIXME. - Inode *target = 0; // ptarget may be NULL + InodeRef target; Dentry *d = request->dentry(); if (d) { if (d->dir) { @@ -1416,15 +1416,14 @@ int Client::verify_reply_trace(int r, target = in; } if (r >= 0) { - if (ptarget) - *ptarget = target; - // verify ino returned in reply and trace_dist are the same if (got_created_ino && created_ino.val != target->ino.val) { ldout(cct, 5) << "create got ino " << created_ino << " but then failed on lookup; EINTR?" << dendl; r = -EINTR; } + if (ptarget) + ptarget->swap(target); } } } @@ -1455,7 +1454,7 @@ int Client::verify_reply_trace(int r, */ int Client::make_request(MetaRequest *request, int uid, int gid, - Inode **ptarget, bool *pcreated, + InodeRef *ptarget, bool *pcreated, int use_mds, bufferlist *pdirbl) { @@ -5108,7 +5107,7 @@ void Client::renew_caps(MetaSession *session) // =============================================================== // high level (POSIXy) interface -int Client::_do_lookup(Inode *dir, const string& name, Inode **target) +int Client::_do_lookup(Inode *dir, const string& name, InodeRef *target) { int op = dir->snapid == CEPH_SNAPDIR ? CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP; MetaRequest *req = new MetaRequest(op); @@ -5125,7 +5124,7 @@ int Client::_do_lookup(Inode *dir, const string& name, Inode **target) return r; } -int Client::_lookup(Inode *dir, const string& dname, Inode **target) +int Client::_lookup(Inode *dir, const string& dname, InodeRef *target) { int r = 0; Dentry *dn = NULL; @@ -5257,10 +5256,10 @@ int Client::get_or_create(Inode *dir, const char* name, return 0; } -int Client::path_walk(const filepath& origpath, Inode **final, bool followsym) +int Client::path_walk(const filepath& origpath, InodeRef *end, bool followsym) { filepath path = origpath; - Inode *cur; + InodeRef cur; if (origpath.absolute()) cur = root; else @@ -5276,8 +5275,8 @@ int Client::path_walk(const filepath& origpath, Inode **final, bool followsym) const string &dname = path[i]; ldout(cct, 10) << " " << i << " " << *cur << " " << dname << dendl; ldout(cct, 20) << " (path is " << path << ")" << dendl; - Inode *next; - int r = _lookup(cur, dname, &next); + InodeRef next; + int r = _lookup(cur.get(), dname, &next); if (r < 0) return r; // only follow trailing symlink if followsym. always follow @@ -5317,13 +5316,13 @@ int Client::path_walk(const filepath& origpath, Inode **final, bool followsym) continue; } } - cur = next; + cur.swap(next); i++; } if (!cur) return -ENOENT; - if (final) - *final = cur; + if (end) + end->swap(cur); return 0; } @@ -5342,18 +5341,15 @@ int Client::link(const char *relexisting, const char *relpath) string name = path.last_dentry(); path.pop_dentry(); - Inode *in, *dir; + InodeRef in, dir; int r; r = path_walk(existing, &in); if (r < 0) goto out; - in->get(); r = path_walk(path, &dir); if (r < 0) - goto out_unlock; - r = _link(in, dir, name.c_str()); - out_unlock: - put_inode(in); + goto out; + r = _link(in.get(), dir.get(), name.c_str()); out: return r; } @@ -5367,11 +5363,11 @@ int Client::unlink(const char *relpath) filepath path(relpath); string name = path.last_dentry(); path.pop_dentry(); - Inode *dir; + InodeRef dir; int r = path_walk(path, &dir); if (r < 0) return r; - return _unlink(dir, name.c_str()); + return _unlink(dir.get(), name.c_str()); } int Client::rename(const char *relfrom, const char *relto) @@ -5388,21 +5384,16 @@ int Client::rename(const char *relfrom, const char *relto) string toname = to.last_dentry(); to.pop_dentry(); - Inode *fromdir, *todir; + InodeRef fromdir, todir; int r; r = path_walk(from, &fromdir); if (r < 0) goto out; - fromdir->get(); r = path_walk(to, &todir); if (r < 0) - goto out_unlock; - todir->get(); - r = _rename(fromdir, fromname.c_str(), todir, toname.c_str()); - put_inode(todir); - out_unlock: - put_inode(fromdir); + goto out; + r = _rename(fromdir.get(), fromname.c_str(), todir.get(), toname.c_str()); out: return r; } @@ -5420,12 +5411,12 @@ int Client::mkdir(const char *relpath, mode_t mode) filepath path(relpath); string name = path.last_dentry(); path.pop_dentry(); - Inode *dir; + InodeRef dir; int r = path_walk(path, &dir); if (r < 0) { return r; } - return _mkdir(dir, name.c_str(), mode); + return _mkdir(dir.get(), name.c_str(), mode); } int Client::mkdirs(const char *relpath, mode_t mode) @@ -5440,12 +5431,12 @@ int Client::mkdirs(const char *relpath, mode_t mode) filepath path(relpath); unsigned int i; int r=0; - Inode *cur = cwd; - Inode *next; + InodeRef cur, next; + cur = cwd; for (i=0; iino).get_path() << dendl; } @@ -5479,11 +5470,11 @@ int Client::rmdir(const char *relpath) filepath path(relpath); string name = path.last_dentry(); path.pop_dentry(); - Inode *dir; + InodeRef dir; int r = path_walk(path, &dir); if (r < 0) return r; - return _rmdir(dir, name.c_str()); + return _rmdir(dir.get(), name.c_str()); } int Client::mknod(const char *relpath, mode_t mode, dev_t rdev) @@ -5496,11 +5487,11 @@ int Client::mknod(const char *relpath, mode_t mode, dev_t rdev) filepath path(relpath); string name = path.last_dentry(); path.pop_dentry(); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; - return _mknod(in, name.c_str(), mode, rdev); + return _mknod(in.get(), name.c_str(), mode, rdev); } // symlinks @@ -5515,11 +5506,11 @@ int Client::symlink(const char *target, const char *relpath) filepath path(relpath); string name = path.last_dentry(); path.pop_dentry(); - Inode *dir; + InodeRef dir; int r = path_walk(path, &dir); if (r < 0) return r; - return _symlink(dir, name.c_str(), target); + return _symlink(dir.get(), name.c_str(), target); } int Client::readlink(const char *relpath, char *buf, loff_t size) @@ -5529,12 +5520,12 @@ int Client::readlink(const char *relpath, char *buf, loff_t size) tout(cct) << relpath << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in, false); if (r < 0) return r; - return _readlink(in, buf, size); + return _readlink(in.get(), buf, size); } int Client::_readlink(Inode *in, char *buf, size_t size) @@ -5574,7 +5565,7 @@ int Client::_getattr(Inode *in, int mask, int uid, int gid, bool force) } int Client::_setattr(Inode *in, struct stat *attr, int mask, int uid, int gid, - Inode **inp) + InodeRef *inp) { int issued = in->caps_issued(); @@ -5703,11 +5694,11 @@ int Client::setattr(const char *relpath, struct stat *attr, int mask) tout(cct) << mask << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; - return _setattr(in, attr, mask); + return _setattr(in, attr, mask); } int Client::fsetattr(int fd, struct stat *attr, int mask) @@ -5724,7 +5715,7 @@ int Client::fsetattr(int fd, struct stat *attr, int mask) if (f->flags & O_PATH) return -EBADF; #endif - return _setattr(f->inode, attr, mask); + return _setattr(f->inode, attr, mask); } int Client::stat(const char *relpath, struct stat *stbuf, @@ -5735,7 +5726,7 @@ int Client::stat(const char *relpath, struct stat *stbuf, tout(cct) << "stat" << std::endl; tout(cct) << relpath << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; @@ -5757,7 +5748,7 @@ int Client::lstat(const char *relpath, struct stat *stbuf, tout(cct) << "lstat" << std::endl; tout(cct) << relpath << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; // don't follow symlinks int r = path_walk(path, &in, false); if (r < 0) @@ -5826,7 +5817,7 @@ int Client::chmod(const char *relpath, mode_t mode) tout(cct) << relpath << std::endl; tout(cct) << mode << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; @@ -5860,7 +5851,7 @@ int Client::lchmod(const char *relpath, mode_t mode) tout(cct) << relpath << std::endl; tout(cct) << mode << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; // don't follow symlinks int r = path_walk(path, &in, false); if (r < 0) @@ -5878,7 +5869,7 @@ int Client::chown(const char *relpath, int uid, int gid) tout(cct) << uid << std::endl; tout(cct) << gid << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; @@ -5922,7 +5913,7 @@ int Client::lchown(const char *relpath, int uid, int gid) tout(cct) << uid << std::endl; tout(cct) << gid << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; // don't follow symlinks int r = path_walk(path, &in, false); if (r < 0) @@ -5944,7 +5935,7 @@ int Client::utime(const char *relpath, struct utimbuf *buf) tout(cct) << buf->modtime << std::endl; tout(cct) << buf->actime << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; @@ -5964,7 +5955,7 @@ int Client::lutime(const char *relpath, struct utimbuf *buf) tout(cct) << buf->modtime << std::endl; tout(cct) << buf->actime << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; // don't follow symlinks int r = path_walk(path, &in, false); if (r < 0) @@ -5997,11 +5988,11 @@ int Client::opendir(const char *relpath, dir_result_t **dirpp) tout(cct) << "opendir" << std::endl; tout(cct) << relpath << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; - r = _opendir(in, dirpp); + r = _opendir(in.get(), dirpp); tout(cct) << (unsigned long)*dirpp << std::endl; return r; } @@ -6668,7 +6659,7 @@ int Client::open(const char *relpath, int flags, mode_t mode, int stripe_unit, #endif filepath path(relpath); - Inode *in; + InodeRef in; bool created = false; /* O_CREATE with O_EXCL enforces O_NOFOLLOW. */ bool followsym = !((flags & O_NOFOLLOW) || ((flags & O_CREAT) && (flags & O_EXCL))); @@ -6688,11 +6679,11 @@ int Client::open(const char *relpath, int flags, mode_t mode, int stripe_unit, filepath dirpath = path; string dname = dirpath.last_dentry(); dirpath.pop_dentry(); - Inode *dir; + InodeRef dir; r = path_walk(dirpath, &dir); if (r < 0) return r; - r = _create(dir, dname.c_str(), flags, mode, &in, &fh, stripe_unit, + r = _create(dir.get(), dname.c_str(), flags, mode, &in, &fh, stripe_unit, stripe_count, object_size, data_pool, &created); } if (r < 0) @@ -6702,17 +6693,16 @@ int Client::open(const char *relpath, int flags, mode_t mode, int stripe_unit, // posix says we can only check permissions of existing files uid_t uid = geteuid(); gid_t gid = getegid(); - r = check_permissions(in, flags, uid, gid); + r = check_permissions(in.get(), flags, uid, gid); if (r < 0) goto out; } if (!fh) - r = _open(in, flags, mode, &fh); + r = _open(in.get(), flags, mode, &fh); if (r >= 0) { // allocate a integer file descriptor assert(fh); - assert(in); r = get_fd(); assert(fd_map.count(r) == 0); fd_map[r] = fh; @@ -7918,14 +7908,14 @@ int Client::chdir(const char *relpath) tout(cct) << "chdir" << std::endl; tout(cct) << relpath << std::endl; filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; - if (cwd != in) { - in->get(); + if (cwd != in.get()) { put_inode(cwd); - cwd = in; + cwd = in.get(); + cwd->get(); } ldout(cct, 3) << "chdir(" << relpath << ") cwd now " << cwd->ino << dendl; return 0; @@ -8435,22 +8425,22 @@ int Client::mksnap(const char *relpath, const char *name) { Mutex::Locker l(client_lock); filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; - Inode *snapdir = open_snapdir(in); + Inode *snapdir = open_snapdir(in.get()); return _mkdir(snapdir, name, 0); } int Client::rmsnap(const char *relpath, const char *name) { Mutex::Locker l(client_lock); filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; - Inode *snapdir = open_snapdir(in); + Inode *snapdir = open_snapdir(in.get()); return _rmdir(snapdir, name); } @@ -8472,7 +8462,7 @@ int Client::get_caps_issued(const char *path) { Mutex::Locker lock(client_lock); filepath p(path); - Inode *in; + InodeRef in; int r = path_walk(p, &in, true); if (r < 0) return r; @@ -8487,7 +8477,7 @@ Inode *Client::open_snapdir(Inode *diri) Inode *in; vinodeno_t vino(diri->ino, CEPH_SNAPDIR); if (!inode_map.count(vino)) { - in = new Inode(cct, vino, &diri->layout); + in = new Inode(this, vino, &diri->layout); in->ino = diri->ino; in->snapid = CEPH_SNAPDIR; @@ -8519,7 +8509,7 @@ int Client::ll_lookup(Inode *parent, const char *name, struct stat *attr, tout(cct) << name << std::endl; string dname(name); - Inode *in; + InodeRef in; int r = 0; r = _lookup(parent, dname, &in); @@ -8530,40 +8520,38 @@ int Client::ll_lookup(Inode *parent, const char *name, struct stat *attr, assert(in); fill_stat(in, attr); - _ll_get(in); + _ll_get(in.get()); out: ldout(cct, 3) << "ll_lookup " << parent << " " << name << " -> " << r << " (" << hex << attr->st_ino << dec << ")" << dendl; tout(cct) << attr->st_ino << std::endl; - *out = in; + *out = in.get(); return r; } -int Client::ll_walk(const char* name, Inode **i, struct stat *attr) +int Client::ll_walk(const char* name, Inode **out, struct stat *attr) { Mutex::Locker lock(client_lock); filepath fp(name, 0); - Inode *destination = NULL; + InodeRef in; int rc; ldout(cct, 3) << "ll_walk" << name << dendl; tout(cct) << "ll_walk" << std::endl; tout(cct) << name << std::endl; - rc = path_walk(fp, &destination, false); - if (rc < 0) - { - attr->st_ino = 0; - *i = NULL; - return rc; - } - else - { - fill_stat(destination, attr); - *i = destination; - return 0; - } + rc = path_walk(fp, &in, false); + if (rc < 0) { + attr->st_ino = 0; + *out = NULL; + return rc; + } else { + assert(in); + fill_stat(in, attr); + *out = in.get(); + return 0; + } } @@ -8707,12 +8695,13 @@ int Client::ll_setattr(Inode *in, struct stat *attr, int mask, int uid, tout(cct) << attr->st_atime << std::endl; tout(cct) << mask << std::endl; - Inode *target = in; + InodeRef target(in); int res = _setattr(in, attr, mask, uid, gid, &target); if (res == 0) { - assert(in == target); + assert(in == target.get()); fill_stat(in, attr); } + ldout(cct, 3) << "ll_setattr " << vino << " = " << res << dendl; return res; } @@ -8724,21 +8713,21 @@ int Client::ll_setattr(Inode *in, struct stat *attr, int mask, int uid, int Client::getxattr(const char *path, const char *name, void *value, size_t size) { Mutex::Locker lock(client_lock); - Inode *ceph_inode; - int r = Client::path_walk(path, &ceph_inode, true); + InodeRef in; + int r = Client::path_walk(path, &in, true); if (r < 0) return r; - return Client::_getxattr(ceph_inode, name, value, size, getuid(), getgid()); + return Client::_getxattr(in.get(), name, value, size, getuid(), getgid()); } int Client::lgetxattr(const char *path, const char *name, void *value, size_t size) { Mutex::Locker lock(client_lock); - Inode *ceph_inode; - int r = Client::path_walk(path, &ceph_inode, false); + InodeRef in; + int r = Client::path_walk(path, &in, false); if (r < 0) return r; - return Client::_getxattr(ceph_inode, name, value, size, getuid(), getgid()); + return Client::_getxattr(in.get(), name, value, size, getuid(), getgid()); } int Client::fgetxattr(int fd, const char *name, void *value, size_t size) @@ -8753,21 +8742,21 @@ int Client::fgetxattr(int fd, const char *name, void *value, size_t size) int Client::listxattr(const char *path, char *list, size_t size) { Mutex::Locker lock(client_lock); - Inode *ceph_inode; - int r = Client::path_walk(path, &ceph_inode, true); + InodeRef in; + int r = Client::path_walk(path, &in, true); if (r < 0) return r; - return Client::_listxattr(ceph_inode, list, size, getuid(), getgid()); + return Client::_listxattr(in.get(), list, size, getuid(), getgid()); } int Client::llistxattr(const char *path, char *list, size_t size) { Mutex::Locker lock(client_lock); - Inode *ceph_inode; - int r = Client::path_walk(path, &ceph_inode, false); + InodeRef in; + int r = Client::path_walk(path, &in, false); if (r < 0) return r; - return Client::_listxattr(ceph_inode, list, size, getuid(), getgid()); + return Client::_listxattr(in.get(), list, size, getuid(), getgid()); } int Client::flistxattr(int fd, char *list, size_t size) @@ -8782,21 +8771,21 @@ int Client::flistxattr(int fd, char *list, size_t size) int Client::removexattr(const char *path, const char *name) { Mutex::Locker lock(client_lock); - Inode *ceph_inode; - int r = Client::path_walk(path, &ceph_inode, true); + InodeRef in; + int r = Client::path_walk(path, &in, true); if (r < 0) return r; - return Client::_removexattr(ceph_inode, name, getuid(), getgid()); + return Client::_removexattr(in.get(), name, getuid(), getgid()); } int Client::lremovexattr(const char *path, const char *name) { Mutex::Locker lock(client_lock); - Inode *ceph_inode; - int r = Client::path_walk(path, &ceph_inode, false); + InodeRef in; + int r = Client::path_walk(path, &in, false); if (r < 0) return r; - return Client::_removexattr(ceph_inode, name, getuid(), getgid()); + return Client::_removexattr(in.get(), name, getuid(), getgid()); } int Client::fremovexattr(int fd, const char *name) @@ -8811,21 +8800,21 @@ int Client::fremovexattr(int fd, const char *name) int Client::setxattr(const char *path, const char *name, const void *value, size_t size, int flags) { Mutex::Locker lock(client_lock); - Inode *ceph_inode; - int r = Client::path_walk(path, &ceph_inode, true); + InodeRef in; + int r = Client::path_walk(path, &in, true); if (r < 0) return r; - return Client::_setxattr(ceph_inode, name, value, size, flags, getuid(), getgid()); + return Client::_setxattr(in.get(), name, value, size, flags, getuid(), getgid()); } int Client::lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags) { Mutex::Locker lock(client_lock); - Inode *ceph_inode; - int r = Client::path_walk(path, &ceph_inode, false); + InodeRef in; + int r = Client::path_walk(path, &in, false); if (r < 0) return r; - return Client::_setxattr(ceph_inode, name, value, size, flags, getuid(), getgid()); + return Client::_setxattr(in.get(), name, value, size, flags, getuid(), getgid()); } int Client::fsetxattr(int fd, const char *name, const void *value, size_t size, int flags) @@ -9290,7 +9279,7 @@ int Client::ll_readlink(Inode *in, char *buf, size_t buflen, int uid, int gid) } int Client::_mknod(Inode *dir, const char *name, mode_t mode, dev_t rdev, - int uid, int gid, Inode **inp) + int uid, int gid, InodeRef *inp) { ldout(cct, 3) << "_mknod(" << dir->ino << " " << name << ", 0" << oct << mode << dec << ", " << rdev << ", uid " << uid << ", gid " @@ -9351,21 +9340,21 @@ int Client::ll_mknod(Inode *parent, const char *name, mode_t mode, tout(cct) << mode << std::endl; tout(cct) << rdev << std::endl; - Inode *in = NULL; + InodeRef in; int r = _mknod(parent, name, mode, rdev, uid, gid, &in); if (r == 0) { fill_stat(in, attr); - _ll_get(in); + _ll_get(in.get()); } tout(cct) << attr->st_ino << std::endl; ldout(cct, 3) << "ll_mknod " << vparent << " " << name << " = " << r << " (" << hex << attr->st_ino << dec << ")" << dendl; - *out = in; + *out = in.get(); return r; } int Client::_create(Inode *dir, const char *name, int flags, mode_t mode, - Inode **inp, Fh **fhp, int stripe_unit, int stripe_count, + InodeRef *inp, Fh **fhp, int stripe_unit, int stripe_count, int object_size, const char *data_pool, bool *created, int uid, int gid) { @@ -9430,7 +9419,7 @@ int Client::_create(Inode *dir, const char *name, int flags, mode_t mode, /* If the caller passed a value in fhp, do the open */ if(fhp) { (*inp)->get_open_ref(cmode); - *fhp = _create_fh(*inp, flags, cmode); + *fhp = _create_fh(inp->get(), flags, cmode); } reply_error: @@ -9450,7 +9439,7 @@ int Client::_create(Inode *dir, const char *name, int flags, mode_t mode, int Client::_mkdir(Inode *dir, const char *name, mode_t mode, int uid, int gid, - Inode **inp) + InodeRef *inp) { ldout(cct, 3) << "_mkdir(" << dir->ino << " " << name << ", 0" << oct << mode << dec << ", uid " << uid << ", gid " << gid << ")" @@ -9510,21 +9499,21 @@ int Client::ll_mkdir(Inode *parent, const char *name, mode_t mode, tout(cct) << name << std::endl; tout(cct) << mode << std::endl; - Inode *in = NULL; + InodeRef in; int r = _mkdir(parent, name, mode, uid, gid, &in); if (r == 0) { fill_stat(in, attr); - _ll_get(in); + _ll_get(in.get()); } tout(cct) << attr->st_ino << std::endl; ldout(cct, 3) << "ll_mkdir " << vparent << " " << name << " = " << r << " (" << hex << attr->st_ino << dec << ")" << dendl; - *out = in; + *out = in.get(); return r; } int Client::_symlink(Inode *dir, const char *name, const char *target, int uid, - int gid, Inode **inp) + int gid, InodeRef *inp) { ldout(cct, 3) << "_symlink(" << dir->ino << " " << name << ", " << target << ", uid " << uid << ", gid " << gid << ")" << dendl; @@ -9582,16 +9571,16 @@ int Client::ll_symlink(Inode *parent, const char *name, const char *value, tout(cct) << name << std::endl; tout(cct) << value << std::endl; - Inode *in = NULL; + InodeRef in; int r = _symlink(parent, name, value, uid, gid, &in); if (r == 0) { fill_stat(in, attr); - _ll_get(in); + _ll_get(in.get()); } tout(cct) << attr->st_ino << std::endl; ldout(cct, 3) << "ll_symlink " << vparent << " " << name << " = " << r << " (" << hex << attr->st_ino << dec << ")" << dendl; - *out = in; + *out = in.get(); return r; } @@ -9610,6 +9599,8 @@ int Client::_unlink(Inode *dir, const char *name, int uid, int gid) path.push_dentry(name); req->set_filepath(path); + InodeRef otherin; + Dentry *de; int res = get_or_create(dir, name, &de); if (res < 0) @@ -9618,11 +9609,10 @@ int Client::_unlink(Inode *dir, const char *name, int uid, int gid) req->dentry_drop = CEPH_CAP_FILE_SHARED; req->dentry_unless = CEPH_CAP_FILE_EXCL; - Inode *otherin; res = _lookup(dir, name, &otherin); if (res < 0) goto fail; - req->set_other_inode(otherin); + req->set_other_inode(otherin.get()); req->other_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL; req->set_inode(dir); @@ -9671,18 +9661,19 @@ int Client::_rmdir(Inode *dir, const char *name, int uid, int gid) req->dentry_unless = CEPH_CAP_FILE_EXCL; req->other_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL; + InodeRef in; + Dentry *de; int res = get_or_create(dir, name, &de); if (res < 0) goto fail; - Inode *in; res = _lookup(dir, name, &in); if (res < 0) goto fail; if (req->get_op() == CEPH_MDS_OP_RMDIR) { req->set_inode(dir); req->set_dentry(de); - req->set_other_inode(in); + req->set_other_inode(in.get()); } else { unlink(de, true, true); } @@ -9735,6 +9726,7 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch return -EXDEV; } + InodeRef target; MetaRequest *req = new MetaRequest(op); filepath from; @@ -9764,19 +9756,18 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch req->dentry_drop = CEPH_CAP_FILE_SHARED; req->dentry_unless = CEPH_CAP_FILE_EXCL; - Inode *oldin; + InodeRef oldin, otherin; res = _lookup(fromdir, fromname, &oldin); if (res < 0) goto fail; - req->set_old_inode(oldin); + req->set_old_inode(oldin.get()); req->old_inode_drop = CEPH_CAP_LINK_SHARED; - Inode *otherin; res = _lookup(todir, toname, &otherin); if (res != 0 && res != -ENOENT) { goto fail; } else if (res == 0) { - req->set_other_inode(otherin); + req->set_other_inode(otherin.get()); req->other_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL; } @@ -9788,9 +9779,7 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch unlink(de, true, true); } - Inode *target; res = make_request(req, uid, gid, &target); - ldout(cct, 10) << "rename result is " << res << dendl; // renamed item from our cache @@ -9823,7 +9812,7 @@ int Client::ll_rename(Inode *parent, const char *name, Inode *newparent, return _rename(parent, name, newparent, newname, uid, gid); } -int Client::_link(Inode *in, Inode *dir, const char *newname, int uid, int gid, Inode **inp) +int Client::_link(Inode *in, Inode *dir, const char *newname, int uid, int gid, InodeRef *inp) { ldout(cct, 3) << "_link(" << in->ino << " to " << dir->ino << " " << newname << " uid " << uid << " gid " << gid << ")" << dendl; @@ -9882,10 +9871,12 @@ int Client::ll_link(Inode *parent, Inode *newparent, const char *newname, tout(cct) << vnewparent << std::endl; tout(cct) << newname << std::endl; - int r = _link(parent, newparent, newname, uid, gid, &parent); + InodeRef target; + int r = _link(parent, newparent, newname, uid, gid, &target); if (r == 0) { - fill_stat(parent, attr); - _ll_get(parent); + assert(target); + fill_stat(target, attr); + _ll_get(target.get()); } return r; } @@ -10075,7 +10066,7 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode, tout(cct) << flags << std::endl; bool created = false; - Inode *in = NULL; + InodeRef in; int r = _lookup(parent, name, &in); if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL)) @@ -10086,9 +10077,6 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode, 0, 0, 0, NULL, &created, uid, gid); if (r < 0) goto out; - - if ((!in) && fhp) - in = (*fhp)->inode; } if (r < 0) @@ -10099,7 +10087,7 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode, ldout(cct, 20) << "ll_create created = " << created << dendl; if (!created) { - r = check_permissions(in, flags, uid, gid); + r = check_permissions(in.get(), flags, uid, gid); if (r < 0) { if (fhp && *fhp) { int release_r = _release_fh(*fhp); @@ -10108,7 +10096,7 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode, goto out; } if (fhp && (*fhp == NULL)) { - r = _open(in, flags, mode, fhp); + r = _open(in.get(), flags, mode, fhp); if (r < 0) goto out; } @@ -10128,8 +10116,8 @@ out: // passing an Inode in outp requires an additional ref if (outp) { if (in) - _ll_get(in); - *outp = in; + _ll_get(in.get()); + *outp = in.get(); } return r; @@ -10580,7 +10568,7 @@ int Client::describe_layout(const char *relpath, ceph_file_layout *lp) Mutex::Locker lock(client_lock); filepath path(relpath); - Inode *in; + InodeRef in; int r = path_walk(path, &in); if (r < 0) return r; @@ -11144,3 +11132,12 @@ void Client::handle_conf_change(const struct md_config_t *conf, } } +void intrusive_ptr_add_ref(Inode *in) +{ + in->get(); +} + +void intrusive_ptr_release(Inode *in) +{ + in->client->put_inode(in); +} diff --git a/src/client/Client.h b/src/client/Client.h index db015040c310..8117ad65dc61 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -47,12 +47,13 @@ using std::fstream; #include "common/Mutex.h" #include "common/Timer.h" #include "common/Finisher.h" - #include "common/compiler_extensions.h" #include "common/cmdparse.h" #include "osdc/ObjectCacher.h" +#include "InodeRef.h" + class MDSMap; class MonClient; @@ -117,7 +118,6 @@ struct DirEntry { DirEntry(const string &n, struct stat& s, int stm) : d_name(n), st(s), stmask(stm) {} }; -struct Inode; struct Cap; class Dir; class Dentry; @@ -300,13 +300,13 @@ public: int make_request(MetaRequest *req, int uid, int gid, //MClientRequest *req, int uid, int gid, - Inode **ptarget = 0, bool *pcreated = 0, + InodeRef *ptarget = 0, bool *pcreated = 0, int use_mds=-1, bufferlist *pdirbl=0); void put_request(MetaRequest *request); void unregister_request(MetaRequest *request); int verify_reply_trace(int r, MetaRequest *request, MClientReply *reply, - Inode **ptarget, bool *pcreated, int uid, int gid); + InodeRef *ptarget, bool *pcreated, int uid, int gid); void encode_cap_releases(MetaRequest *request, mds_rank_t mds); int encode_inode_release(Inode *in, MetaRequest *req, mds_rank_t mds, int drop, @@ -424,6 +424,7 @@ protected: friend class C_Client_SyncCommit; // Asserts on client_lock friend class C_Client_RequestInterrupt; friend class C_Client_Remount; + friend void intrusive_ptr_release(Inode *in); //int get_cache_size() { return lru.lru_get_size(); } //void set_cache_size(int m) { lru.lru_set_max(m); } @@ -438,8 +439,11 @@ protected: // path traversal for high-level interface Inode *cwd; - int path_walk(const filepath& fp, Inode **end, bool followsym=true); + int path_walk(const filepath& fp, InodeRef *end, bool followsym=true); int fill_stat(Inode *in, struct stat *st, frag_info_t *dirstat=0, nest_info_t *rstat=0); + int fill_stat(InodeRef& in, struct stat *st, frag_info_t *dirstat=0, nest_info_t *rstat=0) { + return fill_stat(in.get(), st, dirstat, rstat); + } void touch_dn(Dentry *dn); // trim cache. @@ -654,27 +658,34 @@ private: // internal interface // call these with client_lock held! - int _do_lookup(Inode *dir, const string& name, Inode **target); - int _lookup(Inode *dir, const string& dname, Inode **target); + int _do_lookup(Inode *dir, const string& name, InodeRef *target); + int _lookup(Inode *dir, const string& dname, InodeRef *target); - int _link(Inode *in, Inode *dir, const char *name, int uid=-1, int gid=-1, Inode **inp = 0); + int _link(Inode *in, Inode *dir, const char *name, int uid=-1, int gid=-1, InodeRef *inp = 0); int _unlink(Inode *dir, const char *name, int uid=-1, int gid=-1); int _rename(Inode *olddir, const char *oname, Inode *ndir, const char *nname, int uid=-1, int gid=-1); - int _mkdir(Inode *dir, const char *name, mode_t mode, int uid=-1, int gid=-1, Inode **inp = 0); + int _mkdir(Inode *dir, const char *name, mode_t mode, int uid=-1, int gid=-1, InodeRef *inp = 0); int _rmdir(Inode *dir, const char *name, int uid=-1, int gid=-1); - int _symlink(Inode *dir, const char *name, const char *target, int uid=-1, int gid=-1, Inode **inp = 0); - int _mknod(Inode *dir, const char *name, mode_t mode, dev_t rdev, int uid=-1, int gid=-1, Inode **inp = 0); - int _setattr(Inode *in, struct stat *attr, int mask, int uid=-1, int gid=-1, Inode **inp = 0); + int _symlink(Inode *dir, const char *name, const char *target, int uid=-1, int gid=-1, InodeRef *inp = 0); + int _mknod(Inode *dir, const char *name, mode_t mode, dev_t rdev, int uid=-1, int gid=-1, InodeRef *inp = 0); + int _setattr(Inode *in, struct stat *attr, int mask, int uid=-1, int gid=-1, InodeRef *inp = 0); + int _setattr(InodeRef &in, struct stat *attr, int mask, int uid=-1, int gid=-1, InodeRef *inp = 0) { + return _setattr(in.get(), attr, mask, uid, gid, inp); + } int _getattr(Inode *in, int mask, int uid=-1, int gid=-1, bool force=false); + int _getattr(InodeRef &in, int mask, int uid=-1, int gid=-1, bool force=false) { + return _getattr(in.get(), mask, uid, gid, force); + } int _readlink(Inode *in, char *buf, size_t size); int _getxattr(Inode *in, const char *name, void *value, size_t len, int uid=-1, int gid=-1); int _listxattr(Inode *in, char *names, size_t len, int uid=-1, int gid=-1); int _setxattr(Inode *in, const char *name, const void *value, size_t len, int flags, int uid=-1, int gid=-1); int _removexattr(Inode *in, const char *nm, int uid=-1, int gid=-1); int _open(Inode *in, int flags, mode_t mode, Fh **fhp, int uid=-1, int gid=-1); - int _create(Inode *in, const char *name, int flags, mode_t mode, Inode **inp, Fh **fhp, + int _create(Inode *in, const char *name, int flags, mode_t mode, InodeRef *inp, Fh **fhp, int stripe_unit, int stripe_count, int object_size, const char *data_pool, bool *created = NULL, int uid=-1, int gid=-1); + loff_t _lseek(Fh *fh, loff_t offset, int whence); int _read(Fh *fh, int64_t offset, uint64_t size, bufferlist *bl); int _write(Fh *fh, int64_t offset, uint64_t size, const char *buf, diff --git a/src/client/Inode.cc b/src/client/Inode.cc index c63ba1c9e370..219af9fdec0c 100644 --- a/src/client/Inode.cc +++ b/src/client/Inode.cc @@ -1,10 +1,11 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include "MetaSession.h" +#include "Client.h" #include "Inode.h" #include "Dentry.h" #include "Dir.h" +#include "MetaSession.h" #include "ClientSnapRealm.h" ostream& operator<<(ostream &out, Inode &in) @@ -126,7 +127,7 @@ int Inode::put_cap_ref(int cap) if (cap & 1) { int c = 1 << n; if (cap_refs[c] <= 0) { - lderr(cct) << "put_cap_ref " << ccap_string(c) << " went negative on " << *this << dendl; + lderr(client->cct) << "put_cap_ref " << ccap_string(c) << " went negative on " << *this << dendl; assert(cap_refs[c] > 0); } if (--cap_refs[c] == 0) @@ -151,7 +152,7 @@ bool Inode::cap_is_valid(Cap* cap) << "cap expire " << cap->session->cap_ttl << std::endl << "cur time " << ceph_clock_now(cct) << std::endl;*/ if ((cap->session->cap_gen <= cap->gen) - && (ceph_clock_now(cct) < cap->session->cap_ttl)) { + && (ceph_clock_now(client->cct) < cap->session->cap_ttl)) { return true; } return true; @@ -268,7 +269,7 @@ Dir *Inode::open_dir() { if (!dir) { dir = new Dir(this); - lsubdout(cct, mds, 15) << "open_dir " << dir << " on " << this << dendl; + lsubdout(client->cct, client, 15) << "open_dir " << dir << " on " << this << dendl; assert(dn_set.size() < 2); // dirs can't be hard-linked if (!dn_set.empty()) (*dn_set.begin())->get(); // pin dentry @@ -307,6 +308,21 @@ bool Inode::check_mode(uid_t ruid, gid_t rgid, gid_t *sgids, int sgids_count, ui return (mode & fmode) == fmode; } +void Inode::get() { + _ref++; + lsubdout(client->cct, client, 15) << "inode.get on " << this << " " << ino << '.' << snapid + << " now " << _ref << dendl; +} + +//private method to put a reference; see Client::put_inode() +int Inode::_put(int n) { + _ref -= n; + lsubdout(client->cct, client, 15) << "inode.put on " << this << " " << ino << '.' << snapid + << " now " << _ref << dendl; + assert(_ref >= 0); + return _ref; +} + void Inode::dump(Formatter *f) const { diff --git a/src/client/Inode.h b/src/client/Inode.h index 04a8215a1c94..1ca7d3333245 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -13,6 +13,7 @@ #include "osdc/ObjectCacher.h" #include "include/assert.h" +class Client; struct MetaSession; class Dentry; class Dir; @@ -151,7 +152,7 @@ public: #define I_DIR_ORDERED 2 struct Inode { - CephContext *cct; + Client *client; // -- the actual inode -- inodeno_t ino; @@ -271,19 +272,8 @@ struct Inode { void make_long_path(filepath& p); void make_nosnap_relative_path(filepath& p); - void get() { - _ref++; - lsubdout(cct, mds, 15) << "inode.get on " << this << " " << ino << '.' << snapid - << " now " << _ref << dendl; - } - /// private method to put a reference; see Client::put_inode() - int _put(int n=1) { - _ref -= n; - lsubdout(cct, mds, 15) << "inode.put on " << this << " " << ino << '.' << snapid - << " now " << _ref << dendl; - assert(_ref >= 0); - return _ref; - } + void get(); + int _put(int n=1); int get_num_ref() { return _ref; @@ -303,8 +293,8 @@ struct Inode { xlist unsafe_dir_ops; - Inode(CephContext *cct_, vinodeno_t vino, ceph_file_layout *newlayout) - : cct(cct_), ino(vino.ino), snapid(vino.snapid), + Inode(Client *c, vinodeno_t vino, ceph_file_layout *newlayout) + : client(c), ino(vino.ino), snapid(vino.snapid), rdev(0), mode(0), uid(0), gid(0), nlink(0), size(0), truncate_seq(1), truncate_size(-1), time_warp_seq(0), max_size(0), version(0), xattr_version(0), diff --git a/src/client/InodeRef.h b/src/client/InodeRef.h new file mode 100644 index 000000000000..822ec0ffcdc9 --- /dev/null +++ b/src/client/InodeRef.h @@ -0,0 +1,12 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_CLIENT_INODEREF_H +#define CEPH_CLIENT_INODEREF_H + +#include +class Inode; +void intrusive_ptr_add_ref(Inode *in); +void intrusive_ptr_release(Inode *in); +typedef boost::intrusive_ptr InodeRef; +#endif