char *parse_lock(char *line, struct response *req) { char *more; more = get_fpos(line, &req->r_fpos, REQUIRES_MORE); if (more == NULL) return more; more = get_lock_type(more, &req->r_lock_type); if (more == NULL) return more; if (req->r_lock_type != F_RDLCK && req->r_lock_type != F_WRLCK) { errno = EINVAL; strcpy(errdetail, "Invalid lock type"); sprintf(badtoken, "%s", str_lock_type(req->r_lock_type)); } more = get_longlong(more, &req->r_start, REQUIRES_MORE, "Invalid lock start"); if (more == NULL) return more; return get_longlong(more, &req->r_length, REQUIRES_NO_MORE, "Invalid lock len"); }
void DistributedLock::do_open() { /* If there is no persistence, then there is no contention for distributed locks and we can just return immediately. */ if (!object_.get_persistence_enabled()) return; #ifdef P4P_CLUSTER std::string lockfile = object_.get_file().string() + ".lock"; /* open the file */ fd_ = open(lockfile.c_str(), get_open_flags(), 0600); if (fd_ < 0) throw bfs::filesystem_error("open failed", lockfile, bs::error_code(errno, boost::system::posix_category)); /* acquire the lock */ struct flock lock; memset(&lock, 0, sizeof(lock)); lock.l_type = get_lock_type(); lock.l_whence = SEEK_SET; if (fcntl(fd_, F_SETLKW, &lock) < 0) throw bfs::filesystem_error("lock failed", lockfile, bs::error_code(errno, boost::system::posix_category)); /* ensure the local object is up to date */ try { UpgradableReadLock local_lock(object_); object_.update(*this, local_lock); } catch (distributed_object_error& e) { /* ignore exceptions */ } #else throw std::runtime_error("Persistence support not enabled"); #endif }
static int handle_lock(nfs41_upcall *upcall) { stateid_arg stateid; lock_upcall_args *args = &upcall->args.lock; nfs41_open_state *state = upcall->state_ref; nfs41_lock_state *lock; const uint32_t type = get_lock_type(args->exclusive, args->blocking); int status = NO_ERROR; /* 18.10.3. Operation 12: LOCK - Create Lock * "To lock the file from a specific offset through the end-of-file * (no matter how long the file actually is) use a length field equal * to NFS4_UINT64_MAX." */ if (args->length >= NFS4_UINT64_MAX - args->offset) args->length = NFS4_UINT64_MAX; /* allocate the lock state */ lock = calloc(1, sizeof(nfs41_lock_state)); if (lock == NULL) { status = GetLastError(); goto out; } lock->offset = args->offset; lock->length = args->length; lock->exclusive = args->exclusive; /* if we hold a write delegation, handle the lock locally */ if (open_lock_delegate(state, lock)) { dprintf(LKLVL, "delegated lock { %llu, %llu }\n", lock->offset, lock->length); args->acquired = TRUE; /* for cancel_lock() */ goto out; } /* open_to_lock_owner4 requires an open stateid; if we * have a delegation, convert it to an open stateid */ status = nfs41_delegation_to_open(state, TRUE); if (status) { status = ERROR_FILE_INVALID; goto out_free; } EnterCriticalSection(&state->locks.lock); lock_stateid_arg(state, &stateid); status = nfs41_lock(state->session, &state->file, &state->owner, type, lock->offset, lock->length, FALSE, TRUE, &stateid); if (status) { dprintf(LKLVL, "nfs41_lock failed with %s\n", nfs_error_string(status)); status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP); LeaveCriticalSection(&state->locks.lock); goto out_free; } /* save lock state with the open */ open_lock_add(state, &stateid, lock); LeaveCriticalSection(&state->locks.lock); args->acquired = TRUE; /* for cancel_lock() */ out: return status; out_free: free(lock); goto out; }
char *parse_response(char *line, struct response *resp) { char *rest; long long int dummy_len; if (resp->r_original == '\0') strcpy(resp->r_original, line); resp->r_cmd = NUM_COMMANDS; resp->r_tag = -1; rest = get_tag(line, resp, true, REQUIRES_MORE); if (rest == NULL) goto fail; rest = get_command(rest, &resp->r_cmd); if (rest == NULL) goto fail; rest = get_status(rest, resp); if (rest == NULL) goto fail; switch (resp->r_status) { case STATUS_OK: switch (resp->r_cmd) { case CMD_COMMENT: case CMD_HELLO: rest = get_str(rest, resp->r_data, &resp->r_length, REQUIRES_NO_MORE); break; case CMD_LOCKW: case CMD_LOCK: case CMD_UNLOCK: case CMD_TEST: case CMD_LIST: case CMD_HOP: case CMD_UNHOP: case NUM_COMMANDS: strcpy(errdetail, "Unexpected Status"); errno = EINVAL; sprintf(badtoken, "%s", str_status(resp->r_status)); goto fail; case CMD_ALARM: return get_long(rest, &resp->r_secs, REQUIRES_NO_MORE, "Invalid alarm time"); case CMD_QUIT: return rest; case CMD_OPEN: rest = get_fpos(rest, &resp->r_fpos, REQUIRES_MORE); if (rest == NULL) goto fail; rest = get_long(rest, &resp->r_fno, REQUIRES_NO_MORE, "Invalid file number"); break; case CMD_CLOSE: case CMD_SEEK: rest = get_fpos(rest, &resp->r_fpos, REQUIRES_NO_MORE); break; case CMD_WRITE: rest = get_fpos(rest, &resp->r_fpos, REQUIRES_MORE); if (rest == NULL) goto fail; rest = get_longlong(rest, &resp->r_length, REQUIRES_NO_MORE, "Invalid length"); break; case CMD_READ: rest = get_fpos(rest, &resp->r_fpos, REQUIRES_MORE); if (rest == NULL) goto fail; rest = get_longlong(rest, &resp->r_length, REQUIRES_MORE, "Invalid length"); if (rest == NULL) goto fail; rest = get_str(rest, resp->r_data, &dummy_len, REQUIRES_NO_MORE); if (dummy_len != resp->r_length) { strcpy(errdetail, "Read length doesn't match"); errno = EINVAL; sprintf(badtoken, "%lld != %lld", dummy_len, resp->r_length); goto fail; } break; } break; case STATUS_AVAILABLE: case STATUS_GRANTED: case STATUS_DENIED: case STATUS_DEADLOCK: rest = get_fpos(rest, &resp->r_fpos, REQUIRES_MORE); if (rest == NULL) goto fail; if (resp->r_cmd != CMD_LIST) { rest = get_lock_type(rest, &resp->r_lock_type); if (rest == NULL) goto fail; } rest = get_longlong(rest, &resp->r_start, REQUIRES_MORE, "Invalid lock start"); if (rest == NULL) goto fail; rest = get_longlong(rest, &resp->r_length, REQUIRES_NO_MORE, "Invalid lock length"); break; case STATUS_CONFLICT: rest = get_fpos(rest, &resp->r_fpos, REQUIRES_MORE); if (rest == NULL) goto fail; rest = get_long(rest, &resp->r_pid, REQUIRES_MORE, "Invalid conflict pid"); if (rest == NULL) goto fail; rest = get_lock_type(rest, &resp->r_lock_type); if (rest == NULL) goto fail; rest = get_longlong(rest, &resp->r_start, REQUIRES_MORE, "Invalid lock start"); if (rest == NULL) goto fail; rest = get_longlong(rest, &resp->r_length, REQUIRES_NO_MORE, "Invalid lock length"); break; case STATUS_CANCELED: if (resp->r_cmd == CMD_LOCKW) { rest = get_fpos(rest, &resp->r_fpos, REQUIRES_MORE); if (rest == NULL) goto fail; rest = get_lock_type(rest, &resp->r_lock_type); if (rest == NULL) goto fail; rest = get_longlong(rest, &resp->r_start, REQUIRES_MORE, "Invalid lock start"); if (rest == NULL) goto fail; rest = get_longlong(rest, &resp->r_length, REQUIRES_NO_MORE, "Invalid lock length"); } else if (resp->r_cmd == CMD_ALARM) { rest = get_long(rest, &resp->r_secs, REQUIRES_NO_MORE, "Invalid alarm time"); } else { } break; case STATUS_COMPLETED: break; case STATUS_ERRNO: rest = get_long(rest, &resp->r_errno, REQUIRES_MORE, "Invalid errno"); if (rest == NULL) goto fail; strncpy(resp->r_data, rest, MAXSTR); rest += strlen(rest); break; case STATUS_PARSE_ERROR: break; case STATUS_ERROR: break; } if (rest != NULL) return rest; fail: resp->r_status = STATUS_PARSE_ERROR; sprintf(resp->r_data, "%s %ld ERRNO %d \"%s\" \"%s\" bad token \"%s\"", commands[resp->r_cmd].cmd_name, resp->r_tag, errno, strerror(errno), errdetail, badtoken); resp->r_cmd = NUM_COMMANDS; return NULL; }