From: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> To: <viro@ZenIV.linux.org.uk>, <jack@suse.cz>, <dedekind1@gmail.com>, <richard.weinberger@gmail.com> Cc: linux-fsdevel@vger.kernel.org, Dongsheng Yang <yangds.fnst@cn.fujitsu.com>, linux-mtd@lists.infradead.org Subject: [PATCH v3 22/39] ubifs: implement IO functions for quota files Date: Tue, 15 Sep 2015 17:02:17 +0800 [thread overview] Message-ID: <1442307754-13233-23-git-send-email-yangds.fnst@cn.fujitsu.com> (raw) In-Reply-To: <1442307754-13233-1-git-send-email-yangds.fnst@cn.fujitsu.com> We have to implement 3 functions to support quota in ubifs: ubifs_quota_read(), ubifs_quota_write() and ubifs_get_quotas() ubifs_quota_read(): callback to read quota file. ubifs_quota_write(): callback to write data to quota file. ubifs_get_quotas(): callback to get quota instance for inode. Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> --- fs/ubifs/super.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 791bed47..647677d 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -37,6 +37,7 @@ #include <linux/math64.h> #include <linux/writeback.h> #include <linux/cdev.h> +#include <linux/quotaops.h> #include "ubifs.h" /* @@ -911,6 +912,158 @@ static int check_volume_empty(struct ubifs_info *c) return 0; } +#ifdef CONFIG_QUOTA +static ssize_t ubifs_quota_read(struct super_block *sb, int type, char *data, + size_t len, loff_t off) +{ + struct inode *inode = sb_dqopt(sb)->files[type]; + unsigned long block = off >> UBIFS_BLOCK_SHIFT; + int offset = off & (sb->s_blocksize - 1); + int tocopy = 0; + size_t toread; + char *block_buf; + struct ubifs_data_node *dn; + int ret, err = 0; + loff_t i_size = i_size_read(inode); + + if (off > i_size) + return 0; + if (off + len > i_size) + len = i_size - off; + toread = len; + + dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS); + if (!dn) { + err = -ENOMEM; + goto out; + } + + block_buf = kmalloc(sb->s_blocksize, GFP_NOFS); + if (!block_buf) { + err = -ENOMEM; + goto free_dn; + } + + while (toread > 0) { + tocopy = sb->s_blocksize - offset < toread ? + sb->s_blocksize - offset : toread; + + ret = ubifs_read_block(inode, block_buf, block, dn); + if (ret) { + if (ret != -ENOENT) { + err = ret; + goto free_buf; + } + memset(block_buf, 0, sb->s_blocksize); + } + memcpy(data, block_buf + offset, tocopy); + offset = 0; + block++;; + toread -= tocopy; + data += tocopy; + } +free_buf: + kfree(block_buf); +free_dn: + kfree(dn); +out: + if (!err) + return len; + return err; +} + +static ssize_t ubifs_quota_write(struct super_block *sb, int type, + const char *data, size_t len, loff_t off) +{ + struct inode *inode = sb_dqopt(sb)->files[type]; + unsigned long block = off >> UBIFS_BLOCK_SHIFT; + struct ubifs_info *c = inode->i_sb->s_fs_info; + int offset = off & (sb->s_blocksize - 1); + union ubifs_key key; + int tocopy = 0; + size_t towrite = len; + int ret, err = 0; + struct ubifs_budget_req req = {}; + struct ubifs_data_node *dn; + char *block_buf; + + /* + * Since we budget at most two blocks (one for dirtied block and + * one for new block) here, then error out if the length out of + * what allowed. NOTE, the writing length from quota should never + * be larger than what we allowed here. Ext3 and Ext4 are also + * limiting more strict for the len to one block size. + */ + if (sb->s_blocksize + (sb->s_blocksize - offset) < len) { + ubifs_err(c, "Quota write (off=%llu, len=%llu)" + " cancelled because length is too large", + (unsigned long long)off, (unsigned long long)len); + return -EIO; + } + + if ((offset + len) > sb->s_blocksize) + req.new_block = 1; + if (offset) + req.dirtied_block = 1; + + err = ubifs_budget_space(c, &req); + if (err) + goto out; + + dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS); + if (!dn) { + err = -ENOMEM; + goto release_budget; + } + + block_buf = kmalloc(sb->s_blocksize, GFP_NOFS); + if (!block_buf) { + err = -ENOMEM; + goto free_dn; + } + + while (towrite > 0) { + tocopy = sb->s_blocksize - offset < towrite ? + sb->s_blocksize - offset : towrite; + + if (offset || tocopy != sb->s_blocksize) { + ret = ubifs_read_block(inode, block_buf, block, dn); + if (ret) { + if (ret != -ENOENT) { + err = ret; + goto free_buf; + } + memset(block_buf, 0, sb->s_blocksize); + } + } + memcpy(block_buf + offset, data, tocopy); + data_key_init(c, &key, inode->i_ino, block); + err = ubifs_jnl_write_data(c, inode, &key, block_buf, sb->s_blocksize); + if (err) + goto free_buf; + offset = 0; + block++;; + towrite -= tocopy; + data += tocopy; + } +free_buf: + kfree(block_buf); +free_dn: + kfree(dn); +release_budget: + ubifs_release_budget(c, &req); +out: + if (!err) + return len; + return err; +} + +static struct dquot **ubifs_get_dquots(struct inode *inode) +{ + return ubifs_inode(inode)->i_dquot; +} +#endif + /* * UBIFS mount options. * @@ -1887,6 +2040,11 @@ const struct super_operations ubifs_super_operations = { .remount_fs = ubifs_remount_fs, .show_options = ubifs_show_options, .sync_fs = ubifs_sync_fs, +#ifdef CONFIG_QUOTA + .quota_read = ubifs_quota_read, + .quota_write = ubifs_quota_write, + .get_dquots = ubifs_get_dquots, +#endif }; /** -- 1.8.4.2 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/
WARNING: multiple messages have this Message-ID (diff)
From: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> To: <viro@ZenIV.linux.org.uk>, <jack@suse.cz>, <dedekind1@gmail.com>, <richard.weinberger@gmail.com> Cc: <linux-mtd@lists.infradead.org>, <linux-fsdevel@vger.kernel.org>, Dongsheng Yang <yangds.fnst@cn.fujitsu.com> Subject: [PATCH v3 22/39] ubifs: implement IO functions for quota files Date: Tue, 15 Sep 2015 17:02:17 +0800 [thread overview] Message-ID: <1442307754-13233-23-git-send-email-yangds.fnst@cn.fujitsu.com> (raw) In-Reply-To: <1442307754-13233-1-git-send-email-yangds.fnst@cn.fujitsu.com> We have to implement 3 functions to support quota in ubifs: ubifs_quota_read(), ubifs_quota_write() and ubifs_get_quotas() ubifs_quota_read(): callback to read quota file. ubifs_quota_write(): callback to write data to quota file. ubifs_get_quotas(): callback to get quota instance for inode. Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> --- fs/ubifs/super.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 791bed47..647677d 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -37,6 +37,7 @@ #include <linux/math64.h> #include <linux/writeback.h> #include <linux/cdev.h> +#include <linux/quotaops.h> #include "ubifs.h" /* @@ -911,6 +912,158 @@ static int check_volume_empty(struct ubifs_info *c) return 0; } +#ifdef CONFIG_QUOTA +static ssize_t ubifs_quota_read(struct super_block *sb, int type, char *data, + size_t len, loff_t off) +{ + struct inode *inode = sb_dqopt(sb)->files[type]; + unsigned long block = off >> UBIFS_BLOCK_SHIFT; + int offset = off & (sb->s_blocksize - 1); + int tocopy = 0; + size_t toread; + char *block_buf; + struct ubifs_data_node *dn; + int ret, err = 0; + loff_t i_size = i_size_read(inode); + + if (off > i_size) + return 0; + if (off + len > i_size) + len = i_size - off; + toread = len; + + dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS); + if (!dn) { + err = -ENOMEM; + goto out; + } + + block_buf = kmalloc(sb->s_blocksize, GFP_NOFS); + if (!block_buf) { + err = -ENOMEM; + goto free_dn; + } + + while (toread > 0) { + tocopy = sb->s_blocksize - offset < toread ? + sb->s_blocksize - offset : toread; + + ret = ubifs_read_block(inode, block_buf, block, dn); + if (ret) { + if (ret != -ENOENT) { + err = ret; + goto free_buf; + } + memset(block_buf, 0, sb->s_blocksize); + } + memcpy(data, block_buf + offset, tocopy); + offset = 0; + block++;; + toread -= tocopy; + data += tocopy; + } +free_buf: + kfree(block_buf); +free_dn: + kfree(dn); +out: + if (!err) + return len; + return err; +} + +static ssize_t ubifs_quota_write(struct super_block *sb, int type, + const char *data, size_t len, loff_t off) +{ + struct inode *inode = sb_dqopt(sb)->files[type]; + unsigned long block = off >> UBIFS_BLOCK_SHIFT; + struct ubifs_info *c = inode->i_sb->s_fs_info; + int offset = off & (sb->s_blocksize - 1); + union ubifs_key key; + int tocopy = 0; + size_t towrite = len; + int ret, err = 0; + struct ubifs_budget_req req = {}; + struct ubifs_data_node *dn; + char *block_buf; + + /* + * Since we budget at most two blocks (one for dirtied block and + * one for new block) here, then error out if the length out of + * what allowed. NOTE, the writing length from quota should never + * be larger than what we allowed here. Ext3 and Ext4 are also + * limiting more strict for the len to one block size. + */ + if (sb->s_blocksize + (sb->s_blocksize - offset) < len) { + ubifs_err(c, "Quota write (off=%llu, len=%llu)" + " cancelled because length is too large", + (unsigned long long)off, (unsigned long long)len); + return -EIO; + } + + if ((offset + len) > sb->s_blocksize) + req.new_block = 1; + if (offset) + req.dirtied_block = 1; + + err = ubifs_budget_space(c, &req); + if (err) + goto out; + + dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS); + if (!dn) { + err = -ENOMEM; + goto release_budget; + } + + block_buf = kmalloc(sb->s_blocksize, GFP_NOFS); + if (!block_buf) { + err = -ENOMEM; + goto free_dn; + } + + while (towrite > 0) { + tocopy = sb->s_blocksize - offset < towrite ? + sb->s_blocksize - offset : towrite; + + if (offset || tocopy != sb->s_blocksize) { + ret = ubifs_read_block(inode, block_buf, block, dn); + if (ret) { + if (ret != -ENOENT) { + err = ret; + goto free_buf; + } + memset(block_buf, 0, sb->s_blocksize); + } + } + memcpy(block_buf + offset, data, tocopy); + data_key_init(c, &key, inode->i_ino, block); + err = ubifs_jnl_write_data(c, inode, &key, block_buf, sb->s_blocksize); + if (err) + goto free_buf; + offset = 0; + block++;; + towrite -= tocopy; + data += tocopy; + } +free_buf: + kfree(block_buf); +free_dn: + kfree(dn); +release_budget: + ubifs_release_budget(c, &req); +out: + if (!err) + return len; + return err; +} + +static struct dquot **ubifs_get_dquots(struct inode *inode) +{ + return ubifs_inode(inode)->i_dquot; +} +#endif + /* * UBIFS mount options. * @@ -1887,6 +2040,11 @@ const struct super_operations ubifs_super_operations = { .remount_fs = ubifs_remount_fs, .show_options = ubifs_show_options, .sync_fs = ubifs_sync_fs, +#ifdef CONFIG_QUOTA + .quota_read = ubifs_quota_read, + .quota_write = ubifs_quota_write, + .get_dquots = ubifs_get_dquots, +#endif }; /** -- 1.8.4.2
next prev parent reply other threads:[~2015-09-15 9:02 UTC|newest] Thread overview: 107+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-09-15 9:01 [PATCH v3 00/39] Add quota supporting in ubifs Dongsheng Yang 2015-09-15 9:01 ` Dongsheng Yang 2015-09-15 9:01 ` [PATCH v3 01/39] fs: introduce a ->s_cdev field into struct super_block Dongsheng Yang 2015-09-15 9:01 ` Dongsheng Yang 2015-10-04 6:31 ` Christoph Hellwig 2015-10-05 8:36 ` Jan Kara 2015-09-15 9:01 ` [PATCH v3 02/39] fs: cleanup: remove the blank line before EXPORT_SYMBOL Dongsheng Yang 2015-09-15 9:01 ` Dongsheng Yang 2015-09-15 9:01 ` [PATCH v3 03/39] fs: super: cleanup: make the comment of each function aligned Dongsheng Yang 2015-09-15 9:01 ` Dongsheng Yang 2015-09-15 9:01 ` [PATCH v3 04/39] fs: super: consolidate the get_super class functions Dongsheng Yang 2015-09-15 9:01 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 05/39] fs: super: introduce a get_super_cdev to get super by a cdev reference Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-10-04 6:32 ` Christoph Hellwig 2015-09-15 9:02 ` [PATCH v3 06/39] fs: super: introduce a get_super_cdev_thawed to get sb by " Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 21:24 ` Jan Kara 2015-09-15 9:02 ` [PATCH v3 07/39] fs: char_dev: introduce cd_acquire function to acquire cdev Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-16 8:16 ` Jan Kara 2015-09-17 3:30 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 08/39] fs: introduce a __lookup_dev for internal using Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 09/39] fs: char_dev: introduce lookup_cdev to get cdev by pathname Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 10/39] fs: dquot: skip invalidate_bdev if bdev is NULL Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 11/39] fs: quota: replace opened calling of ->sync_fs with sync_filesystem Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-16 10:14 ` Jan Kara 2015-09-17 6:28 ` Dongsheng Yang 2015-09-17 6:28 ` Dongsheng Yang 2015-09-17 11:05 ` Jan Kara 2015-09-18 5:49 ` Dongsheng Yang 2015-09-18 9:00 ` Jan Kara 2015-09-21 4:31 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 12/39] fs: quota: make quota support fs which is running on char dev Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 13/39] fs: introduce a get_qsize() to inode_operations Dongsheng Yang 2015-10-04 6:33 ` Christoph Hellwig 2015-10-05 8:01 ` Jan Kara 2015-09-15 9:02 ` [PATCH v3 14/39] fs: quota: restore i_flags of quota files in dquot_disable Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 15/39] fs: quota: introduce a callback of restore_iflags to quotactl_ops Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-16 9:47 ` Jan Kara 2015-09-15 9:02 ` [PATCH v3 16/39] ubi: introduce a interface to get cdev in ubi_volume Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 17/39] ubifs: extend budget for blocks Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 18/39] ubifs: fill sb->s_cdev in ubifs_fill_super() Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 19/39] ubifs: fill ->s_dev in ubifs_fill_super Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 20/39] ubifs: export read_block() from file.c Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 21/39] ubifs: introduce i_dquot to ubifs_inode Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang [this message] 2015-09-15 9:02 ` [PATCH v3 22/39] ubifs: implement IO functions for quota files Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 23/39] ubifs: disable quota in ubifs_put_super Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 24/39] ubifs: write quota back in ubifs_sync Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 25/39] ubifs: set/clear MS_RDONLY properly in ubifs_remount Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 26/39] ubifs: suspend & resume quota " Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 27/39] ubifs: check inode with NULL before using it Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 28/39] ubifs: record quota information about inode in ubifs_new_inode Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:35 ` Sheng Yong 2015-09-16 1:46 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 29/39] ubifs: free quota inode information in ubifs_evict_inode Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 30/39] ubifs: alloc quota space in ubifs writing path Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 31/39] ubifs: free quota space in do_truncation Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 32/39] ubifs: free quota space when deleting a file Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 33/39] ubifs: adapt quota space informatin in do_setattr Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 34/39] ubifs: transfer quota information in changing owner or group Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 35/39] ubifs: write inode in ubifs_quota_write if we are appending Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 36/39] ubifs: implement ubifs_get_qsize to get quota size in ubifs Dongsheng Yang 2015-09-16 10:00 ` Jan Kara 2015-09-17 7:23 ` Dongsheng Yang 2015-09-17 7:23 ` Dongsheng Yang 2015-09-17 12:00 ` Jan Kara 2015-09-18 6:14 ` Dongsheng Yang 2015-09-18 11:20 ` Jan Kara 2015-09-21 4:35 ` Dongsheng Yang 2015-09-21 9:13 ` Jan Kara 2015-09-21 9:16 ` Dongsheng Yang 2015-09-21 9:44 ` Jan Kara 2015-09-21 11:02 ` Dongsheng Yang 2015-09-23 7:42 ` Jan Kara 2015-09-24 0:50 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 37/39] ubifs: implement ubifs_restore_iflags for quotactl_operations Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 38/39] ubifs: fill the quota related fields in ubifs_fill_super Dongsheng Yang 2015-09-15 9:02 ` [PATCH v3 39/39] ubifs: introduce quota related mount options Dongsheng Yang 2015-09-15 9:02 ` Dongsheng Yang 2015-09-15 9:36 ` Sheng Yong 2015-09-16 1:48 ` Dongsheng Yang 2015-10-03 18:57 ` [PATCH v3 00/39] Add quota supporting in ubifs Richard Weinberger 2015-10-04 2:32 ` Dongsheng Yang
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1442307754-13233-23-git-send-email-yangds.fnst@cn.fujitsu.com \ --to=yangds.fnst@cn.fujitsu.com \ --cc=dedekind1@gmail.com \ --cc=jack@suse.cz \ --cc=linux-fsdevel@vger.kernel.org \ --cc=linux-mtd@lists.infradead.org \ --cc=richard.weinberger@gmail.com \ --cc=viro@ZenIV.linux.org.uk \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.