summaryrefslogtreecommitdiff
path: root/source3/smbd/vfs.c
diff options
context:
space:
mode:
authorTim Prouty <tprouty@samba.org>2009-02-03 11:56:35 -0800
committerTim Prouty <tprouty@samba.org>2009-02-09 23:47:45 -0800
commitc6f1f055fdeee29ad7c5b2ae9909e8f1b1a7daec (patch)
tree1fc919526e3c6988ede50457ad72b098d42c1be9 /source3/smbd/vfs.c
parent9c1310fa6ae1a67dc0fea3bf549d805ff167e78f (diff)
downloadsamba-c6f1f055fdeee29ad7c5b2ae9909e8f1b1a7daec.tar.gz
samba-c6f1f055fdeee29ad7c5b2ae9909e8f1b1a7daec.tar.bz2
samba-c6f1f055fdeee29ad7c5b2ae9909e8f1b1a7daec.zip
s3 oplocks: Make the level2 oplock contention API more granular
This replaces release_level2_oplocks_on_change with contend_level2_oplock_begin/end in order to contend level2 oplocks throughout an operation rather than just at the begining. This is necessary for some kernel oplock implementations, and also lays the groundwork for better correctness in Samba's standard level2 oplock handling. The next step for non-kernel oplocks is to add additional state to the share mode lock struct that prevents any new opens from granting oplocks while a contending operation is in progress. All operations that contend level 2 oplocks are now correctly spanned except for aio and synchronous writes. The two write paths both have non-trivial error paths that need extra care to get right. RAW-OPLOCK and the rest of 'make test' are still passing with this change.
Diffstat (limited to 'source3/smbd/vfs.c')
-rw-r--r--source3/smbd/vfs.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 515e557f67..8d82ca550c 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -514,8 +514,6 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
uint64_t space_avail;
uint64_t bsize,dfree,dsize;
- release_level_2_oplocks_on_change(fsp);
-
/*
* Actually try and commit the space on disk....
*/
@@ -541,15 +539,23 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n",
fsp->fsp_name, (double)st.st_size ));
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
+
flush_write_cache(fsp, SIZECHANGE_FLUSH);
if ((ret = SMB_VFS_FTRUNCATE(fsp, (SMB_OFF_T)len)) != -1) {
set_filelen_write_cache(fsp, len);
}
+
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
+
return ret;
}
/* Grow - we need to test if we have enough space. */
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
+
if (!lp_strict_allocate(SNUM(fsp->conn)))
return 0;
@@ -581,7 +587,8 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len)
{
int ret;
- release_level_2_oplocks_on_change(fsp);
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
+
DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len));
flush_write_cache(fsp, SIZECHANGE_FLUSH);
if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
@@ -592,6 +599,8 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len)
fsp->fsp_name);
}
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
+
return ret;
}
@@ -613,7 +622,6 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
size_t num_to_write;
ssize_t pwrite_ret;
- release_level_2_oplocks_on_change(fsp);
ret = SMB_VFS_FSTAT(fsp, &st);
if (ret == -1) {
return ret;
@@ -626,13 +634,16 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to len %.0f (%.0f bytes)\n",
fsp->fsp_name, (double)st.st_size, (double)len, (double)(len - st.st_size)));
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
+
flush_write_cache(fsp, SIZECHANGE_FLUSH);
if (!sparse_buf) {
sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
if (!sparse_buf) {
errno = ENOMEM;
- return -1;
+ ret = -1;
+ goto out;
}
}
@@ -647,17 +658,23 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
if (pwrite_ret == -1) {
DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n",
fsp->fsp_name, strerror(errno) ));
- return -1;
+ ret = -1;
+ goto out;
}
if (pwrite_ret == 0) {
- return 0;
+ ret = 0;
+ goto out;
}
total += pwrite_ret;
}
set_filelen_write_cache(fsp, len);
- return 0;
+
+ ret = 0;
+ out:
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
+ return ret;
}
/****************************************************************************