|
|
|
@ -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", |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
if (!PageUptodate(page)) { |
|
|
|
@ -2062,39 +2066,70 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping, |
|
|
|
|
{ |
|
|
|
|
pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
|
|
|
|
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)); |
|
|
|
|
|
|
|
|
|
*pagep = __grab_cache_page(mapping, index); |
|
|
|
|
if (!*pagep) |
|
|
|
|
return -ENOMEM; |
|
|
|
|
|
|
|
|
|
if (PageUptodate(*pagep)) |
|
|
|
|
return 0; |
|
|
|
|
page = __grab_cache_page(mapping, index); |
|
|
|
|
if (!page) { |
|
|
|
|
rc = -ENOMEM; |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* If we are writing a full page it will be up to date,
|
|
|
|
|
no need to read from the server */ |
|
|
|
|
if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE) |
|
|
|
|
return 0; |
|
|
|
|
if (PageUptodate(page)) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
e.g. if we do not have read access to the file |
|
|
|
|
because cifs_write_end will attempt synchronous writes |
|
|
|
|
-- shaggy */ |
|
|
|
|
if ((file->f_flags & O_ACCMODE) != O_WRONLY) { |
|
|
|
|
/*
|
|
|
|
|
* might as well read a page, it is fast enough. If we get |
|
|
|
|
* 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 { |
|
|
|
|
/* we could try using another file handle if there is one -
|
|
|
|
|
but how would we lock it to prevent close of that handle |
|
|
|
|
racing with this read? In any case |
|
|
|
|
this will be written out by write_end so is fine */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
out: |
|
|
|
|
*pagep = page; |
|
|
|
|
return rc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const struct address_space_operations cifs_addr_ops = { |
|
|
|
|