From 3fea05e01f845588eb0de63af435bfec670593be Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 27 May 2019 11:24:14 +0200 Subject: [PATCH] smbd: Remove write cache Since this was written, our write path has changed significantly. In particular we have gained very flexible support for async I/O, with the linux io_uring in the pipeline. Caching stuff in main memory and then doing a blocking pwrite nowadays does not belong into the core smbd code. If someone wants it back, it should be doable in a VFS module. Removes: "write cache size" parameter. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Reviewed-by: Andrew Bartlett Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed Nov 13 00:20:55 UTC 2019 on sn-devel-184 --- WHATSNEW.txt | 18 + docs-xml/smbdotconf/tuning/writecachesize.xml | 33 - source3/include/smb.h | 15 - source3/include/smbprofile.h | 21 - source3/include/vfs.h | 2 +- source3/param/loadparm.c | 1 - source3/smbd/aio.c | 20 +- source3/smbd/close.c | 24 - source3/smbd/fileio.c | 767 +----------------- source3/smbd/globals.c | 3 - source3/smbd/globals.h | 3 - source3/smbd/open.c | 2 - source3/smbd/oplock.c | 6 - source3/smbd/proto.h | 3 - source3/smbd/reply.c | 6 - source3/smbd/smb2_flush.c | 7 - source3/smbd/smb2_read.c | 1 - source3/smbd/vfs.c | 13 +- 18 files changed, 26 insertions(+), 919 deletions(-) delete mode 100644 docs-xml/smbdotconf/tuning/writecachesize.xml diff --git a/WHATSNEW.txt b/WHATSNEW.txt index dccb44dbd27..cc43b29b3d1 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -56,6 +56,23 @@ applies. REMOVED FEATURES ================ +The smb.conf parameter "write cache size" has been removed. + +Since the in-memory write caching code was written, our write path has +changed significantly. In particular we have gained very flexible +support for async I/O, with the new linux io_uring interface in +development. The old write cache concept which cached data in main +memory followed by a blocking pwrite no longer gives any improvement +on modern systems, and may make performance worse on memory-contrained +systems, so this functionality should not be enabled in core smbd +code. + +In addition, it complicated the write code, which is a performance +critical code path. + +If required for specialist purposes, it can be recreated as a VFS +module. + BIND9_FLATFILE deprecated ------------------------- @@ -77,6 +94,7 @@ smb.conf changes nfs4:acedup Changed default merge rndc command Removed + write cache size Removed KNOWN ISSUES ============ diff --git a/docs-xml/smbdotconf/tuning/writecachesize.xml b/docs-xml/smbdotconf/tuning/writecachesize.xml deleted file mode 100644 index 484b35398bf..00000000000 --- a/docs-xml/smbdotconf/tuning/writecachesize.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - If this integer parameter is set to non-zero value, - Samba will create an in-memory cache for each oplocked file - (it does not do this for - non-oplocked files). All writes that the client does not request - to be flushed directly to disk will be stored in this cache if possible. - The cache is flushed onto disk when a write comes in whose offset - would not fit into the cache or when the file is closed by the client. - Reads for the file are also served from this cache if the data is stored - within it. - - This cache allows Samba to batch client writes into a more - efficient write size for RAID disks (i.e. writes may be tuned to - be the RAID stripe size) and can improve performance on systems - where the disk subsystem is a bottleneck but there is free - memory for userspace programs. - - The integer parameter specifies the size of this cache - (per oplocked file) in bytes. - - Note that the write cache won't be used for file handles with a smb2 write lease. - - -aio read size -aio write size -smb2 leases -0 -262144 for a 256k cache size per file - diff --git a/source3/include/smb.h b/source3/include/smb.h index 012ed485494..162cdcc1a32 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -749,19 +749,4 @@ struct smb_extended_info { char samba_version_string[SAMBA_EXTENDED_INFO_VERSION_STRING_LENGTH]; }; -/* - * Reasons for cache flush. - */ - -enum flush_reason_enum { - SAMBA_SEEK_FLUSH, - SAMBA_READ_FLUSH, - SAMBA_WRITE_FLUSH, - SAMBA_READRAW_FLUSH, - SAMBA_OPLOCK_RELEASE_FLUSH, - SAMBA_CLOSE_FLUSH, - SAMBA_SYNC_FLUSH, - SAMBA_SIZECHANGE_FLUSH, -}; - #endif /* _SMB_H */ diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index a003a1d9df0..b771c26c81b 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -108,27 +108,6 @@ struct tevent_context; SMBPROFILE_STATS_COUNT(statcache_hits) \ SMBPROFILE_STATS_SECTION_END \ \ - SMBPROFILE_STATS_SECTION_START(writecache, "Write Cache") \ - SMBPROFILE_STATS_COUNT(writecache_allocations) \ - SMBPROFILE_STATS_COUNT(writecache_deallocations) \ - SMBPROFILE_STATS_COUNT(writecache_cached_reads) \ - SMBPROFILE_STATS_COUNT(writecache_total_writes) \ - SMBPROFILE_STATS_COUNT(writecache_init_writes) \ - SMBPROFILE_STATS_COUNT(writecache_abutted_writes) \ - SMBPROFILE_STATS_COUNT(writecache_non_oplock_writes) \ - SMBPROFILE_STATS_COUNT(writecache_direct_writes) \ - SMBPROFILE_STATS_COUNT(writecache_cached_writes) \ - SMBPROFILE_STATS_COUNT(writecache_perfect_writes) \ - SMBPROFILE_STATS_COUNT(writecache_flush_reason_seek) \ - SMBPROFILE_STATS_COUNT(writecache_flush_reason_read) \ - SMBPROFILE_STATS_COUNT(writecache_flush_reason_readraw) \ - SMBPROFILE_STATS_COUNT(writecache_flush_reason_write) \ - SMBPROFILE_STATS_COUNT(writecache_flush_reason_oplock) \ - SMBPROFILE_STATS_COUNT(writecache_flush_reason_close) \ - SMBPROFILE_STATS_COUNT(writecache_flush_reason_sync) \ - SMBPROFILE_STATS_COUNT(writecache_flush_reason_sizechange) \ - SMBPROFILE_STATS_SECTION_END \ - \ SMBPROFILE_STATS_SECTION_START(SMB, "SMB Calls") \ SMBPROFILE_STATS_BASIC(SMBmkdir) \ SMBPROFILE_STATS_BASIC(SMBrmdir) \ diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 802eb8d0292..a6c57c6bcbc 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -286,6 +286,7 @@ /* Version 42 - Remove SMB_VFS_RMDIR. Use SMB_VFS_UNLINKAT(.., AT_REMOVEDIR) instead. */ /* Version 42 - Remove SMB_VFS_CHOWN */ +/* Version 42 - Remove struct write_cache *wcp from files_struct */ #define SMB_VFS_INTERFACE_VERSION 42 @@ -347,7 +348,6 @@ typedef struct files_struct { uint64_t initial_allocation_size; /* Faked up initial allocation on disk. */ uint16_t file_pid; uint64_t vuid; /* SMB2 compat */ - struct write_cache *wcp; struct timeval open_time; uint32_t access_mask; /* NTCreateX access bits (FILE_READ_DATA etc.) */ bool kernel_share_modes_taken; diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 433762eedfb..31fa229d5ff 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -160,7 +160,6 @@ static const struct loadparm_service _sDefault = .min_print_space = 0, .max_print_jobs = 1000, .max_reported_print_jobs = 0, - .write_cache_size = 0, .create_mask = 0744, .force_create_mode = 0, .directory_mask = 0755, diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 8ac3ef7278e..0f824f5aa1f 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -172,9 +172,8 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn, return NT_STATUS_RETRY; } - /* Only do this on non-chained and non-chaining reads not using the - * write cache. */ - if (req_is_in_chain(smbreq) || (lp_write_cache_size(SNUM(conn)) != 0)) { + /* Only do this on non-chained and non-chaining reads */ + if (req_is_in_chain(smbreq)) { return NT_STATUS_RETRY; } @@ -428,9 +427,8 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn, return NT_STATUS_RETRY; } - /* Only do this on non-chained and non-chaining writes not using the - * write cache. */ - if (req_is_in_chain(smbreq) || (lp_write_cache_size(SNUM(conn)) != 0)) { + /* Only do this on non-chained and non-chaining writes */ + if (req_is_in_chain(smbreq)) { return NT_STATUS_RETRY; } @@ -673,11 +671,6 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn, return NT_STATUS_RETRY; } - /* Only do this on reads not using the write cache. */ - if (lp_write_cache_size(SNUM(conn)) != 0) { - return NT_STATUS_RETRY; - } - if (smbd_smb2_is_compound(smbreq->smb2req)) { return NT_STATUS_RETRY; } @@ -813,11 +806,6 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn, return NT_STATUS_RETRY; } - /* Only do this on writes not using the write cache. */ - if (lp_write_cache_size(SNUM(conn)) != 0) { - return NT_STATUS_RETRY; - } - if (smbd_smb2_is_compound(smbreq->smb2req)) { return NT_STATUS_RETRY; } diff --git a/source3/smbd/close.c b/source3/smbd/close.c index e62480d69da..180a5da735b 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -140,24 +140,6 @@ static NTSTATUS check_magic(struct files_struct *fsp) return status; } -/**************************************************************************** - Common code to close a file or a directory. -****************************************************************************/ - -static NTSTATUS close_filestruct(files_struct *fsp) -{ - NTSTATUS status = NT_STATUS_OK; - - if (fsp->fh->fd != -1) { - if(flush_write_cache(fsp, SAMBA_CLOSE_FLUSH) == -1) { - status = map_nt_error_from_unix(errno); - } - delete_write_cache(fsp); - } - - return status; -} - /**************************************************************************** Delete all streams ****************************************************************************/ @@ -715,9 +697,6 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, * error here, we must remember this. */ - tmp = close_filestruct(fsp); - status = ntstatus_keeperror(status, tmp); - if (NT_STATUS_IS_OK(status) && fsp->op != NULL) { is_durable = fsp->op->global->durable; } @@ -1182,7 +1161,6 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for " "%s\n", fsp_str_dbg(fsp))); - close_filestruct(fsp); file_free(req, fsp); return NT_STATUS_INVALID_PARAMETER; } @@ -1242,7 +1220,6 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("delete_all_streams failed: %s\n", nt_errstr(status))); - close_filestruct(fsp); file_free(req, fsp); return status; } @@ -1287,7 +1264,6 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, /* * Do the code common to files and directories. */ - close_filestruct(fsp); file_free(req, fsp); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) { diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 067ce5a9ad4..b03f86d49d6 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -25,39 +25,6 @@ #include "smbd/globals.h" #include "smbprofile.h" -struct write_cache { - off_t file_size; - off_t offset; - size_t alloc_size; - size_t data_size; - char *data; -}; - -static bool setup_write_cache(files_struct *, off_t); - -/**************************************************************************** - Read from write cache if we can. -****************************************************************************/ - -static bool read_from_write_cache(files_struct *fsp,char *data,off_t pos,size_t n) -{ - struct write_cache *wcp = fsp->wcp; - - if(!wcp) { - return False; - } - - if( n > wcp->data_size || pos < wcp->offset || pos + n > wcp->offset + wcp->data_size) { - return False; - } - - memcpy(data, wcp->data + (pos - wcp->offset), n); - - DO_PROFILE_INC(writecache_cached_reads); - - return True; -} - /**************************************************************************** Read from a file. ****************************************************************************/ @@ -72,18 +39,6 @@ ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n) return -1; } - /* - * Serve from write cache if we can. - */ - - if(read_from_write_cache(fsp, data, pos, n)) { - fsp->fh->pos = pos + n; - fsp->fh->position_information = fsp->fh->pos; - return n; - } - - flush_write_cache(fsp, SAMBA_READ_FLUSH); - fsp->fh->pos = pos; if (n > 0) { @@ -140,26 +95,6 @@ static ssize_t real_write_file(struct smb_request *req, return ret; } -/**************************************************************************** - File size cache change. - Updates size on disk but doesn't flush the cache. -****************************************************************************/ - -static int wcp_file_size_change(files_struct *fsp) -{ - int ret; - struct write_cache *wcp = fsp->wcp; - - wcp->file_size = wcp->offset + wcp->data_size; - ret = SMB_VFS_FTRUNCATE(fsp, wcp->file_size); - if (ret == -1) { - DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f " - "error %s\n", fsp_str_dbg(fsp), - (double)wcp->file_size, strerror(errno))); - } - return ret; -} - void fsp_flush_write_time_update(struct files_struct *fsp) { /* @@ -314,9 +249,7 @@ ssize_t write_file(struct smb_request *req, off_t pos, size_t n) { - struct write_cache *wcp = fsp->wcp; ssize_t total_written = 0; - int write_path = -1; if (fsp->print_file) { uint32_t t; @@ -335,30 +268,8 @@ ssize_t write_file(struct smb_request *req, return -1; } - /* - * If this is the first write and we have an exclusive oplock - * then setup the write cache. - */ - - if (!fsp->modified && - EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && - (wcp == NULL)) { - /* - * Note: no write cache with leases! - * as the handles would have to share the write cache - * that's possible but an improvement for another day... - */ - setup_write_cache(fsp, fsp->fsp_name->st.st_ex_size); - wcp = fsp->wcp; - } - mark_file_modified(fsp); - DO_PROFILE_INC(writecache_total_writes); - if (!fsp->oplock_type) { - DO_PROFILE_INC(writecache_non_oplock_writes); - } - /* * If this file is level II oplocked then we need * to grab the shared memory lock and inform all @@ -371,681 +282,10 @@ ssize_t write_file(struct smb_request *req, contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE); contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE); - if (wcp && req->unread_bytes) { - /* If we're using receivefile don't - * deal with a write cache. - */ - flush_write_cache(fsp, SAMBA_WRITE_FLUSH); - delete_write_cache(fsp); - wcp = NULL; - } - - if(!wcp) { - DO_PROFILE_INC(writecache_direct_writes); - total_written = real_write_file(req, fsp, data, pos, n); - return total_written; - } - - DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f " - "wcp->data_size=%u\n", fsp_str_dbg(fsp), fsp->fh->fd, - (double)pos, (unsigned int)n, (double)wcp->offset, - (unsigned int)wcp->data_size)); - - fsp->fh->pos = pos + n; - - if ((n == 1) && (data[0] == '\0') && (pos > wcp->file_size)) { - int ret; - - /* - * This is a 1-byte write of a 0 beyond the EOF and - * thus implicitly also beyond the current active - * write cache, 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 can not use wcp_file_size_change here because we - * might have an existing write cache, and - * wcp_file_size_change assumes a change to just the - * end of the current write cache. - */ - - wcp->file_size = pos + 1; - ret = SMB_VFS_FTRUNCATE(fsp, wcp->file_size); - if (ret == -1) { - DEBUG(0, ("wcp_file_size_change (%s): ftruncate of " - "size %.0f error %s\n", fsp_str_dbg(fsp), - (double)wcp->file_size, strerror(errno))); - return -1; - } - return 1; - } - - - /* - * If we have active cache and it isn't contiguous then we flush. - * NOTE: There is a small problem with running out of disk .... - */ - - if (wcp->data_size) { - bool cache_flush_needed = False; - - if ((pos >= wcp->offset) && - (pos <= wcp->offset + wcp->data_size)) { - - /* ASCII art.... JRA. - - +--------------+----- - | Cached data | Rest of allocated cache buffer.... - +--------------+----- - - +-------------------+ - | Data to write | - +-------------------+ - - */ - - /* - * Start of write overlaps or abutts the existing data. - */ - - size_t data_used; - - data_used = MIN((wcp->alloc_size - (pos - wcp->offset)), - n); - - memcpy(wcp->data + (pos - wcp->offset), data, - data_used); - - /* - * Update the current buffer size with the new data. - */ - - if(pos + data_used > wcp->offset + wcp->data_size) { - wcp->data_size = pos + data_used - wcp->offset; - } - - /* - * Update the file size if changed. - */ - - if (wcp->offset + wcp->data_size > wcp->file_size) { - if (wcp_file_size_change(fsp) == -1) { - return -1; - } - } - - /* - * If we used all the data then - * return here. - */ - - if(n == data_used) { - return n; - } else { - cache_flush_needed = True; - } - /* - * Move the start of data forward by the amount used, - * cut down the amount left by the same amount. - */ - - data += data_used; - pos += data_used; - n -= data_used; - - DO_PROFILE_INC(writecache_abutted_writes); - total_written = data_used; - - write_path = 1; - - } else if ((pos < wcp->offset) && - (pos + n > wcp->offset) && - (pos + n <= wcp->offset + wcp->alloc_size)) { - - /* ASCII art.... JRA. - - +---------------+ - | Cache buffer | - +---------------+ - - +-------------------+ - | Data to write | - +-------------------+ - - */ - - /* - * End of write overlaps the existing data. - */ - - size_t data_used = pos + n - wcp->offset; - - memcpy(wcp->data, data + n - data_used, data_used); - - /* - * Update the current buffer size with the new data. - */ - - if(pos + n > wcp->offset + wcp->data_size) { - wcp->data_size = pos + n - wcp->offset; - } - - /* - * Update the file size if changed. - */ - - if (wcp->offset + wcp->data_size > wcp->file_size) { - if (wcp_file_size_change(fsp) == -1) { - return -1; - } - } - - /* - * We don't need to move the start of data, but we - * cut down the amount left by the amount used. - */ - - n -= data_used; - - /* - * We cannot have used all the data here. - */ - - cache_flush_needed = True; - - DO_PROFILE_INC(writecache_abutted_writes); - total_written = data_used; - - write_path = 2; - - } else if ((pos >= wcp->file_size) && - (wcp->offset + wcp->data_size == wcp->file_size) && - (pos > wcp->offset + wcp->data_size) && - (pos < wcp->offset + wcp->alloc_size) ) { - - /* ASCII art.... JRA. - - End of file ---->| - - +---------------+---------------+ - | Cached data | Cache buffer | - +---------------+---------------+ - - +-------------------+ - | Data to write | - +-------------------+ - - */ - - /* - * Non-contiguous write part of which fits within - * the cache buffer and is extending the file - * and the cache contents reflect the current - * data up to the current end of the file. - */ - - size_t data_used; - - if(pos + n <= wcp->offset + wcp->alloc_size) { - data_used = n; - } else { - data_used = wcp->offset+wcp->alloc_size-pos; - } - - /* - * Fill in the non-continuous area with zeros. - */ - - memset(wcp->data + wcp->data_size, '\0', - pos - (wcp->offset + wcp->data_size) ); - - memcpy(wcp->data + (pos - wcp->offset), data, - data_used); - - /* - * Update the current buffer size with the new data. - */ - - if(pos + data_used > wcp->offset + wcp->data_size) { - wcp->data_size = pos + data_used - wcp->offset; - } - - /* - * Update the file size if changed. - */ - - if (wcp->offset + wcp->data_size > wcp->file_size) { - if (wcp_file_size_change(fsp) == -1) { - return -1; - } - } - - /* - * If we used all the data then - * return here. - */ - - if(n == data_used) { - return n; - } else { - cache_flush_needed = True; - } - - /* - * Move the start of data forward by the amount used, - * cut down the amount left by the same amount. - */ - - data += data_used; - pos += data_used; - n -= data_used; - - DO_PROFILE_INC(writecache_abutted_writes); - total_written = data_used; - - write_path = 3; - - } else if ( (pos >= wcp->file_size) && - (n == 1) && - (wcp->file_size == wcp->offset + wcp->data_size) && - (pos < wcp->file_size + wcp->alloc_size)) { - - /* - - End of file ---->| - - +---------------+---------------+ - | Cached data | Cache buffer | - +---------------+---------------+ - - |<------- allocated size ---------------->| - - +--------+ - | 1 Byte | - +--------+ - - MS-Office seems to do this a lot to determine if - there's enough space on the filesystem to write a new - file. - - Change to : - - End of file ---->| - +-----------------------+--------+ - | Zeroed Cached data | 1 Byte | - +-----------------------+--------+ - */ - - flush_write_cache(fsp, SAMBA_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); - - /* - * Update the file size if changed. - */ - - if (wcp->offset + wcp->data_size > wcp->file_size) { - if (wcp_file_size_change(fsp) == -1) { - return -1; - } - } - - return n; - - } else { - - /* ASCII art..... JRA. - - Case 1). - - +---------------+---------------+ - | Cached data | Cache buffer | - +---------------+---------------+ - - +---------------+ - | Data to write | - +---------------+ - - Case 2). - - +---------------+---------------+ - | Cached data | Cache buffer | - +---------------+---------------+ - - +-------------------+ - | Data to write | - +-------------------+ - - Case 3). - - +---------------+---------------+ - | Cached data | Cache buffer | - +---------------+---------------+ - - +-----------------------------------------------------+ - | Data to write | - +-----------------------------------------------------+ - - */ - - /* - * Write is bigger than buffer, or there is no - * overlap on the low or high ends. - */ - - DEBUG(9,("write_file: non cacheable write : fd = %d, " - "pos = %.0f, len = %u, " - "current cache pos = %.0f len = %u\n", - fsp->fh->fd, (double)pos, (unsigned int)n, - (double)wcp->offset, - (unsigned int)wcp->data_size )); - - /* - * If write would fit in the cache, and is - * larger than the data already in the cache, - * flush the cache and preferentially copy the - * data new data into it. Otherwise just write - * the data directly. - */ - - if ( n <= wcp->alloc_size && n > wcp->data_size) { - cache_flush_needed = True; - } else { - ssize_t ret = real_write_file(NULL, fsp, data, - pos, n); - - /* - * If the write overlaps the entire - * cache, then discard the current - * contents of the cache. Fix from - * Rasmus Borup Hansen rbh@math.ku.dk. - */ - - if ((pos <= wcp->offset) && - (pos + n >= wcp->offset+wcp->data_size)) { - DEBUG(9,("write_file: discarding " - "overwritten write cache: " - "fd = %d, off=%.0f, " - "size=%u\n", fsp->fh->fd, - (double)wcp->offset, - (unsigned)wcp->data_size)); - wcp->data_size = 0; - } - - DO_PROFILE_INC(writecache_direct_writes); - if (ret == -1) { - return ret; - } - - if (pos + ret > wcp->file_size) { - wcp->file_size = pos + ret; - } - - return ret; - } - - write_path = 4; - - } - - if (cache_flush_needed) { - DEBUG(3, ("SAMBA_WRITE_FLUSH:%d: due to noncontinuous " - "write: fd = %d, size = %.0f, pos = %.0f, " - "n = %u, wcp->offset=%.0f, " - "wcp->data_size=%u\n", - write_path, fsp->fh->fd, - (double)wcp->file_size, (double)pos, - (unsigned int)n, (double)wcp->offset, - (unsigned int)wcp->data_size )); - - flush_write_cache(fsp, SAMBA_WRITE_FLUSH); - } - } - - /* - * If the write request is bigger than the cache - * size, write it all out. - */ - - if (n > wcp->alloc_size ) { - ssize_t ret = real_write_file(NULL,fsp, data, pos, n); - if (ret == -1) { - return -1; - } - - if (pos + ret > wcp->file_size) { - wcp->file_size = pos + n; - } - - DO_PROFILE_INC(writecache_direct_writes); - return total_written + n; - } - - /* - * If there's any data left, cache it. - */ - - if (n) { - DO_PROFILE_INC(writecache_cached_writes); - if (wcp->data_size) { - DO_PROFILE_INC(writecache_abutted_writes); - } else { - DO_PROFILE_INC(writecache_init_writes); - } - - if ((wcp->data_size == 0) - && (pos > wcp->file_size) - && (pos + n <= wcp->file_size + wcp->alloc_size)) { - /* - * This is a write completely beyond the - * current EOF, but within reach of the write - * cache. We expect fill-up writes pretty - * soon, so it does not make sense to start - * the write cache at the current - * offset. These fill-up writes would trigger - * separate pwrites or even unnecessary cache - * flushes because they overlap if this is a - * one-byte allocating write. - */ - wcp->offset = wcp->file_size; - wcp->data_size = pos - wcp->file_size; - memset(wcp->data, 0, wcp->data_size); - } - - memcpy(wcp->data+wcp->data_size, data, n); - if (wcp->data_size == 0) { - wcp->offset = pos; - } - wcp->data_size += n; - - /* - * Update the file size if changed. - */ - - if (wcp->offset + wcp->data_size > wcp->file_size) { - if (wcp_file_size_change(fsp) == -1) { - return -1; - } - } - DEBUG(9, ("wcp->offset = %.0f wcp->data_size = %u cache " - "return %u\n", - (double)wcp->offset, (unsigned int)wcp->data_size, - (unsigned int)n)); - - total_written += n; - return total_written; /* .... that's a write :) */ - } - + total_written = real_write_file(req, fsp, data, pos, n); return total_written; } -/**************************************************************************** - Delete the write cache structure. -****************************************************************************/ - -void delete_write_cache(files_struct *fsp) -{ - struct write_cache *wcp; - - if(!fsp) { - return; - } - - if(!(wcp = fsp->wcp)) { - return; - } - - DO_PROFILE_INC(writecache_deallocations); - allocated_write_caches--; - - SMB_ASSERT(wcp->data_size == 0); - - SAFE_FREE(wcp->data); - SAFE_FREE(fsp->wcp); - - DEBUG(10,("delete_write_cache: File %s deleted write cache\n", - fsp_str_dbg(fsp))); -} - -/**************************************************************************** - Setup the write cache structure. -****************************************************************************/ - -static bool setup_write_cache(files_struct *fsp, off_t file_size) -{ - ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn)); - struct write_cache *wcp; - - if (allocated_write_caches >= MAX_WRITE_CACHES) { - return False; - } - - if(alloc_size == 0 || fsp->wcp) { - return False; - } - - if((wcp = SMB_MALLOC_P(struct write_cache)) == NULL) { - DEBUG(0,("setup_write_cache: malloc fail.\n")); - return False; - } - - wcp->file_size = file_size; - wcp->offset = 0; - wcp->alloc_size = alloc_size; - wcp->data_size = 0; - if((wcp->data = (char *)SMB_MALLOC(wcp->alloc_size)) == NULL) { - DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n", - (unsigned int)wcp->alloc_size )); - SAFE_FREE(wcp); - return False; - } - - memset(wcp->data, '\0', wcp->alloc_size ); - - fsp->wcp = wcp; - DO_PROFILE_INC(writecache_allocations); - allocated_write_caches++; - - DEBUG(10,("setup_write_cache: File %s allocated write cache size %lu\n", - fsp_str_dbg(fsp), (unsigned long)wcp->alloc_size)); - - return True; -} - -/**************************************************************************** - Cope with a size change. -****************************************************************************/ - -void set_filelen_write_cache(files_struct *fsp, off_t file_size) -{ - if(fsp->wcp) { - /* The cache *must* have been flushed before we do this. */ - if (fsp->wcp->data_size != 0) { - char *msg; - if (asprintf(&msg, "set_filelen_write_cache: size change " - "on file %s with write cache size = %lu\n", - fsp->fsp_name->base_name, - (unsigned long)fsp->wcp->data_size) != -1) { - smb_panic(msg); - } else { - smb_panic("set_filelen_write_cache"); - } - } - fsp->wcp->file_size = file_size; - } -} - -/******************************************************************* - Flush a write cache struct to disk. -********************************************************************/ - -ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) -{ - struct write_cache *wcp = fsp->wcp; - size_t data_size; - ssize_t ret; - - if(!wcp || !wcp->data_size) { - return 0; - } - - data_size = wcp->data_size; - wcp->data_size = 0; - - switch (reason) { - case SAMBA_SEEK_FLUSH: - DO_PROFILE_INC(writecache_flush_reason_seek); - break; - case SAMBA_READ_FLUSH: - DO_PROFILE_INC(writecache_flush_reason_read); - break; - case SAMBA_WRITE_FLUSH: - DO_PROFILE_INC(writecache_flush_reason_write);; - break; - case SAMBA_READRAW_FLUSH: - DO_PROFILE_INC(writecache_flush_reason_readraw); - break; - case SAMBA_OPLOCK_RELEASE_FLUSH: - DO_PROFILE_INC(writecache_flush_reason_oplock); - break; - case SAMBA_CLOSE_FLUSH: - DO_PROFILE_INC(writecache_flush_reason_close); - break; - case SAMBA_SYNC_FLUSH: - DO_PROFILE_INC(writecache_flush_reason_sync); - break; - case SAMBA_SIZECHANGE_FLUSH: - DO_PROFILE_INC(writecache_flush_reason_sizechange); - break; - default: - break; - } - - DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", - fsp->fh->fd, (double)wcp->offset, (unsigned int)data_size)); - - if(data_size == wcp->alloc_size) { - DO_PROFILE_INC(writecache_perfect_writes); - } - - ret = real_write_file(NULL, fsp, wcp->data, wcp->offset, data_size); - - /* - * Ensure file size if kept up to date if write extends file. - */ - - if ((ret != -1) && (wcp->offset + ret > wcp->file_size)) { - wcp->file_size = wcp->offset + ret; - } - - return ret; -} - /******************************************************************* sync a file ********************************************************************/ @@ -1057,10 +297,7 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug if (lp_strict_sync(SNUM(conn)) && (lp_sync_always(SNUM(conn)) || write_through)) { - int ret = flush_write_cache(fsp, SAMBA_SYNC_FLUSH); - if (ret == -1) { - return map_nt_error_from_unix(errno); - } + int ret; ret = smb_vfs_fsync_sync(fsp); if (ret == -1) { return map_nt_error_from_unix(errno); diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 0cdce20d122..c0fafecd2eb 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -28,9 +28,6 @@ struct smbd_dmapi_context *dmapi_ctx = NULL; #endif -/* how many write cache buffers have been allocated */ -unsigned int allocated_write_caches = 0; - const struct mangle_fns *mangle_fns = NULL; unsigned char *chartest = NULL; diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index d7d584eb274..c791eb0fa6f 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -30,9 +30,6 @@ struct smbd_dmapi_context; extern struct smbd_dmapi_context *dmapi_ctx; #endif -/* how many write cache buffers have been allocated */ -extern unsigned int allocated_write_caches; - /* A singleton cache to speed up searching by dev/inode. */ struct fsp_singleton_cache { files_struct *fsp; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2d4168c3ebe..fa990cacd5e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1451,8 +1451,6 @@ static NTSTATUS open_file(files_struct *fsp, fsp->aio_write_behind = True; } - fsp->wcp = NULL; /* Write cache pointer. */ - DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", conn->session_info->unix_info->unix_name, smb_fname_str_dbg(smb_fname), diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 1a62821c760..ad993cc95b0 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -139,9 +139,6 @@ static void release_file_oplock(files_struct *fsp) fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; - flush_write_cache(fsp, SAMBA_OPLOCK_RELEASE_FLUSH); - delete_write_cache(fsp); - TALLOC_FREE(fsp->oplock_timeout); } @@ -169,9 +166,6 @@ static void downgrade_file_oplock(files_struct *fsp) sconn->oplocks.level_II_open++; fsp->sent_oplock_break = NO_BREAK_SENT; - flush_write_cache(fsp, SAMBA_OPLOCK_RELEASE_FLUSH); - delete_write_cache(fsp); - TALLOC_FREE(fsp->oplock_timeout); } diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index dd6993a60f0..4bb0f9a54c8 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -330,9 +330,6 @@ ssize_t write_file(struct smb_request *req, const char *data, off_t pos, size_t n); -void delete_write_cache(files_struct *fsp); -void set_filelen_write_cache(files_struct *fsp, off_t file_size); -ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason); NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_through); /* The following definitions come from smbd/filename.c */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6c71b57e046..9e126cd3692 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3643,7 +3643,6 @@ static void send_file_readbraw(connection_struct *conn, */ if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) && - (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) { ssize_t sendfile_read = -1; char header[4]; @@ -3827,8 +3826,6 @@ void reply_readbraw(struct smb_request *req) return; } - flush_write_cache(fsp, SAMBA_READRAW_FLUSH); - startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0); if(req->wct == 10) { /* @@ -4215,7 +4212,6 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, if (!req_is_in_chain(req) && !req->encrypted && (fsp->base_fsp == NULL) && - (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) { uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */]; DATA_BLOB header; @@ -5446,8 +5442,6 @@ void reply_lseek(struct smb_request *req) return; } - flush_write_cache(fsp, SAMBA_SEEK_FLUSH); - mode = SVAL(req->vwv+1, 0) & 3; /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */ startpos = (off_t)IVALS(req->vwv+2, 0); diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c index 470a8df4944..86d5bbc58f0 100644 --- a/source3/smbd/smb2_flush.c +++ b/source3/smbd/smb2_flush.c @@ -125,7 +125,6 @@ static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx, struct tevent_req *subreq; struct smbd_smb2_flush_state *state; struct smb_request *smbreq; - int ret; req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_flush_state); @@ -187,12 +186,6 @@ static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - ret = flush_write_cache(fsp, SAMBA_SYNC_FLUSH); - if (ret == -1) { - tevent_req_nterror(req, map_nt_error_from_unix(errno)); - return tevent_req_post(req, ev); - } - subreq = SMB_VFS_FSYNC_SEND(state, ev, fsp); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index a7d2496bc6f..e84584349ab 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -355,7 +355,6 @@ static NTSTATUS schedule_smb2_sendfile_read(struct smbd_smb2_request *smb2req, smb2req->do_encryption || smbd_smb2_is_compound(smb2req) || (fsp->base_fsp != NULL) || - (fsp->wcp != NULL) || (!S_ISREG(fsp->fsp_name->st.st_ex_mode)) || (state->in_offset >= fsp->fsp_name->st.st_ex_size) || (fsp->fsp_name->st.st_ex_size < state->in_offset + state->in_length)) diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index a104921784f..dbf42cd56f4 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -515,10 +515,7 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK); - flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH); - if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) { - set_filelen_write_cache(fsp, len); - } + ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len); contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK); @@ -585,9 +582,7 @@ int vfs_set_filelen(files_struct *fsp, off_t len) DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp_str_dbg(fsp), (double)len)); - flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH); if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) { - set_filelen_write_cache(fsp, len); notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_ATTRIBUTES, @@ -676,8 +671,6 @@ int vfs_fill_sparse(files_struct *fsp, off_t len) contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE); - flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH); - offset = fsp->fsp_name->st.st_ex_size; num_to_write = len - fsp->fsp_name->st.st_ex_size; @@ -703,10 +696,6 @@ int vfs_fill_sparse(files_struct *fsp, off_t len) out: - if (ret == 0) { - set_filelen_write_cache(fsp, len); - } - contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE); return ret; } -- 2.34.1