From patchwork Tue Dec 9 05:22:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Li Xi X-Patchwork-Id: 418949 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 0C0161400D5 for ; Tue, 9 Dec 2014 16:24:20 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752522AbaLIFYM (ORCPT ); Tue, 9 Dec 2014 00:24:12 -0500 Received: from mail-pd0-f171.google.com ([209.85.192.171]:46078 "EHLO mail-pd0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752475AbaLIFYI (ORCPT ); Tue, 9 Dec 2014 00:24:08 -0500 Received: by mail-pd0-f171.google.com with SMTP id y13so6617221pdi.30 for ; Mon, 08 Dec 2014 21:24:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references; bh=Y2xnwGLWJQndfgU6kKK7hrnlN7W7YLgK4wHqzPihQiM=; b=dN7uHCBcZZmtxlR58rgWfJBjR0B5s5azHodw+vIYqSbAqvuztUZYoObQv8BZ2g0yb7 tLc/+g6llMk9eX2ZkbKgMedevynOhVYFV5a78x+bFN3/01DFQsEYR7Jc8owDb4HiPehn YdEIgJV7K1yuFN55E49UrNCx9MNtQhBmHULQl7V/LipCSpe8IWOWI2+wXlETYqAyHqzE z3fFw+/RTL7UkQjOqRomnID9l4GFK1UV3Feef608Shj2lunB05KgBzH/m5Z3y0sdjwzB vX/9bpU9ZD6jwt/OU2GVmxOBQsLklCcctyQQdNtRlhLMx5pQokfyvIWT7w2VFECMfIMR orPg== X-Received: by 10.68.135.100 with SMTP id pr4mr1744575pbb.123.1418102648029; Mon, 08 Dec 2014 21:24:08 -0800 (PST) Received: from localhost.localdomain ([61.131.246.61]) by mx.google.com with ESMTPSA id my2sm165802pdb.86.2014.12.08.21.24.02 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 08 Dec 2014 21:24:07 -0800 (PST) From: Li Xi X-Google-Original-From: Li Xi To: linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org, linux-api@vger.kernel.org, tytso@mit.edu, adilger@dilger.ca, jack@suse.cz, viro@zeniv.linux.org.uk, hch@infradead.org, dmonakhov@openvz.org Subject: [v8 1/5] vfs: adds general codes to enforces project quota limits Date: Tue, 9 Dec 2014 13:22:24 +0800 Message-Id: <1418102548-5469-2-git-send-email-lixi@ddn.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1418102548-5469-1-git-send-email-lixi@ddn.com> References: <1418102548-5469-1-git-send-email-lixi@ddn.com> Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org This patch adds support for a new quota type PRJQUOTA for project quota enforcement. Also a new method get_projid() is added into dquot_operations structure. Signed-off-by: Li Xi Signed-off-by: Dmitry Monakhov Reviewed-by: Jan Kara --- fs/quota/dquot.c | 35 ++++++++++++++++++++++++++++++----- fs/quota/quota.c | 8 ++++++-- fs/quota/quotaio_v2.h | 6 ++++-- include/linux/quota.h | 2 ++ include/uapi/linux/quota.h | 6 ++++-- 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 6b45272..379ff77 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -1154,8 +1154,8 @@ static int need_print_warning(struct dquot_warn *warn) return uid_eq(current_fsuid(), warn->w_dq_id.uid); case GRPQUOTA: return in_group_p(warn->w_dq_id.gid); - case PRJQUOTA: /* Never taken... Just make gcc happy */ - return 0; + case PRJQUOTA: + return 1; } return 0; } @@ -1394,6 +1394,9 @@ static void __dquot_initialize(struct inode *inode, int type) /* First get references to structures we might need. */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { struct kqid qid; + kprojid_t projid; + int rc; + got[cnt] = NULL; if (type != -1 && cnt != type) continue; @@ -1404,6 +1407,10 @@ static void __dquot_initialize(struct inode *inode, int type) */ if (inode->i_dquot[cnt]) continue; + + if (!sb_has_quota_active(sb, cnt)) + continue; + init_needed = 1; switch (cnt) { @@ -1413,6 +1420,12 @@ static void __dquot_initialize(struct inode *inode, int type) case GRPQUOTA: qid = make_kqid_gid(inode->i_gid); break; + case PRJQUOTA: + rc = inode->i_sb->dq_op->get_projid(inode, &projid); + if (rc) + continue; + qid = make_kqid_projid(projid); + break; } got[cnt] = dqget(sb, qid); } @@ -2156,7 +2169,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, error = -EROFS; goto out_fmt; } - if (!sb->s_op->quota_write || !sb->s_op->quota_read) { + if (!sb->s_op->quota_write || !sb->s_op->quota_read || + (type == PRJQUOTA && sb->dq_op->get_projid == NULL)) { error = -EINVAL; goto out_fmt; } @@ -2397,8 +2411,19 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di) memset(di, 0, sizeof(*di)); di->d_version = FS_DQUOT_VERSION; - di->d_flags = dquot->dq_id.type == USRQUOTA ? - FS_USER_QUOTA : FS_GROUP_QUOTA; + switch (dquot->dq_id.type) { + case USRQUOTA: + di->d_flags = FS_USER_QUOTA; + break; + case GRPQUOTA: + di->d_flags = FS_GROUP_QUOTA; + break; + case PRJQUOTA: + di->d_flags = FS_PROJ_QUOTA; + break; + default: + BUG(); + } di->d_id = from_kqid_munged(current_user_ns(), dquot->dq_id); spin_lock(&dq_data_lock); diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 7562164..795d694 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -30,11 +30,15 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd, case Q_XGETQSTATV: case Q_XQUOTASYNC: break; - /* allow to query information for dquots we "own" */ + /* + * allow to query information for dquots we "own" + * always allow querying project quota + */ case Q_GETQUOTA: case Q_XGETQUOTA: if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) || - (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id)))) + (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id))) || + (type == PRJQUOTA)) break; /*FALLTHROUGH*/ default: diff --git a/fs/quota/quotaio_v2.h b/fs/quota/quotaio_v2.h index f1966b4..4e95430 100644 --- a/fs/quota/quotaio_v2.h +++ b/fs/quota/quotaio_v2.h @@ -13,12 +13,14 @@ */ #define V2_INITQMAGICS {\ 0xd9c01f11, /* USRQUOTA */\ - 0xd9c01927 /* GRPQUOTA */\ + 0xd9c01927, /* GRPQUOTA */\ + 0xd9c03f14, /* PRJQUOTA */\ } #define V2_INITQVERSIONS {\ 1, /* USRQUOTA */\ - 1 /* GRPQUOTA */\ + 1, /* GRPQUOTA */\ + 1, /* PRJQUOTA */\ } /* First generic header */ diff --git a/include/linux/quota.h b/include/linux/quota.h index 80d345a..f1b25f8 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -50,6 +50,7 @@ #undef USRQUOTA #undef GRPQUOTA +#undef PRJQUOTA enum quota_type { USRQUOTA = 0, /* element used for user quotas */ GRPQUOTA = 1, /* element used for group quotas */ @@ -312,6 +313,7 @@ struct dquot_operations { /* get reserved quota for delayed alloc, value returned is managed by * quota code only */ qsize_t *(*get_reserved_space) (struct inode *); + int (*get_projid) (struct inode *, kprojid_t *);/* Get project ID */ }; struct path; diff --git a/include/uapi/linux/quota.h b/include/uapi/linux/quota.h index 3b6cfbe..b2d9486 100644 --- a/include/uapi/linux/quota.h +++ b/include/uapi/linux/quota.h @@ -36,11 +36,12 @@ #include #include -#define __DQUOT_VERSION__ "dquot_6.5.2" +#define __DQUOT_VERSION__ "dquot_6.6.0" -#define MAXQUOTAS 2 +#define MAXQUOTAS 3 #define USRQUOTA 0 /* element used for user quotas */ #define GRPQUOTA 1 /* element used for group quotas */ +#define PRJQUOTA 2 /* element used for project quotas */ /* * Definitions for the default names of the quotas files. @@ -48,6 +49,7 @@ #define INITQFNAMES { \ "user", /* USRQUOTA */ \ "group", /* GRPQUOTA */ \ + "project", /* PRJQUOTA */ \ "undefined", \ };