From 1198a47b97dc8dc6293e3f9b6aa2aaf0e2ff39b1 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sun, 2 Aug 2020 08:35:24 +0800 Subject: [PATCH] client: add mount/initialize states support and convert to RWRef This will help us to break the big client_lock. Such as if we want to add one separate lock for each inode, it will work like: inode_lock.lock(); ... client_lock.lock(); client_lock.unlock(); ... inode_lock.unlock(); So we must get rid of the client_lock for all the "readers", which must hold the client_lock from the beginning until the end. Fixes: https://tracker.ceph.com/issues/46649 Signed-off-by: Xiubo Li --- src/client/Client.cc | 1091 +++++++++++++++++++++++++----------------- src/client/Client.h | 128 ++++- 2 files changed, 776 insertions(+), 443 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 8a2db485526..a4e1ee59838 100755 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -273,6 +273,8 @@ Client::Client(Messenger *m, MonClient *mc, Objecter *objecter_) monclient(mc), objecter(objecter_), whoami(mc->get_global_id()), + mount_state(CLIENT_UNMOUNTED, "Client::mountstate_lock"), + initialize_state(CLIENT_NEW, "Client::initstate_lock"), async_ino_invalidator(m->cct), async_dentry_invalidator(m->cct), interrupt_finisher(m->cct), @@ -491,13 +493,16 @@ void Client::_pre_init() int Client::init() { + RWRef_t iref_writer(initialize_state, CLIENT_INITIALIZING, false); + ceph_assert(iref_writer.is_first_writer()); + _pre_init(); { std::lock_guard l{client_lock}; - ceph_assert(!initialized); messenger->add_dispatcher_tail(this); } _finish_init(); + iref_writer.update_state(CLIENT_INITIALIZED); return 0; } @@ -554,9 +559,6 @@ void Client::_finish_init() lderr(cct) << "error registering admin socket command: " << cpp_strerror(-ret) << dendl; } - - std::lock_guard l{client_lock}; - initialized = true; } void Client::shutdown() @@ -604,16 +606,24 @@ void Client::shutdown() } objectcacher->stop(); // outside of client_lock! this does a join. - { - std::lock_guard l{client_lock}; - ceph_assert(initialized); - initialized = false; - } + + /* + * We are shuting down the client. + * + * Just declare the state to CLIENT_NEW to block and fail any + * new comming "reader" and then try to wait all the in-flight + * "readers" to finish. + */ + RWRef_t iref_writer(initialize_state, CLIENT_NEW, false); + if (!iref_writer.is_first_writer()) + return; + iref_writer.wait_readers_done(); { std::scoped_lock l(timer_lock); timer.shutdown(); } + objecter_finisher.wait_for_empty(); objecter_finisher.stop(); @@ -635,13 +645,13 @@ void Client::trim_cache(bool trim_kernel_dcache) while (lru.lru_get_size() != last) { last = lru.lru_get_size(); - if (!unmounting && lru.lru_get_size() <= max) break; + if (!is_unmounting() && lru.lru_get_size() <= max) break; // trim! Dentry *dn = static_cast(lru.lru_get_next_expire()); if (!dn) break; // done - + trim_dentry(dn); } @@ -840,7 +850,7 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, _assign_faked_root(root); root_ancestor = in; cwd = root; - } else if (!mounted) { + } else if (is_mounting()) { root_parents[root_ancestor] = in; root_ancestor = in; } @@ -2038,8 +2048,10 @@ void Client::populate_metadata(const std::string &mount_root) */ void Client::update_metadata(std::string const &k, std::string const &v) { + RWRef_t iref_reader(initialize_state, CLIENT_INITIALIZED); + ceph_assert(iref_reader.is_state_satisfied()); + std::lock_guard l(client_lock); - ceph_assert(initialized); auto it = metadata.find(k); if (it != metadata.end()) { @@ -2119,7 +2131,7 @@ void Client::handle_client_session(const MConstRef& m) renew_caps(session); session->state = MetaSession::STATE_OPEN; - if (unmounting) + if (is_unmounting()) mount_cond.notify_all(); else connect_mds_targets(from); @@ -2448,7 +2460,7 @@ void Client::handle_client_reply(const MConstRef& reply) request->item.remove_myself(); unregister_request(request); } - if (unmounting) + if (is_unmounting()) mount_cond.notify_all(); } @@ -2584,11 +2596,15 @@ void Client::handle_osd_map(const MConstRef& m) bool Client::ms_dispatch2(const MessageRef &m) { - std::lock_guard l(client_lock); - if (!initialized) { + RWRef_t iref_reader(initialize_state, CLIENT_INITIALIZED); + if (!iref_reader.is_state_satisfied()) { ldout(cct, 10) << "inactive, discarding " << *m << dendl; return true; } +// if (!is_initialized()) +// return true; + + std::lock_guard l(client_lock); switch (m->get_type()) { // mounting and mds sessions @@ -2647,7 +2663,7 @@ bool Client::ms_dispatch2(const MessageRef &m) } // unmounting? - if (unmounting) { + if (is_unmounting()) { ldout(cct, 10) << "unmounting: trim pass, size was " << lru.lru_get_size() << "+" << inode_map.size() << dendl; long unsigned size = lru.lru_get_size() + inode_map.size(); @@ -3546,7 +3562,7 @@ void Client::check_caps(Inode *in, unsigned flags) used = adjust_caps_used_for_lazyio(used, issued, implemented); int retain = wanted | used | CEPH_CAP_PIN; - if (!unmounting && in->nlink > 0) { + if (!is_unmounting() && in->nlink > 0) { if (wanted) { retain |= CEPH_CAP_ANY; } else if (in->is_dir() && @@ -3629,7 +3645,7 @@ void Client::check_caps(Inode *in, unsigned flags) if (wanted & ~(cap.wanted | cap.issued)) goto ack; - if (!revoking && unmounting && (cap_used == 0)) + if (!revoking && is_unmounting() && (cap_used == 0)) goto ack; if ((cap.issued & ~retain) == 0 && // and we don't have anything we wouldn't like @@ -3911,8 +3927,10 @@ public: void Client::_async_invalidate(vinodeno_t ino, int64_t off, int64_t len) { - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return; + ldout(cct, 10) << __func__ << " " << ino << " " << off << "~" << len << dendl; ino_invalidate_cb(callback_handle, ino, off, len); } @@ -4252,7 +4270,7 @@ int Client::_do_remount(bool retry_on_error) (cct->_conf.get_val("client_die_on_failed_remount") || cct->_conf.get_val("client_die_on_failed_dentry_invalidate")) && !(retry_on_error && (++retries_on_invalidate < max_retries)); - if (should_abort && !unmounting) { + if (should_abort && !is_unmounting()) { lderr(cct) << "failed to remount for kernel dentry trimming; quitting!" << dendl; ceph_abort(); } @@ -4273,8 +4291,10 @@ public: void Client::_invalidate_kernel_dcache() { - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return; + if (can_invalidate_dentries) { if (dentry_invalidate_cb && root->dir) { for (ceph::unordered_map::iterator p = root->dir->dentries.begin(); @@ -4336,8 +4356,10 @@ public: void Client::_async_inode_release(vinodeno_t ino) { - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return; + ldout(cct, 10) << __func__ << " " << ino << dendl; ino_release_cb(callback_handle, ino); } @@ -5218,8 +5240,10 @@ public: void Client::_async_dentry_invalidate(vinodeno_t dirino, vinodeno_t ino, string& name) { - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return; + ldout(cct, 10) << __func__ << " '" << name << "' ino " << ino << " in dir " << dirino << dendl; dentry_invalidate_cb(callback_handle, dirino, ino, name.c_str(), name.length()); @@ -5818,11 +5842,12 @@ int Client::mds_command( string *outs, Context *onfinish) { - std::lock_guard lock(client_lock); - - if (!initialized) + RWRef_t iref_reader(initialize_state, CLIENT_INITIALIZED); + if (!iref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + int r; r = authenticate(); if (r < 0) { @@ -5964,14 +5989,17 @@ int Client::subscribe_mdsmap(const std::string &fs_name) int Client::mount(const std::string &mount_root, const UserPerm& perms, bool require_mds, const std::string &fs_name) { - std::unique_lock lock(client_lock); + ceph_assert(is_initialized()); - if (mounted) { - ldout(cct, 5) << "already mounted" << dendl; + /* + * To make sure that the _unmount() must wait until the mount() + * is done. + */ + RWRef_t mref_writer(mount_state, CLIENT_MOUNTING, false); + if (!mref_writer.is_first_writer()) // already mounting or mounted return 0; - } - unmounting = false; + std::unique_lock cl(client_lock); int r = subscribe_mdsmap(fs_name); if (r < 0) { @@ -5979,10 +6007,10 @@ int Client::mount(const std::string &mount_root, const UserPerm& perms, return r; } - lock.unlock(); + cl.unlock(); tick(); // start tick - lock.lock(); - + cl.lock(); + if (require_mds) { while (1) { auto availability = mdsmap->is_cluster_available(); @@ -6032,8 +6060,6 @@ int Client::mount(const std::string &mount_root, const UserPerm& perms, ceph_assert(root); _ll_get(root); - mounted = true; - // trace? if (!cct->_conf->client_trace.empty()) { traceout.open(cct->_conf->client_trace.c_str()); @@ -6054,6 +6080,8 @@ int Client::mount(const std::string &mount_root, const UserPerm& perms, ldout(cct, 3) << "op: map open_files;" << dendl; ldout(cct, 3) << "op: int fd;" << dendl; */ + + mref_writer.update_state(CLIENT_MOUNTED); return 0; } @@ -6149,16 +6177,25 @@ void Client::_abort_mds_sessions(int err) void Client::_unmount(bool abort) { - std::unique_lock lock{client_lock}; - if (unmounting) + /* + * We are unmounting the client. + * + * Just declare the state to STATE_UNMOUNTING to block and fail + * any new comming "reader" and then try to wait all the in-flight + * "readers" to finish. + */ + RWRef_t mref_writer(mount_state, CLIENT_UNMOUNTING, false); + if (!mref_writer.is_first_writer()) return; + mref_writer.wait_readers_done(); + + std::unique_lock lock{client_lock}; if (abort || blacklisted) { ldout(cct, 2) << "unmounting (" << (abort ? "abort)" : "blacklisted)") << dendl; } else { ldout(cct, 2) << "unmounting" << dendl; } - unmounting = true; deleg_timeout = 0; @@ -6283,7 +6320,7 @@ void Client::_unmount(bool abort) _close_sessions(); - mounted = false; + mref_writer.update_state(CLIENT_UNMOUNTED); ldout(cct, 2) << "unmounted." << dendl; } @@ -6336,19 +6373,21 @@ void Client::tick() utime_t now = ceph_clock_now(); - std::lock_guard lock(client_lock); - - if (!mounted && !mds_requests.empty()) { + std::scoped_lock cl(client_lock); + /* + * If the mount() is not finished + */ + if (is_mounting() && !mds_requests.empty()) { MetaRequest *req = mds_requests.begin()->second; if (req->op_stamp + cct->_conf->client_mount_timeout < now) { req->abort(-ETIMEDOUT); if (req->caller_cond) { - req->kick = true; - req->caller_cond->notify_all(); + req->kick = true; + req->caller_cond->notify_all(); } signal_cond_list(waiting_for_mdsmap); for (auto &p : mds_sessions) { - signal_context_list(p.second.waiting_for_open); + signal_context_list(p.second.waiting_for_open); } } } @@ -6377,7 +6416,7 @@ void Client::tick() trim_cache(true); - if (blacklisted && mounted && + if (blacklisted && (is_mounted() || is_unmounting()) && last_auto_reconnect + 30 * 60 < now && cct->_conf.get_val("client_reconnect_stale")) { messenger->client_reset(); @@ -6717,17 +6756,19 @@ int Client::path_walk(const filepath& origpath, InodeRef *end, int Client::link(const char *relexisting, const char *relpath, const UserPerm& perm) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << "link" << std::endl; tout(cct) << relexisting << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath existing(relexisting); InodeRef in, dir; + + std::scoped_lock lock(client_lock); int r = path_walk(existing, &in, perm, true); if (r < 0) return r; @@ -6760,14 +6801,13 @@ int Client::link(const char *relexisting, const char *relpath, const UserPerm& p int Client::unlink(const char *relpath, const UserPerm& perm) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - - if (unmounting) - return -ENOTCONN; - if (std::string(relpath) == "/") return -EISDIR; @@ -6775,6 +6815,8 @@ int Client::unlink(const char *relpath, const UserPerm& perm) string name = path.last_dentry(); path.pop_dentry(); InodeRef dir; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &dir, perm); if (r < 0) return r; @@ -6788,14 +6830,14 @@ int Client::unlink(const char *relpath, const UserPerm& perm) int Client::rename(const char *relfrom, const char *relto, const UserPerm& perm) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relfrom << std::endl; tout(cct) << relto << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - if (std::string(relfrom) == "/" || std::string(relto) == "/") return -EBUSY; @@ -6807,6 +6849,8 @@ int Client::rename(const char *relfrom, const char *relto, const UserPerm& perm) to.pop_dentry(); InodeRef fromdir, todir; + + std::scoped_lock lock(client_lock); int r = path_walk(from, &fromdir, perm); if (r < 0) goto out; @@ -6831,15 +6875,15 @@ out: int Client::mkdir(const char *relpath, mode_t mode, const UserPerm& perm) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << mode << std::endl; ldout(cct, 10) << __func__ << ": " << relpath << dendl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - if (std::string(relpath) == "/") return -EEXIST; @@ -6847,6 +6891,8 @@ int Client::mkdir(const char *relpath, mode_t mode, const UserPerm& perm) string name = path.last_dentry(); path.pop_dentry(); InodeRef dir; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &dir, perm); if (r < 0) return r; @@ -6860,20 +6906,22 @@ int Client::mkdir(const char *relpath, mode_t mode, const UserPerm& perm) int Client::mkdirs(const char *relpath, mode_t mode, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 10) << "Client::mkdirs " << relpath << dendl; tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << mode << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - //get through existing parts of path filepath path(relpath); unsigned int i; int r = 0, caps = 0; InodeRef cur, next; + + std::scoped_lock lock(client_lock); cur = cwd; for (i=0; i_conf->client_permissions) { @@ -6915,13 +6963,13 @@ int Client::mkdirs(const char *relpath, mode_t mode, const UserPerm& perms) int Client::rmdir(const char *relpath, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - if (std::string(relpath) == "/") return -EBUSY; @@ -6929,6 +6977,8 @@ int Client::rmdir(const char *relpath, const UserPerm& perms) string name = path.last_dentry(); path.pop_dentry(); InodeRef dir; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &dir, perms); if (r < 0) return r; @@ -6942,15 +6992,15 @@ int Client::rmdir(const char *relpath, const UserPerm& perms) int Client::mknod(const char *relpath, mode_t mode, const UserPerm& perms, dev_t rdev) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << mode << std::endl; tout(cct) << rdev << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - if (std::string(relpath) == "/") return -EEXIST; @@ -6958,6 +7008,8 @@ int Client::mknod(const char *relpath, mode_t mode, const UserPerm& perms, dev_t string name = path.last_dentry(); path.pop_dentry(); InodeRef dir; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &dir, perms); if (r < 0) return r; @@ -6973,14 +7025,14 @@ int Client::mknod(const char *relpath, mode_t mode, const UserPerm& perms, dev_t int Client::symlink(const char *target, const char *relpath, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << target << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - if (std::string(relpath) == "/") return -EEXIST; @@ -6988,6 +7040,8 @@ int Client::symlink(const char *target, const char *relpath, const UserPerm& per string name = path.last_dentry(); path.pop_dentry(); InodeRef dir; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &dir, perms); if (r < 0) return r; @@ -7001,15 +7055,17 @@ int Client::symlink(const char *target, const char *relpath, const UserPerm& per int Client::readlink(const char *relpath, char *buf, loff_t size, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms, false); if (r < 0) return r; @@ -7307,16 +7363,18 @@ int Client::_setattr(InodeRef &in, struct stat *attr, int mask, int Client::setattr(const char *relpath, struct stat *attr, int mask, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << mask << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms); if (r < 0) return r; @@ -7326,16 +7384,18 @@ int Client::setattr(const char *relpath, struct stat *attr, int mask, int Client::setattrx(const char *relpath, struct ceph_statx *stx, int mask, const UserPerm& perms, int flags) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << mask << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW)); if (r < 0) return r; @@ -7344,14 +7404,15 @@ int Client::setattrx(const char *relpath, struct ceph_statx *stx, int mask, int Client::fsetattr(int fd, struct stat *attr, int mask, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << fd << std::endl; tout(cct) << mask << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -7364,14 +7425,15 @@ int Client::fsetattr(int fd, struct stat *attr, int mask, const UserPerm& perms) int Client::fsetattrx(int fd, struct ceph_statx *stx, int mask, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << fd << std::endl; tout(cct) << mask << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -7385,16 +7447,18 @@ int Client::fsetattrx(int fd, struct ceph_statx *stx, int mask, const UserPerm& int Client::stat(const char *relpath, struct stat *stbuf, const UserPerm& perms, frag_info_t *dirstat, int mask) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << __func__ << " enter (relpath " << relpath << " mask " << mask << ")" << dendl; tout(cct) << "stat" << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms, true, mask); if (r < 0) return r; @@ -7434,19 +7498,20 @@ int Client::statx(const char *relpath, struct ceph_statx *stx, const UserPerm& perms, unsigned int want, unsigned int flags) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << __func__ << " enter (relpath " << relpath << " want " << want << ")" << dendl; tout(cct) << "statx" << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; unsigned mask = statx_to_mask(flags, want); + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), mask); if (r < 0) return r; @@ -7465,16 +7530,18 @@ int Client::statx(const char *relpath, struct ceph_statx *stx, int Client::lstat(const char *relpath, struct stat *stbuf, const UserPerm& perms, frag_info_t *dirstat, int mask) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << __func__ << " enter (relpath " << relpath << " mask " << mask << ")" << dendl; tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); // don't follow symlinks int r = path_walk(path, &in, perms, false, mask); if (r < 0) @@ -7641,16 +7708,18 @@ void Client::touch_dn(Dentry *dn) int Client::chmod(const char *relpath, mode_t mode, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << mode << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms); if (r < 0) return r; @@ -7661,14 +7730,15 @@ int Client::chmod(const char *relpath, mode_t mode, const UserPerm& perms) int Client::fchmod(int fd, mode_t mode, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << fd << std::endl; tout(cct) << mode << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -7683,16 +7753,18 @@ int Client::fchmod(int fd, mode_t mode, const UserPerm& perms) int Client::lchmod(const char *relpath, mode_t mode, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << mode << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); // don't follow symlinks int r = path_walk(path, &in, perms, false); if (r < 0) @@ -7705,17 +7777,19 @@ int Client::lchmod(const char *relpath, mode_t mode, const UserPerm& perms) int Client::chown(const char *relpath, uid_t new_uid, gid_t new_gid, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << new_uid << std::endl; tout(cct) << new_gid << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms); if (r < 0) return r; @@ -7727,15 +7801,16 @@ int Client::chown(const char *relpath, uid_t new_uid, gid_t new_gid, int Client::fchown(int fd, uid_t new_uid, gid_t new_gid, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << fd << std::endl; tout(cct) << new_uid << std::endl; tout(cct) << new_gid << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -7755,17 +7830,19 @@ int Client::fchown(int fd, uid_t new_uid, gid_t new_gid, const UserPerm& perms) int Client::lchown(const char *relpath, uid_t new_uid, gid_t new_gid, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << new_uid << std::endl; tout(cct) << new_gid << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); // don't follow symlinks int r = path_walk(path, &in, perms, false); if (r < 0) @@ -7830,6 +7907,10 @@ int Client::futime(int fd, struct utimbuf *buf, const UserPerm& perms) int Client::utimes(const char *relpath, struct timeval times[2], const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << "atime: " << times[0].tv_sec << "." << times[0].tv_usec @@ -7837,12 +7918,10 @@ int Client::utimes(const char *relpath, struct timeval times[2], tout(cct) << "mtime: " << times[1].tv_sec << "." << times[1].tv_usec << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms); if (r < 0) return r; @@ -7857,6 +7936,10 @@ int Client::utimes(const char *relpath, struct timeval times[2], int Client::lutimes(const char *relpath, struct timeval times[2], const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; tout(cct) << "atime: " << times[0].tv_sec << "." << times[0].tv_usec @@ -7864,12 +7947,10 @@ int Client::lutimes(const char *relpath, struct timeval times[2], tout(cct) << "mtime: " << times[1].tv_sec << "." << times[1].tv_usec << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms, false); if (r < 0) return r; @@ -7894,6 +7975,10 @@ int Client::futimes(int fd, struct timeval times[2], const UserPerm& perms) int Client::futimens(int fd, struct timespec times[2], const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << fd << std::endl; tout(cct) << "atime: " << times[0].tv_sec << "." << times[0].tv_nsec @@ -7902,9 +7987,6 @@ int Client::futimens(int fd, struct timespec times[2], const UserPerm& perms) << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -7922,15 +8004,16 @@ int Client::futimens(int fd, struct timespec times[2], const UserPerm& perms) int Client::flock(int fd, int operation, uint64_t owner) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << fd << std::endl; tout(cct) << operation << std::endl; tout(cct) << owner << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -7940,15 +8023,17 @@ int Client::flock(int fd, int operation, uint64_t owner) int Client::opendir(const char *relpath, dir_result_t **dirpp, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms, true); if (r < 0) return r; @@ -8001,12 +8086,13 @@ void Client::_closedir(dir_result_t *dirp) void Client::rewinddir(dir_result_t *dirp) { - std::lock_guard lock(client_lock); ldout(cct, 3) << __func__ << "(" << dirp << ")" << dendl; - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return; + std::lock_guard lock(client_lock); dir_result_t *d = static_cast(dirp); _readdir_drop_dirp_buffer(d); d->reset(); @@ -8021,13 +8107,14 @@ loff_t Client::telldir(dir_result_t *dirp) void Client::seekdir(dir_result_t *dirp, loff_t offset) { - std::lock_guard lock(client_lock); - ldout(cct, 3) << __func__ << "(" << dirp << ", " << offset << ")" << dendl; - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return; + std::lock_guard lock(client_lock); + if (offset == dirp->offset) return; @@ -8282,11 +8369,12 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p, { int caps = statx_to_mask(flags, want); - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + dir_result_t *dirp = static_cast(d); ldout(cct, 10) << __func__ << " " << *dirp->inode << " offset " << hex << dirp->offset @@ -8655,15 +8743,15 @@ int Client::open(const char *relpath, int flags, const UserPerm& perms, mode_t mode, int stripe_unit, int stripe_count, int object_size, const char *data_pool) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << "open enter(" << relpath << ", " << ceph_flags_sys2wire(flags) << "," << mode << ")" << dendl; tout(cct) << "open" << std::endl; tout(cct) << relpath << std::endl; tout(cct) << ceph_flags_sys2wire(flags) << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *fh = NULL; #if defined(__linux__) && defined(O_PATH) @@ -8679,6 +8767,8 @@ int Client::open(const char *relpath, int flags, const UserPerm& perms, bool created = false; /* O_CREATE with O_EXCL enforces O_NOFOLLOW. */ bool followsym = !((flags & O_NOFOLLOW) || ((flags & O_CREAT) && (flags & O_EXCL))); + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms, followsym, ceph_caps_for_mode(mode)); if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL)) @@ -8745,12 +8835,13 @@ int Client::open(const char *relpath, int flags, const UserPerm& perms, mode_t m int Client::lookup_hash(inodeno_t ino, inodeno_t dirino, const char *name, const UserPerm& perms) { - std::lock_guard lock(client_lock); ldout(cct, 3) << __func__ << " enter(" << ino << ", #" << dirino << "/" << name << ")" << dendl; - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPHASH); filepath path(ino); req->set_filepath(path); @@ -8780,7 +8871,8 @@ int Client::_lookup_ino(inodeno_t ino, const UserPerm& perms, Inode **inode) { ldout(cct, 8) << __func__ << " enter(" << ino << ")" << dendl; - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPINO); @@ -8843,7 +8935,8 @@ int Client::_lookup_name(Inode *ino, Inode *parent, const UserPerm& perms) ceph_assert(parent->is_dir()); ldout(cct, 3) << __func__ << " enter(" << ino->ino << ")" << dendl; - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPNAME); @@ -9058,14 +9151,15 @@ int Client::_renew_caps(Inode *in) int Client::close(int fd) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << "close enter(" << fd << ")" << dendl; tout(cct) << "close" << std::endl; tout(cct) << fd << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *fh = get_filehandle(fd); if (!fh) return -EBADF; @@ -9082,15 +9176,16 @@ int Client::close(int fd) loff_t Client::lseek(int fd, loff_t offset, int whence) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << "lseek" << std::endl; tout(cct) << fd << std::endl; tout(cct) << offset << std::endl; tout(cct) << whence << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -9254,15 +9349,16 @@ int Client::uninline_data(Inode *in, Context *onfinish) int Client::read(int fd, char *buf, loff_t size, loff_t offset) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << "read" << std::endl; tout(cct) << fd << std::endl; tout(cct) << size << std::endl; tout(cct) << offset << std::endl; std::unique_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -9574,7 +9670,7 @@ void Client::_sync_write_commit(Inode *in) put_cap_ref(in, CEPH_CAP_FILE_BUFFER); ldout(cct, 15) << __func__ << " unsafe_sync_write = " << unsafe_sync_write << dendl; - if (unsafe_sync_write == 0 && unmounting) { + if (unsafe_sync_write == 0 && is_unmounting()) { ldout(cct, 10) << __func__ << " -- no more unsafe writes, unmount can proceed" << dendl; mount_cond.notify_all(); } @@ -9582,15 +9678,16 @@ void Client::_sync_write_commit(Inode *in) int Client::write(int fd, const char *buf, loff_t size, loff_t offset) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << "write" << std::endl; tout(cct) << fd << std::endl; tout(cct) << size << std::endl; tout(cct) << offset << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *fh = get_filehandle(fd); if (!fh) return -EBADF; @@ -9661,13 +9758,14 @@ int64_t Client::_preadv_pwritev_locked(Fh *fh, const struct iovec *iov, int Client::_preadv_pwritev(int fd, const struct iovec *iov, unsigned iovcnt, int64_t offset, bool write) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << fd << std::endl; tout(cct) << offset << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *fh = get_filehandle(fd); if (!fh) return -EBADF; @@ -9930,14 +10028,15 @@ int Client::truncate(const char *relpath, loff_t length, const UserPerm& perms) int Client::ftruncate(int fd, loff_t length, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; tout(cct) << fd << std::endl; tout(cct) << length << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -9952,14 +10051,15 @@ int Client::ftruncate(int fd, loff_t length, const UserPerm& perms) int Client::fsync(int fd, bool syncdataonly) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << "fsync" << std::endl; tout(cct) << fd << std::endl; tout(cct) << syncdataonly << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -10061,13 +10161,14 @@ int Client::_fsync(Fh *f, bool syncdataonly) int Client::fstat(int fd, struct stat *stbuf, const UserPerm& perms, int mask) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << "fstat mask " << hex << mask << dec << std::endl; tout(cct) << fd << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -10082,13 +10183,14 @@ int Client::fstat(int fd, struct stat *stbuf, const UserPerm& perms, int mask) int Client::fstatx(int fd, struct ceph_statx *stx, const UserPerm& perms, unsigned int want, unsigned int flags) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << "fstatx flags " << hex << flags << " want " << want << dec << std::endl; tout(cct) << fd << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -10114,15 +10216,17 @@ int Client::fstatx(int fd, struct ceph_statx *stx, const UserPerm& perms, int Client::chdir(const char *relpath, std::string &new_cwd, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << "chdir" << std::endl; tout(cct) << relpath << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - filepath path(relpath); InodeRef in; + + std::scoped_lock lock(client_lock); int r = path_walk(path, &in, perms); if (r < 0) return r; @@ -10180,24 +10284,29 @@ void Client::_getcwd(string& dir, const UserPerm& perms) void Client::getcwd(string& dir, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return; + std::lock_guard l(client_lock); - if (!unmounting) - _getcwd(dir, perms); + + _getcwd(dir, perms); } int Client::statfs(const char *path, struct statvfs *stbuf, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << std::endl; unsigned long int total_files_on_fs; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - ceph_statfs stats; C_SaferCond cond; + std::scoped_lock lock(client_lock); const vector &data_pools = mdsmap->get_data_pools(); if (data_pools.size() == 1) { objecter->get_fs_stats(stats, data_pools[0], &cond); @@ -10649,6 +10758,10 @@ int Client::test_dentry_handling(bool can_invalidate) { int r = 0; + RWRef_t iref_reader(initialize_state, CLIENT_INITIALIZED); + if (!iref_reader.is_state_satisfied()) + return -ENOTCONN; + can_invalidate_dentries = can_invalidate; if (can_invalidate_dentries) { @@ -10697,11 +10810,12 @@ int Client::_sync_fs() int Client::sync_fs() { - std::lock_guard l(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard l(client_lock); + return _sync_fs(); } @@ -10796,11 +10910,12 @@ int Client::lazyio_synchronize(int fd, loff_t offset, size_t count) int Client::mksnap(const char *relpath, const char *name, const UserPerm& perm) { - std::lock_guard l(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard l(client_lock); + filepath path(relpath); InodeRef in; int r = path_walk(path, &in, perm); @@ -10817,11 +10932,12 @@ int Client::mksnap(const char *relpath, const char *name, const UserPerm& perm) int Client::rmsnap(const char *relpath, const char *name, const UserPerm& perms) { - std::lock_guard l(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard l(client_lock); + filepath path(relpath); InodeRef in; int r = path_walk(path, &in, perms); @@ -10839,13 +10955,14 @@ int Client::rmsnap(const char *relpath, const char *name, const UserPerm& perms) // ============================= // expose caps -int Client::get_caps_issued(int fd) { +int Client::get_caps_issued(int fd) +{ + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; std::lock_guard lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -10855,11 +10972,12 @@ int Client::get_caps_issued(int fd) { int Client::get_caps_issued(const char *path, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + filepath p(path); InodeRef in; int r = path_walk(p, &in, perms, true); @@ -10908,14 +11026,16 @@ Inode *Client::open_snapdir(Inode *diri) int Client::ll_lookup(Inode *parent, const char *name, struct stat *attr, Inode **out, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vparent = _get_vino(parent); ldout(cct, 3) << __func__ << " " << vparent << " " << name << dendl; tout(cct) << __func__ << std::endl; tout(cct) << name << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; int r = 0; if (!fuse_default_permissions) { @@ -10953,11 +11073,12 @@ int Client::ll_lookup_inode( Inode **inode) { ceph_assert(inode != NULL); + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + std::lock_guard lock(client_lock); ldout(cct, 3) << "ll_lookup_inode " << ino << dendl; - - if (unmounting) - return -ENOTCONN; // Num1: get inode and *inode int r = _lookup_ino(ino, perms, inode); @@ -11003,14 +11124,16 @@ int Client::ll_lookupx(Inode *parent, const char *name, Inode **out, struct ceph_statx *stx, unsigned want, unsigned flags, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vparent = _get_vino(parent); ldout(cct, 3) << __func__ << " " << vparent << " " << name << dendl; tout(cct) << "ll_lookupx" << std::endl; tout(cct) << name << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; int r = 0; if (!fuse_default_permissions) { @@ -11043,6 +11166,10 @@ int Client::ll_lookupx(Inode *parent, const char *name, Inode **out, int Client::ll_walk(const char* name, Inode **out, struct ceph_statx *stx, unsigned int want, unsigned int flags, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + filepath fp(name, 0); InodeRef in; int rc; @@ -11053,9 +11180,6 @@ int Client::ll_walk(const char* name, Inode **out, struct ceph_statx *stx, tout(cct) << name << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - rc = path_walk(fp, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), mask); if (rc < 0) { /* zero out mask, just in case... */ @@ -11138,7 +11262,8 @@ bool Client::_ll_forget(Inode *in, uint64_t count) tout(cct) << count << std::endl; // Ignore forget if we're no longer mounted - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return true; if (ino == 1) return true; // ignore forget on root. @@ -11186,11 +11311,12 @@ snapid_t Client::ll_get_snapid(Inode *in) Inode *Client::ll_get_inode(ino_t ino) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return NULL; + std::lock_guard lock(client_lock); + vinodeno_t vino = _map_faked_ino(ino); unordered_map::iterator p = inode_map.find(vino); if (p == inode_map.end()) @@ -11202,11 +11328,12 @@ Inode *Client::ll_get_inode(ino_t ino) Inode *Client::ll_get_inode(vinodeno_t vino) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return NULL; + std::lock_guard lock(client_lock); + unordered_map::iterator p = inode_map.find(vino); if (p == inode_map.end()) return NULL; @@ -11231,11 +11358,12 @@ int Client::_ll_getattr(Inode *in, int caps, const UserPerm& perms) int Client::ll_getattr(Inode *in, struct stat *attr, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + int res = _ll_getattr(in, CEPH_STAT_CAP_INODE_ALL, perms); if (res == 0) @@ -11247,11 +11375,12 @@ int Client::ll_getattr(Inode *in, struct stat *attr, const UserPerm& perms) int Client::ll_getattrx(Inode *in, struct ceph_statx *stx, unsigned int want, unsigned int flags, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + int res = 0; unsigned mask = statx_to_mask(flags, want); @@ -11296,11 +11425,12 @@ int Client::_ll_setattrx(Inode *in, struct ceph_statx *stx, int mask, int Client::ll_setattrx(Inode *in, struct ceph_statx *stx, int mask, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef target(in); int res = _ll_setattrx(in, stx, mask, perms, &target); if (res == 0) { @@ -11318,11 +11448,12 @@ int Client::ll_setattr(Inode *in, struct stat *attr, int mask, struct ceph_statx stx; stat_to_statx(attr, &stx); - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef target(in); int res = _ll_setattrx(in, &stx, mask, perms, &target); if (res == 0) { @@ -11341,11 +11472,12 @@ int Client::ll_setattr(Inode *in, struct stat *attr, int mask, int Client::getxattr(const char *path, const char *name, void *value, size_t size, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef in; int r = Client::path_walk(path, &in, perms, true, CEPH_STAT_CAP_XATTR); if (r < 0) @@ -11356,11 +11488,12 @@ int Client::getxattr(const char *path, const char *name, void *value, size_t siz int Client::lgetxattr(const char *path, const char *name, void *value, size_t size, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef in; int r = Client::path_walk(path, &in, perms, false, CEPH_STAT_CAP_XATTR); if (r < 0) @@ -11371,11 +11504,12 @@ int Client::lgetxattr(const char *path, const char *name, void *value, size_t si int Client::fgetxattr(int fd, const char *name, void *value, size_t size, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -11385,11 +11519,12 @@ int Client::fgetxattr(int fd, const char *name, void *value, size_t size, int Client::listxattr(const char *path, char *list, size_t size, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef in; int r = Client::path_walk(path, &in, perms, true, CEPH_STAT_CAP_XATTR); if (r < 0) @@ -11400,11 +11535,12 @@ int Client::listxattr(const char *path, char *list, size_t size, int Client::llistxattr(const char *path, char *list, size_t size, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef in; int r = Client::path_walk(path, &in, perms, false, CEPH_STAT_CAP_XATTR); if (r < 0) @@ -11414,11 +11550,12 @@ int Client::llistxattr(const char *path, char *list, size_t size, int Client::flistxattr(int fd, char *list, size_t size, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -11428,11 +11565,12 @@ int Client::flistxattr(int fd, char *list, size_t size, const UserPerm& perms) int Client::removexattr(const char *path, const char *name, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef in; int r = Client::path_walk(path, &in, perms, true); if (r < 0) @@ -11443,11 +11581,12 @@ int Client::removexattr(const char *path, const char *name, int Client::lremovexattr(const char *path, const char *name, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef in; int r = Client::path_walk(path, &in, perms, false); if (r < 0) @@ -11457,11 +11596,12 @@ int Client::lremovexattr(const char *path, const char *name, int Client::fremovexattr(int fd, const char *name, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -11473,11 +11613,12 @@ int Client::setxattr(const char *path, const char *name, const void *value, { _setxattr_maybe_wait_for_osdmap(name, value, size); - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef in; int r = Client::path_walk(path, &in, perms, true); if (r < 0) @@ -11490,11 +11631,12 @@ int Client::lsetxattr(const char *path, const char *name, const void *value, { _setxattr_maybe_wait_for_osdmap(name, value, size); - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + InodeRef in; int r = Client::path_walk(path, &in, perms, false); if (r < 0) @@ -11507,11 +11649,12 @@ int Client::fsetxattr(int fd, const char *name, const void *value, size_t size, { _setxattr_maybe_wait_for_osdmap(name, value, size); - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -11595,6 +11738,10 @@ int Client::_getxattr(InodeRef &in, const char *name, void *value, size_t size, int Client::ll_getxattr(Inode *in, const char *name, void *value, size_t size, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vino = _get_vino(in); ldout(cct, 3) << __func__ << " " << vino << " " << name << " size " << size << dendl; @@ -11603,9 +11750,6 @@ int Client::ll_getxattr(Inode *in, const char *name, void *value, tout(cct) << name << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - if (!fuse_default_permissions) { int r = xattr_permission(in, name, MAY_READ, perms); if (r < 0) @@ -11648,6 +11792,10 @@ out: int Client::ll_listxattr(Inode *in, char *names, size_t size, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vino = _get_vino(in); ldout(cct, 3) << __func__ << " " << vino << " size " << size << dendl; @@ -11656,9 +11804,6 @@ int Client::ll_listxattr(Inode *in, char *names, size_t size, tout(cct) << size << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - return _listxattr(in, names, size, perms); } @@ -11850,6 +11995,10 @@ void Client::_setxattr_maybe_wait_for_osdmap(const char *name, const void *value int Client::ll_setxattr(Inode *in, const char *name, const void *value, size_t size, int flags, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + _setxattr_maybe_wait_for_osdmap(name, value, size); vinodeno_t vino = _get_vino(in); @@ -11860,9 +12009,6 @@ int Client::ll_setxattr(Inode *in, const char *name, const void *value, tout(cct) << name << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - if (!fuse_default_permissions) { int r = xattr_permission(in, name, MAY_WRITE, perms); if (r < 0) @@ -11915,6 +12061,10 @@ int Client::_removexattr(InodeRef &in, const char *name, const UserPerm& perms) int Client::ll_removexattr(Inode *in, const char *name, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vino = _get_vino(in); ldout(cct, 3) << "ll_removexattr " << vino << " " << name << dendl; @@ -11923,9 +12073,6 @@ int Client::ll_removexattr(Inode *in, const char *name, const UserPerm& perms) tout(cct) << name << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - if (!fuse_default_permissions) { int r = xattr_permission(in, name, MAY_WRITE, perms); if (r < 0) @@ -12195,6 +12342,10 @@ const Client::VXattr *Client::_match_vxattr(Inode *in, const char *name) int Client::ll_readlink(Inode *in, char *buf, size_t buflen, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vino = _get_vino(in); ldout(cct, 3) << "ll_readlink " << vino << dendl; @@ -12202,9 +12353,6 @@ int Client::ll_readlink(Inode *in, char *buf, size_t buflen, const UserPerm& per tout(cct) << vino.ino.val << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - for (auto dn : in->dentries) { touch_dn(dn); } @@ -12272,6 +12420,10 @@ int Client::ll_mknod(Inode *parent, const char *name, mode_t mode, dev_t rdev, struct stat *attr, Inode **out, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vparent = _get_vino(parent); ldout(cct, 3) << "ll_mknod " << vparent << " " << name << dendl; @@ -12282,9 +12434,6 @@ int Client::ll_mknod(Inode *parent, const char *name, mode_t mode, tout(cct) << rdev << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - if (!fuse_default_permissions) { int r = may_create(parent, perms); if (r < 0) @@ -12309,7 +12458,12 @@ int Client::ll_mknodx(Inode *parent, const char *name, mode_t mode, struct ceph_statx *stx, unsigned want, unsigned flags, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + unsigned caps = statx_to_mask(flags, want); + vinodeno_t vparent = _get_vino(parent); ldout(cct, 3) << "ll_mknodx " << vparent << " " << name << dendl; @@ -12320,8 +12474,6 @@ int Client::ll_mknodx(Inode *parent, const char *name, mode_t mode, tout(cct) << rdev << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (!fuse_default_permissions) { int r = may_create(parent, perms); @@ -12497,6 +12649,10 @@ int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& pe int Client::ll_mkdir(Inode *parent, const char *name, mode_t mode, struct stat *attr, Inode **out, const UserPerm& perm) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vparent = _get_vino(parent); ldout(cct, 3) << "ll_mkdir " << vparent << " " << name << dendl; @@ -12506,8 +12662,6 @@ int Client::ll_mkdir(Inode *parent, const char *name, mode_t mode, tout(cct) << mode << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (!fuse_default_permissions) { int r = may_create(parent, perm); @@ -12532,6 +12686,10 @@ int Client::ll_mkdirx(Inode *parent, const char *name, mode_t mode, Inode **out, struct ceph_statx *stx, unsigned want, unsigned flags, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vparent = _get_vino(parent); ldout(cct, 3) << "ll_mkdirx " << vparent << " " << name << dendl; @@ -12541,8 +12699,6 @@ int Client::ll_mkdirx(Inode *parent, const char *name, mode_t mode, Inode **out, tout(cct) << mode << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (!fuse_default_permissions) { int r = may_create(parent, perms); @@ -12615,6 +12771,10 @@ int Client::_symlink(Inode *dir, const char *name, const char *target, int Client::ll_symlink(Inode *parent, const char *name, const char *value, struct stat *attr, Inode **out, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vparent = _get_vino(parent); ldout(cct, 3) << "ll_symlink " << vparent << " " << name << " -> " << value @@ -12625,8 +12785,6 @@ int Client::ll_symlink(Inode *parent, const char *name, const char *value, tout(cct) << value << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (!fuse_default_permissions) { int r = may_create(parent, perms); @@ -12651,6 +12809,10 @@ int Client::ll_symlinkx(Inode *parent, const char *name, const char *value, Inode **out, struct ceph_statx *stx, unsigned want, unsigned flags, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vparent = _get_vino(parent); ldout(cct, 3) << "ll_symlinkx " << vparent << " " << name << " -> " << value @@ -12661,8 +12823,6 @@ int Client::ll_symlinkx(Inode *parent, const char *name, const char *value, tout(cct) << value << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (!fuse_default_permissions) { int r = may_create(parent, perms); @@ -12735,6 +12895,10 @@ int Client::_unlink(Inode *dir, const char *name, const UserPerm& perm) int Client::ll_unlink(Inode *in, const char *name, const UserPerm& perm) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vino = _get_vino(in); ldout(cct, 3) << "ll_unlink " << vino << " " << name << dendl; @@ -12743,8 +12907,6 @@ int Client::ll_unlink(Inode *in, const char *name, const UserPerm& perm) tout(cct) << name << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (!fuse_default_permissions) { int r = may_delete(in, name, perm); @@ -12809,6 +12971,10 @@ int Client::_rmdir(Inode *dir, const char *name, const UserPerm& perms) int Client::ll_rmdir(Inode *in, const char *name, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vino = _get_vino(in); ldout(cct, 3) << "ll_rmdir " << vino << " " << name << dendl; @@ -12817,8 +12983,6 @@ int Client::ll_rmdir(Inode *in, const char *name, const UserPerm& perms) tout(cct) << name << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (!fuse_default_permissions) { int r = may_delete(in, name, perms); @@ -12988,6 +13152,10 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch int Client::ll_rename(Inode *parent, const char *name, Inode *newparent, const char *newname, const UserPerm& perm) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vparent = _get_vino(parent); vinodeno_t vnewparent = _get_vino(newparent); @@ -13000,8 +13168,6 @@ int Client::ll_rename(Inode *parent, const char *name, Inode *newparent, tout(cct) << newname << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (!fuse_default_permissions) { int r = may_delete(parent, name, perm); @@ -13063,6 +13229,10 @@ int Client::_link(Inode *in, Inode *dir, const char *newname, const UserPerm& pe int Client::ll_link(Inode *in, Inode *newparent, const char *newname, const UserPerm& perm) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vino = _get_vino(in); vinodeno_t vnewparent = _get_vino(newparent); @@ -13073,12 +13243,10 @@ int Client::ll_link(Inode *in, Inode *newparent, const char *newname, tout(cct) << vnewparent << std::endl; tout(cct) << newname << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - InodeRef target; + std::scoped_lock lock(client_lock); + if (!fuse_default_permissions) { if (S_ISDIR(in->mode)) return -EPERM; @@ -13197,6 +13365,10 @@ uint64_t Client::ll_get_internal_offset(Inode *in, uint64_t blockno) int Client::ll_opendir(Inode *in, int flags, dir_result_t** dirpp, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vino = _get_vino(in); ldout(cct, 3) << "ll_opendir " << vino << dendl; @@ -13204,8 +13376,6 @@ int Client::ll_opendir(Inode *in, int flags, dir_result_t** dirpp, tout(cct) << vino.ino.val << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (!fuse_default_permissions) { int r = may_open(in, flags, perms); @@ -13223,13 +13393,15 @@ int Client::ll_opendir(Inode *in, int flags, dir_result_t** dirpp, int Client::ll_releasedir(dir_result_t *dirp) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << "ll_releasedir " << dirp << dendl; tout(cct) << "ll_releasedir" << std::endl; tout(cct) << (unsigned long)dirp << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; _closedir(dirp); return 0; @@ -13237,14 +13409,15 @@ int Client::ll_releasedir(dir_result_t *dirp) int Client::ll_fsyncdir(dir_result_t *dirp) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << "ll_fsyncdir " << dirp << dendl; tout(cct) << "ll_fsyncdir" << std::endl; tout(cct) << (unsigned long)dirp << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - return _fsync(dirp->inode.get(), false); } @@ -13252,6 +13425,10 @@ int Client::ll_open(Inode *in, int flags, Fh **fhp, const UserPerm& perms) { ceph_assert(!(flags & O_CREAT)); + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + vinodeno_t vino = _get_vino(in); ldout(cct, 3) << "ll_open " << vino << " " << ceph_flags_sys2wire(flags) << dendl; @@ -13260,8 +13437,6 @@ int Client::ll_open(Inode *in, int flags, Fh **fhp, const UserPerm& perms) tout(cct) << ceph_flags_sys2wire(flags) << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; int r; if (!fuse_default_permissions) { @@ -13369,12 +13544,13 @@ int Client::ll_create(Inode *parent, const char *name, mode_t mode, int flags, struct stat *attr, Inode **outp, Fh **fhp, const UserPerm& perms) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + std::lock_guard lock(client_lock); InodeRef in; - if (unmounting) - return -ENOTCONN; - int r = _ll_create(parent, name, mode, flags, &in, CEPH_STAT_CAP_INODE_ALL, fhp, perms); if (r >= 0) { @@ -13399,12 +13575,13 @@ int Client::ll_createx(Inode *parent, const char *name, mode_t mode, const UserPerm& perms) { unsigned caps = statx_to_mask(lflags, want); + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + std::lock_guard lock(client_lock); InodeRef in; - if (unmounting) - return -ENOTCONN; - int r = _ll_create(parent, name, mode, oflags, &in, caps, fhp, perms); if (r >= 0) { ceph_assert(in); @@ -13425,31 +13602,34 @@ int Client::ll_createx(Inode *parent, const char *name, mode_t mode, loff_t Client::ll_lseek(Fh *fh, loff_t offset, int whence) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << "ll_lseek" << std::endl; tout(cct) << offset << std::endl; tout(cct) << whence << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - return _lseek(fh, offset, whence); } int Client::ll_read(Fh *fh, loff_t off, loff_t len, bufferlist *bl) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << "ll_read " << fh << " " << fh->inode->ino << " " << " " << off << "~" << len << dendl; tout(cct) << "ll_read" << std::endl; tout(cct) << (unsigned long)fh << std::endl; tout(cct) << off << std::endl; tout(cct) << len << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - /* We can't return bytes written larger than INT_MAX, clamp len to that */ len = std::min(len, (loff_t)INT_MAX); + std::scoped_lock lock(client_lock); + int r = _read(fh, off, len, bl); ldout(cct, 3) << "ll_read " << fh << " " << off << "~" << len << " = " << r << dendl; @@ -13462,9 +13642,8 @@ int Client::ll_read_block(Inode *in, uint64_t blockid, uint64_t length, file_layout_t* layout) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; vinodeno_t vino = _get_vino(in); @@ -13472,6 +13651,8 @@ int Client::ll_read_block(Inode *in, uint64_t blockid, C_SaferCond onfinish; bufferlist bl; + std::scoped_lock lock(client_lock); + objecter->read(oid, object_locator_t(layout->pool_id), offset, @@ -13504,7 +13685,11 @@ int Client::ll_write_block(Inode *in, uint64_t blockid, vinodeno_t vino = ll_get_vino(in); int r = 0; std::unique_ptr onsafe = nullptr; - + + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + if (length == 0) { return -EINVAL; } @@ -13527,11 +13712,6 @@ int Client::ll_write_block(Inode *in, uint64_t blockid, /* lock just in time */ client_lock.lock(); - if (unmounting) { - client_lock.unlock(); - return -ENOTCONN; - } - objecter->write(oid, object_locator_t(layout->pool_id), offset, @@ -13558,7 +13738,6 @@ int Client::ll_commit_blocks(Inode *in, uint64_t offset, uint64_t length) { - std::lock_guard lock(client_lock); /* BarrierContext *bctx; vinodeno_t vino = _get_vino(in); @@ -13571,6 +13750,7 @@ int Client::ll_commit_blocks(Inode *in, return -EINVAL; } + std::scoped_lock lock(client_lock); map::iterator p = barriers.find(ino); if (p != barriers.end()) { barrier_interval civ(offset, offset + length); @@ -13589,12 +13769,14 @@ int Client::ll_write(Fh *fh, loff_t off, loff_t len, const char *data) tout(cct) << off << std::endl; tout(cct) << len << std::endl; - std::scoped_lock lock(client_lock); - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; /* We can't return bytes written larger than INT_MAX, clamp len to that */ len = std::min(len, (loff_t)INT_MAX); + std::scoped_lock lock(client_lock); + int r = _write(fh, off, len, data, NULL, 0); ldout(cct, 3) << "ll_write " << fh << " " << off << "~" << len << " = " << r << dendl; @@ -13603,43 +13785,49 @@ int Client::ll_write(Fh *fh, loff_t off, loff_t len, const char *data) int64_t Client::ll_writev(struct Fh *fh, const struct iovec *iov, int iovcnt, int64_t off) { - std::lock_guard lock(client_lock); - if (unmounting) - return -ENOTCONN; + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + + std::scoped_lock lock(client_lock); return _preadv_pwritev_locked(fh, iov, iovcnt, off, true, false); } int64_t Client::ll_readv(struct Fh *fh, const struct iovec *iov, int iovcnt, int64_t off) { - std::lock_guard lock(client_lock); - if (unmounting) - return -ENOTCONN; + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + + std::scoped_lock lock(client_lock); return _preadv_pwritev_locked(fh, iov, iovcnt, off, false, false); } int Client::ll_flush(Fh *fh) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << "ll_flush " << fh << " " << fh->inode->ino << " " << dendl; tout(cct) << "ll_flush" << std::endl; tout(cct) << (unsigned long)fh << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - return _flush(fh); } int Client::ll_fsync(Fh *fh, bool syncdataonly) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << "ll_fsync " << fh << " " << fh->inode->ino << " " << dendl; tout(cct) << "ll_fsync" << std::endl; tout(cct) << (unsigned long)fh << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - int r = _fsync(fh, syncdataonly); if (r) { // If we're returning an error, clear it from the FH @@ -13650,14 +13838,15 @@ int Client::ll_fsync(Fh *fh, bool syncdataonly) int Client::ll_sync_inode(Inode *in, bool syncdataonly) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << "ll_sync_inode " << *in << " " << dendl; tout(cct) << "ll_sync_inode" << std::endl; tout(cct) << (unsigned long)in << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - return _fsync(in, syncdataonly); } @@ -13795,25 +13984,27 @@ int Client::_fallocate(Fh *fh, int mode, int64_t offset, int64_t length) int Client::ll_fallocate(Fh *fh, int mode, int64_t offset, int64_t length) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << __func__ << " " << fh << " " << fh->inode->ino << " " << dendl; tout(cct) << __func__ << " " << mode << " " << offset << " " << length << std::endl; tout(cct) << (unsigned long)fh << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - return _fallocate(fh, mode, offset, length); } int Client::fallocate(int fd, int mode, loff_t offset, loff_t length) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + tout(cct) << __func__ << " " << " " << fd << mode << " " << offset << " " << length << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - Fh *fh = get_filehandle(fd); if (!fh) return -EBADF; @@ -13826,14 +14017,16 @@ int Client::fallocate(int fd, int mode, loff_t offset, loff_t length) int Client::ll_release(Fh *fh) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << __func__ << " (fh)" << fh << " " << fh->inode->ino << " " << dendl; tout(cct) << __func__ << " (fh)" << std::endl; tout(cct) << (unsigned long)fh << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; if (ll_unclosed_fh_set.count(fh)) ll_unclosed_fh_set.erase(fh); @@ -13842,43 +14035,46 @@ int Client::ll_release(Fh *fh) int Client::ll_getlk(Fh *fh, struct flock *fl, uint64_t owner) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << "ll_getlk (fh)" << fh << " " << fh->inode->ino << dendl; tout(cct) << "ll_getk (fh)" << (unsigned long)fh << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - return _getlk(fh, fl, owner); } int Client::ll_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << __func__ << " (fh) " << fh << " " << fh->inode->ino << dendl; tout(cct) << __func__ << " (fh)" << (unsigned long)fh << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - return _setlk(fh, fl, owner, sleep); } int Client::ll_flock(Fh *fh, int cmd, uint64_t owner) { + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + ldout(cct, 3) << __func__ << " (fh) " << fh << " " << fh->inode->ino << dendl; tout(cct) << __func__ << " (fh)" << (unsigned long)fh << std::endl; std::scoped_lock lock(client_lock); - if (unmounting) - return -ENOTCONN; - return _flock(fh, cmd, owner); } int Client::set_deleg_timeout(uint32_t timeout) { - std::lock_guard lock(client_lock); + std::scoped_lock lock(client_lock); /* * The whole point is to prevent blacklisting so we must time out the @@ -13895,11 +14091,12 @@ int Client::ll_delegation(Fh *fh, unsigned cmd, ceph_deleg_cb_t cb, void *priv) { int ret = -EINVAL; - std::lock_guard lock(client_lock); - - if (!mounted) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + Inode *inode = fh->inode.get(); switch(cmd) { @@ -13950,11 +14147,12 @@ void Client::ll_interrupt(void *d) int Client::describe_layout(const char *relpath, file_layout_t *lp, const UserPerm& perms) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + filepath path(relpath); InodeRef in; int r = path_walk(path, &in, perms); @@ -13969,11 +14167,12 @@ int Client::describe_layout(const char *relpath, file_layout_t *lp, int Client::fdescribe_layout(int fd, file_layout_t *lp) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -13987,11 +14186,12 @@ int Client::fdescribe_layout(int fd, file_layout_t *lp) int64_t Client::get_default_pool_id() { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + /* first data pool is the default */ return mdsmap->get_first_data_pool(); } @@ -14000,22 +14200,24 @@ int64_t Client::get_default_pool_id() int64_t Client::get_pool_id(const char *pool_name) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::lock_guard lock(client_lock); + return objecter->with_osdmap(std::mem_fn(&OSDMap::lookup_pg_pool_name), pool_name); } string Client::get_pool_name(int64_t pool) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return string(); + std::scoped_lock lock(client_lock); + return objecter->with_osdmap([pool](const OSDMap& o) { return o.have_pg_pool(pool) ? o.get_pool_name(pool) : string(); }); @@ -14023,11 +14225,12 @@ string Client::get_pool_name(int64_t pool) int Client::get_pool_replication(int64_t pool) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + return objecter->with_osdmap([pool](const OSDMap& o) { return o.have_pg_pool(pool) ? o.get_pg_pool(pool)->get_size() : -ENOENT; }); @@ -14035,11 +14238,12 @@ int Client::get_pool_replication(int64_t pool) int Client::get_file_extent_osds(int fd, loff_t off, loff_t *len, vector& osds) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -14081,11 +14285,12 @@ int Client::get_file_extent_osds(int fd, loff_t off, loff_t *len, vector& o int Client::get_osd_crush_location(int id, vector >& path) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + if (id < 0) return -EINVAL; return objecter->with_osdmap([&](const OSDMap& o) { @@ -14096,11 +14301,12 @@ int Client::get_osd_crush_location(int id, vector >& path) int Client::get_file_stripe_address(int fd, loff_t offset, vector& address) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -14129,11 +14335,12 @@ int Client::get_file_stripe_address(int fd, loff_t offset, int Client::get_osd_addr(int osd, entity_addr_t& addr) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + return objecter->with_osdmap([&](const OSDMap& o) { if (!o.exists(osd)) return -ENOENT; @@ -14146,11 +14353,12 @@ int Client::get_osd_addr(int osd, entity_addr_t& addr) int Client::enumerate_layout(int fd, vector& result, loff_t length, loff_t offset) { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + Fh *f = get_filehandle(fd); if (!f) return -EBADF; @@ -14167,11 +14375,12 @@ int Client::enumerate_layout(int fd, vector& result, /* find an osd with the same ip. -ENXIO if none. */ int Client::get_local_osd() { - std::lock_guard lock(client_lock); - - if (unmounting) + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) return -ENOTCONN; + std::scoped_lock lock(client_lock); + objecter->with_osdmap([this](const OSDMap& o) { if (o.get_epoch() != local_osd_epoch) { local_osd = o.find_osd_on_ip(messenger->get_myaddrs().front()); @@ -14201,8 +14410,8 @@ bool Client::ms_handle_reset(Connection *con) void Client::ms_handle_remote_reset(Connection *con) { + std::scoped_lock lock(client_lock); ldout(cct, 0) << __func__ << " on " << con->get_peer_addr() << dendl; - std::lock_guard l(client_lock); switch (con->get_peer_type()) { case CEPH_ENTITY_TYPE_MDS: { @@ -14562,8 +14771,10 @@ void Client::clear_filer_flags(int flags) // called before mount void Client::set_uuid(const std::string& uuid) { + RWRef_t iref_reader(initialize_state, CLIENT_INITIALIZED); + ceph_assert(iref_reader.is_state_satisfied()); + std::lock_guard l(client_lock); - assert(initialized); assert(!uuid.empty()); metadata["uuid"] = uuid; @@ -14573,8 +14784,10 @@ void Client::set_uuid(const std::string& uuid) // called before mount. 0 means infinite void Client::set_session_timeout(unsigned timeout) { + RWRef_t iref_reader(initialize_state, CLIENT_INITIALIZED); + ceph_assert(iref_reader.is_state_satisfied()); + std::lock_guard l(client_lock); - assert(initialized); metadata["timeout"] = stringify(timeout); } @@ -14583,13 +14796,14 @@ void Client::set_session_timeout(unsigned timeout) int Client::start_reclaim(const std::string& uuid, unsigned flags, const std::string& fs_name) { - std::unique_lock l(client_lock); - if (!initialized) + RWRef_t iref_reader(initialize_state, CLIENT_INITIALIZED); + if (!iref_reader.is_state_satisfied()) return -ENOTCONN; if (uuid.empty()) return -EINVAL; + std::unique_lock l(client_lock); { auto it = metadata.find("uuid"); if (it != metadata.end() && it->second == uuid) @@ -14806,11 +15020,13 @@ StandaloneClient::~StandaloneClient() int StandaloneClient::init() { + RWRef_t iref_writer(initialize_state, CLIENT_INITIALIZING, false); + ceph_assert(iref_writer.is_first_writer()); + _pre_init(); objecter->init(); client_lock.lock(); - ceph_assert(!is_initialized()); messenger->add_dispatcher_tail(objecter); messenger->add_dispatcher_tail(this); @@ -14834,6 +15050,7 @@ int StandaloneClient::init() client_lock.unlock(); _finish_init(); + iref_writer.update_state(CLIENT_INITIALIZED); return 0; } diff --git a/src/client/Client.h b/src/client/Client.h index f1057e8465d..1437d8f29b0 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -37,6 +37,7 @@ #include "msg/Messenger.h" #include "osdc/ObjectCacher.h" +#include "RWRef.h" #include "InodeRef.h" #include "MetaSession.h" #include "UserPerm.h" @@ -66,6 +67,7 @@ class WritebackHandler; class MDSMap; class Message; +class destructive_lock_ref_t; enum { l_c_first = 20000, @@ -236,6 +238,8 @@ public: friend class C_Client_CacheRelease; // Asserts on client_lock friend class SyntheticClient; friend void intrusive_ptr_release(Inode *in); + template friend struct RWRefState; + template friend class RWRef; using Dispatcher::cct; @@ -760,9 +764,6 @@ protected: static const unsigned CHECK_CAPS_NODELAY = 0x1; static const unsigned CHECK_CAPS_SYNCHRONOUS = 0x2; - - bool is_initialized() const { return initialized; } - void check_caps(Inode *in, unsigned flags); void set_cap_epoch_barrier(epoch_t e); @@ -982,6 +983,124 @@ protected: client_t whoami; + /* The state migration mechanism */ + enum _state { + /* For the initialize_state */ + CLIENT_NEW, // The initial state for the initialize_state or after Client::shutdown() + CLIENT_INITIALIZING, // At the beginning of the Client::init() + CLIENT_INITIALIZED, // At the end of CLient::init() + + /* For the mount_state */ + CLIENT_UNMOUNTED, // The initial state for the mount_state or after unmounted + CLIENT_MOUNTING, // At the beginning of Client::mount() + CLIENT_MOUNTED, // At the end of Client::mount() + CLIENT_UNMOUNTING, // At the beginning of the Client::_unmout() + }; + + typedef enum _state state_t; + using RWRef_t = RWRef; + + struct mount_state_t : public RWRefState { + public: + bool is_valid_state(state_t state) override { + switch (state) { + case Client::CLIENT_MOUNTING: + case Client::CLIENT_MOUNTED: + case Client::CLIENT_UNMOUNTING: + case Client::CLIENT_UNMOUNTED: + return true; + default: + return false; + } + } + + int check_reader_state(state_t require) override { + if (require == Client::CLIENT_MOUNTING && + (state == Client::CLIENT_MOUNTING || state == Client::CLIENT_MOUNTED)) + return true; + else + return false; + } + + /* The state migration check */ + int check_writer_state(state_t require) override { + if (require == Client::CLIENT_MOUNTING && + state == Client::CLIENT_UNMOUNTED) + return true; + else if (require == Client::CLIENT_MOUNTED && + state == Client::CLIENT_MOUNTING) + return true; + else if (require == Client::CLIENT_UNMOUNTING && + state == Client::CLIENT_MOUNTED) + return true; + else if (require == Client::CLIENT_UNMOUNTED && + state == Client::CLIENT_UNMOUNTING) + return true; + else + return false; + } + + mount_state_t(state_t state, const char *lockname, uint64_t reader_cnt=0) + : RWRefState (state, lockname, reader_cnt) {} + ~mount_state_t() {} + }; + + struct initialize_state_t : public RWRefState { + public: + bool is_valid_state(state_t state) override { + switch (state) { + case Client::CLIENT_NEW: + case Client::CLIENT_INITIALIZING: + case Client::CLIENT_INITIALIZED: + return true; + default: + return false; + } + } + + int check_reader_state(state_t require) override { + if (require == Client::CLIENT_INITIALIZED && + state >= Client::CLIENT_INITIALIZED) + return true; + else + return false; + } + + /* The state migration check */ + int check_writer_state(state_t require) override { + if (require == Client::CLIENT_INITIALIZING && + (state == Client::CLIENT_NEW)) + return true; + else if (require == Client::CLIENT_INITIALIZED && + (state == Client::CLIENT_INITIALIZING)) + return true; + else if (require == Client::CLIENT_NEW && + (state == Client::CLIENT_INITIALIZED)) + return true; + else + return false; + } + + initialize_state_t(state_t state, const char *lockname, uint64_t reader_cnt=0) + : RWRefState (state, lockname, reader_cnt) {} + ~initialize_state_t() {} + }; + + struct mount_state_t mount_state; + bool is_unmounting() { + return mount_state.check_current_state(CLIENT_UNMOUNTING); + } + bool is_mounted() { + return mount_state.check_current_state(CLIENT_MOUNTED); + } + bool is_mounting() { + return mount_state.check_current_state(CLIENT_MOUNTING); + } + + struct initialize_state_t initialize_state; + bool is_initialized() { + return initialize_state.check_current_state(CLIENT_INITIALIZED); + } private: struct C_Readahead : public Context { @@ -1249,9 +1368,6 @@ private: ceph::unordered_set opened_dirs; uint64_t fd_gen = 1; - bool initialized = false; - bool mounted = false; - bool unmounting = false; bool blacklisted = false; ceph::unordered_map inode_map; -- 2.39.5