From: Li Xi Subject: Re: [PATCH v2 4/4] quota: add project quota support Date: Sat, 9 Aug 2014 00:45:00 +0800 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 To: linux-fsdevel@vger.kernel.org, Ext4 Developers List , viro@zeniv.linux.org.uk, hch@infradead.org, Jan Kara Return-path: Received: from mail-ie0-f173.google.com ([209.85.223.173]:37204 "EHLO mail-ie0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755887AbaHHQpB (ORCPT ); Fri, 8 Aug 2014 12:45:01 -0400 Sender: linux-ext4-owner@vger.kernel.org List-ID: Adds ioctl interface support for ext4 project This patch adds ioctl interface for setting/getting project of ext4. Signed-off-by: Li Xi ddn.com> Signed-off-by: Dmitry Monakhov --- Index: linux.git/fs/ext4/ext4.h =================================================================== --- linux.git.orig/fs/ext4/ext4.h +++ linux.git/fs/ext4/ext4.h @@ -615,6 +615,8 @@ enum { #define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64) #define EXT4_IOC_SWAP_BOOT _IO('f', 17) #define EXT4_IOC_PRECACHE_EXTENTS _IO('f', 18) +#define EXT4_IOC_GETPROJECT _IOR('f', 19, long) +#define EXT4_IOC_SETPROJECT _IOW('f', 20, long) #if defined(__KERNEL__) && defined(CONFIG_COMPAT) /* Index: linux.git/Documentation/filesystems/ext4.txt =================================================================== --- linux.git.orig/Documentation/filesystems/ext4.txt +++ linux.git/Documentation/filesystems/ext4.txt @@ -609,6 +609,10 @@ EXT4_IOC_SWAP_BOOT Swap i_blocks a The data blocks of the previous boot loader will be associated with the given inode. + EXT4_IOC_GETPROJECT Get project ID associated with inode. + + EXT4_IOC_SETPROJECT Set Project ID associated with inode. + .............................................................................. References Index: linux.git/fs/ext4/ioctl.c =================================================================== --- linux.git.orig/fs/ext4/ioctl.c +++ linux.git/fs/ext4/ioctl.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include "ext4_jbd2.h" #include "ext4.h" @@ -611,6 +613,104 @@ resizefs_out: case EXT4_IOC_PRECACHE_EXTENTS: return ext4_ext_precache(inode); + case EXT4_IOC_GETPROJECT: + { +#ifdef CONFIG_QUOTA_PROJECT + __u32 projid; + + if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, + EXT4_FEATURE_RO_COMPAT_PROJECT)) { + ext4_msg(sb, KERN_ERR, + "get project not supported without " + "project feature"); + return -ENOTSUPP; + } + + projid = (__u32)from_kprojid(&init_user_ns, + EXT4_I(inode)->i_projid); + return put_user(projid, (__u32 __user *) arg); +#else + ext4_msg(sb, KERN_ERR, + "get project not supported without " + "CONFIG_QUOTA_PROJECT"); + return -ENOTSUPP; +#endif + } + case EXT4_IOC_SETPROJECT: + { +#ifdef CONFIG_QUOTA_PROJECT + __u32 projid; + int err; + handle_t *handle; + kprojid_t kprojid; + + struct dquot *transfer_to[MAXQUOTAS] = { }; + + if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, + EXT4_FEATURE_RO_COMPAT_PROJECT)) { + ext4_msg(sb, KERN_ERR, + "set project not supported without " + "project feature"); + return -ENOTSUPP; + } + + /* Make sure caller can change project. */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (get_user(projid, (__u32 __user *) arg)) + return -EFAULT; + + kprojid = make_kprojid(&init_user_ns, (projid_t)projid); + + if (projid_eq(kprojid, EXT4_I(inode)->i_projid)) + return 0; + + err = mnt_want_write_file(filp); + if (err) + return err; + + err = -EPERM; + mutex_lock(&inode->i_mutex); + /* Is it quota file? Do not allow user to mess with it */ + if (IS_NOQUOTA(inode)) + goto project_out; + + dquot_initialize(inode); + + handle = ext4_journal_start(inode, EXT4_HT_QUOTA, + EXT4_QUOTA_INIT_BLOCKS(sb) + + EXT4_QUOTA_DEL_BLOCKS(sb) + 3); + if (IS_ERR(handle)) { + err = PTR_ERR(handle); + goto project_out; + } + + transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid)); + if (!transfer_to[PRJQUOTA]) { + err = -ESRCH; + goto project_stop; + } + err = __dquot_transfer(inode, transfer_to); + dqput(transfer_to[PRJQUOTA]); + if (err) + goto project_stop; + + EXT4_I(inode)->i_projid = kprojid; + err = ext4_mark_inode_dirty(handle, inode); +project_stop: + ext4_journal_stop(handle); +project_out: + mutex_unlock(&inode->i_mutex); + mnt_drop_write_file(filp); + return err; +#else + ext4_msg(sb, KERN_ERR, + "set project not supported without " + "CONFIG_QUOTA_PROJECT"); + return -ENOTSUPP; +#endif + } default: return -ENOTTY; }