Root/
1 | /* |
2 | * linux/fs/affs/inode.c |
3 | * |
4 | * (c) 1996 Hans-Joachim Widmaier - Rewritten |
5 | * |
6 | * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem. |
7 | * |
8 | * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem. |
9 | * |
10 | * (C) 1991 Linus Torvalds - minix filesystem |
11 | */ |
12 | |
13 | #include <linux/module.h> |
14 | #include <linux/init.h> |
15 | #include <linux/statfs.h> |
16 | #include <linux/parser.h> |
17 | #include <linux/magic.h> |
18 | #include <linux/sched.h> |
19 | #include <linux/smp_lock.h> |
20 | #include <linux/slab.h> |
21 | #include "affs.h" |
22 | |
23 | extern struct timezone sys_tz; |
24 | |
25 | static int affs_statfs(struct dentry *dentry, struct kstatfs *buf); |
26 | static int affs_remount (struct super_block *sb, int *flags, char *data); |
27 | |
28 | static void |
29 | affs_commit_super(struct super_block *sb, int clean) |
30 | { |
31 | struct affs_sb_info *sbi = AFFS_SB(sb); |
32 | struct buffer_head *bh = sbi->s_root_bh; |
33 | struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh); |
34 | |
35 | tail->bm_flag = cpu_to_be32(clean); |
36 | secs_to_datestamp(get_seconds(), &tail->disk_change); |
37 | affs_fix_checksum(sb, bh); |
38 | mark_buffer_dirty(bh); |
39 | } |
40 | |
41 | static void |
42 | affs_put_super(struct super_block *sb) |
43 | { |
44 | struct affs_sb_info *sbi = AFFS_SB(sb); |
45 | pr_debug("AFFS: put_super()\n"); |
46 | |
47 | lock_kernel(); |
48 | |
49 | if (!(sb->s_flags & MS_RDONLY)) |
50 | affs_commit_super(sb, 1); |
51 | |
52 | kfree(sbi->s_prefix); |
53 | affs_free_bitmap(sb); |
54 | affs_brelse(sbi->s_root_bh); |
55 | kfree(sbi); |
56 | sb->s_fs_info = NULL; |
57 | |
58 | unlock_kernel(); |
59 | } |
60 | |
61 | static void |
62 | affs_write_super(struct super_block *sb) |
63 | { |
64 | int clean = 2; |
65 | |
66 | lock_super(sb); |
67 | if (!(sb->s_flags & MS_RDONLY)) { |
68 | // if (sbi->s_bitmap[i].bm_bh) { |
69 | // if (buffer_dirty(sbi->s_bitmap[i].bm_bh)) { |
70 | // clean = 0; |
71 | affs_commit_super(sb, clean); |
72 | sb->s_dirt = !clean; /* redo until bitmap synced */ |
73 | } else |
74 | sb->s_dirt = 0; |
75 | unlock_super(sb); |
76 | |
77 | pr_debug("AFFS: write_super() at %lu, clean=%d\n", get_seconds(), clean); |
78 | } |
79 | |
80 | static int |
81 | affs_sync_fs(struct super_block *sb, int wait) |
82 | { |
83 | lock_super(sb); |
84 | affs_commit_super(sb, 2); |
85 | sb->s_dirt = 0; |
86 | unlock_super(sb); |
87 | return 0; |
88 | } |
89 | |
90 | static struct kmem_cache * affs_inode_cachep; |
91 | |
92 | static struct inode *affs_alloc_inode(struct super_block *sb) |
93 | { |
94 | struct affs_inode_info *i; |
95 | |
96 | i = kmem_cache_alloc(affs_inode_cachep, GFP_KERNEL); |
97 | if (!i) |
98 | return NULL; |
99 | |
100 | i->vfs_inode.i_version = 1; |
101 | i->i_lc = NULL; |
102 | i->i_ext_bh = NULL; |
103 | i->i_pa_cnt = 0; |
104 | |
105 | return &i->vfs_inode; |
106 | } |
107 | |
108 | static void affs_destroy_inode(struct inode *inode) |
109 | { |
110 | kmem_cache_free(affs_inode_cachep, AFFS_I(inode)); |
111 | } |
112 | |
113 | static void init_once(void *foo) |
114 | { |
115 | struct affs_inode_info *ei = (struct affs_inode_info *) foo; |
116 | |
117 | init_MUTEX(&ei->i_link_lock); |
118 | init_MUTEX(&ei->i_ext_lock); |
119 | inode_init_once(&ei->vfs_inode); |
120 | } |
121 | |
122 | static int init_inodecache(void) |
123 | { |
124 | affs_inode_cachep = kmem_cache_create("affs_inode_cache", |
125 | sizeof(struct affs_inode_info), |
126 | 0, (SLAB_RECLAIM_ACCOUNT| |
127 | SLAB_MEM_SPREAD), |
128 | init_once); |
129 | if (affs_inode_cachep == NULL) |
130 | return -ENOMEM; |
131 | return 0; |
132 | } |
133 | |
134 | static void destroy_inodecache(void) |
135 | { |
136 | kmem_cache_destroy(affs_inode_cachep); |
137 | } |
138 | |
139 | static const struct super_operations affs_sops = { |
140 | .alloc_inode = affs_alloc_inode, |
141 | .destroy_inode = affs_destroy_inode, |
142 | .write_inode = affs_write_inode, |
143 | .delete_inode = affs_delete_inode, |
144 | .clear_inode = affs_clear_inode, |
145 | .put_super = affs_put_super, |
146 | .write_super = affs_write_super, |
147 | .sync_fs = affs_sync_fs, |
148 | .statfs = affs_statfs, |
149 | .remount_fs = affs_remount, |
150 | .show_options = generic_show_options, |
151 | }; |
152 | |
153 | enum { |
154 | Opt_bs, Opt_mode, Opt_mufs, Opt_prefix, Opt_protect, |
155 | Opt_reserved, Opt_root, Opt_setgid, Opt_setuid, |
156 | Opt_verbose, Opt_volume, Opt_ignore, Opt_err, |
157 | }; |
158 | |
159 | static const match_table_t tokens = { |
160 | {Opt_bs, "bs=%u"}, |
161 | {Opt_mode, "mode=%o"}, |
162 | {Opt_mufs, "mufs"}, |
163 | {Opt_prefix, "prefix=%s"}, |
164 | {Opt_protect, "protect"}, |
165 | {Opt_reserved, "reserved=%u"}, |
166 | {Opt_root, "root=%u"}, |
167 | {Opt_setgid, "setgid=%u"}, |
168 | {Opt_setuid, "setuid=%u"}, |
169 | {Opt_verbose, "verbose"}, |
170 | {Opt_volume, "volume=%s"}, |
171 | {Opt_ignore, "grpquota"}, |
172 | {Opt_ignore, "noquota"}, |
173 | {Opt_ignore, "quota"}, |
174 | {Opt_ignore, "usrquota"}, |
175 | {Opt_err, NULL}, |
176 | }; |
177 | |
178 | static int |
179 | parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root, |
180 | int *blocksize, char **prefix, char *volume, unsigned long *mount_opts) |
181 | { |
182 | char *p; |
183 | substring_t args[MAX_OPT_ARGS]; |
184 | |
185 | /* Fill in defaults */ |
186 | |
187 | *uid = current_uid(); |
188 | *gid = current_gid(); |
189 | *reserved = 2; |
190 | *root = -1; |
191 | *blocksize = -1; |
192 | volume[0] = ':'; |
193 | volume[1] = 0; |
194 | *mount_opts = 0; |
195 | if (!options) |
196 | return 1; |
197 | |
198 | while ((p = strsep(&options, ",")) != NULL) { |
199 | int token, n, option; |
200 | if (!*p) |
201 | continue; |
202 | |
203 | token = match_token(p, tokens, args); |
204 | switch (token) { |
205 | case Opt_bs: |
206 | if (match_int(&args[0], &n)) |
207 | return 0; |
208 | if (n != 512 && n != 1024 && n != 2048 |
209 | && n != 4096) { |
210 | printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); |
211 | return 0; |
212 | } |
213 | *blocksize = n; |
214 | break; |
215 | case Opt_mode: |
216 | if (match_octal(&args[0], &option)) |
217 | return 0; |
218 | *mode = option & 0777; |
219 | *mount_opts |= SF_SETMODE; |
220 | break; |
221 | case Opt_mufs: |
222 | *mount_opts |= SF_MUFS; |
223 | break; |
224 | case Opt_prefix: |
225 | *prefix = match_strdup(&args[0]); |
226 | if (!*prefix) |
227 | return 0; |
228 | *mount_opts |= SF_PREFIX; |
229 | break; |
230 | case Opt_protect: |
231 | *mount_opts |= SF_IMMUTABLE; |
232 | break; |
233 | case Opt_reserved: |
234 | if (match_int(&args[0], reserved)) |
235 | return 0; |
236 | break; |
237 | case Opt_root: |
238 | if (match_int(&args[0], root)) |
239 | return 0; |
240 | break; |
241 | case Opt_setgid: |
242 | if (match_int(&args[0], &option)) |
243 | return 0; |
244 | *gid = option; |
245 | *mount_opts |= SF_SETGID; |
246 | break; |
247 | case Opt_setuid: |
248 | if (match_int(&args[0], &option)) |
249 | return 0; |
250 | *uid = option; |
251 | *mount_opts |= SF_SETUID; |
252 | break; |
253 | case Opt_verbose: |
254 | *mount_opts |= SF_VERBOSE; |
255 | break; |
256 | case Opt_volume: { |
257 | char *vol = match_strdup(&args[0]); |
258 | if (!vol) |
259 | return 0; |
260 | strlcpy(volume, vol, 32); |
261 | kfree(vol); |
262 | break; |
263 | } |
264 | case Opt_ignore: |
265 | /* Silently ignore the quota options */ |
266 | break; |
267 | default: |
268 | printk("AFFS: Unrecognized mount option \"%s\" " |
269 | "or missing value\n", p); |
270 | return 0; |
271 | } |
272 | } |
273 | return 1; |
274 | } |
275 | |
276 | /* This function definitely needs to be split up. Some fine day I'll |
277 | * hopefully have the guts to do so. Until then: sorry for the mess. |
278 | */ |
279 | |
280 | static int affs_fill_super(struct super_block *sb, void *data, int silent) |
281 | { |
282 | struct affs_sb_info *sbi; |
283 | struct buffer_head *root_bh = NULL; |
284 | struct buffer_head *boot_bh; |
285 | struct inode *root_inode = NULL; |
286 | s32 root_block; |
287 | int size, blocksize; |
288 | u32 chksum; |
289 | int num_bm; |
290 | int i, j; |
291 | s32 key; |
292 | uid_t uid; |
293 | gid_t gid; |
294 | int reserved; |
295 | unsigned long mount_flags; |
296 | int tmp_flags; /* fix remount prototype... */ |
297 | u8 sig[4]; |
298 | int ret = -EINVAL; |
299 | |
300 | save_mount_options(sb, data); |
301 | |
302 | pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options"); |
303 | |
304 | sb->s_magic = AFFS_SUPER_MAGIC; |
305 | sb->s_op = &affs_sops; |
306 | sb->s_flags |= MS_NODIRATIME; |
307 | |
308 | sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL); |
309 | if (!sbi) |
310 | return -ENOMEM; |
311 | sb->s_fs_info = sbi; |
312 | mutex_init(&sbi->s_bmlock); |
313 | spin_lock_init(&sbi->symlink_lock); |
314 | |
315 | if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, |
316 | &blocksize,&sbi->s_prefix, |
317 | sbi->s_volume, &mount_flags)) { |
318 | printk(KERN_ERR "AFFS: Error parsing options\n"); |
319 | kfree(sbi->s_prefix); |
320 | kfree(sbi); |
321 | return -EINVAL; |
322 | } |
323 | /* N.B. after this point s_prefix must be released */ |
324 | |
325 | sbi->s_flags = mount_flags; |
326 | sbi->s_mode = i; |
327 | sbi->s_uid = uid; |
328 | sbi->s_gid = gid; |
329 | sbi->s_reserved= reserved; |
330 | |
331 | /* Get the size of the device in 512-byte blocks. |
332 | * If we later see that the partition uses bigger |
333 | * blocks, we will have to change it. |
334 | */ |
335 | |
336 | size = sb->s_bdev->bd_inode->i_size >> 9; |
337 | pr_debug("AFFS: initial blocksize=%d, #blocks=%d\n", 512, size); |
338 | |
339 | affs_set_blocksize(sb, PAGE_SIZE); |
340 | /* Try to find root block. Its location depends on the block size. */ |
341 | |
342 | i = 512; |
343 | j = 4096; |
344 | if (blocksize > 0) { |
345 | i = j = blocksize; |
346 | size = size / (blocksize / 512); |
347 | } |
348 | for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) { |
349 | sbi->s_root_block = root_block; |
350 | if (root_block < 0) |
351 | sbi->s_root_block = (reserved + size - 1) / 2; |
352 | pr_debug("AFFS: setting blocksize to %d\n", blocksize); |
353 | affs_set_blocksize(sb, blocksize); |
354 | sbi->s_partition_size = size; |
355 | |
356 | /* The root block location that was calculated above is not |
357 | * correct if the partition size is an odd number of 512- |
358 | * byte blocks, which will be rounded down to a number of |
359 | * 1024-byte blocks, and if there were an even number of |
360 | * reserved blocks. Ideally, all partition checkers should |
361 | * report the real number of blocks of the real blocksize, |
362 | * but since this just cannot be done, we have to try to |
363 | * find the root block anyways. In the above case, it is one |
364 | * block behind the calculated one. So we check this one, too. |
365 | */ |
366 | for (num_bm = 0; num_bm < 2; num_bm++) { |
367 | pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, " |
368 | "size=%d, reserved=%d\n", |
369 | sb->s_id, |
370 | sbi->s_root_block + num_bm, |
371 | blocksize, size, reserved); |
372 | root_bh = affs_bread(sb, sbi->s_root_block + num_bm); |
373 | if (!root_bh) |
374 | continue; |
375 | if (!affs_checksum_block(sb, root_bh) && |
376 | be32_to_cpu(AFFS_ROOT_HEAD(root_bh)->ptype) == T_SHORT && |
377 | be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) { |
378 | sbi->s_hashsize = blocksize / 4 - 56; |
379 | sbi->s_root_block += num_bm; |
380 | key = 1; |
381 | goto got_root; |
382 | } |
383 | affs_brelse(root_bh); |
384 | root_bh = NULL; |
385 | } |
386 | } |
387 | if (!silent) |
388 | printk(KERN_ERR "AFFS: No valid root block on device %s\n", |
389 | sb->s_id); |
390 | goto out_error; |
391 | |
392 | /* N.B. after this point bh must be released */ |
393 | got_root: |
394 | root_block = sbi->s_root_block; |
395 | |
396 | /* Find out which kind of FS we have */ |
397 | boot_bh = sb_bread(sb, 0); |
398 | if (!boot_bh) { |
399 | printk(KERN_ERR "AFFS: Cannot read boot block\n"); |
400 | goto out_error; |
401 | } |
402 | memcpy(sig, boot_bh->b_data, 4); |
403 | brelse(boot_bh); |
404 | chksum = be32_to_cpu(*(__be32 *)sig); |
405 | |
406 | /* Dircache filesystems are compatible with non-dircache ones |
407 | * when reading. As long as they aren't supported, writing is |
408 | * not recommended. |
409 | */ |
410 | if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS |
411 | || chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) { |
412 | printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", |
413 | sb->s_id); |
414 | sb->s_flags |= MS_RDONLY; |
415 | } |
416 | switch (chksum) { |
417 | case MUFS_FS: |
418 | case MUFS_INTLFFS: |
419 | case MUFS_DCFFS: |
420 | sbi->s_flags |= SF_MUFS; |
421 | /* fall thru */ |
422 | case FS_INTLFFS: |
423 | case FS_DCFFS: |
424 | sbi->s_flags |= SF_INTL; |
425 | break; |
426 | case MUFS_FFS: |
427 | sbi->s_flags |= SF_MUFS; |
428 | break; |
429 | case FS_FFS: |
430 | break; |
431 | case MUFS_OFS: |
432 | sbi->s_flags |= SF_MUFS; |
433 | /* fall thru */ |
434 | case FS_OFS: |
435 | sbi->s_flags |= SF_OFS; |
436 | sb->s_flags |= MS_NOEXEC; |
437 | break; |
438 | case MUFS_DCOFS: |
439 | case MUFS_INTLOFS: |
440 | sbi->s_flags |= SF_MUFS; |
441 | case FS_DCOFS: |
442 | case FS_INTLOFS: |
443 | sbi->s_flags |= SF_INTL | SF_OFS; |
444 | sb->s_flags |= MS_NOEXEC; |
445 | break; |
446 | default: |
447 | printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n", |
448 | sb->s_id, chksum); |
449 | goto out_error; |
450 | } |
451 | |
452 | if (mount_flags & SF_VERBOSE) { |
453 | u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0]; |
454 | printk(KERN_NOTICE "AFFS: Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n", |
455 | len > 31 ? 31 : len, |
456 | AFFS_ROOT_TAIL(sb, root_bh)->disk_name + 1, |
457 | sig, sig[3] + '0', blocksize); |
458 | } |
459 | |
460 | sb->s_flags |= MS_NODEV | MS_NOSUID; |
461 | |
462 | sbi->s_data_blksize = sb->s_blocksize; |
463 | if (sbi->s_flags & SF_OFS) |
464 | sbi->s_data_blksize -= 24; |
465 | |
466 | /* Keep super block in cache */ |
467 | sbi->s_root_bh = root_bh; |
468 | /* N.B. after this point s_root_bh must be released */ |
469 | |
470 | tmp_flags = sb->s_flags; |
471 | if (affs_init_bitmap(sb, &tmp_flags)) |
472 | goto out_error; |
473 | sb->s_flags = tmp_flags; |
474 | |
475 | /* set up enough so that it can read an inode */ |
476 | |
477 | root_inode = affs_iget(sb, root_block); |
478 | if (IS_ERR(root_inode)) { |
479 | ret = PTR_ERR(root_inode); |
480 | goto out_error_noinode; |
481 | } |
482 | |
483 | sb->s_root = d_alloc_root(root_inode); |
484 | if (!sb->s_root) { |
485 | printk(KERN_ERR "AFFS: Get root inode failed\n"); |
486 | goto out_error; |
487 | } |
488 | sb->s_root->d_op = &affs_dentry_operations; |
489 | |
490 | pr_debug("AFFS: s_flags=%lX\n",sb->s_flags); |
491 | return 0; |
492 | |
493 | /* |
494 | * Begin the cascaded cleanup ... |
495 | */ |
496 | out_error: |
497 | if (root_inode) |
498 | iput(root_inode); |
499 | out_error_noinode: |
500 | kfree(sbi->s_bitmap); |
501 | affs_brelse(root_bh); |
502 | kfree(sbi->s_prefix); |
503 | kfree(sbi); |
504 | sb->s_fs_info = NULL; |
505 | return ret; |
506 | } |
507 | |
508 | static int |
509 | affs_remount(struct super_block *sb, int *flags, char *data) |
510 | { |
511 | struct affs_sb_info *sbi = AFFS_SB(sb); |
512 | int blocksize; |
513 | uid_t uid; |
514 | gid_t gid; |
515 | int mode; |
516 | int reserved; |
517 | int root_block; |
518 | unsigned long mount_flags; |
519 | int res = 0; |
520 | char *new_opts = kstrdup(data, GFP_KERNEL); |
521 | char volume[32]; |
522 | char *prefix = NULL; |
523 | |
524 | pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data); |
525 | |
526 | *flags |= MS_NODIRATIME; |
527 | |
528 | memcpy(volume, sbi->s_volume, 32); |
529 | if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block, |
530 | &blocksize, &prefix, volume, |
531 | &mount_flags)) { |
532 | kfree(prefix); |
533 | kfree(new_opts); |
534 | return -EINVAL; |
535 | } |
536 | lock_kernel(); |
537 | replace_mount_options(sb, new_opts); |
538 | |
539 | sbi->s_flags = mount_flags; |
540 | sbi->s_mode = mode; |
541 | sbi->s_uid = uid; |
542 | sbi->s_gid = gid; |
543 | /* protect against readers */ |
544 | spin_lock(&sbi->symlink_lock); |
545 | if (prefix) { |
546 | kfree(sbi->s_prefix); |
547 | sbi->s_prefix = prefix; |
548 | } |
549 | memcpy(sbi->s_volume, volume, 32); |
550 | spin_unlock(&sbi->symlink_lock); |
551 | |
552 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { |
553 | unlock_kernel(); |
554 | return 0; |
555 | } |
556 | if (*flags & MS_RDONLY) { |
557 | sb->s_dirt = 1; |
558 | while (sb->s_dirt) |
559 | affs_write_super(sb); |
560 | affs_free_bitmap(sb); |
561 | } else |
562 | res = affs_init_bitmap(sb, flags); |
563 | |
564 | unlock_kernel(); |
565 | return res; |
566 | } |
567 | |
568 | static int |
569 | affs_statfs(struct dentry *dentry, struct kstatfs *buf) |
570 | { |
571 | struct super_block *sb = dentry->d_sb; |
572 | int free; |
573 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); |
574 | |
575 | pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size, |
576 | AFFS_SB(sb)->s_reserved); |
577 | |
578 | free = affs_count_free_blocks(sb); |
579 | buf->f_type = AFFS_SUPER_MAGIC; |
580 | buf->f_bsize = sb->s_blocksize; |
581 | buf->f_blocks = AFFS_SB(sb)->s_partition_size - AFFS_SB(sb)->s_reserved; |
582 | buf->f_bfree = free; |
583 | buf->f_bavail = free; |
584 | buf->f_fsid.val[0] = (u32)id; |
585 | buf->f_fsid.val[1] = (u32)(id >> 32); |
586 | buf->f_namelen = 30; |
587 | return 0; |
588 | } |
589 | |
590 | static int affs_get_sb(struct file_system_type *fs_type, |
591 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
592 | { |
593 | return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super, |
594 | mnt); |
595 | } |
596 | |
597 | static struct file_system_type affs_fs_type = { |
598 | .owner = THIS_MODULE, |
599 | .name = "affs", |
600 | .get_sb = affs_get_sb, |
601 | .kill_sb = kill_block_super, |
602 | .fs_flags = FS_REQUIRES_DEV, |
603 | }; |
604 | |
605 | static int __init init_affs_fs(void) |
606 | { |
607 | int err = init_inodecache(); |
608 | if (err) |
609 | goto out1; |
610 | err = register_filesystem(&affs_fs_type); |
611 | if (err) |
612 | goto out; |
613 | return 0; |
614 | out: |
615 | destroy_inodecache(); |
616 | out1: |
617 | return err; |
618 | } |
619 | |
620 | static void __exit exit_affs_fs(void) |
621 | { |
622 | unregister_filesystem(&affs_fs_type); |
623 | destroy_inodecache(); |
624 | } |
625 | |
626 | MODULE_DESCRIPTION("Amiga filesystem support for Linux"); |
627 | MODULE_LICENSE("GPL"); |
628 | |
629 | module_init(init_affs_fs) |
630 | module_exit(exit_affs_fs) |
631 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9