Add support for original fallocate

In many cases the simple fallocate call is
a no op (since the file is already not sparse) or
can simply be converted from a sparse to a non-sparse
file if we are fallocating the whole file and keeping
the size.

Signed-off-by: Steven French <smfrench@gmail.com>
This commit is contained in:
Steve French 2014-10-18 17:01:15 -05:00 committed by Steve French
parent b2776bf714
commit 9ccf321623

View file

@ -1102,6 +1102,64 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
return rc;
}
static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
loff_t off, loff_t len, bool keep_size)
{
struct inode *inode;
struct cifsInodeInfo *cifsi;
struct cifsFileInfo *cfile = file->private_data;
long rc = -EOPNOTSUPP;
unsigned int xid;
xid = get_xid();
inode = cfile->dentry->d_inode;
cifsi = CIFS_I(inode);
/* if file not oplocked can't be sure whether asking to extend size */
if (!CIFS_CACHE_READ(cifsi))
if (keep_size == false)
return -EOPNOTSUPP;
/*
* 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
*/
if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
if (keep_size == true)
return 0;
/* check if extending file */
else if (i_size_read(inode) >= off + len)
/* not extending file and already not sparse */
return 0;
/* BB: in future add else clause to extend file */
else
return -EOPNOTSUPP;
}
if ((keep_size == true) || (i_size_read(inode) >= off + len)) {
/*
* Check if falloc starts within first few pages of file
* and ends within a few pages of the end of file to
* ensure that most of file is being forced to be
* fallocated now. If so then setting whole file sparse
* ie potentially making a few extra pages at the beginning
* or end of the file non-sparse via set_sparse is harmless.
*/
if ((off > 8192) || (off + len + 8192 < i_size_read(inode)))
return -EOPNOTSUPP;
rc = smb2_set_sparse(xid, tcon, cfile, inode, false);
}
/* BB: else ... in future add code to extend file and set sparse */
free_xid(xid);
return rc;
}
static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
loff_t off, loff_t len)
{
@ -1112,7 +1170,10 @@ static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
if (mode & FALLOC_FL_KEEP_SIZE)
return smb3_zero_range(file, tcon, off, len, true);
return smb3_zero_range(file, tcon, off, len, false);
}
} else if (mode == FALLOC_FL_KEEP_SIZE)
return smb3_simple_falloc(file, tcon, off, len, true);
else if (mode == 0)
return smb3_simple_falloc(file, tcon, off, len, false);
return -EOPNOTSUPP;
}