}
}
+__u32 Locker::get_xattr_total_length(CInode::mempool_xattr_map &xattr)
+{
+ __u32 total = 0;
+
+ for (const auto &p : xattr)
+ total += (p.first.length() + p.second.length());
+ return total;
+}
+
+void Locker::decode_new_xattrs(CInode::mempool_inode *inode,
+ CInode::mempool_xattr_map *px,
+ const cref_t<MClientCaps> &m)
+{
+ CInode::mempool_xattr_map tmp;
+
+ auto p = m->xattrbl.cbegin();
+ decode_noshare(tmp, p);
+ __u32 total = get_xattr_total_length(tmp);
+ inode->xattr_version = m->head.xattr_version;
+ if (total > mds->mdsmap->get_max_xattr_size()) {
+ dout(1) << "Maximum xattr size exceeded: " << total
+ << " max size: " << mds->mdsmap->get_max_xattr_size() << dendl;
+ // Ignore new xattr (!!!) but increase xattr version
+ // XXX how to force the client to drop cached xattrs?
+ inode->xattr_version++;
+ } else {
+ *px = std::move(tmp);
+ }
+}
+
/**
* m and ack might be NULL, so don't dereference them unless dirty != 0
*/
// xattr
if (xattrs) {
dout(7) << " xattrs v" << i->xattr_version << " -> " << m->head.xattr_version
- << " len " << m->xattrbl.length() << dendl;
- i->xattr_version = m->head.xattr_version;
- auto p = m->xattrbl.cbegin();
- decode(*px, p);
+ << " len " << m->xattrbl.length() << dendl;
+ decode_new_xattrs(i, px, m);
}
{
// xattrs update?
if (xattr) {
dout(7) << " xattrs v" << pi.inode->xattr_version << " -> " << m->head.xattr_version << dendl;
- pi.inode->xattr_version = m->head.xattr_version;
- auto p = m->xattrbl.cbegin();
- decode_noshare(*pi.xattrs, p);
+ decode_new_xattrs(pi.inode.get(), pi.xattrs.get(), m);
wrlock_force(&in->xattrlock, mut);
}
bool any_late_revoking_caps(xlist<Capability*> const &revoking, double timeout) const;
uint64_t calc_new_max_size(const CInode::inode_const_ptr& pi, uint64_t size);
+ __u32 get_xattr_total_length(CInode::mempool_xattr_map &xattr);
+ void decode_new_xattrs(CInode::mempool_inode *inode,
+ CInode::mempool_xattr_map *px,
+ const cref_t<MClientCaps> &m);
MDSRank *mds;
MDCache *mdcache;
unsigned max_bytes = req->head.args.readdir.max_bytes;
if (!max_bytes)
// make sure at least one item can be encoded
- max_bytes = (512 << 10) + g_conf()->mds_max_xattr_pairs_size;
+ max_bytes = (512 << 10) + mds->mdsmap->get_max_xattr_size();
// start final blob
bufferlist dirbl;
cur_xattrs_size += p.first.length() + p.second.length();
}
- if (((cur_xattrs_size + inc) > g_conf()->mds_max_xattr_pairs_size)) {
+ if (((cur_xattrs_size + inc) > mds->mdsmap->get_max_xattr_size())) {
dout(10) << "xattr kv pairs size too big. cur_xattrs_size "
<< cur_xattrs_size << ", inc " << inc << dendl;
respond_to_request(mdr, -CEPHFS_ENOSPC);
int max_bytes = req->head.args.readdir.max_bytes;
if (!max_bytes)
// make sure at least one item can be encoded
- max_bytes = (512 << 10) + g_conf()->mds_max_xattr_pairs_size;
+ max_bytes = (512 << 10) + mds->mdsmap->get_max_xattr_size();
__u64 last_snapid = 0;
string offset_str = req->get_path2();
unsigned max_bytes = req->head.args.snapdiff.max_bytes;
if (!max_bytes)
// make sure at least one item can be encoded
- max_bytes = (512 << 10) + g_conf()->mds_max_xattr_pairs_size;
+ max_bytes = (512 << 10) + mds->mdsmap->get_max_xattr_size();
// start final blob
bufferlist dirbl;