From patchwork Thu Apr 9 15:14:33 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Li Xi X-Patchwork-Id: 6188531 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9E6CD9F2EC for ; Thu, 9 Apr 2015 15:15:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7C5212035C for ; Thu, 9 Apr 2015 15:15:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 57E16201F4 for ; Thu, 9 Apr 2015 15:15:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755627AbbDIPPB (ORCPT ); Thu, 9 Apr 2015 11:15:01 -0400 Received: from mail-pa0-f42.google.com ([209.85.220.42]:34065 "EHLO mail-pa0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755252AbbDIPO7 (ORCPT ); Thu, 9 Apr 2015 11:14:59 -0400 Received: by pacyx8 with SMTP id yx8so152350664pac.1; Thu, 09 Apr 2015 08:14:58 -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=guaS/BbrHMAwy9rxYu2D+ffW4zRpnK/w0uvukcRKFRQ=; b=GbiI9PxxS5VVeMKP28et9jDQvpNlEKaTMvumgsblt8I2VtVGmPPBxBozb4erCmj+0g xllj9flYN2gu3Yy9kMUatX4I5+eXDHX3RLeARAQxPGiaC0NSVtxnCsxU5fcBDJWlSGa1 E8QkpEDxY6A0QD/68vtzYA16Sgkue7pnYnw0WE3OTVV1rR4EtR+M1s0bERIf73q/7ZxS Czca3PGiBLSpy5Lnf9CxeCfr2m4y3Km8c01kuyHhvEL0sgTTJpWBP4AzzwJT46cDMnMg 1+ZqQYWkN9hkt4d1aVmZAHOSNVMtf6fSsKmnuvVa5acPfiRv+R6Lr7tCJ18hNhuV+BSG 7iqw== X-Received: by 10.68.239.65 with SMTP id vq1mr56740464pbc.49.1428592498532; Thu, 09 Apr 2015 08:14:58 -0700 (PDT) Received: from localhost.localdomain (ddnj-fw01.datadirectnet.jp. [180.42.29.249]) by mx.google.com with ESMTPSA id nm1sm14634822pbc.50.2015.04.09.08.14.56 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Apr 2015 08:14:57 -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: [v12 1/5] vfs: adds general codes to enforces project quota limits Date: Fri, 10 Apr 2015 00:14:33 +0900 Message-Id: <1428592477-8212-2-git-send-email-lixi@ddn.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1428592477-8212-1-git-send-email-lixi@ddn.com> References: <1428592477-8212-1-git-send-email-lixi@ddn.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 | 5 ++++- fs/quota/quotaio_v2.h | 6 ++++-- include/linux/quota.h | 2 ++ include/uapi/linux/quota.h | 6 ++++-- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 8f0acef..a02bb68 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -1159,8 +1159,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; } @@ -1399,6 +1399,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; @@ -1409,6 +1412,10 @@ static void __dquot_initialize(struct inode *inode, int type) */ if (i_dquot(inode)[cnt]) continue; + + if (!sb_has_quota_active(sb, cnt)) + continue; + init_needed = 1; switch (cnt) { @@ -1418,6 +1425,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); } @@ -2161,7 +2174,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; } @@ -2402,8 +2416,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 2aa4151..33b30b1 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -30,7 +30,10 @@ 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))) || 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 50978b7..ba51f7e 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 */ @@ -317,6 +318,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", \ };