Commit 8e36a5d6 authored by Linus Torvalds's avatar Linus Torvalds
parents 9bd062d9 a98ee8c1
...@@ -1475,7 +1475,11 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, ...@@ -1475,7 +1475,11 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
cFYI(1, ("write_end for page %p from pos %lld with %d bytes", cFYI(1, ("write_end for page %p from pos %lld with %d bytes",
page, pos, copied)); page, pos, copied));
if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE) if (PageChecked(page)) {
if (copied == len)
SetPageUptodate(page);
ClearPageChecked(page);
} else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
SetPageUptodate(page); SetPageUptodate(page);
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
...@@ -2062,39 +2066,70 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping, ...@@ -2062,39 +2066,70 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
{ {
pgoff_t index = pos >> PAGE_CACHE_SHIFT; pgoff_t index = pos >> PAGE_CACHE_SHIFT;
loff_t offset = pos & (PAGE_CACHE_SIZE - 1); loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
loff_t page_start = pos & PAGE_MASK;
loff_t i_size;
struct page *page;
int rc = 0;
cFYI(1, ("write_begin from %lld len %d", (long long)pos, len)); cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
*pagep = __grab_cache_page(mapping, index); page = __grab_cache_page(mapping, index);
if (!*pagep) if (!page) {
return -ENOMEM; rc = -ENOMEM;
goto out;
if (PageUptodate(*pagep)) }
return 0;
/* If we are writing a full page it will be up to date, if (PageUptodate(page))
no need to read from the server */ goto out;
if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE)
return 0;
if ((file->f_flags & O_ACCMODE) != O_WRONLY) { /*
int rc; * If we write a full page it will be up to date, no need to read from
* the server. If the write is short, we'll end up doing a sync write
* instead.
*/
if (len == PAGE_CACHE_SIZE)
goto out;
/* might as well read a page, it is fast enough */ /*
rc = cifs_readpage_worker(file, *pagep, &offset); * optimize away the read when we have an oplock, and we're not
* expecting to use any of the data we'd be reading in. That
* is, when the page lies beyond the EOF, or straddles the EOF
* and the write will cover all of the existing data.
*/
if (CIFS_I(mapping->host)->clientCanCacheRead) {
i_size = i_size_read(mapping->host);
if (page_start >= i_size ||
(offset == 0 && (pos + len) >= i_size)) {
zero_user_segments(page, 0, offset,
offset + len,
PAGE_CACHE_SIZE);
/*
* PageChecked means that the parts of the page
* to which we're not writing are considered up
* to date. Once the data is copied to the
* page, it can be set uptodate.
*/
SetPageChecked(page);
goto out;
}
}
/* we do not need to pass errors back if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
e.g. if we do not have read access to the file /*
because cifs_write_end will attempt synchronous writes * might as well read a page, it is fast enough. If we get
-- shaggy */ * an error, we don't need to return it. cifs_write_end will
* do a sync write instead since PG_uptodate isn't set.
*/
cifs_readpage_worker(file, page, &page_start);
} else { } else {
/* we could try using another file handle if there is one - /* we could try using another file handle if there is one -
but how would we lock it to prevent close of that handle but how would we lock it to prevent close of that handle
racing with this read? In any case racing with this read? In any case
this will be written out by write_end so is fine */ this will be written out by write_end so is fine */
} }
out:
return 0; *pagep = page;
return rc;
} }
const struct address_space_operations cifs_addr_ops = { const struct address_space_operations cifs_addr_ops = {
......
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