Commit 916a3b0f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.8-rc2-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "Six cifs/smb3 fixes, three of them for stable.

  Fixes xfstests 451, 313 and 316"

* tag '5.8-rc2-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: misc: Use array_size() in if-statement controlling expression
  cifs: update ctime and mtime during truncate
  cifs/smb3: Fix data inconsistent when punch hole
  cifs/smb3: Fix data inconsistent when zero file range
  cifs: Fix double add page to memcg when cifs_readpages
  cifs: Fix cached_fid refcnt leak in open_shroot
parents 3cd1c5d5 bf1028a4
...@@ -4336,7 +4336,8 @@ readpages_get_pages(struct address_space *mapping, struct list_head *page_list, ...@@ -4336,7 +4336,8 @@ readpages_get_pages(struct address_space *mapping, struct list_head *page_list,
break; break;
__SetPageLocked(page); __SetPageLocked(page);
if (add_to_page_cache_locked(page, mapping, page->index, gfp)) { rc = add_to_page_cache_locked(page, mapping, page->index, gfp);
if (rc) {
__ClearPageLocked(page); __ClearPageLocked(page);
break; break;
} }
...@@ -4352,6 +4353,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -4352,6 +4353,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
struct list_head *page_list, unsigned num_pages) struct list_head *page_list, unsigned num_pages)
{ {
int rc; int rc;
int err = 0;
struct list_head tmplist; struct list_head tmplist;
struct cifsFileInfo *open_file = file->private_data; struct cifsFileInfo *open_file = file->private_data;
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
...@@ -4396,7 +4398,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -4396,7 +4398,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
* the order of declining indexes. When we put the pages in * the order of declining indexes. When we put the pages in
* the rdata->pages, then we want them in increasing order. * the rdata->pages, then we want them in increasing order.
*/ */
while (!list_empty(page_list)) { while (!list_empty(page_list) && !err) {
unsigned int i, nr_pages, bytes, rsize; unsigned int i, nr_pages, bytes, rsize;
loff_t offset; loff_t offset;
struct page *page, *tpage; struct page *page, *tpage;
...@@ -4429,9 +4431,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -4429,9 +4431,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
return 0; return 0;
} }
rc = readpages_get_pages(mapping, page_list, rsize, &tmplist, nr_pages = 0;
err = readpages_get_pages(mapping, page_list, rsize, &tmplist,
&nr_pages, &offset, &bytes); &nr_pages, &offset, &bytes);
if (rc) { if (!nr_pages) {
add_credits_and_wake_if(server, credits, 0); add_credits_and_wake_if(server, credits, 0);
break; break;
} }
......
...@@ -2535,6 +2535,15 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, ...@@ -2535,6 +2535,15 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
if (rc == 0) { if (rc == 0) {
cifsInode->server_eof = attrs->ia_size; cifsInode->server_eof = attrs->ia_size;
cifs_setsize(inode, attrs->ia_size); cifs_setsize(inode, attrs->ia_size);
/*
* The man page of truncate says if the size changed,
* then the st_ctime and st_mtime fields for the file
* are updated.
*/
attrs->ia_ctime = attrs->ia_mtime = current_time(inode);
attrs->ia_valid |= ATTR_CTIME | ATTR_MTIME;
cifs_truncate_page(inode->i_mapping, inode->i_size); cifs_truncate_page(inode->i_mapping, inode->i_size);
} }
......
...@@ -844,28 +844,26 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw) ...@@ -844,28 +844,26 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
struct bio_vec *bv = NULL; struct bio_vec *bv = NULL;
if (iov_iter_is_kvec(iter)) { if (iov_iter_is_kvec(iter)) {
memcpy(&ctx->iter, iter, sizeof(struct iov_iter)); memcpy(&ctx->iter, iter, sizeof(*iter));
ctx->len = count; ctx->len = count;
iov_iter_advance(iter, count); iov_iter_advance(iter, count);
return 0; return 0;
} }
if (max_pages * sizeof(struct bio_vec) <= CIFS_AIO_KMALLOC_LIMIT) if (array_size(max_pages, sizeof(*bv)) <= CIFS_AIO_KMALLOC_LIMIT)
bv = kmalloc_array(max_pages, sizeof(struct bio_vec), bv = kmalloc_array(max_pages, sizeof(*bv), GFP_KERNEL);
GFP_KERNEL);
if (!bv) { if (!bv) {
bv = vmalloc(array_size(max_pages, sizeof(struct bio_vec))); bv = vmalloc(array_size(max_pages, sizeof(*bv)));
if (!bv) if (!bv)
return -ENOMEM; return -ENOMEM;
} }
if (max_pages * sizeof(struct page *) <= CIFS_AIO_KMALLOC_LIMIT) if (array_size(max_pages, sizeof(*pages)) <= CIFS_AIO_KMALLOC_LIMIT)
pages = kmalloc_array(max_pages, sizeof(struct page *), pages = kmalloc_array(max_pages, sizeof(*pages), GFP_KERNEL);
GFP_KERNEL);
if (!pages) { if (!pages) {
pages = vmalloc(array_size(max_pages, sizeof(struct page *))); pages = vmalloc(array_size(max_pages, sizeof(*pages)));
if (!pages) { if (!pages) {
kvfree(bv); kvfree(bv);
return -ENOMEM; return -ENOMEM;
......
...@@ -763,6 +763,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, ...@@ -763,6 +763,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
/* close extra handle outside of crit sec */ /* close extra handle outside of crit sec */
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
} }
rc = 0;
goto oshr_free; goto oshr_free;
} }
...@@ -3187,6 +3188,11 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, ...@@ -3187,6 +3188,11 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid, trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid,
ses->Suid, offset, len); ses->Suid, offset, len);
/*
* We zero the range through ioctl, so we need remove the page caches
* first, otherwise the data may be inconsistent with the server.
*/
truncate_pagecache_range(inode, offset, offset + len - 1);
/* if file not oplocked can't be sure whether asking to extend size */ /* if file not oplocked can't be sure whether asking to extend size */
if (!CIFS_CACHE_READ(cifsi)) if (!CIFS_CACHE_READ(cifsi))
...@@ -3253,6 +3259,12 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, ...@@ -3253,6 +3259,12 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
return rc; return rc;
} }
/*
* We implement the punch hole through ioctl, so we need remove the page
* caches first, otherwise the data may be inconsistent with the server.
*/
truncate_pagecache_range(inode, offset, offset + len - 1);
cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len); cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
fsctl_buf.FileOffset = cpu_to_le64(offset); fsctl_buf.FileOffset = cpu_to_le64(offset);
......
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