From patchwork Fri Jan 5 10:47:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luis Henriques X-Patchwork-Id: 10146285 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B8B326034B for ; Fri, 5 Jan 2018 10:47:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A4DA22873E for ; Fri, 5 Jan 2018 10:47:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 985EB28773; Fri, 5 Jan 2018 10:47:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 365A72873E for ; Fri, 5 Jan 2018 10:47:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751283AbeAEKrm (ORCPT ); Fri, 5 Jan 2018 05:47:42 -0500 Received: from mx2.suse.de ([195.135.220.15]:36331 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751012AbeAEKri (ORCPT ); Fri, 5 Jan 2018 05:47:38 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id EA744ABB4; Fri, 5 Jan 2018 10:47:36 +0000 (UTC) From: Luis Henriques To: ceph-devel@vger.kernel.org Cc: "Yan, Zheng" , Jeff Layton , Jan Fajerski , Luis Henriques Subject: [PATCH v4 4/6] ceph: quota: support for ceph.quota.max_bytes Date: Fri, 5 Jan 2018 10:47:21 +0000 Message-Id: <20180105104723.16202-5-lhenriques@suse.com> In-Reply-To: <20180105104723.16202-1-lhenriques@suse.com> References: <20180105104723.16202-1-lhenriques@suse.com> Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Luis Henriques --- fs/ceph/file.c | 11 +++++++++++ fs/ceph/inode.c | 4 ++++ fs/ceph/quota.c | 28 +++++++++++++++++++++++++++- fs/ceph/super.h | 2 ++ 4 files changed, 44 insertions(+), 1 deletion(-) -- To unsubscribe from this list: send the line "unsubscribe ceph-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 5a77a66e3d6b..762402d323a6 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1331,6 +1331,11 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) pos = iocb->ki_pos; count = iov_iter_count(from); + if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) { + err = -EDQUOT; + goto out; + } + err = file_remove_privs(file); if (err) goto out; @@ -1661,6 +1666,12 @@ static long ceph_fallocate(struct file *file, int mode, goto unlock; } + if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)) && + ceph_quota_is_max_bytes_exceeded(inode, offset + length)) { + ret = -EDQUOT; + goto unlock; + } + if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) && !(mode & FALLOC_FL_PUNCH_HOLE)) { ret = -ENOSPC; diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 8a0ba96e105d..342ba26f6232 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -2130,6 +2130,10 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) if (err != 0) return err; + if ((attr->ia_valid & ATTR_SIZE) && + ceph_quota_is_max_bytes_exceeded(inode, attr->ia_size)) + return -EDQUOT; + err = __ceph_setattr(inode, attr); if (err >= 0 && (attr->ia_valid & ATTR_MODE)) diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c index 5d7dada91a57..745f9f47027b 100644 --- a/fs/ceph/quota.c +++ b/fs/ceph/quota.c @@ -134,7 +134,8 @@ bool ceph_quota_is_same_realm(struct inode *old, struct inode *new) } enum quota_check_op { - QUOTA_CHECK_MAX_FILES_OP /* check quota max_files limit */ + QUOTA_CHECK_MAX_FILES_OP, /* check quota max_files limit */ + QUOTA_CHECK_MAX_BYTES_OP /* check quota max_files limit */ }; /* @@ -171,6 +172,9 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op, if (op == QUOTA_CHECK_MAX_FILES_OP) { max = ci->i_max_files; rvalue = ci->i_rfiles + ci->i_rsubdirs; + } else { + max = ci->i_max_bytes; + rvalue = ci->i_rbytes; } is_root = (ci->i_vino.ino == CEPH_INO_ROOT); spin_unlock(&ci->i_ceph_lock); @@ -178,6 +182,9 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op, case QUOTA_CHECK_MAX_FILES_OP: exceeded = (max && (rvalue >= max)); break; + case QUOTA_CHECK_MAX_BYTES_OP: + exceeded = (max && (rvalue + delta > max)); + break; default: /* Shouldn't happen */ pr_warn("Invalid quota check op (%d)\n", op); @@ -212,3 +219,22 @@ bool ceph_quota_is_max_files_exceeded(struct inode *inode) return check_quota_exceeded(inode, QUOTA_CHECK_MAX_FILES_OP, 0); } + +/* + * ceph_quota_is_max_bytes_exceeded - check if we can write to a file + * @inode: inode being written + * @newsize: new size if write succeeds + * + * This functions returns true is max_bytes quota allows a file size to reach + * @newsize; it returns false otherwise. + */ +bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, loff_t newsize) +{ + loff_t size = i_size_read(inode); + + /* return immediately if we're decreasing file size */ + if (newsize <= size) + return false; + + return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_OP, (newsize - size)); +} diff --git a/fs/ceph/super.h b/fs/ceph/super.h index a66e73338386..60ace9ce5a94 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -1028,5 +1028,7 @@ extern void ceph_handle_quota(struct ceph_mds_client *mdsc, struct ceph_msg *msg); extern bool ceph_quota_is_max_files_exceeded(struct inode *inode); extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new); +extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, + loff_t newlen); #endif /* _FS_CEPH_SUPER_H */