ceph_queue_caps_release(inode);
+ if (__ceph_has_any_quota(ci))
+ ceph_adjust_quota_realms_count(inode, false);
+
/*
* we may still have a snap_realm reference if there are stray
* caps in i_snap_caps.
inode->i_rdev = le32_to_cpu(info->rdev);
inode->i_blkbits = fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1;
- ci->i_max_bytes = iinfo->max_bytes;
- ci->i_max_files = iinfo->max_files;
+ __ceph_update_quota(ci, iinfo->max_bytes, iinfo->max_files);
if ((new_version || (new_issued & CEPH_CAP_AUTH_SHARED)) &&
(issued & CEPH_CAP_AUTH_EXCL) == 0) {
atomic_set(&mdsc->num_sessions, 0);
mdsc->max_sessions = 0;
mdsc->stopping = 0;
+ atomic64_set(&mdsc->quotarealms_count, 0);
mdsc->last_snap_seq = 0;
init_rwsem(&mdsc->snap_rwsem);
mdsc->snap_realms = RB_ROOT;
int max_sessions; /* len of s_mds_sessions */
int stopping; /* true if shutting down */
+ atomic64_t quotarealms_count; /* # realms with quota */
+
/*
* snap_rwsem will cover cap linkage into snaprealms, and
* realm snap contexts. (later, we can do per-realm snap
#include "super.h"
#include "mds_client.h"
-static inline bool ceph_has_quota(struct ceph_inode_info *ci)
+void ceph_adjust_quota_realms_count(struct inode *inode, bool inc)
{
- return (ci && (ci->i_max_files || ci->i_max_bytes));
+ struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+ if (inc)
+ atomic64_inc(&mdsc->quotarealms_count);
+ else
+ atomic64_dec(&mdsc->quotarealms_count);
+}
+
+static inline bool ceph_has_realms_with_quotas(struct inode *inode)
+{
+ struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+ return atomic64_read(&mdsc->quotarealms_count) > 0;
}
void ceph_handle_quota(struct ceph_mds_client *mdsc,
ci->i_rbytes = le64_to_cpu(h->rbytes);
ci->i_rfiles = le64_to_cpu(h->rfiles);
ci->i_rsubdirs = le64_to_cpu(h->rsubdirs);
- ci->i_max_bytes = le64_to_cpu(h->max_bytes);
- ci->i_max_files = le64_to_cpu(h->max_files);
+ __ceph_update_quota(ci, le64_to_cpu(h->max_bytes),
+ le64_to_cpu(h->max_files));
spin_unlock(&ci->i_ceph_lock);
iput(inode);
break;
ci = ceph_inode(in);
- has_quota = ceph_has_quota(ci);
+ has_quota = __ceph_has_any_quota(ci);
iput(in);
next = realm->parent;
*/
bool ceph_quota_is_max_files_exceeded(struct inode *inode)
{
+ if (!ceph_has_realms_with_quotas(inode))
+ return false;
+
WARN_ON(!S_ISDIR(inode->i_mode));
return check_quota_exceeded(inode, QUOTA_CHECK_MAX_FILES_OP, 0);
{
loff_t size = i_size_read(inode);
+ if (!ceph_has_realms_with_quotas(inode))
+ return false;
+
/* return immediately if we're decreasing file size */
if (newsize <= size)
return false;
{
loff_t size = ceph_inode(inode)->i_reported_size;
+ if (!ceph_has_realms_with_quotas(inode))
+ return false;
+
/* return immediately if we're decreasing file size */
if (newsize <= size)
return false;
extern void ceph_fs_debugfs_cleanup(struct ceph_fs_client *client);
/* quota.c */
+static inline bool __ceph_has_any_quota(struct ceph_inode_info *ci)
+{
+ return ci->i_max_files || ci->i_max_bytes;
+}
+
+extern void ceph_adjust_quota_realms_count(struct inode *inode, bool inc);
+
+static inline void __ceph_update_quota(struct ceph_inode_info *ci,
+ u64 max_bytes, u64 max_files)
+{
+ bool had_quota, has_quota;
+ had_quota = __ceph_has_any_quota(ci);
+ ci->i_max_bytes = max_bytes;
+ ci->i_max_files = max_files;
+ has_quota = __ceph_has_any_quota(ci);
+
+ if (had_quota != has_quota)
+ ceph_adjust_quota_realms_count(&ci->vfs_inode, has_quota);
+}
+
extern void ceph_handle_quota(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg);