Example #1
0
/*
 * parse the mount options
 * - this function has been shamelessly adapted from the ext3 fs which
 *   shamelessly adapted it from the msdos fs
 */
static int afs_parse_options(struct afs_mount_params *params,
			     char *options, const char **devname)
{
	struct afs_cell *cell;
	substring_t args[MAX_OPT_ARGS];
	char *p;
	int token;

	_enter("%s", options);

	options[PAGE_SIZE - 1] = 0;

	while ((p = strsep(&options, ","))) {
		if (!*p)
			continue;

		token = match_token(p, afs_options_list, args);
		switch (token) {
		case afs_opt_cell:
			cell = afs_cell_lookup(args[0].from,
					       args[0].to - args[0].from,
					       false);
			if (IS_ERR(cell))
				return PTR_ERR(cell);
			afs_put_cell(params->cell);
			params->cell = cell;
			break;

		case afs_opt_rwpath:
			params->rwpath = 1;
			break;

		case afs_opt_vol:
			*devname = args[0].from;
			break;

		case afs_opt_autocell:
			params->autocell = 1;
			break;

		default:
			printk(KERN_ERR "kAFS:"
			       " Unknown or invalid mount option: '%s'\n", p);
			return -EINVAL;
		}
	}

	_leave(" = 0");
	return 0;
}
Example #2
0
/*
 * parse a device name to get cell name, volume name, volume type and R/W
 * selector
 * - this can be one of the following:
 *	"%[cell:]volume[.]"		R/W volume
 *	"#[cell:]volume[.]"		R/O or R/W volume (rwpath=0),
 *					 or R/W (rwpath=1) volume
 *	"%[cell:]volume.readonly"	R/O volume
 *	"#[cell:]volume.readonly"	R/O volume
 *	"%[cell:]volume.backup"		Backup volume
 *	"#[cell:]volume.backup"		Backup volume
 */
static int afs_parse_device_name(struct afs_mount_params *params,
				 const char *name)
{
	struct afs_cell *cell;
	const char *cellname, *suffix;
	int cellnamesz;

	_enter(",%s", name);

	if (!name) {
		printk(KERN_ERR "kAFS: no volume name specified\n");
		return -EINVAL;
	}

	if ((name[0] != '%' && name[0] != '#') || !name[1]) {
		printk(KERN_ERR "kAFS: unparsable volume name\n");
		return -EINVAL;
	}

	/* determine the type of volume we're looking for */
	params->type = AFSVL_ROVOL;
	params->force = false;
	if (params->rwpath || name[0] == '%') {
		params->type = AFSVL_RWVOL;
		params->force = true;
	}
	name++;

	/* split the cell name out if there is one */
	params->volname = strchr(name, ':');
	if (params->volname) {
		cellname = name;
		cellnamesz = params->volname - name;
		params->volname++;
	} else {
		params->volname = name;
		cellname = NULL;
		cellnamesz = 0;
	}

	/* the volume type is further affected by a possible suffix */
	suffix = strrchr(params->volname, '.');
	if (suffix) {
		if (strcmp(suffix, ".readonly") == 0) {
			params->type = AFSVL_ROVOL;
			params->force = true;
		} else if (strcmp(suffix, ".backup") == 0) {
			params->type = AFSVL_BACKVOL;
			params->force = true;
		} else if (suffix[1] == 0) {
		} else {
			suffix = NULL;
		}
	}

	params->volnamesz = suffix ?
		suffix - params->volname : strlen(params->volname);

	_debug("cell %*.*s [%p]",
	       cellnamesz, cellnamesz, cellname ?: "", params->cell);

	/* lookup the cell record */
	if (cellname || !params->cell) {
		cell = afs_cell_lookup(cellname, cellnamesz, true);
		if (IS_ERR(cell)) {
			printk(KERN_ERR "kAFS: unable to lookup cell '%*.*s'\n",
			       cellnamesz, cellnamesz, cellname ?: "");
			return PTR_ERR(cell);
		}
		afs_put_cell(params->cell);
		params->cell = cell;
	}
/*
 * lookup a volume by name
 * - this can be one of the following:
 *	"%[cell:]volume[.]"		R/W volume
 *	"#[cell:]volume[.]"		R/O or R/W volume (rwparent=0),
 *					 or R/W (rwparent=1) volume
 *	"%[cell:]volume.readonly"	R/O volume
 *	"#[cell:]volume.readonly"	R/O volume
 *	"%[cell:]volume.backup"		Backup volume
 *	"#[cell:]volume.backup"		Backup volume
 *
 * The cell name is optional, and defaults to the current cell.
 *
 * See "The Rules of Mount Point Traversal" in Chapter 5 of the AFS SysAdmin
 * Guide
 * - Rule 1: Explicit type suffix forces access of that type or nothing
 *           (no suffix, then use Rule 2 & 3)
 * - Rule 2: If parent volume is R/O, then mount R/O volume by preference, R/W
 *           if not available
 * - Rule 3: If parent volume is R/W, then only mount R/W volume unless
 *           explicitly told otherwise
 */
int afs_volume_lookup(const char *name, struct afs_cell *cell, int rwpath,
		      struct afs_volume **_volume)
{
	struct afs_vlocation *vlocation = NULL;
	struct afs_volume *volume = NULL;
	afs_voltype_t type;
	const char *cellname, *volname, *suffix;
	char srvtmask;
	int force, ret, loop, cellnamesz, volnamesz;

	_enter("%s,,%d,", name, rwpath);

	if (!name || (name[0] != '%' && name[0] != '#') || !name[1]) {
		printk("kAFS: unparsable volume name\n");
		return -EINVAL;
	}

	/* determine the type of volume we're looking for */
	force = 0;
	type = AFSVL_ROVOL;

	if (rwpath || name[0] == '%') {
		type = AFSVL_RWVOL;
		force = 1;
	}

	suffix = strrchr(name, '.');
	if (suffix) {
		if (strcmp(suffix, ".readonly") == 0) {
			type = AFSVL_ROVOL;
			force = 1;
		}
		else if (strcmp(suffix, ".backup") == 0) {
			type = AFSVL_BACKVOL;
			force = 1;
		}
		else if (suffix[1] == 0) {
		}
		else {
			suffix = NULL;
		}
	}

	/* split the cell and volume names */
	name++;
	volname = strchr(name, ':');
	if (volname) {
		cellname = name;
		cellnamesz = volname - name;
		volname++;
	}
	else {
		volname = name;
		cellname = NULL;
		cellnamesz = 0;
	}

	volnamesz = suffix ? suffix - volname : strlen(volname);

	_debug("CELL:%*.*s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
	       cellnamesz, cellnamesz, cellname ?: "", cell,
	       volnamesz, volnamesz, volname, suffix ?: "-",
	       type,
	       force ? " FORCE" : "");

	/* lookup the cell record */
	if (cellname || !cell) {
		ret = afs_cell_lookup(cellname, cellnamesz, &cell);
		if (ret<0) {
			printk("kAFS: unable to lookup cell '%s'\n",
			       cellname ?: "");
			goto error;
		}