関数 | |
static BOOL | setup_write_cache (files_struct *, SMB_OFF_T) |
static BOOL | read_from_write_cache (files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) |
ssize_t | read_file (files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) |
static ssize_t | real_write_file (files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n) |
static int | wcp_file_size_change (files_struct *fsp) |
ssize_t | write_file (files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n) |
void | delete_write_cache (files_struct *fsp) |
void | set_filelen_write_cache (files_struct *fsp, SMB_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) |
int | fsp_stat (files_struct *fsp, SMB_STRUCT_STAT *pst) |
変数 | |
static unsigned int | allocated_write_caches |
static BOOL setup_write_cache | ( | files_struct * | , | |
SMB_OFF_T | ||||
) | [static] |
参照先 write_cache::alloc_size・allocated_write_caches・files_struct::conn・write_cache::data・write_cache::data_size・write_cache::file_size・files_struct::fsp_name・write_cache::offset・files_struct::wcp.
参照元 write_file().
00744 { 00745 ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn)); 00746 write_cache *wcp; 00747 00748 if (allocated_write_caches >= MAX_WRITE_CACHES) { 00749 return False; 00750 } 00751 00752 if(alloc_size == 0 || fsp->wcp) { 00753 return False; 00754 } 00755 00756 if((wcp = SMB_MALLOC_P(write_cache)) == NULL) { 00757 DEBUG(0,("setup_write_cache: malloc fail.\n")); 00758 return False; 00759 } 00760 00761 wcp->file_size = file_size; 00762 wcp->offset = 0; 00763 wcp->alloc_size = alloc_size; 00764 wcp->data_size = 0; 00765 if((wcp->data = (char *)SMB_MALLOC(wcp->alloc_size)) == NULL) { 00766 DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n", 00767 (unsigned int)wcp->alloc_size )); 00768 SAFE_FREE(wcp); 00769 return False; 00770 } 00771 00772 memset(wcp->data, '\0', wcp->alloc_size ); 00773 00774 fsp->wcp = wcp; 00775 DO_PROFILE_INC(writecache_allocated_write_caches); 00776 allocated_write_caches++; 00777 00778 DEBUG(10,("setup_write_cache: File %s allocated write cache size %lu\n", 00779 fsp->fsp_name, (unsigned long)wcp->alloc_size )); 00780 00781 return True; 00782 }
static BOOL read_from_write_cache | ( | files_struct * | fsp, | |
char * | data, | |||
SMB_OFF_T | pos, | |||
size_t | n | |||
) | [static] |
参照先 write_cache::data・write_cache::data_size・write_cache::offset・files_struct::wcp.
参照元 read_file().
00032 { 00033 write_cache *wcp = fsp->wcp; 00034 00035 if(!wcp) { 00036 return False; 00037 } 00038 00039 if( n > wcp->data_size || pos < wcp->offset || pos + n > wcp->offset + wcp->data_size) { 00040 return False; 00041 } 00042 00043 memcpy(data, wcp->data + (pos - wcp->offset), n); 00044 00045 DO_PROFILE_INC(writecache_read_hits); 00046 00047 return True; 00048 }
ssize_t read_file | ( | files_struct * | fsp, | |
char * | data, | |||
SMB_OFF_T | pos, | |||
size_t | n | |||
) |
参照先 errno・fd_handle::fd・files_struct::fh・flush_write_cache()・files_struct::fsp_name・fd_handle::pos・fd_handle::position_information・files_struct::print_file・read_from_write_cache().
参照元 fake_sendfile()・reply_lockread()・reply_read()・reply_readbmpx()・send_file_readbraw()・send_file_readX().
00055 { 00056 ssize_t ret=0,readret; 00057 00058 /* you can't read from print files */ 00059 if (fsp->print_file) { 00060 return -1; 00061 } 00062 00063 /* 00064 * Serve from write cache if we can. 00065 */ 00066 00067 if(read_from_write_cache(fsp, data, pos, n)) { 00068 fsp->fh->pos = pos + n; 00069 fsp->fh->position_information = fsp->fh->pos; 00070 return n; 00071 } 00072 00073 flush_write_cache(fsp, READ_FLUSH); 00074 00075 fsp->fh->pos = pos; 00076 00077 if (n > 0) { 00078 #ifdef DMF_FIX 00079 int numretries = 3; 00080 tryagain: 00081 readret = SMB_VFS_PREAD(fsp,fsp->fh->fd,data,n,pos); 00082 00083 if (readret == -1) { 00084 if ((errno == EAGAIN) && numretries) { 00085 DEBUG(3,("read_file EAGAIN retry in 10 seconds\n")); 00086 (void)sleep(10); 00087 --numretries; 00088 goto tryagain; 00089 } 00090 return -1; 00091 } 00092 #else /* NO DMF fix. */ 00093 readret = SMB_VFS_PREAD(fsp,fsp->fh->fd,data,n,pos); 00094 00095 if (readret == -1) { 00096 return -1; 00097 } 00098 #endif 00099 if (readret > 0) { 00100 ret += readret; 00101 } 00102 } 00103 00104 DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n", 00105 fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); 00106 00107 fsp->fh->pos += ret; 00108 fsp->fh->position_information = fsp->fh->pos; 00109 00110 return(ret); 00111 }
static ssize_t real_write_file | ( | files_struct * | fsp, | |
const char * | data, | |||
SMB_OFF_T | pos, | |||
size_t | n | |||
) | [static] |
参照先 files_struct::conn・files_struct::fh・files_struct::fsp_name・files_struct::last_write_time・null_timespec()・files_struct::pending_modtime・files_struct::pending_modtime_owner・fd_handle::pos・timespec_current()・vfs_fill_sparse()・vfs_pwrite_data()・vfs_write_data().
参照元 flush_write_cache()・write_file().
00121 { 00122 ssize_t ret; 00123 00124 if (pos == -1) { 00125 ret = vfs_write_data(fsp, data, n); 00126 } else { 00127 fsp->fh->pos = pos; 00128 if (pos && lp_strict_allocate(SNUM(fsp->conn))) { 00129 if (vfs_fill_sparse(fsp, pos) == -1) { 00130 return -1; 00131 } 00132 } 00133 ret = vfs_pwrite_data(fsp, data, n, pos); 00134 } 00135 00136 DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n", 00137 fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); 00138 00139 if (ret != -1) { 00140 fsp->fh->pos += ret; 00141 00142 /* 00143 * It turns out that setting the last write time from a Windows 00144 * client stops any subsequent writes from updating the write time. 00145 * Doing this after the write gives a race condition here where 00146 * a stat may see the changed write time before we reset it here, 00147 * but it's cheaper than having to store the write time in shared 00148 * memory and look it up using dev/inode across all running smbd's. 00149 * The 99% solution will hopefully be good enough in this case. JRA. 00150 */ 00151 00152 if (!null_timespec(fsp->pending_modtime)) { 00153 set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime); 00154 00155 /* If we didn't get the "set modtime" call ourselves, we must 00156 store the last write time to restore on close. JRA. */ 00157 if (!fsp->pending_modtime_owner) { 00158 fsp->last_write_time = timespec_current(); 00159 } 00160 } 00161 00162 /* Yes - this is correct - writes don't update this. JRA. */ 00163 /* Found by Samba4 tests. */ 00164 #if 0 00165 fsp->position_information = fsp->pos; 00166 #endif 00167 } 00168 00169 return ret; 00170 }
static int wcp_file_size_change | ( | files_struct * | fsp | ) | [static] |
参照先 write_cache::data_size・errno・fd_handle::fd・files_struct::fh・write_cache::file_size・files_struct::fsp_name・write_cache::offset・strerror()・files_struct::wcp.
参照元 write_file().
00178 { 00179 int ret; 00180 write_cache *wcp = fsp->wcp; 00181 00182 wcp->file_size = wcp->offset + wcp->data_size; 00183 ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, wcp->file_size); 00184 if (ret == -1) { 00185 DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f error %s\n", 00186 fsp->fsp_name, (double)wcp->file_size, strerror(errno) )); 00187 } 00188 return ret; 00189 }
ssize_t write_file | ( | files_struct * | fsp, | |
const char * | data, | |||
SMB_OFF_T | pos, | |||
size_t | n | |||
) |
参照先 write_cache::alloc_size・files_struct::can_write・files_struct::conn・write_cache::data・write_cache::data_size・errno・fd_handle::fd・files_struct::fh・write_cache::file_size・flush_write_cache()・files_struct::fsp_name・files_struct::modified・write_cache::offset・files_struct::oplock_type・fd_handle::pos・files_struct::print_file・print_job_write()・profile_p・files_struct::rap_print_jobid・rap_to_pjobid()・real_write_file()・release_level_2_oplocks_on_change()・setup_write_cache()・files_struct::wcp・wcp_file_size_change()・profile_stats::writecache_abutted_writes・profile_stats::writecache_allocated_write_caches・profile_stats::writecache_direct_writes・profile_stats::writecache_flushed_writes・profile_stats::writecache_init_writes・profile_stats::writecache_non_oplock_writes・profile_stats::writecache_num_perfect_writes・profile_stats::writecache_num_write_caches・profile_stats::writecache_read_hits・profile_stats::writecache_total_writes.
参照元 reply_printwrite()・reply_write()・reply_write_and_X()・reply_writebmpx()・reply_writebraw()・reply_writebs()・reply_writeclose()・reply_writeunlock().
00196 { 00197 write_cache *wcp = fsp->wcp; 00198 ssize_t total_written = 0; 00199 int write_path = -1; 00200 00201 if (fsp->print_file) { 00202 fstring sharename; 00203 uint32 jobid; 00204 00205 if (!rap_to_pjobid(fsp->rap_print_jobid, sharename, &jobid)) { 00206 DEBUG(3,("write_file: Unable to map RAP jobid %u to jobid.\n", 00207 (unsigned int)fsp->rap_print_jobid )); 00208 errno = EBADF; 00209 return -1; 00210 } 00211 00212 return print_job_write(SNUM(fsp->conn), jobid, data, pos, n); 00213 } 00214 00215 if (!fsp->can_write) { 00216 errno = EPERM; 00217 return -1; 00218 } 00219 00220 if (!fsp->modified) { 00221 SMB_STRUCT_STAT st; 00222 fsp->modified = True; 00223 00224 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) { 00225 int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); 00226 if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { 00227 file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st, False); 00228 } 00229 00230 /* 00231 * If this is the first write and we have an exclusive oplock then setup 00232 * the write cache. 00233 */ 00234 00235 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) { 00236 setup_write_cache(fsp, st.st_size); 00237 wcp = fsp->wcp; 00238 } 00239 } 00240 } 00241 00242 #ifdef WITH_PROFILE 00243 DO_PROFILE_INC(writecache_total_writes); 00244 if (!fsp->oplock_type) { 00245 DO_PROFILE_INC(writecache_non_oplock_writes); 00246 } 00247 #endif 00248 00249 /* 00250 * If this file is level II oplocked then we need 00251 * to grab the shared memory lock and inform all 00252 * other files with a level II lock that they need 00253 * to flush their read caches. We keep the lock over 00254 * the shared memory area whilst doing this. 00255 */ 00256 00257 release_level_2_oplocks_on_change(fsp); 00258 00259 #ifdef WITH_PROFILE 00260 if (profile_p && profile_p->writecache_total_writes % 500 == 0) { 00261 DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u total=%u \ 00262 nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", 00263 profile_p->writecache_init_writes, 00264 profile_p->writecache_abutted_writes, 00265 profile_p->writecache_total_writes, 00266 profile_p->writecache_non_oplock_writes, 00267 profile_p->writecache_allocated_write_caches, 00268 profile_p->writecache_num_write_caches, 00269 profile_p->writecache_direct_writes, 00270 profile_p->writecache_num_perfect_writes, 00271 profile_p->writecache_read_hits )); 00272 00273 DEBUG(3,("WRITECACHE: Flushes SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n", 00274 profile_p->writecache_flushed_writes[SEEK_FLUSH], 00275 profile_p->writecache_flushed_writes[READ_FLUSH], 00276 profile_p->writecache_flushed_writes[WRITE_FLUSH], 00277 profile_p->writecache_flushed_writes[READRAW_FLUSH], 00278 profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH], 00279 profile_p->writecache_flushed_writes[CLOSE_FLUSH], 00280 profile_p->writecache_flushed_writes[SYNC_FLUSH] )); 00281 } 00282 #endif 00283 00284 if(!wcp) { 00285 DO_PROFILE_INC(writecache_direct_writes); 00286 total_written = real_write_file(fsp, data, pos, n); 00287 return total_written; 00288 } 00289 00290 DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n", 00291 fsp->fsp_name, fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size)); 00292 00293 fsp->fh->pos = pos + n; 00294 00295 /* 00296 * If we have active cache and it isn't contiguous then we flush. 00297 * NOTE: There is a small problem with running out of disk .... 00298 */ 00299 00300 if (wcp->data_size) { 00301 BOOL cache_flush_needed = False; 00302 00303 if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) { 00304 00305 /* ASCII art.... JRA. 00306 00307 +--------------+----- 00308 | Cached data | Rest of allocated cache buffer.... 00309 +--------------+----- 00310 00311 +-------------------+ 00312 | Data to write | 00313 +-------------------+ 00314 00315 */ 00316 00317 /* 00318 * Start of write overlaps or abutts the existing data. 00319 */ 00320 00321 size_t data_used = MIN((wcp->alloc_size - (pos - wcp->offset)), n); 00322 00323 memcpy(wcp->data + (pos - wcp->offset), data, data_used); 00324 00325 /* 00326 * Update the current buffer size with the new data. 00327 */ 00328 00329 if(pos + data_used > wcp->offset + wcp->data_size) { 00330 wcp->data_size = pos + data_used - wcp->offset; 00331 } 00332 00333 /* 00334 * Update the file size if changed. 00335 */ 00336 00337 if (wcp->offset + wcp->data_size > wcp->file_size) { 00338 if (wcp_file_size_change(fsp) == -1) { 00339 return -1; 00340 } 00341 } 00342 00343 /* 00344 * If we used all the data then 00345 * return here. 00346 */ 00347 00348 if(n == data_used) { 00349 return n; 00350 } else { 00351 cache_flush_needed = True; 00352 } 00353 /* 00354 * Move the start of data forward by the amount used, 00355 * cut down the amount left by the same amount. 00356 */ 00357 00358 data += data_used; 00359 pos += data_used; 00360 n -= data_used; 00361 00362 DO_PROFILE_INC(writecache_abutted_writes); 00363 total_written = data_used; 00364 00365 write_path = 1; 00366 00367 } else if ((pos < wcp->offset) && (pos + n > wcp->offset) && 00368 (pos + n <= wcp->offset + wcp->alloc_size)) { 00369 00370 /* ASCII art.... JRA. 00371 00372 +---------------+ 00373 | Cache buffer | 00374 +---------------+ 00375 00376 +-------------------+ 00377 | Data to write | 00378 +-------------------+ 00379 00380 */ 00381 00382 /* 00383 * End of write overlaps the existing data. 00384 */ 00385 00386 size_t data_used = pos + n - wcp->offset; 00387 00388 memcpy(wcp->data, data + n - data_used, data_used); 00389 00390 /* 00391 * Update the current buffer size with the new data. 00392 */ 00393 00394 if(pos + n > wcp->offset + wcp->data_size) { 00395 wcp->data_size = pos + n - wcp->offset; 00396 } 00397 00398 /* 00399 * Update the file size if changed. 00400 */ 00401 00402 if (wcp->offset + wcp->data_size > wcp->file_size) { 00403 if (wcp_file_size_change(fsp) == -1) { 00404 return -1; 00405 } 00406 } 00407 00408 /* 00409 * We don't need to move the start of data, but we 00410 * cut down the amount left by the amount used. 00411 */ 00412 00413 n -= data_used; 00414 00415 /* 00416 * We cannot have used all the data here. 00417 */ 00418 00419 cache_flush_needed = True; 00420 00421 DO_PROFILE_INC(writecache_abutted_writes); 00422 total_written = data_used; 00423 00424 write_path = 2; 00425 00426 } else if ( (pos >= wcp->file_size) && 00427 (wcp->offset + wcp->data_size == wcp->file_size) && 00428 (pos > wcp->offset + wcp->data_size) && 00429 (pos < wcp->offset + wcp->alloc_size) ) { 00430 00431 /* ASCII art.... JRA. 00432 00433 End of file ---->| 00434 00435 +---------------+---------------+ 00436 | Cached data | Cache buffer | 00437 +---------------+---------------+ 00438 00439 +-------------------+ 00440 | Data to write | 00441 +-------------------+ 00442 00443 */ 00444 00445 /* 00446 * Non-contiguous write part of which fits within 00447 * the cache buffer and is extending the file 00448 * and the cache contents reflect the current 00449 * data up to the current end of the file. 00450 */ 00451 00452 size_t data_used; 00453 00454 if(pos + n <= wcp->offset + wcp->alloc_size) { 00455 data_used = n; 00456 } else { 00457 data_used = wcp->offset + wcp->alloc_size - pos; 00458 } 00459 00460 /* 00461 * Fill in the non-continuous area with zeros. 00462 */ 00463 00464 memset(wcp->data + wcp->data_size, '\0', 00465 pos - (wcp->offset + wcp->data_size) ); 00466 00467 memcpy(wcp->data + (pos - wcp->offset), data, data_used); 00468 00469 /* 00470 * Update the current buffer size with the new data. 00471 */ 00472 00473 if(pos + data_used > wcp->offset + wcp->data_size) { 00474 wcp->data_size = pos + data_used - wcp->offset; 00475 } 00476 00477 /* 00478 * Update the file size if changed. 00479 */ 00480 00481 if (wcp->offset + wcp->data_size > wcp->file_size) { 00482 if (wcp_file_size_change(fsp) == -1) { 00483 return -1; 00484 } 00485 } 00486 00487 /* 00488 * If we used all the data then 00489 * return here. 00490 */ 00491 00492 if(n == data_used) { 00493 return n; 00494 } else { 00495 cache_flush_needed = True; 00496 } 00497 00498 /* 00499 * Move the start of data forward by the amount used, 00500 * cut down the amount left by the same amount. 00501 */ 00502 00503 data += data_used; 00504 pos += data_used; 00505 n -= data_used; 00506 00507 DO_PROFILE_INC(writecache_abutted_writes); 00508 total_written = data_used; 00509 00510 write_path = 3; 00511 00512 } else if ( (pos >= wcp->file_size) && 00513 (n == 1) && 00514 (wcp->file_size == wcp->offset + wcp->data_size) && 00515 (pos < wcp->file_size + wcp->alloc_size)) { 00516 00517 /* 00518 00519 End of file ---->| 00520 00521 +---------------+---------------+ 00522 | Cached data | Cache buffer | 00523 +---------------+---------------+ 00524 00525 |<------- allocated size ---------------->| 00526 00527 +--------+ 00528 | 1 Byte | 00529 +--------+ 00530 00531 MS-Office seems to do this a lot to determine if there's enough 00532 space on the filesystem to write a new file. 00533 00534 Change to : 00535 00536 End of file ---->| 00537 +-----------------------+--------+ 00538 | Zeroed Cached data | 1 Byte | 00539 +-----------------------+--------+ 00540 */ 00541 00542 flush_write_cache(fsp, WRITE_FLUSH); 00543 wcp->offset = wcp->file_size; 00544 wcp->data_size = pos - wcp->file_size + 1; 00545 memset(wcp->data, '\0', wcp->data_size); 00546 memcpy(wcp->data + wcp->data_size-1, data, 1); 00547 00548 /* 00549 * Update the file size if changed. 00550 */ 00551 00552 if (wcp->offset + wcp->data_size > wcp->file_size) { 00553 if (wcp_file_size_change(fsp) == -1) { 00554 return -1; 00555 } 00556 } 00557 00558 return n; 00559 00560 } else { 00561 00562 /* ASCII art..... JRA. 00563 00564 Case 1). 00565 00566 +---------------+---------------+ 00567 | Cached data | Cache buffer | 00568 +---------------+---------------+ 00569 00570 +-------------------+ 00571 | Data to write | 00572 +-------------------+ 00573 00574 Case 2). 00575 00576 +---------------+---------------+ 00577 | Cached data | Cache buffer | 00578 +---------------+---------------+ 00579 00580 +-------------------+ 00581 | Data to write | 00582 +-------------------+ 00583 00584 Case 3). 00585 00586 +---------------+---------------+ 00587 | Cached data | Cache buffer | 00588 +---------------+---------------+ 00589 00590 +-----------------------------------------------------+ 00591 | Data to write | 00592 +-----------------------------------------------------+ 00593 00594 */ 00595 00596 /* 00597 * Write is bigger than buffer, or there is no overlap on the 00598 * low or high ends. 00599 */ 00600 00601 DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \ 00602 len = %u\n",fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size )); 00603 00604 /* 00605 * If write would fit in the cache, and is larger than 00606 * the data already in the cache, flush the cache and 00607 * preferentially copy the data new data into it. Otherwise 00608 * just write the data directly. 00609 */ 00610 00611 if ( n <= wcp->alloc_size && n > wcp->data_size) { 00612 cache_flush_needed = True; 00613 } else { 00614 ssize_t ret = real_write_file(fsp, data, pos, n); 00615 00616 /* 00617 * If the write overlaps the entire cache, then 00618 * discard the current contents of the cache. 00619 * Fix from Rasmus Borup Hansen rbh@math.ku.dk. 00620 */ 00621 00622 if ((pos <= wcp->offset) && 00623 (pos + n >= wcp->offset + wcp->data_size) ) { 00624 DEBUG(9,("write_file: discarding overwritten write \ 00625 cache: fd = %d, off=%.0f, size=%u\n", fsp->fh->fd, (double)wcp->offset, (unsigned int)wcp->data_size )); 00626 wcp->data_size = 0; 00627 } 00628 00629 DO_PROFILE_INC(writecache_direct_writes); 00630 if (ret == -1) { 00631 return ret; 00632 } 00633 00634 if (pos + ret > wcp->file_size) { 00635 wcp->file_size = pos + ret; 00636 } 00637 00638 return ret; 00639 } 00640 00641 write_path = 4; 00642 00643 } 00644 00645 if (cache_flush_needed) { 00646 DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \ 00647 n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", 00648 write_path, fsp->fh->fd, (double)wcp->file_size, (double)pos, (unsigned int)n, 00649 (double)wcp->offset, (unsigned int)wcp->data_size )); 00650 00651 flush_write_cache(fsp, WRITE_FLUSH); 00652 } 00653 } 00654 00655 /* 00656 * If the write request is bigger than the cache 00657 * size, write it all out. 00658 */ 00659 00660 if (n > wcp->alloc_size ) { 00661 ssize_t ret = real_write_file(fsp, data, pos, n); 00662 if (ret == -1) { 00663 return -1; 00664 } 00665 00666 if (pos + ret > wcp->file_size) { 00667 wcp->file_size = pos + n; 00668 } 00669 00670 DO_PROFILE_INC(writecache_direct_writes); 00671 return total_written + n; 00672 } 00673 00674 /* 00675 * If there's any data left, cache it. 00676 */ 00677 00678 if (n) { 00679 #ifdef WITH_PROFILE 00680 if (wcp->data_size) { 00681 DO_PROFILE_INC(writecache_abutted_writes); 00682 } else { 00683 DO_PROFILE_INC(writecache_init_writes); 00684 } 00685 #endif 00686 memcpy(wcp->data+wcp->data_size, data, n); 00687 if (wcp->data_size == 0) { 00688 wcp->offset = pos; 00689 DO_PROFILE_INC(writecache_num_write_caches); 00690 } 00691 wcp->data_size += n; 00692 00693 /* 00694 * Update the file size if changed. 00695 */ 00696 00697 if (wcp->offset + wcp->data_size > wcp->file_size) { 00698 if (wcp_file_size_change(fsp) == -1) { 00699 return -1; 00700 } 00701 } 00702 DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n", 00703 (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n)); 00704 00705 total_written += n; 00706 return total_written; /* .... that's a write :) */ 00707 } 00708 00709 return total_written; 00710 }
void delete_write_cache | ( | files_struct * | fsp | ) |
参照先 allocated_write_caches・write_cache::data・write_cache::data_size・files_struct::fsp_name・files_struct::wcp.
参照元 close_filestruct().
00717 { 00718 write_cache *wcp; 00719 00720 if(!fsp) { 00721 return; 00722 } 00723 00724 if(!(wcp = fsp->wcp)) { 00725 return; 00726 } 00727 00728 DO_PROFILE_DEC(writecache_allocated_write_caches); 00729 allocated_write_caches--; 00730 00731 SMB_ASSERT(wcp->data_size == 0); 00732 00733 SAFE_FREE(wcp->data); 00734 SAFE_FREE(fsp->wcp); 00735 00736 DEBUG(10,("delete_write_cache: File %s deleted write cache\n", fsp->fsp_name )); 00737 }
void set_filelen_write_cache | ( | files_struct * | fsp, | |
SMB_OFF_T | file_size | |||
) |
参照先 write_cache::data_size・write_cache::file_size・files_struct::fsp_name・smb_panic()・files_struct::wcp.
参照元 vfs_allocate_file_space()・vfs_fill_sparse()・vfs_set_filelen().
00789 { 00790 if(fsp->wcp) { 00791 /* The cache *must* have been flushed before we do this. */ 00792 if (fsp->wcp->data_size != 0) { 00793 pstring msg; 00794 slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \ 00795 on file %s with write cache size = %lu\n", fsp->fsp_name, (unsigned long)fsp->wcp->data_size ); 00796 smb_panic(msg); 00797 } 00798 fsp->wcp->file_size = file_size; 00799 } 00800 }
ssize_t flush_write_cache | ( | files_struct * | fsp, | |
enum flush_reason_enum | reason | |||
) |
参照先 write_cache::alloc_size・write_cache::data・write_cache::data_size・fd_handle::fd・files_struct::fh・write_cache::file_size・write_cache::offset・real_write_file()・files_struct::wcp.
参照元 close_filestruct()・read_file()・release_file_oplock()・reply_lseek()・reply_readbraw()・sync_file()・vfs_allocate_file_space()・vfs_fill_sparse()・vfs_set_filelen()・write_file().
00807 { 00808 write_cache *wcp = fsp->wcp; 00809 size_t data_size; 00810 ssize_t ret; 00811 00812 if(!wcp || !wcp->data_size) { 00813 return 0; 00814 } 00815 00816 data_size = wcp->data_size; 00817 wcp->data_size = 0; 00818 00819 DO_PROFILE_DEC_INC(writecache_num_write_caches,writecache_flushed_writes[reason]); 00820 00821 DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", 00822 fsp->fh->fd, (double)wcp->offset, (unsigned int)data_size)); 00823 00824 #ifdef WITH_PROFILE 00825 if(data_size == wcp->alloc_size) { 00826 DO_PROFILE_INC(writecache_num_perfect_writes); 00827 } 00828 #endif 00829 00830 ret = real_write_file(fsp, wcp->data, wcp->offset, data_size); 00831 00832 /* 00833 * Ensure file size if kept up to date if write extends file. 00834 */ 00835 00836 if ((ret != -1) && (wcp->offset + ret > wcp->file_size)) { 00837 wcp->file_size = wcp->offset + ret; 00838 } 00839 00840 return ret; 00841 }
NTSTATUS sync_file | ( | connection_struct * | conn, | |
files_struct * | fsp, | |||
BOOL | write_through | |||
) |
参照先 errno・fd_handle::fd・files_struct::fh・flush_write_cache()・map_nt_error_from_unix().
参照元 file_sync_all()・handle_aio_write_complete()・reply_flush()・reply_write()・reply_write_and_X()・reply_writebmpx()・reply_writebraw()・reply_writebs()・reply_writeunlock().
00848 { 00849 if (fsp->fh->fd == -1) 00850 return NT_STATUS_INVALID_HANDLE; 00851 00852 if (lp_strict_sync(SNUM(conn)) && 00853 (lp_syncalways(SNUM(conn)) || write_through)) { 00854 int ret = flush_write_cache(fsp, SYNC_FLUSH); 00855 if (ret == -1) { 00856 return map_nt_error_from_unix(errno); 00857 } 00858 ret = SMB_VFS_FSYNC(fsp,fsp->fh->fd); 00859 if (ret == -1) { 00860 return map_nt_error_from_unix(errno); 00861 } 00862 } 00863 return NT_STATUS_OK; 00864 }
int fsp_stat | ( | files_struct * | fsp, | |
SMB_STRUCT_STAT * | pst | |||
) |
参照先 files_struct::conn・fd_handle::fd・files_struct::fh・files_struct::fsp_name.
参照元 reply_getattrE().
00871 { 00872 if (fsp->fh->fd == -1) { 00873 return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst); 00874 } else { 00875 return SMB_VFS_FSTAT(fsp,fsp->fh->fd, pst); 00876 } 00877 }
unsigned int allocated_write_caches [static] |