📄 brlock_ctdb.c
字号:
if (nlocks == NULL) { return CTDB_ERR_NOMEM; } call->reply_data->dptr = (uint8_t *)nlocks; nlocks[ncount] = locks[i]; call->reply_data->dsize += sizeof(struct lock_struct); } } return 0;}/* send notifications for all pending locks - the file is being closed by this user*/static int brl_ctdb_notify_all(struct ctdb_call_info *call, struct lock_struct *locks, int count){ int i; for (i=0;i<count;i++) { if (locks->lock_type >= PENDING_READ_LOCK) { int ret = brl_ctdb_notify_unlock(call, locks, count, &locks[i]); if (ret != 0) return ret; } } return 0;}/* send off any messages needed to notify of pending locks that should now retry*/static void brl_ctdb_notify_send(struct brl_context *brl, TDB_DATA *reply_data){ struct lock_struct *locks = (struct lock_struct *)reply_data->dptr; int i, count = reply_data->dsize / sizeof(struct lock_struct); for (i=0;i<count;i++) { messaging_send_ptr(brl->messaging_ctx, locks[i].context.server, MSG_BRL_RETRY, locks[i].notify_ptr); }}struct ctdb_unlock_req { uint16_t smbpid; uint64_t start; uint64_t size; struct server_id server; struct brl_context *brl; struct ntvfs_handle *ntvfs;};/* Unlock a range of bytes.*/static int brl_ctdb_unlock_func(struct ctdb_call_info *call){ struct ctdb_unlock_req *req = (struct ctdb_unlock_req *)call->call_data->dptr; TDB_DATA dbuf; int count, i; struct lock_struct *locks, *lock; struct lock_context context; NTSTATUS status = NT_STATUS_OK; dbuf = call->record_data; context.smbpid = req->smbpid; context.server = req->server; context.ctx = req->brl; /* there are existing locks - find a match */ locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); for (i=0; i<count; i++) { lock = &locks[i]; if (brl_ctdb_same_context(&lock->context, &context) && lock->ntvfs == req->ntvfs && lock->start == req->start && lock->size == req->size && lock->lock_type == WRITE_LOCK) { break; } } if (i < count) goto found; for (i=0; i<count; i++) { lock = &locks[i]; if (brl_ctdb_same_context(&lock->context, &context) && lock->ntvfs == req->ntvfs && lock->start == req->start && lock->size == req->size && lock->lock_type < PENDING_READ_LOCK) { break; } }found: if (i < count) { struct lock_struct removed_lock = *lock; call->new_data = talloc(call, TDB_DATA); if (call->new_data == NULL) { return CTDB_ERR_NOMEM; } call->new_data->dptr = talloc_size(call, dbuf.dsize - sizeof(*lock)); if (call->new_data->dptr == NULL) { return CTDB_ERR_NOMEM; } call->new_data->dsize = dbuf.dsize - sizeof(*lock); memcpy(call->new_data->dptr, locks, i*sizeof(*lock)); memcpy(call->new_data->dptr+i*sizeof(*lock), locks+i+1, (count-(i+1))*sizeof(*lock)); if (count > 1) { int ret = brl_ctdb_notify_unlock(call, locks, count, &removed_lock); if (ret != 0) return ret; } } if (i == count) { /* we didn't find it */ status = NT_STATUS_RANGE_NOT_LOCKED; } call->status = NT_STATUS_V(status); return 0;}/* Unlock a range of bytes.*/static NTSTATUS brl_ctdb_unlock(struct brl_context *brl, struct brl_handle *brlh, uint16_t smbpid, uint64_t start, uint64_t size){ struct ctdb_call call; struct ctdb_unlock_req req; int ret; call.call_id = FUNC_BRL_UNLOCK; call.key.dptr = brlh->key.data; call.key.dsize = brlh->key.length; call.call_data.dptr = (uint8_t *)&req; call.call_data.dsize = sizeof(req); ZERO_STRUCT(req); req.smbpid = smbpid; req.start = start; req.size = size; req.server = brl->server; req.brl = brl; req.ntvfs = brlh->ntvfs; ret = ctdb_call(brl->ctdb_db, &call); if (ret == -1) { DEBUG(0,("ctdb_call failed - %s\n", __location__)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } brl_ctdb_notify_send(brl, &call.reply_data); return NT_STATUS(call.status);}struct ctdb_remove_pending_req { struct server_id server; void *notify_ptr;};/* remove a pending lock. This is called when the caller has either given up trying to establish a lock or when they have succeeded in getting it. In either case they no longer need to be notified.*/static int brl_ctdb_remove_pending_func(struct ctdb_call_info *call){ struct ctdb_remove_pending_req *req = (struct ctdb_remove_pending_req *)call->call_data->dptr; TDB_DATA dbuf; int count, i; struct lock_struct *locks; NTSTATUS status = NT_STATUS_OK; dbuf = call->record_data; /* there are existing locks - find a match */ locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); for (i=0; i<count; i++) { struct lock_struct *lock = &locks[i]; if (lock->lock_type >= PENDING_READ_LOCK && lock->notify_ptr == req->notify_ptr && cluster_id_equal(&lock->context.server, &req->server)) { call->new_data = talloc(call, TDB_DATA); if (call->new_data == NULL) { return CTDB_ERR_NOMEM; } call->new_data->dptr = talloc_size(call, dbuf.dsize - sizeof(*lock)); if (call->new_data->dptr == NULL) { return CTDB_ERR_NOMEM; } call->new_data->dsize = dbuf.dsize - sizeof(*lock); memcpy(call->new_data->dptr, locks, i*sizeof(*lock)); memcpy(call->new_data->dptr+i*sizeof(*lock), locks+i+1, (count-(i+1))*sizeof(*lock)); break; } } if (i == count) { /* we didn't find it */ status = NT_STATUS_RANGE_NOT_LOCKED; } call->status = NT_STATUS_V(status); return 0;}static NTSTATUS brl_ctdb_remove_pending(struct brl_context *brl, struct brl_handle *brlh, void *notify_ptr){ struct ctdb_call call; struct ctdb_remove_pending_req req; int ret; call.call_id = FUNC_BRL_REMOVE_PENDING; call.key.dptr = brlh->key.data; call.key.dsize = brlh->key.length; call.call_data.dptr = (uint8_t *)&req; call.call_data.dsize = sizeof(req); ZERO_STRUCT(req); req.notify_ptr = notify_ptr; req.server = brl->server; ret = ctdb_call(brl->ctdb_db, &call); if (ret == -1) { DEBUG(0,("ctdb_call failed - %s\n", __location__)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } return NT_STATUS(call.status);}struct ctdb_locktest_req { uint16_t smbpid; uint64_t start; uint64_t size; enum brl_type lock_type; struct brl_context *brl; struct server_id server; struct ntvfs_handle *ntvfs;};/* remove a pending lock. This is called when the caller has either given up trying to establish a lock or when they have succeeded in getting it. In either case they no longer need to be notified.*/static int brl_ctdb_locktest_func(struct ctdb_call_info *call){ struct ctdb_locktest_req *req = (struct ctdb_locktest_req *)call->call_data->dptr; TDB_DATA dbuf; int count, i; struct lock_struct *locks, lock; NTSTATUS status = NT_STATUS_OK; lock.context.smbpid = req->smbpid; lock.context.server = req->server; lock.context.ctx = req->brl; lock.ntvfs = req->ntvfs; lock.start = req->start; lock.size = req->size; lock.lock_type = req->lock_type; dbuf = call->record_data; /* there are existing locks - find a match */ locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); for (i=0; i<count; i++) { if (brl_ctdb_conflict_other(&locks[i], &lock)) { status = NT_STATUS_FILE_LOCK_CONFLICT; break; } } call->status = NT_STATUS_V(status); return 0;}/* Test if we are allowed to perform IO on a region of an open file*/static NTSTATUS brl_ctdb_locktest(struct brl_context *brl, struct brl_handle *brlh, uint16_t smbpid, uint64_t start, uint64_t size, enum brl_type lock_type){ struct ctdb_call call; struct ctdb_locktest_req req; int ret; call.call_id = FUNC_BRL_LOCKTEST; call.key.dptr = brlh->key.data; call.key.dsize = brlh->key.length; call.call_data.dptr = (uint8_t *)&req; call.call_data.dsize = sizeof(req); ZERO_STRUCT(req); req.smbpid = smbpid; req.start = start; req.size = size; req.lock_type = lock_type; req.server = brl->server; req.brl = brl; req.ntvfs = brlh->ntvfs; ret = ctdb_call(brl->ctdb_db, &call); if (ret == -1) { DEBUG(0,("ctdb_call failed - %s\n", __location__)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } return NT_STATUS(call.status);}struct ctdb_close_req { struct brl_context *brl; struct server_id server; struct ntvfs_handle *ntvfs;};/* remove a pending lock. This is called when the caller has either given up trying to establish a lock or when they have succeeded in getting it. In either case they no longer need to be notified.*/static int brl_ctdb_close_func(struct ctdb_call_info *call){ struct ctdb_close_req *req = (struct ctdb_close_req *)call->call_data->dptr; TDB_DATA dbuf; int count, dcount=0, i; struct lock_struct *locks; NTSTATUS status = NT_STATUS_OK; dbuf = call->record_data; /* there are existing locks - find a match */ locks = (struct lock_struct *)dbuf.dptr; count = dbuf.dsize / sizeof(*locks); for (i=0; i<count; i++) { struct lock_struct *lock = &locks[i]; if (lock->context.ctx == req->brl && cluster_id_equal(&lock->context.server, &req->server) && lock->ntvfs == req->ntvfs) { /* found it - delete it */ if (count > 1 && i < count-1) { memmove(&locks[i], &locks[i+1], sizeof(*locks)*((count-1) - i)); } count--; i--; dcount++; } } if (dcount > 0) { call->new_data = talloc(call, TDB_DATA); if (call->new_data == NULL) { return CTDB_ERR_NOMEM; } brl_ctdb_notify_all(call, locks, count); call->new_data->dptr = talloc_size(call, count*sizeof(struct lock_struct)); if (call->new_data->dptr == NULL) { return CTDB_ERR_NOMEM; } call->new_data->dsize = count*sizeof(struct lock_struct); memcpy(call->new_data->dptr, locks, count*sizeof(struct lock_struct)); } call->status = NT_STATUS_V(status); return 0;}/* Test if we are allowed to perform IO on a region of an open file*/static NTSTATUS brl_ctdb_close(struct brl_context *brl, struct brl_handle *brlh){ struct ctdb_call call; struct ctdb_close_req req; int ret; call.call_id = FUNC_BRL_CLOSE; call.key.dptr = brlh->key.data; call.key.dsize = brlh->key.length; call.call_data.dptr = (uint8_t *)&req; call.call_data.dsize = sizeof(req); ZERO_STRUCT(req); req.brl = brl; req.server = brl->server; req.ntvfs = brlh->ntvfs; ret = ctdb_call(brl->ctdb_db, &call); if (ret == -1) { DEBUG(0,("ctdb_call failed - %s\n", __location__)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } brl_ctdb_notify_send(brl, &call.reply_data); return NT_STATUS(call.status);}static const struct brlock_ops brlock_tdb_ops = { .brl_init = brl_ctdb_init, .brl_create_handle = brl_ctdb_create_handle, .brl_lock = brl_ctdb_lock, .brl_unlock = brl_ctdb_unlock, .brl_remove_pending = brl_ctdb_remove_pending, .brl_locktest = brl_ctdb_locktest, .brl_close = brl_ctdb_close};void brl_ctdb_init_ops(void){ struct ctdb_context *ctdb = talloc_get_type(cluster_backend_handle(), struct ctdb_context); struct ctdb_db_context *ctdb_db; brl_set_ops(&brlock_tdb_ops); ctdb_db = ctdb_db_handle(ctdb, "brlock"); if (ctdb_db == NULL) { DEBUG(0,("Failed to get attached ctdb db handle for brlock\n")); return; } ctdb_set_call(ctdb_db, brl_ctdb_lock_func, FUNC_BRL_LOCK); ctdb_set_call(ctdb_db, brl_ctdb_unlock_func, FUNC_BRL_UNLOCK); ctdb_set_call(ctdb_db, brl_ctdb_remove_pending_func, FUNC_BRL_REMOVE_PENDING); ctdb_set_call(ctdb_db, brl_ctdb_locktest_func, FUNC_BRL_LOCKTEST); ctdb_set_call(ctdb_db, brl_ctdb_close_func, FUNC_BRL_CLOSE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -