summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/aio.c4
-rw-r--r--source3/smbd/fileio.c4
-rw-r--r--source3/smbd/oplock.c25
-rw-r--r--source3/smbd/oplock_irix.c6
-rw-r--r--source3/smbd/oplock_linux.c6
-rw-r--r--source3/smbd/reply.c11
-rw-r--r--source3/smbd/vfs.c33
7 files changed, 62 insertions, 27 deletions
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c
index 75ce07d41a..6b19e098e5 100644
--- a/source3/smbd/aio.c
+++ b/source3/smbd/aio.c
@@ -291,7 +291,9 @@ bool schedule_aio_write_and_X(connection_struct *conn,
aio_ex->req = talloc_move(aio_ex, &req);
- release_level_2_oplocks_on_change(fsp);
+ /* This should actually be improved to span the write. */
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
if (!write_through && !lp_syncalways(SNUM(fsp->conn))
&& fsp->aio_write_behind) {
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 3e3f0943b3..a9a97a2d14 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -318,7 +318,9 @@ ssize_t write_file(struct smb_request *req,
* the shared memory area whilst doing this.
*/
- release_level_2_oplocks_on_change(fsp);
+ /* This should actually be improved to span the write. */
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
#ifdef WITH_PROFILE
if (profile_p && profile_p->writecache_total_writes % 500 == 0) {
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 0945ac6677..4c84fd41ed 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -329,7 +329,7 @@ static void add_oplock_timeout_handler(files_struct *fsp)
the client for LEVEL2.
*******************************************************************/
-static void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx,
+void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx,
void *private_data,
uint32_t msg_type,
struct server_id src,
@@ -699,7 +699,8 @@ static void process_open_retry_message(struct messaging_context *msg_ctx,
none.
****************************************************************************/
-void release_level_2_oplocks_on_change(files_struct *fsp)
+static void contend_level2_oplocks_begin_default(files_struct *fsp,
+ enum level2_contention_type type)
{
int i;
struct share_mode_lock *lck;
@@ -799,6 +800,26 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
TALLOC_FREE(lck);
}
+void contend_level2_oplocks_begin(files_struct *fsp,
+ enum level2_contention_type type)
+{
+ if (koplocks && koplocks->ops->contend_level2_oplocks_begin) {
+ koplocks->ops->contend_level2_oplocks_begin(fsp, type);
+ return;
+ }
+
+ contend_level2_oplocks_begin_default(fsp, type);
+}
+
+void contend_level2_oplocks_end(files_struct *fsp,
+ enum level2_contention_type type)
+{
+ /* Only kernel oplocks implement this so far */
+ if (koplocks && koplocks->ops->contend_level2_oplocks_end) {
+ koplocks->ops->contend_level2_oplocks_end(fsp, type);
+ }
+}
+
/****************************************************************************
Linearize a share mode entry struct to an internal oplock break message.
****************************************************************************/
diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c
index 23b2fa9081..bbc9132a08 100644
--- a/source3/smbd/oplock_irix.c
+++ b/source3/smbd/oplock_irix.c
@@ -270,8 +270,10 @@ static void irix_oplocks_read_fde_handler(struct event_context *ev,
****************************************************************************/
static const struct kernel_oplocks_ops irix_koplocks = {
- .set_oplock = irix_set_kernel_oplock,
- .release_oplock = irix_release_kernel_oplock,
+ .set_oplock = irix_set_kernel_oplock,
+ .release_oplock = irix_release_kernel_oplock,
+ .contend_level2_oplocks_begin = NULL,
+ .contend_level2_oplocks_end = NULL,
};
struct kernel_oplocks *irix_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c
index 5840ff0851..273fbfdc01 100644
--- a/source3/smbd/oplock_linux.c
+++ b/source3/smbd/oplock_linux.c
@@ -179,8 +179,10 @@ static bool linux_oplocks_available(void)
****************************************************************************/
static const struct kernel_oplocks_ops linux_koplocks = {
- .set_oplock = linux_set_kernel_oplock,
- .release_oplock = linux_release_kernel_oplock,
+ .set_oplock = linux_set_kernel_oplock,
+ .release_oplock = linux_release_kernel_oplock,
+ .contend_level2_oplocks_begin = NULL,
+ .contend_level2_oplocks_end = NULL,
};
struct kernel_oplocks *linux_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 60e2e5dc7a..151f9d0827 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3010,8 +3010,6 @@ void reply_lockread(struct smb_request *req)
return;
}
- release_level_2_oplocks_on_change(fsp);
-
numtoread = SVAL(req->vwv+1, 0);
startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
@@ -4497,8 +4495,6 @@ void reply_lock(struct smb_request *req)
return;
}
- release_level_2_oplocks_on_change(fsp);
-
count = (uint64_t)IVAL(req->vwv+1, 0);
offset = (uint64_t)IVAL(req->vwv+3, 0);
@@ -6870,13 +6866,6 @@ void reply_lockingX(struct smb_request *req)
}
}
- /*
- * We do this check *after* we have checked this is not a oplock break
- * response message. JRA.
- */
-
- release_level_2_oplocks_on_change(fsp);
-
if (req->buflen <
(num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
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;
}
/****************************************************************************