static fsal_status_t lock_op(struct fsal_obj_handle *obj_hdl, const struct req_op_context *opctx, void * p_owner, fsal_lock_op_t lock_op, fsal_lock_param_t *request_lock, fsal_lock_param_t *conflicting_lock) { int rc = 0; fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 }; struct glusterfs_handle *objhandle = container_of(obj_hdl, struct glusterfs_handle, handle); struct flock flock; int cmd; int saverrno = 0; #ifdef GLTIMING struct timespec s_time, e_time; now(&s_time); #endif if (objhandle->openflags == FSAL_O_CLOSED) { LogDebug(COMPONENT_FSAL, "ERROR: Attempting to lock with no file descriptor open"); status.major = ERR_FSAL_FAULT; goto out; } if (lock_op == FSAL_OP_LOCKT) { cmd = F_GETLK; } else if (lock_op == FSAL_OP_LOCK || lock_op == FSAL_OP_UNLOCK) { cmd = F_SETLK; } else { LogDebug(COMPONENT_FSAL, "ERROR: Unsupported lock operation %d\n", lock_op); status.major = ERR_FSAL_NOTSUPP; goto out; } if (request_lock->lock_type == FSAL_LOCK_R) { flock.l_type = F_RDLCK; } else if (request_lock->lock_type == FSAL_LOCK_W) { flock.l_type = F_WRLCK; } else { LogDebug(COMPONENT_FSAL, "ERROR: The requested lock type was not read or write."); status.major = ERR_FSAL_NOTSUPP; goto out; } /* TODO: Override R/W and just provide U? */ if (lock_op == FSAL_OP_UNLOCK) flock.l_type = F_UNLCK; flock.l_len = request_lock->lock_length; flock.l_start = request_lock->lock_start; flock.l_whence = SEEK_SET; rc = glfs_posix_lock (objhandle->glfd, cmd, &flock); if (rc != 0 && lock_op == FSAL_OP_LOCK && conflicting_lock && (errno == EACCES || errno == EAGAIN)) { /* process conflicting lock */ saverrno = errno; cmd = F_GETLK; rc = glfs_posix_lock (objhandle->glfd, cmd, &flock); if (rc) { LogCrit(COMPONENT_FSAL, "Failed to get conflicting lock post lock" " failure"); status = gluster2fsal_error(errno); goto out; } conflicting_lock->lock_length = flock.l_len; conflicting_lock->lock_start = flock.l_start; conflicting_lock->lock_type = flock.l_type; status = gluster2fsal_error(saverrno); goto out; } else if (rc != 0) { status = gluster2fsal_error(errno); goto out; } if (conflicting_lock != NULL) { if (lock_op == FSAL_OP_LOCKT && flock.l_type != F_UNLCK) { conflicting_lock->lock_length = flock.l_len; conflicting_lock->lock_start = flock.l_start; conflicting_lock->lock_type = flock.l_type; } else { conflicting_lock->lock_length = 0; conflicting_lock->lock_start = 0; conflicting_lock->lock_type = FSAL_NO_LOCK; } } out: #ifdef GLTIMING now(&e_time); latency_update(&s_time, &e_time, lat_lock_op); #endif return status; }
int lock_test(glfs_fd_t *glfd1, glfs_fd_t *glfd2, bool should_fail, int l1_start, int l1_len, char *l1_owner, int lo1_len, int l2_start, int l2_len, char *l2_owner, int lo2_len) { int ret = -1, f_ret = -1; struct flock lock1 = { 0, }, lock2 = { 0, }; lock1: if (!glfd1) goto lock2; /* lock on glfd1 */ lock1.l_type = F_WRLCK; lock1.l_whence = SEEK_SET; lock1.l_start = l1_start; lock1.l_len = l1_len; ret = glfs_fd_set_lkowner(glfd1, l1_owner, lo1_len); LOG_ERR("glfs_fd_set_lkowner on glfd1", ret); ret = glfs_posix_lock(glfd1, F_SETLK, &lock1); LOG_ERR("glfs_posix_lock on glfd1", ret); lock2: if (!glfd2) goto out; /* lock on glfd2 */ lock2.l_type = F_WRLCK; lock2.l_whence = SEEK_SET; lock2.l_start = l2_start; lock2.l_len = l2_len; ret = glfs_fd_set_lkowner(glfd2, l2_owner, lo2_len); LOG_ERR("glfs_fd_set_lkowner on glfd2", ret); ret = glfs_posix_lock(glfd2, F_SETLK, &lock2); if (should_fail && ret) { f_ret = 0; } else if (!ret && !should_fail) { f_ret = 0; } else { f_ret = -1; } out: fprintf(stderr, "Lock test on glfd1 (start(%d), len(%d)," " lk_owner(%s)) and glfd2 (start(%d), len(%d), " "lk_owner(%s)) - expected(%s) - result(%s)\n", l1_start, l1_len, l1_owner, l2_start, l2_len, l2_owner, (should_fail ? "FAIL" : "SUCCESS"), (ret ? "FAIL" : "SUCCESS")); return f_ret; }