File: /usr/src/linux/drivers/isdn/avmb1/capifs.c
1 /*
2 * $Id: capifs.c,v 1.14.6.7 2001/05/24 08:29:08 kai Exp $
3 *
4 * (c) Copyright 2000 by Carsten Paeth (calle@calle.de)
5 *
6 * Heavily based on devpts filesystem from H. Peter Anvin
7 *
8 */
9
10 #include <linux/version.h>
11 #include <linux/fs.h>
12 #include <linux/tty.h>
13 #include <linux/types.h>
14 #include <linux/errno.h>
15 #include <linux/stat.h>
16 #include <linux/param.h>
17 #include <linux/module.h>
18 #include <linux/string.h>
19 #include <linux/init.h>
20 #include <linux/kdev_t.h>
21 #include <linux/kernel.h>
22 #include <linux/locks.h>
23 #include <linux/major.h>
24 #include <linux/slab.h>
25 #include <linux/ctype.h>
26 #include <asm/bitops.h>
27 #include <asm/uaccess.h>
28
29 MODULE_AUTHOR("Carsten Paeth <calle@calle.de>");
30
31 static char *revision = "$Revision: 1.14.6.7 $";
32
33 struct capifs_ncci {
34 struct inode *inode;
35 char used;
36 char type;
37 unsigned int num;
38 kdev_t kdev;
39 };
40
41 struct capifs_sb_info {
42 u32 magic;
43 struct super_block *next;
44 struct super_block **back;
45 int setuid;
46 int setgid;
47 uid_t uid;
48 gid_t gid;
49 umode_t mode;
50
51 unsigned int max_ncci;
52 struct capifs_ncci *nccis;
53 };
54
55 #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
56 #define CAPIFS_SBI_MAGIC (('C'<<24)|('A'<<16)|('P'<<8)|'I')
57
58 static inline struct capifs_sb_info *SBI(struct super_block *sb)
59 {
60 return (struct capifs_sb_info *)(sb->u.generic_sbp);
61 }
62
63 /* ------------------------------------------------------------------ */
64
65 static int capifs_root_readdir(struct file *,void *,filldir_t);
66 static struct dentry *capifs_root_lookup(struct inode *,struct dentry *);
67 static int capifs_revalidate(struct dentry *, int);
68 static struct inode *capifs_new_inode(struct super_block *sb);
69
70 static struct file_operations capifs_root_operations = {
71 read: generic_read_dir,
72 readdir: capifs_root_readdir,
73 };
74
75 struct inode_operations capifs_root_inode_operations = {
76 lookup: capifs_root_lookup,
77 };
78
79 static struct dentry_operations capifs_dentry_operations = {
80 d_revalidate: capifs_revalidate,
81 };
82
83 /*
84 * /dev/capi/%d
85 * /dev/capi/r%d
86 */
87
88 static int capifs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
89 {
90 struct inode * inode = filp->f_dentry->d_inode;
91 struct capifs_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
92 off_t nr;
93 char numbuf[32];
94
95 nr = filp->f_pos;
96
97 switch(nr)
98 {
99 case 0:
100 if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
101 return 0;
102 filp->f_pos = ++nr;
103 /* fall through */
104 case 1:
105 if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
106 return 0;
107 filp->f_pos = ++nr;
108 /* fall through */
109 default:
110 while (nr < sbi->max_ncci) {
111 int n = nr - 2;
112 struct capifs_ncci *np = &sbi->nccis[n];
113 if (np->inode && np->used) {
114 char *p = numbuf;
115 if (np->type) *p++ = np->type;
116 sprintf(p, "%u", np->num);
117 if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_UNKNOWN) < 0 )
118 return 0;
119 }
120 filp->f_pos = ++nr;
121 }
122 break;
123 }
124
125 return 0;
126 }
127
128 /*
129 * Revalidate is called on every cache lookup. We use it to check that
130 * the ncci really does still exist. Never revalidate negative dentries;
131 * for simplicity (fix later?)
132 */
133 static int capifs_revalidate(struct dentry * dentry, int flags)
134 {
135 struct capifs_sb_info *sbi;
136
137 if ( !dentry->d_inode )
138 return 0;
139
140 sbi = SBI(dentry->d_inode->i_sb);
141
142 return ( sbi->nccis[dentry->d_inode->i_ino - 2].inode == dentry->d_inode );
143 }
144
145 static struct dentry *capifs_root_lookup(struct inode * dir, struct dentry * dentry)
146 {
147 struct capifs_sb_info *sbi = SBI(dir->i_sb);
148 struct capifs_ncci *np;
149 unsigned int i;
150 char numbuf[32];
151 char *p, *tmp;
152 unsigned int num;
153 char type = 0;
154
155 dentry->d_inode = NULL; /* Assume failure */
156 dentry->d_op = &capifs_dentry_operations;
157
158 if (dentry->d_name.len >= sizeof(numbuf) )
159 return NULL;
160 strncpy(numbuf, dentry->d_name.name, dentry->d_name.len);
161 numbuf[dentry->d_name.len] = 0;
162 p = numbuf;
163 if (!isdigit(*p)) type = *p++;
164 tmp = p;
165 num = (unsigned int)simple_strtoul(p, &tmp, 10);
166 if (tmp == p || *tmp)
167 return NULL;
168
169 for (i = 0, np = sbi->nccis ; i < sbi->max_ncci; i++, np++) {
170 if (np->used && np->num == num && np->type == type)
171 break;
172 }
173
174 if ( i >= sbi->max_ncci )
175 return NULL;
176
177 dentry->d_inode = np->inode;
178 if ( dentry->d_inode )
179 atomic_inc(&dentry->d_inode->i_count);
180
181 d_add(dentry, dentry->d_inode);
182
183 return NULL;
184 }
185
186 /* ------------------------------------------------------------------ */
187
188 static struct super_block *mounts = NULL;
189
190 static void capifs_put_super(struct super_block *sb)
191 {
192 struct capifs_sb_info *sbi = SBI(sb);
193 struct inode *inode;
194 int i;
195
196 for ( i = 0 ; i < sbi->max_ncci ; i++ ) {
197 if ( (inode = sbi->nccis[i].inode) ) {
198 if (atomic_read(&inode->i_count) != 1 )
199 printk("capifs_put_super: badness: entry %d count %d\n",
200 i, (unsigned)atomic_read(&inode->i_count));
201 inode->i_nlink--;
202 iput(inode);
203 }
204 }
205
206 *sbi->back = sbi->next;
207 if ( sbi->next )
208 SBI(sbi->next)->back = sbi->back;
209
210 kfree(sbi->nccis);
211 kfree(sbi);
212 }
213
214 static int capifs_statfs(struct super_block *sb, struct statfs *buf);
215
216 static struct super_operations capifs_sops = {
217 put_super: capifs_put_super,
218 statfs: capifs_statfs,
219 };
220
221 static int capifs_parse_options(char *options, struct capifs_sb_info *sbi)
222 {
223 int setuid = 0;
224 int setgid = 0;
225 uid_t uid = 0;
226 gid_t gid = 0;
227 umode_t mode = 0600;
228 unsigned int maxncci = 512;
229 char *this_char, *value;
230
231 this_char = NULL;
232 if ( options )
233 this_char = strtok(options,",");
234 for ( ; this_char; this_char = strtok(NULL,",")) {
235 if ((value = strchr(this_char,'=')) != NULL)
236 *value++ = 0;
237 if (!strcmp(this_char,"uid")) {
238 if (!value || !*value)
239 return 1;
240 uid = simple_strtoul(value,&value,0);
241 if (*value)
242 return 1;
243 setuid = 1;
244 }
245 else if (!strcmp(this_char,"gid")) {
246 if (!value || !*value)
247 return 1;
248 gid = simple_strtoul(value,&value,0);
249 if (*value)
250 return 1;
251 setgid = 1;
252 }
253 else if (!strcmp(this_char,"mode")) {
254 if (!value || !*value)
255 return 1;
256 mode = simple_strtoul(value,&value,8);
257 if (*value)
258 return 1;
259 }
260 else if (!strcmp(this_char,"maxncci")) {
261 if (!value || !*value)
262 return 1;
263 maxncci = simple_strtoul(value,&value,8);
264 if (*value)
265 return 1;
266 }
267 else
268 return 1;
269 }
270 sbi->setuid = setuid;
271 sbi->setgid = setgid;
272 sbi->uid = uid;
273 sbi->gid = gid;
274 sbi->mode = mode & ~S_IFMT;
275 sbi->max_ncci = maxncci;
276
277 return 0;
278 }
279
280 struct super_block *capifs_read_super(struct super_block *s, void *data,
281 int silent)
282 {
283 struct inode * root_inode;
284 struct dentry * root;
285 struct capifs_sb_info *sbi;
286
287 /* Super block already completed? */
288 if (s->s_root)
289 goto out;
290
291 sbi = (struct capifs_sb_info *) kmalloc(sizeof(struct capifs_sb_info), GFP_KERNEL);
292 if ( !sbi )
293 goto fail;
294
295 memset(sbi, 0, sizeof(struct capifs_sb_info));
296 sbi->magic = CAPIFS_SBI_MAGIC;
297
298 if ( capifs_parse_options(data,sbi) ) {
299 kfree(sbi);
300 printk("capifs: called with bogus options\n");
301 goto fail;
302 }
303
304 sbi->nccis = kmalloc(sizeof(struct capifs_ncci) * sbi->max_ncci, GFP_KERNEL);
305 if ( !sbi->nccis ) {
306 kfree(sbi);
307 goto fail;
308 }
309 memset(sbi->nccis, 0, sizeof(struct capifs_ncci) * sbi->max_ncci);
310
311 s->u.generic_sbp = (void *) sbi;
312 s->s_blocksize = 1024;
313 s->s_blocksize_bits = 10;
314 s->s_magic = CAPIFS_SUPER_MAGIC;
315 s->s_op = &capifs_sops;
316 s->s_root = NULL;
317
318 /*
319 * Get the root inode and dentry, but defer checking for errors.
320 */
321 root_inode = capifs_new_inode(s);
322 if (root_inode) {
323 root_inode->i_ino = 1;
324 root_inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
325 root_inode->i_op = &capifs_root_inode_operations;
326 root_inode->i_fop = &capifs_root_operations;
327 root_inode->i_nlink = 2;
328 }
329 root = d_alloc_root(root_inode);
330
331 /*
332 * Check whether somebody else completed the super block.
333 */
334 if (s->s_root) {
335 if (root) dput(root);
336 else iput(root_inode);
337 goto out;
338 }
339
340 if (!root) {
341 printk("capifs: get root dentry failed\n");
342 /*
343 * iput() can block, so we clear the super block first.
344 */
345 iput(root_inode);
346 kfree(sbi->nccis);
347 kfree(sbi);
348 goto fail;
349 }
350
351 /*
352 * Check whether somebody else completed the super block.
353 */
354 if (s->s_root)
355 goto out;
356
357 /*
358 * Success! Install the root dentry now to indicate completion.
359 */
360 s->s_root = root;
361
362 sbi->next = mounts;
363 if ( sbi->next )
364 SBI(sbi->next)->back = &(sbi->next);
365 sbi->back = &mounts;
366 mounts = s;
367
368 out: /* Success ... somebody else completed the super block for us. */
369 return s;
370 fail:
371 return NULL;
372 }
373
374 static int capifs_statfs(struct super_block *sb, struct statfs *buf)
375 {
376 buf->f_type = CAPIFS_SUPER_MAGIC;
377 buf->f_bsize = 1024;
378 buf->f_blocks = 0;
379 buf->f_bfree = 0;
380 buf->f_bavail = 0;
381 buf->f_files = 0;
382 buf->f_ffree = 0;
383 buf->f_namelen = NAME_MAX;
384 return 0;
385 }
386
387 static struct inode *capifs_new_inode(struct super_block *sb)
388 {
389 struct inode *inode = new_inode(sb);
390 if (inode) {
391 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
392 inode->i_blocks = 0;
393 inode->i_blksize = 1024;
394 inode->i_uid = inode->i_gid = 0;
395 }
396 return inode;
397 }
398
399 static DECLARE_FSTYPE(capifs_fs_type, "capifs", capifs_read_super, 0);
400
401 void capifs_new_ncci(char type, unsigned int num, kdev_t device)
402 {
403 struct super_block *sb;
404 struct capifs_sb_info *sbi;
405 struct capifs_ncci *np;
406 ino_t ino;
407
408 for ( sb = mounts ; sb ; sb = sbi->next ) {
409 sbi = SBI(sb);
410
411 for (ino = 0, np = sbi->nccis ; ino < sbi->max_ncci; ino++, np++) {
412 if (np->used == 0) {
413 np->used = 1;
414 np->type = type;
415 np->num = num;
416 np->kdev = device;
417 break;
418 }
419 }
420 if ( ino >= sbi->max_ncci )
421 continue;
422
423 if ((np->inode = capifs_new_inode(sb)) != NULL) {
424 struct inode *inode = np->inode;
425 inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
426 inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
427 inode->i_nlink = 1;
428 inode->i_ino = ino + 2;
429 init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
430 }
431 }
432 }
433
434 void capifs_free_ncci(char type, unsigned int num)
435 {
436 struct super_block *sb;
437 struct capifs_sb_info *sbi;
438 struct inode *inode;
439 struct capifs_ncci *np;
440 ino_t ino;
441
442 for ( sb = mounts ; sb ; sb = sbi->next ) {
443 sbi = SBI(sb);
444
445 for (ino = 0, np = sbi->nccis ; ino < sbi->max_ncci; ino++, np++) {
446 if (!np->used || np->type != type || np->num != num)
447 continue;
448 if (np->inode) {
449 inode = np->inode;
450 np->inode = 0;
451 np->used = 0;
452 inode->i_nlink--;
453 iput(inode);
454 break;
455 }
456 }
457 }
458 }
459
460 static int __init capifs_init(void)
461 {
462 char rev[32];
463 char *p;
464 int err;
465
466 MOD_INC_USE_COUNT;
467
468 if ((p = strchr(revision, ':')) != 0 && p[1]) {
469 strncpy(rev, p + 2, sizeof(rev));
470 rev[sizeof(rev)-1] = 0;
471 if ((p = strchr(rev, '$')) != 0 && p > rev)
472 *(p-1) = 0;
473 } else
474 strcpy(rev, "1.0");
475
476 err = register_filesystem(&capifs_fs_type);
477 if (err) {
478 MOD_DEC_USE_COUNT;
479 return err;
480 }
481 printk(KERN_NOTICE "capifs: Rev %s\n", rev);
482 MOD_DEC_USE_COUNT;
483 return 0;
484 }
485
486 static void __exit capifs_exit(void)
487 {
488 unregister_filesystem(&capifs_fs_type);
489 }
490
491 EXPORT_SYMBOL(capifs_new_ncci);
492 EXPORT_SYMBOL(capifs_free_ncci);
493
494 module_init(capifs_init);
495 module_exit(capifs_exit);
496