Diff markup
1 /* -*- linux-c -*- --------------------------- 1 /* -*- linux-c -*- --------------------------------------------------------- *
2 * 2 *
3 * linux/fs/devpts/inode.c 3 * linux/fs/devpts/inode.c
4 * 4 *
5 * Copyright 1998-2004 H. Peter Anvin -- All 5 * Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved
6 * 6 *
7 * This file is part of the Linux kernel and i 7 * This file is part of the Linux kernel and is made available under
8 * the terms of the GNU General Public License 8 * the terms of the GNU General Public License, version 2, or at your
9 * option, any later version, incorporated her 9 * option, any later version, incorporated herein by reference.
10 * 10 *
11 * ------------------------------------------- 11 * ------------------------------------------------------------------------- */
12 12
13 #include <linux/module.h> 13 #include <linux/module.h>
14 #include <linux/init.h> 14 #include <linux/init.h>
15 #include <linux/fs.h> 15 #include <linux/fs.h>
16 #include <linux/sched.h> 16 #include <linux/sched.h>
17 #include <linux/namei.h> 17 #include <linux/namei.h>
18 #include <linux/mount.h> 18 #include <linux/mount.h>
19 #include <linux/tty.h> 19 #include <linux/tty.h>
20 #include <linux/mutex.h> <<
21 #include <linux/idr.h> <<
22 #include <linux/devpts_fs.h> 20 #include <linux/devpts_fs.h>
23 #include <linux/parser.h> 21 #include <linux/parser.h>
24 #include <linux/fsnotify.h> 22 #include <linux/fsnotify.h>
25 #include <linux/seq_file.h> 23 #include <linux/seq_file.h>
26 24
27 #define DEVPTS_SUPER_MAGIC 0x1cd1 25 #define DEVPTS_SUPER_MAGIC 0x1cd1
28 26
29 #define DEVPTS_DEFAULT_MODE 0600 27 #define DEVPTS_DEFAULT_MODE 0600
30 /* <<
31 * ptmx is a new node in /dev/pts and will be <<
32 * instance) mode. To prevent surprises in use <<
33 * ptmx to 0. Use 'chmod' or remount with '-o <<
34 * permissions. <<
35 */ <<
36 #define DEVPTS_DEFAULT_PTMX_MODE 0000 <<
37 #define PTMX_MINOR 2 <<
38 <<
39 extern int pty_limit; /* Con <<
40 static DEFINE_MUTEX(allocated_ptys_lock); <<
41 28
42 static struct vfsmount *devpts_mnt; 29 static struct vfsmount *devpts_mnt;
>> 30 static struct dentry *devpts_root;
43 31
44 struct pts_mount_opts { !! 32 static struct {
45 int setuid; 33 int setuid;
46 int setgid; 34 int setgid;
47 uid_t uid; 35 uid_t uid;
48 gid_t gid; 36 gid_t gid;
49 umode_t mode; 37 umode_t mode;
50 umode_t ptmxmode; !! 38 } config = {.mode = DEVPTS_DEFAULT_MODE};
51 int newinstance; <<
52 }; <<
53 39
54 enum { 40 enum {
55 Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmo !! 41 Opt_uid, Opt_gid, Opt_mode,
56 Opt_err 42 Opt_err
57 }; 43 };
58 44
59 static const match_table_t tokens = { !! 45 static match_table_t tokens = {
60 {Opt_uid, "uid=%u"}, 46 {Opt_uid, "uid=%u"},
61 {Opt_gid, "gid=%u"}, 47 {Opt_gid, "gid=%u"},
62 {Opt_mode, "mode=%o"}, 48 {Opt_mode, "mode=%o"},
63 #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES <<
64 {Opt_ptmxmode, "ptmxmode=%o"}, <<
65 {Opt_newinstance, "newinstance"}, <<
66 #endif <<
67 {Opt_err, NULL} 49 {Opt_err, NULL}
68 }; 50 };
69 51
70 struct pts_fs_info { !! 52 static int devpts_remount(struct super_block *sb, int *flags, char *data)
71 struct ida allocated_ptys; <<
72 struct pts_mount_opts mount_opts; <<
73 struct dentry *ptmx_dentry; <<
74 }; <<
75 <<
76 static inline struct pts_fs_info *DEVPTS_SB(st <<
77 { <<
78 return sb->s_fs_info; <<
79 } <<
80 <<
81 static inline struct super_block *pts_sb_from_ <<
82 { <<
83 #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES <<
84 if (inode->i_sb->s_magic == DEVPTS_SUP <<
85 return inode->i_sb; <<
86 #endif <<
87 return devpts_mnt->mnt_sb; <<
88 } <<
89 <<
90 #define PARSE_MOUNT 0 <<
91 #define PARSE_REMOUNT 1 <<
92 <<
93 /* <<
94 * parse_mount_options(): <<
95 * Set @opts to mount options specified i <<
96 * specified in @data, set it to its defa <<
97 * 'newinstance' option which can only be <<
98 * cannot be changed during remount). <<
99 * <<
100 * Note: @data may be NULL (in which case all <<
101 */ <<
102 static int parse_mount_options(char *data, int <<
103 { 53 {
104 char *p; 54 char *p;
105 55
106 opts->setuid = 0; !! 56 config.setuid = 0;
107 opts->setgid = 0; !! 57 config.setgid = 0;
108 opts->uid = 0; !! 58 config.uid = 0;
109 opts->gid = 0; !! 59 config.gid = 0;
110 opts->mode = DEVPTS_DEFAULT_MODE; !! 60 config.mode = DEVPTS_DEFAULT_MODE;
111 opts->ptmxmode = DEVPTS_DEFAULT_PTMX_M <<
112 <<
113 /* newinstance makes sense only on ini <<
114 if (op == PARSE_MOUNT) <<
115 opts->newinstance = 0; <<
116 61
117 while ((p = strsep(&data, ",")) != NUL 62 while ((p = strsep(&data, ",")) != NULL) {
118 substring_t args[MAX_OPT_ARGS] 63 substring_t args[MAX_OPT_ARGS];
119 int token; 64 int token;
120 int option; 65 int option;
121 66
122 if (!*p) 67 if (!*p)
123 continue; 68 continue;
124 69
125 token = match_token(p, tokens, 70 token = match_token(p, tokens, args);
126 switch (token) { 71 switch (token) {
127 case Opt_uid: 72 case Opt_uid:
128 if (match_int(&args[0] 73 if (match_int(&args[0], &option))
129 return -EINVAL 74 return -EINVAL;
130 opts->uid = option; !! 75 config.uid = option;
131 opts->setuid = 1; !! 76 config.setuid = 1;
132 break; 77 break;
133 case Opt_gid: 78 case Opt_gid:
134 if (match_int(&args[0] 79 if (match_int(&args[0], &option))
135 return -EINVAL 80 return -EINVAL;
136 opts->gid = option; !! 81 config.gid = option;
137 opts->setgid = 1; !! 82 config.setgid = 1;
138 break; 83 break;
139 case Opt_mode: 84 case Opt_mode:
140 if (match_octal(&args[ 85 if (match_octal(&args[0], &option))
141 return -EINVAL 86 return -EINVAL;
142 opts->mode = option & !! 87 config.mode = option & S_IALLUGO;
143 break; 88 break;
144 #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES <<
145 case Opt_ptmxmode: <<
146 if (match_octal(&args[ <<
147 return -EINVAL <<
148 opts->ptmxmode = optio <<
149 break; <<
150 case Opt_newinstance: <<
151 /* newinstance makes s <<
152 if (op == PARSE_MOUNT) <<
153 opts->newinsta <<
154 break; <<
155 #endif <<
156 default: 89 default:
157 printk(KERN_ERR "devpt 90 printk(KERN_ERR "devpts: called with bogus options\n");
158 return -EINVAL; 91 return -EINVAL;
159 } 92 }
160 } 93 }
161 94
162 return 0; 95 return 0;
163 } 96 }
164 97
165 #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES <<
166 static int mknod_ptmx(struct super_block *sb) <<
167 { <<
168 int mode; <<
169 int rc = -ENOMEM; <<
170 struct dentry *dentry; <<
171 struct inode *inode; <<
172 struct dentry *root = sb->s_root; <<
173 struct pts_fs_info *fsi = DEVPTS_SB(sb <<
174 struct pts_mount_opts *opts = &fsi->mo <<
175 <<
176 mutex_lock(&root->d_inode->i_mutex); <<
177 <<
178 /* If we have already created ptmx nod <<
179 if (fsi->ptmx_dentry) { <<
180 rc = 0; <<
181 goto out; <<
182 } <<
183 <<
184 dentry = d_alloc_name(root, "ptmx"); <<
185 if (!dentry) { <<
186 printk(KERN_NOTICE "Unable to <<
187 goto out; <<
188 } <<
189 <<
190 /* <<
191 * Create a new 'ptmx' node in this mo <<
192 */ <<
193 inode = new_inode(sb); <<
194 if (!inode) { <<
195 printk(KERN_ERR "Unable to all <<
196 dput(dentry); <<
197 goto out; <<
198 } <<
199 <<
200 inode->i_ino = 2; <<
201 inode->i_mtime = inode->i_atime = inod <<
202 <<
203 mode = S_IFCHR|opts->ptmxmode; <<
204 init_special_inode(inode, mode, MKDEV( <<
205 <<
206 d_add(dentry, inode); <<
207 <<
208 fsi->ptmx_dentry = dentry; <<
209 rc = 0; <<
210 out: <<
211 mutex_unlock(&root->d_inode->i_mutex); <<
212 return rc; <<
213 } <<
214 <<
215 static void update_ptmx_mode(struct pts_fs_inf <<
216 { <<
217 struct inode *inode; <<
218 if (fsi->ptmx_dentry) { <<
219 inode = fsi->ptmx_dentry->d_in <<
220 inode->i_mode = S_IFCHR|fsi->m <<
221 } <<
222 } <<
223 #else <<
224 static inline void update_ptmx_mode(struct pts <<
225 { <<
226 return; <<
227 } <<
228 #endif <<
229 <<
230 static int devpts_remount(struct super_block * <<
231 { <<
232 int err; <<
233 struct pts_fs_info *fsi = DEVPTS_SB(sb <<
234 struct pts_mount_opts *opts = &fsi->mo <<
235 <<
236 err = parse_mount_options(data, PARSE_ <<
237 <<
238 /* <<
239 * parse_mount_options() restores opti <<
240 * before parsing and may have changed <<
241 * mode in the inode too. Bogus option <<
242 * so do this even on error return. <<
243 */ <<
244 update_ptmx_mode(fsi); <<
245 <<
246 return err; <<
247 } <<
248 <<
249 static int devpts_show_options(struct seq_file 98 static int devpts_show_options(struct seq_file *seq, struct vfsmount *vfs)
250 { 99 {
251 struct pts_fs_info *fsi = DEVPTS_SB(vf !! 100 if (config.setuid)
252 struct pts_mount_opts *opts = &fsi->mo !! 101 seq_printf(seq, ",uid=%u", config.uid);
253 !! 102 if (config.setgid)
254 if (opts->setuid) !! 103 seq_printf(seq, ",gid=%u", config.gid);
255 seq_printf(seq, ",uid=%u", opt !! 104 seq_printf(seq, ",mode=%03o", config.mode);
256 if (opts->setgid) <<
257 seq_printf(seq, ",gid=%u", opt <<
258 seq_printf(seq, ",mode=%03o", opts->mo <<
259 #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES <<
260 seq_printf(seq, ",ptmxmode=%03o", opts <<
261 #endif <<
262 105
263 return 0; 106 return 0;
264 } 107 }
265 108
266 static const struct super_operations devpts_so 109 static const struct super_operations devpts_sops = {
267 .statfs = simple_statfs, 110 .statfs = simple_statfs,
268 .remount_fs = devpts_remount, 111 .remount_fs = devpts_remount,
269 .show_options = devpts_show_options, 112 .show_options = devpts_show_options,
270 }; 113 };
271 114
272 static void *new_pts_fs_info(void) <<
273 { <<
274 struct pts_fs_info *fsi; <<
275 <<
276 fsi = kzalloc(sizeof(struct pts_fs_inf <<
277 if (!fsi) <<
278 return NULL; <<
279 <<
280 ida_init(&fsi->allocated_ptys); <<
281 fsi->mount_opts.mode = DEVPTS_DEFAULT_ <<
282 fsi->mount_opts.ptmxmode = DEVPTS_DEFA <<
283 <<
284 return fsi; <<
285 } <<
286 <<
287 static int 115 static int
288 devpts_fill_super(struct super_block *s, void 116 devpts_fill_super(struct super_block *s, void *data, int silent)
289 { 117 {
290 struct inode *inode; !! 118 struct inode * inode;
291 119
292 s->s_blocksize = 1024; 120 s->s_blocksize = 1024;
293 s->s_blocksize_bits = 10; 121 s->s_blocksize_bits = 10;
294 s->s_magic = DEVPTS_SUPER_MAGIC; 122 s->s_magic = DEVPTS_SUPER_MAGIC;
295 s->s_op = &devpts_sops; 123 s->s_op = &devpts_sops;
296 s->s_time_gran = 1; 124 s->s_time_gran = 1;
297 125
298 s->s_fs_info = new_pts_fs_info(); <<
299 if (!s->s_fs_info) <<
300 goto fail; <<
301 <<
302 inode = new_inode(s); 126 inode = new_inode(s);
303 if (!inode) 127 if (!inode)
304 goto free_fsi; !! 128 goto fail;
305 inode->i_ino = 1; 129 inode->i_ino = 1;
306 inode->i_mtime = inode->i_atime = inod 130 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
>> 131 inode->i_blocks = 0;
>> 132 inode->i_uid = inode->i_gid = 0;
307 inode->i_mode = S_IFDIR | S_IRUGO | S_ 133 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
308 inode->i_op = &simple_dir_inode_operat 134 inode->i_op = &simple_dir_inode_operations;
309 inode->i_fop = &simple_dir_operations; 135 inode->i_fop = &simple_dir_operations;
310 inode->i_nlink = 2; 136 inode->i_nlink = 2;
311 137
312 s->s_root = d_alloc_root(inode); !! 138 devpts_root = s->s_root = d_alloc_root(inode);
313 if (s->s_root) 139 if (s->s_root)
314 return 0; 140 return 0;
315 !! 141
316 printk(KERN_ERR "devpts: get root dent !! 142 printk("devpts: get root dentry failed\n");
317 iput(inode); 143 iput(inode);
318 <<
319 free_fsi: <<
320 kfree(s->s_fs_info); <<
321 fail: 144 fail:
322 return -ENOMEM; 145 return -ENOMEM;
323 } 146 }
324 147
325 #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES <<
326 static int compare_init_pts_sb(struct super_bl <<
327 { <<
328 if (devpts_mnt) <<
329 return devpts_mnt->mnt_sb == s <<
330 return 0; <<
331 } <<
332 <<
333 /* <<
334 * devpts_get_sb() <<
335 * <<
336 * If the '-o newinstance' mount option wa <<
337 * (private) instance of devpts. PTYs cre <<
338 * independent of the PTYs in other devpts <<
339 * <<
340 * If the '-o newinstance' option was not <<
341 * initial kernel mount of devpts. This t <<
342 * legacy, single-instance semantics. <<
343 * <<
344 * The 'newinstance' option is needed to s <<
345 * semantics in devpts while preserving ba <<
346 * current 'single-namespace' semantics. i <<
347 * without the 'newinstance' mount option <<
348 * kernel mount, like get_sb_single(). <<
349 * <<
350 * Mounts with 'newinstance' option create <<
351 * <<
352 * NOTE: <<
353 * <<
354 * For single-mount semantics, devpts cann <<
355 * because get_sb_single()/sget() find and <<
356 * the most recent mount of devpts. But th <<
357 * 'newinstance' mount and get_sb_single() <<
358 * super-block instead of the initial supe <<
359 */ <<
360 static int devpts_get_sb(struct file_system_ty 148 static int devpts_get_sb(struct file_system_type *fs_type,
361 int flags, const char *dev_name, void 149 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
362 { 150 {
363 int error; <<
364 struct pts_mount_opts opts; <<
365 struct super_block *s; <<
366 <<
367 error = parse_mount_options(data, PARS <<
368 if (error) <<
369 return error; <<
370 <<
371 if (opts.newinstance) <<
372 s = sget(fs_type, NULL, set_an <<
373 else <<
374 s = sget(fs_type, compare_init <<
375 <<
376 if (IS_ERR(s)) <<
377 return PTR_ERR(s); <<
378 <<
379 if (!s->s_root) { <<
380 s->s_flags = flags; <<
381 error = devpts_fill_super(s, d <<
382 if (error) <<
383 goto out_undo_sget; <<
384 s->s_flags |= MS_ACTIVE; <<
385 } <<
386 <<
387 simple_set_mnt(mnt, s); <<
388 <<
389 memcpy(&(DEVPTS_SB(s))->mount_opts, &o <<
390 <<
391 error = mknod_ptmx(s); <<
392 if (error) <<
393 goto out_dput; <<
394 <<
395 return 0; <<
396 <<
397 out_dput: <<
398 dput(s->s_root); /* undo dget() in sim <<
399 <<
400 out_undo_sget: <<
401 deactivate_locked_super(s); <<
402 return error; <<
403 } <<
404 <<
405 #else <<
406 /* <<
407 * This supports only the legacy single-instan <<
408 * multiple-instance semantics) <<
409 */ <<
410 static int devpts_get_sb(struct file_system_ty <<
411 const char *dev_name, void *da <<
412 { <<
413 return get_sb_single(fs_type, flags, d 151 return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt);
414 } 152 }
415 #endif <<
416 <<
417 static void devpts_kill_sb(struct super_block <<
418 { <<
419 struct pts_fs_info *fsi = DEVPTS_SB(sb <<
420 <<
421 kfree(fsi); <<
422 kill_litter_super(sb); <<
423 } <<
424 153
425 static struct file_system_type devpts_fs_type 154 static struct file_system_type devpts_fs_type = {
>> 155 .owner = THIS_MODULE,
426 .name = "devpts", 156 .name = "devpts",
427 .get_sb = devpts_get_sb, 157 .get_sb = devpts_get_sb,
428 .kill_sb = devpts_kill_sb, !! 158 .kill_sb = kill_anon_super,
429 }; 159 };
430 160
431 /* 161 /*
432 * The normal naming convention is simply /dev 162 * The normal naming convention is simply /dev/pts/<number>; this conforms
433 * to the System V naming convention 163 * to the System V naming convention
434 */ 164 */
435 165
436 int devpts_new_index(struct inode *ptmx_inode) !! 166 static struct dentry *get_node(int num)
437 { <<
438 struct super_block *sb = pts_sb_from_i <<
439 struct pts_fs_info *fsi = DEVPTS_SB(sb <<
440 int index; <<
441 int ida_ret; <<
442 <<
443 retry: <<
444 if (!ida_pre_get(&fsi->allocated_ptys, <<
445 return -ENOMEM; <<
446 <<
447 mutex_lock(&allocated_ptys_lock); <<
448 ida_ret = ida_get_new(&fsi->allocated_ <<
449 if (ida_ret < 0) { <<
450 mutex_unlock(&allocated_ptys_l <<
451 if (ida_ret == -EAGAIN) <<
452 goto retry; <<
453 return -EIO; <<
454 } <<
455 <<
456 if (index >= pty_limit) { <<
457 ida_remove(&fsi->allocated_pty <<
458 mutex_unlock(&allocated_ptys_l <<
459 return -EIO; <<
460 } <<
461 mutex_unlock(&allocated_ptys_lock); <<
462 return index; <<
463 } <<
464 <<
465 void devpts_kill_index(struct inode *ptmx_inod <<
466 { 167 {
467 struct super_block *sb = pts_sb_from_i !! 168 char s[12];
468 struct pts_fs_info *fsi = DEVPTS_SB(sb !! 169 struct dentry *root = devpts_root;
469 !! 170 mutex_lock(&root->d_inode->i_mutex);
470 mutex_lock(&allocated_ptys_lock); !! 171 return lookup_one_len(s, root, sprintf(s, "%d", num));
471 ida_remove(&fsi->allocated_ptys, idx); <<
472 mutex_unlock(&allocated_ptys_lock); <<
473 } 172 }
474 173
475 int devpts_pty_new(struct inode *ptmx_inode, s !! 174 int devpts_pty_new(struct tty_struct *tty)
476 { 175 {
477 /* tty layer puts index from devpts_ne <<
478 int number = tty->index; 176 int number = tty->index;
479 struct tty_driver *driver = tty->drive 177 struct tty_driver *driver = tty->driver;
480 dev_t device = MKDEV(driver->major, dr 178 dev_t device = MKDEV(driver->major, driver->minor_start+number);
481 struct dentry *dentry; 179 struct dentry *dentry;
482 struct super_block *sb = pts_sb_from_i !! 180 struct inode *inode = new_inode(devpts_mnt->mnt_sb);
483 struct inode *inode = new_inode(sb); <<
484 struct dentry *root = sb->s_root; <<
485 struct pts_fs_info *fsi = DEVPTS_SB(sb <<
486 struct pts_mount_opts *opts = &fsi->mo <<
487 char s[12]; <<
488 181
489 /* We're supposed to be given the slav 182 /* We're supposed to be given the slave end of a pty */
490 BUG_ON(driver->type != TTY_DRIVER_TYPE 183 BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY);
491 BUG_ON(driver->subtype != PTY_TYPE_SLA 184 BUG_ON(driver->subtype != PTY_TYPE_SLAVE);
492 185
493 if (!inode) 186 if (!inode)
494 return -ENOMEM; 187 return -ENOMEM;
495 188
496 inode->i_ino = number + 3; !! 189 inode->i_ino = number+2;
497 inode->i_uid = opts->setuid ? opts->ui !! 190 inode->i_uid = config.setuid ? config.uid : current->fsuid;
498 inode->i_gid = opts->setgid ? opts->gi !! 191 inode->i_gid = config.setgid ? config.gid : current->fsgid;
499 inode->i_mtime = inode->i_atime = inod 192 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
500 init_special_inode(inode, S_IFCHR|opts !! 193 init_special_inode(inode, S_IFCHR|config.mode, device);
501 inode->i_private = tty; 194 inode->i_private = tty;
502 tty->driver_data = inode; <<
503 <<
504 sprintf(s, "%d", number); <<
505 195
506 mutex_lock(&root->d_inode->i_mutex); !! 196 dentry = get_node(number);
507 !! 197 if (!IS_ERR(dentry) && !dentry->d_inode) {
508 dentry = d_alloc_name(root, s); !! 198 d_instantiate(dentry, inode);
509 if (!IS_ERR(dentry)) { !! 199 fsnotify_create(devpts_root->d_inode, dentry);
510 d_add(dentry, inode); <<
511 fsnotify_create(root->d_inode, <<
512 } 200 }
513 201
514 mutex_unlock(&root->d_inode->i_mutex); !! 202 mutex_unlock(&devpts_root->d_inode->i_mutex);
515 203
516 return 0; 204 return 0;
517 } 205 }
518 206
519 struct tty_struct *devpts_get_tty(struct inode !! 207 struct tty_struct *devpts_get_tty(int number)
520 { 208 {
521 struct dentry *dentry; !! 209 struct dentry *dentry = get_node(number);
522 struct tty_struct *tty; 210 struct tty_struct *tty;
523 211
524 BUG_ON(pts_inode->i_rdev == MKDEV(TTYA <<
525 <<
526 /* Ensure dentry has not been deleted <<
527 dentry = d_find_alias(pts_inode); <<
528 if (!dentry) <<
529 return NULL; <<
530 <<
531 tty = NULL; 212 tty = NULL;
532 if (pts_inode->i_sb->s_magic == DEVPTS !! 213 if (!IS_ERR(dentry)) {
533 tty = (struct tty_struct *)pts !! 214 if (dentry->d_inode)
>> 215 tty = dentry->d_inode->i_private;
>> 216 dput(dentry);
>> 217 }
534 218
535 dput(dentry); !! 219 mutex_unlock(&devpts_root->d_inode->i_mutex);
536 220
537 return tty; 221 return tty;
538 } 222 }
539 223
540 void devpts_pty_kill(struct tty_struct *tty) !! 224 void devpts_pty_kill(int number)
541 { 225 {
542 struct inode *inode = tty->driver_data !! 226 struct dentry *dentry = get_node(number);
543 struct super_block *sb = pts_sb_from_i <<
544 struct dentry *root = sb->s_root; <<
545 struct dentry *dentry; <<
546 <<
547 BUG_ON(inode->i_rdev == MKDEV(TTYAUX_M <<
548 227
549 mutex_lock(&root->d_inode->i_mutex); !! 228 if (!IS_ERR(dentry)) {
550 !! 229 struct inode *inode = dentry->d_inode;
551 dentry = d_find_alias(inode); !! 230 if (inode) {
552 if (IS_ERR(dentry)) !! 231 inode->i_nlink--;
553 goto out; !! 232 d_delete(dentry);
554 !! 233 dput(dentry);
555 if (dentry) { !! 234 }
556 inode->i_nlink--; !! 235 dput(dentry);
557 d_delete(dentry); <<
558 dput(dentry); /* d_alloc_nam <<
559 } 236 }
560 !! 237 mutex_unlock(&devpts_root->d_inode->i_mutex);
561 dput(dentry); /* d_find_alia <<
562 out: <<
563 mutex_unlock(&root->d_inode->i_mutex); <<
564 } 238 }
565 239
566 static int __init init_devpts_fs(void) 240 static int __init init_devpts_fs(void)
567 { 241 {
568 int err = register_filesystem(&devpts_ 242 int err = register_filesystem(&devpts_fs_type);
569 if (!err) { 243 if (!err) {
570 devpts_mnt = kern_mount(&devpt 244 devpts_mnt = kern_mount(&devpts_fs_type);
571 if (IS_ERR(devpts_mnt)) { !! 245 if (IS_ERR(devpts_mnt))
572 err = PTR_ERR(devpts_m 246 err = PTR_ERR(devpts_mnt);
573 unregister_filesystem( <<
574 } <<
575 } 247 }
576 return err; 248 return err;
577 } 249 }
>> 250
>> 251 static void __exit exit_devpts_fs(void)
>> 252 {
>> 253 unregister_filesystem(&devpts_fs_type);
>> 254 mntput(devpts_mnt);
>> 255 }
>> 256
578 module_init(init_devpts_fs) 257 module_init(init_devpts_fs)
>> 258 module_exit(exit_devpts_fs)
>> 259 MODULE_LICENSE("GPL");
579 260
|
This page was automatically generated by the
LXR engine.
|