From 35a033f576a7bcbe89bc96c05eefc6d47ede8fc5 Mon Sep 17 00:00:00 2001 From: Shyamsundar Ranganathan Date: Wed, 22 Jul 2020 15:21:50 -0400 Subject: [PATCH] client: expose ceph.quota.max_bytes xattr within snapshots For directories within snapshots, expose the ceph.quota.max_bytes extended attribute information. This enables fetching quota information when the snapshot was taken and is particularly useful when cloning subvolume snapshots, to enforce the quota on the clone subvolume as well. Fixes: https://tracker.ceph.com/issues/46278 Signed-off-by: Shyamsundar Ranganathan --- src/client/Client.cc | 3 +- src/test/libcephfs/test.cc | 79 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 1e884075220f4..4f443c0b8f263 100755 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -11876,7 +11876,8 @@ int Client::ll_removexattr(Inode *in, const char *name, const UserPerm& perms) bool Client::_vxattrcb_quota_exists(Inode *in) { return in->quota.is_enable() && - in->snaprealm && in->snaprealm->ino == in->ino; + (in->snapid != CEPH_NOSNAP || + (in->snaprealm && in->snaprealm->ino == in->ino)); } size_t Client::_vxattrcb_quota(Inode *in, char *val, size_t size) { diff --git a/src/test/libcephfs/test.cc b/src/test/libcephfs/test.cc index f8c4b2bdcac75..a7a6ffc7e1556 100644 --- a/src/test/libcephfs/test.cc +++ b/src/test/libcephfs/test.cc @@ -2274,6 +2274,85 @@ TEST(LibCephFS, SnapXattrs) { ceph_shutdown(cmount); } +TEST(LibCephFS, SnapQuota) { + struct ceph_mount_info *cmount; + ASSERT_EQ(ceph_create(&cmount, NULL), 0); + ASSERT_EQ(ceph_conf_read_file(cmount, NULL), 0); + ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL)); + ASSERT_EQ(ceph_mount(cmount, NULL), 0); + + char test_snap_dir_quota_xattr[256]; + char test_snap_subdir_quota_xattr[256]; + char test_snap_subdir_noquota_xattr[256]; + char xattrk[128]; + char xattrv[128]; + char c_temp[PATH_MAX]; + char gxattrv[128]; + int xbuflen = sizeof(gxattrv); + pid_t mypid = getpid(); + + // create dir and set quota + sprintf(test_snap_dir_quota_xattr, "test_snap_dir_quota_xattr_%d", mypid); + ASSERT_EQ(0, ceph_mkdir(cmount, test_snap_dir_quota_xattr, 0777)); + + sprintf(xattrk, "ceph.quota.max_bytes"); + sprintf(xattrv, "65536"); + ASSERT_EQ(0, ceph_setxattr(cmount, test_snap_dir_quota_xattr, xattrk, (void *)xattrv, 5, XATTR_CREATE)); + + // create subdir and set quota + sprintf(test_snap_subdir_quota_xattr, "test_snap_dir_quota_xattr_%d/subdir_quota", mypid); + ASSERT_EQ(0, ceph_mkdirs(cmount, test_snap_subdir_quota_xattr, 0777)); + + sprintf(xattrk, "ceph.quota.max_bytes"); + sprintf(xattrv, "32768"); + ASSERT_EQ(0, ceph_setxattr(cmount, test_snap_subdir_quota_xattr, xattrk, (void *)xattrv, 5, XATTR_CREATE)); + + // create subdir with no quota + sprintf(test_snap_subdir_noquota_xattr, "test_snap_dir_quota_xattr_%d/subdir_noquota", mypid); + ASSERT_EQ(0, ceph_mkdirs(cmount, test_snap_subdir_noquota_xattr, 0777)); + + // snapshot dir + sprintf(c_temp, "/.snap/test_snap_dir_quota_xattr_snap_%d", mypid); + ASSERT_EQ(0, ceph_mkdirs(cmount, c_temp, 0777)); + + // check dir quota under snap + sprintf(c_temp, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d", mypid, mypid); + int alen = ceph_getxattr(cmount, c_temp, "ceph.quota.max_bytes", (void *)gxattrv, xbuflen); + ASSERT_LT(0, alen); + ASSERT_LT(alen, xbuflen); + gxattrv[alen] = '\0'; + ASSERT_STREQ(gxattrv, "65536"); + + // check subdir quota under snap + sprintf(c_temp, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d/subdir_quota", mypid, mypid); + alen = ceph_getxattr(cmount, c_temp, "ceph.quota.max_bytes", (void *)gxattrv, xbuflen); + ASSERT_LT(0, alen); + ASSERT_LT(alen, xbuflen); + gxattrv[alen] = '\0'; + ASSERT_STREQ(gxattrv, "32768"); + + // ensure subdir noquota xattr under snap + sprintf(c_temp, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d/subdir_noquota", mypid, mypid); + EXPECT_EQ(-ENODATA, ceph_getxattr(cmount, c_temp, "ceph.quota.max_bytes", (void *)gxattrv, xbuflen)); + + // listxattr() shouldn't return ceph.quota.max_bytes vxattr + sprintf(c_temp, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d", mypid, mypid); + char xattrlist[512]; + int len = ceph_listxattr(cmount, c_temp, xattrlist, sizeof(xattrlist)); + ASSERT_GE(sizeof(xattrlist), (size_t)len); + char *p = xattrlist; + int found = 0; + while (len > 0) { + if (strcmp(p, "ceph.quota.max_bytes") == 0) + found++; + len -= strlen(p) + 1; + p += strlen(p) + 1; + } + ASSERT_EQ(found, 0); + + ceph_shutdown(cmount); +} + TEST(LibCephFS, Lseek) { struct ceph_mount_info *cmount; ASSERT_EQ(0, ceph_create(&cmount, NULL)); -- 2.39.5