diff --git a/src/client/Client.cc b/src/client/Client.cc index 01e130037a256..0695ea2400fff 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -1061,7 +1061,6 @@ Dentry *Client::insert_dentry_inode(Dir *dir, const string& dname, LeaseStat *dl } update_dentry_lease(dn, dlease, from, session); - dn->alternate_name = std::move(dlease->alternate_name); return dn; } @@ -1069,6 +1068,8 @@ void Client::update_dentry_lease(Dentry *dn, LeaseStat *dlease, utime_t from, Me { utime_t dttl = from; dttl += (float)dlease->duration_ms / 1000.0; + + ldout(cct, 15) << __func__ << " " << *dn << " " << *dlease << " from " << from << dendl; ceph_assert(dn); @@ -1085,6 +1086,7 @@ void Client::update_dentry_lease(Dentry *dn, LeaseStat *dlease, utime_t from, Me dn->cap_shared_gen = dn->dir->parent_inode->shared_gen; if (dlease->mask & CEPH_LEASE_PRIMARY_LINK) dn->mark_primary(); + dn->alternate_name = std::move(dlease->alternate_name); } @@ -1281,7 +1283,7 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session, dirp->cache_index++; } // add to cached result list - dirp->buffer.push_back(dir_result_t::dentry(dn->offset, dname, in)); + dirp->buffer.push_back(dir_result_t::dentry(dn->offset, dname, dn->alternate_name, in)); ldout(cct, 15) << __func__ << " " << hex << dn->offset << dec << ": '" << dname << "' -> " << in->ino << dendl; } @@ -2371,6 +2373,7 @@ ref_t Client::build_client_request(MetaRequest *request) } req->set_filepath(request->get_filepath()); req->set_filepath2(request->get_filepath2()); + req->set_alternate_name(request->alternate_name); req->set_data(request->data); req->set_retry_attempt(request->retry_attempt++); req->head.num_fwd = request->num_fwd; @@ -6697,10 +6700,11 @@ bool Client::_dentry_valid(const Dentry *dn) } int Client::_lookup(Inode *dir, const string& dname, int mask, InodeRef *target, - const UserPerm& perms) + const UserPerm& perms, std::string* alternate_name) { int r = 0; Dentry *dn = NULL; + bool did_lookup_request = false; // can only request shared caps mask &= CEPH_CAP_ANY_SHARED | CEPH_STAT_RSTAT; @@ -6746,13 +6750,13 @@ int Client::_lookup(Inode *dir, const string& dname, int mask, InodeRef *target, goto done; } +relookup: if (dir->dir && dir->dir->dentries.count(dname)) { dn = dir->dir->dentries[dname]; - ldout(cct, 20) << __func__ << " have dn " << dname << " mds." << dn->lease_mds << " ttl " << dn->lease_ttl - << " seq " << dn->lease_seq - << dendl; + ldout(cct, 20) << __func__ << " have " << *dn << " from mds." << dn->lease_mds + << " ttl " << dn->lease_ttl << " seq " << dn->lease_seq << dendl; if (!dn->inode || dn->inode->caps_issued_mask(mask, true)) { if (_dentry_valid(dn)) { @@ -6784,16 +6788,29 @@ int Client::_lookup(Inode *dir, const string& dname, int mask, InodeRef *target, } } + if (did_lookup_request) { + r = 0; + goto done; + } r = _do_lookup(dir, dname, mask, target, perms); - goto done; + did_lookup_request = true; + if (r == 0) { + /* complete lookup to get dentry for alternate_name */ + goto relookup; + } else { + goto done; + } hit_dn: if (dn->inode) { *target = dn->inode; + if (alternate_name) + *alternate_name = dn->alternate_name; } else { r = -ENOENT; } touch_dn(dn); + goto done; done: if (r < 0) @@ -6825,11 +6842,33 @@ int Client::get_or_create(Inode *dir, const char* name, return 0; } +int Client::walk(std::string_view path, walk_dentry_result* wdr, const UserPerm& perms, bool followsym) +{ + RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); + if (!mref_reader.is_state_satisfied()) + return -ENOTCONN; + + ldout(cct, 10) << __func__ << ": " << path << dendl; + + std::scoped_lock lock(client_lock); + + return path_walk(path, wdr, perms, followsym); +} + int Client::path_walk(const filepath& origpath, InodeRef *end, const UserPerm& perms, bool followsym, int mask) +{ + walk_dentry_result wdr; + int rc = path_walk(origpath, &wdr, perms, followsym, mask); + *end = std::move(wdr.in); + return rc; +} + +int Client::path_walk(const filepath& origpath, walk_dentry_result* result, const UserPerm& perms, bool followsym, int mask) { filepath path = origpath; InodeRef cur; + std::string alternate_name; if (origpath.absolute()) cur = root; else @@ -6857,7 +6896,7 @@ int Client::path_walk(const filepath& origpath, InodeRef *end, /* Get extra requested caps on the last component */ if (i == (path.depth() - 1)) caps |= mask; - int r = _lookup(cur.get(), dname, caps, &next, perms); + int r = _lookup(cur.get(), dname, caps, &next, perms, &alternate_name); if (r < 0) return r; // only follow trailing symlink if followsym. always follow @@ -6902,15 +6941,17 @@ int Client::path_walk(const filepath& origpath, InodeRef *end, } if (!cur) return -ENOENT; - if (end) - end->swap(cur); + if (result) { + result->in = std::move(cur); + result->alternate_name = std::move(alternate_name); + } return 0; } // namespace ops -int Client::link(const char *relexisting, const char *relpath, const UserPerm& perm) +int Client::link(const char *relexisting, const char *relpath, const UserPerm& perm, std::string alternate_name) { RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); if (!mref_reader.is_state_satisfied()) @@ -6951,7 +6992,7 @@ int Client::link(const char *relexisting, const char *relpath, const UserPerm& p if (r < 0) return r; } - r = _link(in.get(), dir.get(), name.c_str(), perm); + r = _link(in.get(), dir.get(), name.c_str(), perm, std::move(alternate_name)); return r; } @@ -6984,7 +7025,7 @@ int Client::unlink(const char *relpath, const UserPerm& perm) return _unlink(dir.get(), name.c_str(), perm); } -int Client::rename(const char *relfrom, const char *relto, const UserPerm& perm) +int Client::rename(const char *relfrom, const char *relto, const UserPerm& perm, std::string alternate_name) { RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); if (!mref_reader.is_state_satisfied()) @@ -7022,14 +7063,14 @@ int Client::rename(const char *relfrom, const char *relto, const UserPerm& perm) if (r < 0 && r != -ENOENT) return r; } - r = _rename(fromdir.get(), fromname.c_str(), todir.get(), toname.c_str(), perm); + r = _rename(fromdir.get(), fromname.c_str(), todir.get(), toname.c_str(), perm, std::move(alternate_name)); out: return r; } // dirs -int Client::mkdir(const char *relpath, mode_t mode, const UserPerm& perm) +int Client::mkdir(const char *relpath, mode_t mode, const UserPerm& perm, std::string alternate_name) { RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); if (!mref_reader.is_state_satisfied()) @@ -7057,7 +7098,7 @@ int Client::mkdir(const char *relpath, mode_t mode, const UserPerm& perm) if (r < 0) return r; } - return _mkdir(dir.get(), name.c_str(), mode, perm); + return _mkdir(dir.get(), name.c_str(), mode, perm, 0, {}, std::move(alternate_name)); } int Client::mkdirs(const char *relpath, mode_t mode, const UserPerm& perms) @@ -7179,7 +7220,7 @@ int Client::mknod(const char *relpath, mode_t mode, const UserPerm& perms, dev_t // symlinks -int Client::symlink(const char *target, const char *relpath, const UserPerm& perms) +int Client::symlink(const char *target, const char *relpath, const UserPerm& perms, std::string alternate_name) { RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); if (!mref_reader.is_state_satisfied()) @@ -7206,7 +7247,7 @@ int Client::symlink(const char *target, const char *relpath, const UserPerm& per if (r < 0) return r; } - return _symlink(dir.get(), name.c_str(), target, perms); + return _symlink(dir.get(), name.c_str(), target, perms, std::move(alternate_name)); } int Client::readlink(const char *relpath, char *buf, loff_t size, const UserPerm& perms) @@ -8916,7 +8957,7 @@ int Client::getdir(const char *relpath, list& contents, /****** file i/o **********/ 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) + int object_size, const char *data_pool, std::string alternate_name) { RWRef_t mref_reader(mount_state, CLIENT_MOUNTING); if (!mref_reader.is_state_satisfied()) @@ -8974,7 +9015,8 @@ int Client::open(const char *relpath, int flags, const UserPerm& perms, goto out; } r = _create(dir.get(), dname.c_str(), flags, mode, &in, &fh, stripe_unit, - stripe_count, object_size, data_pool, &created, perms); + stripe_count, object_size, data_pool, &created, perms, + std::move(alternate_name)); } if (r < 0) goto out; @@ -9004,12 +9046,6 @@ int Client::open(const char *relpath, int flags, const UserPerm& perms, return r; } -int Client::open(const char *relpath, int flags, const UserPerm& perms, mode_t mode) -{ - /* Use default file striping parameters */ - return open(relpath, flags, perms, mode, 0, 0, 0, NULL); -} - int Client::lookup_hash(inodeno_t ino, inodeno_t dirino, const char *name, const UserPerm& perms) { @@ -12781,7 +12817,7 @@ int Client::ll_mknodx(Inode *parent, const char *name, mode_t mode, int Client::_create(Inode *dir, 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, - const UserPerm& perms) + const UserPerm& perms, std::string alternate_name) { ldout(cct, 8) << "_create(" << dir->ino << " " << name << ", 0" << oct << mode << dec << ")" << dendl; @@ -12818,6 +12854,7 @@ int Client::_create(Inode *dir, const char *name, int flags, mode_t mode, dir->make_nosnap_relative_path(path); path.push_dentry(name); req->set_filepath(path); + req->set_alternate_name(std::move(alternate_name)); req->set_inode(dir); req->head.args.open.flags = cflags | CEPH_O_CREAT; @@ -12874,7 +12911,8 @@ int Client::_create(Inode *dir, const char *name, int flags, mode_t mode, } int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& perm, - InodeRef *inp, const std::map &metadata) + InodeRef *inp, const std::map &metadata, + std::string alternate_name) { ldout(cct, 8) << "_mkdir(" << dir->ino << " " << name << ", 0" << oct << mode << dec << ", uid " << perm.uid() @@ -12901,6 +12939,7 @@ int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& pe req->set_inode(dir); req->dentry_drop = CEPH_CAP_FILE_SHARED; req->dentry_unless = CEPH_CAP_FILE_EXCL; + req->set_alternate_name(std::move(alternate_name)); mode |= S_IFDIR; bufferlist bl; @@ -13018,7 +13057,7 @@ int Client::ll_mkdirx(Inode *parent, const char *name, mode_t mode, Inode **out, } int Client::_symlink(Inode *dir, const char *name, const char *target, - const UserPerm& perms, InodeRef *inp) + const UserPerm& perms, std::string alternate_name, InodeRef *inp) { ldout(cct, 8) << "_symlink(" << dir->ino << " " << name << ", " << target << ", uid " << perms.uid() << ", gid " << perms.gid() << ")" @@ -13040,6 +13079,7 @@ int Client::_symlink(Inode *dir, const char *name, const char *target, dir->make_nosnap_relative_path(path); path.push_dentry(name); req->set_filepath(path); + req->set_alternate_name(std::move(alternate_name)); req->set_inode(dir); req->set_string2(target); req->dentry_drop = CEPH_CAP_FILE_SHARED; @@ -13088,7 +13128,7 @@ int Client::ll_symlink(Inode *parent, const char *name, const char *value, } InodeRef in; - int r = _symlink(parent, name, value, perms, &in); + int r = _symlink(parent, name, value, perms, "", &in); if (r == 0) { fill_stat(in, attr); _ll_get(in.get()); @@ -13126,7 +13166,7 @@ int Client::ll_symlinkx(Inode *parent, const char *name, const char *value, } InodeRef in; - int r = _symlink(parent, name, value, perms, &in); + int r = _symlink(parent, name, value, perms, "", &in); if (r == 0) { fill_statx(in, statx_to_mask(flags, want), stx); _ll_get(in.get()); @@ -13288,7 +13328,7 @@ int Client::ll_rmdir(Inode *in, const char *name, const UserPerm& perms) return _rmdir(in, name, perms); } -int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const char *toname, const UserPerm& perm) +int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const char *toname, const UserPerm& perm, std::string alternate_name) { ldout(cct, 8) << "_rename(" << fromdir->ino << " " << fromname << " to " << todir->ino << " " << toname @@ -13326,6 +13366,7 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch to.push_dentry(toname); req->set_filepath(to); req->set_filepath2(from); + req->set_alternate_name(std::move(alternate_name)); Dentry *oldde; int res = get_or_create(fromdir, fromname, &oldde); @@ -13424,10 +13465,10 @@ int Client::ll_rename(Inode *parent, const char *name, Inode *newparent, return r; } - return _rename(parent, name, newparent, newname, perm); + return _rename(parent, name, newparent, newname, perm, ""); } -int Client::_link(Inode *in, Inode *dir, const char *newname, const UserPerm& perm, InodeRef *inp) +int Client::_link(Inode *in, Inode *dir, const char *newname, const UserPerm& perm, std::string alternate_name, InodeRef *inp) { ldout(cct, 8) << "_link(" << in->ino << " to " << dir->ino << " " << newname << " uid " << perm.uid() << " gid " << perm.gid() << ")" << dendl; @@ -13447,6 +13488,7 @@ int Client::_link(Inode *in, Inode *dir, const char *newname, const UserPerm& pe filepath path(newname, dir->ino); req->set_filepath(path); + req->set_alternate_name(std::move(alternate_name)); filepath existing(in->ino); req->set_filepath2(existing); @@ -13506,7 +13548,7 @@ int Client::ll_link(Inode *in, Inode *newparent, const char *newname, return r; } - return _link(in, newparent, newname, perm, &target); + return _link(in, newparent, newname, perm, "", &target); } int Client::ll_num_osds(void) @@ -13734,7 +13776,7 @@ int Client::_ll_create(Inode *parent, const char *name, mode_t mode, goto out; } r = _create(parent, name, flags, mode, in, fhp, 0, 0, 0, NULL, &created, - perms); + perms, ""); if (r < 0) goto out; } diff --git a/src/client/Client.h b/src/client/Client.h index 5278fd78b941f..84e49e4f37270 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -136,11 +136,12 @@ struct dir_result_t { struct dentry { int64_t offset; - string name; + std::string name; + std::string alternate_name; InodeRef inode; explicit dentry(int64_t o) : offset(o) {} - dentry(int64_t o, const string& n, const InodeRef& in) : - offset(o), name(n), inode(in) {} + dentry(int64_t o, std::string n, std::string an, InodeRef in) : + offset(o), name(std::move(n)), alternate_name(std::move(an)), inode(std::move(in)) {} }; struct dentry_off_lt { bool operator()(const dentry& d, int64_t off) const { @@ -248,6 +249,11 @@ class Client : public Dispatcher, public md_config_obs_t { typedef int (*add_dirent_cb_t)(void *p, struct dirent *de, struct ceph_statx *stx, off_t off, Inode *in); + struct walk_dentry_result { + InodeRef in; + std::string alternate_name; + }; + class CommandHook : public AdminSocketHook { public: explicit CommandHook(Client *client); @@ -363,19 +369,22 @@ class Client : public Dispatcher, public md_config_obs_t { loff_t telldir(dir_result_t *dirp); void seekdir(dir_result_t *dirp, loff_t offset); - int link(const char *existing, const char *newname, const UserPerm& perm); + int link(const char *existing, const char *newname, const UserPerm& perm, std::string alternate_name=""); int unlink(const char *path, const UserPerm& perm); - int rename(const char *from, const char *to, const UserPerm& perm); + int rename(const char *from, const char *to, const UserPerm& perm, std::string alternate_name=""); // dirs - int mkdir(const char *path, mode_t mode, const UserPerm& perm); + int mkdir(const char *path, mode_t mode, const UserPerm& perm, std::string alternate_name=""); int mkdirs(const char *path, mode_t mode, const UserPerm& perms); int rmdir(const char *path, const UserPerm& perms); // symlinks int readlink(const char *path, char *buf, loff_t size, const UserPerm& perms); - int symlink(const char *existing, const char *newname, const UserPerm& perms); + int symlink(const char *existing, const char *newname, const UserPerm& perms, std::string alternate_name=""); + + // path traversal for high-level interface + int walk(std::string_view path, struct walk_dentry_result* result, const UserPerm& perms, bool followsym=true); // inode stuff unsigned statx_to_mask(unsigned int flags, unsigned int want); @@ -413,10 +422,12 @@ class Client : public Dispatcher, public md_config_obs_t { // file ops int mknod(const char *path, mode_t mode, const UserPerm& perms, dev_t rdev=0); - int open(const char *path, int flags, const UserPerm& perms, mode_t mode=0); + int open(const char *path, int flags, const UserPerm& perms, mode_t mode=0, std::string alternate_name="") { + return open(path, flags, perms, mode, 0, 0, 0, NULL, alternate_name); + } int open(const char *path, int flags, const UserPerm& perms, mode_t mode, int stripe_unit, int stripe_count, int object_size, - const char *data_pool); + const char *data_pool, std::string alternate_name=""); int lookup_hash(inodeno_t ino, inodeno_t dirino, const char *name, const UserPerm& perms); int lookup_ino(inodeno_t ino, const UserPerm& perms, Inode **inode=NULL); @@ -867,6 +878,10 @@ class Client : public Dispatcher, public md_config_obs_t { void handle_client_reply(const MConstRef& reply); bool is_dir_operation(MetaRequest *request); + int path_walk(const filepath& fp, struct walk_dentry_result* result, const UserPerm& perms, bool followsym=true, int mask=0); + int path_walk(const filepath& fp, InodeRef *end, const UserPerm& perms, + bool followsym=true, int mask=0); + // fake inode number for 32-bits ino_t void _assign_faked_ino(Inode *in); void _assign_faked_root(Inode *in); @@ -936,10 +951,6 @@ class Client : public Dispatcher, public md_config_obs_t { Dentry* link(Dir *dir, const string& name, Inode *in, Dentry *dn); void unlink(Dentry *dn, bool keepdir, bool keepdentry); - // path traversal for high-level interface - int path_walk(const filepath& fp, InodeRef *end, const UserPerm& perms, - bool followsym=true, int mask=0); - 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); @@ -1217,17 +1228,18 @@ class Client : public Dispatcher, public md_config_obs_t { const UserPerm& perms); int _lookup(Inode *dir, const string& dname, int mask, InodeRef *target, - const UserPerm& perm); + const UserPerm& perm, std::string* alternate_name=nullptr); - int _link(Inode *in, Inode *dir, const char *name, const UserPerm& perm, + int _link(Inode *in, Inode *dir, const char *name, const UserPerm& perm, std::string alternate_name, InodeRef *inp = 0); int _unlink(Inode *dir, const char *name, const UserPerm& perm); - int _rename(Inode *olddir, const char *oname, Inode *ndir, const char *nname, const UserPerm& perm); + int _rename(Inode *olddir, const char *oname, Inode *ndir, const char *nname, const UserPerm& perm, std::string alternate_name); int _mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& perm, - InodeRef *inp = 0, const std::map &metadata={}); + InodeRef *inp = 0, const std::map &metadata={}, + std::string alternate_name=""); int _rmdir(Inode *dir, const char *name, const UserPerm& perms); int _symlink(Inode *dir, const char *name, const char *target, - const UserPerm& perms, InodeRef *inp = 0); + const UserPerm& perms, std::string alternate_name, InodeRef *inp = 0); int _mknod(Inode *dir, const char *name, mode_t mode, dev_t rdev, const UserPerm& perms, InodeRef *inp = 0); int _do_setattr(Inode *in, struct ceph_statx *stx, int mask, @@ -1266,7 +1278,8 @@ class Client : public Dispatcher, public md_config_obs_t { int _renew_caps(Inode *in); 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, const UserPerm &perms); + const char *data_pool, bool *created, const UserPerm &perms, + std::string alternate_name); loff_t _lseek(Fh *fh, loff_t offset, int whence); int64_t _read(Fh *fh, int64_t offset, uint64_t size, bufferlist *bl); diff --git a/src/client/MetaRequest.h b/src/client/MetaRequest.h index 4d0f37273a471..db134a705832c 100644 --- a/src/client/MetaRequest.h +++ b/src/client/MetaRequest.h @@ -29,6 +29,7 @@ struct MetaRequest { utime_t op_stamp; ceph_mds_request_head head; filepath path, path2; + std::string alternate_name; bufferlist data; int inode_drop; //the inode caps this operation will drop int inode_unless; //unless we have these caps already @@ -169,6 +170,7 @@ struct MetaRequest { void set_retry_attempt(int a) { head.num_retry = a; } void set_filepath(const filepath& fp) { path = fp; } void set_filepath2(const filepath& fp) { path2 = fp; } + void set_alternate_name(std::string an) { alternate_name = an; } void set_string2(const char *s) { path2.set_path(std::string_view(s), 0); } void set_caller_perms(const UserPerm& _perms) { perms.shallow_copy(_perms); diff --git a/src/messages/MClientRequest.h b/src/messages/MClientRequest.h index a02572367c069..c51f1149e0cd9 100644 --- a/src/messages/MClientRequest.h +++ b/src/messages/MClientRequest.h @@ -180,7 +180,7 @@ class MClientRequest final : public MMDSOp { head.flags = head.flags | CEPH_MDS_FLAG_ASYNC; } - void set_alternate_name(std::string&& _alternate_name) { + void set_alternate_name(std::string _alternate_name) { alternate_name = std::move(_alternate_name); } void set_alternate_name(bufferptr&& cipher) {