diff options
author | Volker Lendecke <vl@samba.org> | 2010-07-19 16:15:01 +0200 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2010-07-19 22:06:28 +0200 |
commit | 6763730304627a58139450fd3e03a0ce48e31bb9 (patch) | |
tree | 292bc671b35cf1655595ef08b859592ec5ba5ebd /source3/smbd | |
parent | 944494d350fa0e42aa8a87849fa7168731f3b0a6 (diff) | |
download | samba-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.c | 54 |
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 |