}
/* see if we are allowed to open at the same time as existing opens */
- status = odb_open_file(lck, f->handle, name->full_name, name->stream_id,
- share_access, access_mask, del_on_close,
- io->generic.in.open_disposition,
- false, OPLOCK_NONE, NULL);
+ status = odb_can_open(lck, name->stream_id,
+ share_access, access_mask, del_on_close,
+ io->generic.in.open_disposition, false);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(lck);
+ return status;
+ }
+
+ /* now really mark the file as open */
+ status = odb_open_file(lck, f->handle, name->full_name,
+ NULL, false, OPLOCK_NONE, NULL);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(lck);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- status = odb_open_file(lck, f->handle, name->full_name, name->stream_id,
- share_access, access_mask, del_on_close,
- io->generic.in.open_disposition,
- false, OPLOCK_NONE, NULL);
+ status = odb_can_open(lck, name->stream_id,
+ share_access, access_mask, del_on_close,
+ io->generic.in.open_disposition, false);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ goto cleanup_delete;
+ }
+
+ status = odb_open_file(lck, f->handle, name->full_name,
+ NULL, false, OPLOCK_NONE, NULL);
if (!NT_STATUS_IS_OK(status)) {
goto cleanup_delete;
bool del_on_close;
struct pvfs_filename *parent;
uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
+ bool allow_level_II_oplock = false;
if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) &&
(create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
oplock_level = OPLOCK_EXCLUSIVE;
}
- status = odb_open_file(lck, f->handle, name->full_name, name->stream_id,
- share_access, access_mask, del_on_close,
- io->generic.in.open_disposition,
- false, oplock_level, &oplock_granted);
- talloc_free(lck);
+ if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) {
+ allow_level_II_oplock = true;
+ }
+
+ status = odb_can_open(lck, name->stream_id,
+ share_access, access_mask, del_on_close,
+ io->generic.in.open_disposition, false);
if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(lck);
/* bad news, we must have hit a race - we don't delete the file
- here as the most likely scenario is that someone else created
+ here as the most likely scenario is that someone else created
the file at the same time */
close(fd);
return status;
}
-
f->ntvfs = h;
f->pvfs = pvfs;
f->pending_list = NULL;
f->handle->sticky_write_time = false;
f->handle->open_completed = false;
+ status = odb_open_file(lck, f->handle, name->full_name,
+ &f->handle->fd, allow_level_II_oplock,
+ 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
+ here as the most likely scenario is that someone else created
+ the file at the same time */
+ close(fd);
+ return status;
+ }
+
DLIST_ADD(pvfs->files.list, f);
+ /* setup a destructor to avoid file descriptor leaks on
+ abnormal termination */
+ talloc_set_destructor(f, pvfs_fnum_destructor);
+ talloc_set_destructor(f->handle, pvfs_handle_destructor);
+
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);
- talloc_set_destructor(f->handle, pvfs_handle_destructor);
-
io->generic.out.oplock_level = oplock_granted;
io->generic.out.file.ntvfs = f->ntvfs;
io->generic.out.create_action = NTCREATEX_ACTION_CREATED;
/*
setup for a retry of a request that was rejected
- by odb_open_file() or odb_can_open()
+ by odb_can_open()
*/
NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
bool del_on_close;
bool stream_existed, stream_truncate=false;
uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
+ bool allow_level_II_oplock = false;
/* use the generic mapping code to avoid implementing all the
different open calls. */
oplock_level = OPLOCK_EXCLUSIVE;
}
+ if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) {
+ allow_level_II_oplock = true;
+ }
+
/* see if we are allowed to open at the same time as existing opens */
- status = odb_open_file(lck, f->handle, name->full_name, name->stream_id,
- share_access, access_mask, del_on_close,
- io->generic.in.open_disposition,
- false, oplock_level, &oplock_granted);
+ status = odb_can_open(lck, name->stream_id,
+ share_access, access_mask, del_on_close,
+ io->generic.in.open_disposition, false);
/*
* on a sharing violation we need to retry when the file is closed by
return status;
}
- 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;
-
if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) {
flags |= O_RDWR;
} else {
f->handle->fd = fd;
+ /* now really mark the file as open */
+ status = odb_open_file(lck, f->handle, name->full_name,
+ &f->handle->fd, allow_level_II_oplock,
+ oplock_level, &oplock_granted);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(lck);
+ return status;
+ }
+
+ 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;
+
stream_existed = name->stream_exists;
/* if this was a stream create then create the stream as well */