(linklock.gcaps_xlocker_mask(client) << linklock.get_cap_shift());
}
-int CInode::get_caps_allowed_for_client(Session *session, mempool_inode *file_i) const
+int CInode::get_caps_allowed_for_client(Session *session, Capability *cap,
+ mempool_inode *file_i) const
{
client_t client = session->get_client();
int allowed;
}
if (!is_dir()) {
- if ((file_i->inline_data.version != CEPH_INLINE_NONE &&
- !session->get_connection()->has_feature(
- CEPH_FEATURE_MDS_INLINE_DATA)) ||
- (!file_i->layout.pool_ns.empty() &&
- !session->get_connection()->has_feature(
- CEPH_FEATURE_FS_FILE_LAYOUT_V2)))
- allowed &= ~(CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR);
+ if (file_i->inline_data.version == CEPH_INLINE_NONE &&
+ file_i->layout.pool_ns.empty()) {
+ // noop
+ } else if (cap) {
+ if ((file_i->inline_data.version != CEPH_INLINE_NONE &&
+ cap->is_noinline()) ||
+ (!file_i->layout.pool_ns.empty() &&
+ cap->is_nopoolns()))
+ allowed &= ~(CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR);
+ } else {
+ auto& conn = session->get_connection();
+ if ((file_i->inline_data.version != CEPH_INLINE_NONE &&
+ !conn->has_feature(CEPH_FEATURE_MDS_INLINE_DATA)) ||
+ (!file_i->layout.pool_ns.empty() &&
+ !conn->has_feature(CEPH_FEATURE_FS_FILE_LAYOUT_V2)))
+ allowed &= ~(CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR);
+ }
}
return allowed;
}
*/
ecap.caps = valid ? get_caps_allowed_by_type(CAP_ANY) : CEPH_STAT_CAP_INODE;
if (last == CEPH_NOSNAP || is_any_caps())
- ecap.caps = ecap.caps & get_caps_allowed_for_client(session, file_i);
+ ecap.caps = ecap.caps & get_caps_allowed_for_client(session, nullptr, file_i);
ecap.seq = 0;
ecap.mseq = 0;
ecap.realm = 0;
int issue = 0;
if (!no_caps && cap) {
int likes = get_caps_liked();
- int allowed = get_caps_allowed_for_client(session, file_i);
+ int allowed = get_caps_allowed_for_client(session, cap, file_i);
issue = (cap->wanted() | likes) & allowed;
cap->issue_norevoke(issue);
issue = cap->pending();
encode(file_i->rstat.rctime, bl);
dirfragtree.encode(bl);
encode(symlink, bl);
- if (session->get_connection()->has_feature(CEPH_FEATURE_DIRLAYOUTHASH)) {
+ auto& conn = session->get_connection();
+ if (conn->has_feature(CEPH_FEATURE_DIRLAYOUTHASH)) {
encode(file_i->dir_layout, bl);
}
encode_xattrs();
- if (session->get_connection()->has_feature(CEPH_FEATURE_MDS_INLINE_DATA)) {
+ if (conn->has_feature(CEPH_FEATURE_MDS_INLINE_DATA)) {
encode(inline_version, bl);
encode(inline_data, bl);
}
- if (session->get_connection()->has_feature(CEPH_FEATURE_MDS_QUOTA)) {
+ if (conn->has_feature(CEPH_FEATURE_MDS_QUOTA)) {
mempool_inode *policy_i = ppolicy ? pi : oi;
encode(policy_i->quota, bl);
}
- if (session->get_connection()->has_feature(CEPH_FEATURE_FS_FILE_LAYOUT_V2)) {
+ if (conn->has_feature(CEPH_FEATURE_FS_FILE_LAYOUT_V2)) {
encode(layout.pool_ns, bl);
}
- if (session->get_connection()->has_feature(CEPH_FEATURE_FS_BTIME)) {
+ if (conn->has_feature(CEPH_FEATURE_FS_BTIME)) {
encode(any_i->btime, bl);
encode(any_i->change_attr, bl);
}
int get_caps_allowed_by_type(int type) const;
int get_caps_careful() const;
int get_xlocker_mask(client_t client) const;
- int get_caps_allowed_for_client(Session *s, mempool_inode *file_i) const;
+ int get_caps_allowed_for_client(Session *s, Capability *cap, mempool_inode *file_i) const;
// caps issued, wanted
int get_caps_issued(int *ploner = 0, int *pother = 0, int *pxlocker = 0,
void Capability::Export::encode(bufferlist &bl) const
{
- ENCODE_START(2, 2, bl);
+ ENCODE_START(3, 2, bl);
encode(cap_id, bl);
encode(wanted, bl);
encode(issued, bl);
encode(seq, bl);
encode(mseq, bl);
encode(last_issue_stamp, bl);
+ encode(state, bl);
ENCODE_FINISH(bl);
}
void Capability::Export::decode(bufferlist::const_iterator &p)
{
- DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, p);
+ DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, p);
decode(cap_id, p);
decode(wanted, p);
decode(issued, p);
decode(seq, p);
decode(mseq, p);
decode(last_issue_stamp, p);
+ if (struct_v >= 3)
+ decode(state, p);
DECODE_FINISH(p);
}
if (session) {
session->touch_cap_bottom(this);
cap_gen = session->get_cap_gen();
+
+ auto& conn = session->get_connection();
+ if (conn) {
+ if (!conn->has_feature(CEPH_FEATURE_MDS_INLINE_DATA))
+ state |= STATE_NOINLINE;
+ if (!conn->has_feature(CEPH_FEATURE_FS_FILE_LAYOUT_V2))
+ state |= STATE_NOPOOLNS;
+ if (!conn->has_feature(CEPH_FEATURE_MDS_QUOTA))
+ state |= STATE_NOQUOTA;
+ }
}
}
MEMPOOL_CLASS_HELPERS();
struct Export {
- int64_t cap_id;
- int32_t wanted;
- int32_t issued;
- int32_t pending;
+ int64_t cap_id = 0;
+ int32_t wanted = 0;
+ int32_t issued = 0;
+ int32_t pending = 0;
snapid_t client_follows;
- ceph_seq_t seq;
- ceph_seq_t mseq;
+ ceph_seq_t seq = 0;
+ ceph_seq_t mseq = 0;
utime_t last_issue_stamp;
- Export() : cap_id(0), wanted(0), issued(0), pending(0), seq(0), mseq(0) {}
- Export(int64_t id, int w, int i, int p, snapid_t cf, ceph_seq_t s, ceph_seq_t m, utime_t lis) :
+ uint32_t state = 0;
+ Export() {}
+ Export(int64_t id, int w, int i, int p, snapid_t cf,
+ ceph_seq_t s, ceph_seq_t m, utime_t lis, unsigned st) :
cap_id(id), wanted(w), issued(i), pending(p), client_follows(cf),
- seq(s), mseq(m), last_issue_stamp(lis) {}
+ seq(s), mseq(m), last_issue_stamp(lis), state(st) {}
void encode(bufferlist &bl) const;
void decode(bufferlist::const_iterator &p);
void dump(Formatter *f) const;
const static unsigned STATE_IMPORTING = (1<<2);
const static unsigned STATE_NEEDSNAPFLUSH = (1<<3);
const static unsigned STATE_CLIENTWRITEABLE = (1<<4);
+ const static unsigned STATE_NOINLINE = (1<<5);
+ const static unsigned STATE_NOPOOLNS = (1<<6);
+ const static unsigned STATE_NOQUOTA = (1<<7);
+
+ const static unsigned MASK_STATE_EXPORTED =
+ (STATE_CLIENTWRITEABLE | STATE_NOINLINE | STATE_NOPOOLNS | STATE_NOQUOTA);
Capability(CInode *i=nullptr, Session *s=nullptr, uint64_t id=0);
Capability(const Capability& other) = delete;
}
}
+ bool is_noinline() const { return state & STATE_NOINLINE; }
+ bool is_nopoolns() const { return state & STATE_NOPOOLNS; }
+ bool is_noquota() const { return state & STATE_NOQUOTA; }
+
CInode *get_inode() const { return inode; }
Session *get_session() const { return session; }
client_t get_client() const;
// -- exports --
Export make_export() const {
- return Export(cap_id, wanted(), issued(), pending(), client_follows, get_last_seq(), mseq+1, last_issue_stamp);
+ return Export(cap_id, wanted(), issued(), pending(), client_follows, get_last_seq(), mseq+1, last_issue_stamp, state);
}
void merge(const Export& other, bool auth_cap) {
if (!is_stale()) {
client_follows = other.client_follows;
+ state |= other.state & MASK_STATE_EXPORTED;
+ if ((other.state & STATE_CLIENTWRITEABLE) && !is_notable())
+ mark_notable();
+
// wanted
set_wanted(wanted() | other.wanted);
if (auth_cap)
// add in any xlocker-only caps (for locks this client is the xlocker for)
allowed |= xlocker_allowed & in->get_xlocker_mask(it->first);
- Session *session = mds->get_session(it->first);
- if (in->inode.inline_data.version != CEPH_INLINE_NONE &&
- !(session &&
- session->get_connection() &&
- session->get_connection()->has_feature(CEPH_FEATURE_MDS_INLINE_DATA)))
+ if ((in->inode.inline_data.version != CEPH_INLINE_NONE &&
+ cap->is_noinline()) ||
+ (!in->inode.layout.pool_ns.empty() &&
+ cap->is_nopoolns()))
allowed &= ~(CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR);
int pending = cap->pending();
mds->get_osd_epoch_barrier());
in->encode_cap_message(m, cap);
- mds->send_message_client_counted(m, it->first);
+ mds->send_message_client_counted(m, cap->get_session());
}
}
mds->server->create_quota_realm(in);
for (auto &p : in->client_caps) {
- Session *session = mds->get_session(p.first);
- if (!session ||
- !session->get_connection() ||
- !session->get_connection()->has_feature(CEPH_FEATURE_MDS_QUOTA))
- continue;
-
Capability *cap = &p.second;
+ if (cap->is_noquota())
+ continue;
if (exclude_ct >= 0 && exclude_ct != p.first)
goto update;
msg->ino = in->ino();
msg->rstat = i->rstat;
msg->quota = i->quota;
- mds->send_message_client_counted(msg, session->get_connection());
+ mds->send_message_client_counted(msg, cap->get_session());
}
for (const auto &it : in->get_replicas()) {
auto msg = MGatherCaps::create();