aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/devpts/inode.c113
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
328static 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 */
369static 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
399static int devpts_get_sb(struct file_system_type *fs_type, 351static 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
426out_dput: 391out_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); 394out_undo_sget:
395 up_write(&s->s_umount);
396 deactivate_super(s);
430 return error; 397 return error;
431} 398}
432 399