int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
{
	int ret;
	SMB_STRUCT_STAT st;
	SMB_OFF_T offset;
	size_t total;
	size_t num_to_write;
	ssize_t pwrite_ret;

	ret = SMB_VFS_FSTAT(fsp, &st);
	if (ret == -1) {
		return ret;
	}

	if (len <= st.st_ex_size) {
		return 0;
	}

	DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
		  "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
		  (double)st.st_ex_size, (double)len,
		  (double)(len - st.st_ex_size)));

	contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);

	flush_write_cache(fsp, SIZECHANGE_FLUSH);

	if (!sparse_buf) {
		sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
		if (!sparse_buf) {
			errno = ENOMEM;
			ret = -1;
			goto out;
		}
	}

	offset = st.st_ex_size;
	num_to_write = len - st.st_ex_size;
	total = 0;

	while (total < num_to_write) {
		size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total));

		pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
		if (pwrite_ret == -1) {
			DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file "
				  "%s failed with error %s\n",
				  fsp_str_dbg(fsp), strerror(errno)));
			ret = -1;
			goto out;
		}
		if (pwrite_ret == 0) {
			ret = 0;
			goto out;
		}

		total += pwrite_ret;
	}

	set_filelen_write_cache(fsp, len);

	ret = 0;
 out:
	contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
	return ret;
}
int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
{
	int ret;
	SMB_STRUCT_STAT st;
	SMB_OFF_T offset;
	size_t total;
	size_t num_to_write;
	ssize_t pwrite_ret;

	ret = SMB_VFS_FSTAT(fsp, &st);
	if (ret == -1) {
		return ret;
	}

	if (len <= st.st_ex_size) {
		return 0;
	}

	DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
		  "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
		  (double)st.st_ex_size, (double)len,
		  (double)(len - st.st_ex_size)));

	contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);

	flush_write_cache(fsp, SIZECHANGE_FLUSH);

	if (!sparse_buf) {
		sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
		if (!sparse_buf) {
			errno = ENOMEM;
			ret = -1;
			goto out;
		}
	}

	offset = st.st_ex_size;
	num_to_write = len - st.st_ex_size;
	total = 0;

	while (total < num_to_write) {
		size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total));

		pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
		if (pwrite_ret == -1) {
			DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file "
				  "%s failed with error %s\n",
				  fsp_str_dbg(fsp), strerror(errno)));
			ret = -1;
			goto out;
		}
		if (pwrite_ret == 0) {
			ret = 0;
			goto out;
		}

		total += pwrite_ret;
	}

	set_filelen_write_cache(fsp, len);

	ret = 0;
 out:
	contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
	return ret;
}