[patch 21/22] fuse: limit dirty pages

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

 



From: Miklos Szeredi <mszeredi@xxxxxxx>

Add a per-filesystem limit for the number of dirty pages.  If half the
limit is reached, background writeback is started.  If the limit is
reached, then start some writeback and wait until the the number goes
below the limit again.

The dirty limit is currently hardcoded at 1MB.  This limiting is
necessary, so that buggy or unfriendly filesystems don't hurt system
performance too badly.

Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxx>
---

Index: linux/fs/fuse/file.c
===================================================================
--- linux.orig/fs/fuse/file.c	2007-02-27 14:41:12.000000000 +0100
+++ linux/fs/fuse/file.c	2007-02-27 14:41:13.000000000 +0100
@@ -780,10 +780,35 @@ static void fuse_vma_close(struct vm_are
 	filemap_write_and_wait(vma->vm_file->f_mapping);
 }
 
+static int fuse_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	long nr_dirty = atomic_long_read(&fc->bdi.nr_dirty);
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_NONE,
+		.nr_to_write = FUSE_MAX_PAGES_PER_REQ,
+		.range_cyclic = 1,
+	};
+
+	while (nr_dirty >= fc->max_dirty) {
+		sync_sb(inode->i_sb, &wbc);
+		congestion_wait(WRITE, HZ / 10);
+		nr_dirty = atomic_long_read(&fc->bdi.nr_dirty);
+		wbc.nr_to_write = FUSE_MAX_PAGES_PER_REQ;
+	}
+	if (nr_dirty >= fc->max_dirty / 2) {
+		wbc.nonblocking = 1;
+		sync_sb(inode->i_sb, &wbc);
+	}
+	return 0;
+}
+
 static struct vm_operations_struct fuse_file_vm_ops = {
 	.close		= fuse_vma_close,
 	.nopage		= filemap_nopage,
 	.populate	= filemap_populate,
+	.page_mkwrite	= fuse_page_mkwrite,
 };
 
 static void fuse_send_writepages(struct fuse_req *req, struct inode *inode)
Index: linux/fs/fuse/fuse_i.h
===================================================================
--- linux.orig/fs/fuse/fuse_i.h	2007-02-27 14:41:13.000000000 +0100
+++ linux/fs/fuse/fuse_i.h	2007-02-27 14:41:13.000000000 +0100
@@ -397,6 +397,9 @@ struct fuse_conn {
 
 	/** Reserved request for the DESTROY message */
 	struct fuse_req *destroy_req;
+
+	/** Maximum number of dirty pages in this fs */
+	unsigned long max_dirty;
 };
 
 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
Index: linux/fs/fuse/inode.c
===================================================================
--- linux.orig/fs/fuse/inode.c	2007-02-27 14:41:11.000000000 +0100
+++ linux/fs/fuse/inode.c	2007-02-27 14:41:13.000000000 +0100
@@ -425,6 +425,7 @@ static struct fuse_conn *new_conn(void)
 		fc->bdi.unplug_io_fn = default_unplug_io_fn;
 		fc->reqctr = 0;
 		fc->blocked = 1;
+		fc->max_dirty = (1024 * 1024) / PAGE_CACHE_SIZE;
 		get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
 	}
 	return fc;

--
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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