aboutsummaryrefslogtreecommitdiffstats
path: root/fs/devpts/inode.c
diff options
context:
space:
mode:
authorSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>2009-03-07 13:14:41 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2009-03-27 14:44:04 -0400
commit482984f06df54d886995a4383d2f5bb85e3de945 (patch)
tree30d4b05f6dbaeec18b741b182b25c776d8ae65c3 /fs/devpts/inode.c
parentfdbf5348661ac9d519164d1489f30cc0384fda58 (diff)
Parse mount options just once and copy them to super block
Since all the mount option parsing is done in devpts, we could do it just once and pass it around in devpts functions and eventually store it in the super block. Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/devpts/inode.c')
-rw-r--r--fs/devpts/inode.c100
1 files changed, 22 insertions, 78 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index fb4da9d89130..70013dd8ec70 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -322,60 +322,21 @@ static int compare_init_pts_sb(struct super_block *s, void *p)
322} 322}
323 323
324/* 324/*
325 * Safely parse the mount options in @data and update @opts.
326 *
327 * devpts ends up parsing options two times during mount, due to the
328 * two modes of operation it supports. The first parse occurs in
329 * devpts_get_sb() when determining the mode (single-instance or
330 * multi-instance mode). The second parse happens in devpts_remount()
331 * or new_pts_mount() depending on the mode.
332 *
333 * Parsing of options modifies the @data making subsequent parsing
334 * incorrect. So make a local copy of @data and parse it.
335 *
336 * Return: 0 On success, -errno on error
337 */
338static int safe_parse_mount_options(void *data, struct pts_mount_opts *opts)
339{
340 int rc;
341 void *datacp;
342
343 if (!data)
344 return 0;
345
346 /* Use kstrdup() ? */
347 datacp = kmalloc(PAGE_SIZE, GFP_KERNEL);
348 if (!datacp)
349 return -ENOMEM;
350
351 memcpy(datacp, data, PAGE_SIZE);
352 rc = parse_mount_options((char *)datacp, PARSE_MOUNT, opts);
353 kfree(datacp);
354
355 return rc;
356}
357
358/*
359 * Mount a new (private) instance of devpts. PTYs created in this 325 * Mount a new (private) instance of devpts. PTYs created in this
360 * instance are independent of the PTYs in other devpts instances. 326 * instance are independent of the PTYs in other devpts instances.
361 */ 327 */
362static int new_pts_mount(struct file_system_type *fs_type, int flags, 328static int new_pts_mount(struct file_system_type *fs_type, int flags,
363 void *data, struct vfsmount *mnt) 329 void *data, struct pts_mount_opts *opts, struct vfsmount *mnt)
364{ 330{
365 int err; 331 int err;
366 struct pts_fs_info *fsi; 332 struct pts_fs_info *fsi;
367 struct pts_mount_opts *opts;
368 333
369 err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt); 334 err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt);
370 if (err) 335 if (err)
371 return err; 336 return err;
372 337
373 fsi = DEVPTS_SB(mnt->mnt_sb); 338 fsi = DEVPTS_SB(mnt->mnt_sb);
374 opts = &fsi->mount_opts; 339 memcpy(&fsi->mount_opts, opts, sizeof(opts));
375
376 err = parse_mount_options(data, PARSE_MOUNT, opts);
377 if (err)
378 goto fail;
379 340
380 err = mknod_ptmx(mnt->mnt_sb); 341 err = mknod_ptmx(mnt->mnt_sb);
381 if (err) 342 if (err)
@@ -391,28 +352,6 @@ fail:
391} 352}
392 353
393/* 354/*
394 * Check if 'newinstance' mount option was specified in @data.
395 *
396 * Return: -errno on error (eg: invalid mount options specified)
397 * : 1 if 'newinstance' mount option was specified
398 * : 0 if 'newinstance' mount option was NOT specified
399 */
400static int is_new_instance_mount(void *data)
401{
402 int rc;
403 struct pts_mount_opts opts;
404
405 if (!data)
406 return 0;
407
408 rc = safe_parse_mount_options(data, &opts);
409 if (!rc)
410 rc = opts.newinstance;
411
412 return rc;
413}
414
415/*
416 * get_init_pts_sb() 355 * get_init_pts_sb()
417 * 356 *
418 * This interface is needed to support multiple namespace semantics in 357 * This interface is needed to support multiple namespace semantics in
@@ -434,10 +373,9 @@ static int is_new_instance_mount(void *data)
434 * presence of the private namespace (i.e 'newinstance') super-blocks. 373 * presence of the private namespace (i.e 'newinstance') super-blocks.
435 */ 374 */
436static int get_init_pts_sb(struct file_system_type *fs_type, int flags, 375static int get_init_pts_sb(struct file_system_type *fs_type, int flags,
437 void *data, struct vfsmount *mnt) 376 void *data, struct pts_mount_opts *opts, struct vfsmount *mnt)
438{ 377{
439 struct super_block *s; 378 struct super_block *s;
440 struct pts_mount_opts *opts;
441 struct pts_fs_info *fsi; 379 struct pts_fs_info *fsi;
442 int error; 380 int error;
443 381
@@ -455,11 +393,12 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags,
455 } 393 }
456 s->s_flags |= MS_ACTIVE; 394 s->s_flags |= MS_ACTIVE;
457 } 395 }
458 fsi = DEVPTS_SB(s);
459 opts = &fsi->mount_opts;
460 parse_mount_options(data, PARSE_REMOUNT, opts);
461 396
462 simple_set_mnt(mnt, s); 397 simple_set_mnt(mnt, s);
398
399 fsi = DEVPTS_SB(mnt->mnt_sb);
400 memcpy(&fsi->mount_opts, opts, sizeof(opts));
401
463 return 0; 402 return 0;
464} 403}
465 404
@@ -469,11 +408,11 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags,
469 * kernel still allows multiple-instances. 408 * kernel still allows multiple-instances.
470 */ 409 */
471static int init_pts_mount(struct file_system_type *fs_type, int flags, 410static int init_pts_mount(struct file_system_type *fs_type, int flags,
472 void *data, struct vfsmount *mnt) 411 void *data, struct pts_mount_opts *opts, struct vfsmount *mnt)
473{ 412{
474 int err; 413 int err;
475 414
476 err = get_init_pts_sb(fs_type, flags, data, mnt); 415 err = get_init_pts_sb(fs_type, flags, data, opts, mnt);
477 if (err) 416 if (err)
478 return err; 417 return err;
479 418
@@ -490,17 +429,22 @@ static int init_pts_mount(struct file_system_type *fs_type, int flags,
490static int devpts_get_sb(struct file_system_type *fs_type, 429static int devpts_get_sb(struct file_system_type *fs_type,
491 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 430 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
492{ 431{
493 int new; 432 int error;
494 433 struct pts_mount_opts opts;
495 new = is_new_instance_mount(data);
496 if (new < 0)
497 return new;
498 434
499 if (new) 435 memset(&opts, 0, sizeof(opts));
500 return new_pts_mount(fs_type, flags, data, mnt); 436 if (data) {
437 error = parse_mount_options(data, PARSE_MOUNT, &opts);
438 if (error)
439 return error;
440 }
501 441
502 return init_pts_mount(fs_type, flags, data, mnt); 442 if (opts.newinstance)
443 return new_pts_mount(fs_type, flags, data, &opts, mnt);
444 else
445 return init_pts_mount(fs_type, flags, data, &opts, mnt);
503} 446}
447
504#else 448#else
505/* 449/*
506 * This supports only the legacy single-instance semantics (no 450 * This supports only the legacy single-instance semantics (no