mirror of
https://github.com/ceph/ceph
synced 2025-01-04 10:12:30 +00:00
client: report root's quota in statfs
When user is mounted a quota-restricted inode as the root, report that inode's quota status as the filesystem statistics in statfs. This allows us to have a fairly convincing illusion that someone has a filesystem to themselves, when they're really mounting a restricted part of the larger global filesystem. Fixes: http://tracker.ceph.com/issues/15599 Signed-off-by: John Spray <john.spray@redhat.com>
This commit is contained in:
parent
30af2cd071
commit
b6d2b6d1a5
@ -43,6 +43,25 @@ for example, to restrict client ``foo`` to ``mnt/bar`` directory, we will use. :
|
||||
|
||||
./ceph-fuse -n client.foo mnt -r /bar
|
||||
|
||||
Free space reporting
|
||||
--------------------
|
||||
|
||||
By default, when a client is mounting a sub-directory, the used space (``df``)
|
||||
will be calculated from the quota on that sub-directory, rather than reporting
|
||||
the overall amount of space used on the cluster.
|
||||
|
||||
If you would like the client to report the overall usage of the filesystem,
|
||||
and not just the quota usage on the sub-directory mounted, then set the
|
||||
following config option on the client:
|
||||
|
||||
::
|
||||
|
||||
client quota df = false
|
||||
|
||||
If quotas are not enabled, or no quota is set on the sub-directory mounted,
|
||||
then the overall usage of the filesystem will be reported irrespective of
|
||||
the value of this setting.
|
||||
|
||||
OSD restriction
|
||||
===============
|
||||
|
||||
|
@ -8752,19 +8752,11 @@ int Client::statfs(const char *path, struct statvfs *stbuf)
|
||||
tout(cct) << "statfs" << std::endl;
|
||||
|
||||
ceph_statfs stats;
|
||||
|
||||
Mutex lock("Client::statfs::lock");
|
||||
Cond cond;
|
||||
bool done;
|
||||
int rval;
|
||||
|
||||
objecter->get_fs_stats(stats, new C_SafeCond(&lock, &cond, &done, &rval));
|
||||
C_SaferCond cond;
|
||||
objecter->get_fs_stats(stats, &cond);
|
||||
|
||||
client_lock.Unlock();
|
||||
lock.Lock();
|
||||
while (!done)
|
||||
cond.Wait(lock);
|
||||
lock.Unlock();
|
||||
int rval = cond.wait();
|
||||
client_lock.Lock();
|
||||
|
||||
memset(stbuf, 0, sizeof(*stbuf));
|
||||
@ -8779,9 +8771,6 @@ int Client::statfs(const char *path, struct statvfs *stbuf)
|
||||
const int CEPH_BLOCK_SHIFT = 22;
|
||||
stbuf->f_frsize = 1 << CEPH_BLOCK_SHIFT;
|
||||
stbuf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
|
||||
stbuf->f_blocks = stats.kb >> (CEPH_BLOCK_SHIFT - 10);
|
||||
stbuf->f_bfree = stats.kb_avail >> (CEPH_BLOCK_SHIFT - 10);
|
||||
stbuf->f_bavail = stats.kb_avail >> (CEPH_BLOCK_SHIFT - 10);
|
||||
stbuf->f_files = stats.num_objects;
|
||||
stbuf->f_ffree = -1;
|
||||
stbuf->f_favail = -1;
|
||||
@ -8789,6 +8778,37 @@ int Client::statfs(const char *path, struct statvfs *stbuf)
|
||||
stbuf->f_flag = 0; // ??
|
||||
stbuf->f_namemax = NAME_MAX;
|
||||
|
||||
// Usually quota_root will == root_ancestor, but if the mount root has no
|
||||
// quota but we can see a parent of it that does have a quota, we'll
|
||||
// respect that one instead.
|
||||
assert(root != nullptr);
|
||||
Inode *quota_root = get_quota_root(root);
|
||||
|
||||
// get_quota_root should always give us something if client quotas are
|
||||
// enabled
|
||||
assert(cct->_conf->client_quota == false || quota_root != nullptr);
|
||||
|
||||
if (quota_root && cct->_conf->client_quota_df && quota_root->quota.max_bytes) {
|
||||
// Special case: if there is a size quota set on the Inode acting
|
||||
// as the root for this client mount, then report the quota status
|
||||
// as the filesystem statistics.
|
||||
const fsblkcnt_t total = quota_root->quota.max_bytes >> CEPH_BLOCK_SHIFT;
|
||||
const fsblkcnt_t used = quota_root->rstat.rbytes >> CEPH_BLOCK_SHIFT;
|
||||
const fsblkcnt_t free = total - used;
|
||||
|
||||
|
||||
stbuf->f_blocks = total;
|
||||
stbuf->f_bfree = free;
|
||||
stbuf->f_bavail = free;
|
||||
} else {
|
||||
// General case: report the overall RADOS cluster's statistics. Because
|
||||
// multiple pools may be used without one filesystem namespace via
|
||||
// layouts, this is the most correct thing we can do.
|
||||
stbuf->f_blocks = stats.kb >> (CEPH_BLOCK_SHIFT - 10);
|
||||
stbuf->f_bfree = stats.kb_avail >> (CEPH_BLOCK_SHIFT - 10);
|
||||
stbuf->f_bavail = stats.kb_avail >> (CEPH_BLOCK_SHIFT - 10);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
@ -382,6 +382,7 @@ OPTION(client_notify_timeout, OPT_INT, 10) // in seconds
|
||||
OPTION(osd_client_watch_timeout, OPT_INT, 30) // in seconds
|
||||
OPTION(client_caps_release_delay, OPT_INT, 5) // in seconds
|
||||
OPTION(client_quota, OPT_BOOL, false)
|
||||
OPTION(client_quota_df, OPT_BOOL, true) // use quota for df on subdir mounts
|
||||
OPTION(client_oc, OPT_BOOL, true)
|
||||
OPTION(client_oc_size, OPT_INT, 1024*1024* 200) // MB * n
|
||||
OPTION(client_oc_max_dirty, OPT_INT, 1024*1024* 100) // MB * n (dirty OR tx.. bigish)
|
||||
|
Loading…
Reference in New Issue
Block a user