diff options
| author | Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> | 2009-01-02 08:42:19 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:36 -0500 |
| commit | d4076ac55bf8755ce6c5706478631c1726cf0179 (patch) | |
| tree | 55959d50da843e2ec8b1bbaeeed299c716e9f516 /fs/devpts | |
| parent | 1f8f1e296583f9f832c2fe7b5a219675b74bf43e (diff) | |
Define get_init_pts_sb()
See comments in the function header for details. The new interface will
be used in a follow-on patch.
Changelog [v2]:
[Dave Hansen] Replace get_sb_ref() in fs/super.c with get_init_pts_sb()
and make the new interface private to devpts
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/devpts')
| -rw-r--r-- | fs/devpts/inode.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 8ee9dc2f9e4..2d0eb2cf99e 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 | ||
| 308 | static 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 | */ | ||
| 337 | static 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 | |||
| 308 | static int devpts_get_sb(struct file_system_type *fs_type, | 361 | static 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 | ||
| 314 | static void devpts_kill_sb(struct super_block *sb) | 367 | static void devpts_kill_sb(struct super_block *sb) |
