/* * 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; }
/* * 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; }