fileio.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 861 行 · 第 1/2 页

C
861
字号
                       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) &&			    (pos < wcp->offset + 2*wcp->alloc_size) &&			    (wcp->file_size == wcp->offset + wcp->data_size)) {                        /*                        +---------------+                        | Cached data   |                        +---------------+                                                         +--------+                                                         | 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.                        */			SMB_BIG_UINT new_start = wcp->offset + wcp->data_size;			flush_write_cache(fsp, WRITE_FLUSH);			wcp->offset = new_start;			wcp->data_size = pos - new_start + 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(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 int)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,("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, 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(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) {#ifdef WITH_PROFILE		if (wcp->data_size) {			DO_PROFILE_INC(writecache_abutted_writes);		} else {			DO_PROFILE_INC(writecache_init_writes);		}#endif		memcpy(wcp->data+wcp->data_size, data, n);		if (wcp->data_size == 0) {			wcp->offset = pos;			DO_PROFILE_INC(writecache_num_write_caches);		}		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 :) */	}  	return total_written;}/**************************************************************************** Delete the write cache structure.****************************************************************************/void delete_write_cache(files_struct *fsp){	write_cache *wcp;	if(!fsp) {		return;	}	if(!(wcp = fsp->wcp)) {		return;	}	DO_PROFILE_DEC(writecache_allocated_write_caches);	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->fsp_name ));}/**************************************************************************** Setup the write cache structure.****************************************************************************/static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size){	ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn));	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(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_allocated_write_caches);	allocated_write_caches++;	DEBUG(10,("setup_write_cache: File %s allocated write cache size %lu\n",		fsp->fsp_name, (unsigned long)wcp->alloc_size ));	return True;}/**************************************************************************** Cope with a size change.****************************************************************************/void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size){	if(fsp->wcp) {		/* The cache *must* have been flushed before we do this. */		if (fsp->wcp->data_size != 0) {			pstring msg;			slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \on file %s with write cache size = %lu\n", fsp->fsp_name, (unsigned long)fsp->wcp->data_size );			smb_panic(msg);		}		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){	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;	DO_PROFILE_DEC_INC(writecache_num_write_caches,writecache_flushed_writes[reason]);	DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n",		fsp->fh->fd, (double)wcp->offset, (unsigned int)data_size));#ifdef WITH_PROFILE	if(data_size == wcp->alloc_size) {		DO_PROFILE_INC(writecache_num_perfect_writes);	}#endif	ret = real_write_file(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********************************************************************/void sync_file(connection_struct *conn, files_struct *fsp, BOOL write_through){       	if (fsp->fh->fd == -1)		return;	if (lp_strict_sync(SNUM(conn)) &&	    (lp_syncalways(SNUM(conn)) || write_through)) {		flush_write_cache(fsp, SYNC_FLUSH);		SMB_VFS_FSYNC(fsp,fsp->fh->fd);	}}/************************************************************ Perform a stat whether a valid fd or not.************************************************************/int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst){	if (fsp->fh->fd == -1) {		return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst);	} else {		return SMB_VFS_FSTAT(fsp,fsp->fh->fd, pst);	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?