From fb6f52261a4cdbc529c04e28b29f82a8cbb9640f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 08:59:21 +0100 Subject: pvfs_wait: 'private' -> 'private_data' and use talloc_get_type() metze (This used to be commit 16a7d0cc37614fc41245fdcdf3b5a4a4a421f31d) --- source4/ntvfs/posix/pvfs_wait.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_wait.c b/source4/ntvfs/posix/pvfs_wait.c index 989985a033..838a801567 100644 --- a/source4/ntvfs/posix/pvfs_wait.c +++ b/source4/ntvfs/posix/pvfs_wait.c @@ -31,7 +31,7 @@ struct pvfs_wait { struct pvfs_wait *next, *prev; struct pvfs_state *pvfs; void (*handler)(void *, enum pvfs_wait_notice); - void *private; + void *private_data; int msg_type; struct messaging_context *msg_ctx; struct event_context *ev; @@ -45,20 +45,23 @@ struct pvfs_wait { previous ntvfs handlers in the chain (such as security context) */ NTSTATUS pvfs_async_setup(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, void *private) + struct ntvfs_request *req, void *private_data) { - struct pvfs_wait *pwait = private; - pwait->handler(pwait->private, pwait->reason); + struct pvfs_wait *pwait = talloc_get_type(private_data, + struct pvfs_wait); + pwait->handler(pwait->private_data, pwait->reason); return NT_STATUS_OK; } /* receive a completion message for a wait */ -static void pvfs_wait_dispatch(struct messaging_context *msg, void *private, uint32_t msg_type, +static void pvfs_wait_dispatch(struct messaging_context *msg, + void *private_data, uint32_t msg_type, struct server_id src, DATA_BLOB *data) { - struct pvfs_wait *pwait = private; + struct pvfs_wait *pwait = talloc_get_type(private_data, + struct pvfs_wait); struct ntvfs_request *req; void *p = NULL; @@ -70,7 +73,7 @@ static void pvfs_wait_dispatch(struct messaging_context *msg, void *private, uin pp = (void **)data->data; p = *pp; } - if (p == NULL || p != pwait->private) { + if (p == NULL || p != pwait->private_data) { return; } @@ -91,9 +94,11 @@ static void pvfs_wait_dispatch(struct messaging_context *msg, void *private, uin receive a timeout on a message wait */ static void pvfs_wait_timeout(struct event_context *ev, - struct timed_event *te, struct timeval t, void *private) + struct timed_event *te, struct timeval t, + void *private_data) { - struct pvfs_wait *pwait = talloc_get_type(private, struct pvfs_wait); + struct pvfs_wait *pwait = talloc_get_type(private_data, + struct pvfs_wait); struct ntvfs_request *req = pwait->req; pwait->reason = PVFS_WAIT_TIMEOUT; @@ -131,7 +136,7 @@ void *pvfs_wait_message(struct pvfs_state *pvfs, int msg_type, struct timeval end_time, void (*fn)(void *, enum pvfs_wait_notice), - void *private) + void *private_data) { struct pvfs_wait *pwait; @@ -140,7 +145,7 @@ void *pvfs_wait_message(struct pvfs_state *pvfs, return NULL; } - pwait->private = private; + pwait->private_data = private_data; pwait->handler = fn; pwait->msg_ctx = pvfs->ntvfs->ctx->msg_ctx; pwait->ev = pvfs->ntvfs->ctx->event_ctx; -- cgit From a0a0d4a5d0c24729a26a37ff54caa665de9149a2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 09:02:17 +0100 Subject: pvfs_wait: use struct pvfs_wait * instead of void * metze (This used to be commit 3b70331536d2402814db13a9f1f226a39373313a) --- source4/ntvfs/posix/pvfs_lock.c | 2 +- source4/ntvfs/posix/pvfs_notify.c | 8 +++++--- source4/ntvfs/posix/pvfs_open.c | 2 +- source4/ntvfs/posix/pvfs_wait.c | 12 ++++++------ source4/ntvfs/posix/vfs_posix.h | 2 ++ 5 files changed, 15 insertions(+), 11 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c index b9bb58c71d..df85b2b775 100644 --- a/source4/ntvfs/posix/pvfs_lock.c +++ b/source4/ntvfs/posix/pvfs_lock.c @@ -53,7 +53,7 @@ struct pvfs_pending_lock { struct pvfs_file *f; struct ntvfs_request *req; int pending_lock; - void *wait_handle; + struct pvfs_wait *wait_handle; struct timeval end_time; }; diff --git a/source4/ntvfs/posix/pvfs_notify.c b/source4/ntvfs/posix/pvfs_notify.c index 210f949395..06d2bc8e0c 100644 --- a/source4/ntvfs/posix/pvfs_notify.c +++ b/source4/ntvfs/posix/pvfs_notify.c @@ -268,9 +268,11 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs, /* if the buffer is empty then start waiting */ if (f->notify_buffer->num_changes == 0) { - void *wait_handle = - pvfs_wait_message(pvfs, req, -1, timeval_zero(), - pvfs_notify_end, f->notify_buffer); + struct pvfs_wait *wait_handle; + wait_handle = pvfs_wait_message(pvfs, req, -1, + timeval_zero(), + pvfs_notify_end, + f->notify_buffer); NT_STATUS_HAVE_NO_MEMORY(wait_handle); talloc_steal(req, wait_handle); return NT_STATUS_OK; diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 8558f0476a..3ccd239523 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -756,7 +756,7 @@ struct pvfs_open_retry { struct ntvfs_module_context *ntvfs; struct ntvfs_request *req; union smb_open *io; - void *wait_handle; + struct pvfs_wait *wait_handle; DATA_BLOB odb_locking_key; }; diff --git a/source4/ntvfs/posix/pvfs_wait.c b/source4/ntvfs/posix/pvfs_wait.c index 838a801567..291250befd 100644 --- a/source4/ntvfs/posix/pvfs_wait.c +++ b/source4/ntvfs/posix/pvfs_wait.c @@ -131,12 +131,12 @@ static int pvfs_wait_destructor(struct pvfs_wait *pwait) if msg_type == -1 then no message is registered, and it is assumed that the caller handles any messaging setup needed */ -void *pvfs_wait_message(struct pvfs_state *pvfs, - struct ntvfs_request *req, - int msg_type, - struct timeval end_time, - void (*fn)(void *, enum pvfs_wait_notice), - void *private_data) +struct pvfs_wait *pvfs_wait_message(struct pvfs_state *pvfs, + struct ntvfs_request *req, + int msg_type, + struct timeval end_time, + void (*fn)(void *, enum pvfs_wait_notice), + void *private_data) { struct pvfs_wait *pwait; diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index a660da329a..84c456dcfe 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -28,6 +28,8 @@ #include "ntvfs/common/ntvfs_common.h" #include "dsdb/samdb/samdb.h" +struct pvfs_wait; + /* this is the private structure for the posix vfs backend. It is used to hold per-connection (per tree connect) state information */ struct pvfs_state { -- cgit From 1cd2008aa49d38792f273bb28922d33b5b9b0066 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 19:59:13 +0100 Subject: pvfs: pass NULL to pvfs_can_*() when no odb_lock is needed by the caller metze (This used to be commit e585e2306334bd919f567f53d8d08903dfdfb102) --- source4/ntvfs/posix/pvfs_rename.c | 11 ++++++----- source4/ntvfs/posix/pvfs_setfileinfo.c | 4 +--- source4/ntvfs/posix/pvfs_unlink.c | 6 ++---- 3 files changed, 9 insertions(+), 12 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c index ea12f49333..5693e79314 100644 --- a/source4/ntvfs/posix/pvfs_rename.c +++ b/source4/ntvfs/posix/pvfs_rename.c @@ -192,8 +192,8 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, { struct pvfs_filename *name1, *name2; TALLOC_CTX *mem_ctx = talloc_new(req); + struct odb_lock *lck = NULL; NTSTATUS status; - struct odb_lock *lck, *lck2; /* resolve the wildcard pattern for this name */ fname2 = pvfs_resolve_wildcard(mem_ctx, fname1, fname2); @@ -216,6 +216,7 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, status = pvfs_can_rename(pvfs, req, name1, &lck); if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); goto failed; } @@ -223,7 +224,7 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, status = pvfs_resolve_partial(pvfs, mem_ctx, dir_path, fname2, &name2); if (NT_STATUS_IS_OK(status)) { - status = pvfs_can_delete(pvfs, req, name2, &lck2); + status = pvfs_can_delete(pvfs, req, name2, NULL); if (!NT_STATUS_IS_OK(status)) { goto failed; } @@ -311,7 +312,7 @@ static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; NTSTATUS status; struct pvfs_filename *name1, *name2; - struct odb_lock *lck; + struct odb_lock *lck = NULL; /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, ren->rename.in.pattern1, @@ -354,6 +355,7 @@ static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs, status = pvfs_can_rename(pvfs, req, name1, &lck); if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); return status; } @@ -375,7 +377,6 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; NTSTATUS status; struct pvfs_filename *name1, *name2; - struct odb_lock *lck; switch (ren->ntrename.in.flags) { case RENAME_FLAG_RENAME: @@ -421,7 +422,7 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs, return status; } - status = pvfs_can_rename(pvfs, req, name1, &lck); + status = pvfs_can_rename(pvfs, req, name1, NULL); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index 9c78699edb..fbbb8c2d4b 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -142,8 +142,6 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs, /* if the destination exists, then check the rename is allowed */ if (name2->exists) { - struct odb_lock *lck; - if (strcmp(name2->full_name, name->full_name) == 0) { /* rename to same name is null-op */ return NT_STATUS_OK; @@ -153,7 +151,7 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs, return NT_STATUS_OBJECT_NAME_COLLISION; } - status = pvfs_can_delete(pvfs, req, name2, &lck); + status = pvfs_can_delete(pvfs, req, name2, NULL); if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) { return NT_STATUS_ACCESS_DENIED; } diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index ef56d99fb5..d6e60b59d3 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -33,7 +33,6 @@ static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, uint16_t attrib) { NTSTATUS status; - struct odb_lock *lck; if (!name->stream_exists) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -45,7 +44,7 @@ static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, return status; } - status = pvfs_can_delete(pvfs, req, name, &lck); + status = pvfs_can_delete(pvfs, req, name, NULL); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -64,7 +63,6 @@ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, { struct pvfs_filename *name; NTSTATUS status; - struct odb_lock *lck; /* get a pvfs_filename object */ status = pvfs_resolve_partial(pvfs, req, @@ -80,7 +78,7 @@ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, return status; } - status = pvfs_can_delete(pvfs, req, name, &lck); + status = pvfs_can_delete(pvfs, req, name, NULL); if (!NT_STATUS_IS_OK(status)) { talloc_free(name); return status; -- cgit From f56ff422a525fc6fdf04de8e2ce5c5fa4c097629 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 20:01:25 +0100 Subject: pvfs: handle SHARING_VIOLATION and OPLOCK_NOT_GRANTED in pvfs_can_delete/rename() If the caller asks for the odb_lock return it also if we return NT_STATUS_SHARING_VIOLATION or NT_STATUS_OPLOCK_NOT_GRANTED so that the caller can add the pending notification. metze (This used to be commit daab9cb11eb540fae7ec3c024a586f5fd02cfc71) --- source4/ntvfs/posix/pvfs_open.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3ccd239523..0d97b3d629 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1447,7 +1447,19 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, status = pvfs_access_check_simple(pvfs, req, name, SEC_STD_DELETE); } - if (!NT_STATUS_IS_OK(status)) { + /* + * if it's a sharing violation or we got no oplock + * only keep the lock if the caller requested access + * to the lock + */ + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + if (lckp) { + *lckp = lck; + } else { + talloc_free(lck); + } + } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); *lckp = lck; } else if (lckp != NULL) { @@ -1487,7 +1499,19 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, 0, SEC_STD_DELETE); - if (!NT_STATUS_IS_OK(status)) { + /* + * if it's a sharing violation or we got no oplock + * only keep the lock if the caller requested access + * to the lock + */ + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + if (lckp) { + *lckp = lck; + } else { + talloc_free(lck); + } + } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); *lckp = lck; } else if (lckp != NULL) { -- cgit From 6f077d4017e6df9e070b1c3ea85b7afacf3437cd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 19:56:36 +0100 Subject: pvfs_open: unify talloc behavior in pvfs_can_delete/rename/stat() And also handle NULL for lckp in the error path without crashing. metze (This used to be commit 04eb1be0c67317067ee0ca70c731fef958cd513c) --- source4/ntvfs/posix/pvfs_open.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 0d97b3d629..3a8b17ab16 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1461,8 +1461,10 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, } } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); - *lckp = lck; - } else if (lckp != NULL) { + if (lckp) { + *lckp = NULL; + } + } else if (lckp) { *lckp = lck; } @@ -1513,8 +1515,10 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, } } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); - *lckp = lck; - } else if (lckp != NULL) { + if (lckp) { + *lckp = NULL; + } + } else if (lckp) { *lckp = lck; } @@ -1549,6 +1553,10 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, NTCREATEX_SHARE_ACCESS_WRITE, 0, 0); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + } + return status; } -- cgit From 63b15441f4a5f636a079fa5407b2e97a8b99b6e2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 20:12:46 +0100 Subject: pvfs_unlink: pass down a struct pvfs_filename to pvfs_unlink_one() metze (This used to be commit 43ec7fa2d898ce306557ea9092b6412bcc2f97ec) --- source4/ntvfs/posix/pvfs_unlink.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index d6e60b59d3..101dd75de6 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -58,34 +58,23 @@ static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, */ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, struct ntvfs_request *req, - const char *unix_path, - const char *fname, uint32_t attrib) + struct pvfs_filename *name, + uint32_t attrib) { - struct pvfs_filename *name; NTSTATUS status; - /* get a pvfs_filename object */ - status = pvfs_resolve_partial(pvfs, req, - unix_path, fname, &name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* make sure its matches the given attributes */ status = pvfs_match_attrib(pvfs, name, attrib, 0); if (!NT_STATUS_IS_OK(status)) { - talloc_free(name); return status; } status = pvfs_can_delete(pvfs, req, name, NULL); if (!NT_STATUS_IS_OK(status)) { - talloc_free(name); return status; } if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { - talloc_free(name); return NT_STATUS_FILE_IS_A_DIRECTORY; } @@ -108,8 +97,6 @@ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, name->full_name); } - talloc_free(name); - return status; } @@ -156,6 +143,7 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, } status = NT_STATUS_NO_SUCH_FILE; + talloc_free(name); ofs = 0; @@ -166,10 +154,20 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, return NT_STATUS_OBJECT_NAME_INVALID; } - status = pvfs_unlink_one(pvfs, req, pvfs_list_unix_path(dir), fname, unl->unlink.in.attrib); + /* get a pvfs_filename object */ + status = pvfs_resolve_partial(pvfs, req, + pvfs_list_unix_path(dir), + fname, &name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = pvfs_unlink_one(pvfs, req, name, unl->unlink.in.attrib); if (NT_STATUS_IS_OK(status)) { total_deleted++; } + + talloc_free(name); } if (total_deleted > 0) { -- cgit From a56bd4fa82bcb5c586f182e8123f2fc41b12e41d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Feb 2008 09:23:53 +0100 Subject: pvfs_unlink: pass down union smb_unlink completely to sub functions metze (This used to be commit 8301189e94be850494482e8c064b2400a5d11157) --- source4/ntvfs/posix/pvfs_unlink.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index 101dd75de6..8dbf9ee724 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -29,8 +29,8 @@ */ static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, struct ntvfs_request *req, - struct pvfs_filename *name, - uint16_t attrib) + union smb_unlink *unl, + struct pvfs_filename *name) { NTSTATUS status; @@ -39,7 +39,8 @@ static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, } /* make sure its matches the given attributes */ - status = pvfs_match_attrib(pvfs, name, attrib, 0); + status = pvfs_match_attrib(pvfs, name, + unl->unlink.in.attrib, 0); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -58,13 +59,14 @@ static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, */ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, struct ntvfs_request *req, - struct pvfs_filename *name, - uint32_t attrib) + union smb_unlink *unl, + struct pvfs_filename *name) { NTSTATUS status; /* make sure its matches the given attributes */ - status = pvfs_match_attrib(pvfs, name, attrib, 0); + status = pvfs_match_attrib(pvfs, name, + unl->unlink.in.attrib, 0); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -133,7 +135,7 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, } if (name->stream_name) { - return pvfs_unlink_stream(pvfs, req, name, unl->unlink.in.attrib); + return pvfs_unlink_stream(pvfs, req, unl, name); } /* get list of matching files */ @@ -162,7 +164,7 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, return status; } - status = pvfs_unlink_one(pvfs, req, name, unl->unlink.in.attrib); + status = pvfs_unlink_one(pvfs, req, unl, name); if (NT_STATUS_IS_OK(status)) { total_deleted++; } -- cgit From d5414cdc63b797a47fcbd1f55df98c7dd850ffa6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Feb 2008 09:28:51 +0100 Subject: pvfs_unlink: move !name->stream_exists into the caller metze (This used to be commit e01554e1617dc3c08a4ed6b4e016fd627f529ef9) --- source4/ntvfs/posix/pvfs_unlink.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index 8dbf9ee724..2b96a5032c 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -34,10 +34,6 @@ static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, { NTSTATUS status; - if (!name->stream_exists) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - /* make sure its matches the given attributes */ status = pvfs_match_attrib(pvfs, name, unl->unlink.in.attrib, 0); @@ -135,6 +131,10 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, } if (name->stream_name) { + if (!name->stream_exists) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + return pvfs_unlink_stream(pvfs, req, unl, name); } -- cgit From 0634c12abb634034fcaf842647c2bc09a92bfd68 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Feb 2008 09:30:51 +0100 Subject: pvfs_unlink: add a fast path for the non wildcard case metze (This used to be commit 83e6c99f78990b6b1df520bdee14b9f931ad0420) --- source4/ntvfs/posix/pvfs_unlink.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index 2b96a5032c..72649e646d 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -138,6 +138,10 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, return pvfs_unlink_stream(pvfs, req, unl, name); } + if (!name->has_wildcard) { + return pvfs_unlink_one(pvfs, req, unl, name); + } + /* get list of matching files */ status = pvfs_list_start(pvfs, name, req, &dir); if (!NT_STATUS_IS_OK(status)) { -- cgit From 58745900d30cbfa8729ce99e7110cfc5e4a78c2a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Feb 2008 09:37:22 +0100 Subject: pvfs_unlink: splitup the logic into generic and file specific functions metze (This used to be commit 7572afdc2635bdf9afbe1eda3c7498d0b5201db3) --- source4/ntvfs/posix/pvfs_unlink.c | 45 ++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index 72649e646d..0763a4e48c 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -51,27 +51,13 @@ static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, /* - unlink one file + unlink a file */ -static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, - struct ntvfs_request *req, - union smb_unlink *unl, - struct pvfs_filename *name) +static NTSTATUS pvfs_unlink_file(struct pvfs_state *pvfs, + struct pvfs_filename *name) { NTSTATUS status; - /* make sure its matches the given attributes */ - status = pvfs_match_attrib(pvfs, name, - unl->unlink.in.attrib, 0); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = pvfs_can_delete(pvfs, req, name, NULL); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { return NT_STATUS_FILE_IS_A_DIRECTORY; } @@ -98,6 +84,31 @@ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, return status; } +/* + unlink one file +*/ +static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, + struct ntvfs_request *req, + union smb_unlink *unl, + struct pvfs_filename *name) +{ + NTSTATUS status; + + /* make sure its matches the given attributes */ + status = pvfs_match_attrib(pvfs, name, + unl->unlink.in.attrib, 0); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = pvfs_can_delete(pvfs, req, name, NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return pvfs_unlink_file(pvfs, name); +} + /* delete a file - the dirtype specifies the file types to include in the search. The name can contain CIFS wildcards, but rarely does (except with OS/2 clients) -- cgit From 599901c139e99dca26f267439c14119e6c3f2092 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Feb 2008 09:41:41 +0100 Subject: pvfs_unlink: move stream logic into pvfs_unlink_one() metze (This used to be commit 438032e12f3040fbb58488ca537e4d8da39b6124) --- source4/ntvfs/posix/pvfs_unlink.c | 42 ++++++++------------------------------- 1 file changed, 8 insertions(+), 34 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index 0763a4e48c..bda4014bee 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -24,32 +24,6 @@ #include "system/dir.h" -/* - unlink a stream - */ -static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, - struct ntvfs_request *req, - union smb_unlink *unl, - struct pvfs_filename *name) -{ - NTSTATUS status; - - /* make sure its matches the given attributes */ - status = pvfs_match_attrib(pvfs, name, - unl->unlink.in.attrib, 0); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = pvfs_can_delete(pvfs, req, name, NULL); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - return pvfs_stream_delete(pvfs, name, -1); -} - - /* unlink a file */ @@ -106,6 +80,14 @@ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, return status; } + if (name->stream_name) { + if (!name->stream_exists) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + return pvfs_stream_delete(pvfs, name, -1); + } + return pvfs_unlink_file(pvfs, name); } @@ -141,14 +123,6 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, return NT_STATUS_FILE_IS_A_DIRECTORY; } - if (name->stream_name) { - if (!name->stream_exists) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - return pvfs_unlink_stream(pvfs, req, unl, name); - } - if (!name->has_wildcard) { return pvfs_unlink_one(pvfs, req, unl, name); } -- cgit From 69631a215b655415477ee0e71a08beca86dd5b2f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Feb 2008 09:14:54 +0100 Subject: pvfs_setfileinfo_rename: map DELETE_PENDING to ACCESS_DENIED This is needed as odb_can_open/pvfs_can_delete changed the return value. metze (This used to be commit 1ba0b9a8f1f84c7c949b3d184843462b87446707) --- source4/ntvfs/posix/pvfs_setfileinfo.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index fbbb8c2d4b..c6d014a72f 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -152,6 +152,9 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs, } status = pvfs_can_delete(pvfs, req, name2, NULL); + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { + return NT_STATUS_ACCESS_DENIED; + } if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) { return NT_STATUS_ACCESS_DENIED; } -- cgit From 9852e0d31582f669179c2a8c8ebdb263fef611f2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 25 Feb 2008 16:49:40 +0100 Subject: pvfs_open: pass down open_disposition and break_to_none to odb_open_file() metze (This used to be commit 46500983fe2f63540a67e2e963ab264fa8a090d0) --- source4/ntvfs/posix/pvfs_open.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3a8b17ab16..1b5ea56d64 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -296,9 +296,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, f->handle, f->handle->name->stream_id, + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, - name->full_name, OPLOCK_NONE, NULL); + io->generic.in.open_disposition, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); @@ -349,9 +350,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_open_file(lck, f->handle, f->handle->name->stream_id, + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, - name->full_name, OPLOCK_NONE, NULL); + io->generic.in.open_disposition, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; @@ -669,9 +671,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, oplock_level = OPLOCK_EXCLUSIVE; } - status = odb_open_file(lck, f->handle, name->stream_id, + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, - name->full_name, oplock_level, &oplock_granted); + io->generic.in.open_disposition, + false, oplock_level, &oplock_granted); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { /* bad news, we must have hit a race - we don't delete the file @@ -1186,9 +1189,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, f->handle, f->handle->name->stream_id, + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, - name->full_name, oplock_level, &oplock_granted); + io->generic.in.open_disposition, + false, oplock_level, &oplock_granted); /* on a sharing violation we need to retry when the file is closed by the other user, or after 1 second */ -- cgit From c93cf42d9fe4f1e382a762e7c1eafef0dff122c1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 25 Feb 2008 17:50:22 +0100 Subject: pvfs_open: fix odb_can_open() callers after prototype change metze (This used to be commit 904159327b3cb80fbec6aa5a4feaa141190a3f3a) --- source4/ntvfs/posix/pvfs_open.c | 51 ++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 16 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1b5ea56d64..bbfe4ac733 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1428,6 +1428,9 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; + uint32_t share_access; + uint32_t access_mask; + bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { @@ -1440,15 +1443,18 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_can_open(lck, - NTCREATEX_SHARE_ACCESS_READ | - NTCREATEX_SHARE_ACCESS_WRITE | - NTCREATEX_SHARE_ACCESS_DELETE, - NTCREATEX_OPTIONS_DELETE_ON_CLOSE, - SEC_STD_DELETE); + share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE; + access_mask = SEC_STD_DELETE; + delete_on_close = true; + + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, delete_on_close, + 0, false); if (NT_STATUS_IS_OK(status)) { - status = pvfs_access_check_simple(pvfs, req, name, SEC_STD_DELETE); + status = pvfs_access_check_simple(pvfs, req, name, access_mask); } /* @@ -1487,6 +1493,9 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; + uint32_t share_access; + uint32_t access_mask; + bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { @@ -1499,11 +1508,14 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_can_open(lck, - NTCREATEX_SHARE_ACCESS_READ | - NTCREATEX_SHARE_ACCESS_WRITE, - 0, - SEC_STD_DELETE); + share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + access_mask = SEC_STD_DELETE; + delete_on_close = false; + + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, delete_on_close, + 0, false); /* * if it's a sharing violation or we got no oplock @@ -1540,6 +1552,9 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; + uint32_t share_access; + uint32_t access_mask; + bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { @@ -1552,10 +1567,14 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_can_open(lck, - NTCREATEX_SHARE_ACCESS_READ | - NTCREATEX_SHARE_ACCESS_WRITE, - 0, 0); + share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + access_mask = 0; + delete_on_close = false; + + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, delete_on_close, + 0, false); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); -- cgit From d7ea52e9a3cd920f7c8a3b00f7cd28a7f605a993 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 17:48:13 +0100 Subject: pvfs_open: make the retry logic indepdendent from open and sharing violations metze (This used to be commit 56bd63a4236ebf360d3e805c8560df86759573f7) --- source4/ntvfs/posix/pvfs_open.c | 149 ++++++++++++++++++++++++++-------------- source4/ntvfs/posix/vfs_posix.h | 5 ++ 2 files changed, 104 insertions(+), 50 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index bbfe4ac733..8e1870fa70 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -751,20 +751,25 @@ cleanup_delete: return status; } - /* - state of a pending open retry + state of a pending retry */ -struct pvfs_open_retry { +struct pvfs_odb_retry { struct ntvfs_module_context *ntvfs; struct ntvfs_request *req; - union smb_open *io; - struct pvfs_wait *wait_handle; DATA_BLOB odb_locking_key; + void *io; + void *private_data; + void (*callback)(struct pvfs_odb_retry *r, + struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + void *io, + void *private_data, + enum pvfs_wait_notice reason); }; -/* destroy a pending open request */ -static int pvfs_retry_destructor(struct pvfs_open_retry *r) +/* destroy a pending request */ +static int pvfs_odb_retry_destructor(struct pvfs_odb_retry *r) { struct pvfs_state *pvfs = r->ntvfs->private_data; if (r->odb_locking_key.data) { @@ -778,15 +783,92 @@ static int pvfs_retry_destructor(struct pvfs_open_retry *r) return 0; } +static void pvfs_odb_retry_callback(void *_r, enum pvfs_wait_notice reason) +{ + struct pvfs_odb_retry *r = talloc_get_type(_r, struct pvfs_odb_retry); + + if (reason == PVFS_WAIT_EVENT) { + /* + * The pending odb entry is already removed. + * We use a null locking key to indicate this + * to the destructor. + */ + data_blob_free(&r->odb_locking_key); + } + + r->callback(r, r->ntvfs, r->req, r->io, r->private_data, reason); +} + /* - retry an open + setup for a retry of a request that was rejected + by odb_open_file() or odb_can_open() */ -static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) +NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + struct odb_lock *lck, + struct timeval end_time, + void *io, + void *private_data, + void (*callback)(struct pvfs_odb_retry *r, + struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + void *io, + void *private_data, + enum pvfs_wait_notice reason)) { - struct pvfs_open_retry *r = private; - struct ntvfs_module_context *ntvfs = r->ntvfs; - struct ntvfs_request *req = r->req; - union smb_open *io = r->io; + struct pvfs_state *pvfs = ntvfs->private_data; + struct pvfs_odb_retry *r; + struct pvfs_wait *wait_handle; + NTSTATUS status; + + r = talloc(req, struct pvfs_odb_retry); + NT_STATUS_HAVE_NO_MEMORY(r); + + r->ntvfs = ntvfs; + r->req = req; + r->io = io; + r->private_data = private_data; + r->callback = callback; + r->odb_locking_key = odb_get_key(r, lck); + if (r->odb_locking_key.data == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* setup a pending lock */ + status = odb_open_file_pending(lck, r); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + talloc_free(lck); + + talloc_set_destructor(r, pvfs_odb_retry_destructor); + + wait_handle = pvfs_wait_message(pvfs, req, + MSG_PVFS_RETRY_OPEN, end_time, + pvfs_odb_retry_callback, r); + if (wait_handle == NULL) { + return NT_STATUS_NO_MEMORY; + } + + talloc_steal(r, wait_handle); + + talloc_steal(pvfs, r); + + return NT_STATUS_OK; +} + +/* + retry an open after a sharing violation +*/ +static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r, + struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + void *_io, + void *private_data, + enum pvfs_wait_notice reason) +{ + union smb_open *io = talloc_get_type(_io, union smb_open); NTSTATUS status; /* w2k3 ignores SMBntcancel for outstanding open requests. It's probably @@ -795,8 +877,6 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) return; } - talloc_free(r->wait_handle); - if (reason == PVFS_WAIT_TIMEOUT) { /* if it timed out, then give the failure immediately */ @@ -806,9 +886,6 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) return; } - /* the pending odb entry is already removed. We use a null locking - key to indicate this */ - data_blob_free(&r->odb_locking_key); talloc_free(r); /* try the open again, which could trigger another retry setup @@ -925,7 +1002,6 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, struct odb_lock *lck) { struct pvfs_state *pvfs = ntvfs->private_data; - struct pvfs_open_retry *r; NTSTATUS status; struct timeval end_time; @@ -939,40 +1015,13 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, } } - r = talloc(req, struct pvfs_open_retry); - if (r == NULL) { - return NT_STATUS_NO_MEMORY; - } - - r->ntvfs = ntvfs; - r->req = req; - r->io = io; - r->odb_locking_key = data_blob_talloc(r, - f->handle->odb_locking_key.data, - f->handle->odb_locking_key.length); - - end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay); - - /* setup a pending lock */ - status = odb_open_file_pending(lck, r); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - talloc_free(lck); + /* the retry should allocate a new file handle */ talloc_free(f); - talloc_set_destructor(r, pvfs_retry_destructor); - - r->wait_handle = pvfs_wait_message(pvfs, req, MSG_PVFS_RETRY_OPEN, end_time, - pvfs_open_retry, r); - if (r->wait_handle == NULL) { - return NT_STATUS_NO_MEMORY; - } - - talloc_steal(pvfs, r); + end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay); - return NT_STATUS_OK; + return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL, + pvfs_retry_open_sharing); } /* diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 84c456dcfe..50875c3f9b 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -230,6 +230,11 @@ struct pvfs_dir; /* types of notification for pvfs wait events */ enum pvfs_wait_notice {PVFS_WAIT_EVENT, PVFS_WAIT_TIMEOUT, PVFS_WAIT_CANCEL}; +/* + state of a pending retry +*/ +struct pvfs_odb_retry; + #define PVFS_EADB "posix:eadb" #define PVFS_XATTR "posix:xattr" #define PVFS_FAKE_OPLOCKS "posix:fakeoplocks" -- cgit From 95fafa694cbb6f695488c750d481bb1e427da6eb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 25 Feb 2008 08:32:35 +0100 Subject: pvfs: add pvfs_setup_oplock() to receive oplock breaks and pass them to the client metze (This used to be commit b09a2b126723bd75afd245f549703a04e512e129) --- source4/ntvfs/posix/config.mk | 1 + source4/ntvfs/posix/pvfs_oplock.c | 136 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 source4/ntvfs/posix/pvfs_oplock.c (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk index 6879940337..88048c2af7 100644 --- a/source4/ntvfs/posix/config.mk +++ b/source4/ntvfs/posix/config.mk @@ -53,6 +53,7 @@ OBJ_FILES = \ pvfs_resolve.o \ pvfs_shortname.o \ pvfs_lock.o \ + pvfs_oplock.o \ pvfs_wait.o \ pvfs_seek.o \ pvfs_ioctl.o \ diff --git a/source4/ntvfs/posix/pvfs_oplock.c b/source4/ntvfs/posix/pvfs_oplock.c new file mode 100644 index 0000000000..50b1478f13 --- /dev/null +++ b/source4/ntvfs/posix/pvfs_oplock.c @@ -0,0 +1,136 @@ +/* + Unix SMB/CIFS implementation. + + POSIX NTVFS backend - oplock handling + + Copyright (C) Stefan Metzmacher 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "lib/messaging/messaging.h" +#include "lib/messaging/irpc.h" +#include "vfs_posix.h" + + +struct pvfs_oplock { + struct pvfs_file_handle *handle; + struct pvfs_file *file; + uint32_t level; + struct messaging_context *msg_ctx; +}; + +/* + receive oplock breaks and forward them to the client +*/ +static void pvfs_oplock_break(struct pvfs_oplock *opl, uint8_t level) +{ + NTSTATUS status; + struct pvfs_file *f = opl->file; + struct pvfs_file_handle *h = opl->handle; + struct pvfs_state *pvfs = h->pvfs; + + DEBUG(10,("pvfs_oplock_break: sending oplock break level %d for '%s' %p\n", + level, h->name->original_name, h)); + status = ntvfs_send_oplock_break(pvfs->ntvfs, f->ntvfs, level); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("pvfs_oplock_break: sending oplock break failed: %s\n", + nt_errstr(status))); + } +} + +static void pvfs_oplock_break_dispatch(struct messaging_context *msg, + void *private_data, uint32_t msg_type, + struct server_id src, DATA_BLOB *data) +{ + struct pvfs_oplock *opl = talloc_get_type(private_data, + struct pvfs_oplock); + struct opendb_oplock_break opb; + + ZERO_STRUCT(opb); + + /* we need to check that this one is for us. See + messaging_send_ptr() for the other side of this. + */ + if (data->length == sizeof(struct opendb_oplock_break)) { + struct opendb_oplock_break *p; + p = (struct opendb_oplock_break *)data->data; + opb = *p; + } else { + DEBUG(0,("%s: ignore oplock break with length[%u]\n", + __location__, data->length)); + return; + } + if (opb.file_handle != opl->handle) { + return; + } + + /* + * maybe we should use ntvfs_setup_async() + */ + pvfs_oplock_break(opl, opb.level); +} + +static int pvfs_oplock_destructor(struct pvfs_oplock *opl) +{ + messaging_deregister(opl->msg_ctx, MSG_NTVFS_OPLOCK_BREAK, opl); + return 0; +} + +NTSTATUS pvfs_setup_oplock(struct pvfs_file *f, uint32_t oplock_granted) +{ + NTSTATUS status; + struct pvfs_oplock *opl; + uint32_t level = OPLOCK_NONE; + + f->handle->oplock = NULL; + + switch (oplock_granted) { + case EXCLUSIVE_OPLOCK_RETURN: + level = OPLOCK_EXCLUSIVE; + break; + case BATCH_OPLOCK_RETURN: + level = OPLOCK_BATCH; + break; + case LEVEL_II_OPLOCK_RETURN: + level = OPLOCK_LEVEL_II; + break; + } + + if (level == OPLOCK_NONE) { + return NT_STATUS_OK; + } + + opl = talloc(f->handle, struct pvfs_oplock); + NT_STATUS_HAVE_NO_MEMORY(opl); + + opl->handle = f->handle; + opl->file = f; + opl->level = level; + opl->msg_ctx = f->pvfs->ntvfs->ctx->msg_ctx; + + status = messaging_register(opl->msg_ctx, + opl, + MSG_NTVFS_OPLOCK_BREAK, + pvfs_oplock_break_dispatch); + NT_STATUS_NOT_OK_RETURN(status); + + /* destructor */ + talloc_set_destructor(opl, pvfs_oplock_destructor); + + f->handle->oplock = opl; + + return NT_STATUS_OK; +} -- cgit From be1ba5b63164e7dab4bf067bc1aac4ed9cece2bc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 25 Feb 2008 08:39:13 +0100 Subject: pvfs_open: call pvfs_setup_oplock() if an oplock was granted This is needed to receive oplock breaks from other "processes" metze (This used to be commit dd56f55afdc0d114a0b0bceb0e4feb022919323a) --- source4/ntvfs/posix/pvfs_open.c | 22 +++++++++++++++++++--- source4/ntvfs/posix/vfs_posix.h | 8 ++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 8e1870fa70..8429c14d1b 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -268,6 +268,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; + f->handle->oplock = NULL; f->handle->sticky_write_time = false; f->handle->open_completed = false; @@ -684,9 +685,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } - if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { - oplock_granted = OPLOCK_BATCH; - } f->ntvfs = h; f->pvfs = pvfs; @@ -705,12 +703,23 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; + f->handle->oplock = NULL; f->handle->have_opendb_entry = true; f->handle->sticky_write_time = false; f->handle->open_completed = false; DLIST_ADD(pvfs->files.list, f); + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + oplock_granted = OPLOCK_BATCH; + } else if (oplock_granted != OPLOCK_NONE) { + status = pvfs_setup_oplock(f, oplock_granted); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + return status; + } + } + /* setup a destructor to avoid file descriptor leaks on abnormal termination */ talloc_set_destructor(f, pvfs_fnum_destructor); @@ -1185,6 +1194,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; + f->handle->oplock = NULL; f->handle->have_opendb_entry = false; f->handle->sticky_write_time = false; f->handle->open_completed = false; @@ -1257,6 +1267,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { oplock_granted = OPLOCK_BATCH; + } else if (oplock_granted != OPLOCK_NONE) { + status = pvfs_setup_oplock(f, oplock_granted); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + return status; + } } f->handle->have_opendb_entry = true; diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 50875c3f9b..72469505cc 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -29,6 +29,7 @@ #include "dsdb/samdb/samdb.h" struct pvfs_wait; +struct pvfs_oplock; /* this is the private structure for the posix vfs backend. It is used to hold per-connection (per tree connect) state information */ @@ -154,6 +155,13 @@ struct pvfs_file_handle { bool have_opendb_entry; + /* + * we need to wait for oplock break requests from other processes, + * and we need to remember the pvfs_file so we can correctly + * forward the oplock break to the client + */ + struct pvfs_oplock *oplock; + /* we need this hook back to our parent for lock destruction */ struct pvfs_state *pvfs; -- cgit From 4ee328d7d26f1a86559993f6533b8a1e12a4c6a1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 25 Feb 2008 09:51:58 +0100 Subject: pvfs: handle oplock releases in its own function pvfs_oplock_release() metze (This used to be commit 27ec7bfc8b7f46c97e6878caf5cd694c517ce053) --- source4/ntvfs/posix/pvfs_lock.c | 11 +++---- source4/ntvfs/posix/pvfs_oplock.c | 64 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 7 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c index df85b2b775..0796286b7e 100644 --- a/source4/ntvfs/posix/pvfs_lock.c +++ b/source4/ntvfs/posix/pvfs_lock.c @@ -294,6 +294,10 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, return ntvfs_map_lock(ntvfs, req, lck); } + if (lck->lockx.in.mode & LOCKING_ANDX_OPLOCK_RELEASE) { + return pvfs_oplock_release(ntvfs, req, lck); + } + f = pvfs_find_fd(pvfs, req, lck->lockx.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; @@ -338,13 +342,6 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, return NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks); } - if (lck->lockx.in.mode & LOCKING_ANDX_OPLOCK_RELEASE) { - DEBUG(0,("received unexpected oplock break\n")); - talloc_free(pending); - return NT_STATUS_NOT_IMPLEMENTED; - } - - /* the unlocks happen first */ locks = lck->lockx.in.locks; diff --git a/source4/ntvfs/posix/pvfs_oplock.c b/source4/ntvfs/posix/pvfs_oplock.c index 50b1478f13..eff9ae1f1d 100644 --- a/source4/ntvfs/posix/pvfs_oplock.c +++ b/source4/ntvfs/posix/pvfs_oplock.c @@ -134,3 +134,67 @@ NTSTATUS pvfs_setup_oplock(struct pvfs_file *f, uint32_t oplock_granted) return NT_STATUS_OK; } + +NTSTATUS pvfs_oplock_release(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, union smb_lock *lck) +{ + struct pvfs_state *pvfs = ntvfs->private_data; + struct pvfs_file *f; + struct pvfs_file_handle *h; + struct odb_lock *olck; + uint8_t oplock_break; + NTSTATUS status; + + f = pvfs_find_fd(pvfs, req, lck->lockx.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + + h = f->handle; + + if (h->fd == -1) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } + + if (!h->have_opendb_entry) { + return NT_STATUS_FOOBAR; + } + + if (!h->oplock) { + return NT_STATUS_FOOBAR; + } + + olck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); + if (olck == NULL) { + DEBUG(0,("Unable to lock opendb for oplock update\n")); + return NT_STATUS_FOOBAR; + } + + oplock_break = (lck->lockx.in.mode >> 8) & 0xFF; + if (oplock_break == OPLOCK_BREAK_TO_NONE) { + h->oplock->level = OPLOCK_NONE; + } else if (oplock_break == OPLOCK_BREAK_TO_LEVEL_II) { + h->oplock->level = OPLOCK_LEVEL_II; + } else { + /* fallback to level II in case of a invalid value */ + DEBUG(1,("unexpected oplock break level[0x%02X]\n", oplock_break)); + h->oplock->level = OPLOCK_LEVEL_II; + } + status = odb_update_oplock(olck, h, h->oplock->level); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to update oplock level for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + talloc_free(olck); + return status; + } + + talloc_free(olck); + + /* after a break to none, we no longer have an oplock attached */ + if (h->oplock->level == OPLOCK_NONE) { + talloc_free(h->oplock); + h->oplock = NULL; + } + + return NT_STATUS_OK; +} -- cgit From 348439e9301fa3b07f5263a6dabc61557a384179 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Feb 2008 16:34:50 +0100 Subject: pvfs_oplocks: add pvfs_break_level2_oplocks() metze (This used to be commit e0837238b6b09143970f03b6a78201c3fe55f3cd) --- source4/ntvfs/posix/pvfs_oplock.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_oplock.c b/source4/ntvfs/posix/pvfs_oplock.c index eff9ae1f1d..cf30ddbc59 100644 --- a/source4/ntvfs/posix/pvfs_oplock.c +++ b/source4/ntvfs/posix/pvfs_oplock.c @@ -198,3 +198,42 @@ NTSTATUS pvfs_oplock_release(struct ntvfs_module_context *ntvfs, return NT_STATUS_OK; } + +NTSTATUS pvfs_break_level2_oplocks(struct pvfs_file *f) +{ + struct pvfs_file_handle *h = f->handle; + struct odb_lock *olck; + NTSTATUS status; + + if (h->oplock && h->oplock->level == OPLOCK_EXCLUSIVE) { + return NT_STATUS_OK; + } + + olck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); + if (olck == NULL) { + DEBUG(0,("Unable to lock opendb for oplock update\n")); + return NT_STATUS_FOOBAR; + } + + if (h->oplock && h->oplock->level == OPLOCK_BATCH) { + status = odb_update_oplock(olck, h, OPLOCK_LEVEL_II); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to update oplock level for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + talloc_free(olck); + return status; + } + } + + status = odb_break_oplocks(olck); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to break level2 oplocks to none for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + talloc_free(olck); + return status; + } + + talloc_free(olck); + + return NT_STATUS_OK; +} -- cgit From 4344ac6209df4be2dad6a8b1c0766101f5972f13 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Feb 2008 16:34:50 +0100 Subject: pvfs: send oplock breaks to none to level2 holders on write/lock requests metze (This used to be commit b8c42a1ff8fd4131ef2a1ad92a7405a2e4d335d3) --- source4/ntvfs/posix/pvfs_lock.c | 3 +++ source4/ntvfs/posix/pvfs_write.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c index 0796286b7e..baa92880f1 100644 --- a/source4/ntvfs/posix/pvfs_lock.c +++ b/source4/ntvfs/posix/pvfs_lock.c @@ -307,6 +307,9 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, return NT_STATUS_FILE_IS_A_DIRECTORY; } + status = pvfs_break_level2_oplocks(f); + NT_STATUS_NOT_OK_RETURN(status); + if (lck->lockx.in.timeout != 0 && (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { pending = talloc(f, struct pvfs_pending_lock); diff --git a/source4/ntvfs/posix/pvfs_write.c b/source4/ntvfs/posix/pvfs_write.c index 5a11f01952..dda8c83407 100644 --- a/source4/ntvfs/posix/pvfs_write.c +++ b/source4/ntvfs/posix/pvfs_write.c @@ -57,7 +57,10 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs, wr->writex.in.count, WRITE_LOCK); NT_STATUS_NOT_OK_RETURN(status); - + + status = pvfs_break_level2_oplocks(f); + NT_STATUS_NOT_OK_RETURN(status); + if (f->handle->name->stream_name) { ret = pvfs_stream_write(pvfs, f->handle, -- cgit From ee81b7a85e8bb749a00c85bfdcf8f1e341ad2eea Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 23 Feb 2008 11:46:43 +0100 Subject: pvfs_setfileinfo: break level2 oplocks on setfileinfo() ALLOCATION_INFO and END_OF_FILE_INFO metze (This used to be commit b258f9d8d4bf3606f4884d1bff548f16dadc08aa) --- source4/ntvfs/posix/pvfs_setfileinfo.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index c6d014a72f..d1d8f819ef 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -355,6 +355,9 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, case RAW_SFILEINFO_ALLOCATION_INFO: case RAW_SFILEINFO_ALLOCATION_INFORMATION: + status = pvfs_break_level2_oplocks(f); + NT_STATUS_NOT_OK_RETURN(status); + newstats.dos.alloc_size = info->allocation_info.in.alloc_size; if (newstats.dos.alloc_size < newstats.st.st_size) { newstats.st.st_size = newstats.dos.alloc_size; @@ -365,6 +368,9 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, case RAW_SFILEINFO_END_OF_FILE_INFO: case RAW_SFILEINFO_END_OF_FILE_INFORMATION: + status = pvfs_break_level2_oplocks(f); + NT_STATUS_NOT_OK_RETURN(status); + newstats.st.st_size = info->end_of_file_info.in.size; break; -- cgit From c0d1543a6a5fee3d767a366186dd634a395c8146 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 25 Feb 2008 19:17:45 +0100 Subject: pvfs: add posix:oplocktimeout=30 option metze (This used to be commit 5abc57ddab558c13db3864d13afc2ad3b1641d1c) --- source4/ntvfs/posix/vfs_posix.c | 4 ++++ source4/ntvfs/posix/vfs_posix.h | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index e058e6f546..ca874d1db1 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -91,6 +91,10 @@ static void pvfs_setup_options(struct pvfs_state *pvfs) PVFS_SHARE_DELAY, PVFS_SHARE_DELAY_DEFAULT); + pvfs->oplock_break_timeout = share_int_option(scfg, + PVFS_OPLOCK_TIMEOUT, + PVFS_OPLOCK_TIMEOUT_DEFAULT); + pvfs->share_name = talloc_strdup(pvfs, scfg->name); pvfs->fs_attribs = diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 72469505cc..4d22a91714 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -52,9 +52,12 @@ struct pvfs_state { ntcancel */ struct pvfs_wait *wait_list; - /* the sharing violation timeout */ + /* the sharing violation timeout (nsecs) */ uint_t sharing_violation_delay; + /* the oplock break timeout (secs) */ + uint_t oplock_break_timeout; + /* filesystem attributes (see FS_ATTR_*) */ uint32_t fs_attribs; @@ -247,6 +250,7 @@ struct pvfs_odb_retry; #define PVFS_XATTR "posix:xattr" #define PVFS_FAKE_OPLOCKS "posix:fakeoplocks" #define PVFS_SHARE_DELAY "posix:sharedelay" +#define PVFS_OPLOCK_TIMEOUT "posix:oplocktimeout" #define PVFS_ALLOCATION_ROUNDING "posix:allocationrounding" #define PVFS_SEARCH_INACTIVITY "posix:searchinactivity" #define PVFS_ACL "posix:acl" @@ -254,7 +258,8 @@ struct pvfs_odb_retry; #define PVFS_XATTR_DEFAULT true #define PVFS_FAKE_OPLOCKS_DEFAULT false -#define PVFS_SHARE_DELAY_DEFAULT 1000000 +#define PVFS_SHARE_DELAY_DEFAULT 1000000 /* nsecs */ +#define PVFS_OPLOCK_TIMEOUT_DEFAULT 30 /* secs */ #define PVFS_ALLOCATION_ROUNDING_DEFAULT 512 #define PVFS_SEARCH_INACTIVITY_DEFAULT 300 -- cgit From 61e17794c394d2c070ce7df9cee6c53d846e7b75 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Feb 2008 11:52:17 +0100 Subject: pvfs_unlink: retry unlink after oplock not granted metze (This used to be commit 746e89ce2e74dbd2cea8f5575c403e4c61f82cb8) --- source4/ntvfs/posix/pvfs_open.c | 26 ++++++++--- source4/ntvfs/posix/pvfs_unlink.c | 94 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 7 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 8429c14d1b..4110df292d 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1008,7 +1008,8 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_open *io, struct pvfs_file *f, - struct odb_lock *lck) + struct odb_lock *lck, + NTSTATUS parent_status) { struct pvfs_state *pvfs = ntvfs->private_data; NTSTATUS status; @@ -1027,7 +1028,15 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, /* the retry should allocate a new file handle */ talloc_free(f); - end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay); + if (NT_STATUS_EQUAL(parent_status, NT_STATUS_SHARING_VIOLATION)) { + end_time = timeval_add(&req->statistics.request_time, + 0, pvfs->sharing_violation_delay); + } else if (NT_STATUS_EQUAL(parent_status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + end_time = timeval_add(&req->statistics.request_time, + pvfs->oplock_break_timeout, 0); + } else { + return NT_STATUS_INTERNAL_ERROR; + } return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL, pvfs_retry_open_sharing); @@ -1253,11 +1262,16 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, io->generic.in.open_disposition, false, oplock_level, &oplock_granted); - /* on a sharing violation we need to retry when the file is closed by - the other user, or after 1 second */ - if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) && + /* + * on a sharing violation we need to retry when the file is closed by + * the other user, or after 1 second + * on a non granted oplock we need to retry when the file is closed by + * the other user, or after 30 seconds + */ + if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) && (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return pvfs_open_setup_retry(ntvfs, req, io, f, lck); + return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status); } if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index bda4014bee..7a2d964b9d 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -23,6 +23,84 @@ #include "vfs_posix.h" #include "system/dir.h" +/* + retry an open after a sharing violation +*/ +static void pvfs_retry_unlink(struct pvfs_odb_retry *r, + struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + void *_io, + void *private_data, + enum pvfs_wait_notice reason) +{ + union smb_unlink *io = talloc_get_type(_io, union smb_unlink); + NTSTATUS status = NT_STATUS_INTERNAL_ERROR; + + talloc_free(r); + + switch (reason) { + case PVFS_WAIT_CANCEL: +/*TODO*/ + status = NT_STATUS_CANCELLED; + break; + case PVFS_WAIT_TIMEOUT: + /* if it timed out, then give the failure + immediately */ +/*TODO*/ + status = NT_STATUS_SHARING_VIOLATION; + break; + case PVFS_WAIT_EVENT: + + /* try the open again, which could trigger another retry setup + if it wants to, so we have to unmark the async flag so we + will know if it does a second async reply */ + req->async_states->state &= ~NTVFS_ASYNC_STATE_ASYNC; + + status = pvfs_unlink(ntvfs, req, io); + if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { + /* the 2nd try also replied async, so we don't send + the reply yet */ + return; + } + + /* re-mark it async, just in case someone up the chain does + paranoid checking */ + req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; + break; + } + + /* send the reply up the chain */ + req->async_states->status = status; + req->async_states->send_fn(req); +} + +/* + setup for a unlink retry after a sharing violation + or a non granted oplock +*/ +static NTSTATUS pvfs_unlink_setup_retry(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + union smb_unlink *io, + struct odb_lock *lck, + NTSTATUS status) +{ + struct pvfs_state *pvfs = ntvfs->private_data; + struct timeval end_time; + + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) { + end_time = timeval_add(&req->statistics.request_time, + 0, pvfs->sharing_violation_delay); + } else if (NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + end_time = timeval_add(&req->statistics.request_time, + pvfs->oplock_break_timeout, 0); + } else { + return NT_STATUS_INTERNAL_ERROR; + } + + return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL, + pvfs_retry_unlink); +} + /* unlink a file @@ -67,6 +145,7 @@ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, struct pvfs_filename *name) { NTSTATUS status; + struct odb_lock *lck = NULL; /* make sure its matches the given attributes */ status = pvfs_match_attrib(pvfs, name, @@ -75,7 +154,20 @@ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, return status; } - status = pvfs_can_delete(pvfs, req, name, NULL); + status = pvfs_can_delete(pvfs, req, name, &lck); + + /* + * on a sharing violation we need to retry when the file is closed by + * the other user, or after 1 second + * on a non granted oplock we need to retry when the file is closed by + * the other user, or after 30 seconds + */ + if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) && + (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { + return pvfs_unlink_setup_retry(pvfs->ntvfs, req, unl, lck, status); + } + if (!NT_STATUS_IS_OK(status)) { return status; } -- cgit From 4eb0fcc5173ddf50305fa5094ec0d87d53d71a33 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 23 Feb 2008 11:49:39 +0100 Subject: pvfs_open: add pvfs_can_update_file_size() TODO: this is not complete, we need more tests to trigger this metze (This used to be commit 66ad1081f2be8a0caa16fb0d614b857a5bde751c) --- source4/ntvfs/posix/pvfs_open.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 4110df292d..12b70c00fd 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1620,6 +1620,68 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, return status; } +/* + determine if the file size of a file can be changed, + or if it is prevented by an already open file +*/ +NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs, + struct ntvfs_request *req, + struct pvfs_filename *name, + struct odb_lock **lckp) +{ + NTSTATUS status; + DATA_BLOB key; + struct odb_lock *lck; + uint32_t share_access; + uint32_t access_mask; + bool break_to_none; + bool delete_on_close; + + status = pvfs_locking_key(name, name, &key); + if (!NT_STATUS_IS_OK(status)) { + return NT_STATUS_NO_MEMORY; + } + + lck = odb_lock(req, pvfs->odb_context, &key); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for can_stat\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + /* TODO: this may needs some more flags */ + share_access = NTCREATEX_SHARE_ACCESS_WRITE; + access_mask = 0; + delete_on_close = false; + break_to_none = true; + + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, delete_on_close, + 0, break_to_none); + + /* + * if it's a sharing violation or we got no oplock + * only keep the lock if the caller requested access + * to the lock + */ + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + if (lckp) { + *lckp = lck; + } else { + talloc_free(lck); + } + } else if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + if (lckp) { + *lckp = NULL; + } + } else if (lckp) { + *lckp = lck; + } + + return status; +} + /* determine if file meta data can be accessed, or if it is prevented by an already open file -- cgit From fa2e4ba03cd65f850d8f118ce61d5c4a80f0e30a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 23 Feb 2008 11:50:19 +0100 Subject: pvfs_setpathinfo: retry setpathinfo after oplock not granted on on setpathinfo ALLOCATION_INFO and END_OF_FILE_INFO metze (This used to be commit 4e27ac8c529d5a1675fb02215191a2be7913ec97) --- source4/ntvfs/posix/pvfs_setfileinfo.c | 107 +++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index d1d8f819ef..da1e31e639 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -472,6 +472,84 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, return pvfs_dosattrib_save(pvfs, h->name, h->fd); } +/* + retry an open after a sharing violation +*/ +static void pvfs_retry_setpathinfo(struct pvfs_odb_retry *r, + struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + void *_info, + void *private_data, + enum pvfs_wait_notice reason) +{ + union smb_setfileinfo *info = talloc_get_type(_info, + union smb_setfileinfo); + NTSTATUS status = NT_STATUS_INTERNAL_ERROR; + + talloc_free(r); + + switch (reason) { + case PVFS_WAIT_CANCEL: +/*TODO*/ + status = NT_STATUS_CANCELLED; + break; + case PVFS_WAIT_TIMEOUT: + /* if it timed out, then give the failure + immediately */ +/*TODO*/ + status = NT_STATUS_SHARING_VIOLATION; + break; + case PVFS_WAIT_EVENT: + + /* try the open again, which could trigger another retry setup + if it wants to, so we have to unmark the async flag so we + will know if it does a second async reply */ + req->async_states->state &= ~NTVFS_ASYNC_STATE_ASYNC; + + status = pvfs_setpathinfo(ntvfs, req, info); + if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { + /* the 2nd try also replied async, so we don't send + the reply yet */ + return; + } + + /* re-mark it async, just in case someone up the chain does + paranoid checking */ + req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; + break; + } + + /* send the reply up the chain */ + req->async_states->status = status; + req->async_states->send_fn(req); +} + +/* + setup for a unlink retry after a sharing violation + or a non granted oplock +*/ +static NTSTATUS pvfs_setpathinfo_setup_retry(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + union smb_setfileinfo *info, + struct odb_lock *lck, + NTSTATUS status) +{ + struct pvfs_state *pvfs = ntvfs->private_data; + struct timeval end_time; + + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) { + end_time = timeval_add(&req->statistics.request_time, + 0, pvfs->sharing_violation_delay); + } else if (NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + end_time = timeval_add(&req->statistics.request_time, + pvfs->oplock_break_timeout, 0); + } else { + return NT_STATUS_INTERNAL_ERROR; + } + + return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, info, NULL, + pvfs_retry_setpathinfo); +} /* set info on a pathname @@ -486,6 +564,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, struct utimbuf unix_times; uint32_t access_needed; uint32_t change_mask = 0; + struct odb_lock *lck = NULL; /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, info->generic.in.file.path, @@ -560,6 +639,20 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, case RAW_SFILEINFO_ALLOCATION_INFO: case RAW_SFILEINFO_ALLOCATION_INFORMATION: + status = pvfs_can_update_file_size(pvfs, req, name, &lck); + /* + * on a sharing violation we need to retry when the file is closed by + * the other user, or after 1 second + * on a non granted oplock we need to retry when the file is closed by + * the other user, or after 30 seconds + */ + if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) && + (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { + return pvfs_setpathinfo_setup_retry(pvfs->ntvfs, req, info, lck, status); + } + NT_STATUS_NOT_OK_RETURN(status); + if (info->allocation_info.in.alloc_size > newstats.dos.alloc_size) { /* strange. Increasing the allocation size via setpathinfo should be silently ignored */ @@ -575,6 +668,20 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, case RAW_SFILEINFO_END_OF_FILE_INFO: case RAW_SFILEINFO_END_OF_FILE_INFORMATION: + status = pvfs_can_update_file_size(pvfs, req, name, &lck); + /* + * on a sharing violation we need to retry when the file is closed by + * the other user, or after 1 second + * on a non granted oplock we need to retry when the file is closed by + * the other user, or after 30 seconds + */ + if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) && + (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { + return pvfs_setpathinfo_setup_retry(pvfs->ntvfs, req, info, lck, status); + } + NT_STATUS_NOT_OK_RETURN(status); + newstats.st.st_size = info->end_of_file_info.in.size; break; -- cgit From 9f8fc29ea418c7ed2e2f206eb4789080ec9ab3f1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Feb 2008 10:21:39 +0100 Subject: pvfs_open: pass NTCREATEX_DISP_OPEN to odb_can_open() As 0 is NTCREATEX_DISP_SUPERSEDE and that's not what we want here. metze (This used to be commit 10c42e3d4ab71a71dfe620b40841dfe98f458c1a) --- source4/ntvfs/posix/pvfs_open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 12b70c00fd..ef05db5eac 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1530,7 +1530,7 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, - 0, false); + NTCREATEX_DISP_OPEN, false); if (NT_STATUS_IS_OK(status)) { status = pvfs_access_check_simple(pvfs, req, name, access_mask); @@ -1594,7 +1594,7 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, - 0, false); + NTCREATEX_DISP_OPEN, false); /* * if it's a sharing violation or we got no oplock @@ -1656,7 +1656,7 @@ NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs, status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, - 0, break_to_none); + NTCREATEX_DISP_OPEN, break_to_none); /* * if it's a sharing violation or we got no oplock @@ -1715,7 +1715,7 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, - 0, false); + NTCREATEX_DISP_OPEN, false); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); -- cgit From b40be554e7775687a01704b9af0aa272cc9019d0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Feb 2008 10:28:07 +0100 Subject: pvfs_open: pass down an access mask in pvfs_can_stat() metze (This used to be commit 6c34c7bc6801e470e5ec50aa93d0a07f7ad59314) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index ef05db5eac..0e4250d744 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1710,7 +1710,7 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; - access_mask = 0; + access_mask = SEC_FILE_READ_ATTRIBUTE; delete_on_close = false; status = odb_can_open(lck, name->stream_id, -- cgit From c62faaa75e2bf2c82b7a905b27d29f70ae0c7591 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Feb 2008 10:29:07 +0100 Subject: pvfs_qfileinfo: down discard the return value of pvfs_can_stat() The odb_can_open() code returns DELETE_PENDING if a delete is really pending. metze (This used to be commit 066ba3c7cfff12cb0b5298fc45eabb5fc097d056) --- source4/ntvfs/posix/pvfs_qfileinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c index 2f01c08fb0..8d23d707a4 100644 --- a/source4/ntvfs/posix/pvfs_qfileinfo.c +++ b/source4/ntvfs/posix/pvfs_qfileinfo.c @@ -330,7 +330,7 @@ NTSTATUS pvfs_qpathinfo(struct ntvfs_module_context *ntvfs, status = pvfs_can_stat(pvfs, req, name); if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_DELETE_PENDING; + return status; } status = pvfs_access_check_simple(pvfs, req, name, -- cgit From 55377f0352d73fa354e8abcf3e644c63c78d0ca6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Feb 2008 10:26:33 +0100 Subject: pvfs_open: pass down an access mask to pvfs_can_update_file_size() You just need SEC_FILE_WRITE_ATTRIBUTE to change the filesize... metze (This used to be commit 27e39063a0b759c7bced1cc9d7a6cb9192820c70) --- source4/ntvfs/posix/pvfs_open.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 0e4250d744..a01352f60c 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1648,9 +1648,19 @@ NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* TODO: this may needs some more flags */ - share_access = NTCREATEX_SHARE_ACCESS_WRITE; - access_mask = 0; + share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE; + /* + * I would have thought that we would need to pass + * SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA here too + * + * But you only need SEC_FILE_WRITE_ATTRIBUTE permissions + * to set the filesize. + * + * --metze + */ + access_mask = SEC_FILE_WRITE_ATTRIBUTE; delete_on_close = false; break_to_none = true; -- cgit