cifs: add support for fallocate mode 0 for non-sparse files
RHBZ 1336264 When we extend a file we must also force the size to be updated. This fixes an issue with holetest in xfs-tests which performs the following sequence : 1, create a new file 2, use fallocate mode==0 to populate the file 3, mmap the file 4, touch each page by reading the mmapped region. Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
fe12926863
commit
8bd0d70144
|
@ -149,6 +149,9 @@ extern ssize_t cifs_file_copychunk_range(unsigned int xid,
|
|||
size_t len, unsigned int flags);
|
||||
|
||||
extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
|
||||
extern void cifs_setsize(struct inode *inode, loff_t offset);
|
||||
extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
|
||||
|
||||
#ifdef CONFIG_CIFS_NFSD_EXPORT
|
||||
extern const struct export_operations cifs_export_ops;
|
||||
#endif /* CONFIG_CIFS_NFSD_EXPORT */
|
||||
|
|
|
@ -2228,7 +2228,7 @@ int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int cifs_truncate_page(struct address_space *mapping, loff_t from)
|
||||
int cifs_truncate_page(struct address_space *mapping, loff_t from)
|
||||
{
|
||||
pgoff_t index = from >> PAGE_SHIFT;
|
||||
unsigned offset = from & (PAGE_SIZE - 1);
|
||||
|
@ -2245,7 +2245,7 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void cifs_setsize(struct inode *inode, loff_t offset)
|
||||
void cifs_setsize(struct inode *inode, loff_t offset)
|
||||
{
|
||||
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/uuid.h>
|
||||
#include <linux/sort.h>
|
||||
#include <crypto/aead.h>
|
||||
#include "cifsfs.h"
|
||||
#include "cifsglob.h"
|
||||
#include "smb2pdu.h"
|
||||
#include "smb2proto.h"
|
||||
|
@ -3171,29 +3172,33 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extending the file
|
||||
*/
|
||||
if ((keep_size == false) && i_size_read(inode) < off + len) {
|
||||
if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0)
|
||||
smb2_set_sparse(xid, tcon, cfile, inode, false);
|
||||
|
||||
eof = cpu_to_le64(off + len);
|
||||
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, cfile->pid, &eof);
|
||||
if (rc == 0) {
|
||||
cifsi->server_eof = off + len;
|
||||
cifs_setsize(inode, off + len);
|
||||
cifs_truncate_page(inode->i_mapping, inode->i_size);
|
||||
truncate_setsize(inode, off + len);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Files are non-sparse by default so falloc may be a no-op
|
||||
* Must check if file sparse. If not sparse, and not extending
|
||||
* then no need to do anything since file already allocated
|
||||
* Must check if file sparse. If not sparse, and since we are not
|
||||
* extending then no need to do anything since file already allocated
|
||||
*/
|
||||
if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
|
||||
if (keep_size == true)
|
||||
rc = 0;
|
||||
/* check if extending file */
|
||||
else if (i_size_read(inode) >= off + len)
|
||||
/* not extending file and already not sparse */
|
||||
rc = 0;
|
||||
/* BB: in future add else clause to extend file */
|
||||
else
|
||||
rc = -EOPNOTSUPP;
|
||||
if (rc)
|
||||
trace_smb3_falloc_err(xid, cfile->fid.persistent_fid,
|
||||
tcon->tid, tcon->ses->Suid, off, len, rc);
|
||||
else
|
||||
trace_smb3_falloc_done(xid, cfile->fid.persistent_fid,
|
||||
tcon->tid, tcon->ses->Suid, off, len);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((keep_size == true) || (i_size_read(inode) >= off + len)) {
|
||||
|
@ -3207,25 +3212,14 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
|
|||
*/
|
||||
if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) {
|
||||
rc = -EOPNOTSUPP;
|
||||
trace_smb3_falloc_err(xid, cfile->fid.persistent_fid,
|
||||
tcon->tid, tcon->ses->Suid, off, len, rc);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
smb2_set_sparse(xid, tcon, cfile, inode, false);
|
||||
rc = 0;
|
||||
} else {
|
||||
smb2_set_sparse(xid, tcon, cfile, inode, false);
|
||||
rc = 0;
|
||||
if (i_size_read(inode) < off + len) {
|
||||
eof = cpu_to_le64(off + len);
|
||||
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, cfile->pid,
|
||||
&eof);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (rc)
|
||||
trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, tcon->tid,
|
||||
tcon->ses->Suid, off, len, rc);
|
||||
|
|
Loading…
Reference in New Issue