Commit df43f015 authored by Trond Myklebust's avatar Trond Myklebust

[PATCH] Add nfs_writepages & backing_dev...

The following patch adds a simple ->writepages method that interprets
the extra information passed down in Andrew's writeback_control
structure, and translates it into nfs-speak.

It also adds a backing_dev_info structure that scales the readahead in
terms of the rsize. Maximum readahead is still 128k if you use 32k
rsize, but it is scaled down to 4k if you use 1k rsize.
parent 6a3a5e24
...@@ -169,6 +169,7 @@ struct address_space_operations nfs_file_aops = { ...@@ -169,6 +169,7 @@ struct address_space_operations nfs_file_aops = {
.readpage = nfs_readpage, .readpage = nfs_readpage,
.readpages = nfs_readpages, .readpages = nfs_readpages,
.writepage = nfs_writepage, .writepage = nfs_writepage,
.writepages = nfs_writepages,
.prepare_write = nfs_prepare_write, .prepare_write = nfs_prepare_write,
.commit_write = nfs_commit_write, .commit_write = nfs_commit_write,
#ifdef CONFIG_NFS_DIRECTIO #ifdef CONFIG_NFS_DIRECTIO
......
...@@ -106,7 +106,7 @@ nfs_write_inode(struct inode *inode, int sync) ...@@ -106,7 +106,7 @@ nfs_write_inode(struct inode *inode, int sync)
{ {
int flags = sync ? FLUSH_WAIT : 0; int flags = sync ? FLUSH_WAIT : 0;
nfs_sync_file(inode, NULL, 0, 0, flags); nfs_commit_file(inode, NULL, 0, 0, flags);
} }
static void static void
...@@ -327,6 +327,7 @@ int nfs_sb_init(struct super_block *sb) ...@@ -327,6 +327,7 @@ int nfs_sb_init(struct super_block *sb)
server->acdirmin = server->acdirmax = 0; server->acdirmin = server->acdirmax = 0;
sb->s_flags |= MS_SYNCHRONOUS; sb->s_flags |= MS_SYNCHRONOUS;
} }
server->backing_dev_info.ra_pages = server->rpages << 2;
sb->s_maxbytes = fsinfo.maxfilesize; sb->s_maxbytes = fsinfo.maxfilesize;
if (sb->s_maxbytes > MAX_LFS_FILESIZE) if (sb->s_maxbytes > MAX_LFS_FILESIZE)
...@@ -696,6 +697,7 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) ...@@ -696,6 +697,7 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
inode->i_fop = &nfs_file_operations; inode->i_fop = &nfs_file_operations;
inode->i_data.a_ops = &nfs_file_aops; inode->i_data.a_ops = &nfs_file_aops;
inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info;
} else if (S_ISDIR(inode->i_mode)) { } else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &nfs_dir_inode_operations; inode->i_op = &nfs_dir_inode_operations;
inode->i_fop = &nfs_dir_operations; inode->i_fop = &nfs_dir_operations;
......
...@@ -52,6 +52,8 @@ ...@@ -52,6 +52,8 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/mpage.h>
#include <linux/writeback.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
...@@ -277,6 +279,25 @@ region_locked(struct inode *inode, struct nfs_page *req) ...@@ -277,6 +279,25 @@ region_locked(struct inode *inode, struct nfs_page *req)
return 0; return 0;
} }
int
nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
{
struct inode *inode = mapping->host;
int is_sync = !wbc->nonblocking;
int err;
err = generic_writepages(mapping, wbc);
if (err)
goto out;
err = nfs_flush_file(inode, NULL, 0, 0, 0);
if (err < 0)
goto out;
if (is_sync)
err = nfs_wb_all(inode);
out:
return err;
}
/* /*
* Insert a write request into an inode * Insert a write request into an inode
*/ */
...@@ -850,6 +871,7 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data, int how) ...@@ -850,6 +871,7 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data, int how)
req = nfs_list_entry(head->next); req = nfs_list_entry(head->next);
nfs_list_remove_request(req); nfs_list_remove_request(req);
nfs_list_add_request(req, &data->pages); nfs_list_add_request(req, &data->pages);
SetPageWriteback(req->wb_page);
*pages++ = req->wb_page; *pages++ = req->wb_page;
count += req->wb_bytes; count += req->wb_bytes;
} }
...@@ -1005,10 +1027,12 @@ nfs_writeback_done(struct rpc_task *task, int stable, ...@@ -1005,10 +1027,12 @@ nfs_writeback_done(struct rpc_task *task, int stable,
SetPageError(page); SetPageError(page);
if (req->wb_file) if (req->wb_file)
req->wb_file->f_error = task->tk_status; req->wb_file->f_error = task->tk_status;
end_page_writeback(page);
nfs_inode_remove_request(req); nfs_inode_remove_request(req);
dprintk(", error = %d\n", task->tk_status); dprintk(", error = %d\n", task->tk_status);
goto next; goto next;
} }
end_page_writeback(page);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (stable != NFS_UNSTABLE || data->verf.committed == NFS_FILE_SYNC) { if (stable != NFS_UNSTABLE || data->verf.committed == NFS_FILE_SYNC) {
......
...@@ -319,6 +319,7 @@ extern void nfs_complete_unlink(struct dentry *); ...@@ -319,6 +319,7 @@ extern void nfs_complete_unlink(struct dentry *);
* linux/fs/nfs/write.c * linux/fs/nfs/write.c
*/ */
extern int nfs_writepage(struct page *); extern int nfs_writepage(struct page *);
extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern int nfs_flush_incompatible(struct file *file, struct page *page); extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
extern void nfs_writeback_done(struct rpc_task *task, int stable, extern void nfs_writeback_done(struct rpc_task *task, int stable,
...@@ -343,6 +344,13 @@ extern int nfs_commit_file(struct inode *, struct file *, unsigned long, unsign ...@@ -343,6 +344,13 @@ extern int nfs_commit_file(struct inode *, struct file *, unsigned long, unsign
extern int nfs_commit_list(struct list_head *, int); extern int nfs_commit_list(struct list_head *, int);
extern int nfs_scan_lru_commit(struct nfs_server *, struct list_head *); extern int nfs_scan_lru_commit(struct nfs_server *, struct list_head *);
extern int nfs_scan_lru_commit_timeout(struct nfs_server *, struct list_head *); extern int nfs_scan_lru_commit_timeout(struct nfs_server *, struct list_head *);
#else
static inline int
nfs_commit_file(struct inode *inode, struct file *file, unsigned long offset,
unsigned int len, int flags)
{
return 0;
}
#endif #endif
static inline int static inline int
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _NFS_FS_SB #define _NFS_FS_SB
#include <linux/list.h> #include <linux/list.h>
#include <linux/backing-dev.h>
/* /*
* NFS client parameters stored in the superblock. * NFS client parameters stored in the superblock.
...@@ -9,6 +10,7 @@ ...@@ -9,6 +10,7 @@
struct nfs_server { struct nfs_server {
struct rpc_clnt * client; /* RPC client handle */ struct rpc_clnt * client; /* RPC client handle */
struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */ struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */
struct backing_dev_info backing_dev_info;
int flags; /* various flags */ int flags; /* various flags */
unsigned int caps; /* server capabilities */ unsigned int caps; /* server capabilities */
unsigned int rsize; /* read size */ unsigned int rsize; /* read size */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment