summaryrefslogtreecommitdiff
path: root/source4/ntvfs
diff options
context:
space:
mode:
Diffstat (limited to 'source4/ntvfs')
-rw-r--r--source4/ntvfs/common/notify.c10
-rw-r--r--source4/ntvfs/common/opendb.c10
-rw-r--r--source4/ntvfs/common/opendb.h6
-rw-r--r--source4/ntvfs/common/opendb_tdb.c55
-rw-r--r--source4/ntvfs/posix/pvfs_open.c91
-rw-r--r--source4/ntvfs/posix/pvfs_qfileinfo.c6
-rw-r--r--source4/ntvfs/posix/pvfs_rename.c112
-rw-r--r--source4/ntvfs/posix/pvfs_resolve.c7
-rw-r--r--source4/ntvfs/posix/pvfs_xattr.c2
-rw-r--r--source4/ntvfs/sysdep/inotify.c9
10 files changed, 209 insertions, 99 deletions
diff --git a/source4/ntvfs/common/notify.c b/source4/ntvfs/common/notify.c
index 94d32488eb..23aa3fb668 100644
--- a/source4/ntvfs/common/notify.c
+++ b/source4/ntvfs/common/notify.c
@@ -45,6 +45,7 @@ struct notify_context {
struct notify_array *array;
int seqnum;
struct sys_notify_context *sys_notify_ctx;
+ struct smb_iconv_convenience *iconv_convenience;
};
@@ -107,6 +108,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
notify->messaging_ctx = messaging_ctx;
notify->list = NULL;
notify->array = NULL;
+ notify->iconv_convenience = lp_iconv_convenience(lp_ctx);
notify->seqnum = tdb_get_seqnum(notify->w->tdb);
talloc_set_destructor(notify, notify_destructor);
@@ -171,7 +173,7 @@ static NTSTATUS notify_load(struct notify_context *notify)
blob.data = dbuf.dptr;
blob.length = dbuf.dsize;
- ndr_err = ndr_pull_struct_blob(&blob, notify->array, lp_iconv_convenience(global_loadparm),
+ ndr_err = ndr_pull_struct_blob(&blob, notify->array, notify->iconv_convenience,
notify->array,
(ndr_pull_flags_fn_t)ndr_pull_notify_array);
free(dbuf.dptr);
@@ -220,7 +222,7 @@ static NTSTATUS notify_save(struct notify_context *notify)
tmp_ctx = talloc_new(notify);
NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
- ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, lp_iconv_convenience(global_loadparm), notify->array,
+ ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, notify->iconv_convenience, notify->array,
(ndr_push_flags_fn_t)ndr_push_notify_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(tmp_ctx);
@@ -256,7 +258,7 @@ static void notify_handler(struct messaging_context *msg_ctx, void *private_data
return;
}
- ndr_err = ndr_pull_struct_blob(data, tmp_ctx, lp_iconv_convenience(global_loadparm), &ev,
+ ndr_err = ndr_pull_struct_blob(data, tmp_ctx, notify->iconv_convenience, &ev,
(ndr_pull_flags_fn_t)ndr_pull_notify_event);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(tmp_ctx);
@@ -555,7 +557,7 @@ static void notify_send(struct notify_context *notify, struct notify_entry *e,
tmp_ctx = talloc_new(notify);
- ndr_err = ndr_push_struct_blob(&data, tmp_ctx, lp_iconv_convenience(global_loadparm), &ev, (ndr_push_flags_fn_t)ndr_push_notify_event);
+ ndr_err = ndr_push_struct_blob(&data, tmp_ctx, notify->iconv_convenience, &ev, (ndr_push_flags_fn_t)ndr_push_notify_event);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(tmp_ctx);
return;
diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c
index 36144d0406..d8cb67686b 100644
--- a/source4/ntvfs/common/opendb.c
+++ b/source4/ntvfs/common/opendb.c
@@ -118,9 +118,10 @@ _PUBLIC_ NTSTATUS odb_open_file_pending(struct odb_lock *lck, void *private)
/*
remove a opendb entry
*/
-_PUBLIC_ NTSTATUS odb_close_file(struct odb_lock *lck, void *file_handle)
+_PUBLIC_ NTSTATUS odb_close_file(struct odb_lock *lck, void *file_handle,
+ const char **delete_path)
{
- return ops->odb_close_file(lck, file_handle);
+ return ops->odb_close_file(lck, file_handle, delete_path);
}
@@ -154,10 +155,9 @@ _PUBLIC_ NTSTATUS odb_set_delete_on_close(struct odb_lock *lck, bool del_on_clos
people still have the file open
*/
_PUBLIC_ NTSTATUS odb_get_delete_on_close(struct odb_context *odb,
- DATA_BLOB *key, bool *del_on_close,
- int *open_count, char **path)
+ DATA_BLOB *key, bool *del_on_close)
{
- return ops->odb_get_delete_on_close(odb, key, del_on_close, open_count, path);
+ return ops->odb_get_delete_on_close(odb, key, del_on_close);
}
diff --git a/source4/ntvfs/common/opendb.h b/source4/ntvfs/common/opendb.h
index 9591bcf6b9..33f2e1c88d 100644
--- a/source4/ntvfs/common/opendb.h
+++ b/source4/ntvfs/common/opendb.h
@@ -32,13 +32,13 @@ struct opendb_ops {
uint32_t open_disposition, bool break_to_none,
uint32_t oplock_level, uint32_t *oplock_granted);
NTSTATUS (*odb_open_file_pending)(struct odb_lock *lck, void *private);
- NTSTATUS (*odb_close_file)(struct odb_lock *lck, void *file_handle);
+ NTSTATUS (*odb_close_file)(struct odb_lock *lck, void *file_handle,
+ const char **delete_path);
NTSTATUS (*odb_remove_pending)(struct odb_lock *lck, void *private);
NTSTATUS (*odb_rename)(struct odb_lock *lck, const char *path);
NTSTATUS (*odb_set_delete_on_close)(struct odb_lock *lck, bool del_on_close);
NTSTATUS (*odb_get_delete_on_close)(struct odb_context *odb,
- DATA_BLOB *key, bool *del_on_close,
- int *open_count, char **path);
+ DATA_BLOB *key, bool *del_on_close);
NTSTATUS (*odb_can_open)(struct odb_lock *lck,
uint32_t stream_id, uint32_t share_access,
uint32_t access_mask, bool delete_on_close,
diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c
index fe5a0a8864..37c1c0850b 100644
--- a/source4/ntvfs/common/opendb_tdb.c
+++ b/source4/ntvfs/common/opendb_tdb.c
@@ -376,8 +376,26 @@ static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb,
exclusive oplocks afterwards. */
for (i=0;i<file->num_entries;i++) {
if (file->entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
+ bool oplock_return = OPLOCK_BREAK_TO_LEVEL_II;
+ /* if this is an attribute only access
+ * it doesn't conflict with an EXCLUSIVE oplock
+ * but we'll not grant the oplock below
+ */
+ attrs_only = access_attributes_only(access_mask,
+ open_disposition,
+ break_to_none);
+ if (attrs_only) {
+ break;
+ }
+ /*
+ * send an oplock break to the holder of the
+ * oplock and tell caller to retry later
+ */
+ if (break_to_none) {
+ oplock_return = OPLOCK_BREAK_TO_NONE;
+ }
odb_oplock_break_send(odb, &file->entries[i],
- OPLOCK_BREAK_TO_NONE);
+ oplock_return);
return NT_STATUS_OPLOCK_NOT_GRANTED;
}
}
@@ -449,8 +467,8 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck,
e.oplock_level = OPLOCK_EXCLUSIVE;
*oplock_granted = EXCLUSIVE_OPLOCK_RETURN;
} else {
- e.oplock_level = OPLOCK_NONE;
- *oplock_granted = NO_OPLOCK_RETURN;
+ e.oplock_level = OPLOCK_LEVEL_II;
+ *oplock_granted = LEVEL_II_OPLOCK_RETURN;
}
} else if (oplock_level == OPLOCK_BATCH) {
if (file.num_entries == 0) {
@@ -509,10 +527,12 @@ static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private)
/*
remove a opendb entry
*/
-static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle)
+static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle,
+ const char **_delete_path)
{
struct odb_context *odb = lck->odb;
struct opendb_file file;
+ const char *delete_path = NULL;
int i;
NTSTATUS status;
@@ -548,7 +568,16 @@ static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle)
file.num_pending = 0;
file.num_entries--;
-
+
+ if (file.num_entries == 0 && file.delete_on_close) {
+ delete_path = talloc_strdup(lck, file.path);
+ NT_STATUS_HAVE_NO_MEMORY(delete_path);
+ }
+
+ if (_delete_path) {
+ *_delete_path = delete_path;
+ }
+
return odb_push_record(lck, &file);
}
@@ -705,20 +734,20 @@ static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_cl
people still have the file open
*/
static NTSTATUS odb_tdb_get_delete_on_close(struct odb_context *odb,
- DATA_BLOB *key, bool *del_on_close,
- int *open_count, char **path)
+ DATA_BLOB *key, bool *del_on_close)
{
NTSTATUS status;
struct opendb_file file;
struct odb_lock *lck;
+ (*del_on_close) = false;
+
lck = odb_lock(odb, odb, key);
NT_STATUS_HAVE_NO_MEMORY(lck);
status = odb_pull_record(lck, &file);
if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
talloc_free(lck);
- (*del_on_close) = false;
return NT_STATUS_OK;
}
if (!NT_STATUS_IS_OK(status)) {
@@ -727,16 +756,6 @@ static NTSTATUS odb_tdb_get_delete_on_close(struct odb_context *odb,
}
(*del_on_close) = file.delete_on_close;
- if (open_count != NULL) {
- (*open_count) = file.num_entries;
- }
- if (path != NULL) {
- *path = talloc_strdup(odb, file.path);
- NT_STATUS_HAVE_NO_MEMORY(*path);
- if (file.num_entries == 1 && file.entries[0].delete_on_close) {
- (*del_on_close) = true;
- }
- }
talloc_free(lck);
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index a01352f60c..740a0a9d13 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -50,29 +50,10 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs,
*/
static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h)
{
- int open_count;
- char *path = NULL;
-
- if (h->name->stream_name == NULL &&
- pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) &&
- open_count == 1) {
- NTSTATUS status;
- status = pvfs_xattr_unlink_hook(h->pvfs, path);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",
- path, nt_errstr(status)));
- }
- if (rmdir(path) != 0) {
- DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n",
- path, strerror(errno)));
- }
- }
-
- talloc_free(path);
-
if (h->have_opendb_entry) {
struct odb_lock *lck;
NTSTATUS status;
+ const char *delete_path = NULL;
lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
if (lck == NULL) {
@@ -80,12 +61,24 @@ static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h)
return 0;
}
- status = odb_close_file(lck, h);
+ status = odb_close_file(lck, h, &delete_path);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n",
+ DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n",
h->name->full_name, nt_errstr(status)));
}
+ if (h->name->stream_name == NULL && delete_path) {
+ status = pvfs_xattr_unlink_hook(h->pvfs, delete_path);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",
+ delete_path, nt_errstr(status)));
+ }
+ if (rmdir(delete_path) != 0) {
+ DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n",
+ delete_path, strerror(errno)));
+ }
+ }
+
talloc_free(lck);
}
@@ -410,9 +403,6 @@ cleanup_delete:
*/
static int pvfs_handle_destructor(struct pvfs_file_handle *h)
{
- int open_count;
- char *path = NULL;
-
/* the write time is no longer sticky */
if (h->sticky_write_time) {
NTSTATUS status;
@@ -441,32 +431,10 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h)
h->fd = -1;
}
- if (h->name->stream_name == NULL &&
- h->open_completed &&
- pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) &&
- open_count == 1) {
- NTSTATUS status;
- status = pvfs_xattr_unlink_hook(h->pvfs, path);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",
- path, nt_errstr(status)));
- }
- if (unlink(path) != 0) {
- DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n",
- path, strerror(errno)));
- } else {
- notify_trigger(h->pvfs->notify_context,
- NOTIFY_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- path);
- }
- }
-
- talloc_free(path);
-
if (h->have_opendb_entry) {
struct odb_lock *lck;
NTSTATUS status;
+ const char *delete_path = NULL;
lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
if (lck == NULL) {
@@ -474,12 +442,30 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h)
return 0;
}
- status = odb_close_file(lck, h);
+ status = odb_close_file(lck, h, &delete_path);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n",
h->name->full_name, nt_errstr(status)));
}
+ if (h->name->stream_name == NULL &&
+ h->open_completed && delete_path) {
+ status = pvfs_xattr_unlink_hook(h->pvfs, delete_path);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",
+ delete_path, nt_errstr(status)));
+ }
+ if (unlink(delete_path) != 0) {
+ DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n",
+ delete_path, strerror(errno)));
+ } else {
+ notify_trigger(h->pvfs->notify_context,
+ NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ delete_path);
+ }
+ }
+
talloc_free(lck);
}
@@ -574,7 +560,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
status = pvfs_locking_key(parent, req, &locking_key);
NT_STATUS_NOT_OK_RETURN(status);
status = odb_get_delete_on_close(pvfs->odb_context, &locking_key,
- &del_on_close, NULL, NULL);
+ &del_on_close);
NT_STATUS_NOT_OK_RETURN(status);
if (del_on_close) {
return NT_STATUS_DELETE_PENDING;
@@ -1738,14 +1724,13 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs,
/*
determine if delete on close is set on
*/
-bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h,
- int *open_count, char **path)
+bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h)
{
NTSTATUS status;
bool del_on_close;
status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key,
- &del_on_close, open_count, path);
+ &del_on_close);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1,("WARNING: unable to determine delete on close status for open file\n"));
return false;
diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c
index 8d23d707a4..6ed729541f 100644
--- a/source4/ntvfs/posix/pvfs_qfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_qfileinfo.c
@@ -380,7 +380,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
switch (info->generic.level) {
case RAW_FILEINFO_STANDARD_INFO:
case RAW_FILEINFO_STANDARD_INFORMATION:
- if (pvfs_delete_on_close_set(pvfs, h, NULL, NULL)) {
+ if (pvfs_delete_on_close_set(pvfs, h)) {
info->standard_info.out.delete_pending = 1;
info->standard_info.out.nlink--;
}
@@ -388,7 +388,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
case RAW_FILEINFO_ALL_INFO:
case RAW_FILEINFO_ALL_INFORMATION:
- if (pvfs_delete_on_close_set(pvfs, h, NULL, NULL)) {
+ if (pvfs_delete_on_close_set(pvfs, h)) {
info->all_info.out.delete_pending = 1;
info->all_info.out.nlink--;
}
@@ -407,7 +407,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
break;
case RAW_FILEINFO_SMB2_ALL_INFORMATION:
- if (pvfs_delete_on_close_set(pvfs, h, NULL, NULL)) {
+ if (pvfs_delete_on_close_set(pvfs, h)) {
info->all_info2.out.delete_pending = 1;
info->all_info2.out.nlink--;
}
diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c
index 5693e79314..185e35f800 100644
--- a/source4/ntvfs/posix/pvfs_rename.c
+++ b/source4/ntvfs/posix/pvfs_rename.c
@@ -134,12 +134,12 @@ static const char *pvfs_resolve_wildcard_component(TALLOC_CTX *mem_ctx,
resolve a wildcard rename pattern.
*/
static const char *pvfs_resolve_wildcard(TALLOC_CTX *mem_ctx,
+ struct smb_iconv_convenience *iconv_convenience,
const char *fname,
const char *pattern)
{
const char *base1, *base2;
const char *ext1, *ext2;
- struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(global_loadparm);
char *p;
/* break into base part plus extension */
@@ -181,6 +181,84 @@ static const char *pvfs_resolve_wildcard(TALLOC_CTX *mem_ctx,
}
/*
+ retry an rename after a sharing violation
+*/
+static void pvfs_retry_rename(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_rename *io = talloc_get_type(_io, union smb_rename);
+ 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_rename(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 rename retry after a sharing violation
+ or a non granted oplock
+*/
+static NTSTATUS pvfs_rename_setup_retry(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req,
+ union smb_rename *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_rename);
+}
+
+/*
rename one file from a wildcard set
*/
static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs,
@@ -196,7 +274,7 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs,
NTSTATUS status;
/* resolve the wildcard pattern for this name */
- fname2 = pvfs_resolve_wildcard(mem_ctx, fname1, fname2);
+ fname2 = pvfs_resolve_wildcard(mem_ctx, lp_iconv_convenience(pvfs->ntvfs->ctx->lp_ctx), fname1, fname2);
if (fname2 == NULL) {
return NT_STATUS_NO_MEMORY;
}
@@ -354,8 +432,19 @@ static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs,
}
status = pvfs_can_rename(pvfs, req, name1, &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_rename_setup_retry(pvfs->ntvfs, req, ren, lck, status);
+ }
+
if (!NT_STATUS_IS_OK(status)) {
- talloc_free(lck);
return status;
}
@@ -377,6 +466,7 @@ 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 = NULL;
switch (ren->ntrename.in.flags) {
case RENAME_FLAG_RENAME:
@@ -422,7 +512,18 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs,
return status;
}
- status = pvfs_can_rename(pvfs, req, name1, NULL);
+ status = pvfs_can_rename(pvfs, req, name1, &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_rename_setup_retry(pvfs->ntvfs, req, ren, lck, status);
+ }
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -432,6 +533,9 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs,
status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE);
NT_STATUS_NOT_OK_RETURN(status);
status = pvfs_do_rename(pvfs, name1, name2->full_name);
+ if (NT_STATUS_IS_OK(status)) {
+ status = odb_rename(lck, name2->full_name);
+ }
NT_STATUS_NOT_OK_RETURN(status);
break;
diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c
index cf74816391..2bfc47beff 100644
--- a/source4/ntvfs/posix/pvfs_resolve.c
+++ b/source4/ntvfs/posix/pvfs_resolve.c
@@ -329,14 +329,15 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name,
reduce a name that contains .. components or repeated \ separators
return NULL if it can't be reduced
*/
-static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t flags)
+static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx,
+ struct smb_iconv_convenience *iconv_convenience,
+ const char **fname, uint_t flags)
{
codepoint_t c;
size_t c_size, len;
int i, num_components, err_count;
char **components;
char *p, *s, *ret;
- struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(global_loadparm);
s = talloc_strdup(mem_ctx, *fname);
if (s == NULL) return NT_STATUS_NO_MEMORY;
@@ -471,7 +472,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
/* it might contain .. components which need to be reduced */
- status = pvfs_reduce_name(*name, &cifs_name, flags);
+ status = pvfs_reduce_name(*name, lp_iconv_convenience(pvfs->ntvfs->ctx->lp_ctx), &cifs_name, flags);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
diff --git a/source4/ntvfs/posix/pvfs_xattr.c b/source4/ntvfs/posix/pvfs_xattr.c
index 39090bf702..b66d252a45 100644
--- a/source4/ntvfs/posix/pvfs_xattr.c
+++ b/source4/ntvfs/posix/pvfs_xattr.c
@@ -140,7 +140,7 @@ _PUBLIC_ NTSTATUS pvfs_xattr_ndr_save(struct pvfs_state *pvfs,
NTSTATUS status;
enum ndr_err_code ndr_err;
- ndr_err = ndr_push_struct_blob(&blob, mem_ctx, lp_iconv_convenience(global_loadparm), p, (ndr_push_flags_fn_t)push_fn);
+ ndr_err = ndr_push_struct_blob(&blob, mem_ctx, lp_iconv_convenience(pvfs->ntvfs->ctx->lp_ctx), p, (ndr_push_flags_fn_t)push_fn);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(mem_ctx);
return ndr_map_error2ntstatus(ndr_err);
diff --git a/source4/ntvfs/sysdep/inotify.c b/source4/ntvfs/sysdep/inotify.c
index 3fa710415b..093c15abab 100644
--- a/source4/ntvfs/sysdep/inotify.c
+++ b/source4/ntvfs/sysdep/inotify.c
@@ -244,11 +244,6 @@ static void inotify_handler(struct event_context *ev, struct fd_event *fde,
static NTSTATUS inotify_setup(struct sys_notify_context *ctx)
{
struct inotify_private *in;
-
- if (!lp_parm_bool(global_loadparm, NULL, "notify", "inotify", true)) {
- return NT_STATUS_INVALID_SYSTEM_SERVICE;
- }
-
in = talloc(ctx, struct inotify_private);
NT_STATUS_HAVE_NO_MEMORY(in);
in->fd = inotify_init();
@@ -339,6 +334,10 @@ static NTSTATUS inotify_watch(struct sys_notify_context *ctx,
/* maybe setup the inotify fd */
if (ctx->private_data == NULL) {
NTSTATUS status;
+ if (!lp_parm_bool(global_loadparm, NULL, "notify", "inotify", true)) {
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
+
status = inotify_setup(ctx);
NT_STATUS_NOT_OK_RETURN(status);
}