[RFC PATCH 8/9] jfs: Write quota through the page cache

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Remove call to jfs_get_block() and use the page cache directly instead
of wrapping it in a buffer_head.

Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx>
---
 fs/jfs/super.c | 71 ++++++++++++++++++++++++++------------------------
 1 file changed, 37 insertions(+), 34 deletions(-)

diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 1e7d117b555d..151c62e2a08f 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -14,7 +14,6 @@
 #include <linux/moduleparam.h>
 #include <linux/kthread.h>
 #include <linux/posix_acl.h>
-#include <linux/buffer_head.h>
 #include <linux/exportfs.h>
 #include <linux/crc32.h>
 #include <linux/slab.h>
@@ -760,54 +759,58 @@ static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data,
 
 /* Write to quotafile */
 static ssize_t jfs_quota_write(struct super_block *sb, int type,
-			       const char *data, size_t len, loff_t off)
+			       const char *data, size_t len, loff_t pos)
 {
 	struct inode *inode = sb_dqopt(sb)->files[type];
-	sector_t blk = off >> sb->s_blocksize_bits;
+	struct address_space *mapping = inode->i_mapping;
 	int err = 0;
-	int offset = off & (sb->s_blocksize - 1);
-	int tocopy;
 	size_t towrite = len;
-	struct buffer_head tmp_bh;
-	struct buffer_head *bh;
 
 	inode_lock(inode);
 	while (towrite > 0) {
-		tocopy = sb->s_blocksize - offset < towrite ?
-				sb->s_blocksize - offset : towrite;
-
-		tmp_bh.b_state = 0;
-		tmp_bh.b_size = i_blocksize(inode);
-		err = jfs_get_block(inode, blk, &tmp_bh, 1);
-		if (err)
-			goto out;
-		if (offset || tocopy != sb->s_blocksize)
-			bh = sb_bread(sb, tmp_bh.b_blocknr);
-		else
-			bh = sb_getblk(sb, tmp_bh.b_blocknr);
-		if (!bh) {
-			err = -EIO;
-			goto out;
+		pgoff_t index = pos / PAGE_SIZE;
+		size_t tocopy = min(PAGE_SIZE - offset_in_page(pos), towrite);
+		struct folio *folio;
+		void *dst;
+
+		if (offset_in_page(pos) ||
+		    (towrite < PAGE_SIZE && (pos + towrite < inode->i_size))) {
+			folio = read_mapping_folio(mapping, index, NULL);
+			if (IS_ERR(folio)) {
+				err = PTR_ERR(folio);
+				break;
+			}
+		} else {
+			folio = __filemap_get_folio(mapping, index,
+					FGP_CREAT|FGP_WRITE, GFP_KERNEL);
+			if (!folio) {
+				err = -ENOMEM;
+				break;
+			}
 		}
-		lock_buffer(bh);
-		memcpy(bh->b_data+offset, data, tocopy);
-		flush_dcache_page(bh->b_page);
-		set_buffer_uptodate(bh);
-		mark_buffer_dirty(bh);
-		unlock_buffer(bh);
-		brelse(bh);
-		offset = 0;
+
+		folio_lock(folio);
+		dst = kmap_local_folio(folio, offset_in_folio(folio, pos));
+		memcpy(dst, data, tocopy);
 		towrite -= tocopy;
 		data += tocopy;
-		blk++;
+		pos += tocopy;
+		if (!towrite && pos >= inode->i_size)
+			memset(dst + tocopy, 0, PAGE_SIZE - tocopy);
+		kunmap_local(dst);
+
+		folio_mark_uptodate(folio);
+		folio_mark_dirty(folio);
+		folio_unlock(folio);
+		folio_put(folio);
 	}
-out:
+
 	if (len == towrite) {
 		inode_unlock(inode);
 		return err;
 	}
-	if (inode->i_size < off+len-towrite)
-		i_size_write(inode, off+len-towrite);
+	if (inode->i_size < pos + len - towrite)
+		i_size_write(inode, pos + len - towrite);
 	inode->i_mtime = inode->i_ctime = current_time(inode);
 	mark_inode_dirty(inode);
 	inode_unlock(inode);
-- 
2.34.1




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux