aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/super.c')
-rw-r--r--fs/afs/super.c142
1 files changed, 120 insertions, 22 deletions
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 77e68759788f..497350a5463b 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -24,12 +24,6 @@
24 24
25#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ 25#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
26 26
27struct afs_mount_params {
28 int rwpath;
29 struct afs_cell *default_cell;
30 struct afs_volume *volume;
31};
32
33static void afs_i_init_once(void *foo, struct kmem_cache *cachep, 27static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
34 unsigned long flags); 28 unsigned long flags);
35 29
@@ -150,8 +144,8 @@ static int want_no_value(char *const *_value, const char *option)
150 * - this function has been shamelessly adapted from the ext3 fs which 144 * - this function has been shamelessly adapted from the ext3 fs which
151 * shamelessly adapted it from the msdos fs 145 * shamelessly adapted it from the msdos fs
152 */ 146 */
153static int afs_super_parse_options(struct afs_mount_params *params, 147static int afs_parse_options(struct afs_mount_params *params,
154 char *options, const char **devname) 148 char *options, const char **devname)
155{ 149{
156 struct afs_cell *cell; 150 struct afs_cell *cell;
157 char *key, *value; 151 char *key, *value;
@@ -183,8 +177,8 @@ static int afs_super_parse_options(struct afs_mount_params *params,
183 cell = afs_cell_lookup(value, strlen(value)); 177 cell = afs_cell_lookup(value, strlen(value));
184 if (IS_ERR(cell)) 178 if (IS_ERR(cell))
185 return PTR_ERR(cell); 179 return PTR_ERR(cell);
186 afs_put_cell(params->default_cell); 180 afs_put_cell(params->cell);
187 params->default_cell = cell; 181 params->cell = cell;
188 } else { 182 } else {
189 printk("kAFS: Unknown mount option: '%s'\n", key); 183 printk("kAFS: Unknown mount option: '%s'\n", key);
190 ret = -EINVAL; 184 ret = -EINVAL;
@@ -199,6 +193,99 @@ error:
199} 193}
200 194
201/* 195/*
196 * parse a device name to get cell name, volume name, volume type and R/W
197 * selector
198 * - this can be one of the following:
199 * "%[cell:]volume[.]" R/W volume
200 * "#[cell:]volume[.]" R/O or R/W volume (rwpath=0),
201 * or R/W (rwpath=1) volume
202 * "%[cell:]volume.readonly" R/O volume
203 * "#[cell:]volume.readonly" R/O volume
204 * "%[cell:]volume.backup" Backup volume
205 * "#[cell:]volume.backup" Backup volume
206 */
207static int afs_parse_device_name(struct afs_mount_params *params,
208 const char *name)
209{
210 struct afs_cell *cell;
211 const char *cellname, *suffix;
212 int cellnamesz;
213
214 _enter(",%s", name);
215
216 if (!name) {
217 printk(KERN_ERR "kAFS: no volume name specified\n");
218 return -EINVAL;
219 }
220
221 if ((name[0] != '%' && name[0] != '#') || !name[1]) {
222 printk(KERN_ERR "kAFS: unparsable volume name\n");
223 return -EINVAL;
224 }
225
226 /* determine the type of volume we're looking for */
227 params->type = AFSVL_ROVOL;
228 params->force = false;
229 if (params->rwpath || name[0] == '%') {
230 params->type = AFSVL_RWVOL;
231 params->force = true;
232 }
233 name++;
234
235 /* split the cell name out if there is one */
236 params->volname = strchr(name, ':');
237 if (params->volname) {
238 cellname = name;
239 cellnamesz = params->volname - name;
240 params->volname++;
241 } else {
242 params->volname = name;
243 cellname = NULL;
244 cellnamesz = 0;
245 }
246
247 /* the volume type is further affected by a possible suffix */
248 suffix = strrchr(params->volname, '.');
249 if (suffix) {
250 if (strcmp(suffix, ".readonly") == 0) {
251 params->type = AFSVL_ROVOL;
252 params->force = true;
253 } else if (strcmp(suffix, ".backup") == 0) {
254 params->type = AFSVL_BACKVOL;
255 params->force = true;
256 } else if (suffix[1] == 0) {
257 } else {
258 suffix = NULL;
259 }
260 }
261
262 params->volnamesz = suffix ?
263 suffix - params->volname : strlen(params->volname);
264
265 _debug("cell %*.*s [%p]",
266 cellnamesz, cellnamesz, cellname ?: "", params->cell);
267
268 /* lookup the cell record */
269 if (cellname || !params->cell) {
270 cell = afs_cell_lookup(cellname, cellnamesz);
271 if (IS_ERR(cell)) {
272 printk(KERN_ERR "kAFS: unable to lookup cell '%s'\n",
273 cellname ?: "");
274 return PTR_ERR(cell);
275 }
276 afs_put_cell(params->cell);
277 params->cell = cell;
278 }
279
280 _debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
281 params->cell->name, params->cell,
282 params->volnamesz, params->volnamesz, params->volname,
283 suffix ?: "-", params->type, params->force ? " FORCE" : "");
284
285 return 0;
286}
287
288/*
202 * check a superblock to see if it's the one we're looking for 289 * check a superblock to see if it's the one we're looking for
203 */ 290 */
204static int afs_test_super(struct super_block *sb, void *data) 291static int afs_test_super(struct super_block *sb, void *data)
@@ -244,7 +331,7 @@ static int afs_fill_super(struct super_block *sb, void *data)
244 fid.vid = as->volume->vid; 331 fid.vid = as->volume->vid;
245 fid.vnode = 1; 332 fid.vnode = 1;
246 fid.unique = 1; 333 fid.unique = 1;
247 inode = afs_iget(sb, &fid); 334 inode = afs_iget(sb, params->key, &fid);
248 if (IS_ERR(inode)) 335 if (IS_ERR(inode))
249 goto error_inode; 336 goto error_inode;
250 337
@@ -285,31 +372,40 @@ static int afs_get_sb(struct file_system_type *fs_type,
285 struct afs_mount_params params; 372 struct afs_mount_params params;
286 struct super_block *sb; 373 struct super_block *sb;
287 struct afs_volume *vol; 374 struct afs_volume *vol;
375 struct key *key;
288 int ret; 376 int ret;
289 377
290 _enter(",,%s,%p", dev_name, options); 378 _enter(",,%s,%p", dev_name, options);
291 379
292 memset(&params, 0, sizeof(params)); 380 memset(&params, 0, sizeof(params));
293 381
294 /* parse the options */ 382 /* parse the options and device name */
295 if (options) { 383 if (options) {
296 ret = afs_super_parse_options(&params, options, &dev_name); 384 ret = afs_parse_options(&params, options, &dev_name);
297 if (ret < 0) 385 if (ret < 0)
298 goto error; 386 goto error;
299 if (!dev_name) {
300 printk("kAFS: no volume name specified\n");
301 ret = -EINVAL;
302 goto error;
303 }
304 } 387 }
305 388
389
390 ret = afs_parse_device_name(&params, dev_name);
391 if (ret < 0)
392 goto error;
393
394 /* try and do the mount securely */
395 key = afs_request_key(params.cell);
396 if (IS_ERR(key)) {
397 _leave(" = %ld [key]", PTR_ERR(key));
398 ret = PTR_ERR(key);
399 goto error;
400 }
401 params.key = key;
402
306 /* parse the device name */ 403 /* parse the device name */
307 vol = afs_volume_lookup(dev_name, params.default_cell, params.rwpath); 404 vol = afs_volume_lookup(&params);
308 if (IS_ERR(vol)) { 405 if (IS_ERR(vol)) {
309 ret = PTR_ERR(vol); 406 ret = PTR_ERR(vol);
310 goto error; 407 goto error;
311 } 408 }
312
313 params.volume = vol; 409 params.volume = vol;
314 410
315 /* allocate a deviceless superblock */ 411 /* allocate a deviceless superblock */
@@ -337,13 +433,14 @@ static int afs_get_sb(struct file_system_type *fs_type,
337 433
338 simple_set_mnt(mnt, sb); 434 simple_set_mnt(mnt, sb);
339 afs_put_volume(params.volume); 435 afs_put_volume(params.volume);
340 afs_put_cell(params.default_cell); 436 afs_put_cell(params.cell);
341 _leave(" = 0 [%p]", sb); 437 _leave(" = 0 [%p]", sb);
342 return 0; 438 return 0;
343 439
344error: 440error:
345 afs_put_volume(params.volume); 441 afs_put_volume(params.volume);
346 afs_put_cell(params.default_cell); 442 afs_put_cell(params.cell);
443 key_put(params.key);
347 _leave(" = %d", ret); 444 _leave(" = %d", ret);
348 return ret; 445 return ret;
349} 446}
@@ -375,6 +472,7 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
375 memset(vnode, 0, sizeof(*vnode)); 472 memset(vnode, 0, sizeof(*vnode));
376 inode_init_once(&vnode->vfs_inode); 473 inode_init_once(&vnode->vfs_inode);
377 init_waitqueue_head(&vnode->update_waitq); 474 init_waitqueue_head(&vnode->update_waitq);
475 mutex_init(&vnode->permits_lock);
378 spin_lock_init(&vnode->lock); 476 spin_lock_init(&vnode->lock);
379 INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); 477 INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
380 mutex_init(&vnode->cb_broken_lock); 478 mutex_init(&vnode->cb_broken_lock);