Blame view
fs/devpts/inode.c
13.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* -*- linux-c -*- --------------------------------------------------------- * * * linux/fs/devpts/inode.c * * Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved * * This file is part of the Linux kernel and is made available under * the terms of the GNU General Public License, version 2, or at your * option, any later version, incorporated herein by reference. * * ------------------------------------------------------------------------- */ #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/sched.h> #include <linux/namei.h> |
5a0e3ad6a include cleanup: ... |
18 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
19 20 |
#include <linux/mount.h> #include <linux/tty.h> |
718a91633 devpts: factor ou... |
21 |
#include <linux/mutex.h> |
1fd7317d0 Move magic number... |
22 |
#include <linux/magic.h> |
718a91633 devpts: factor ou... |
23 |
#include <linux/idr.h> |
1da177e4c Linux-2.6.12-rc2 |
24 |
#include <linux/devpts_fs.h> |
7a673c6b8 [PATCH] devpts: u... |
25 |
#include <linux/parser.h> |
3972b7f67 devpts: add fsnot... |
26 |
#include <linux/fsnotify.h> |
b87a267eb mount options: fi... |
27 |
#include <linux/seq_file.h> |
1da177e4c Linux-2.6.12-rc2 |
28 |
|
b87a267eb mount options: fi... |
29 |
#define DEVPTS_DEFAULT_MODE 0600 |
1f8f1e296 Define mknod_ptmx() |
30 31 32 33 34 35 36 |
/* * ptmx is a new node in /dev/pts and will be unused in legacy (single- * instance) mode. To prevent surprises in user space, set permissions of * ptmx to 0. Use 'chmod' or remount with '-o ptmxmode' to set meaningful * permissions. */ #define DEVPTS_DEFAULT_PTMX_MODE 0000 |
527b3e477 Simplify devpts_g... |
37 |
#define PTMX_MINOR 2 |
b87a267eb mount options: fi... |
38 |
|
718a91633 devpts: factor ou... |
39 |
extern int pty_limit; /* Config limit on Unix98 ptys */ |
718a91633 devpts: factor ou... |
40 |
static DEFINE_MUTEX(allocated_ptys_lock); |
1da177e4c Linux-2.6.12-rc2 |
41 |
static struct vfsmount *devpts_mnt; |
1da177e4c Linux-2.6.12-rc2 |
42 |
|
31af0abbd Per-mount 'config... |
43 |
struct pts_mount_opts { |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 48 |
int setuid; int setgid; uid_t uid; gid_t gid; umode_t mode; |
1f8f1e296 Define mknod_ptmx() |
49 |
umode_t ptmxmode; |
2a1b2dc0c Enable multiple i... |
50 |
int newinstance; |
31af0abbd Per-mount 'config... |
51 |
}; |
1da177e4c Linux-2.6.12-rc2 |
52 |
|
7a673c6b8 [PATCH] devpts: u... |
53 |
enum { |
2a1b2dc0c Enable multiple i... |
54 |
Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, |
7a673c6b8 [PATCH] devpts: u... |
55 56 |
Opt_err }; |
a447c0932 vfs: Use const fo... |
57 |
static const match_table_t tokens = { |
7a673c6b8 [PATCH] devpts: u... |
58 59 60 |
{Opt_uid, "uid=%u"}, {Opt_gid, "gid=%u"}, {Opt_mode, "mode=%o"}, |
1f8f1e296 Define mknod_ptmx() |
61 62 |
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES {Opt_ptmxmode, "ptmxmode=%o"}, |
2a1b2dc0c Enable multiple i... |
63 |
{Opt_newinstance, "newinstance"}, |
1f8f1e296 Define mknod_ptmx() |
64 |
#endif |
7a673c6b8 [PATCH] devpts: u... |
65 66 |
{Opt_err, NULL} }; |
e76b7c01e Per-mount allocat... |
67 68 |
struct pts_fs_info { struct ida allocated_ptys; |
31af0abbd Per-mount 'config... |
69 |
struct pts_mount_opts mount_opts; |
1f8f1e296 Define mknod_ptmx() |
70 |
struct dentry *ptmx_dentry; |
e76b7c01e Per-mount allocat... |
71 72 73 74 75 76 |
}; static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb) { return sb->s_fs_info; } |
59e55e6cf Remove devpts_roo... |
77 78 |
static inline struct super_block *pts_sb_from_inode(struct inode *inode) { |
2a1b2dc0c Enable multiple i... |
79 |
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES |
59e55e6cf Remove devpts_roo... |
80 81 |
if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) return inode->i_sb; |
2a1b2dc0c Enable multiple i... |
82 |
#endif |
59e55e6cf Remove devpts_roo... |
83 84 |
return devpts_mnt->mnt_sb; } |
2a1b2dc0c Enable multiple i... |
85 86 |
#define PARSE_MOUNT 0 #define PARSE_REMOUNT 1 |
1f71ebedb devpts: correctly... |
87 88 89 90 91 92 93 94 95 |
/* * parse_mount_options(): * Set @opts to mount options specified in @data. If an option is not * specified in @data, set it to its default value. The exception is * 'newinstance' option which can only be set/cleared on a mount (i.e. * cannot be changed during remount). * * Note: @data may be NULL (in which case all options are set to default). */ |
2a1b2dc0c Enable multiple i... |
96 |
static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) |
1da177e4c Linux-2.6.12-rc2 |
97 |
{ |
7a673c6b8 [PATCH] devpts: u... |
98 |
char *p; |
31af0abbd Per-mount 'config... |
99 100 101 102 103 |
opts->setuid = 0; opts->setgid = 0; opts->uid = 0; opts->gid = 0; opts->mode = DEVPTS_DEFAULT_MODE; |
1f8f1e296 Define mknod_ptmx() |
104 |
opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; |
7a673c6b8 [PATCH] devpts: u... |
105 |
|
2a1b2dc0c Enable multiple i... |
106 107 108 |
/* newinstance makes sense only on initial mount */ if (op == PARSE_MOUNT) opts->newinstance = 0; |
7a673c6b8 [PATCH] devpts: u... |
109 110 111 112 113 114 |
while ((p = strsep(&data, ",")) != NULL) { substring_t args[MAX_OPT_ARGS]; int token; int option; if (!*p) |
1da177e4c Linux-2.6.12-rc2 |
115 |
continue; |
7a673c6b8 [PATCH] devpts: u... |
116 117 118 119 120 121 |
token = match_token(p, tokens, args); switch (token) { case Opt_uid: if (match_int(&args[0], &option)) return -EINVAL; |
31af0abbd Per-mount 'config... |
122 123 |
opts->uid = option; opts->setuid = 1; |
7a673c6b8 [PATCH] devpts: u... |
124 125 126 127 |
break; case Opt_gid: if (match_int(&args[0], &option)) return -EINVAL; |
31af0abbd Per-mount 'config... |
128 129 |
opts->gid = option; opts->setgid = 1; |
7a673c6b8 [PATCH] devpts: u... |
130 131 132 133 |
break; case Opt_mode: if (match_octal(&args[0], &option)) return -EINVAL; |
31af0abbd Per-mount 'config... |
134 |
opts->mode = option & S_IALLUGO; |
7a673c6b8 [PATCH] devpts: u... |
135 |
break; |
1f8f1e296 Define mknod_ptmx() |
136 137 138 139 140 141 |
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES case Opt_ptmxmode: if (match_octal(&args[0], &option)) return -EINVAL; opts->ptmxmode = option & S_IALLUGO; break; |
2a1b2dc0c Enable multiple i... |
142 143 144 145 146 |
case Opt_newinstance: /* newinstance makes sense only on initial mount */ if (op == PARSE_MOUNT) opts->newinstance = 1; break; |
1f8f1e296 Define mknod_ptmx() |
147 |
#endif |
7a673c6b8 [PATCH] devpts: u... |
148 149 150 |
default: printk(KERN_ERR "devpts: called with bogus options "); |
1da177e4c Linux-2.6.12-rc2 |
151 152 153 |
return -EINVAL; } } |
1da177e4c Linux-2.6.12-rc2 |
154 155 156 |
return 0; } |
1f8f1e296 Define mknod_ptmx() |
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES static int mknod_ptmx(struct super_block *sb) { int mode; int rc = -ENOMEM; struct dentry *dentry; struct inode *inode; struct dentry *root = sb->s_root; struct pts_fs_info *fsi = DEVPTS_SB(sb); struct pts_mount_opts *opts = &fsi->mount_opts; mutex_lock(&root->d_inode->i_mutex); /* If we have already created ptmx node, return */ if (fsi->ptmx_dentry) { rc = 0; goto out; } dentry = d_alloc_name(root, "ptmx"); if (!dentry) { printk(KERN_NOTICE "Unable to alloc dentry for ptmx node "); goto out; } /* * Create a new 'ptmx' node in this mount of devpts. */ inode = new_inode(sb); if (!inode) { printk(KERN_ERR "Unable to alloc inode for ptmx node "); dput(dentry); goto out; } inode->i_ino = 2; |
1f8f1e296 Define mknod_ptmx() |
195 196 197 198 199 200 201 202 203 |
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; mode = S_IFCHR|opts->ptmxmode; init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2)); d_add(dentry, inode); fsi->ptmx_dentry = dentry; rc = 0; |
1f8f1e296 Define mknod_ptmx() |
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
out: mutex_unlock(&root->d_inode->i_mutex); return rc; } static void update_ptmx_mode(struct pts_fs_info *fsi) { struct inode *inode; if (fsi->ptmx_dentry) { inode = fsi->ptmx_dentry->d_inode; inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode; } } #else static inline void update_ptmx_mode(struct pts_fs_info *fsi) { return; } #endif |
53af8ee40 Extract option pa... |
223 224 |
static int devpts_remount(struct super_block *sb, int *flags, char *data) { |
1f8f1e296 Define mknod_ptmx() |
225 |
int err; |
53af8ee40 Extract option pa... |
226 227 |
struct pts_fs_info *fsi = DEVPTS_SB(sb); struct pts_mount_opts *opts = &fsi->mount_opts; |
2a1b2dc0c Enable multiple i... |
228 |
err = parse_mount_options(data, PARSE_REMOUNT, opts); |
1f8f1e296 Define mknod_ptmx() |
229 230 231 232 233 234 235 236 237 238 |
/* * parse_mount_options() restores options to default values * before parsing and may have changed ptmxmode. So, update the * mode in the inode too. Bogus options don't fail the remount, * so do this even on error return. */ update_ptmx_mode(fsi); return err; |
53af8ee40 Extract option pa... |
239 |
} |
34c80b1d9 vfs: switch ->sho... |
240 |
static int devpts_show_options(struct seq_file *seq, struct dentry *root) |
b87a267eb mount options: fi... |
241 |
{ |
34c80b1d9 vfs: switch ->sho... |
242 |
struct pts_fs_info *fsi = DEVPTS_SB(root->d_sb); |
31af0abbd Per-mount 'config... |
243 244 245 246 247 248 249 |
struct pts_mount_opts *opts = &fsi->mount_opts; if (opts->setuid) seq_printf(seq, ",uid=%u", opts->uid); if (opts->setgid) seq_printf(seq, ",gid=%u", opts->gid); seq_printf(seq, ",mode=%03o", opts->mode); |
1f8f1e296 Define mknod_ptmx() |
250 251 252 |
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); #endif |
b87a267eb mount options: fi... |
253 254 255 |
return 0; } |
ee9b6d61a [PATCH] Mark stru... |
256 |
static const struct super_operations devpts_sops = { |
1da177e4c Linux-2.6.12-rc2 |
257 258 |
.statfs = simple_statfs, .remount_fs = devpts_remount, |
b87a267eb mount options: fi... |
259 |
.show_options = devpts_show_options, |
1da177e4c Linux-2.6.12-rc2 |
260 |
}; |
e76b7c01e Per-mount allocat... |
261 262 263 264 265 266 267 268 269 |
static void *new_pts_fs_info(void) { struct pts_fs_info *fsi; fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL); if (!fsi) return NULL; ida_init(&fsi->allocated_ptys); |
31af0abbd Per-mount 'config... |
270 |
fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE; |
1f8f1e296 Define mknod_ptmx() |
271 |
fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; |
e76b7c01e Per-mount allocat... |
272 273 274 |
return fsi; } |
1da177e4c Linux-2.6.12-rc2 |
275 276 277 |
static int devpts_fill_super(struct super_block *s, void *data, int silent) { |
1f8f1e296 Define mknod_ptmx() |
278 |
struct inode *inode; |
1da177e4c Linux-2.6.12-rc2 |
279 280 281 282 283 |
s->s_blocksize = 1024; s->s_blocksize_bits = 10; s->s_magic = DEVPTS_SUPER_MAGIC; s->s_op = &devpts_sops; |
1da177e4c Linux-2.6.12-rc2 |
284 |
s->s_time_gran = 1; |
e76b7c01e Per-mount allocat... |
285 286 287 |
s->s_fs_info = new_pts_fs_info(); if (!s->s_fs_info) goto fail; |
1da177e4c Linux-2.6.12-rc2 |
288 289 |
inode = new_inode(s); if (!inode) |
3850aba74 devpts: fix doubl... |
290 |
goto fail; |
1da177e4c Linux-2.6.12-rc2 |
291 292 |
inode->i_ino = 1; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
1da177e4c Linux-2.6.12-rc2 |
293 294 295 |
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; |
bfe868486 filesystems: add ... |
296 |
set_nlink(inode, 2); |
1da177e4c Linux-2.6.12-rc2 |
297 |
|
59e55e6cf Remove devpts_roo... |
298 |
s->s_root = d_alloc_root(inode); |
1da177e4c Linux-2.6.12-rc2 |
299 300 |
if (s->s_root) return 0; |
1f8f1e296 Define mknod_ptmx() |
301 |
|
835aa440f devpts: Coding st... |
302 303 |
printk(KERN_ERR "devpts: get root dentry failed "); |
1da177e4c Linux-2.6.12-rc2 |
304 |
iput(inode); |
e76b7c01e Per-mount allocat... |
305 |
|
1da177e4c Linux-2.6.12-rc2 |
306 307 308 |
fail: return -ENOMEM; } |
8c056e5b1 devpts: fix unuse... |
309 |
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES |
d4076ac55 Define get_init_p... |
310 311 312 313 |
static int compare_init_pts_sb(struct super_block *s, void *p) { if (devpts_mnt) return devpts_mnt->mnt_sb == s; |
2a1b2dc0c Enable multiple i... |
314 315 |
return 0; } |
2a1b2dc0c Enable multiple i... |
316 |
/* |
fc14f2fef convert get_sb_si... |
317 |
* devpts_mount() |
1bd790356 Merge code for si... |
318 319 320 321 322 323 324 325 |
* * If the '-o newinstance' mount option was specified, mount a new * (private) instance of devpts. PTYs created in this instance are * independent of the PTYs in other devpts instances. * * If the '-o newinstance' option was not specified, mount/remount the * initial kernel mount of devpts. This type of mount gives the * legacy, single-instance semantics. |
289f00e22 Remove get_init_p... |
326 |
* |
1bd790356 Merge code for si... |
327 328 329 330 |
* The 'newinstance' option is needed to support multiple namespace * semantics in devpts while preserving backward compatibility of the * current 'single-namespace' semantics. i.e all mounts of devpts * without the 'newinstance' mount option should bind to the initial |
fc14f2fef convert get_sb_si... |
331 |
* kernel mount, like mount_single(). |
d4076ac55 Define get_init_p... |
332 |
* |
1bd790356 Merge code for si... |
333 |
* Mounts with 'newinstance' option create a new, private namespace. |
d4076ac55 Define get_init_p... |
334 |
* |
1bd790356 Merge code for si... |
335 |
* NOTE: |
d4076ac55 Define get_init_p... |
336 |
* |
fc14f2fef convert get_sb_si... |
337 338 |
* For single-mount semantics, devpts cannot use mount_single(), * because mount_single()/sget() find and use the super-block from |
d4076ac55 Define get_init_p... |
339 |
* the most recent mount of devpts. But that recent mount may be a |
fc14f2fef convert get_sb_si... |
340 |
* 'newinstance' mount and mount_single() would pick the newinstance |
d4076ac55 Define get_init_p... |
341 |
* super-block instead of the initial super-block. |
d4076ac55 Define get_init_p... |
342 |
*/ |
fc14f2fef convert get_sb_si... |
343 344 |
static struct dentry *devpts_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) |
1da177e4c Linux-2.6.12-rc2 |
345 |
{ |
482984f06 Parse mount optio... |
346 347 |
int error; struct pts_mount_opts opts; |
1bd790356 Merge code for si... |
348 |
struct super_block *s; |
2a1b2dc0c Enable multiple i... |
349 |
|
1f71ebedb devpts: correctly... |
350 351 |
error = parse_mount_options(data, PARSE_MOUNT, &opts); if (error) |
fc14f2fef convert get_sb_si... |
352 |
return ERR_PTR(error); |
2a1b2dc0c Enable multiple i... |
353 |
|
482984f06 Parse mount optio... |
354 |
if (opts.newinstance) |
1bd790356 Merge code for si... |
355 |
s = sget(fs_type, NULL, set_anon_super, NULL); |
482984f06 Parse mount optio... |
356 |
else |
1bd790356 Merge code for si... |
357 |
s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL); |
945cf2c79 Move common mknod... |
358 |
|
1bd790356 Merge code for si... |
359 |
if (IS_ERR(s)) |
fc14f2fef convert get_sb_si... |
360 |
return ERR_CAST(s); |
1bd790356 Merge code for si... |
361 362 363 364 365 366 367 368 |
if (!s->s_root) { s->s_flags = flags; error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0); if (error) goto out_undo_sget; s->s_flags |= MS_ACTIVE; } |
1bd790356 Merge code for si... |
369 |
memcpy(&(DEVPTS_SB(s))->mount_opts, &opts, sizeof(opts)); |
945cf2c79 Move common mknod... |
370 |
|
1bd790356 Merge code for si... |
371 |
error = mknod_ptmx(s); |
945cf2c79 Move common mknod... |
372 |
if (error) |
894680710 Simplify devpts_g... |
373 |
goto out_undo_sget; |
945cf2c79 Move common mknod... |
374 |
|
fc14f2fef convert get_sb_si... |
375 |
return dget(s->s_root); |
1bd790356 Merge code for si... |
376 377 |
out_undo_sget: |
6f5bbff9a Convert obvious p... |
378 |
deactivate_locked_super(s); |
fc14f2fef convert get_sb_si... |
379 |
return ERR_PTR(error); |
1da177e4c Linux-2.6.12-rc2 |
380 |
} |
482984f06 Parse mount optio... |
381 |
|
2a1b2dc0c Enable multiple i... |
382 383 384 385 386 |
#else /* * This supports only the legacy single-instance semantics (no * multiple-instance semantics) */ |
fc14f2fef convert get_sb_si... |
387 388 |
static struct dentry *devpts_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) |
2a1b2dc0c Enable multiple i... |
389 |
{ |
fc14f2fef convert get_sb_si... |
390 |
return mount_single(fs_type, flags, data, devpts_fill_super); |
2a1b2dc0c Enable multiple i... |
391 392 |
} #endif |
1da177e4c Linux-2.6.12-rc2 |
393 |
|
e76b7c01e Per-mount allocat... |
394 395 396 397 398 |
static void devpts_kill_sb(struct super_block *sb) { struct pts_fs_info *fsi = DEVPTS_SB(sb); kfree(fsi); |
1f8f1e296 Define mknod_ptmx() |
399 |
kill_litter_super(sb); |
e76b7c01e Per-mount allocat... |
400 |
} |
1da177e4c Linux-2.6.12-rc2 |
401 |
static struct file_system_type devpts_fs_type = { |
1da177e4c Linux-2.6.12-rc2 |
402 |
.name = "devpts", |
fc14f2fef convert get_sb_si... |
403 |
.mount = devpts_mount, |
e76b7c01e Per-mount allocat... |
404 |
.kill_sb = devpts_kill_sb, |
1da177e4c Linux-2.6.12-rc2 |
405 406 407 408 409 410 |
}; /* * The normal naming convention is simply /dev/pts/<number>; this conforms * to the System V naming convention */ |
15f1a6338 Add an instance p... |
411 |
int devpts_new_index(struct inode *ptmx_inode) |
718a91633 devpts: factor ou... |
412 |
{ |
e76b7c01e Per-mount allocat... |
413 414 |
struct super_block *sb = pts_sb_from_inode(ptmx_inode); struct pts_fs_info *fsi = DEVPTS_SB(sb); |
718a91633 devpts: factor ou... |
415 |
int index; |
7ee7c12b7 [PATCH] devpts: s... |
416 |
int ida_ret; |
718a91633 devpts: factor ou... |
417 418 |
retry: |
835aa440f devpts: Coding st... |
419 |
if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL)) |
718a91633 devpts: factor ou... |
420 |
return -ENOMEM; |
718a91633 devpts: factor ou... |
421 422 |
mutex_lock(&allocated_ptys_lock); |
e76b7c01e Per-mount allocat... |
423 |
ida_ret = ida_get_new(&fsi->allocated_ptys, &index); |
7ee7c12b7 [PATCH] devpts: s... |
424 |
if (ida_ret < 0) { |
718a91633 devpts: factor ou... |
425 |
mutex_unlock(&allocated_ptys_lock); |
7ee7c12b7 [PATCH] devpts: s... |
426 |
if (ida_ret == -EAGAIN) |
718a91633 devpts: factor ou... |
427 428 429 430 431 |
goto retry; return -EIO; } if (index >= pty_limit) { |
e76b7c01e Per-mount allocat... |
432 |
ida_remove(&fsi->allocated_ptys, index); |
718a91633 devpts: factor ou... |
433 434 435 436 437 438 |
mutex_unlock(&allocated_ptys_lock); return -EIO; } mutex_unlock(&allocated_ptys_lock); return index; } |
15f1a6338 Add an instance p... |
439 |
void devpts_kill_index(struct inode *ptmx_inode, int idx) |
718a91633 devpts: factor ou... |
440 |
{ |
e76b7c01e Per-mount allocat... |
441 442 |
struct super_block *sb = pts_sb_from_inode(ptmx_inode); struct pts_fs_info *fsi = DEVPTS_SB(sb); |
718a91633 devpts: factor ou... |
443 |
mutex_lock(&allocated_ptys_lock); |
e76b7c01e Per-mount allocat... |
444 |
ida_remove(&fsi->allocated_ptys, idx); |
718a91633 devpts: factor ou... |
445 446 |
mutex_unlock(&allocated_ptys_lock); } |
15f1a6338 Add an instance p... |
447 |
int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
448 |
{ |
835aa440f devpts: Coding st... |
449 450 |
/* tty layer puts index from devpts_new_index() in here */ int number = tty->index; |
1da177e4c Linux-2.6.12-rc2 |
451 452 453 |
struct tty_driver *driver = tty->driver; dev_t device = MKDEV(driver->major, driver->minor_start+number); struct dentry *dentry; |
59e55e6cf Remove devpts_roo... |
454 455 456 |
struct super_block *sb = pts_sb_from_inode(ptmx_inode); struct inode *inode = new_inode(sb); struct dentry *root = sb->s_root; |
31af0abbd Per-mount 'config... |
457 458 |
struct pts_fs_info *fsi = DEVPTS_SB(sb); struct pts_mount_opts *opts = &fsi->mount_opts; |
aa597bc1f fs: devpts_pty_ne... |
459 |
int ret = 0; |
89a52e109 Simplify devpts_p... |
460 |
char s[12]; |
1da177e4c Linux-2.6.12-rc2 |
461 462 463 464 465 466 467 |
/* We're supposed to be given the slave end of a pty */ BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY); BUG_ON(driver->subtype != PTY_TYPE_SLAVE); if (!inode) return -ENOMEM; |
d0eafc7db CRED: Wrap task c... |
468 469 470 |
inode->i_ino = number + 3; inode->i_uid = opts->setuid ? opts->uid : current_fsuid(); inode->i_gid = opts->setgid ? opts->gid : current_fsgid(); |
1da177e4c Linux-2.6.12-rc2 |
471 |
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
31af0abbd Per-mount 'config... |
472 |
init_special_inode(inode, S_IFCHR|opts->mode, device); |
8e18e2941 [PATCH] inode_die... |
473 |
inode->i_private = tty; |
a6f37daa8 Simplify devpts_p... |
474 |
tty->driver_data = inode; |
1da177e4c Linux-2.6.12-rc2 |
475 |
|
89a52e109 Simplify devpts_p... |
476 |
sprintf(s, "%d", number); |
59e55e6cf Remove devpts_roo... |
477 |
mutex_lock(&root->d_inode->i_mutex); |
89a52e109 Simplify devpts_p... |
478 |
|
59e55e6cf Remove devpts_roo... |
479 |
dentry = d_alloc_name(root, s); |
b12d12596 fs/devpts/inode.c... |
480 |
if (dentry) { |
89a52e109 Simplify devpts_p... |
481 |
d_add(dentry, inode); |
59e55e6cf Remove devpts_roo... |
482 |
fsnotify_create(root->d_inode, dentry); |
aa597bc1f fs: devpts_pty_ne... |
483 484 485 |
} else { iput(inode); ret = -ENOMEM; |
3972b7f67 devpts: add fsnot... |
486 |
} |
1da177e4c Linux-2.6.12-rc2 |
487 |
|
59e55e6cf Remove devpts_roo... |
488 |
mutex_unlock(&root->d_inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
489 |
|
aa597bc1f fs: devpts_pty_ne... |
490 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
491 |
} |
15f1a6338 Add an instance p... |
492 |
struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) |
1da177e4c Linux-2.6.12-rc2 |
493 |
{ |
edfacdd6f devpts_get_tty() ... |
494 495 |
struct dentry *dentry; struct tty_struct *tty; |
527b3e477 Simplify devpts_g... |
496 |
BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); |
1da177e4c Linux-2.6.12-rc2 |
497 |
|
edfacdd6f devpts_get_tty() ... |
498 499 500 501 502 503 |
/* Ensure dentry has not been deleted by devpts_pty_kill() */ dentry = d_find_alias(pts_inode); if (!dentry) return NULL; tty = NULL; |
527b3e477 Simplify devpts_g... |
504 |
if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) |
edfacdd6f devpts_get_tty() ... |
505 506 507 508 509 |
tty = (struct tty_struct *)pts_inode->i_private; dput(dentry); return tty; |
1da177e4c Linux-2.6.12-rc2 |
510 |
} |
15f1a6338 Add an instance p... |
511 |
void devpts_pty_kill(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
512 |
{ |
a6f37daa8 Simplify devpts_p... |
513 |
struct inode *inode = tty->driver_data; |
59e55e6cf Remove devpts_roo... |
514 515 |
struct super_block *sb = pts_sb_from_inode(inode); struct dentry *root = sb->s_root; |
a6f37daa8 Simplify devpts_p... |
516 |
struct dentry *dentry; |
1da177e4c Linux-2.6.12-rc2 |
517 |
|
a6f37daa8 Simplify devpts_p... |
518 |
BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); |
59e55e6cf Remove devpts_roo... |
519 |
mutex_lock(&root->d_inode->i_mutex); |
a6f37daa8 Simplify devpts_p... |
520 521 |
dentry = d_find_alias(inode); |
a6f37daa8 Simplify devpts_p... |
522 |
|
6d6b77f16 filesystems: add ... |
523 |
drop_nlink(inode); |
aa597bc1f fs: devpts_pty_ne... |
524 525 |
d_delete(dentry); dput(dentry); /* d_alloc_name() in devpts_pty_new() */ |
835aa440f devpts: Coding st... |
526 |
dput(dentry); /* d_find_alias above */ |
aa597bc1f fs: devpts_pty_ne... |
527 |
|
59e55e6cf Remove devpts_roo... |
528 |
mutex_unlock(&root->d_inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
529 530 531 532 533 534 535 |
} static int __init init_devpts_fs(void) { int err = register_filesystem(&devpts_fs_type); if (!err) { devpts_mnt = kern_mount(&devpts_fs_type); |
93d5581e2 devpts: unregiste... |
536 |
if (IS_ERR(devpts_mnt)) { |
1da177e4c Linux-2.6.12-rc2 |
537 |
err = PTR_ERR(devpts_mnt); |
93d5581e2 devpts: unregiste... |
538 539 |
unregister_filesystem(&devpts_fs_type); } |
1da177e4c Linux-2.6.12-rc2 |
540 541 542 |
} return err; } |
1da177e4c Linux-2.6.12-rc2 |
543 |
module_init(init_devpts_fs) |