Otherwise inodes' xattr maps may reference a large shared buffer
(from omap fetch or journal read). If mds trims and loads inode
repeatly, each inode can reference different large buffer in the
worst case.
Fixes: https://tracker.ceph.com/issues/45090
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
(cherry picked from commit
deff94c8f43bb3734b688ccb828d942b8f150638)
symlink = std::string_view(tmp);
}
decode(dirfragtree, bl);
- decode(xattrs, bl);
+ decode_noshare(xattrs, bl);
decode(snap_blob, bl);
decode(old_inodes, bl);
utime_t tm;
decode(tm, p);
if (inode.ctime < tm) inode.ctime = tm;
- decode(xattrs, p);
+ decode_noshare(xattrs, p);
DECODE_FINISH(p);
}
symlink = std::string_view(tmp);
}
decode(dirfragtree, p);
- decode(xattrs, p);
+ decode_noshare(xattrs, p);
decode(old_inodes, p);
decode(damage_flags, p);
decode_snap(p);
damage_flags_t damage_flags = 0;
};
+inline void decode_noshare(InodeStoreBase::mempool_xattr_map& xattrs,
+ ceph::buffer::list::const_iterator &p)
+{
+ decode_noshare<mempool::mds_co::pool_allocator>(xattrs, p);
+}
+
class InodeStore : public InodeStoreBase {
public:
void encode(bufferlist &bl, uint64_t features) const {
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(*pi.xattrs, p);
+ decode_noshare(*pi.xattrs, p);
wrlock_force(&in->xattrlock, mut);
}
// xattrs on new inode?
CInode::mempool_xattr_map xattrs;
- decode(xattrs, p);
+ decode_noshare(xattrs, p);
for (const auto &p : xattrs) {
dout(10) << "prepare_new_inode setting xattr " << p.first << dendl;
auto em = in->xattrs.emplace(std::piecewise_construct, std::forward_as_tuple(p.first), std::forward_as_tuple(p.second));
decode(dnlast, bl);
decode(dnv, bl);
decode(inode, bl);
- decode(xattrs, bl);
+ decode_noshare(xattrs, bl);
if (inode.is_symlink())
decode(symlink, bl);
if (inode.is_dir()) {
template<template<typename> class Allocator>
using xattr_map = compact_map<alloc_string<Allocator>, bufferptr, std::less<alloc_string<Allocator>>, Allocator<std::pair<const alloc_string<Allocator>, bufferptr>>>; // FIXME bufferptr not in mempool
+template<template<typename> class Allocator>
+inline void decode_noshare(xattr_map<Allocator>& xattrs, ceph::buffer::list::const_iterator &p)
+{
+ __u32 n;
+ decode(n, p);
+ while (n-- > 0) {
+ alloc_string<Allocator> key;
+ decode(key, p);
+ __u32 len;
+ decode(len, p);
+ p.copy_deep(len, xattrs[key]);
+ }
+}
+
template<template<typename> class Allocator = std::allocator>
struct old_inode_t {
snapid_t first;
DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl);
decode(first, bl);
decode(inode, bl);
- decode(xattrs, bl);
+ decode_noshare<Allocator>(xattrs, bl);
DECODE_FINISH(bl);
}