Skip to content

Commit

Permalink
cephfs: add chattr -i to expired a worm file which is in retained state
Browse files Browse the repository at this point in the history
Signed-off-by: Wei Qiaomiao <wei.qiaomiao@zte.com.cn>
  • Loading branch information
weiqiaomiao committed Sep 2, 2019
1 parent fee71d0 commit f2a5842
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 39 deletions.
47 changes: 30 additions & 17 deletions src/client/Client.cc
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -11463,7 +11463,7 @@ int Client::ll_listxattr(Inode *in, char *names, size_t size,
}

int Client::_do_setxattr(Inode *in, const char *name, const void *value,
size_t size, int flags, const UserPerm& perms)
size_t size, int flags, int worm_flags, const UserPerm& perms)
{

int xattr_flags = 0;
Expand All @@ -11481,6 +11481,7 @@ int Client::_do_setxattr(Inode *in, const char *name, const void *value,
req->set_string2(name);
req->set_inode(in);
req->head.args.setxattr.flags = xattr_flags;
req->head.args.setxattr.set_worm_attr = worm_flags;

bufferlist bl;
assert (value || size == 0);
Expand Down Expand Up @@ -11564,7 +11565,7 @@ int Client::_setxattr(Inode *in, const char *name, const void *value,
}
}

int ret = _do_setxattr(in, name, value, size, flags, perms);
int ret = _do_setxattr(in, name, value, size, flags, 0, perms);
if (ret >= 0 && check_realm) {
// check if snaprealm was created for quota inode
if (in->quota.is_enable() &&
Expand Down Expand Up @@ -11769,7 +11770,7 @@ int Client::set_worm_exptime(Inode *in, const char *name, const void *value,
char buf[64];
snprintf(buf, sizeof(buf), "%u_%u", exp_time.tv.tv_sec, exp_time.tv.tv_nsec);

res = _do_setxattr(in, "ceph.worm.exp_time", &buf, std::strlen(buf), flags, perms);
res = _do_setxattr(in, "ceph.worm.exp_time", &buf, std::strlen(buf), flags, 0, perms);

return res;
}
Expand Down Expand Up @@ -11800,7 +11801,7 @@ int Client::worm_state_transition(Inode *in, const UserPerm& perms, int op)
uint32_t worm_state = in->worm.worm_state | WORM_RETAIN;
utime_t exp_time;
if (in->worm.is_reten_period_ulimit()) {
exp_time.tv.tv_sec = 4294967295;
exp_time.tv.tv_sec = UINT32_MAX;
exp_time.tv.tv_nsec = 0;
} else {
exp_time.tv.tv_sec = in->mtime.sec() + in->worm.retention_period + in->worm.auto_commit_period;
Expand All @@ -11809,7 +11810,7 @@ int Client::worm_state_transition(Inode *in, const UserPerm& perms, int op)

char buf[64];
snprintf(buf, sizeof(buf), "state=%u exp_time=%u_%u", worm_state, exp_time.tv.tv_sec, exp_time.tv.tv_nsec);
res = _do_setxattr(in, "ceph.worm", &buf, std::strlen(buf), 0, perms);
res = _do_setxattr(in, "ceph.worm", &buf, std::strlen(buf), 0, 0, perms);
if (res) {
ldout(cct, 3) << "set worm info return:" << res << dendl;
return res;
Expand All @@ -11829,7 +11830,7 @@ int Client::worm_state_transition(Inode *in, const UserPerm& perms, int op)
uint32_t worm_state = (in->worm.worm_state | WORM_EXPIRE) & (~WORM_RETAIN);
char buf[12];
snprintf(buf, sizeof(buf), "%u", worm_state);
res = _do_setxattr(in, "ceph.worm.state", &buf, std::strlen(buf), 0, perms);
res = _do_setxattr(in, "ceph.worm.state", &buf, std::strlen(buf), 0, 0,perms);
if (res){
ldout(cct, 3) << "set worm state (" << worm_state << ") return:"<< res << dendl;
return res;
Expand Down Expand Up @@ -12056,7 +12057,6 @@ size_t Client::_vxattrcb_snap_btime(Inode *in, char *val, size_t size)
name: CEPH_XATTR_NAME(_type, _name), \
getxattr_cb: &Client::_vxattrcb_ ## _type ## _ ## _name, \
readonly: false, \
hidden: true, \
exists_cb: &Client::_vxattrcb_worm_exists, \
flags: 0, \
}
Expand Down Expand Up @@ -12109,7 +12109,6 @@ const Client::VXattr Client::_dir_vxattrs[] = {
name: "ceph.worm",
getxattr_cb: &Client::_vxattrcb_worm,
readonly: false,
hidden: true,
exists_cb: &Client::_vxattrcb_worm_exists,
flags: 0,
},
Expand Down Expand Up @@ -12146,7 +12145,6 @@ const Client::VXattr Client::_file_vxattrs[] = {
name: "ceph.worm",
getxattr_cb: &Client::_vxattrcb_worm,
readonly: false,
hidden: true,
exists_cb: &Client::_vxattrcb_worm_exists,
flags: 0,
},
Expand Down Expand Up @@ -13148,43 +13146,58 @@ int Client::ll_file_layout(Fh *fh, file_layout_t *layout)
return ll_file_layout(fh->inode.get(), layout);
}

int Client::ll_set_flags(Inode *in, const UserPerm& perms)
int Client::ll_set_flags(Inode *in, int worm_flag, const UserPerm& perms)
{
std::lock_guard lock(client_lock);
int res = 0;

if(!in->worm.is_enable()) {
if (!in->worm.is_enable()) {
return -EOPNOTSUPP;
}

if (in->worm.is_retain()) {
return res;
}


if (in->worm.is_enable() && !in->worm.is_retain()) {
// set immutuble flag
if (worm_flag != 0 && !in->worm.is_retain()) {
uint32_t worm_state = (in->worm.worm_state | WORM_RETAIN) & (~WORM_EXPIRE);
utime_t exp_time;
if (in->worm.is_reten_period_ulimit()) {
exp_time.tv.tv_sec = 4294967295;
exp_time.tv.tv_sec = UINT32_MAX;
exp_time.tv.tv_nsec = 0;
} else {
exp_time.tv.tv_sec = in->mtime.sec() + in->worm.retention_period;
exp_time.tv.tv_nsec = in->mtime.nsec();
}
char buf[64];
snprintf(buf, sizeof(buf), "state=%u exp_time=%u_%u", worm_state, exp_time.tv.tv_sec, exp_time.tv.tv_nsec);
res = _do_setxattr(in, "ceph.worm", &buf, std::strlen(buf), 0, perms);
res = _do_setxattr(in, "ceph.worm", &buf, std::strlen(buf), 0, 0, perms);
if (res) {
ldout(cct, 3) << "set worm info return:" << res << dendl;
}
return res;
}

// clear immutuble flag
if (worm_flag == 0 && in->worm.is_retain()) {
uint32_t worm_state = (in->worm.worm_state | WORM_EXPIRE) & (~WORM_RETAIN);
char buf[12];
snprintf(buf, sizeof(buf), "%u", worm_state);
res = _do_setxattr(in, "ceph.worm.state", &buf, std::strlen(buf), 0, CEPH_XATTR_WANT_SET_WORM_CAPS, perms);
if (res){
ldout(cct, 3) << "set worm state (" << worm_state << ") return:"<< res << dendl;
}
return res;
}

return res;
}

int Client::ll_set_flags(Fh *fh, const UserPerm& perms)
int Client::ll_set_flags(Fh *fh, int worm_flag, const UserPerm& perms)
{
return ll_set_flags(fh->inode.get(), perms);
return ll_set_flags(fh->inode.get(), worm_flag, perms);
}

int Client::ll_get_flags(Inode *in, const UserPerm& perms)
Expand Down Expand Up @@ -14555,7 +14568,7 @@ int Client::_posix_acl_chmod(Inode *in, mode_t mode, const UserPerm& perms)
r = posix_acl_access_chmod(acl, mode);
if (r < 0)
goto out;
r = _do_setxattr(in, ACL_EA_ACCESS, acl.c_str(), acl.length(), 0, perms);
r = _do_setxattr(in, ACL_EA_ACCESS, acl.c_str(), acl.length(), 0, 0, perms);
} else {
r = 0;
}
Expand Down
6 changes: 3 additions & 3 deletions src/client/Client.h
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -739,8 +739,8 @@ class Client : public Dispatcher, public md_config_obs_t {
bool use_faked_inos() { return _use_faked_inos; }
vinodeno_t map_faked_ino(ino_t ino);

int ll_set_flags(Fh *fh, const UserPerm& perms);
int ll_set_flags(Inode *in, const UserPerm& perms);
int ll_set_flags(Fh *fh, int worm_flag, const UserPerm& perms);
int ll_set_flags(Inode *in, int worm_flag, const UserPerm& perms);

int ll_get_flags(Fh *fh, const UserPerm& perms);
int ll_get_flags(Inode *in, const UserPerm& perms);
Expand Down Expand Up @@ -1099,7 +1099,7 @@ class Client : public Dispatcher, public md_config_obs_t {
const UserPerm& perms);
int _listxattr(Inode *in, char *names, size_t len, const UserPerm& perms);
int _do_setxattr(Inode *in, const char *name, const void *value, size_t len,
int flags, const UserPerm& perms);
int flags, int worm_flags, const UserPerm& perms);
int _setxattr(Inode *in, const char *name, const void *value, size_t len,
int flags, const UserPerm& perms);
int _setxattr(InodeRef &in, const char *name, const void *value, size_t len,
Expand Down
1 change: 0 additions & 1 deletion src/client/Inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ struct Inode {
_ref(0), ll_ref(0), dir_pin(MDS_RANK_NONE)
{
memset(&dir_layout, 0, sizeof(dir_layout));
memset(&worm, 0, sizeof(worm));
}
~Inode();

Expand Down
22 changes: 11 additions & 11 deletions src/client/fuse_ll.cc
Original file line number Diff line number Diff line change
Expand Up @@ -673,18 +673,18 @@ static void fuse_ll_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, st
fuse_reply_err(req, EOPNOTSUPP);
return;
}

if (*flags & FS_IMMUTABLE_FL) {
Fh *fh = (Fh*)fi->fh;
const struct fuse_ctx *ctx = fuse_req_ctx(req);
UserPerm perms(ctx->uid, ctx->gid);
get_fuse_groups(perms, req);
int ret = cfuse->client->ll_set_flags(fh, perms);
if (ret) {
fuse_reply_err(req, -ret);
return;
}

int worm_flag = *flags & FS_IMMUTABLE_FL;
Fh *fh = (Fh*)fi->fh;
const struct fuse_ctx *ctx = fuse_req_ctx(req);
UserPerm perms(ctx->uid, ctx->gid);
get_fuse_groups(perms, req);
int ret = cfuse->client->ll_set_flags(fh, worm_flag, perms);
if (ret) {
fuse_reply_err(req, -ret);
return;
}

fuse_reply_ioctl(req, 0, NULL, 0);
}
break;
Expand Down
4 changes: 4 additions & 0 deletions src/include/ceph_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ int ceph_flags_sys2wire(int flags);
#define CEPH_XATTR_REPLACE (1 << 1)
#define CEPH_XATTR_REMOVE (1 << 31)

#define CEPH_XATTR_WANT_SET_WORM_CAPS 1

/*
* readdir request flags;
*/
Expand Down Expand Up @@ -487,6 +489,7 @@ union ceph_mds_request_args_legacy {
struct {
__le32 flags;
__le32 osdmap_epoch; /* use for set file/dir layout */
__le32 set_worm_attr; /* use for set worm attr */
} __attribute__ ((packed)) setxattr;
struct {
struct ceph_file_layout layout;
Expand Down Expand Up @@ -563,6 +566,7 @@ union ceph_mds_request_args {
struct {
__le32 flags;
__le32 osdmap_epoch; /* use for set file/dir layout */
__le32 set_worm_attr; /* use for set worm attr */
} __attribute__ ((packed)) setxattr;
struct {
struct ceph_file_layout layout;
Expand Down
13 changes: 13 additions & 0 deletions src/mds/MDSAuthCaps.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ struct MDSCapParser : qi::grammar<Iterator, MDSAuthCaps()>
(lit("rw"))[_val = MDSCapSpec(MDSCapSpec::RW)]
|
(lit("r"))[_val = MDSCapSpec(MDSCapSpec::READ)]
|
(lit("rwpi"))[_val = MDSCapSpec(MDSCapSpec::RWPI)]
|
(lit("rwpsi"))[_val = MDSCapSpec(MDSCapSpec::RWPSI)]
);

grant = lit("allow") >> (capspec >> match >>
Expand Down Expand Up @@ -246,6 +250,12 @@ bool MDSAuthCaps::is_capable(std::string_view inode_path,
}
}

if (mask & MAY_SET_WORM) {
if (!grant.spec.allow_set_worm()) {
continue;
}
}

if (mask & MAY_SNAPSHOT) {
if (!grant.spec.allow_snapshot()) {
continue;
Expand Down Expand Up @@ -396,6 +406,9 @@ ostream &operator<<(ostream &out, const MDSCapSpec &spec)
if (spec.allow_snapshot()) {
out << "s";
}
if (spec.allow_set_worm()) {
out << "i";
}
}

return out;
Expand Down
10 changes: 9 additions & 1 deletion src/mds/MDSAuthCaps.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum {
MAY_CHGRP = (1 << 5),
MAY_SET_VXATTR = (1 << 6),
MAY_SNAPSHOT = (1 << 7),
MAY_SET_WORM = (1 << 8),
};

class CephContext;
Expand All @@ -46,16 +47,20 @@ struct MDSCapSpec {
static const unsigned SET_VXATTR = (1 << 3);
// if the capability permits mksnap/rmsnap
static const unsigned SNAPSHOT = (1 << 4);
// if the capability permits setting worm attr
static const unsigned SET_WORM = (1 << 5);

static const unsigned RW = (READ|WRITE);
static const unsigned RWP = (READ|WRITE|SET_VXATTR);
static const unsigned RWS = (READ|WRITE|SNAPSHOT);
static const unsigned RWPS = (READ|WRITE|SET_VXATTR|SNAPSHOT);
static const unsigned RWPI = (READ|WRITE|SET_VXATTR|SET_WORM);
static const unsigned RWPSI = (READ|WRITE|SET_VXATTR|SNAPSHOT|SET_WORM);

MDSCapSpec() = default;
MDSCapSpec(unsigned _caps) : caps(_caps) {
if (caps & ALL)
caps |= RWPS;
caps |= RWPSI;
}

bool allow_all() const {
Expand Down Expand Up @@ -84,6 +89,9 @@ struct MDSCapSpec {
bool allow_set_vxattr() const {
return (caps & SET_VXATTR);
}
bool allow_set_worm() const {
return (caps & SET_WORM);
}
private:
unsigned caps = 0;
};
Expand Down
13 changes: 9 additions & 4 deletions src/mds/Server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5244,13 +5244,13 @@ int Server::parse_worm_vxattr(MDRequestRef& mdr, CInode *cur, string name, strin
parse_worm_vxattr(mdr, cur, "worm.enable", "1", worm);
}

if (q == 0xffffffff) { // retetion period ulimit
if (q == UINT32_MAX) { // retetion period ulimit
worm->worm_state |= WORM_RETEN_PERIOD_UNLIMIT;
}
worm->retention_period = q;
} else if (name == "worm.min_retention_period") {
uint32_t q = boost::lexical_cast<uint32_t>(value);
if ((worm->is_enable() && !worm->is_root())|| (q > MAX_MIN_RETEN_PERIOD && q != 0xffffffff)){
if (worm->is_enable() && !worm->is_root()){
return -EINVAL;
}

Expand All @@ -5261,7 +5261,7 @@ int Server::parse_worm_vxattr(MDRequestRef& mdr, CInode *cur, string name, strin
worm->min_retention_period = q;
} else if (name == "worm.max_retention_period") {
uint32_t q = boost::lexical_cast<uint32_t>(value);
if ((worm->is_enable() && !worm->is_root())|| (q > MIN_MAX_RETEN_PERIOD && q != 0xffffffff)){
if (worm->is_enable() && !worm->is_root()){
return -EINVAL;
}

Expand Down Expand Up @@ -5500,8 +5500,13 @@ void Server::handle_set_vxattr(MDRequestRef& mdr, CInode *cur,
cur->set_export_pin(rank);
pip = &pi.inode;
} else if (name.compare(0, 9, "ceph.worm") == 0) {
int flags = req->head.args.setxattr.set_worm_attr;
if (flags == CEPH_XATTR_WANT_SET_WORM_CAPS){
if (!check_access(mdr, cur, MAY_SET_WORM)) {
return;
};
}
worm_info_t worm = cur->get_projected_inode()->worm;

rest = name.substr(name.find("worm"));
int r = parse_worm_vxattr(mdr, cur, rest, value, &worm);
if (r >= 0 && !worm.is_valid()) {
Expand Down
2 changes: 0 additions & 2 deletions src/mds/mdstypes.h
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@
#define WORM_RETAIN 4 // the worm file is in retained state
#define WORM_EXPIRE 8 // the worm file is in expired state
#define WORM_RETEN_PERIOD_UNLIMIT 16 //the worm file retention period is unlimit
#define MAX_MIN_RETEN_PERIOD 946080000 // 30 years
#define MIN_MAX_RETEN_PERIOD 2207520000 // 70 years

typedef int32_t mds_rank_t;
constexpr mds_rank_t MDS_RANK_NONE = -1;
Expand Down

0 comments on commit f2a5842

Please sign in to comment.