}
update_dentry_lease(dn, dlease, from, session);
- dn->alternate_name = std::move(dlease->alternate_name);
return dn;
}
{
utime_t dttl = from;
dttl += (float)dlease->duration_ms / 1000.0;
+
+ ldout(cct, 15) << __func__ << " " << *dn << " " << *dlease << " from " << from << dendl;
ceph_assert(dn);
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);
}
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;
}
}
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;
}
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;
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)) {
}
}
+ 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)
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
/* 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
}
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())
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;
}
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())
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())
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)
// 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())
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)
/****** 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())
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;
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)
{
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;
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;
}
int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& perm,
- InodeRef *inp, const std::map<std::string, std::string> &metadata)
+ InodeRef *inp, const std::map<std::string, std::string> &metadata,
+ std::string alternate_name)
{
ldout(cct, 8) << "_mkdir(" << dir->ino << " " << name << ", 0" << oct
<< mode << dec << ", uid " << perm.uid()
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;
}
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() << ")"
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;
}
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());
}
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());
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
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);
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;
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);
return r;
}
- return _link(in, newparent, newname, perm, &target);
+ return _link(in, newparent, newname, perm, "", &target);
}
int Client::ll_num_osds(void)
goto out;
}
r = _create(parent, name, flags, mode, in, fhp, 0, 0, 0, NULL, &created,
- perms);
+ perms, "");
if (r < 0)
goto out;
}
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 {
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);
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);
// 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);
void handle_client_reply(const MConstRef<MClientReply>& 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);
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);
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<std::string, std::string> &metadata={});
+ InodeRef *inp = 0, const std::map<std::string, std::string> &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,
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);