Lines Matching +full:data +full:- +full:path
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* -*- linux-c -*- --------------------------------------------------------- *
6 * Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved
8 * ------------------------------------------------------------------------- */
30 * ptmx is a new node in /dev/pts and will be unused in legacy (single-
32 * ptmx to 0. Use 'chmod' or remount with '-o ptmxmode' to set meaningful
53 .data = &pty_limit,
61 .data = &pty_reserve,
69 .data = &pty_count,
109 return sb->s_fs_info; in DEVPTS_SB()
112 static int devpts_ptmx_path(struct path *path) in devpts_ptmx_path() argument
118 err = path_pts(path); in devpts_ptmx_path()
122 /* Is the path the root of a devpts filesystem? */ in devpts_ptmx_path()
123 sb = path->mnt->mnt_sb; in devpts_ptmx_path()
124 if ((sb->s_magic != DEVPTS_SUPER_MAGIC) || in devpts_ptmx_path()
125 (path->mnt->mnt_root != sb->s_root)) in devpts_ptmx_path()
126 return -ENODEV; in devpts_ptmx_path()
134 * - The ptmx device node is located in the same directory as the devpts
138 * - The ptmx device node is located outside the devpts filesystem mount
140 * is a symlink, separate device node, or bind-mount.
141 * A supported scenario is bind-mounting /dev/pts/ptmx to /dev/ptmx and
144 * devpts mount and the ptmx bind-mount, after resolving the /dev/ptmx
145 * bind-mount.
147 * This is e.g. the case when bind-mounting /dev/pts/ptmx to /ptmx.
151 struct path path; in devpts_mntget() local
154 path = filp->f_path; in devpts_mntget()
155 path_get(&path); in devpts_mntget()
160 while (path.mnt->mnt_root == path.dentry) in devpts_mntget()
161 if (follow_up(&path) == 0) in devpts_mntget()
165 if ((path.mnt->mnt_sb->s_magic != DEVPTS_SUPER_MAGIC) || in devpts_mntget()
166 (DEVPTS_SB(path.mnt->mnt_sb) != fsi)) in devpts_mntget()
167 err = devpts_ptmx_path(&path); in devpts_mntget()
168 dput(path.dentry); in devpts_mntget()
170 if (DEVPTS_SB(path.mnt->mnt_sb) == fsi) in devpts_mntget()
171 return path.mnt; in devpts_mntget()
173 err = -ENODEV; in devpts_mntget()
176 mntput(path.mnt); in devpts_mntget()
183 struct path path; in devpts_acquire() local
186 path = filp->f_path; in devpts_acquire()
187 path_get(&path); in devpts_acquire()
190 if (path.mnt->mnt_sb->s_magic != DEVPTS_SUPER_MAGIC) { in devpts_acquire()
193 err = devpts_ptmx_path(&path); in devpts_acquire()
203 sb = path.mnt->mnt_sb; in devpts_acquire()
204 atomic_inc(&sb->s_active); in devpts_acquire()
208 path_put(&path); in devpts_acquire()
214 deactivate_super(fsi->sb); in devpts_release()
222 * Set @opts to mount options specified in @data. If an option is not
223 * specified in @data, set it to its default value.
225 * Note: @data may be NULL (in which case all options are set to default).
227 static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) in parse_mount_options() argument
233 opts->setuid = 0; in parse_mount_options()
234 opts->setgid = 0; in parse_mount_options()
235 opts->uid = GLOBAL_ROOT_UID; in parse_mount_options()
236 opts->gid = GLOBAL_ROOT_GID; in parse_mount_options()
237 opts->mode = DEVPTS_DEFAULT_MODE; in parse_mount_options()
238 opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; in parse_mount_options()
239 opts->max = NR_UNIX98_PTY_MAX; in parse_mount_options()
245 opts->reserve = in parse_mount_options()
246 (current->nsproxy->mnt_ns == init_task.nsproxy->mnt_ns); in parse_mount_options()
248 while ((p = strsep(&data, ",")) != NULL) { in parse_mount_options()
260 return -EINVAL; in parse_mount_options()
263 return -EINVAL; in parse_mount_options()
264 opts->uid = uid; in parse_mount_options()
265 opts->setuid = 1; in parse_mount_options()
269 return -EINVAL; in parse_mount_options()
272 return -EINVAL; in parse_mount_options()
273 opts->gid = gid; in parse_mount_options()
274 opts->setgid = 1; in parse_mount_options()
278 return -EINVAL; in parse_mount_options()
279 opts->mode = option & S_IALLUGO; in parse_mount_options()
283 return -EINVAL; in parse_mount_options()
284 opts->ptmxmode = option & S_IALLUGO; in parse_mount_options()
291 return -EINVAL; in parse_mount_options()
292 opts->max = option; in parse_mount_options()
296 return -EINVAL; in parse_mount_options()
306 int rc = -ENOMEM; in mknod_ptmx()
309 struct dentry *root = sb->s_root; in mknod_ptmx()
311 struct pts_mount_opts *opts = &fsi->mount_opts; in mknod_ptmx()
318 if (fsi->ptmx_dentry) { in mknod_ptmx()
339 inode->i_ino = 2; in mknod_ptmx()
342 mode = S_IFCHR|opts->ptmxmode; in mknod_ptmx()
344 inode->i_uid = ptmx_uid; in mknod_ptmx()
345 inode->i_gid = ptmx_gid; in mknod_ptmx()
349 fsi->ptmx_dentry = dentry; in mknod_ptmx()
359 if (fsi->ptmx_dentry) { in update_ptmx_mode()
360 inode = d_inode(fsi->ptmx_dentry); in update_ptmx_mode()
361 inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode; in update_ptmx_mode()
365 static int devpts_remount(struct super_block *sb, int *flags, char *data) in devpts_remount() argument
369 struct pts_mount_opts *opts = &fsi->mount_opts; in devpts_remount()
371 err = parse_mount_options(data, PARSE_REMOUNT, opts); in devpts_remount()
386 struct pts_fs_info *fsi = DEVPTS_SB(root->d_sb); in devpts_show_options()
387 struct pts_mount_opts *opts = &fsi->mount_opts; in devpts_show_options()
389 if (opts->setuid) in devpts_show_options()
391 from_kuid_munged(&init_user_ns, opts->uid)); in devpts_show_options()
392 if (opts->setgid) in devpts_show_options()
394 from_kgid_munged(&init_user_ns, opts->gid)); in devpts_show_options()
395 seq_printf(seq, ",mode=%03o", opts->mode); in devpts_show_options()
396 seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); in devpts_show_options()
397 if (opts->max < NR_UNIX98_PTY_MAX) in devpts_show_options()
398 seq_printf(seq, ",max=%d", opts->max); in devpts_show_options()
417 ida_init(&fsi->allocated_ptys); in new_pts_fs_info()
418 fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE; in new_pts_fs_info()
419 fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; in new_pts_fs_info()
420 fsi->sb = sb; in new_pts_fs_info()
426 devpts_fill_super(struct super_block *s, void *data, int silent) in devpts_fill_super() argument
431 s->s_iflags &= ~SB_I_NODEV; in devpts_fill_super()
432 s->s_blocksize = 1024; in devpts_fill_super()
433 s->s_blocksize_bits = 10; in devpts_fill_super()
434 s->s_magic = DEVPTS_SUPER_MAGIC; in devpts_fill_super()
435 s->s_op = &devpts_sops; in devpts_fill_super()
436 s->s_d_op = &simple_dentry_operations; in devpts_fill_super()
437 s->s_time_gran = 1; in devpts_fill_super()
439 error = -ENOMEM; in devpts_fill_super()
440 s->s_fs_info = new_pts_fs_info(s); in devpts_fill_super()
441 if (!s->s_fs_info) in devpts_fill_super()
444 error = parse_mount_options(data, PARSE_MOUNT, &DEVPTS_SB(s)->mount_opts); in devpts_fill_super()
448 error = -ENOMEM; in devpts_fill_super()
452 inode->i_ino = 1; in devpts_fill_super()
454 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; in devpts_fill_super()
455 inode->i_op = &simple_dir_inode_operations; in devpts_fill_super()
456 inode->i_fop = &simple_dir_operations; in devpts_fill_super()
459 s->s_root = d_make_root(inode); in devpts_fill_super()
460 if (!s->s_root) { in devpts_fill_super()
471 dput(s->s_root); in devpts_fill_super()
472 s->s_root = NULL; in devpts_fill_super()
484 int flags, const char *dev_name, void *data) in devpts_mount() argument
486 return mount_nodev(fs_type, flags, data, devpts_fill_super); in devpts_mount()
494 ida_destroy(&fsi->allocated_ptys); in devpts_kill_sb()
513 int index = -ENOSPC; in devpts_new_index()
515 if (atomic_inc_return(&pty_count) >= (pty_limit - in devpts_new_index()
516 (fsi->mount_opts.reserve ? 0 : pty_reserve))) in devpts_new_index()
519 index = ida_alloc_max(&fsi->allocated_ptys, fsi->mount_opts.max - 1, in devpts_new_index()
530 ida_free(&fsi->allocated_ptys, idx); in devpts_kill_index()
535 * devpts_pty_new -- create a new inode in /dev/pts/
546 struct super_block *sb = fsi->sb; in devpts_pty_new()
552 root = sb->s_root; in devpts_pty_new()
553 opts = &fsi->mount_opts; in devpts_pty_new()
557 return ERR_PTR(-ENOMEM); in devpts_pty_new()
559 inode->i_ino = index + 3; in devpts_pty_new()
560 inode->i_uid = opts->setuid ? opts->uid : current_fsuid(); in devpts_pty_new()
561 inode->i_gid = opts->setgid ? opts->gid : current_fsgid(); in devpts_pty_new()
563 init_special_inode(inode, S_IFCHR|opts->mode, MKDEV(UNIX98_PTY_SLAVE_MAJOR, index)); in devpts_pty_new()
569 dentry->d_fsdata = priv; in devpts_pty_new()
574 dentry = ERR_PTR(-ENOMEM); in devpts_pty_new()
581 * devpts_get_priv -- get private data for a slave
588 if (dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC) in devpts_get_priv()
590 return dentry->d_fsdata; in devpts_get_priv()
594 * devpts_pty_kill -- remove inode form /dev/pts/
601 WARN_ON_ONCE(dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC); in devpts_pty_kill()
603 dentry->d_fsdata = NULL; in devpts_pty_kill()
604 drop_nlink(dentry->d_inode); in devpts_pty_kill()
606 fsnotify_unlink(d_inode(dentry->d_parent), dentry); in devpts_pty_kill()