summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2010-07-19 16:15:01 +0200
committerVolker Lendecke <vl@samba.org>2010-07-19 22:06:28 +0200
commit6763730304627a58139450fd3e03a0ce48e31bb9 (patch)
tree292bc671b35cf1655595ef08b859592ec5ba5ebd /source3/smbd
parent944494d350fa0e42aa8a87849fa7168731f3b0a6 (diff)
downloadsamba-6763730304627a58139450fd3e03a0ce48e31bb9.tar.gz
samba-6763730304627a58139450fd3e03a0ce48e31bb9.tar.bz2
samba-6763730304627a58139450fd3e03a0ce48e31bb9.zip
s3: Avoid pwrite calls for the 1-byte writes with zero content
When a write cache is empty and we write one 0, there is no point in actually writing into the write cache, which would trigger a potentially superfluous write cache flush. We can rely on posix semantics to give us 0's when subsequent read calls want to read from file areas not written yet. Jeremy, please check!
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/fileio.c54
1 files changed, 50 insertions, 4 deletions
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 92757f7052..f9fcc1be50 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -653,10 +653,31 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
*/
flush_write_cache(fsp, WRITE_FLUSH);
- wcp->offset = wcp->file_size;
- wcp->data_size = pos - wcp->file_size + 1;
- memset(wcp->data, '\0', wcp->data_size);
- memcpy(wcp->data + wcp->data_size-1, data, 1);
+
+ if (data[0] == '\0') {
+ /*
+ * This is a 1-byte write of a 0
+ * beyond the EOF, the typical
+ * file-extending (and allocating, but
+ * we're using the write cache here)
+ * write done by Windows. We just have
+ * to ftruncate the file and rely on
+ * posix semantics to return zeros for
+ * non-written file data that is
+ * within the file length.
+ *
+ * We have to cheat the offset to make
+ * wcp_file_size_change do the right
+ * thing with the ftruncate call.
+ */
+ wcp->offset = pos + 1;
+ wcp->data_size = 0;
+ } else {
+ wcp->offset = wcp->file_size;
+ wcp->data_size = pos - wcp->file_size + 1;
+ memset(wcp->data, '\0', wcp->data_size);
+ memcpy(wcp->data + wcp->data_size-1, data, 1);
+ }
/*
* Update the file size if changed.
@@ -799,6 +820,31 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n",
if ((wcp->data_size == 0)
&& (pos > wcp->file_size)
+ && (n == 1)
+ && (data[0] == '\0')) {
+ /*
+ * This is a 1-byte write of a 0 beyond the
+ * EOF, the typical file-extending (and
+ * allocating, but we're using the write cache
+ * here) write done by Windows. We just have
+ * to ftruncate the file and rely on posix
+ * semantics to return zeros for non-written
+ * file data that is within the file length.
+ *
+ * We have to cheat the offset to make
+ * wcp_file_size_change do the right thing
+ * with the ftruncate call.
+ */
+ wcp->offset = pos+1;
+ wcp->data_size = 0;
+ if (wcp_file_size_change(fsp) == -1) {
+ return -1;
+ }
+ return 1;
+ }
+
+ if ((wcp->data_size == 0)
+ && (pos > wcp->file_size)
&& (pos + n <= wcp->file_size + wcp->alloc_size)) {
/*
* This is a write completely beyond the