Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 158533
b: refs/heads/master
c: 38c7304
h: refs/heads/master
i:
  158531: e33cd1c
v: v3
  • Loading branch information
Peter Staubach authored and Trond Myklebust committed Aug 10, 2009
1 parent d9f12aa commit 4cbf1df
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 074cc1deec5dee63fcd5d966b36fa4f3765b50fc
refs/heads/master: 38c73044f5f4da2ef4339319b170e5e19f8dec87
48 changes: 46 additions & 2 deletions trunk/fs/nfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,42 @@ nfs_file_fsync(struct file *file, struct dentry *dentry, int datasync)
return nfs_do_fsync(ctx, inode);
}

/*
* Decide whether a read/modify/write cycle may be more efficient
* then a modify/write/read cycle when writing to a page in the
* page cache.
*
* The modify/write/read cycle may occur if a page is read before
* being completely filled by the writer. In this situation, the
* page must be completely written to stable storage on the server
* before it can be refilled by reading in the page from the server.
* This can lead to expensive, small, FILE_SYNC mode writes being
* done.
*
* It may be more efficient to read the page first if the file is
* open for reading in addition to writing, the page is not marked
* as Uptodate, it is not dirty or waiting to be committed,
* indicating that it was previously allocated and then modified,
* that there were valid bytes of data in that range of the file,
* and that the new data won't completely replace the old data in
* that range of the file.
*/
static int nfs_want_read_modify_write(struct file *file, struct page *page,
loff_t pos, unsigned len)
{
unsigned int pglen = nfs_page_length(page);
unsigned int offset = pos & (PAGE_CACHE_SIZE - 1);
unsigned int end = offset + len;

if ((file->f_mode & FMODE_READ) && /* open for read? */
!PageUptodate(page) && /* Uptodate? */
!PagePrivate(page) && /* i/o request already? */
pglen && /* valid bytes of file? */
(end < pglen || offset)) /* replace all valid bytes? */
return 1;
return 0;
}

/*
* This does the "real" work of the write. We must allocate and lock the
* page to be sent back to the generic routine, which then copies the
Expand All @@ -340,15 +376,16 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
struct page **pagep, void **fsdata)
{
int ret;
pgoff_t index;
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
struct page *page;
index = pos >> PAGE_CACHE_SHIFT;
int once_thru = 0;

dfprintk(PAGECACHE, "NFS: write_begin(%s/%s(%ld), %u@%lld)\n",
file->f_path.dentry->d_parent->d_name.name,
file->f_path.dentry->d_name.name,
mapping->host->i_ino, len, (long long) pos);

start:
/*
* Prevent starvation issues if someone is doing a consistency
* sync-to-disk
Expand All @@ -367,6 +404,13 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
if (ret) {
unlock_page(page);
page_cache_release(page);
} else if (!once_thru &&
nfs_want_read_modify_write(file, page, pos, len)) {
once_thru = 1;
ret = nfs_readpage(file, page);
page_cache_release(page);
if (!ret)
goto start;
}
return ret;
}
Expand Down

0 comments on commit 4cbf1df

Please sign in to comment.