aboutsummaryrefslogtreecommitdiffstats
path: root/fs/devpts
diff options
context:
space:
mode:
Diffstat (limited to 'fs/devpts')
-rw-r--r--fs/devpts/inode.c55
1 files changed, 54 insertions, 1 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 8ee9dc2f9e48..2d0eb2cf99e6 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -305,10 +305,63 @@ fail:
305 return -ENOMEM; 305 return -ENOMEM;
306} 306}
307 307
308static int compare_init_pts_sb(struct super_block *s, void *p)
309{
310 if (devpts_mnt)
311 return devpts_mnt->mnt_sb == s;
312
313 return 0;
314}
315
316/*
317 * get_init_pts_sb()
318 *
319 * This interface is needed to support multiple namespace semantics in
320 * devpts while preserving backward compatibility of the current 'single-
321 * namespace' semantics. i.e all mounts of devpts without the 'newinstance'
322 * mount option should bind to the initial kernel mount, like
323 * get_sb_single().
324 *
325 * Mounts with 'newinstance' option create a new private namespace.
326 *
327 * But for single-mount semantics, devpts cannot use get_sb_single(),
328 * because get_sb_single()/sget() find and use the super-block from
329 * the most recent mount of devpts. But that recent mount may be a
330 * 'newinstance' mount and get_sb_single() would pick the newinstance
331 * super-block instead of the initial super-block.
332 *
333 * This interface is identical to get_sb_single() except that it
334 * consistently selects the 'single-namespace' superblock even in the
335 * presence of the private namespace (i.e 'newinstance') super-blocks.
336 */
337static int get_init_pts_sb(struct file_system_type *fs_type, int flags,
338 void *data, struct vfsmount *mnt)
339{
340 struct super_block *s;
341 int error;
342
343 s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL);
344 if (IS_ERR(s))
345 return PTR_ERR(s);
346
347 if (!s->s_root) {
348 s->s_flags = flags;
349 error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
350 if (error) {
351 up_write(&s->s_umount);
352 deactivate_super(s);
353 return error;
354 }
355 s->s_flags |= MS_ACTIVE;
356 }
357 do_remount_sb(s, flags, data, 0);
358 return simple_set_mnt(mnt, s);
359}
360
308static int devpts_get_sb(struct file_system_type *fs_type, 361static int devpts_get_sb(struct file_system_type *fs_type,
309 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 362 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
310{ 363{
311 return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt); 364 return get_init_pts_sb(fs_type, flags, data, mnt);
312} 365}
313 366
314static void devpts_kill_sb(struct super_block *sb) 367static void devpts_kill_sb(struct super_block *sb)