From patchwork Sun Oct 26 05:22:49 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Li Xi X-Patchwork-Id: 403120 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 3D49E140088 for ; Sun, 26 Oct 2014 16:25:19 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750965AbaJZFZM (ORCPT ); Sun, 26 Oct 2014 01:25:12 -0400 Received: from mail-pd0-f181.google.com ([209.85.192.181]:55146 "EHLO mail-pd0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750943AbaJZFZK (ORCPT ); Sun, 26 Oct 2014 01:25:10 -0400 Received: by mail-pd0-f181.google.com with SMTP id w10so3711190pde.12 for ; Sat, 25 Oct 2014 22:25:10 -0700 (PDT) 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=raNOPCjYwlOJ8C3BbD2Ep2DWs5MDm2eVV7ITxY2wr38=; b=zzM4TNQN6eNOus19AR0IUvyXVw0gzaMqrEwq972GYmTmwOvE2CPyFGVhPb0k5f2Dqt rCmcl0pYvS7pcXNys0myqgTFa4bhz4dOsCjeVJMh7385c1QGfNiMTiYHBJoyAnNNm4vB au4qlaRU+mgNImwsRTX4wrM44XsQul9CCI+UZhYBsFttDTN6HjkHQSumCgig7pgREUEv eC5FEk1vwDi9wRB/K+tjYvL9fLHyjFBHdCObeJ1lP9XCbDlWan5gTp5pDzVCaEuLytkU m5CJbxh2A0pkoFbF5233l9ZMCm9x8FoBGIeG02C7vlbYgGG5PNUmRuWEasWq3ienKkJu 0q4Q== X-Received: by 10.70.48.10 with SMTP id h10mr15541509pdn.2.1414301109933; Sat, 25 Oct 2014 22:25:09 -0700 (PDT) Received: from localhost.localdomain ([59.54.192.157]) by mx.google.com with ESMTPSA id v9sm7509027pdr.62.2014.10.25.22.25.05 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 25 Oct 2014 22:25:09 -0700 (PDT) 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: [v5 1/5] Adds general codes to enforces project quota limits Date: Sun, 26 Oct 2014 13:22:49 +0800 Message-Id: <1414300973-1118-2-git-send-email-lixi@ddn.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1414300973-1118-1-git-send-email-lixi@ddn.com> References: <1414300973-1118-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 --- fs/quota/dquot.c | 32 ++++++++++++++++++++++++++++---- fs/quota/quota.c | 10 ++++++++-- fs/quota/quotaio_v2.h | 6 ++++-- include/linux/quota.h | 2 ++ include/uapi/linux/quota.h | 6 ++++-- 5 files changed, 46 insertions(+), 10 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index f2d0eee..d757d5d 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); } @@ -2397,8 +2410,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..d4d1ab9 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: @@ -72,6 +76,8 @@ static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id, return sb->s_qcop->quota_on_meta(sb, type, id); if (IS_ERR(path)) return PTR_ERR(path); + if (type == PRJQUOTA && sb->dq_op->get_projid == NULL) + return -EOPNOTSUPP; return sb->s_qcop->quota_on(sb, type, id, path); } 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", \ };