示例#1
0
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");
}
示例#2
0
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
}
示例#3
0
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;
}
示例#4
0
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;
}