Skip to content

Commit 8bd0d70

Browse files
Ronnie Sahlbergsmfrench
authored andcommitted
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 <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent fe12926 commit 8bd0d70

File tree

3 files changed

+34
-37
lines changed

3 files changed

+34
-37
lines changed

fs/cifs/cifsfs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ extern ssize_t cifs_file_copychunk_range(unsigned int xid,
149149
size_t len, unsigned int flags);
150150

151151
extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
152+
extern void cifs_setsize(struct inode *inode, loff_t offset);
153+
extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
154+
152155
#ifdef CONFIG_CIFS_NFSD_EXPORT
153156
extern const struct export_operations cifs_export_ops;
154157
#endif /* CONFIG_CIFS_NFSD_EXPORT */

fs/cifs/inode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2228,7 +2228,7 @@ int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
22282228
return -ENOTSUPP;
22292229
}
22302230

2231-
static int cifs_truncate_page(struct address_space *mapping, loff_t from)
2231+
int cifs_truncate_page(struct address_space *mapping, loff_t from)
22322232
{
22332233
pgoff_t index = from >> PAGE_SHIFT;
22342234
unsigned offset = from & (PAGE_SIZE - 1);
@@ -2245,7 +2245,7 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
22452245
return rc;
22462246
}
22472247

2248-
static void cifs_setsize(struct inode *inode, loff_t offset)
2248+
void cifs_setsize(struct inode *inode, loff_t offset)
22492249
{
22502250
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
22512251

fs/cifs/smb2ops.c

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/uuid.h>
1313
#include <linux/sort.h>
1414
#include <crypto/aead.h>
15+
#include "cifsfs.h"
1516
#include "cifsglob.h"
1617
#include "smb2pdu.h"
1718
#include "smb2proto.h"
@@ -3171,29 +3172,33 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
31713172
return rc;
31723173
}
31733174

3175+
/*
3176+
* Extending the file
3177+
*/
3178+
if ((keep_size == false) && i_size_read(inode) < off + len) {
3179+
if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0)
3180+
smb2_set_sparse(xid, tcon, cfile, inode, false);
3181+
3182+
eof = cpu_to_le64(off + len);
3183+
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
3184+
cfile->fid.volatile_fid, cfile->pid, &eof);
3185+
if (rc == 0) {
3186+
cifsi->server_eof = off + len;
3187+
cifs_setsize(inode, off + len);
3188+
cifs_truncate_page(inode->i_mapping, inode->i_size);
3189+
truncate_setsize(inode, off + len);
3190+
}
3191+
goto out;
3192+
}
3193+
31743194
/*
31753195
* Files are non-sparse by default so falloc may be a no-op
3176-
* Must check if file sparse. If not sparse, and not extending
3177-
* then no need to do anything since file already allocated
3196+
* Must check if file sparse. If not sparse, and since we are not
3197+
* extending then no need to do anything since file already allocated
31783198
*/
31793199
if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
3180-
if (keep_size == true)
3181-
rc = 0;
3182-
/* check if extending file */
3183-
else if (i_size_read(inode) >= off + len)
3184-
/* not extending file and already not sparse */
3185-
rc = 0;
3186-
/* BB: in future add else clause to extend file */
3187-
else
3188-
rc = -EOPNOTSUPP;
3189-
if (rc)
3190-
trace_smb3_falloc_err(xid, cfile->fid.persistent_fid,
3191-
tcon->tid, tcon->ses->Suid, off, len, rc);
3192-
else
3193-
trace_smb3_falloc_done(xid, cfile->fid.persistent_fid,
3194-
tcon->tid, tcon->ses->Suid, off, len);
3195-
free_xid(xid);
3196-
return rc;
3200+
rc = 0;
3201+
goto out;
31973202
}
31983203

31993204
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,
32073212
*/
32083213
if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) {
32093214
rc = -EOPNOTSUPP;
3210-
trace_smb3_falloc_err(xid, cfile->fid.persistent_fid,
3211-
tcon->tid, tcon->ses->Suid, off, len, rc);
3212-
free_xid(xid);
3213-
return rc;
3214-
}
3215-
3216-
smb2_set_sparse(xid, tcon, cfile, inode, false);
3217-
rc = 0;
3218-
} else {
3219-
smb2_set_sparse(xid, tcon, cfile, inode, false);
3220-
rc = 0;
3221-
if (i_size_read(inode) < off + len) {
3222-
eof = cpu_to_le64(off + len);
3223-
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
3224-
cfile->fid.volatile_fid, cfile->pid,
3225-
&eof);
3215+
goto out;
32263216
}
32273217
}
32283218

3219+
smb2_set_sparse(xid, tcon, cfile, inode, false);
3220+
rc = 0;
3221+
3222+
out:
32293223
if (rc)
32303224
trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, tcon->tid,
32313225
tcon->ses->Suid, off, len, rc);

0 commit comments

Comments
 (0)