diff options
Diffstat (limited to 'fs/devpts')
-rw-r--r-- | fs/devpts/inode.c | 113 |
1 files changed, 40 insertions, 73 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 9c775fa4130f..63a4a59e4148 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -322,85 +322,38 @@ static int compare_init_pts_sb(struct super_block *s, void *p) | |||
322 | } | 322 | } |
323 | 323 | ||
324 | /* | 324 | /* |
325 | * Mount a new (private) instance of devpts. PTYs created in this | 325 | * devpts_get_sb() |
326 | * instance are independent of the PTYs in other devpts instances. | 326 | * |
327 | */ | 327 | * If the '-o newinstance' mount option was specified, mount a new |
328 | static int new_pts_mount(struct file_system_type *fs_type, int flags, | 328 | * (private) instance of devpts. PTYs created in this instance are |
329 | void *data, struct pts_mount_opts *opts, struct vfsmount *mnt) | 329 | * independent of the PTYs in other devpts instances. |
330 | { | 330 | * |
331 | int err; | 331 | * If the '-o newinstance' option was not specified, mount/remount the |
332 | struct pts_fs_info *fsi; | 332 | * initial kernel mount of devpts. This type of mount gives the |
333 | 333 | * legacy, single-instance semantics. | |
334 | err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt); | ||
335 | if (err) | ||
336 | return err; | ||
337 | |||
338 | fsi = DEVPTS_SB(mnt->mnt_sb); | ||
339 | memcpy(&fsi->mount_opts, opts, sizeof(opts)); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | /* | ||
345 | * init_pts_mount() | ||
346 | * | 334 | * |
347 | * Mount or remount the initial kernel mount of devpts. This type of | 335 | * The 'newinstance' option is needed to support multiple namespace |
348 | * mount maintains the legacy, single-instance semantics, while the | 336 | * semantics in devpts while preserving backward compatibility of the |
349 | * kernel still allows multiple-instances. | 337 | * current 'single-namespace' semantics. i.e all mounts of devpts |
338 | * without the 'newinstance' mount option should bind to the initial | ||
339 | * kernel mount, like get_sb_single(). | ||
350 | * | 340 | * |
351 | * This interface is needed to support multiple namespace semantics in | 341 | * Mounts with 'newinstance' option create a new, private namespace. |
352 | * devpts while preserving backward compatibility of the current 'single- | ||
353 | * namespace' semantics. i.e all mounts of devpts without the 'newinstance' | ||
354 | * mount option should bind to the initial kernel mount, like | ||
355 | * get_sb_single(). | ||
356 | * | 342 | * |
357 | * Mounts with 'newinstance' option create a new private namespace. | 343 | * NOTE: |
358 | * | 344 | * |
359 | * But for single-mount semantics, devpts cannot use get_sb_single(), | 345 | * For single-mount semantics, devpts cannot use get_sb_single(), |
360 | * because get_sb_single()/sget() find and use the super-block from | 346 | * because get_sb_single()/sget() find and use the super-block from |
361 | * the most recent mount of devpts. But that recent mount may be a | 347 | * the most recent mount of devpts. But that recent mount may be a |
362 | * 'newinstance' mount and get_sb_single() would pick the newinstance | 348 | * 'newinstance' mount and get_sb_single() would pick the newinstance |
363 | * super-block instead of the initial super-block. | 349 | * super-block instead of the initial super-block. |
364 | * | ||
365 | * This interface is identical to get_sb_single() except that it | ||
366 | * consistently selects the 'single-namespace' superblock even in the | ||
367 | * presence of the private namespace (i.e 'newinstance') super-blocks. | ||
368 | */ | 350 | */ |
369 | static int init_pts_mount(struct file_system_type *fs_type, int flags, | ||
370 | void *data, struct pts_mount_opts *opts, struct vfsmount *mnt) | ||
371 | { | ||
372 | struct super_block *s; | ||
373 | struct pts_fs_info *fsi; | ||
374 | int error; | ||
375 | |||
376 | s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL); | ||
377 | if (IS_ERR(s)) | ||
378 | return PTR_ERR(s); | ||
379 | |||
380 | if (!s->s_root) { | ||
381 | s->s_flags = flags; | ||
382 | error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0); | ||
383 | if (error) { | ||
384 | up_write(&s->s_umount); | ||
385 | deactivate_super(s); | ||
386 | return error; | ||
387 | } | ||
388 | s->s_flags |= MS_ACTIVE; | ||
389 | } | ||
390 | |||
391 | simple_set_mnt(mnt, s); | ||
392 | |||
393 | fsi = DEVPTS_SB(mnt->mnt_sb); | ||
394 | memcpy(&fsi->mount_opts, opts, sizeof(opts)); | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static int devpts_get_sb(struct file_system_type *fs_type, | 351 | static int devpts_get_sb(struct file_system_type *fs_type, |
400 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 352 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
401 | { | 353 | { |
402 | int error; | 354 | int error; |
403 | struct pts_mount_opts opts; | 355 | struct pts_mount_opts opts; |
356 | struct super_block *s; | ||
404 | 357 | ||
405 | memset(&opts, 0, sizeof(opts)); | 358 | memset(&opts, 0, sizeof(opts)); |
406 | if (data) { | 359 | if (data) { |
@@ -410,23 +363,37 @@ static int devpts_get_sb(struct file_system_type *fs_type, | |||
410 | } | 363 | } |
411 | 364 | ||
412 | if (opts.newinstance) | 365 | if (opts.newinstance) |
413 | error = new_pts_mount(fs_type, flags, data, &opts, mnt); | 366 | s = sget(fs_type, NULL, set_anon_super, NULL); |
414 | else | 367 | else |
415 | error = init_pts_mount(fs_type, flags, data, &opts, mnt); | 368 | s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL); |
416 | 369 | ||
417 | if (error) | 370 | if (IS_ERR(s)) |
418 | return error; | 371 | return PTR_ERR(s); |
372 | |||
373 | if (!s->s_root) { | ||
374 | s->s_flags = flags; | ||
375 | error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0); | ||
376 | if (error) | ||
377 | goto out_undo_sget; | ||
378 | s->s_flags |= MS_ACTIVE; | ||
379 | } | ||
380 | |||
381 | simple_set_mnt(mnt, s); | ||
382 | |||
383 | memcpy(&(DEVPTS_SB(s))->mount_opts, &opts, sizeof(opts)); | ||
419 | 384 | ||
420 | error = mknod_ptmx(mnt->mnt_sb); | 385 | error = mknod_ptmx(s); |
421 | if (error) | 386 | if (error) |
422 | goto out_dput; | 387 | goto out_dput; |
423 | 388 | ||
424 | return 0; | 389 | return 0; |
425 | 390 | ||
426 | out_dput: | 391 | out_dput: |
427 | dput(mnt->mnt_sb->s_root); | 392 | dput(s->s_root); |
428 | up_write(&mnt->mnt_sb->s_umount); | 393 | |
429 | deactivate_super(mnt->mnt_sb); | 394 | out_undo_sget: |
395 | up_write(&s->s_umount); | ||
396 | deactivate_super(s); | ||
430 | return error; | 397 | return error; |
431 | } | 398 | } |
432 | 399 | ||