Skip to content

Commit

Permalink
ceph: quota: add counter for snaprealms with quota
Browse files Browse the repository at this point in the history
By keeping a counter with the number of snaprealms that have quota set
allows to optimize the functions that need to walk throught the realms
hierarchy looking for quotas.  Thus, if this counter is zero it's safe to
assume that there are no realms with quota.

Signed-off-by: Luis Henriques <lhenriques@suse.com>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
  • Loading branch information
Luis Henriques authored and Ilya Dryomov committed Apr 2, 2018
1 parent e3161f1 commit d557c48
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 7 deletions.
6 changes: 4 additions & 2 deletions fs/ceph/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,9 @@ void ceph_destroy_inode(struct inode *inode)

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.
Expand Down Expand Up @@ -796,8 +799,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
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) {
Expand Down
1 change: 1 addition & 0 deletions fs/ceph/mds_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -3609,6 +3609,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
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;
Expand Down
2 changes: 2 additions & 0 deletions fs/ceph/mds_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ struct ceph_mds_client {
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
Expand Down
29 changes: 24 additions & 5 deletions fs/ceph/quota.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,19 @@
#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,
Expand Down Expand Up @@ -62,8 +72,8 @@ 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);
Expand Down Expand Up @@ -103,7 +113,7 @@ static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc,
break;

ci = ceph_inode(in);
has_quota = ceph_has_quota(ci);
has_quota = __ceph_has_any_quota(ci);
iput(in);

next = realm->parent;
Expand Down Expand Up @@ -241,6 +251,9 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
*/
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);
Expand All @@ -258,6 +271,9 @@ bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, loff_t newsize)
{
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;
Expand All @@ -277,6 +293,9 @@ bool ceph_quota_is_max_bytes_approaching(struct inode *inode, loff_t newsize)
{
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;
Expand Down
20 changes: 20 additions & 0 deletions fs/ceph/super.h
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,26 @@ extern int ceph_fs_debugfs_init(struct ceph_fs_client *client);
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);
Expand Down

0 comments on commit d557c48

Please sign in to comment.