(fs_name)[_val = phoenix::construct<MDSCapMatch>(std::string(),
_1)]);
- // capspec = * | r[w][p][s]
+ // capspec = * | r[w][f][p][s]
capspec = spaces >> (
lit("*")[_val = MDSCapSpec(MDSCapSpec::ALL)]
|
lit("all")[_val = MDSCapSpec(MDSCapSpec::ALL)]
|
+ (lit("rwfps"))[_val = MDSCapSpec(MDSCapSpec::RWFPS)]
+ |
(lit("rwps"))[_val = MDSCapSpec(MDSCapSpec::RWPS)]
|
+ (lit("rwfp"))[_val = MDSCapSpec(MDSCapSpec::RWFP)]
+ |
+ (lit("rwfs"))[_val = MDSCapSpec(MDSCapSpec::RWFS)]
+ |
(lit("rwp"))[_val = MDSCapSpec(MDSCapSpec::RWP)]
|
(lit("rws"))[_val = MDSCapSpec(MDSCapSpec::RWS)]
|
+ (lit("rwf"))[_val = MDSCapSpec(MDSCapSpec::RWF)]
+ |
(lit("rw"))[_val = MDSCapSpec(MDSCapSpec::RW)]
|
(lit("r"))[_val = MDSCapSpec(MDSCapSpec::READ)]
}
}
+ if (mask & MAY_FULL) {
+ if (!grant.spec.allow_full()) {
+ continue;
+ }
+ }
+
// check unix permissions?
if (grant.match.uid == MDSCapMatch::MDS_AUTH_UID_ANY) {
return true;
if (spec.allow_write()) {
out << "w";
}
+ if (spec.allow_full()) {
+ out << "f";
+ }
if (spec.allow_set_vxattr()) {
out << "p";
}
MAY_CHGRP = (1 << 5),
MAY_SET_VXATTR = (1 << 6),
MAY_SNAPSHOT = (1 << 7),
+ MAY_FULL = (1 << 8),
};
// what we can do
static const unsigned SET_VXATTR = (1 << 3);
// if the capability permits mksnap/rmsnap
static const unsigned SNAPSHOT = (1 << 4);
+ // if the capability permits to bypass osd full check
+ static const unsigned FULL = (1 << 5);
static const unsigned RW = (READ|WRITE);
+ static const unsigned RWF = (READ|WRITE|FULL);
static const unsigned RWP = (READ|WRITE|SET_VXATTR);
static const unsigned RWS = (READ|WRITE|SNAPSHOT);
+ static const unsigned RWFP = (READ|WRITE|FULL|SET_VXATTR);
+ static const unsigned RWFS = (READ|WRITE|FULL|SNAPSHOT);
static const unsigned RWPS = (READ|WRITE|SET_VXATTR|SNAPSHOT);
+ static const unsigned RWFPS = (READ|WRITE|FULL|SET_VXATTR|SNAPSHOT);
MDSCapSpec() = default;
MDSCapSpec(unsigned _caps) : caps(_caps) {
if (caps & ALL)
- caps |= RWPS;
+ caps |= RWFPS;
}
bool allow_all() const {
bool allow_set_vxattr() const {
return (caps & SET_VXATTR);
}
+ bool allow_full() const {
+ return (caps & FULL);
+ }
private:
unsigned caps = 0;
};
}
if (is_full) {
+ CInode *cur = try_get_auth_inode(mdr, req->get_filepath().get_ino());
+ if (!cur) {
+ respond_to_request(mdr, -EINVAL);
+ return;
+ }
if (req->get_op() == CEPH_MDS_OP_SETLAYOUT ||
req->get_op() == CEPH_MDS_OP_SETDIRLAYOUT ||
req->get_op() == CEPH_MDS_OP_SETLAYOUT ||
(!mdr->has_more() || mdr->more()->witnessed.empty())) // haven't started peer request
) {
- dout(20) << __func__ << ": full, responding CEPHFS_ENOSPC to op " << ceph_mds_op_name(req->get_op()) << dendl;
- respond_to_request(mdr, -CEPHFS_ENOSPC);
- return;
+ if (check_access(mdr, cur, MAY_FULL)) {
+ dout(20) << __func__ << ": full, has FULL caps, permitting op " << ceph_mds_op_name(req->get_op()) << dendl;
+ } else {
+ dout(20) << __func__ << ": full, responding CEPHFS_ENOSPC to op " << ceph_mds_op_name(req->get_op()) << dendl;
+ respond_to_request(mdr, -CEPHFS_ENOSPC);
+ return;
+ }
} else {
dout(20) << __func__ << ": full, permitting op " << ceph_mds_op_name(req->get_op()) << dendl;
}