lkml.org 
[lkml]   [2013]   [Jan]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
Subject[PATCH] fix multiple mark_page_accessed called when sequentially writing a file with blocksize less than PAGE_SIZE ,which might pollute the LRU.
From
sequential write to a file with blocksize less than PAGE_SIZE  will call
mark_page_accessed multiple times,

if (!pagevec_space(pvec))
__pagevec_lru_add(pvec, lru);
it seems this trick fix this problem,but not quite thoroughly. there's a chance
that when another page was added to the pvec before the 14th page was
secondly mark_page_accesseded, then the 14th page was still active.



diff --git a/fs/open.c b/fs/open.c
index 9b33c0c..a418419 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -674,6 +674,13 @@ int open_check_o_direct(struct file *f)
return 0;
}

+
+static void
+file_w_state_init(struct file_w_state *wstat)
+{
+ wstat->prev_w_pos=-1;
+}
+
static int do_dentry_open(struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
@@ -730,6 +737,7 @@ static int do_dentry_open(struct file *f,
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
+ file_w_state_init(&f->f_wstat);

return 0;

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7617ee0..b90d3ff 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -746,6 +746,10 @@ struct file_ra_state {
loff_t prev_pos; /* Cache last read() position */
};

+struct file_w_state {
+ loff_t prev_w_pos;
+};
+
/*
* Check if @index falls in the readahead windows.
*/
@@ -787,6 +791,7 @@ struct file {
struct fown_struct f_owner;
const struct cred *f_cred;
struct file_ra_state f_ra;
+ struct file_w_state f_wstat;

u64 f_version;
#ifdef CONFIG_SECURITY
diff --git a/mm/filemap.c b/mm/filemap.c
index 83efee7..ea144a9 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2287,6 +2287,9 @@ static ssize_t generic_perform_write(struct file *file,
long status = 0;
ssize_t written = 0;
unsigned int flags = 0;
+ unsigned long prev_pos=file->f_wstat.prev_w_pos;
+ unsigned long prev_off=(prev_pos & (PAGE_CACHE_SIZE -1));
+ pgoff_t prev_index=(prev_pos >> PAGE_CACHE_SHIFT);

/*
* Copies from kernel address space cannot fail (NFSD is a big user).
@@ -2296,12 +2299,14 @@ static ssize_t generic_perform_write(struct file *file,

do {
struct page *page;
+ pgoff_t index;
unsigned long offset; /* Offset into pagecache page */
unsigned long bytes; /* Bytes to write to page */
size_t copied; /* Bytes copied from user */
void *fsdata;

offset = (pos & (PAGE_CACHE_SIZE - 1));
+ index = pos >> PAGE_CACHE_SHIFT;
bytes = min_t(unsigned long, PAGE_CACHE_SIZE - offset,
iov_iter_count(i));

@@ -2334,7 +2339,8 @@ again:
pagefault_enable();
flush_dcache_page(page);

- mark_page_accessed(page);
+ if (index != prev_index || offset != prev_off)
+ mark_page_accessed(page);
status = a_ops->write_end(file, mapping, pos, bytes, copied,
page, fsdata);
if (unlikely(status < 0))
@@ -2359,6 +2365,8 @@ again:
}
pos += copied;
written += copied;
+ prev_index = index;
+ prev_off = offset;

balance_dirty_pages_ratelimited(mapping);
if (fatal_signal_pending(current)) {
@@ -2367,6 +2375,7 @@ again:
}
} while (iov_iter_count(i));

+ file->f_wstat.prev_w_pos=pos;
return written ? written : status;
}

\
 
 \ /
  Last update: 2013-01-08 15:21    [W:0.026 / U:0.412 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site