1
0
mirror of https://github.com/samba-team/samba.git synced 2025-12-02 00:23:50 +03:00

pvfs_unlink: retry unlink after oplock not granted

metze
This commit is contained in:
Stefan Metzmacher
2008-02-22 11:52:17 +01:00
parent 5abc57ddab
commit 746e89ce2e
2 changed files with 113 additions and 7 deletions

View File

@@ -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)) {

View File

@@ -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;
}