}
int Client::ll_link(Inode *in, Inode *newparent, const char *newname,
- struct stat *attr, const UserPerm& perm)
+ const UserPerm& perm)
{
Mutex::Locker lock(client_lock);
InodeRef target;
if (!cct->_conf->fuse_default_permissions) {
- if (S_ISDIR(in->mode)) {
- r = -EPERM;
- goto out;
- }
+ if (S_ISDIR(in->mode))
+ return -EPERM;
+
r = may_hardlink(in, perm);
if (r < 0)
- goto out;
+ return r;
+
r = may_create(newparent, perm);
if (r < 0)
- goto out;
+ return r;
}
- r = _link(in, newparent, newname, perm, &target);
- if (r == 0) {
- assert(target);
- fill_stat(target, attr);
- }
-out:
- return r;
+ return _link(in, newparent, newname, perm, &target);
}
int Client::ll_num_osds(void)
int ll_rename(Inode *parent, const char *name, Inode *newparent,
const char *newname, const UserPerm& perm);
int ll_link(Inode *in, Inode *newparent, const char *newname,
- struct stat *attr, const UserPerm& perm);
+ const UserPerm& perm);
int ll_open(Inode *in, int flags, Fh **fh, const UserPerm& perms);
int _ll_create(Inode *parent, const char *name, mode_t mode,
int flags, InodeRef *in, int caps, Fh **fhp,
int64_t i = t.get_int();
int64_t ni = t.get_int();
const char *nn = t.get_string(buf, p);
- struct stat attr;
if (ll_inos.count(i) &&
ll_inos.count(ni)) {
i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
i2 = client->ll_get_inode(vinodeno_t(ll_inos[ni],CEPH_NOSNAP));
- client->ll_link(i1, i2, nn, &attr, perms);
+ client->ll_link(i1, i2, nn, perms);
client->ll_put(i1);
client->ll_put(i2);
}
UserPerm perm(ctx->uid, ctx->gid);
GET_GROUPS(perm, req);
- int r = cfuse->client->ll_link(in, nin, newname, &fe.attr, perm);
+ /*
+ * Note that we could successfully link, but then fail the subsequent
+ * getattr and return an error. Perhaps we should ignore getattr errors,
+ * but then how do we tell FUSE that the attrs are bogus?
+ */
+ int r = cfuse->client->ll_link(in, nin, newname, perm);
if (r == 0) {
- fe.ino = cfuse->make_fake_ino(fe.attr.st_ino, fe.attr.st_dev);
- fe.attr.st_rdev = new_encode_dev(fe.attr.st_rdev);
- fuse_reply_entry(req, &fe);
- } else {
- fuse_reply_err(req, -r);
+ r = cfuse->client->ll_getattr(in, &fe.attr, perm);
+ if (r == 0) {
+ fe.ino = cfuse->make_fake_ino(fe.attr.st_ino, fe.attr.st_dev);
+ fe.attr.st_rdev = new_encode_dev(fe.attr.st_rdev);
+ fuse_reply_entry(req, &fe);
+ }
+ }
+ if (r != 0) {
/*
* Many ll operations in libcephfs return an extra inode reference, but
* ll_link currently does not. Still, FUSE needs one for the new dentry,
* On error however, we must put that reference.
*/
cfuse->iput(in);
+ fuse_reply_err(req, -r);
}
cfuse->iput(nin);
struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms);
int ceph_ll_link(struct ceph_mount_info *cmount, struct Inode *in,
- struct Inode *newparrent, const char *name,
- struct stat *attr, int uid, int gid);
+ struct Inode *newparent, const char *name,
+ const UserPerm *perms);
int ceph_ll_opendir(struct ceph_mount_info *cmount, struct Inode *in,
struct ceph_dir_result **dirpp, int uid, int gid);
int ceph_ll_releasedir(struct ceph_mount_info *cmount,
extern "C" int ceph_ll_link(class ceph_mount_info *cmount,
Inode *in, Inode *newparent,
- const char *name, struct stat *attr, int uid,
- int gid)
+ const char *name, const UserPerm *perms)
{
- UserPerm perms(uid, gid);
- return (cmount->get_client()->ll_link(in, newparent, name, attr, perms));
+ return cmount->get_client()->ll_link(in, newparent, name, *perms);
}
extern "C" int ceph_ll_opendir(class ceph_mount_info *cmount,
sprintf(filename, "nlinkorig%x", getpid());
sprintf(linkname, "nlinklink%x", getpid());
- struct stat st;
struct ceph_statx stx;
Fh *fh;
UserPerm *perms = ceph_mount_perms(cmount);
&file, &fh, &stx, CEPH_STATX_NLINK, 0, perms), 0);
ASSERT_EQ(stx.stx_nlink, (nlink_t)1);
- ASSERT_EQ(ceph_ll_link(cmount, file, dir, linkname, &st, getuid(), getgid()), 0);
- ASSERT_EQ(st.st_nlink, (nlink_t)2);
+ ASSERT_EQ(ceph_ll_link(cmount, file, dir, linkname, perms), 0);
+ ASSERT_EQ(ceph_ll_getattr(cmount, file, &stx, CEPH_STATX_NLINK, 0, perms), 0);
+ ASSERT_EQ(stx.stx_nlink, (nlink_t)2);
ASSERT_EQ(ceph_ll_unlink(cmount, dir, linkname, getuid(), getgid()), 0);
ASSERT_EQ(ceph_ll_lookup(cmount, dir, filename, &file, &stx,