Ejemplo n.º 1
0
// Format: ip{4,6}_address:path options
// Available options:
//	hard		- retry requests until success
//	soft		- retry requests no more than retrans times (default)
//  timeo=X		- request time limit before next retransmission (default: 60s)
//	retrans=X	- retry requests X times (default: 5)
//	ac			- use metadata cache (default)
//	noac		- do not use metadata cache
//	xattr-emu	- emulate named attributes
//	noxattr-emu	- do not emulate named attributes (default)
//	port=X		- connect to port X (default: 2049)
//	proto=X		- user transport protocol X (default: tcp)
//	dirtime=X	- attempt revalidate directory cache not more often than each X
//				  seconds
static status_t
ParseArguments(const char* _args, AddressResolver** address, char** _path,
	MountConfiguration* conf)
{
	if (_args == NULL)
		return B_BAD_VALUE;

	char* args = strdup(_args);
	if (args == NULL)
		return B_NO_MEMORY;
	MemoryDeleter argsDeleter(args);

	char* options = strchr(args, ' ');
	if (options != NULL)
		*options++ = '\0';

	char* path = strrchr(args, ':');
	if (path == NULL)
		return B_MISMATCHED_VALUES;
	*path++ = '\0';

	*address = new AddressResolver(args);
	if (*address == NULL)
		return B_NO_MEMORY;

	*_path = strdup(path);
	if (*_path == NULL) {
		delete *address;
		return B_NO_MEMORY;
	}

	conf->fHard = false;
	conf->fRetryLimit = 5;
	conf->fRequestTimeout = sSecToBigTime(60);
	conf->fEmulateNamedAttrs = false;
	conf->fCacheMetadata = true;
	conf->fDirectoryCacheTime = sSecToBigTime(5);

	char* optionsEnd = NULL;
	if (options != NULL)
		optionsEnd = strchr(options, ' ');
	while (options != NULL && *options != '\0') {
		if (optionsEnd != NULL)
			*optionsEnd++ = '\0';

		if (strcmp(options, "hard") == 0)
			conf->fHard = true;
		else if (strncmp(options, "retrans=", 8) == 0) {
			options += strlen("retrans=");
			conf->fRetryLimit = atoi(options);
		} else if (strncmp(options, "timeo=", 6) == 0) {
			options += strlen("timeo=");
			conf->fRequestTimeout = atoi(options);
		} else if (strcmp(options, "noac") == 0)
			conf->fCacheMetadata = false;
		else if (strcmp(options, "xattr-emu") == 0)
			conf->fEmulateNamedAttrs = true;
		else if (strncmp(options, "port=", 5) == 0) {
			options += strlen("port=");
			(*address)->ForcePort(atoi(options));
		} else if (strncmp(options, "proto=", 6) == 0) {
			options += strlen("proto=");
			(*address)->ForceProtocol(options);
		} else if (strncmp(options, "dirtime=", 8) == 0) {
			options += strlen("dirtime=");
			conf->fDirectoryCacheTime = sSecToBigTime(atoi(options));
		}

		options = optionsEnd;
		if (options != NULL)
			optionsEnd = strchr(options, ' ');
	}

	return B_OK;
}
Ejemplo n.º 2
0
bool
NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
	OpenStateCookie* cookie, OpenState* state, uint32* sequence)
{
	uint32 leaseTime;

	// No request send by the client should cause any of the following errors.
	ASSERT(nfs4Error != NFS4ERR_CLID_INUSE);
	ASSERT(nfs4Error != NFS4ERR_NOFILEHANDLE);
	ASSERT(nfs4Error != NFS4ERR_BAD_STATEID);
	ASSERT(nfs4Error != NFS4ERR_RESTOREFH);
	ASSERT(nfs4Error != NFS4ERR_LOCKS_HELD);
	ASSERT(nfs4Error != NFS4ERR_OP_ILLEGAL);

	if (cookie != NULL)
		state = cookie->fOpenState;

	switch (nfs4Error) {
		case NFS4_OK:
			return false;

		// retransmission of CLOSE caused seqid to fall back
		case NFS4ERR_BAD_SEQID:
			ASSERT(sequence != NULL);
			(*sequence)++;
			return true;

		// server needs more time, we need to wait
		case NFS4ERR_LOCKED:
		case NFS4ERR_DELAY:
			if (sequence != NULL)
				fFileSystem->OpenOwnerSequenceUnlock(*sequence);

			if (cookie == NULL) {
				snooze_etc(sSecToBigTime(5), B_SYSTEM_TIMEBASE,
					B_RELATIVE_TIMEOUT);

				if (sequence != NULL)
					*sequence = fFileSystem->OpenOwnerSequenceLock();

				return true;
			}

			if ((cookie->fMode & O_NONBLOCK) == 0) {
				status_t result = acquire_sem_etc(cookie->fSnoozeCancel, 1,
					B_RELATIVE_TIMEOUT, sSecToBigTime(5));

				if (sequence != NULL)
					*sequence = fFileSystem->OpenOwnerSequenceLock();

				if (result != B_TIMED_OUT) {
					if (result == B_OK)
						release_sem(cookie->fSnoozeCancel);
					return false;
				}
				return true;
			}

			if (sequence != NULL)
				*sequence = fFileSystem->OpenOwnerSequenceLock();
			return false;

		// server is in grace period, we need to wait
		case NFS4ERR_GRACE:
			leaseTime = fFileSystem->NFSServer()->LeaseTime();
			if (sequence != NULL)
				fFileSystem->OpenOwnerSequenceUnlock(*sequence);

			if (cookie == NULL) {
				snooze_etc(sSecToBigTime(leaseTime) / 3, B_SYSTEM_TIMEBASE,
					B_RELATIVE_TIMEOUT);
				if (sequence != NULL)
					*sequence = fFileSystem->OpenOwnerSequenceLock();
				return true;
			}

			if ((cookie->fMode & O_NONBLOCK) == 0) {
				status_t result = acquire_sem_etc(cookie->fSnoozeCancel, 1,
					B_RELATIVE_TIMEOUT, sSecToBigTime(leaseTime) / 3);

				if (sequence != NULL)
					*sequence = fFileSystem->OpenOwnerSequenceLock();

				if (result != B_TIMED_OUT) {
					if (result == B_OK)
						release_sem(cookie->fSnoozeCancel);
					return false;
				}
				return true;
			}

			if (sequence != NULL)
				*sequence = fFileSystem->OpenOwnerSequenceLock();
			return false;

		// server has rebooted, reclaim share and try again
		case NFS4ERR_STALE_CLIENTID:
		case NFS4ERR_STALE_STATEID:
			if (state != NULL) {
				if (sequence != NULL)
					fFileSystem->OpenOwnerSequenceUnlock(*sequence);

				fFileSystem->NFSServer()->ServerRebooted(state->fClientID);
				if (sequence != NULL)
					*sequence = fFileSystem->OpenOwnerSequenceLock();

				return true;
			}
			return false;

		// File Handle has expired, is invalid or the node has been deleted
		case NFS4ERR_NOFILEHANDLE:
		case NFS4ERR_BADHANDLE:
		case NFS4ERR_FHEXPIRED:
		case NFS4ERR_STALE:
			if (fInfo.UpdateFileHandles(fFileSystem) == B_OK)
				return true;
			return false;

		// filesystem has been moved
		case NFS4ERR_LEASE_MOVED:
		case NFS4ERR_MOVED:
			fFileSystem->Migrate(serv);
			return true;

		// lease has expired
		case NFS4ERR_EXPIRED:
			if (state != NULL) {
				fFileSystem->NFSServer()->ClientId(state->fClientID, true);
				return true;
			}
			return false;

		default:
			return false;
	}
}