From: Shyamsundar Ranganathan Date: Wed, 22 Jul 2020 19:21:50 +0000 (-0400) Subject: client: expose ceph.quota.max_bytes xattr within snapshots X-Git-Tag: v14.2.12~112^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0aa0f43feba7706f458076154ad6c64497f69d49;p=ceph.git 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 (cherry picked from commit 35a033f576a7bcbe89bc96c05eefc6d47ede8fc5) --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 48e40e36a0d3..30df4ac1ebca 100755 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -11804,7 +11804,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 ac10976b9801..e4998d0a92c5 100644 --- a/src/test/libcephfs/test.cc +++ b/src/test/libcephfs/test.cc @@ -2289,6 +2289,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));