Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ccf3216 authored by Steve French's avatar Steve French Committed by Steve French
Browse files

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: default avatarSteven French <smfrench@gmail.com>
parent b2776bf7
Loading
Loading
Loading
Loading
+62 −1
Original line number Original line Diff line number Diff line
@@ -1102,6 +1102,64 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
	return rc;
	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,
static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
			   loff_t off, loff_t len)
			   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)
		if (mode & FALLOC_FL_KEEP_SIZE)
			return smb3_zero_range(file, tcon, off, len, true);
			return smb3_zero_range(file, tcon, off, len, true);
		return smb3_zero_range(file, tcon, off, len, false);
		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;
	return -EOPNOTSUPP;
}
}