Skip to content

Commit 7b5fe62

Browse files
Merge pull request ceph#64864 from chrisphoffman/wip-choffman-72355
client: use path supplied in statfs Reviewed-by: Venky Shankar <[email protected]> Reviewed-by: Patrick Donnelly <[email protected]> Reviewed-by: Frank S. Filz <[email protected]>
2 parents c14dc89 + 45776aa commit 7b5fe62

File tree

4 files changed

+90
-20
lines changed

4 files changed

+90
-20
lines changed

qa/tasks/cephfs/test_cephfs_shell.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ def test_df_for_valid_directory(self):
833833
def test_df_for_invalid_directory(self):
834834
dir_abspath = path.join(self.mount_a.mountpoint, 'non-existent-dir')
835835
self.negtest_cephfs_shell_cmd(cmd='df ' + dir_abspath,
836-
errmsg='error in stat')
836+
errmsg='statfs failed')
837837

838838
def test_df_for_valid_file(self):
839839
s = 'df test' * 14145016

src/client/Client.cc

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12569,33 +12569,36 @@ int Client::getcwd(string& dir, const UserPerm& perms)
1256912569
return _getcwd(dir, perms);
1257012570
}
1257112571

12572-
int Client::statfs(const char *path, struct statvfs *stbuf,
12572+
int Client::_statfs(Inode *in, struct statvfs *stbuf,
1257312573
const UserPerm& perms)
1257412574
{
12575-
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
12576-
if (!mref_reader.is_state_satisfied())
12577-
return -ENOTCONN;
12575+
ceph_assert(ceph_mutex_is_locked_by_me(client_lock));
1257812576

12577+
ldout(cct, 10) << __func__ << dendl;
1257912578
tout(cct) << __func__ << std::endl;
1258012579
unsigned long int total_files_on_fs;
1258112580

1258212581
ceph_statfs stats;
1258312582
C_SaferCond cond;
1258412583

12585-
std::unique_lock lock(client_lock);
1258612584
const vector<int64_t> &data_pools = mdsmap->get_data_pools();
1258712585
if (data_pools.size() == 1) {
1258812586
objecter->get_fs_stats(stats, data_pools[0], &cond);
1258912587
} else {
1259012588
objecter->get_fs_stats(stats, std::optional<int64_t>(), &cond);
1259112589
}
1259212590

12593-
lock.unlock();
12591+
client_lock.unlock();
1259412592
int rval = cond.wait();
12595-
lock.lock();
12593+
client_lock.lock();
1259612594

12597-
ceph_assert(root);
12598-
total_files_on_fs = root->rstat.rfiles + root->rstat.rsubdirs;
12595+
ceph_assert(in);
12596+
// Usually quota_root will == root_ancestor, but if the mount root has no
12597+
// quota but we can see a parent of it that does have a quota, we'll
12598+
// respect that one instead.
12599+
InodeRef quota_root = in->quota.is_enabled() ? in : get_quota_root(in, perms);
12600+
12601+
total_files_on_fs = quota_root->rstat.rfiles + quota_root->rstat.rsubdirs;
1259912602

1260012603
if (rval < 0) {
1260112604
ldout(cct, 1) << "underlying call to statfs returned error: "
@@ -12623,12 +12626,6 @@ int Client::statfs(const char *path, struct statvfs *stbuf,
1262312626
stbuf->f_flag = 0; // ??
1262412627
stbuf->f_namemax = NAME_MAX;
1262512628

12626-
// Usually quota_root will == root_ancestor, but if the mount root has no
12627-
// quota but we can see a parent of it that does have a quota, we'll
12628-
// respect that one instead.
12629-
ceph_assert(root != nullptr);
12630-
InodeRef quota_root = root->quota.is_enabled(QUOTA_MAX_BYTES) ? root : get_quota_root(root.get(), perms, QUOTA_MAX_BYTES);
12631-
1263212629
// get_quota_root should always give us something if client quotas are
1263312630
// enabled
1263412631
ceph_assert(cct->_conf.get_val<bool>("client_quota") == false || quota_root != nullptr);
@@ -13013,10 +13010,29 @@ int Client::get_snap_info(const char *path, const UserPerm &perms, SnapInfo *sna
1301313010

1301413011
int Client::ll_statfs(Inode *in, struct statvfs *stbuf, const UserPerm& perms)
1301513012
{
13016-
/* Since the only thing this does is wrap a call to statfs, and
13017-
statfs takes a lock, it doesn't seem we have a need to split it
13018-
out. */
13019-
return statfs(0, stbuf, perms);
13013+
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
13014+
if (!mref_reader.is_state_satisfied())
13015+
return -ENOTCONN;
13016+
13017+
std::unique_lock cl(client_lock);
13018+
return _statfs(in, stbuf, perms);
13019+
}
13020+
13021+
int Client::statfs(const char *path, struct statvfs *stbuf, const UserPerm& perms)
13022+
{
13023+
RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
13024+
if (!mref_reader.is_state_satisfied())
13025+
return -ENOTCONN;
13026+
13027+
std::unique_lock cl(client_lock);
13028+
13029+
walk_dentry_result wdr;
13030+
if (int rc = path_walk(cwd, filepath(path), &wdr, perms, {}); rc < 0) {
13031+
return rc;
13032+
}
13033+
13034+
auto in = wdr.target.get();
13035+
return _statfs(in, stbuf, perms);
1302013036
}
1302113037

1302213038
void Client::_ll_register_callbacks(struct ceph_client_callback_args *args)

src/client/Client.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,6 +1865,8 @@ class Client : public Dispatcher, public md_config_obs_t {
18651865
int _lookup_vino(vinodeno_t ino, const UserPerm& perms, Inode **inode=NULL);
18661866
bool _ll_forget(Inode *in, uint64_t count);
18671867

1868+
int _statfs(Inode *in, struct statvfs *stbuf, const UserPerm& perms);
1869+
18681870
void collect_and_send_metrics();
18691871
void collect_and_send_global_metrics();
18701872

src/test/libcephfs/test.cc

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,58 @@ TEST(LibCephFS, FlagO_PATH) {
10191019
}
10201020
#endif /* __linux */
10211021

1022+
TEST(LibCephFS, StatfsQuota) {
1023+
1024+
struct ceph_mount_info *cmount;
1025+
ASSERT_EQ(ceph_create(&cmount, NULL), 0);
1026+
ASSERT_EQ(ceph_conf_read_file(cmount, NULL), 0);
1027+
ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
1028+
ASSERT_EQ(ceph_mount(cmount, NULL), 0);
1029+
1030+
const char* quota_dir = "quota_dir";
1031+
1032+
ASSERT_EQ(0, ceph_mkdir(cmount, quota_dir, 0777));
1033+
EXPECT_EQ(0, ceph_setxattr(cmount, quota_dir, "ceph.quota.max_files", "10000", 05, 0));
1034+
1035+
const int num_quota_files = 1;
1036+
char quota_file[256];
1037+
sprintf(quota_file, "%s/test_statfs_quota_%d", quota_dir, getpid());
1038+
1039+
int fd = ceph_open(cmount, quota_file, O_CREAT|O_RDWR, 0666);
1040+
ASSERT_GT(fd, 0);
1041+
1042+
ceph_close(cmount, fd);
1043+
1044+
const int num_reg_files = 5;
1045+
char regular_file[256];
1046+
for (int i = 0; i < num_reg_files; i++) {
1047+
sprintf(regular_file, "test_statfs_regular_%d", i);
1048+
fd = ceph_open(cmount, regular_file, O_CREAT|O_RDWR, 0666);
1049+
ceph_close(cmount, fd);
1050+
}
1051+
1052+
ASSERT_EQ(0, ceph_unmount(cmount));
1053+
ASSERT_EQ(0, ceph_mount(cmount, NULL));
1054+
1055+
struct statvfs quota_stvbuf;
1056+
ASSERT_EQ(0, ceph_statfs(cmount, quota_file, &quota_stvbuf));
1057+
ASSERT_EQ(num_quota_files+1, quota_stvbuf.f_files); // +1 for dirent quota_dir
1058+
1059+
struct statvfs reg_stvbuf;
1060+
ASSERT_EQ(0, ceph_statfs(cmount, "test_statfs_regular_1", &reg_stvbuf));
1061+
ASSERT_GT(reg_stvbuf.f_files, quota_stvbuf.f_files);
1062+
1063+
for (int i = 0; i < num_reg_files; i++) {
1064+
sprintf(regular_file, "test_statfs_regular_%d", i);
1065+
ASSERT_EQ(0, ceph_unlink(cmount, regular_file));
1066+
}
1067+
1068+
ASSERT_EQ(0, ceph_unlink(cmount, quota_file));
1069+
ASSERT_EQ(0, ceph_rmdir(cmount, quota_dir));
1070+
1071+
ceph_shutdown(cmount);
1072+
}
1073+
10221074
TEST(LibCephFS, Symlinks) {
10231075
struct ceph_mount_info *cmount;
10241076
ASSERT_EQ(ceph_create(&cmount, NULL), 0);

0 commit comments

Comments
 (0)