📄 opendb_tdb.c
字号:
} } if (_attrs_only) { *_attrs_only = attrs_only; } return NT_STATUS_OK;}/* register an open file in the open files database. The share_access rules are implemented by odb_can_open() and it's needed to call odb_can_open() before odb_open_file() otherwise NT_STATUS_INTERNAL_ERROR is returned Note that the path is only used by the delete on close logic, not for comparing with other filenames*/static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle, const char *path, int *fd, bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted){ struct odb_context *odb = lck->odb; if (!lck->can_open.e) { return NT_STATUS_INTERNAL_ERROR; } if (odb->oplocks == false) { oplock_level = OPLOCK_NONE; } if (!oplock_granted) { oplock_level = OPLOCK_NONE; } if (lck->file.path == NULL) { lck->file.path = talloc_strdup(lck, path); NT_STATUS_HAVE_NO_MEMORY(lck->file.path); } /* possibly grant an exclusive, batch or level2 oplock */ if (lck->can_open.attrs_only) { oplock_level = OPLOCK_NONE; } else if (oplock_level == OPLOCK_EXCLUSIVE) { if (lck->file.num_entries == 0) { oplock_level = OPLOCK_EXCLUSIVE; } else if (allow_level_II_oplock) { oplock_level = OPLOCK_LEVEL_II; } else { oplock_level = OPLOCK_NONE; } } else if (oplock_level == OPLOCK_BATCH) { if (lck->file.num_entries == 0) { oplock_level = OPLOCK_BATCH; } else if (allow_level_II_oplock) { oplock_level = OPLOCK_LEVEL_II; } else { oplock_level = OPLOCK_NONE; } } else if (oplock_level == OPLOCK_LEVEL_II) { oplock_level = OPLOCK_LEVEL_II; } else { oplock_level = OPLOCK_NONE; } lck->can_open.e->file_handle = file_handle; lck->can_open.e->fd = fd; lck->can_open.e->allow_level_II_oplock = allow_level_II_oplock; lck->can_open.e->oplock_level = oplock_level; if (odb->lease_ctx && fd) { NTSTATUS status; status = sys_lease_setup(odb->lease_ctx, lck->can_open.e); NT_STATUS_NOT_OK_RETURN(status); } if (oplock_granted) { if (lck->can_open.e->oplock_level == OPLOCK_EXCLUSIVE) { *oplock_granted = EXCLUSIVE_OPLOCK_RETURN; } else if (lck->can_open.e->oplock_level == OPLOCK_BATCH) { *oplock_granted = BATCH_OPLOCK_RETURN; } else if (lck->can_open.e->oplock_level == OPLOCK_LEVEL_II) { *oplock_granted = LEVEL_II_OPLOCK_RETURN; } else { *oplock_granted = NO_OPLOCK_RETURN; } } /* it doesn't conflict, so add it to the end */ lck->file.entries = talloc_realloc(lck, lck->file.entries, struct opendb_entry, lck->file.num_entries+1); NT_STATUS_HAVE_NO_MEMORY(lck->file.entries); lck->file.entries[lck->file.num_entries] = *lck->can_open.e; lck->file.num_entries++; talloc_free(lck->can_open.e); lck->can_open.e = NULL; return odb_push_record(lck, &lck->file);}/* register a pending open file in the open files database*/static NTSTATUS odb_tdb_open_file_pending(struct odb_lock *lck, void *private){ struct odb_context *odb = lck->odb; if (lck->file.path == NULL) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } lck->file.pending = talloc_realloc(lck, lck->file.pending, struct opendb_pending, lck->file.num_pending+1); NT_STATUS_HAVE_NO_MEMORY(lck->file.pending); lck->file.pending[lck->file.num_pending].server = odb->ntvfs_ctx->server_id; lck->file.pending[lck->file.num_pending].notify_ptr = private; lck->file.num_pending++; return odb_push_record(lck, &lck->file);}/* remove a opendb entry*/static NTSTATUS odb_tdb_close_file(struct odb_lock *lck, void *file_handle, const char **_delete_path){ struct odb_context *odb = lck->odb; const char *delete_path = NULL; int i; if (lck->file.path == NULL) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* find the entry, and delete it */ for (i=0;i<lck->file.num_entries;i++) { if (file_handle == lck->file.entries[i].file_handle && cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.entries[i].server)) { if (lck->file.entries[i].delete_on_close) { lck->file.delete_on_close = true; } if (odb->lease_ctx && lck->file.entries[i].fd) { NTSTATUS status; status = sys_lease_remove(odb->lease_ctx, &lck->file.entries[i]); NT_STATUS_NOT_OK_RETURN(status); } if (i < lck->file.num_entries-1) { memmove(lck->file.entries+i, lck->file.entries+i+1, (lck->file.num_entries - (i+1)) * sizeof(struct opendb_entry)); } break; } } if (i == lck->file.num_entries) { return NT_STATUS_UNSUCCESSFUL; } /* send any pending notifications, removing them once sent */ for (i=0;i<lck->file.num_pending;i++) { messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, lck->file.pending[i].server, MSG_PVFS_RETRY_OPEN, lck->file.pending[i].notify_ptr); } lck->file.num_pending = 0; lck->file.num_entries--; if (lck->file.num_entries == 0 && lck->file.delete_on_close) { delete_path = lck->file.path; } if (_delete_path) { *_delete_path = delete_path; } return odb_push_record(lck, &lck->file);}/* update the oplock level of the client*/static NTSTATUS odb_tdb_update_oplock(struct odb_lock *lck, void *file_handle, uint32_t oplock_level){ struct odb_context *odb = lck->odb; int i; if (lck->file.path == NULL) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* find the entry, and update it */ for (i=0;i<lck->file.num_entries;i++) { if (file_handle == lck->file.entries[i].file_handle && cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.entries[i].server)) { lck->file.entries[i].oplock_level = oplock_level; if (odb->lease_ctx && lck->file.entries[i].fd) { NTSTATUS status; status = sys_lease_update(odb->lease_ctx, &lck->file.entries[i]); NT_STATUS_NOT_OK_RETURN(status); } break; } } if (i == lck->file.num_entries) { return NT_STATUS_UNSUCCESSFUL; } /* send any pending notifications, removing them once sent */ for (i=0;i<lck->file.num_pending;i++) { messaging_send_ptr(odb->ntvfs_ctx->msg_ctx, lck->file.pending[i].server, MSG_PVFS_RETRY_OPEN, lck->file.pending[i].notify_ptr); } lck->file.num_pending = 0; return odb_push_record(lck, &lck->file);}/* send oplocks breaks to none to all level2 holders*/static NTSTATUS odb_tdb_break_oplocks(struct odb_lock *lck){ struct odb_context *odb = lck->odb; int i; bool modified = false; /* see if anyone has an oplock, which we need to break */ for (i=0;i<lck->file.num_entries;i++) { if (lck->file.entries[i].oplock_level == OPLOCK_LEVEL_II) { /* * there could be multiple level2 oplocks * and we just send a break to none to all of them * without waiting for a release */ odb_oplock_break_send(odb->ntvfs_ctx->msg_ctx, &lck->file.entries[i], OPLOCK_BREAK_TO_NONE); lck->file.entries[i].oplock_level = OPLOCK_NONE; modified = true; } } if (modified) { return odb_push_record(lck, &lck->file); } return NT_STATUS_OK;}/* remove a pending opendb entry*/static NTSTATUS odb_tdb_remove_pending(struct odb_lock *lck, void *private){ struct odb_context *odb = lck->odb; int i; if (lck->file.path == NULL) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* find the entry, and delete it */ for (i=0;i<lck->file.num_pending;i++) { if (private == lck->file.pending[i].notify_ptr && cluster_id_equal(&odb->ntvfs_ctx->server_id, &lck->file.pending[i].server)) { if (i < lck->file.num_pending-1) { memmove(lck->file.pending+i, lck->file.pending+i+1, (lck->file.num_pending - (i+1)) * sizeof(struct opendb_pending)); } break; } } if (i == lck->file.num_pending) { return NT_STATUS_UNSUCCESSFUL; } lck->file.num_pending--; return odb_push_record(lck, &lck->file);}/* rename the path in a open file*/static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path){ if (lck->file.path == NULL) { /* not having the record at all is OK */ return NT_STATUS_OK; } lck->file.path = talloc_strdup(lck, path); NT_STATUS_HAVE_NO_MEMORY(lck->file.path); return odb_push_record(lck, &lck->file);}/* get the path of an open file*/static NTSTATUS odb_tdb_get_path(struct odb_lock *lck, const char **path){ *path = NULL; /* we don't ignore NT_STATUS_OBJECT_NAME_NOT_FOUND here */ if (lck->file.path == NULL) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } *path = lck->file.path; return NT_STATUS_OK;}/* update delete on close flag on an open file*/static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_close){ if (lck->file.path == NULL) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } lck->file.delete_on_close = del_on_close; return odb_push_record(lck, &lck->file);}/* return the current value of the delete_on_close bit, and how many 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){ struct odb_lock *lck; (*del_on_close) = false; lck = odb_lock(odb, odb, key); NT_STATUS_HAVE_NO_MEMORY(lck); (*del_on_close) = lck->file.delete_on_close; talloc_free(lck); return NT_STATUS_OK;}/* determine if a file can be opened with the given share_access, create_options and access_mask*/static NTSTATUS odb_tdb_can_open(struct odb_lock *lck, uint32_t stream_id, uint32_t share_access, uint32_t access_mask, bool delete_on_close, uint32_t open_disposition, bool break_to_none){ struct odb_context *odb = lck->odb; NTSTATUS status; status = odb_tdb_open_can_internal(odb, &lck->file, stream_id, share_access, access_mask, delete_on_close, open_disposition, break_to_none, &lck->can_open.attrs_only); NT_STATUS_NOT_OK_RETURN(status); lck->can_open.e = talloc(lck, struct opendb_entry); NT_STATUS_HAVE_NO_MEMORY(lck->can_open.e); lck->can_open.e->server = odb->ntvfs_ctx->server_id; lck->can_open.e->file_handle = NULL; lck->can_open.e->fd = NULL; lck->can_open.e->stream_id = stream_id; lck->can_open.e->share_access = share_access; lck->can_open.e->access_mask = access_mask; lck->can_open.e->delete_on_close = delete_on_close; lck->can_open.e->allow_level_II_oplock = false; lck->can_open.e->oplock_level = OPLOCK_NONE; return NT_STATUS_OK;}static const struct opendb_ops opendb_tdb_ops = { .odb_init = odb_tdb_init, .odb_lock = odb_tdb_lock, .odb_get_key = odb_tdb_get_key, .odb_open_file = odb_tdb_open_file, .odb_open_file_pending = odb_tdb_open_file_pending, .odb_close_file = odb_tdb_close_file, .odb_remove_pending = odb_tdb_remove_pending, .odb_rename = odb_tdb_rename, .odb_get_path = odb_tdb_get_path, .odb_set_delete_on_close = odb_tdb_set_delete_on_close, .odb_get_delete_on_close = odb_tdb_get_delete_on_close, .odb_can_open = odb_tdb_can_open, .odb_update_oplock = odb_tdb_update_oplock, .odb_break_oplocks = odb_tdb_break_oplocks};void odb_tdb_init_ops(void){ sys_lease_init(); odb_set_ops(&opendb_tdb_ops);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -