./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
===============
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));
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;
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;
}
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)