Magellan Linux

Contents of /trunk/kernel26-alx/patches-2.6.24-r3/0161-2.6.24-axfs-svn18.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1022 - (show annotations) (download)
Sun Apr 25 14:59:21 2010 UTC (14 years ago) by niro
File size: 98156 byte(s)
-added alx kernel

1 diff -Naur linux-2.6.24/fs/axfs/axfs_bdev.c linux-2.6.24-axfs/fs/axfs/axfs_bdev.c
2 --- linux-2.6.24/fs/axfs/axfs_bdev.c 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.24-axfs/fs/axfs/axfs_bdev.c 2008-08-24 19:12:32.000000000 +0200
4 @@ -0,0 +1,179 @@
5 +/*
6 + * Advanced XIP File System for Linux - AXFS
7 + * Readonly, compressed, and XIP filesystem for Linux systems big and small
8 + *
9 + * Copyright(c) 2008 Numonyx
10 + *
11 + * This program is free software; you can redistribute it and/or modify it
12 + * under the terms and conditions of the GNU General Public License,
13 + * version 2, as published by the Free Software Foundation.
14 + *
15 + * Authors:
16 + * Jared Hulbert <jaredeh@gmail.com>
17 + *
18 + * Project url: http://axfs.sourceforge.net
19 + *
20 + * axfs_bdev.c -
21 + * Allows axfs to use block devices or has dummy functions if block
22 + * device support is compiled out of the kernel.
23 + *
24 + */
25 +
26 +#include <linux/axfs.h>
27 +#include <linux/mount.h>
28 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
29 +#else
30 +#define CONFIG_BLOCK
31 +#endif
32 +#ifdef CONFIG_BLOCK
33 +#include <linux/buffer_head.h>
34 +#include <linux/namei.h>
35 +
36 +int axfs_fill_super(struct super_block *sb, void *data, int silent);
37 +
38 +int axfs_get_sb_bdev(struct file_system_type *fs_type, int flags,
39 + const char *dev_name, struct axfs_super *sbi,
40 + struct vfsmount *mnt, int *err)
41 +{
42 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)
43 + *err = get_sb_bdev(fs_type, flags, dev_name, sbi, axfs_fill_super, mnt);
44 +
45 + if (*err)
46 + return FALSE;
47 +#else
48 + mnt->mnt_sb =
49 + get_sb_bdev(fs_type, flags, dev_name, (void *)sbi, axfs_fill_super);
50 + if (IS_ERR(mnt->mnt_sb)) {
51 + *err = PTR_ERR(mnt->mnt_sb);
52 + return FALSE;
53 + }
54 +#endif
55 + return TRUE;
56 +}
57 +
58 +void axfs_kill_block_super(struct super_block *sb)
59 +{
60 + kill_block_super(sb);
61 +}
62 +
63 +/******************************************************************************
64 + *
65 + * axfs_copy_block_data
66 + *
67 + * Description: Helper function to read data from block device
68 + *
69 + * Parameters:
70 + * (IN) sb - pointer to super block structure.
71 + *
72 + * (IN) dst_addr - pointer to buffer into which data is to be read.
73 + *
74 + * (IN) boffset - offset within block device
75 + *
76 + * (IN) len - length of data to be read
77 + *
78 + * Returns:
79 + * 0 or error number
80 + *
81 + *****************************************************************************/
82 +int axfs_copy_block(struct super_block *sb, void *dst_addr, u64 fsoffset,
83 + u64 len)
84 +{
85 + struct axfs_super *sbi = AXFS_SB(sb);
86 + u64 boffset = AXFS_FSOFFSET_2_DEVOFFSET(sbi, fsoffset);
87 + u64 blocks;
88 + u64 blksize = sb->s_blocksize;
89 + unsigned long dst;
90 + unsigned long src;
91 + sector_t block;
92 + size_t bytes;
93 + struct buffer_head *bh;
94 + u64 copied = 0;
95 +
96 + if (len == 0)
97 + return 0;
98 +
99 + blocks = len / blksize;
100 + if ((len % blksize) > 0)
101 + blocks += 1;
102 +
103 + while (copied < len) {
104 + /* Explicit casting for ARM linker errors. */
105 + block = (sector_t) boffset + (sector_t) copied;
106 + block /= (sector_t) blksize;
107 + bh = sb_bread(sb, block);
108 + src = (unsigned long)bh->b_data;
109 + dst = (unsigned long)dst_addr;
110 + if (copied == 0) {
111 + /* Explicit casting for ARM linker errors. */
112 + bytes = (size_t) blksize;
113 + bytes -= (size_t) boffset % (size_t) blksize;
114 + if (bytes > len)
115 + bytes = len;
116 + /* Explicit casting for ARM linker errors. */
117 + src += (unsigned long)boffset % (unsigned long)blksize;
118 + } else {
119 + dst += copied;
120 + if ((len - copied) < blksize) {
121 + bytes = len - copied;
122 + } else {
123 + bytes = blksize;
124 + }
125 + }
126 + memcpy((void *)dst, (void *)src, bytes);
127 + copied += bytes;
128 + brelse(bh);
129 + }
130 + return 0;
131 +}
132 +
133 +int axfs_is_dev_bdev(char *path)
134 +{
135 + struct nameidata nd;
136 + int ret = FALSE;
137 +
138 + if (!path)
139 + return FALSE;
140 +
141 + if (path_lookup(path, LOOKUP_FOLLOW, &nd))
142 + return FALSE;
143 +
144 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24)
145 + if (S_ISBLK(nd.path.dentry->d_inode->i_mode))
146 +#else
147 + if (S_ISBLK(nd.dentry->d_inode->i_mode))
148 +#endif
149 + ret = TRUE;
150 +
151 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24)
152 + path_put(&nd.path);
153 +#else
154 + path_release(&nd);
155 +#endif
156 + return ret;
157 +}
158 +
159 +#else
160 +
161 +int axfs_get_sb_bdev(struct file_system_type *fs_type, int flags,
162 + const char *dev_name, struct axfs_super *sbi,
163 + struct vfsmount *mnt, int *err)
164 +{
165 + return FALSE;
166 +}
167 +
168 +void axfs_kill_block_super(struct super_block *sb)
169 +{
170 +}
171 +
172 +int axfs_copy_block(struct super_block *sb, void *dst_addr, u64 fsoffset,
173 + u64 len)
174 +{
175 + return -EINVAL;
176 +}
177 +
178 +int axfs_is_dev_bdev(char *path)
179 +{
180 + return FALSE;
181 +}
182 +
183 +#endif /* CONFIG_BLOCK */
184 diff -Naur linux-2.6.24/fs/axfs/axfs_inode.c linux-2.6.24-axfs/fs/axfs/axfs_inode.c
185 --- linux-2.6.24/fs/axfs/axfs_inode.c 1970-01-01 01:00:00.000000000 +0100
186 +++ linux-2.6.24-axfs/fs/axfs/axfs_inode.c 2008-08-24 19:12:32.000000000 +0200
187 @@ -0,0 +1,711 @@
188 +/*
189 + * Advanced XIP File System for Linux - AXFS
190 + * Readonly, compressed, and XIP filesystem for Linux systems big and small
191 + *
192 + * Copyright(c) 2008 Numonyx
193 + *
194 + * This program is free software; you can redistribute it and/or modify it
195 + * under the terms and conditions of the GNU General Public License,
196 + * version 2, as published by the Free Software Foundation.
197 + *
198 + * Authors:
199 + * Eric Anderson
200 + * Jared Hulbert <jaredeh@gmail.com>
201 + * Sujaya Srinivasan
202 + * Justin Treon
203 + *
204 + * Project url: http://axfs.sourceforge.net
205 + *
206 + * Borrowed heavily from fs/cramfs/inode.c by Linus Torvalds
207 + *
208 + * axfs_inode.c -
209 + * Contains the most of the filesystem logic with the major exception of the
210 + * mounting infrastructure.
211 + *
212 + */
213 +
214 +#include <linux/axfs.h>
215 +#include <linux/pagemap.h>
216 +
217 +/***************** functions in other axfs files ******************************/
218 +int axfs_get_sb(struct file_system_type *, int, const char *, void *,
219 + struct vfsmount *);
220 +void axfs_kill_super(struct super_block *);
221 +void axfs_profiling_add(struct axfs_super *, unsigned long, unsigned int);
222 +int axfs_copy_mtd(struct super_block *, void *, u64, u64);
223 +int axfs_copy_block(struct super_block *, void *, u64, u64);
224 +/******************************************************************************/
225 +static int axfs_readdir(struct file *, void *, filldir_t);
226 +static int axfs_mmap(struct file *, struct vm_area_struct *);
227 +static ssize_t axfs_file_read(struct file *, char __user *, size_t, loff_t *);
228 +static int axfs_readpage(struct file *, struct page *);
229 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
230 +static int axfs_fault(struct vm_area_struct *, struct vm_fault *);
231 +#else
232 +static struct page *axfs_nopage(struct vm_area_struct *, unsigned long, int *);
233 +#endif
234 +static struct dentry *axfs_lookup(struct inode *, struct dentry *,
235 + struct nameidata *);
236 +static int axfs_get_xip_mem(struct address_space *, pgoff_t, int, void **,
237 + unsigned long *);
238 +#ifdef VM_MIXEDMAP
239 +#else
240 +struct page *axfs_get_xip_page(struct address_space *mapping, sector_t offset,
241 + int create);
242 +#endif
243 +
244 +/******************************************************************************/
245 +
246 +static struct file_operations axfs_directory_operations = {
247 + .llseek = generic_file_llseek,
248 + .read = generic_read_dir,
249 + .readdir = axfs_readdir,
250 +};
251 +
252 +static struct file_operations axfs_fops = {
253 + .read = axfs_file_read,
254 + .aio_read = generic_file_aio_read,
255 + .mmap = axfs_mmap,
256 +};
257 +
258 +static struct address_space_operations axfs_aops = {
259 + .readpage = axfs_readpage,
260 +#ifdef VM_MIXEDMAP
261 + .get_xip_mem = axfs_get_xip_mem,
262 +#else
263 + .get_xip_page = axfs_get_xip_page,
264 +#endif
265 +};
266 +
267 +static struct inode_operations axfs_dir_inode_operations = {
268 + .lookup = axfs_lookup,
269 +};
270 +
271 +static struct vm_operations_struct axfs_vm_ops = {
272 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
273 + .fault = axfs_fault,
274 +#else
275 + .nopage = axfs_nopage,
276 +#endif
277 +};
278 +
279 +static int axfs_copy_data(struct super_block *sb, void *dst,
280 + struct axfs_region_desc *region, u64 offset, u64 len)
281 +{
282 + u64 mmapped = 0;
283 + u64 end = region->fsoffset + offset + len;
284 + u64 begin = region->fsoffset + offset;
285 + u64 left;
286 + void *addr;
287 + void *newdst;
288 + struct axfs_super *sbi = AXFS_SB(sb);
289 +
290 + if (len == 0)
291 + return 0;
292 +
293 + if (region->virt_addr) {
294 + if (sbi->mmap_size >= end) {
295 + mmapped = len;
296 + } else if (sbi->mmap_size > begin) {
297 + mmapped = sbi->mmap_size - begin;
298 + }
299 + }
300 +
301 + if (mmapped) {
302 + addr = (void *)(region->virt_addr + offset);
303 + memcpy(dst, addr, mmapped);
304 + }
305 +
306 + newdst = (void *)(dst + mmapped);
307 + left = len - mmapped;
308 +
309 + if (left == 0)
310 + return len;
311 +
312 + if (AXFS_HAS_BDEV(sb)) {
313 + return axfs_copy_block(sb, newdst, begin + mmapped, left);
314 + } else if (AXFS_HAS_MTD(sb)) {
315 + return axfs_copy_mtd(sb, newdst, begin + mmapped, left);
316 + } else {
317 + return 0;
318 + }
319 +}
320 +
321 +static int axfs_iget5_test(struct inode *inode, void *opaque)
322 +{
323 + u64 *inode_number = (u64 *) opaque;
324 +
325 + if (inode->i_sb == NULL) {
326 + printk(KERN_ERR "axfs_iget5_test:"
327 + " the super block is set to null\n");
328 + }
329 + if (inode->i_ino == *inode_number)
330 + return 1; /* matches */
331 + else
332 + return 0; /* does not match */
333 +}
334 +
335 +static int axfs_iget5_set(struct inode *inode, void *opaque)
336 +{
337 + u64 *inode_number = (u64 *) opaque;
338 +
339 + if (inode->i_sb == NULL) {
340 + printk(KERN_ERR "axfs_iget5_set:"
341 + " the super block is set to null \n");
342 + }
343 + inode->i_ino = *inode_number;
344 + return 0;
345 +}
346 +
347 +struct inode *axfs_create_vfs_inode(struct super_block *sb, int ino)
348 +{
349 + struct axfs_super *sbi = AXFS_SB(sb);
350 + struct inode *inode;
351 + u64 size;
352 +
353 + inode = iget5_locked(sb, ino, axfs_iget5_test, axfs_iget5_set, &ino);
354 +
355 + if (!(inode && (inode->i_state & I_NEW)))
356 + return inode;
357 +
358 + inode->i_mode = AXFS_GET_MODE(sbi, ino);
359 + inode->i_uid = AXFS_GET_UID(sbi, ino);
360 + size = AXFS_GET_INODE_FILE_SIZE(sbi, ino);
361 + inode->i_size = size;
362 + inode->i_blocks = AXFS_GET_INODE_NUM_ENTRIES(sbi, ino);
363 + inode->i_blkbits = PAGE_CACHE_SIZE * 8;
364 + inode->i_gid = AXFS_GET_GID(sbi, ino);
365 +
366 + inode->i_mtime = inode->i_atime = inode->i_ctime = sbi->timestamp;
367 + inode->i_ino = ino;
368 +
369 + if (S_ISREG(inode->i_mode)) {
370 + inode->i_fop = &axfs_fops;
371 + inode->i_data.a_ops = &axfs_aops;
372 + inode->i_mapping->a_ops = &axfs_aops;
373 + } else if (S_ISDIR(inode->i_mode)) {
374 + inode->i_op = &axfs_dir_inode_operations;
375 + inode->i_fop = &axfs_directory_operations;
376 + } else if (S_ISLNK(inode->i_mode)) {
377 + inode->i_op = &page_symlink_inode_operations;
378 + inode->i_data.a_ops = &axfs_aops;
379 + } else {
380 + inode->i_size = 0;
381 + inode->i_blocks = 0;
382 + init_special_inode(inode, inode->i_mode, old_decode_dev(size));
383 + }
384 + unlock_new_inode(inode);
385 +
386 + return inode;
387 +}
388 +
389 +#ifdef VM_MIXEDMAP
390 +#else
391 +static int axfs_insert_pfns(struct file *file, struct vm_area_struct *vma)
392 +{
393 + struct inode *inode = file->f_dentry->d_inode;
394 + struct super_block *sb = inode->i_sb;
395 + struct axfs_super *sbi = AXFS_SB(sb);
396 + unsigned long array_index, length, offset, count, xip_addr, addr, pfn;
397 + unsigned int numpages;
398 + u64 ino_number = inode->i_ino;
399 + int error;
400 +
401 + offset = vma->vm_pgoff;
402 +
403 + array_index = AXFS_GET_INODE_ARRAY_INDEX(sbi, ino_number);
404 + array_index += offset;
405 + length = vma->vm_end - vma->vm_start;
406 +
407 + if (length > inode->i_size)
408 + length = inode->i_size;
409 +
410 + length = PAGE_ALIGN(length);
411 + numpages = length >> PAGE_SHIFT;
412 +
413 + for (count = 0; count < numpages; count++, array_index++) {
414 + if (!AXFS_IS_NODE_XIP(sbi, array_index))
415 + continue;
416 +#ifdef VM_XIP
417 + vma->vm_flags |= (VM_IO | VM_XIP);
418 +#endif
419 + addr = vma->vm_start + (PAGE_SIZE * count);
420 + xip_addr = AXFS_GET_XIP_REGION_PHYSADDR(sbi);
421 + xip_addr += AXFS_GET_NODE_INDEX(sbi, array_index) << PAGE_SHIFT;
422 + pfn = xip_addr >> PAGE_SHIFT;
423 +
424 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
425 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
426 + error = vm_insert_pfn(vma, addr, pfn);
427 +#else
428 + error =
429 + remap_pfn_range(vma, addr, pfn, PAGE_SIZE,
430 + vma->vm_page_prot);
431 +#endif
432 +#else
433 + xip_addr = pfn << PAGE_SHIFT;
434 + error =
435 + remap_page_range(vma, addr, xip_addr, PAGE_SIZE,
436 + vma->vm_page_prot);
437 +#endif
438 + if (error)
439 + return error;
440 + }
441 +
442 + return 0;
443 +}
444 +#endif
445 +
446 +static int axfs_mmap(struct file *file, struct vm_area_struct *vma)
447 +{
448 +
449 + file_accessed(file);
450 +
451 + vma->vm_ops = &axfs_vm_ops;
452 +
453 +#ifdef VM_MIXEDMAP
454 +#ifdef VM_CAN_NONLINEAR
455 + vma->vm_flags |= VM_CAN_NONLINEAR | VM_MIXEDMAP;
456 +#else
457 + vma->vm_flags | = VM_IO | VM_MIXEDMAP;
458 +#endif
459 +#else
460 +#ifdef VM_PFNMAP
461 + vma->vm_flags |= VM_IO | VM_PFNMAP;
462 +#else
463 + vma->vm_flags |= VM_IO;
464 +#endif
465 +#endif
466 +#ifdef VM_XIP
467 + vma->vm_flags |= VM_XIP;
468 +#endif
469 +
470 +#ifdef VM_MIXEDMAP
471 + return 0;
472 +#else
473 + return axfs_insert_pfns(file, vma);
474 +#endif
475 +}
476 +
477 +static struct dentry *axfs_lookup(struct inode *dir, struct dentry *dentry,
478 + struct nameidata *nd)
479 +{
480 + struct super_block *sb = dir->i_sb;
481 + struct axfs_super *sbi = AXFS_SB(sb);
482 + u64 ino_number = dir->i_ino;
483 + u64 dir_index = 0;
484 + u64 entry;
485 + char *name;
486 + int namelen, err;
487 +
488 + while (dir_index < AXFS_GET_INODE_NUM_ENTRIES(sbi, ino_number)) {
489 + entry = AXFS_GET_INODE_ARRAY_INDEX(sbi, ino_number);
490 + entry += dir_index;
491 +
492 + name = AXFS_GET_INODE_NAME(sbi, entry);
493 + namelen = strlen(name);
494 +
495 + /* fast test, the entries are sorted alphabetically and the
496 + * first letter is smaller than the first letter in the search
497 + * name then it isn't in this directory. Keeps this loop from
498 + * needing to scan through always.
499 + */
500 + if (dentry->d_name.name[0] < name[0])
501 + break;
502 +
503 + dir_index++;
504 +
505 + /* Quick check that the name is roughly the right length */
506 + if (dentry->d_name.len != namelen)
507 + continue;
508 +
509 + err = memcmp(dentry->d_name.name, name, namelen);
510 + if (err > 0)
511 + continue;
512 +
513 + /* The file name isn't present in the directory. */
514 + if (err < 0)
515 + break;
516 +
517 + d_add(dentry, axfs_create_vfs_inode(dir->i_sb, entry));
518 + goto out;
519 +
520 + }
521 + d_add(dentry, NULL);
522 +
523 +out:
524 + return NULL;
525 +}
526 +
527 +static int axfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
528 +{
529 + struct inode *inode = filp->f_dentry->d_inode;
530 + struct super_block *sb = inode->i_sb;
531 + struct axfs_super *sbi = AXFS_SB(sb);
532 + u64 ino_number = inode->i_ino;
533 + u64 entry;
534 + loff_t dir_index;
535 + char *name;
536 + int namelen, mode;
537 + int err = 0;
538 +
539 + /* Get the current index into the directory and verify it is not beyond
540 + the end of the list */
541 + dir_index = filp->f_pos;
542 + if (dir_index >= AXFS_GET_INODE_NUM_ENTRIES(sbi, ino_number))
543 + goto out;
544 +
545 + /* Verify the inode is for a directory */
546 + if (!(S_ISDIR(inode->i_mode))) {
547 + err = -EINVAL;
548 + goto out;
549 + }
550 +
551 + while (dir_index < AXFS_GET_INODE_NUM_ENTRIES(sbi, ino_number)) {
552 + entry = AXFS_GET_INODE_ARRAY_INDEX(sbi, ino_number) + dir_index;
553 +
554 + name = (char *)AXFS_GET_INODE_NAME(sbi, entry);
555 + namelen = strlen(name);
556 +
557 + mode = (int)AXFS_GET_MODE(sbi, entry);
558 + err = filldir(dirent, name, namelen, dir_index, entry, mode);
559 +
560 + if (err)
561 + break;
562 +
563 + dir_index++;
564 + filp->f_pos = dir_index;
565 + }
566 +
567 +out:
568 + return 0;
569 +}
570 +
571 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
572 +/******************************************************************************
573 + *
574 + * axfs_fault
575 + *
576 + * Description: This function is mapped into the VMA operations vector, and
577 + * gets called on a page fault. Depending on whether the page
578 + * is XIP or compressed, xip_file_fault or filemap_fault is
579 + * called. This function also logs when a fault occurs when
580 + * profiling is on.
581 + *
582 + * Parameters:
583 + * (IN) vma - The virtual memory area corresponding to a file
584 + *
585 + * (IN) vmf - The fault info pass in by the fault handler
586 + *
587 + * Returns:
588 + * 0 or error number
589 + *
590 + *****************************************************************************/
591 +static int axfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
592 +#else
593 +static struct page *axfs_nopage(struct vm_area_struct *vma,
594 + unsigned long address, int *type)
595 +#endif
596 +{
597 + struct file *file = vma->vm_file;
598 + struct inode *inode = file->f_dentry->d_inode;
599 + struct super_block *sb = inode->i_sb;
600 + struct axfs_super *sbi = AXFS_SB(sb);
601 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
602 +#else
603 + unsigned long pgoff;
604 +#endif
605 + u64 ino_number = inode->i_ino;
606 + u64 array_index;
607 +
608 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
609 + array_index = AXFS_GET_INODE_ARRAY_INDEX(sbi, ino_number) + vmf->pgoff;
610 +#else
611 + pgoff = ((address - vma->vm_start) >> PAGE_CACHE_SHIFT) + vma->vm_pgoff;
612 + array_index = AXFS_GET_INODE_ARRAY_INDEX(sbi, ino_number) + pgoff;
613 +#endif
614 +
615 + /* if that pages are marked for write they will probably end up in RAM
616 + therefore we don't want their counts for being XIP'd */
617 + if (!(vma->vm_flags & VM_WRITE))
618 + axfs_profiling_add(sbi, array_index, ino_number);
619 +
620 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
621 + /* figure out if the node is XIP or compressed and call the
622 + appropriate function
623 + */
624 +#ifdef VM_MIXEDMAP
625 + if (AXFS_IS_NODE_XIP(sbi, array_index))
626 +#else
627 + if (AXFS_IS_NODE_XIP(sbi, array_index) && !AXFS_PHYSADDR_IS_VALID(sbi))
628 +#endif
629 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
630 + return xip_file_fault(vma, vmf);
631 +#else
632 + return xip_file_nopage(vma, address, type);
633 +#endif
634 +#endif
635 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
636 + return filemap_fault(vma, vmf);
637 +#else
638 + return filemap_nopage(vma, address, type);
639 +#endif
640 +
641 +}
642 +
643 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
644 +#else
645 +static ssize_t axfs_xip_file_read(struct file *filp, char __user *buf,
646 + size_t len, loff_t *ppos)
647 +{
648 + struct address_space *mapping = filp->f_mapping;
649 + struct inode *inode = mapping->host;
650 + unsigned long index, end_index, offset;
651 + loff_t isize, pos;
652 + size_t copied = 0, error = 0;
653 +
654 + pos = *ppos;
655 + index = pos >> PAGE_CACHE_SHIFT;
656 + offset = pos & ~PAGE_CACHE_MASK;
657 +
658 + isize = i_size_read(inode);
659 + if (!isize)
660 + goto out;
661 +
662 + end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
663 + do {
664 + unsigned long nr, left, pfn;
665 + void *xip_mem;
666 + int zero = 0;
667 +
668 + /* nr is the maximum number of bytes to copy from this page */
669 + nr = PAGE_CACHE_SIZE;
670 + if (index >= end_index) {
671 + if (index > end_index)
672 + goto out;
673 + nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
674 + if (nr <= offset)
675 + goto out;
676 + }
677 + nr = nr - offset;
678 + if (nr > len)
679 + nr = len;
680 + axfs_get_xip_mem(mapping, index, 0, &xip_mem, &pfn);
681 + if (!xip_mem) {
682 + error = -EIO;
683 + goto out;
684 + }
685 + if (unlikely(IS_ERR(xip_mem))) {
686 + if (PTR_ERR(xip_mem) == -ENODATA) {
687 + /* sparse */
688 + zero = 1;
689 + } else {
690 + error = PTR_ERR(xip_mem);
691 + goto out;
692 + }
693 + }
694 + /*
695 + * Ok, we have the mem, so now we can copy it to user space...
696 + *
697 + * The actor routine returns how many bytes were actually used..
698 + * NOTE! This may not be the same as how much of a user buffer
699 + * we filled up (we may be padding etc), so we can only update
700 + * "pos" here (the actor routine has to update the user buffer
701 + * pointers and the remaining count).
702 + */
703 + if (!zero)
704 + left =
705 + __copy_to_user(buf + copied, xip_mem + offset, nr);
706 + else
707 + left = __clear_user(buf + copied, nr);
708 +
709 + if (left) {
710 + error = -EFAULT;
711 + goto out;
712 + }
713 +
714 + copied += (nr - left);
715 + offset += (nr - left);
716 + index += offset >> PAGE_CACHE_SHIFT;
717 + offset &= ~PAGE_CACHE_MASK;
718 + } while (copied < len);
719 +
720 +out:
721 + *ppos = pos + copied;
722 + if (filp)
723 + file_accessed(filp);
724 +
725 + return (copied ? copied : error);
726 +}
727 +#endif
728 +
729 +/******************************************************************************
730 + *
731 + * axfs_file_read
732 + *
733 + * Description: axfs_file_read is mapped into the file_operations vector for
734 + * all axfs files. It loops through the pages to be read and calls
735 + * either do_sync_read (if the page is a compressed one) or
736 + * xip_file_read (if the page is XIP).
737 + *
738 + * Parameters:
739 + * (IN) filp - file to be read
740 + *
741 + * (OUT) buf - user buffer that is filled with the data that we read.
742 + *
743 + * (IN) len - length of file to be read
744 + *
745 + * (IN) ppos - offset within the file to read from
746 + *
747 + * Returns:
748 + * actual size of data read.
749 + *
750 + *****************************************************************************/
751 +static ssize_t axfs_file_read(struct file *filp, char __user *buf, size_t len,
752 + loff_t *ppos)
753 +{
754 + struct inode *inode = filp->f_dentry->d_inode;
755 + struct super_block *sb = inode->i_sb;
756 + struct axfs_super *sbi = AXFS_SB(sb);
757 + size_t read = 0, total_read = 0;
758 + size_t readlength, actual_size, file_size, remaining;
759 + u64 ino_number = inode->i_ino;
760 + u64 size, array_index;
761 +
762 + file_size = AXFS_GET_INODE_FILE_SIZE(sbi, ino_number);
763 + remaining = file_size - *ppos;
764 + actual_size = len > remaining ? remaining : len;
765 + readlength = actual_size < PAGE_SIZE ? actual_size : PAGE_SIZE;
766 +
767 + for (size = actual_size; size > 0; size -= read) {
768 + array_index = AXFS_GET_INODE_ARRAY_INDEX(sbi, ino_number);
769 + array_index += *ppos >> PAGE_SHIFT;
770 +
771 + if (AXFS_IS_NODE_XIP(sbi, array_index)) {
772 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
773 + read = xip_file_read(filp, buf, readlength, ppos);
774 +#else
775 + read = axfs_xip_file_read(filp, buf, readlength, ppos);
776 +#endif
777 + } else {
778 + read = do_sync_read(filp, buf, readlength, ppos);
779 + }
780 + buf += read;
781 + total_read += read;
782 +
783 + if ((len - total_read < PAGE_SIZE) && (total_read != len))
784 + readlength = len - total_read;
785 + }
786 +
787 + return total_read;
788 +}
789 +
790 +static int axfs_readpage(struct file *file, struct page *page)
791 +{
792 + struct inode *inode = page->mapping->host;
793 + struct super_block *sb = inode->i_sb;
794 + struct axfs_super *sbi = AXFS_SB(sb);
795 + u64 array_index, node_index, cnode_index, maxblock, ofs;
796 + u64 ino_number = inode->i_ino;
797 + u32 max_len, cnode_offset;
798 + u32 cblk_size = sbi->cblock_size;
799 + u32 len = 0;
800 + u8 node_type;
801 + void *pgdata;
802 + void *src;
803 + void *cblk0 = sbi->cblock_buffer[0];
804 + void *cblk1 = sbi->cblock_buffer[1];
805 +
806 + maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
807 + pgdata = kmap(page);
808 +
809 + if (page->index >= maxblock)
810 + goto out;
811 +
812 + array_index = AXFS_GET_INODE_ARRAY_INDEX(sbi, ino_number);
813 + array_index += page->index;
814 +
815 + node_index = AXFS_GET_NODE_INDEX(sbi, array_index);
816 + node_type = AXFS_GET_NODE_TYPE(sbi, array_index);
817 +
818 + if (node_type == Compressed) {
819 + /* node is in compessed region */
820 + cnode_offset = AXFS_GET_CNODE_OFFSET(sbi, node_index);
821 + cnode_index = AXFS_GET_CNODE_INDEX(sbi, node_index);
822 + down_write(&sbi->lock);
823 + if (cnode_index != sbi->current_cnode_index) {
824 + /* uncompress only necessary if different cblock */
825 + ofs = AXFS_GET_CBLOCK_OFFSET(sbi, cnode_index);
826 + len = AXFS_GET_CBLOCK_OFFSET(sbi, cnode_index + 1);
827 + len -= ofs;
828 + axfs_copy_data(sb, cblk1, &(sbi->compressed), ofs, len);
829 + axfs_uncompress_block(cblk0, cblk_size, cblk1, len);
830 + sbi->current_cnode_index = cnode_index;
831 + }
832 + downgrade_write(&sbi->lock);
833 + max_len = cblk_size - cnode_offset;
834 + len = max_len > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : max_len;
835 + src = (void *)((unsigned long)cblk0 + cnode_offset);
836 + memcpy(pgdata, src, len);
837 + up_read(&sbi->lock);
838 + } else if (node_type == Byte_Aligned) {
839 + /* node is in BA region */
840 + ofs = AXFS_GET_BANODE_OFFSET(sbi, node_index);
841 + max_len = sbi->byte_aligned.size - ofs;
842 + len = max_len > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : max_len;
843 + axfs_copy_data(sb, pgdata, &(sbi->byte_aligned), ofs, len);
844 + } else {
845 + /* node is XIP */
846 + ofs = node_index << PAGE_SHIFT;
847 + len = PAGE_CACHE_SIZE;
848 + axfs_copy_data(sb, pgdata, &(sbi->xip), ofs, len);
849 + }
850 +
851 +out:
852 + memset(pgdata + len, 0, PAGE_CACHE_SIZE - len);
853 + kunmap(page);
854 + flush_dcache_page(page);
855 + SetPageUptodate(page);
856 + unlock_page(page);
857 + return 0;
858 +}
859 +
860 +static int axfs_get_xip_mem(struct address_space *mapping, pgoff_t offset,
861 + int create, void **kaddr, unsigned long *pfn)
862 +{
863 + struct inode *inode = mapping->host;
864 + struct super_block *sb = inode->i_sb;
865 + struct axfs_super *sbi = AXFS_SB(sb);
866 + u64 ino_number = inode->i_ino;
867 + u64 ino_index, node_index;
868 +
869 + ino_index = AXFS_GET_INODE_ARRAY_INDEX(sbi, ino_number);
870 + ino_index += offset;
871 +
872 + node_index = AXFS_GET_NODE_INDEX(sbi, ino_index);
873 +
874 + *kaddr = (void *)(sbi->xip.virt_addr + (node_index << PAGE_SHIFT));
875 + if (AXFS_PHYSADDR_IS_VALID(sbi)) {
876 + *pfn = (AXFS_GET_XIP_REGION_PHYSADDR(sbi) >> PAGE_SHIFT);
877 + *pfn += node_index;
878 + } else {
879 + *pfn = page_to_pfn(virt_to_page((unsigned long)*kaddr));
880 + }
881 +
882 + return 0;
883 +}
884 +
885 +#ifdef VM_MIXEDMAP
886 +#else
887 +
888 +struct page *axfs_get_xip_page(struct address_space *mapping, sector_t offset,
889 + int create)
890 +{
891 + unsigned long pfn;
892 + void *kaddr;
893 +
894 + axfs_get_xip_mem(mapping, offset * 512, create, &kaddr, &pfn);
895 +
896 + return virt_to_page(kaddr);
897 +}
898 +#endif
899 diff -Naur linux-2.6.24/fs/axfs/axfs_mtd.c linux-2.6.24-axfs/fs/axfs/axfs_mtd.c
900 --- linux-2.6.24/fs/axfs/axfs_mtd.c 1970-01-01 01:00:00.000000000 +0100
901 +++ linux-2.6.24-axfs/fs/axfs/axfs_mtd.c 2008-08-24 19:12:32.000000000 +0200
902 @@ -0,0 +1,506 @@
903 +/*
904 + * Advanced XIP File System for Linux - AXFS
905 + * Readonly, compressed, and XIP filesystem for Linux systems big and small
906 + *
907 + * Copyright(c) 2008 Numonyx
908 + *
909 + * This program is free software; you can redistribute it and/or modify it
910 + * under the terms and conditions of the GNU General Public License,
911 + * version 2, as published by the Free Software Foundation.
912 + *
913 + * Authors:
914 + * Jared Hulbert <jaredeh@gmail.com>
915 + *
916 + * Project url: http://axfs.sourceforge.net
917 + *
918 + * axfs_mtd.c -
919 + * Allows axfs to use mtd devices or has dummy functions if mtd
920 + * device support is compiled out of the kernel.
921 + */
922 +
923 +#include <linux/axfs.h>
924 +#include <linux/fs.h>
925 +#include <linux/mount.h>
926 +#include <linux/ctype.h>
927 +#include <linux/namei.h>
928 +
929 +#ifdef CONFIG_MTD
930 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
931 +#include <linux/mtd/super.h>
932 +#else
933 +#include <linux/mtd/mtd.h>
934 +#endif
935 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
936 +#else
937 +#define OLD_POINT 1
938 +#endif
939 +
940 +int axfs_fill_super(struct super_block *, void *, int);
941 +
942 +static struct mtd_info *axfs_get_mtd_device(int mtdnr)
943 +{
944 + struct mtd_info *device;
945 +
946 + device = get_mtd_device(NULL, mtdnr);
947 +
948 + if (!PTR_ERR(device))
949 + return NULL;
950 +
951 + return device;
952 +}
953 +
954 +int axfs_is_dev_mtd(char *path, int *mtdnr)
955 +{
956 + char *off = NULL;
957 + char *endptr = NULL;
958 + char dev[] = "/dev/\0";
959 + char mtd[] = "mtd\0";
960 + char mtdblk[] = "mtdblock\0";
961 +
962 + if (!path || !*path)
963 + return FALSE;
964 +
965 + off = path;
966 +
967 + if (strncmp(dev, off, strlen(dev)) == 0)
968 + off += strlen(dev);
969 +
970 + if (!strncmp(mtd, off, strlen(mtd)) && isdigit(off[strlen(mtd)]))
971 + off += strlen(mtd);
972 +
973 + if (!strncmp(mtdblk, off, strlen(mtdblk))
974 + && isdigit(off[strlen(mtdblk)]))
975 + off += strlen(mtdblk);
976 +
977 + *mtdnr = simple_strtoul(off, &endptr, 0);
978 +
979 + if (!*endptr)
980 + return TRUE;
981 +
982 + return FALSE;
983 +}
984 +
985 +static struct mtd_info *axfs_get_mtd_info(struct super_block *sb, u64 fsoffset)
986 +{
987 + struct axfs_super *sbi = AXFS_SB(sb);
988 +
989 + if (fsoffset == 0)
990 + return (struct mtd_info *)AXFS_MTD0(sb);
991 +
992 + if (fsoffset < sbi->mmap_size)
993 + return (struct mtd_info *)AXFS_MTD0(sb);
994 +
995 + if (AXFS_MTD1(sb) != NULL)
996 + return (struct mtd_info *)AXFS_MTD1(sb);
997 +
998 + return (struct mtd_info *)AXFS_MTD0(sb);
999 +}
1000 +
1001 +int axfs_copy_mtd(struct super_block *sb, void *dst, u64 fsoffset, u64 len)
1002 +{
1003 + struct axfs_super *sbi = AXFS_SB(sb);
1004 + u64 offset = AXFS_FSOFFSET_2_DEVOFFSET(sbi, fsoffset);
1005 + struct mtd_info *mtd;
1006 + u_char *mtdbuf = (u_char *) dst;
1007 + size_t retlen;
1008 + int err;
1009 +
1010 + if (len == 0)
1011 + return 0;
1012 +
1013 + mtd = axfs_get_mtd_info(sb, fsoffset);
1014 + err = mtd->read(mtd, (loff_t) offset, (size_t) len, &retlen, mtdbuf);
1015 +
1016 + if (len != retlen)
1017 + return -EIO;
1018 +
1019 + return err;
1020 +}
1021 +
1022 +/******************************************************************************
1023 + *
1024 + * axfs_map_mtd
1025 + *
1026 + * Description: When provided, uses the mtd point() capability to map allow
1027 + * axfs a direct memory access to the filesystem.
1028 + *
1029 + * Parameters:
1030 + * (IN) sb - pointer to the super_block structure
1031 + *
1032 + * Returns:
1033 + * 0 or error number
1034 + *
1035 + *****************************************************************************/
1036 +int axfs_map_mtd(struct super_block *sb)
1037 +{
1038 + struct axfs_super *sbi = AXFS_SB(sb);
1039 + struct mtd_info *mtd = (struct mtd_info *)AXFS_MTD0(sb);
1040 + size_t retlen;
1041 + int err = 0;
1042 +#ifndef OLD_POINT
1043 + void *virt;
1044 + resource_size_t phys;
1045 +#else
1046 + u_char *virt;
1047 +#endif
1048 +
1049 + if (!mtd->point || !mtd->unpoint)
1050 + return 0;
1051 +
1052 +#ifndef OLD_POINT
1053 + err = mtd->point(mtd, 0, sbi->mmap_size, &retlen, &virt, &phys);
1054 +#else
1055 + err = mtd->point(mtd, 0, sbi->mmap_size, &retlen, &virt);
1056 +#endif
1057 + if (err)
1058 + return err;
1059 +
1060 + if (retlen != sbi->mmap_size) {
1061 +#ifndef OLD_POINT
1062 + mtd->unpoint(mtd, 0, retlen);
1063 +#else
1064 + mtd->unpoint(mtd, 0, 0, retlen);
1065 +#endif
1066 + return -EINVAL;
1067 + }
1068 +
1069 + sbi->virt_start_addr = (unsigned long)virt;
1070 +#ifndef OLD_POINT
1071 + sbi->phys_start_addr = (unsigned long)phys;
1072 +#else
1073 + sbi->phys_start_addr = 0;
1074 +#endif
1075 + sbi->mtd_pointed = TRUE;
1076 +
1077 + return 0;
1078 +}
1079 +
1080 +void axfs_unmap_mtd(struct super_block *sb)
1081 +{
1082 + struct axfs_super *sbi = AXFS_SB(sb);
1083 + struct mtd_info *mtd = (struct mtd_info *)AXFS_MTD0(sb);
1084 +
1085 + if (!sbi)
1086 + return;
1087 +
1088 + if (AXFS_MTD1(sb))
1089 + put_mtd_device((struct mtd_info *)AXFS_MTD1(sb));
1090 +
1091 + if (AXFS_IS_POINTED(sbi)) {
1092 +#ifndef OLD_POINT
1093 + mtd->unpoint(mtd, 0, sbi->mmap_size);
1094 +#else
1095 + mtd->unpoint(mtd, 0, 0, sbi->mmap_size);
1096 +#endif
1097 + } else {
1098 + if (AXFS_MTD0(sb))
1099 + put_mtd_device((struct mtd_info *)AXFS_MTD0(sb));
1100 + }
1101 +}
1102 +
1103 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
1104 +#else
1105 +/* -------------------- START COPY FROM 2.6.22 -------------------------- */
1106 +/* MTD-based superblock management
1107 + *
1108 + * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved.
1109 + * Written by: David Howells <dhowells@redhat.com>
1110 + * David Woodhouse <dwmw2@infradead.org>
1111 + *
1112 + * This program is free software; you can redistribute it and/or
1113 + * modify it under the terms of the GNU General Public License
1114 + * as published by the Free Software Foundation; either version
1115 + * 2 of the License, or (at your option) any later version.
1116 + */
1117 +
1118 +/*
1119 + * compare superblocks to see if they're equivalent
1120 + * - they are if the underlying MTD device is the same
1121 + */
1122 +static int get_sb_mtd_compare(struct super_block *sb, void *_mtd)
1123 +{
1124 + struct mtd_info *mtd = _mtd;
1125 + struct mtd_info *s_mtd = (struct mtd_info *)AXFS_MTD0(sb);
1126 +
1127 + if (s_mtd == mtd) {
1128 + DEBUG(2, "MTDSB: Match on device %d (\"%s\")\n",
1129 + mtd->index, mtd->name);
1130 + return 1;
1131 + }
1132 +
1133 + DEBUG(2, "MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
1134 + s_mtd->index, s_mtd->name, mtd->index, mtd->name);
1135 + return 0;
1136 +}
1137 +
1138 +/*
1139 + * mark the superblock by the MTD device it is using
1140 + * - set the device number to be the correct MTD block device for pesuperstence
1141 + * of NFS exports
1142 + */
1143 +static int get_sb_mtd_set(struct super_block *sb, void *_mtd)
1144 +{
1145 + struct mtd_info *mtd = _mtd;
1146 + struct mtd_info *s_mtd = (struct mtd_info *)AXFS_MTD0(sb);
1147 +
1148 + s_mtd = mtd;
1149 + sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
1150 + return 0;
1151 +}
1152 +
1153 +/* Lifted wholesale from 2.6.22 */
1154 +int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
1155 +{
1156 + mnt->mnt_sb = sb;
1157 + mnt->mnt_root = dget(sb->s_root);
1158 + return 0;
1159 +}
1160 +
1161 +/*
1162 + * get a superblock on an MTD-backed filesystem
1163 + */
1164 +static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags,
1165 + const char *dev_name, void *data,
1166 + struct mtd_info *mtd,
1167 + int (*fill_super) (struct super_block *, void *, int),
1168 + struct vfsmount *mnt)
1169 +{
1170 + struct super_block *sb;
1171 + int ret;
1172 +
1173 + sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, mtd);
1174 + if (IS_ERR(sb))
1175 + goto out_error;
1176 +
1177 + if (sb->s_root)
1178 + goto already_mounted;
1179 +
1180 + /* fresh new superblock */
1181 + DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n",
1182 + mtd->index, mtd->name);
1183 +
1184 + ret = fill_super(sb, data, 0);
1185 + if (ret < 0) {
1186 + up_write(&sb->s_umount);
1187 + deactivate_super(sb);
1188 + return ret;
1189 + }
1190 +
1191 + /* go */
1192 + sb->s_flags |= MS_ACTIVE;
1193 + return simple_set_mnt(mnt, sb);
1194 +
1195 + /* new mountpoint for an already mounted superblock */
1196 + already_mounted:
1197 + DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n",
1198 + mtd->index, mtd->name);
1199 + ret = simple_set_mnt(mnt, sb);
1200 + goto out_put;
1201 +
1202 + out_error:
1203 + ret = PTR_ERR(sb);
1204 + out_put:
1205 + put_mtd_device(mtd);
1206 + return ret;
1207 +}
1208 +
1209 +/*
1210 + * get a superblock on an MTD-backed filesystem by MTD device number
1211 + */
1212 +static int get_sb_mtd_nr(struct file_system_type *fs_type, int flags,
1213 + const char *dev_name, void *data, int mtdnr,
1214 + int (*fill_super) (struct super_block *, void *, int),
1215 + struct vfsmount *mnt)
1216 +{
1217 + struct mtd_info *mtd;
1218 +
1219 + mtd = get_mtd_device(NULL, mtdnr);
1220 + if (IS_ERR(mtd)) {
1221 + DEBUG(0, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
1222 + return PTR_ERR(mtd);
1223 + }
1224 +
1225 + return get_sb_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super,
1226 + mnt);
1227 +}
1228 +
1229 +/*
1230 + * set up an MTD-based superblock
1231 + */
1232 +static int get_sb_mtd(struct file_system_type *fs_type, int flags,
1233 + const char *dev_name, void *data,
1234 + int (*fill_super) (struct super_block *, void *, int),
1235 + struct vfsmount *mnt)
1236 +{
1237 + struct nameidata nd;
1238 + int mtdnr, ret;
1239 +
1240 + if (!dev_name)
1241 + return -EINVAL;
1242 +
1243 + DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name);
1244 +
1245 + /* the preferred way of mounting in future; especially when
1246 + * CONFIG_BLOCK=n - we specify the underlying MTD device by number or
1247 + * by name, so that we don't require block device support to be present
1248 + * in the kernel. */
1249 + if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
1250 + if (dev_name[3] == ':') {
1251 + struct mtd_info *mtd;
1252 +
1253 + /* mount by MTD device name */
1254 + DEBUG(1, "MTDSB: mtd:%%s, name \"%s\"\n", dev_name + 4);
1255 +
1256 + for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
1257 + mtd = get_mtd_device(NULL, mtdnr);
1258 + if (!IS_ERR(mtd)) {
1259 + if (!strcmp(mtd->name, dev_name + 4))
1260 + return get_sb_mtd_aux(fs_type,
1261 + flags,
1262 + dev_name,
1263 + data, mtd,
1264 + fill_super,
1265 + mnt);
1266 +
1267 + put_mtd_device(mtd);
1268 + }
1269 + }
1270 +
1271 + printk(KERN_NOTICE "MTD:"
1272 + " MTD device with name \"%s\" not found.\n",
1273 + dev_name + 4);
1274 +
1275 + } else if (isdigit(dev_name[3])) {
1276 + /* mount by MTD device number name */
1277 + char *endptr;
1278 +
1279 + mtdnr = simple_strtoul(dev_name + 3, &endptr, 0);
1280 + if (!*endptr) {
1281 + /* It was a valid number */
1282 + DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n", mtdnr);
1283 + return get_sb_mtd_nr(fs_type, flags,
1284 + dev_name, data,
1285 + mtdnr, fill_super, mnt);
1286 + }
1287 + }
1288 + }
1289 +
1290 + /* try the old way - the hack where we allowed users to mount
1291 + * /dev/mtdblock$(n) but didn't actually _use_ the blockdev
1292 + */
1293 + ret = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
1294 +
1295 + DEBUG(1, "MTDSB: path_lookup() returned %d, inode %p\n",
1296 + ret, nd.dentry ? nd.dentry->d_inode : NULL);
1297 +
1298 + if (ret)
1299 + return ret;
1300 +
1301 + ret = -EINVAL;
1302 +
1303 + if (!S_ISBLK(nd.dentry->d_inode->i_mode))
1304 + goto out;
1305 +
1306 + if (nd.mnt->mnt_flags & MNT_NODEV) {
1307 + ret = -EACCES;
1308 + goto out;
1309 + }
1310 +
1311 + if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR)
1312 + goto not_an_MTD_device;
1313 +
1314 + mtdnr = iminor(nd.dentry->d_inode);
1315 + path_release(&nd);
1316 +
1317 + return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super,
1318 + mnt);
1319 +
1320 + not_an_MTD_device:
1321 + printk(KERN_NOTICE
1322 + "MTD: Attempt to mount non-MTD device \"%s\"\n", dev_name);
1323 + out:
1324 + path_release(&nd);
1325 + return ret;
1326 +
1327 +}
1328 +
1329 +/*
1330 + * destroy an MTD-based superblock
1331 + */
1332 +static void kill_mtd_super(struct super_block *sb)
1333 +{
1334 + struct mtd_info *s_mtd = (struct mtd_info *)AXFS_MTD0(sb);
1335 + generic_shutdown_super(sb);
1336 + put_mtd_device(s_mtd);
1337 + AXFS_MTD0(sb) = NULL;
1338 +}
1339 +
1340 +/* ---------------------- END COPY --------------------------------------*/
1341 +#endif
1342 +
1343 +int axfs_get_sb_mtd(struct file_system_type *fs_type, int flags,
1344 + const char *dev_name, struct axfs_super *sbi,
1345 + struct vfsmount *mnt, int *err)
1346 +{
1347 + int nflags, mtdnr;
1348 +
1349 + if (axfs_is_dev_mtd(sbi->second_dev, &mtdnr)) {
1350 + sbi->mtd1 = (void *)axfs_get_mtd_device(mtdnr);
1351 + if (!sbi->mtd1) {
1352 + *err = -EINVAL;
1353 + return FALSE;
1354 + }
1355 + }
1356 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
1357 + nflags = flags & MS_SILENT;
1358 +#else
1359 + nflags = flags;
1360 +#endif
1361 +
1362 + *err = get_sb_mtd(fs_type, nflags, dev_name, sbi, axfs_fill_super, mnt);
1363 + if (*err)
1364 + return FALSE;
1365 +
1366 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
1367 + sbi->mtd0 = mnt->mnt_sb->s_mtd;
1368 +#endif
1369 + return TRUE;
1370 +}
1371 +
1372 +void axfs_kill_mtd_super(struct super_block *sb)
1373 +{
1374 + kill_mtd_super(sb);
1375 +}
1376 +#else
1377 +
1378 +int axfs_map_mtd(struct super_block *sb)
1379 +{
1380 + return 0;
1381 +}
1382 +
1383 +void axfs_unmap_mtd(struct super_block *sb)
1384 +{
1385 +}
1386 +
1387 +int axfs_copy_mtd(struct super_block *sb, void *dst, u64 fsoffset, u64 len)
1388 +{
1389 + return -EINVAL;
1390 +}
1391 +
1392 +int axfs_get_sb_mtd(struct file_system_type *fs_type, int flags,
1393 + const char *dev_name, char *second_dev,
1394 + struct axfs_super *sbi, struct vfsmount *mnt, int *err)
1395 +{
1396 + return FALSE;
1397 +}
1398 +
1399 +int axfs_is_dev_mtd(char *path, int *mtdnr)
1400 +{
1401 + return FALSE;
1402 +}
1403 +
1404 +void axfs_kill_mtd_super(struct super_block *sb)
1405 +{
1406 +}
1407 +
1408 +#endif /* CONFIG_MTD */
1409 diff -Naur linux-2.6.24/fs/axfs/axfs_physmem.c linux-2.6.24-axfs/fs/axfs/axfs_physmem.c
1410 --- linux-2.6.24/fs/axfs/axfs_physmem.c 1970-01-01 01:00:00.000000000 +0100
1411 +++ linux-2.6.24-axfs/fs/axfs/axfs_physmem.c 2008-08-24 19:12:32.000000000 +0200
1412 @@ -0,0 +1,69 @@
1413 +/*
1414 + * Advanced XIP File System for Linux - AXFS
1415 + * Readonly, compressed, and XIP filesystem for Linux systems big and small
1416 + *
1417 + * Copyright(c) 2008 Numonyx
1418 + *
1419 + * This program is free software; you can redistribute it and/or modify it
1420 + * under the terms and conditions of the GNU General Public License,
1421 + * version 2, as published by the Free Software Foundation.
1422 + *
1423 + * Authors:
1424 + * Jared Hulbert <jaredeh@gmail.com>
1425 + *
1426 + * Project url: http://axfs.sourceforge.net
1427 + *
1428 + * axfs_physmem.c -
1429 + * Allows axfs to use striaght memory or has dummy functions if
1430 + * this is a UML system.
1431 + */
1432 +
1433 +#include <linux/axfs.h>
1434 +#include <linux/fs.h>
1435 +#ifdef CONFIG_UML
1436 +
1437 +void axfs_map_physmem(struct axfs_super *sbi, unsigned long size)
1438 +{
1439 +}
1440 +
1441 +void axfs_unmap_physmem(struct super_block *sb)
1442 +{
1443 +}
1444 +
1445 +#else
1446 +#include <asm/io.h>
1447 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
1448 +#else
1449 +#include <asm/pgtable.h>
1450 +#endif
1451 +
1452 +#ifdef ioremap_cached
1453 +#define AXFS_REMAP(a,b) (void __force *)ioremap_cached((a),(b))
1454 +#else
1455 +#define AXFS_REMAP(a,b) (void __force *)ioremap((a),(b))
1456 +#endif /* ioremap_cached */
1457 +
1458 +void axfs_map_physmem(struct axfs_super *sbi, unsigned long size)
1459 +{
1460 + void *addr;
1461 +
1462 + if (AXFS_IS_PHYSMEM(sbi)) {
1463 + addr = AXFS_REMAP(sbi->phys_start_addr, size);
1464 + sbi->virt_start_addr = (unsigned long)addr;
1465 + }
1466 +}
1467 +
1468 +void axfs_unmap_physmem(struct super_block *sb)
1469 +{
1470 + struct axfs_super *sbi = AXFS_SB(sb);
1471 +
1472 + if (!sbi)
1473 + return;
1474 +
1475 + if (AXFS_IS_PHYSMEM(sbi) && AXFS_VIRTADDR_IS_VALID(sbi)) {
1476 + iounmap((void *)(sbi->virt_start_addr));
1477 + sbi->virt_start_addr = 0;
1478 + }
1479 +}
1480 +
1481 +#endif /* CONFIG_UML */
1482 diff -Naur linux-2.6.24/fs/axfs/axfs_profiling.c linux-2.6.24-axfs/fs/axfs/axfs_profiling.c
1483 --- linux-2.6.24/fs/axfs/axfs_profiling.c 1970-01-01 01:00:00.000000000 +0100
1484 +++ linux-2.6.24-axfs/fs/axfs/axfs_profiling.c 2008-08-24 19:12:32.000000000 +0200
1485 @@ -0,0 +1,602 @@
1486 +/*
1487 + * Advanced XIP File System for Linux - AXFS
1488 + * Readonly, compressed, and XIP filesystem for Linux systems big and small
1489 + *
1490 + * Copyright(c) 2008 Numonyx
1491 + *
1492 + * This program is free software; you can redistribute it and/or modify it
1493 + * under the terms and conditions of the GNU General Public License,
1494 + * version 2, as published by the Free Software Foundation.
1495 + *
1496 + * Authors:
1497 + * Eric Anderson
1498 + * Jared Hulbert <jaredeh@gmail.com>
1499 + * Sujaya Srinivasan
1500 + * Justin Treon
1501 + *
1502 + * More info and current contacts at http://axfs.sourceforge.net
1503 + *
1504 + * axfs_profiling.c -
1505 + * Tracks pages of files that enter the page cache. Outputs through a proc
1506 + * file which generates a comma separated data file with path, page offset,
1507 + * count of times entered page cache.
1508 + */
1509 +
1510 +#include <linux/axfs.h>
1511 +#ifdef CONFIG_AXFS_PROFILING
1512 +#include <linux/module.h>
1513 +#include <linux/vmalloc.h>
1514 +#include <linux/proc_fs.h>
1515 +
1516 +#define AXFS_PROC_DIR_NAME "axfs"
1517 +
1518 +struct axfs_profiling_manager {
1519 + struct axfs_profiling_data *profiling_data;
1520 + struct axfs_super *sbi;
1521 + u32 *dir_structure;
1522 + u32 size;
1523 +};
1524 +
1525 +#define MAX_STRING_LEN 1024
1526 +
1527 +/* Handles for our Directory and File */
1528 +static struct proc_dir_entry *axfs_proc_dir;
1529 +static u32 proc_name_inc;
1530 +
1531 +/******************************************************************************
1532 + *
1533 + * axfs_init_profile_dir_structure
1534 + *
1535 + * Description:
1536 + * Creates the structures for tracking the page usage data and creates the
1537 + * proc file that will be used to get the data.
1538 + *
1539 + * Parameters:
1540 + * (IN) manager - pointer to the profile manager for the filing system
1541 + *
1542 + * (IN) num_inodes - number of files in the system
1543 + *
1544 + * Returns:
1545 + * 0
1546 + *
1547 + *****************************************************************************/
1548 +static int axfs_init_profile_dir_structure(struct axfs_profiling_manager
1549 + *manager, u32 num_inodes)
1550 +{
1551 +
1552 + struct axfs_super *sbi = (struct axfs_super *)manager->sbi;
1553 + u32 child_index = 0, i, j;
1554 + u32 *dir_structure = manager->dir_structure;
1555 +
1556 + /* loop through each inode in the image and find all
1557 + of the directories and mark their children */
1558 + for (i = 0; i < num_inodes; i++) {
1559 + /* determine if the entry is a directory */
1560 + if (!S_ISDIR(AXFS_GET_MODE(sbi, i)))
1561 + continue;
1562 +
1563 + /* get the index number for this directory */
1564 + child_index = AXFS_GET_INODE_ARRAY_INDEX(sbi, i);
1565 +
1566 + /* get the offset to its children */
1567 + for (j = 0; j < AXFS_GET_INODE_NUM_ENTRIES(sbi, i); j++) {
1568 + if (dir_structure[child_index + j] != 0) {
1569 + printk(KERN_ERR
1570 + "axfs: ERROR inode was already set old "
1571 + "%lu new %lu\n", (unsigned long)
1572 + dir_structure[child_index + j],
1573 + (unsigned long)i);
1574 + }
1575 + dir_structure[child_index + j] = i;
1576 + }
1577 + }
1578 +
1579 + return 0;
1580 +}
1581 +
1582 +/******************************************************************************
1583 + *
1584 + * axfs_get_directory_path
1585 + *
1586 + * Description:
1587 + * Determines the directory path of every file for printing the spreadsheet.
1588 + *
1589 + * Parameters:
1590 + * (IN) manager - Pointer to axfs profile manager
1591 + *
1592 + * (OUT) buffer - Pointer to the printable directory path for each file
1593 + *
1594 + * (IN) inode_number - Inode number of file to look up
1595 + *
1596 + * Returns:
1597 + * Size of the path to the file
1598 + *
1599 + *
1600 + **************************************************************************/
1601 +static int axfs_get_directory_path(struct axfs_profiling_manager *manager,
1602 + char *buffer, u32 inode_number)
1603 +{
1604 + u32 path_depth = 0;
1605 + u32 path_size = 0;
1606 + u32 string_len = 0;
1607 + u32 index = inode_number;
1608 + u32 dir_number;
1609 + u8 **path_array = NULL;
1610 + struct axfs_super *sbi = (struct axfs_super *)manager->sbi;
1611 + int i;
1612 +
1613 + /* determine how deep the directory path is and how big the name
1614 + string will be walk back until the root directory index is found
1615 + (index 0 is root) */
1616 + while (manager->dir_structure[index] != 0) {
1617 + path_depth++;
1618 + /* set the index to the index of the parent directory */
1619 + index = manager->dir_structure[index];
1620 + }
1621 +
1622 + if (path_depth != 0) {
1623 + /* create an array that will hold a pointer for each of the
1624 + directories names */
1625 + path_array = vmalloc(path_depth * sizeof(*path_array));
1626 + if (path_array == NULL) {
1627 + printk(KERN_DEBUG
1628 + "axfs: directory_path vmalloc failed.\n");
1629 + goto out;
1630 + }
1631 + }
1632 +
1633 + index = manager->dir_structure[inode_number];
1634 + for (i = path_depth; i > 0; i--) {
1635 + /* get the array_index for the directory corresponding to
1636 + index */
1637 + dir_number = AXFS_GET_INODE_ARRAY_INDEX(sbi, index);
1638 +
1639 + /* store a pointer to the name in the array */
1640 + path_array[(i - 1)] = (u8 *) AXFS_GET_INODE_NAME(sbi, index);
1641 +
1642 + index = manager->dir_structure[index];
1643 + }
1644 +
1645 + /* now print out the directory structure from the begining */
1646 + string_len = sprintf(buffer, "./");
1647 + path_size += string_len;
1648 + for (i = 0; i < path_depth; i++) {
1649 + buffer = buffer + string_len;
1650 + string_len = sprintf(buffer, "%s/", (char *)path_array[i]);
1651 + path_size += string_len;
1652 + }
1653 +
1654 + if (path_array != NULL)
1655 + vfree(path_array);
1656 +
1657 +out:
1658 + return path_size;
1659 +
1660 +}
1661 +
1662 +static ssize_t axfs_procfile_read(char *buffer,
1663 + char **buffer_location,
1664 + off_t offset, int buffer_length, int *eof,
1665 + void *data)
1666 +{
1667 + struct axfs_profiling_manager *man;
1668 + struct axfs_profiling_data *profile;
1669 + struct axfs_super *sbi;
1670 + u64 array_index;
1671 + u64 loop_size, inode_page_offset, node_offset, inode_number;
1672 + u64 print_len = 0;
1673 + unsigned long addr;
1674 + int len = 0;
1675 + int i;
1676 + char *buff, *name = NULL;
1677 +
1678 + man = (struct axfs_profiling_manager *)data;
1679 + sbi = man->sbi;
1680 +
1681 + loop_size = man->size / sizeof(*profile);
1682 +
1683 + /* If all data has been returned set EOF */
1684 + if (offset >= loop_size) {
1685 + *eof = 1;
1686 + return 0;
1687 + }
1688 +
1689 + buff = buffer;
1690 + /* print as much as the buffer can take */
1691 + for (i = offset; i < loop_size; i++) {
1692 +
1693 + if ((print_len + MAX_STRING_LEN) > buffer_length)
1694 + break;
1695 + /* get the first profile data structure */
1696 + profile = &(man->profiling_data[i]);
1697 +
1698 + if (profile->count == 0)
1699 + continue;
1700 +
1701 + inode_number = profile->inode_number;
1702 +
1703 + /* file names can be duplicated so we must print out the path */
1704 + len = axfs_get_directory_path(man, buff, inode_number);
1705 +
1706 + print_len += len;
1707 + buff += len;
1708 +
1709 + /* get a pointer to the inode name */
1710 + array_index = AXFS_GET_INODE_ARRAY_INDEX(sbi, inode_number);
1711 + name = (char *)AXFS_GET_INODE_NAME(sbi, inode_number);
1712 +
1713 + /* need to convert the page number in the node area to
1714 + the page number within the file */
1715 + node_offset = i;
1716 + /* gives the offset of the node in the node list area
1717 + then substract that from the */
1718 + inode_page_offset = node_offset - array_index;
1719 +
1720 + /* set everything up to print out */
1721 + addr = (unsigned long)(inode_page_offset * PAGE_SIZE);
1722 + len = sprintf(buff, "%s,%lu,%lu\n", name, addr, profile->count);
1723 +
1724 + print_len += len;
1725 + buff += len;
1726 + }
1727 +
1728 + /* return the number of items printed.
1729 + This will be added to offset and passed back to us */
1730 + *buffer_location = (char *)(i - offset);
1731 +
1732 + return print_len;
1733 +}
1734 +
1735 +static ssize_t axfs_procfile_write(struct file *file,
1736 + const char *buffer, unsigned long count,
1737 + void *data)
1738 +{
1739 + struct axfs_profiling_manager *man_ptr =
1740 + (struct axfs_profiling_manager *)data;
1741 +
1742 + if ((count >= 2) && (0 == memcmp(buffer, "on", 2))) {
1743 + man_ptr->sbi->profiling_on = TRUE;
1744 + } else if ((count >= 3) && (0 == memcmp(buffer, "off", 3))) {
1745 + man_ptr->sbi->profiling_on = FALSE;
1746 + } else if ((count >= 5) && (0 == memcmp(buffer, "clear", 5))) {
1747 + memset(man_ptr->profiling_data, 0, man_ptr->size);
1748 + } else {
1749 + printk(KERN_INFO
1750 + "axfs: Unknown command. Supported options are:\n");
1751 + printk(KERN_INFO "\t\"on\"\tTurn on profiling\n");
1752 + printk(KERN_INFO "\t\"off\"\tTurn off profiling\n");
1753 + printk(KERN_INFO "\t\"clear\"\tClear profiling buffer\n");
1754 + }
1755 +
1756 + return count;
1757 +}
1758 +
1759 +static int axfs_create_proc_directory(void)
1760 +{
1761 + if (axfs_proc_dir == NULL) {
1762 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
1763 + axfs_proc_dir = proc_mkdir(AXFS_PROC_DIR_NAME, NULL);
1764 +#else
1765 + axfs_proc_dir = proc_mkdir(AXFS_PROC_DIR_NAME, &proc_root);
1766 +#endif
1767 + if (!axfs_proc_dir) {
1768 + printk(KERN_WARNING
1769 + "axfs: Failed to create directory\n");
1770 + return FALSE;
1771 + }
1772 + }
1773 + return TRUE;
1774 +}
1775 +
1776 +static void axfs_delete_proc_directory(void)
1777 +{
1778 + /* Determine if there are any directory elements
1779 + and remove if all of the proc files are removed. */
1780 + if (axfs_proc_dir != NULL) {
1781 + if (axfs_proc_dir->subdir == NULL) {
1782 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
1783 + remove_proc_entry(AXFS_PROC_DIR_NAME, NULL);
1784 +#else
1785 + remove_proc_entry(AXFS_PROC_DIR_NAME, &proc_root);
1786 +#endif
1787 + axfs_proc_dir = NULL;
1788 + }
1789 + }
1790 +}
1791 +
1792 +/******************************************************************************
1793 + *
1794 + * axfs_delete_proc_file
1795 + *
1796 + * Description:
1797 + * Will search through the proc directory for the correct proc file,
1798 + * then delete it
1799 + *
1800 + * Parameters:
1801 + * (IN) sbi- axfs superblock pointer to determine which proc file to remove
1802 + *
1803 + * Returns:
1804 + * The profiling manager pointer for the proc file.
1805 + *
1806 + *****************************************************************************/
1807 +static struct axfs_profiling_manager *axfs_delete_proc_file(struct axfs_super
1808 + *sbi)
1809 +{
1810 + struct proc_dir_entry *current_proc_file;
1811 + struct axfs_profiling_manager *manager;
1812 + void *rv = NULL;
1813 +
1814 + if (!axfs_proc_dir)
1815 + return NULL;
1816 +
1817 + /* Walk through the proc file entries to find the matching sbi */
1818 + current_proc_file = axfs_proc_dir->subdir;
1819 +
1820 + while (current_proc_file != NULL) {
1821 + manager = current_proc_file->data;
1822 + if (manager == NULL) {
1823 + printk(KERN_WARNING
1824 + "axfs: Error removing proc file private "
1825 + "data was NULL.\n");
1826 + rv = NULL;
1827 + break;
1828 + }
1829 + if (manager->sbi == sbi) {
1830 + /* we found the match */
1831 + remove_proc_entry(current_proc_file->name,
1832 + axfs_proc_dir);
1833 + rv = (void *)manager;
1834 + break;
1835 + }
1836 + current_proc_file = axfs_proc_dir->next;
1837 + }
1838 + return (struct axfs_profiling_manager *)rv;
1839 +}
1840 +
1841 +/******************************************************************************
1842 + *
1843 + * axfs_register_profiling_proc
1844 + *
1845 + * Description:
1846 + * Will register the instance of the proc file for a given volume.
1847 + *
1848 + * Parameters:
1849 + * (IN) manager - Pointer to the profiling manager for the axfs volume
1850 + *
1851 + * Returns:
1852 + * 0 or error number
1853 + *
1854 + *****************************************************************************/
1855 +static int axfs_register_profiling_proc(struct axfs_profiling_manager *manager)
1856 +{
1857 + int rv = 0;
1858 + struct proc_dir_entry *proc_file;
1859 + char file_name[20];
1860 +
1861 + if (!axfs_create_proc_directory()) {
1862 + rv = -ENOMEM;
1863 + goto out;
1864 + }
1865 +
1866 + sprintf(file_name, "volume%d", proc_name_inc);
1867 + proc_file = create_proc_entry(file_name, (mode_t) 0644, axfs_proc_dir);
1868 + if (proc_file == NULL) {
1869 + remove_proc_entry(file_name, axfs_proc_dir);
1870 + axfs_delete_proc_directory();
1871 + rv = -ENOMEM;
1872 + goto out;
1873 + }
1874 +
1875 + proc_name_inc++;
1876 + proc_file->read_proc = axfs_procfile_read;
1877 + proc_file->write_proc = axfs_procfile_write;
1878 + proc_file->owner = THIS_MODULE;
1879 + proc_file->mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1880 + proc_file->uid = 0;
1881 + proc_file->gid = 0;
1882 + proc_file->data = manager;
1883 +
1884 + printk(KERN_DEBUG "axfs: Proc entry created\n");
1885 +
1886 +out:
1887 + return rv;
1888 +}
1889 +
1890 +/******************************************************************************
1891 + *
1892 + * axfs_unregister_profiling_proc
1893 + *
1894 + * Description:
1895 + * Will unregister the instance of the proc file for the volume that was
1896 + * mounted. If this is the last volume mounted then the proc directory
1897 + * will also be removed.
1898 + *
1899 + * Parameters:
1900 + * (IN) sbi- axfs superblock pointer to determine which proc file to remove
1901 + *
1902 + * Returns:
1903 + * The profiling manager pointer for the proc file.
1904 + *
1905 + *****************************************************************************/
1906 +static struct axfs_profiling_manager *axfs_unregister_profiling_proc(struct
1907 + axfs_super
1908 + *sbi)
1909 +{
1910 + struct axfs_profiling_manager *manager;
1911 + manager = axfs_delete_proc_file(sbi);
1912 + axfs_delete_proc_directory();
1913 + return manager;
1914 +}
1915 +
1916 +/******************************************************************************
1917 + *
1918 + * axfs_init_profiling
1919 + *
1920 + * Description:
1921 + * Creates the structures for tracking the page usage data and creates the
1922 + * proc file that will be used to get the data.
1923 + *
1924 + * Parameters:
1925 + * (IN) sbi- axfs superblock pointer
1926 + *
1927 + * Returns:
1928 + * TRUE or FALSE
1929 + *
1930 + *****************************************************************************/
1931 +int axfs_init_profiling(struct axfs_super *sbi)
1932 +{
1933 +
1934 + u32 num_nodes, num_inodes;
1935 + struct axfs_profiling_manager *manager = NULL;
1936 + struct axfs_profiling_data *profile_data = NULL;
1937 + int err = -ENOMEM;
1938 +
1939 + /* determine the max number of pages in the FS */
1940 + num_nodes = sbi->blocks;
1941 + if (!num_nodes)
1942 + return 0;
1943 +
1944 + manager = vmalloc(sizeof(*manager));
1945 + if (!manager)
1946 + goto out;
1947 +
1948 + profile_data = vmalloc(num_nodes * sizeof(*profile_data));
1949 + if (!profile_data)
1950 + goto out;
1951 +
1952 + memset(profile_data, 0, num_nodes * sizeof(*profile_data));
1953 +
1954 + /* determine the max number of inodes in the FS */
1955 + num_inodes = sbi->files;
1956 +
1957 + manager->dir_structure = vmalloc(num_inodes * sizeof(u32 *));
1958 + if (!manager->dir_structure)
1959 + goto out;
1960 +
1961 + memset(manager->dir_structure, 0, (num_inodes * sizeof(u32 *)));
1962 +
1963 + manager->profiling_data = profile_data;
1964 + manager->size = num_nodes * sizeof(*profile_data);
1965 + manager->sbi = sbi;
1966 + sbi->profiling_on = TRUE; /* Turn on profiling by default */
1967 + sbi->profile_data_ptr = profile_data;
1968 +
1969 + err = axfs_init_profile_dir_structure(manager, num_inodes);
1970 + if (err)
1971 + goto out;
1972 +
1973 + err = axfs_register_profiling_proc(manager);
1974 + if (err)
1975 + goto out;
1976 +
1977 + return 0;
1978 +
1979 +out:
1980 + if (manager->dir_structure)
1981 + vfree(manager->dir_structure);
1982 + if (profile_data)
1983 + vfree(profile_data);
1984 + if (manager)
1985 + vfree(manager);
1986 + return err;
1987 +}
1988 +
1989 +/******************************************************************************
1990 + *
1991 + * axfs_shutdown_profiling
1992 + *
1993 + * Description:
1994 + * Remove the proc file for this volume and release the memory in the
1995 + * profiling manager
1996 + *
1997 + * Parameters:
1998 + * (IN) sbi- axfs superblock pointer
1999 + *
2000 + * Returns:
2001 + * TRUE or FALSE
2002 + *
2003 + *****************************************************************************/
2004 +int axfs_shutdown_profiling(struct axfs_super *sbi)
2005 +{
2006 + struct axfs_profiling_manager *manager;
2007 + /* remove the proc file for this volume and release the memory in the
2008 + profiling manager */
2009 +
2010 + if (!sbi)
2011 + return TRUE;
2012 +
2013 + if (!sbi->profile_data_ptr)
2014 + return TRUE;
2015 +
2016 + manager = axfs_unregister_profiling_proc(sbi);
2017 +
2018 + if (manager == NULL)
2019 + return FALSE;
2020 +
2021 + if (manager->dir_structure)
2022 + vfree(manager->dir_structure);
2023 + if (manager->profiling_data)
2024 + vfree(manager->profiling_data);
2025 + if (manager)
2026 + vfree(manager);
2027 + return TRUE;
2028 +}
2029 +
2030 +/******************************************************************************
2031 + *
2032 + * axfs_profiling_add
2033 + *
2034 + * Description:
2035 + * Log when a node is paged into memory by incrementing the count in the
2036 + * array profile data structure.
2037 + *
2038 + * Parameters:
2039 + * (IN) sbi- axfs superblock pointer
2040 + *
2041 + * (IN) array_index - The offset into the nodes table of file (node number)
2042 + *
2043 + * (IN) axfs_inode_number - Inode of the node to determine file name later
2044 + *
2045 + * Returns:
2046 + * none
2047 + *
2048 + *****************************************************************************/
2049 +void axfs_profiling_add(struct axfs_super *sbi, unsigned long array_index,
2050 + unsigned int axfs_inode_number)
2051 +{
2052 + unsigned long addr;
2053 + struct axfs_profiling_data *profile_data;
2054 +
2055 + if (sbi->profiling_on != TRUE)
2056 + return;
2057 +
2058 + addr = (unsigned long)sbi->profile_data_ptr;
2059 + addr += array_index * sizeof(*profile_data);
2060 +
2061 + profile_data = (struct axfs_profiling_data *)addr;
2062 +
2063 + /* Record the inode number to determine the file name later. */
2064 + profile_data->inode_number = axfs_inode_number;
2065 +
2066 + /* Increment the number of times the node has been paged in */
2067 + profile_data->count++;
2068 +}
2069 +
2070 +#else
2071 +
2072 +int axfs_init_profiling(struct axfs_super *sbi)
2073 +{
2074 + return 0;
2075 +}
2076 +
2077 +int axfs_shutdown_profiling(struct axfs_super *sbi)
2078 +{
2079 + return 0;
2080 +}
2081 +
2082 +void axfs_profiling_add(struct axfs_super *sbi, unsigned long array_index,
2083 + unsigned int axfs_inode_number)
2084 +{
2085 +}
2086 +
2087 +#endif /* CONFIG_AXFS_PROFILING */
2088 diff -Naur linux-2.6.24/fs/axfs/axfs_super.c linux-2.6.24-axfs/fs/axfs/axfs_super.c
2089 --- linux-2.6.24/fs/axfs/axfs_super.c 1970-01-01 01:00:00.000000000 +0100
2090 +++ linux-2.6.24-axfs/fs/axfs/axfs_super.c 2008-08-24 19:12:32.000000000 +0200
2091 @@ -0,0 +1,928 @@
2092 +/*
2093 + * Advanced XIP File System for Linux - AXFS
2094 + * Readonly, compressed, and XIP filesystem for Linux systems big and small
2095 + *
2096 + * Copyright(c) 2008 Numonyx
2097 + *
2098 + * This program is free software; you can redistribute it and/or modify it
2099 + * under the terms and conditions of the GNU General Public License,
2100 + * version 2, as published by the Free Software Foundation.
2101 + *
2102 + * Authors:
2103 + * Eric Anderson
2104 + * Jared Hulbert <jaredeh@gmail.com>
2105 + * Sujaya Srinivasan
2106 + * Justin Treon
2107 + *
2108 + * More info and current contacts at http://axfs.sourceforge.net
2109 + *
2110 + * axfs_super.c -
2111 + * Contains the core code used to mount the fs.
2112 + *
2113 + */
2114 +
2115 +#include <linux/axfs.h>
2116 +#include <linux/fs.h>
2117 +#include <linux/vmalloc.h>
2118 +#include <linux/parser.h>
2119 +#include <linux/statfs.h>
2120 +#include <linux/module.h>
2121 +#include <linux/mount.h>
2122 +#include <linux/mtd/mtd.h>
2123 +
2124 +/******************** Function Declarations ****************************/
2125 +static struct super_operations axfs_sops;
2126 +static struct axfs_super *axfs_get_sbi(void);
2127 +static void axfs_put_sbi(struct axfs_super *);
2128 +/***************** functions in other axfs files ***************************/
2129 +int axfs_get_sb_bdev(struct file_system_type *, int, const char *,
2130 + struct axfs_super *, struct vfsmount *, int *);
2131 +void axfs_kill_block_super(struct super_block *);
2132 +int axfs_copy_block(struct super_block *, void *, u64, u64);
2133 +int axfs_is_dev_bdev(char *);
2134 +#ifndef NO_PHYSMEM
2135 +void axfs_map_physmem(struct axfs_super *, unsigned long);
2136 +void axfs_unmap_physmem(struct super_block *);
2137 +#endif
2138 +int axfs_map_mtd(struct super_block *);
2139 +void axfs_unmap_mtd(struct super_block *);
2140 +int axfs_copy_mtd(struct super_block *, void *, u64, u64);
2141 +int axfs_get_sb_mtd(struct file_system_type *, int, const char *,
2142 + struct axfs_super *, struct vfsmount *, int *);
2143 +int axfs_is_dev_mtd(char *, int *);
2144 +void axfs_kill_mtd_super(struct super_block *);
2145 +struct inode *axfs_create_vfs_inode(struct super_block *, int);
2146 +int axfs_get_uml_address(char *, unsigned long *, unsigned long *);
2147 +int axfs_init_profiling(struct axfs_super *);
2148 +int axfs_shutdown_profiling(struct axfs_super *);
2149 +void axfs_profiling_add(struct axfs_super *, unsigned long, unsigned int);
2150 +struct inode *axfs_create_vfs_inode(struct super_block *, int);
2151 +/******************************************************************************/
2152 +
2153 +static void axfs_free_region(struct axfs_super *sbi,
2154 + struct axfs_region_desc *region)
2155 +{
2156 + if (!region)
2157 + return;
2158 +
2159 + if (AXFS_IS_REGION_XIP(sbi, region))
2160 + return;
2161 +
2162 + if (region->virt_addr)
2163 + vfree(region->virt_addr);
2164 +}
2165 +
2166 +static void axfs_put_sbi(struct axfs_super *sbi)
2167 +{
2168 + if (!sbi)
2169 + return;
2170 +
2171 + axfs_shutdown_profiling(sbi);
2172 +
2173 + axfs_free_region(sbi, &sbi->strings);
2174 + axfs_free_region(sbi, &sbi->xip);
2175 + axfs_free_region(sbi, &sbi->compressed);
2176 + axfs_free_region(sbi, &sbi->byte_aligned);
2177 + axfs_free_region(sbi, &sbi->node_type);
2178 + axfs_free_region(sbi, &sbi->node_index);
2179 + axfs_free_region(sbi, &sbi->cnode_offset);
2180 + axfs_free_region(sbi, &sbi->cnode_index);
2181 + axfs_free_region(sbi, &sbi->banode_offset);
2182 + axfs_free_region(sbi, &sbi->cblock_offset);
2183 + axfs_free_region(sbi, &sbi->inode_file_size);
2184 + axfs_free_region(sbi, &sbi->inode_name_offset);
2185 + axfs_free_region(sbi, &sbi->inode_num_entries);
2186 + axfs_free_region(sbi, &sbi->inode_mode_index);
2187 + axfs_free_region(sbi, &sbi->inode_array_index);
2188 + axfs_free_region(sbi, &sbi->modes);
2189 + axfs_free_region(sbi, &sbi->uids);
2190 + axfs_free_region(sbi, &sbi->gids);
2191 +
2192 + if (sbi->second_dev)
2193 + kfree(sbi->second_dev);
2194 +
2195 + if (sbi->cblock_buffer[0])
2196 + vfree(sbi->cblock_buffer[0]);
2197 + if (sbi->cblock_buffer[1])
2198 + vfree(sbi->cblock_buffer[1]);
2199 +
2200 + kfree(sbi);
2201 +}
2202 +
2203 +static void axfs_put_super(struct super_block *sb)
2204 +{
2205 + axfs_unmap_mtd(sb);
2206 +#ifndef NO_PHYSMEM
2207 + axfs_unmap_physmem(sb);
2208 +#endif
2209 + axfs_put_sbi(AXFS_SB(sb));
2210 + sb->s_fs_info = NULL;
2211 +}
2212 +
2213 +static int axfs_copy_mem(struct super_block *sb, void *buf, u64 fsoffset,
2214 + u64 len)
2215 +{
2216 + struct axfs_super *sbi = AXFS_SB(sb);
2217 + unsigned long addr;
2218 +
2219 + addr = sbi->virt_start_addr + (unsigned long)fsoffset;
2220 + memcpy(buf, (void *)addr, (size_t) len);
2221 + return 0;
2222 +}
2223 +
2224 +static int axfs_copy_metadata(struct super_block *sb, void *buf, u64 fsoffset,
2225 + u64 len)
2226 +{
2227 + struct axfs_super *sbi = AXFS_SB(sb);
2228 + u64 end = fsoffset + len;
2229 + u64 a = sbi->mmap_size - fsoffset;
2230 + u64 b = end - sbi->mmap_size;
2231 + void *bb = (void *)((unsigned long)buf + (unsigned long)a);
2232 + int err;
2233 +
2234 + /* Catches case where sbi is not yet fully initialized. */
2235 + if ((sbi->magic == 0) && (sbi->virt_start_addr != 0))
2236 + return axfs_copy_mem(sb, buf, fsoffset, len);
2237 +
2238 + if (fsoffset < sbi->mmap_size) {
2239 + if (end > sbi->mmap_size) {
2240 + err = axfs_copy_metadata(sb, buf, fsoffset, a);
2241 + if (err)
2242 + return err;
2243 + err = axfs_copy_metadata(sb, bb, sbi->mmap_size, b);
2244 + } else {
2245 + if (AXFS_IS_OFFSET_MMAPABLE(sbi, fsoffset)) {
2246 + err = axfs_copy_mem(sb, buf, fsoffset, len);
2247 + } else if (AXFS_HAS_MTD(sb)) {
2248 + err = axfs_copy_mtd(sb, buf, fsoffset, len);
2249 + } else if (AXFS_HAS_BDEV(sb)) {
2250 + err = axfs_copy_block(sb, buf, fsoffset, len);
2251 + } else {
2252 + err = -EINVAL;
2253 + }
2254 + }
2255 + } else {
2256 + if (AXFS_NODEV(sb)) {
2257 + err = axfs_copy_mem(sb, buf, fsoffset, len);
2258 + } else if (AXFS_HAS_BDEV(sb)) {
2259 + err = axfs_copy_block(sb, buf, fsoffset, len);
2260 + } else if (AXFS_HAS_MTD(sb)) {
2261 + err = axfs_copy_mtd(sb, buf, fsoffset, len);
2262 + } else {
2263 + err = -EINVAL;
2264 + }
2265 + }
2266 + return err;
2267 +}
2268 +
2269 +static int axfs_fill_region_data(struct super_block *sb,
2270 + struct axfs_region_desc *region, int force)
2271 +{
2272 + struct axfs_super *sbi = AXFS_SB(sb);
2273 + unsigned long addr;
2274 + void *buff = NULL;
2275 + void *vaddr;
2276 + int err = -ENOMEM;
2277 + u64 size = region->size;
2278 + u64 fsoffset = region->fsoffset;
2279 + u64 end = fsoffset + size;
2280 + u64 c_size = region->compressed_size;
2281 +
2282 + if (size == 0)
2283 + return 0;
2284 +
2285 + if (AXFS_IS_REGION_INCORE(region))
2286 + goto incore;
2287 +
2288 + if (AXFS_IS_REGION_COMPRESSED(region))
2289 + goto incore;
2290 +
2291 + if (AXFS_IS_REGION_XIP(sbi, region)) {
2292 + if ((end > sbi->mmap_size) && (force))
2293 + goto incore;
2294 + addr = sbi->virt_start_addr;
2295 + addr += (unsigned long)fsoffset;
2296 + region->virt_addr = (void *)addr;
2297 + return 0;
2298 + }
2299 +
2300 + if (force)
2301 + goto incore;
2302 +
2303 + region->virt_addr = NULL;
2304 + return 0;
2305 +
2306 +incore:
2307 + region->virt_addr = vmalloc(size);
2308 + if (!region->virt_addr)
2309 + goto out;
2310 + vaddr = region->virt_addr;
2311 +
2312 + if (AXFS_IS_REGION_COMPRESSED(region)) {
2313 + buff = vmalloc(c_size);
2314 + if (!buff)
2315 + goto out;
2316 + axfs_copy_metadata(sb, buff, fsoffset, c_size);
2317 + err = axfs_uncompress_block(vaddr, size, buff, c_size);
2318 + if (!err)
2319 + goto out;
2320 + vfree(buff);
2321 + } else {
2322 + axfs_copy_metadata(sb, vaddr, fsoffset, size);
2323 + }
2324 +
2325 + return 0;
2326 +
2327 +out:
2328 + if (buff)
2329 + vfree(buff);
2330 + if (region->virt_addr)
2331 + vfree(region->virt_addr);
2332 + return err;
2333 +}
2334 +
2335 +static int axfs_fill_region_data_ptrs(struct super_block *sb)
2336 +{
2337 + int err;
2338 + struct axfs_super *sbi = AXFS_SB(sb);
2339 +
2340 + err = axfs_fill_region_data(sb, &sbi->strings, TRUE);
2341 + if (err)
2342 + goto out;
2343 +
2344 + err = axfs_fill_region_data(sb, &sbi->xip, TRUE);
2345 + if (err)
2346 + goto out;
2347 +
2348 + err = axfs_fill_region_data(sb, &sbi->compressed, FALSE);
2349 + if (err)
2350 + goto out;
2351 +
2352 + err = axfs_fill_region_data(sb, &sbi->byte_aligned, FALSE);
2353 + if (err)
2354 + goto out;
2355 +
2356 + err = axfs_fill_region_data(sb, &sbi->node_type, TRUE);
2357 + if (err)
2358 + goto out;
2359 + err = axfs_fill_region_data(sb, &sbi->node_index, TRUE);
2360 + if (err)
2361 + goto out;
2362 + err = axfs_fill_region_data(sb, &sbi->cnode_offset, TRUE);
2363 + if (err)
2364 + goto out;
2365 + err = axfs_fill_region_data(sb, &sbi->cnode_index, TRUE);
2366 + if (err)
2367 + goto out;
2368 + err = axfs_fill_region_data(sb, &sbi->banode_offset, TRUE);
2369 + if (err)
2370 + goto out;
2371 + err = axfs_fill_region_data(sb, &sbi->cblock_offset, TRUE);
2372 + if (err)
2373 + goto out;
2374 + err = axfs_fill_region_data(sb, &sbi->inode_file_size, TRUE);
2375 + if (err)
2376 + goto out;
2377 + err = axfs_fill_region_data(sb, &sbi->inode_name_offset, TRUE);
2378 + if (err)
2379 + goto out;
2380 + err = axfs_fill_region_data(sb, &sbi->inode_num_entries, TRUE);
2381 + if (err)
2382 + goto out;
2383 + err = axfs_fill_region_data(sb, &sbi->inode_mode_index, TRUE);
2384 + if (err)
2385 + goto out;
2386 + err = axfs_fill_region_data(sb, &sbi->inode_array_index, TRUE);
2387 + if (err)
2388 + goto out;
2389 + err = axfs_fill_region_data(sb, &sbi->modes, TRUE);
2390 + if (err)
2391 + goto out;
2392 + err = axfs_fill_region_data(sb, &sbi->uids, TRUE);
2393 + if (err)
2394 + goto out;
2395 + err = axfs_fill_region_data(sb, &sbi->gids, TRUE);
2396 + if (err)
2397 + goto out;
2398 +
2399 +out:
2400 + return err;
2401 +}
2402 +
2403 +static int axfs_init_cblock_buffers(struct axfs_super *sbi)
2404 +{
2405 + sbi->current_cnode_index = -1;
2406 + sbi->cblock_buffer[0] = vmalloc(sbi->cblock_size);
2407 + sbi->cblock_buffer[1] = vmalloc(sbi->cblock_size);
2408 + if ((!sbi->cblock_buffer[0]) || (!sbi->cblock_buffer[1]))
2409 + return -ENOMEM;
2410 +
2411 + return 0;
2412 +}
2413 +
2414 +static int axfs_fixup_devices(struct super_block *sb)
2415 +{
2416 + struct axfs_super *sbi = AXFS_SB(sb);
2417 + int err = 0;
2418 +
2419 +#ifndef NO_PHYSMEM
2420 + if (AXFS_IS_PHYSMEM(sbi)) {
2421 + axfs_map_physmem(sbi, sbi->mmap_size);
2422 + } else if (AXFS_HAS_MTD(sb)) {
2423 +#else
2424 + if (AXFS_HAS_MTD(sb)) {
2425 +#endif
2426 + err = axfs_map_mtd(sb);
2427 + } else if (AXFS_IS_IOMEM(sbi)) {
2428 + sbi->phys_start_addr = 0;
2429 + }
2430 + return err;
2431 +}
2432 +
2433 +static void axfs_fill_region_desc(struct super_block *sb,
2434 + struct axfs_region_desc_onmedia *out,
2435 + u64 offset_be, struct axfs_region_desc *in)
2436 +{
2437 + u64 offset = be64_to_cpu(offset_be);
2438 +
2439 + axfs_copy_metadata(sb, (void *)out, offset, sizeof(*out));
2440 +
2441 + in->fsoffset = be64_to_cpu(out->fsoffset);
2442 + in->size = be64_to_cpu(out->size);
2443 + in->compressed_size = be64_to_cpu(out->compressed_size);
2444 + in->max_index = be64_to_cpu(out->max_index);
2445 + in->table_byte_depth = out->table_byte_depth;
2446 + in->incore = out->incore;
2447 +}
2448 +
2449 +static int axfs_fill_region_descriptors(struct super_block *sb,
2450 + struct axfs_super_onmedia *sbo)
2451 +{
2452 + struct axfs_super *sbi = AXFS_SB(sb);
2453 + struct axfs_region_desc_onmedia *out;
2454 +
2455 + out = kmalloc(sizeof(*out), GFP_KERNEL);
2456 + if (!out)
2457 + return -ENOMEM;
2458 + memset(out, 0, sizeof(*out));
2459 +
2460 + axfs_fill_region_desc(sb, out, sbo->strings, &sbi->strings);
2461 + axfs_fill_region_desc(sb, out, sbo->xip, &sbi->xip);
2462 + axfs_fill_region_desc(sb, out, sbo->compressed, &sbi->compressed);
2463 + axfs_fill_region_desc(sb, out, sbo->byte_aligned, &sbi->byte_aligned);
2464 + axfs_fill_region_desc(sb, out, sbo->node_type, &sbi->node_type);
2465 + axfs_fill_region_desc(sb, out, sbo->node_index, &sbi->node_index);
2466 + axfs_fill_region_desc(sb, out, sbo->cnode_offset, &sbi->cnode_offset);
2467 + axfs_fill_region_desc(sb, out, sbo->cnode_index, &sbi->cnode_index);
2468 + axfs_fill_region_desc(sb, out, sbo->banode_offset, &sbi->banode_offset);
2469 + axfs_fill_region_desc(sb, out, sbo->cblock_offset, &sbi->cblock_offset);
2470 + axfs_fill_region_desc(sb, out, sbo->inode_file_size,
2471 + &sbi->inode_file_size);
2472 + axfs_fill_region_desc(sb, out, sbo->inode_name_offset,
2473 + &sbi->inode_name_offset);
2474 + axfs_fill_region_desc(sb, out, sbo->inode_num_entries,
2475 + &sbi->inode_num_entries);
2476 + axfs_fill_region_desc(sb, out, sbo->inode_mode_index,
2477 + &sbi->inode_mode_index);
2478 + axfs_fill_region_desc(sb, out, sbo->inode_array_index,
2479 + &sbi->inode_array_index);
2480 + axfs_fill_region_desc(sb, out, sbo->modes, &sbi->modes);
2481 + axfs_fill_region_desc(sb, out, sbo->uids, &sbi->uids);
2482 + axfs_fill_region_desc(sb, out, sbo->gids, &sbi->gids);
2483 +
2484 + kfree(out);
2485 +
2486 + return 0;
2487 +}
2488 +
2489 +int axfs_set_compression_type(struct axfs_super *sbi)
2490 +{
2491 + if (sbi->compression_type != ZLIB)
2492 + return -EINVAL;
2493 +
2494 + return 0;
2495 +}
2496 +
2497 +static int axfs_get_onmedia_super(struct super_block *sb)
2498 +{
2499 + int err;
2500 + struct axfs_super *sbi = AXFS_SB(sb);
2501 + struct axfs_super_onmedia *sbo;
2502 +
2503 + sbo = kmalloc(sizeof(*sbo), GFP_KERNEL);
2504 + if (!sbo)
2505 + return -ENOMEM;
2506 +
2507 +#ifndef NO_PHYSMEM
2508 + axfs_map_physmem(sbi, sizeof(*sbo));
2509 +#endif
2510 + axfs_copy_metadata(sb, (void *)sbo, 0, sizeof(*sbo));
2511 +
2512 + /* Do sanity checks on the superblock */
2513 + if (be32_to_cpu(sbo->magic) != AXFS_MAGIC) {
2514 + printk(KERN_ERR "axfs: wrong magic\n");
2515 + err = -EINVAL;
2516 + goto out;
2517 + }
2518 +
2519 + /* verify the signiture is correct */
2520 + if (strncmp(sbo->signature, AXFS_SIGNATURE, sizeof(AXFS_SIGNATURE))) {
2521 + printk(KERN_ERR "axfs: wrong axfs signature,"
2522 + " read %s, expected %s\n",
2523 + sbo->signature, AXFS_SIGNATURE);
2524 + err = -EINVAL;
2525 + goto out;
2526 + }
2527 +
2528 + sbi->magic = be32_to_cpu(sbo->magic);
2529 + sbi->version_major = sbo->version_major;
2530 + sbi->version_minor = sbo->version_minor;
2531 + sbi->version_sub = sbo->version_sub;
2532 + sbi->files = be64_to_cpu(sbo->files);
2533 + sbi->size = be64_to_cpu(sbo->size);
2534 + sbi->blocks = be64_to_cpu(sbo->blocks);
2535 + sbi->mmap_size = be64_to_cpu(sbo->mmap_size);
2536 + sbi->cblock_size = be32_to_cpu(sbo->cblock_size);
2537 + sbi->timestamp.tv_sec = be64_to_cpu(sbo->timestamp);
2538 + sbi->timestamp.tv_nsec = 0;
2539 + sbi->compression_type = sbo->compression_type;
2540 +
2541 + err = axfs_set_compression_type(sbi);
2542 + if (err)
2543 + goto out;
2544 +
2545 + /* If no block or MTD device, adjust mmapable to cover all image */
2546 + if (AXFS_NODEV(sb))
2547 + sbi->mmap_size = sbi->size;
2548 +
2549 + err = axfs_fill_region_descriptors(sb, sbo);
2550 + if (err)
2551 + goto out;
2552 +
2553 + err = 0;
2554 +out:
2555 + kfree(sbo);
2556 +#ifndef NO_PHYSMEM
2557 + axfs_unmap_physmem(sb);
2558 +#endif
2559 + return err;
2560 +}
2561 +
2562 +/* Verify that the size of the block segment of a split filesystem
2563 + is less than or equal to that of the device containing it.
2564 + Validation of the size of an mmap segment vs. the device containing
2565 + it is handled by the point() function in axfs_map_mtd.
2566 +*/
2567 +int axfs_verify_device_sizes(struct super_block *sb)
2568 +{
2569 + struct axfs_super *sbi = AXFS_SB(sb);
2570 + struct mtd_info *mtd0 = AXFS_MTD(sb);
2571 + struct mtd_info *mtd1 = AXFS_MTD1(sb);
2572 + int sndsize = sbi->size - sbi->mmap_size;
2573 +
2574 + /* Whole FS on one device */
2575 + if (mtd0 && !mtd1 && (mtd0->size < sbi->size)) {
2576 + printk(KERN_ERR "axfs: ERROR: Filesystem extends beyond end of"
2577 + "MTD! Filesystem cannot be safely mounted!\n");
2578 + printk(KERN_ERR "mtd name: %s, mtd size: 0x%x,"
2579 + " fs size: 0x%llx\n", mtd0->name, mtd0->size, sbi->size);
2580 + return -EINVAL;
2581 + }
2582 +
2583 + /* Split filesystem using physaddr */
2584 + if (sndsize && !mtd0 && mtd1 && (mtd1->size < sndsize)) {
2585 + printk(KERN_ERR "axfs: ERROR: The specified second_dev device "
2586 + "is smaller than the store and download segment!\n");
2587 + printk(KERN_ERR "mtd name: %s, mtd size: 0x%x, "
2588 + "snd size: 0x%x\n", mtd1->name, mtd1->size, sndsize);
2589 + return -EINVAL;
2590 + }
2591 +
2592 + /* Split filesystem using two devices */
2593 + if (sndsize && mtd0 && mtd1) {
2594 + if (mtd0->size < sbi->mmap_size) {
2595 + printk(KERN_ERR "axfs: ERROR: Mmap segment extends"
2596 + " beyond end of MTD!");
2597 + printk(KERN_ERR "mtd name: %s, mtd size: 0x%x, mmap "
2598 + "size: 0x%llx",
2599 + mtd0->name, mtd0->size, sbi->mmap_size);
2600 + return -EINVAL;
2601 + }
2602 + if (mtd1->size < sndsize) {
2603 + printk(KERN_ERR "axfs: ERROR: The specified second_dev "
2604 + "device is smaller than the store and download "
2605 + "segment!\n");
2606 + printk(KERN_ERR "mtd name: %s, mtd size: 0x%x, "
2607 + "snd size: 0x%x\n",
2608 + mtd1->name, mtd1->size, sndsize);
2609 + return -EINVAL;
2610 + }
2611 + }
2612 +
2613 + return 0;
2614 +}
2615 +
2616 +/* Read the last four bytes of the volume and make sure the AXFS magic is
2617 + present. */
2618 +int axfs_verify_eofs_magic(struct super_block *sb)
2619 +{
2620 + struct axfs_super *sbi = AXFS_SB(sb);
2621 + u32 buf = 0;
2622 + int err;
2623 + u32 fsoffset = sbi->size - sizeof(u32);
2624 + int len = sizeof(u32);
2625 +
2626 + err = axfs_copy_metadata(sb, &buf, fsoffset, len);
2627 +
2628 + if (err)
2629 + return -EINVAL;
2630 +
2631 + if (be32_to_cpu(buf) != AXFS_MAGIC) {
2632 + printk(KERN_ERR "READ: 0x%x\n", be32_to_cpu(buf));
2633 + printk(KERN_ERR "ERROR: Filesystem is incomplete and cannot be "
2634 + "mounted!\n");
2635 + return -EINVAL;
2636 + }
2637 +
2638 + return 0;
2639 +}
2640 +
2641 +static int axfs_do_fill_super(struct super_block *sb)
2642 +{
2643 + struct axfs_super *sbi = AXFS_SB(sb);
2644 + int err;
2645 +
2646 + err = axfs_get_onmedia_super(sb);
2647 + if (err)
2648 + goto out;
2649 +
2650 + err = axfs_fixup_devices(sb);
2651 + if (err)
2652 + goto out;
2653 +
2654 + err = axfs_verify_device_sizes(sb);
2655 + if (err)
2656 + goto out;
2657 +
2658 + err = axfs_verify_eofs_magic(sb);
2659 + if (err)
2660 + goto out;
2661 +
2662 + err = axfs_fill_region_data_ptrs(sb);
2663 + if (err)
2664 + goto out;
2665 +
2666 + /* Check that the root inode is in a sane state */
2667 + if (!S_ISDIR(AXFS_GET_MODE(sbi, 0))) {
2668 + printk(KERN_ERR "axfs: root is not a directory\n");
2669 + err = -EINVAL;
2670 + goto out;
2671 + }
2672 +
2673 + if (AXFS_GET_INODE_NUM_ENTRIES(sbi, 0) == 0) {
2674 + printk(KERN_INFO "axfs: empty filesystem");
2675 + err = -EINVAL;
2676 + goto out;
2677 + }
2678 +
2679 + err = axfs_init_cblock_buffers(sbi);
2680 + if (err)
2681 + goto out;
2682 +
2683 + init_rwsem(&sbi->lock);
2684 +
2685 + return 0;
2686 +
2687 +out:
2688 + axfs_put_super(sb);
2689 + return err;
2690 +}
2691 +
2692 +int axfs_fill_super(struct super_block *sb, void *data, int silent)
2693 +{
2694 + struct axfs_super *sbi_in = (struct axfs_super *)data;
2695 + struct axfs_super *sbi;
2696 + struct inode *root;
2697 + int err;
2698 +
2699 + sbi = axfs_get_sbi();
2700 + sb->s_fs_info = (void *)sbi;
2701 + memcpy(sbi, sbi_in, sizeof(*sbi));
2702 +
2703 + /* fully populate the incore superblock structures */
2704 + err = axfs_do_fill_super(sb);
2705 + if (err)
2706 + goto out;
2707 +
2708 + sb->s_flags |= MS_RDONLY;
2709 +
2710 + /* Setup the VFS super block now */
2711 + sb->s_op = &axfs_sops;
2712 + root = axfs_create_vfs_inode(sb, 0);
2713 + if (!root) {
2714 + err = -EINVAL;
2715 + goto out;
2716 + }
2717 +
2718 + sb->s_root = d_alloc_root(root);
2719 + if (!sb->s_root) {
2720 + iput(root);
2721 + err = -EINVAL;
2722 + goto out;
2723 + }
2724 +
2725 + err = axfs_init_profiling(sbi);
2726 + if (err)
2727 + goto out;
2728 +
2729 + return 0;
2730 +
2731 +out:
2732 + axfs_put_super(sb);
2733 + return err;
2734 +}
2735 +
2736 +static int axfs_get_sb_address(struct file_system_type *fs_type, int flags,
2737 + struct axfs_super *sbi, struct vfsmount *mnt,
2738 + int *err)
2739 +{
2740 + int mtdnr;
2741 + char *sd = sbi->second_dev;
2742 +
2743 + if (sbi->phys_start_addr == 0)
2744 + return FALSE;
2745 +
2746 + if (sbi->phys_start_addr & (PAGE_SIZE - 1)) {
2747 + printk(KERN_ERR
2748 + "axfs: address 0x%lx for axfs image isn't aligned"
2749 + " to a page boundary\n", sbi->phys_start_addr);
2750 + *err = -EINVAL;
2751 + return TRUE;
2752 + }
2753 +
2754 + if (axfs_is_dev_mtd(sd, &mtdnr)) {
2755 + return axfs_get_sb_mtd(fs_type, flags, sd, sbi, mnt, err);
2756 + } else if (axfs_is_dev_bdev(sd)) {
2757 + return axfs_get_sb_bdev(fs_type, flags, sd, sbi, mnt, err);
2758 + } else {
2759 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
2760 + *err = get_sb_nodev(fs_type, flags, sbi, axfs_fill_super, mnt);
2761 +#else
2762 + mnt->mnt_sb =
2763 + get_sb_nodev(fs_type, flags, (void *)sbi, axfs_fill_super);
2764 +#endif
2765 + }
2766 +
2767 + return TRUE;
2768 +}
2769 +
2770 +/* helpers for parse_axfs_options */
2771 +enum {
2772 + OPTION_ERR,
2773 + OPTION_SECOND_DEV,
2774 + OPTION_PHYSICAL_ADDRESS_LOWER_X,
2775 + OPTION_PHYSICAL_ADDRESS_UPPER_X,
2776 + OPTION_IOMEM
2777 +};
2778 +
2779 +/* helpers for parse_axfs_options */
2780 +static match_table_t tokens = {
2781 + {OPTION_SECOND_DEV, "second_dev=%s"},
2782 + {OPTION_PHYSICAL_ADDRESS_LOWER_X, "physaddr=0x%s"},
2783 + {OPTION_PHYSICAL_ADDRESS_UPPER_X, "physaddr=0X%s"},
2784 + {OPTION_IOMEM, "iomem=%s"},
2785 + {OPTION_ERR, NULL}
2786 +};
2787 +
2788 +static int axfs_check_options(char *options, struct axfs_super *sbi)
2789 +{
2790 + unsigned long address = 0;
2791 + char *iomem = NULL;
2792 + unsigned long length = 0;
2793 + char *p;
2794 + int err = -EINVAL;
2795 + substring_t args[MAX_OPT_ARGS];
2796 +
2797 + if (!options)
2798 + return 0;
2799 +
2800 + if (!*options)
2801 + return 0;
2802 +
2803 + while ((p = strsep(&options, ",")) != NULL) {
2804 + int token;
2805 + if (!*p)
2806 + continue;
2807 +
2808 + token = match_token(p, tokens, args);
2809 + switch (token) {
2810 + case OPTION_SECOND_DEV:
2811 + sbi->second_dev = match_strdup(&args[0]);
2812 + if (!(sbi->second_dev)) {
2813 + err = -ENOMEM;
2814 + goto out;
2815 + }
2816 + if (!*(sbi->second_dev))
2817 + goto bad_value;
2818 + break;
2819 + case OPTION_IOMEM:
2820 + iomem = match_strdup(&args[0]);
2821 + if (!(iomem)) {
2822 + err = -ENOMEM;
2823 + goto out;
2824 + }
2825 + if (!*iomem)
2826 + goto bad_value;
2827 + break;
2828 + case OPTION_PHYSICAL_ADDRESS_LOWER_X:
2829 + case OPTION_PHYSICAL_ADDRESS_UPPER_X:
2830 + if (match_hex(&args[0], (int *)&address))
2831 + goto out;
2832 + if (!address)
2833 + goto bad_value;
2834 + break;
2835 + default:
2836 + printk(KERN_ERR
2837 + "axfs: unrecognized mount option \"%s\" "
2838 + "or missing value\n", p);
2839 + goto out;
2840 + }
2841 + }
2842 +
2843 + if (iomem) {
2844 + if (address)
2845 + goto out;
2846 + err = axfs_get_uml_address(iomem, &address, &length);
2847 + kfree(iomem);
2848 + sbi->iomem_size = length;
2849 + sbi->virt_start_addr = address;
2850 + }
2851 +
2852 + sbi->phys_start_addr = address;
2853 + return 0;
2854 +
2855 +bad_value:
2856 + printk(KERN_ERR
2857 + "axfs: unrecognized mount option \"%s\" "
2858 + "or missing value\n", p);
2859 +out:
2860 + if (iomem)
2861 + kfree(iomem);
2862 + return err;
2863 +}
2864 +
2865 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)
2866 +int axfs_get_sb(struct file_system_type *fs_type, int flags,
2867 + const char *dev_name, void *data, struct vfsmount *mnt)
2868 +#else
2869 +struct super_block *axfs_get_sb(struct file_system_type *fs_type, int flags,
2870 + const char *dev_name, void *data)
2871 +#endif
2872 +{
2873 + struct axfs_super *sbi;
2874 + int err;
2875 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)
2876 +#else
2877 + struct super_block *sb;
2878 + struct vfsmount *mnt;
2879 + mnt = kmalloc(sizeof(*mnt), GFP_KERNEL);
2880 + memset(mnt, 0, sizeof(*mnt));
2881 +#endif
2882 +
2883 + sbi = axfs_get_sbi();
2884 + if (IS_ERR(sbi))
2885 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)
2886 + return PTR_ERR(sbi);
2887 +#else
2888 + return (struct super_block *)sbi;
2889 +#endif
2890 +
2891 + err = axfs_check_options((char *)data, sbi);
2892 + if (err)
2893 + goto out;
2894 +
2895 + /* First we check if we are mounting directly to memory */
2896 + if (axfs_get_sb_address(fs_type, flags, sbi, mnt, &err))
2897 + goto out;
2898 +
2899 + /* Next we assume there's a MTD device */
2900 + if (axfs_get_sb_mtd(fs_type, flags, dev_name, sbi, mnt, &err))
2901 + goto out;
2902 +
2903 + /* Now we assume it's a block device */
2904 + if (sbi->second_dev) {
2905 + printk(KERN_ERR
2906 + "axfs: can't specify secondary block device %s because"
2907 + " %s is assumed to be a block device\n", sbi->second_dev,
2908 + dev_name);
2909 + err = -EINVAL;
2910 + goto out;
2911 + }
2912 +
2913 + if (axfs_get_sb_bdev(fs_type, flags, dev_name, sbi, mnt, &err))
2914 + goto out;
2915 +
2916 + err = -EINVAL;
2917 +
2918 +out:
2919 + axfs_put_sbi(sbi);
2920 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)
2921 + return err;
2922 +#else
2923 + if (err)
2924 + return ERR_PTR(err);
2925 +
2926 + sb = mnt->mnt_sb;
2927 + kfree(mnt);
2928 + return sb;
2929 +#endif
2930 +}
2931 +
2932 +static struct axfs_super *axfs_get_sbi(void)
2933 +{
2934 + struct axfs_super *sbi;
2935 +
2936 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
2937 + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
2938 +#else
2939 + sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
2940 + memset(sbi, 0, sizeof(*sbi));
2941 +#endif
2942 + if (sbi)
2943 + return sbi;
2944 +
2945 + axfs_put_sbi(sbi);
2946 + return ERR_PTR(-ENOMEM);
2947 +}
2948 +
2949 +static void axfs_kill_super(struct super_block *sb)
2950 +{
2951 + if (AXFS_NODEV(sb))
2952 + return kill_anon_super(sb);
2953 +
2954 + if (AXFS_HAS_MTD(sb))
2955 + axfs_kill_mtd_super(sb);
2956 +
2957 + if (AXFS_HAS_BDEV(sb))
2958 + axfs_kill_block_super(sb);
2959 +}
2960 +
2961 +static int axfs_remount(struct super_block *sb, int *flags, char *data)
2962 +{
2963 + *flags |= MS_RDONLY;
2964 + return 0;
2965 +}
2966 +
2967 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)
2968 +static int axfs_statfs(struct dentry *dentry, struct kstatfs *buf)
2969 +#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2970 +static int axfs_statfs(struct super_block *sb, struct kstatfs *buf)
2971 +#else
2972 +static int axfs_statfs(struct super_block *sb, struct statfs *buf)
2973 +#endif
2974 +{
2975 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)
2976 + struct axfs_super *sbi = AXFS_SB(dentry->d_sb);
2977 +#else
2978 + struct axfs_super *sbi = AXFS_SB(sb);
2979 +#endif
2980 +
2981 + buf->f_type = AXFS_MAGIC;
2982 + buf->f_bsize = AXFS_PAGE_SIZE;
2983 + buf->f_blocks = sbi->blocks;
2984 + buf->f_bfree = 0;
2985 + buf->f_bavail = 0;
2986 + buf->f_files = sbi->files;
2987 + buf->f_ffree = 0;
2988 + buf->f_namelen = AXFS_MAXPATHLEN;
2989 + return 0;
2990 +}
2991 +
2992 +static struct super_operations axfs_sops = {
2993 + .put_super = axfs_put_super,
2994 + .remount_fs = axfs_remount,
2995 + .statfs = axfs_statfs,
2996 +};
2997 +
2998 +static struct file_system_type axfs_fs_type = {
2999 + .owner = THIS_MODULE,
3000 + .name = "axfs",
3001 + .get_sb = axfs_get_sb,
3002 + .kill_sb = axfs_kill_super,
3003 +};
3004 +
3005 +static int __init init_axfs_fs(void)
3006 +{
3007 + axfs_uncompress_init();
3008 + return register_filesystem(&axfs_fs_type);
3009 +}
3010 +
3011 +static void __exit exit_axfs_fs(void)
3012 +{
3013 + axfs_uncompress_exit();
3014 + unregister_filesystem(&axfs_fs_type);
3015 +}
3016 +
3017 +module_init(init_axfs_fs);
3018 +module_exit(exit_axfs_fs);
3019 +MODULE_LICENSE("GPL");
3020 diff -Naur linux-2.6.24/fs/axfs/axfs_uml.c linux-2.6.24-axfs/fs/axfs/axfs_uml.c
3021 --- linux-2.6.24/fs/axfs/axfs_uml.c 1970-01-01 01:00:00.000000000 +0100
3022 +++ linux-2.6.24-axfs/fs/axfs/axfs_uml.c 2008-08-24 19:12:32.000000000 +0200
3023 @@ -0,0 +1,47 @@
3024 +/*
3025 + * Advanced XIP File System for Linux - AXFS
3026 + * Readonly, compressed, and XIP filesystem for Linux systems big and small
3027 + *
3028 + * Copyright(c) 2008 Numonyx
3029 + *
3030 + * This program is free software; you can redistribute it and/or modify it
3031 + * under the terms and conditions of the GNU General Public License,
3032 + * version 2, as published by the Free Software Foundation.
3033 + *
3034 + * Authors:
3035 + * Jared Hulbert <jaredeh@gmail.com>
3036 + *
3037 + * Project url: http://axfs.sourceforge.net
3038 + *
3039 + * axfs_uml.c -
3040 + * Allows axfs to a UML kernels find_iomem() interface as an XIP device or
3041 + * dummy functions if this is not a UML build.
3042 + */
3043 +
3044 +#include <linux/axfs.h>
3045 +#ifdef CONFIG_UML
3046 +#include <mem_user.h>
3047 +int axfs_get_uml_address(char *iomem, unsigned long *address,
3048 + unsigned long *length)
3049 +{
3050 + *address = find_iomem(iomem, length);
3051 + if (!(*address)) {
3052 + printk(KERN_DEBUG "axfs: find_iomem() failed\n");
3053 + return -EINVAL;
3054 + }
3055 +
3056 + if (*length < PAGE_SIZE) {
3057 + printk(KERN_DEBUG
3058 + "axfs: iomem() too small, must be at least %li Bytes\n",
3059 + PAGE_SIZE);
3060 + return -EINVAL;
3061 + }
3062 + return 0;
3063 +}
3064 +#else
3065 +int axfs_get_uml_address(char *iomem, unsigned long *address,
3066 + unsigned long *length)
3067 +{
3068 + return 0;
3069 +}
3070 +#endif /* CONFIG_UML */
3071 diff -Naur linux-2.6.24/fs/axfs/axfs_uncompress.c linux-2.6.24-axfs/fs/axfs/axfs_uncompress.c
3072 --- linux-2.6.24/fs/axfs/axfs_uncompress.c 1970-01-01 01:00:00.000000000 +0100
3073 +++ linux-2.6.24-axfs/fs/axfs/axfs_uncompress.c 2008-08-24 19:12:32.000000000 +0200
3074 @@ -0,0 +1,124 @@
3075 +/*
3076 + * Advanced XIP File System for Linux - AXFS
3077 + * Readonly, compressed, and XIP filesystem for Linux systems big and small
3078 + *
3079 + * Modified in 2006 by Eric Anderson
3080 + * from the cramfs sources fs/cramfs/uncompress.c
3081 + *
3082 + * (C) Copyright 1999 Linus Torvalds
3083 + *
3084 + * axfs_uncompress.c -
3085 + * axfs interfaces to the uncompression library. There's really just
3086 + * three entrypoints:
3087 + *
3088 + * - axfs_uncompress_init() - called to initialize the thing.
3089 + * - axfs_uncompress_exit() - tell me when you're done
3090 + * - axfs_uncompress_block() - uncompress a block.
3091 + *
3092 + * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
3093 + * only have one stream, and we'll initialize it only once even if it
3094 + * then is used by multiple filesystems.
3095 + *
3096 + */
3097 +
3098 +#ifndef ALL_VERSIONS
3099 +#include <linux/version.h> /* For multi-version support */
3100 +#endif
3101 +#include <linux/errno.h>
3102 +#include <linux/vmalloc.h>
3103 +#include <linux/zlib.h>
3104 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
3105 +#include <linux/mutex.h>
3106 +#else
3107 +#include <linux/rwsem.h>
3108 +#endif
3109 +
3110 +static z_stream stream;
3111 +static int initialized;
3112 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
3113 +static struct mutex axfs_uncmp_mutex;
3114 +#else
3115 +static struct rw_semaphore axfs_uncmp_mutex;
3116 +#endif
3117 +
3118 +int axfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
3119 +{
3120 + int err;
3121 + int out;
3122 +
3123 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
3124 + mutex_lock(&axfs_uncmp_mutex);
3125 +#else
3126 + down_write(&axfs_uncmp_mutex);
3127 +#endif
3128 +
3129 + stream.next_in = src;
3130 + stream.avail_in = srclen;
3131 +
3132 + stream.next_out = dst;
3133 + stream.avail_out = dstlen;
3134 +
3135 + err = zlib_inflateReset(&stream);
3136 + if (err != Z_OK) {
3137 + printk(KERN_ERR "zlib_inflateReset error %d\n", err);
3138 + zlib_inflateEnd(&stream);
3139 + zlib_inflateInit(&stream);
3140 + }
3141 +
3142 + err = zlib_inflate(&stream, Z_FINISH);
3143 + if (err != Z_STREAM_END)
3144 + goto err;
3145 +
3146 + out = stream.total_out;
3147 +
3148 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
3149 + mutex_unlock(&axfs_uncmp_mutex);
3150 +#else
3151 + up_write(&axfs_uncmp_mutex);
3152 +#endif
3153 +
3154 + return out;
3155 +
3156 +err:
3157 +
3158 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
3159 + mutex_unlock(&axfs_uncmp_mutex);
3160 +#else
3161 + up_write(&axfs_uncmp_mutex);
3162 +#endif
3163 +
3164 + printk(KERN_ERR "Error %d while decompressing!\n", err);
3165 + printk(KERN_ERR "%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
3166 + return 0;
3167 +}
3168 +
3169 +int axfs_uncompress_init(void)
3170 +{
3171 + if (!initialized++) {
3172 +
3173 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
3174 + mutex_init(&axfs_uncmp_mutex);
3175 +#else
3176 + init_rwsem(&axfs_uncmp_mutex);
3177 +#endif
3178 +
3179 + stream.workspace = vmalloc(zlib_inflate_workspacesize());
3180 + if (!stream.workspace) {
3181 + initialized = 0;
3182 + return -ENOMEM;
3183 + }
3184 + stream.next_in = NULL;
3185 + stream.avail_in = 0;
3186 + zlib_inflateInit(&stream);
3187 + }
3188 + return 0;
3189 +}
3190 +
3191 +int axfs_uncompress_exit(void)
3192 +{
3193 + if (!--initialized) {
3194 + zlib_inflateEnd(&stream);
3195 + vfree(stream.workspace);
3196 + }
3197 + return 0;
3198 +}
3199 diff -Naur linux-2.6.24/fs/axfs/Makefile linux-2.6.24-axfs/fs/axfs/Makefile
3200 --- linux-2.6.24/fs/axfs/Makefile 1970-01-01 01:00:00.000000000 +0100
3201 +++ linux-2.6.24-axfs/fs/axfs/Makefile 2008-08-24 19:12:32.000000000 +0200
3202 @@ -0,0 +1,7 @@
3203 +#
3204 +# Makefile for the linux axfs routines
3205 +#
3206 +
3207 +obj-$(CONFIG_AXFS) += axfs.o
3208 +
3209 +axfs-objs := axfs_inode.o axfs_super.o axfs_uncompress.o axfs_profiling.o axfs_uml.o axfs_mtd.o axfs_bdev.o axfs_physmem.o
3210 diff -Naur linux-2.6.24/fs/Kconfig linux-2.6.24-axfs/fs/Kconfig
3211 --- linux-2.6.24/fs/Kconfig 2008-08-24 19:12:03.000000000 +0200
3212 +++ linux-2.6.24-axfs/fs/Kconfig 2008-08-24 19:12:32.000000000 +0200
3213 @@ -1043,6 +1043,27 @@
3214
3215 menu "Miscellaneous filesystems"
3216
3217 +config AXFS
3218 + tristate "Advanced XIP File System (AXFS) support (EXPERIMENTAL)"
3219 + select FS_XIP
3220 + select ZLIB_INFLATE
3221 + default n
3222 + help
3223 + The Advanced XIP File System or (AXFS) is a highly compressed
3224 + readonly filesystem like cramfs or squashfs. It also can be
3225 + configured to store individual pages of files compressed or
3226 + uncompressed as XIP pages. This allows for faster boot up and
3227 + application launch time with a smaller memory footprint.
3228 +
3229 +config AXFS_PROFILING
3230 + bool "Profiling extensions for AXFS (EXPERIMENTAL)"
3231 + depends on AXFS
3232 + default n
3233 + help
3234 + Profiling tooling used to identify what pages in the filesystem
3235 + image are actually accessed and how much.
3236 +
3237 +
3238 config ADFS_FS
3239 tristate "ADFS file system support (EXPERIMENTAL)"
3240 depends on BLOCK && EXPERIMENTAL
3241 diff -Naur linux-2.6.24/fs/Makefile linux-2.6.24-axfs/fs/Makefile
3242 --- linux-2.6.24/fs/Makefile 2008-08-24 19:12:03.000000000 +0200
3243 +++ linux-2.6.24-axfs/fs/Makefile 2008-08-24 19:12:32.000000000 +0200
3244 @@ -72,6 +72,7 @@
3245 obj-$(CONFIG_JBD2) += jbd2/
3246 obj-$(CONFIG_EXT2_FS) += ext2/
3247 obj-$(CONFIG_CRAMFS) += cramfs/
3248 +obj-$(CONFIG_AXFS) += axfs/
3249 obj-$(CONFIG_SQUASHFS) += squashfs/
3250 obj-y += ramfs/
3251 obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
3252 diff -Naur linux-2.6.24/include/linux/axfs.h linux-2.6.24-axfs/include/linux/axfs.h
3253 --- linux-2.6.24/include/linux/axfs.h 1970-01-01 01:00:00.000000000 +0100
3254 +++ linux-2.6.24-axfs/include/linux/axfs.h 2008-08-24 19:12:32.000000000 +0200
3255 @@ -0,0 +1,375 @@
3256 +/*
3257 + * Advanced XIP File System for Linux - AXFS
3258 + * Readonly, compressed, and XIP filesystem for Linux systems big and small
3259 + *
3260 + * Copyright(c) 2008 Numonyx
3261 + *
3262 + * This program is free software; you can redistribute it and/or modify it
3263 + * under the terms and conditions of the GNU General Public License,
3264 + * version 2, as published by the Free Software Foundation.
3265 + *
3266 + * Authors:
3267 + * Eric Anderson
3268 + * Jared Hulbert <jaredeh@gmail.com>
3269 + * Sujaya Srinivasan
3270 + * Justin Treon
3271 + *
3272 + * Project url: http://axfs.sourceforge.net
3273 + */
3274 +
3275 +#ifndef __AXFS_H
3276 +#define __AXFS_H
3277 +
3278 +#ifndef ALL_VERSIONS
3279 +#include <linux/version.h> /* For multi-version support */
3280 +#endif
3281 +
3282 +#ifdef __KERNEL__
3283 +#include <linux/rwsem.h>
3284 +#endif
3285 +#include <linux/errno.h>
3286 +#include <linux/time.h>
3287 +
3288 +#define AXFS_MAGIC 0x48A0E4CD /* some random number */
3289 +#define AXFS_SIGNATURE "Advanced XIP FS"
3290 +#define AXFS_MAXPATHLEN 255
3291 +
3292 +/* Uncompression interfaces to the underlying zlib */
3293 +int axfs_uncompress_block(void *, int, void *, int);
3294 +int axfs_uncompress_init(void);
3295 +int axfs_uncompress_exit(void);
3296 +
3297 +struct axfs_profiling_data {
3298 + u64 inode_number;
3299 + unsigned long count;
3300 +};
3301 +
3302 +enum axfs_node_types {
3303 + XIP = 0,
3304 + Compressed,
3305 + Byte_Aligned,
3306 +};
3307 +
3308 +enum axfs_compression_types {
3309 + ZLIB = 0
3310 +};
3311 +
3312 +/*
3313 + * on media struct describing a data region
3314 + */
3315 +struct axfs_region_desc_onmedia {
3316 + u64 fsoffset;
3317 + u64 size;
3318 + u64 compressed_size;
3319 + u64 max_index;
3320 + u8 table_byte_depth;
3321 + u8 incore;
3322 +};
3323 +
3324 +struct axfs_region_desc {
3325 + u64 fsoffset;
3326 + u64 size;
3327 + u64 compressed_size;
3328 + u64 max_index;
3329 + void *virt_addr;
3330 + u8 table_byte_depth;
3331 + u8 incore;
3332 +};
3333 +
3334 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
3335 +#else
3336 +struct axfs_fill_super_info {
3337 + struct axfs_super_onmedia *onmedia_super_block;
3338 + unsigned long physical_start_address;
3339 + unsigned long virtual_start_address;
3340 +};
3341 +#endif
3342 +/*
3343 + * axfs_super is the on media format for the super block it must be big endian
3344 + */
3345 +struct axfs_super_onmedia {
3346 + u32 magic; /* 0x48A0E4CD - random number */
3347 + u8 signature[16]; /* "Advanced XIP FS" */
3348 + u8 digest[40]; /* sha1 digest for checking data integrity */
3349 + u32 cblock_size; /* maximum size of the block being compressed */
3350 + u64 files; /* number of inodes/files in fs */
3351 + u64 size; /* total image size */
3352 + u64 blocks; /* number of nodes in fs */
3353 + u64 mmap_size; /* size of the memory mapped part of image */
3354 + u64 strings; /* offset to strings region descriptor */
3355 + u64 xip; /* offset to xip region descriptor */
3356 + u64 byte_aligned; /* offset to the byte aligned region desc */
3357 + u64 compressed; /* offset to the compressed region desc */
3358 + u64 node_type; /* offset to node type region desc */
3359 + u64 node_index; /* offset to node index region desc */
3360 + u64 cnode_offset; /* offset to cnode offset region desc */
3361 + u64 cnode_index; /* offset to cnode index region desc */
3362 + u64 banode_offset; /* offset to banode offset region desc */
3363 + u64 cblock_offset; /* offset to cblock offset region desc */
3364 + u64 inode_file_size; /* offset to inode file size desc*/
3365 + u64 inode_name_offset; /* offset to inode num_entries region desc */
3366 + u64 inode_num_entries; /* offset to inode num_entries region desc */
3367 + u64 inode_mode_index; /* offset to inode mode index region desc */
3368 + u64 inode_array_index; /* offset to inode node index region desc */
3369 + u64 modes; /* offset to mode mode region desc */
3370 + u64 uids; /* offset to mode uid index region desc */
3371 + u64 gids; /* offset to mode gid index region desc */
3372 + u8 version_major;
3373 + u8 version_minor;
3374 + u8 version_sub;
3375 + u8 compression_type; /* Identifies type of compression used on FS */
3376 + u64 timestamp; /* UNIX time_t of filesystem build time */
3377 +};
3378 +
3379 +/*
3380 + * axfs super-block data in core
3381 + */
3382 +struct axfs_super {
3383 + u32 magic;
3384 + u8 version_major;
3385 + u8 version_minor;
3386 + u8 version_sub;
3387 + u8 padding;
3388 + u64 files;
3389 + u64 size;
3390 + u64 blocks;
3391 + u64 mmap_size;
3392 + struct axfs_region_desc strings;
3393 + struct axfs_region_desc xip;
3394 + struct axfs_region_desc compressed;
3395 + struct axfs_region_desc byte_aligned;
3396 + struct axfs_region_desc node_type;
3397 + struct axfs_region_desc node_index;
3398 + struct axfs_region_desc cnode_offset;
3399 + struct axfs_region_desc cnode_index;
3400 + struct axfs_region_desc banode_offset;
3401 + struct axfs_region_desc cblock_offset;
3402 + struct axfs_region_desc inode_file_size;
3403 + struct axfs_region_desc inode_name_offset;
3404 + struct axfs_region_desc inode_num_entries;
3405 + struct axfs_region_desc inode_mode_index;
3406 + struct axfs_region_desc inode_array_index;
3407 + struct axfs_region_desc modes;
3408 + struct axfs_region_desc uids;
3409 + struct axfs_region_desc gids;
3410 + unsigned long phys_start_addr;
3411 + unsigned long virt_start_addr;
3412 + char *second_dev;
3413 + unsigned long iomem_size;
3414 + void *mtd0; /* primary device */
3415 + void *mtd1; /* secondary device */
3416 + u32 cblock_size;
3417 + u64 current_cnode_index;
3418 + void *cblock_buffer[2];
3419 + struct rw_semaphore lock;
3420 + struct axfs_profiling_data *profile_data_ptr;
3421 + u8 profiling_on; /* Determines if profiling is on or off */
3422 + u8 mtd_pointed;
3423 + u8 compression_type;
3424 + struct timespec timestamp;
3425 +};
3426 +
3427 +#define AXFS_PAGE_SIZE 4096
3428 +
3429 +#define AXFS_SB(sb) (struct axfs_super *)((sb)->s_fs_info)
3430 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
3431 +#define AXFS_MTD(sb) (void *)((sb)->s_mtd)
3432 +#else
3433 +#define AXFS_MTD(sb) 0
3434 +#endif
3435 +#define AXFS_MTD0(sb) (((AXFS_SB(sb))->mtd0) ? \
3436 + ((AXFS_SB(sb))->mtd0) : (AXFS_MTD(sb)))
3437 +#define AXFS_MTD1(sb) ((AXFS_SB(sb))->mtd1)
3438 +
3439 +#define AXFS_BDEV(sb) ((sb)->s_bdev)
3440 +
3441 +#define AXFS_HAS_BDEV(sb) \
3442 + ((AXFS_BDEV(sb) != NULL) ? TRUE : FALSE)
3443 +#define AXFS_HAS_MTD(sb) \
3444 + (((AXFS_MTD0(sb) != NULL) || \
3445 + (AXFS_MTD1(sb) != NULL) || \
3446 + (AXFS_MTD(sb) != NULL)) ? TRUE : FALSE)
3447 +
3448 +#define AXFS_NODEV(sb) \
3449 + ((!AXFS_HAS_MTD(sb) && !AXFS_HAS_BDEV(sb)) ? TRUE : FALSE)
3450 +
3451 +static inline u64 axfs_bytetable_stitch(u8 depth, u8 *table, u64 index)
3452 +{
3453 + u64 i;
3454 + u64 output = 0;
3455 + u64 byte = 0;
3456 + u64 j;
3457 + u64 bits;
3458 +
3459 + for (i = 0; i < depth; i++) {
3460 + j = index * depth + i;
3461 + bits = 8 * (depth - i - 1);
3462 + byte = table[j];
3463 + output += byte << bits;
3464 + }
3465 + return output;
3466 +}
3467 +
3468 +#define AXFS_GET_BYTETABLE_VAL(desc,index) \
3469 + axfs_bytetable_stitch(((struct axfs_region_desc)(desc)).table_byte_depth,\
3470 + (u8 *)((struct axfs_region_desc)(desc)).virt_addr, index)
3471 +
3472 +#define AXFS_GET_NODE_TYPE(sbi,node_index) \
3473 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->node_type,\
3474 + (node_index))
3475 +
3476 +#define AXFS_GET_NODE_INDEX(sbi,node__index) \
3477 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->node_index,\
3478 + (node__index))
3479 +
3480 +#define AXFS_IS_NODE_XIP(sbi,node_index) \
3481 + (AXFS_GET_NODE_TYPE(sbi, (node_index)) == XIP)
3482 +
3483 +#define AXFS_GET_CNODE_INDEX(sbi,node_index) \
3484 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->cnode_index,\
3485 + (node_index))
3486 +
3487 +#define AXFS_GET_CNODE_OFFSET(desc,node_index) \
3488 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->cnode_offset,\
3489 + (node_index))
3490 +
3491 +#define AXFS_GET_BANODE_OFFSET(desc,node_index) \
3492 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->banode_offset,\
3493 + (node_index))
3494 +
3495 +#define AXFS_GET_CBLOCK_OFFSET(desc,node_index) \
3496 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->cblock_offset,\
3497 + (node_index))
3498 +
3499 +#define AXFS_GET_INODE_FILE_SIZE(sbi,inode_index) \
3500 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->inode_file_size,\
3501 + (inode_index))
3502 +
3503 +#define AXFS_GET_INODE_NAME_OFFSET(sbi,inode_index) \
3504 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->inode_name_offset,\
3505 + (inode_index))
3506 +
3507 +#define AXFS_GET_INODE_NUM_ENTRIES(sbi,inode_index) \
3508 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->inode_num_entries,\
3509 + (inode_index))
3510 +
3511 +#define AXFS_GET_INODE_MODE_INDEX(sbi,inode_index) \
3512 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->inode_mode_index,\
3513 + (inode_index))
3514 +
3515 +#define AXFS_GET_INODE_ARRAY_INDEX(sbi,inode_index) \
3516 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->inode_array_index,\
3517 + (inode_index))
3518 +
3519 +#define AXFS_GET_MODE(sbi,mode_index) \
3520 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->modes,\
3521 + (AXFS_GET_INODE_MODE_INDEX(sbi, (mode_index))))
3522 +
3523 +#define AXFS_GET_UID(sbi,mode_index) \
3524 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->uids,\
3525 + (AXFS_GET_INODE_MODE_INDEX(sbi, (mode_index))))
3526 +
3527 +#define AXFS_GET_GID(sbi,mode_index) \
3528 + AXFS_GET_BYTETABLE_VAL(((struct axfs_super *)(sbi))->gids,\
3529 + (AXFS_GET_INODE_MODE_INDEX(sbi, (mode_index))))
3530 +
3531 +#define AXFS_IS_REGION_COMPRESSED(_region) \
3532 + (( \
3533 + ((struct axfs_region_desc *)(_region))->compressed_size > \
3534 + 0 \
3535 + ) ? TRUE : FALSE)
3536 +
3537 +#define AXFS_PHYSADDR_IS_VALID(sbi) \
3538 + (((((struct axfs_super *)(sbi))->phys_start_addr) > 0 \
3539 + ) ? TRUE : FALSE)
3540 +
3541 +#define AXFS_VIRTADDR_IS_VALID(sbi) \
3542 + (((((struct axfs_super *)(sbi))->virt_start_addr) > 0 \
3543 + ) ? TRUE : FALSE)
3544 +
3545 +#define AXFS_IS_IOMEM(sbi) \
3546 + (((((struct axfs_super *)(sbi))->iomem_size) > 0) ? TRUE : FALSE)
3547 +
3548 +#define AXFS_IS_POINTED(sbi) \
3549 + (((((struct axfs_super *)(sbi))->mtd_pointed) > 0) ? TRUE : FALSE)
3550 +
3551 +#define AXFS_IS_PHYSMEM(sbi) \
3552 + (( \
3553 + AXFS_PHYSADDR_IS_VALID(sbi) \
3554 + && !AXFS_IS_IOMEM(sbi) \
3555 + && !AXFS_IS_POINTED(sbi) \
3556 + ) ? TRUE : FALSE)
3557 +
3558 +#define AXFS_IS_MMAPABLE(sbi,offset) \
3559 + ((\
3560 + (((struct axfs_super *)(sbi))->mmap_size) > (offset) \
3561 + ) ? TRUE : FALSE)
3562 +
3563 +#define AXFS_IS_OFFSET_MMAPABLE(sbi,offset) \
3564 + (( \
3565 + AXFS_IS_MMAPABLE(sbi, offset) && AXFS_VIRTADDR_IS_VALID(sbi) \
3566 + ) ? TRUE : FALSE)
3567 +
3568 +#define AXFS_IS_REGION_MMAPABLE(sbi,_region) \
3569 + (( \
3570 + AXFS_IS_MMAPABLE(sbi, ((struct axfs_region_desc *)(_region))->fsoffset) \
3571 + && AXFS_VIRTADDR_IS_VALID(sbi) \
3572 + ) ? TRUE : FALSE)
3573 +
3574 +#define AXFS_IS_REGION_INCORE(_region) \
3575 + (((_region)->incore > 0) ? TRUE : FALSE)
3576 +
3577 +#define AXFS_IS_REGION_XIP(sbi,_region) \
3578 + (( \
3579 + !AXFS_IS_REGION_COMPRESSED(_region) && \
3580 + !AXFS_IS_REGION_INCORE(_region) && \
3581 + AXFS_IS_REGION_MMAPABLE(sbi,_region) \
3582 + ) ? TRUE : FALSE)
3583 +
3584 +#define AXFS_GET_XIP_REGION_PHYSADDR(sbi) \
3585 + (unsigned long)((sbi)->phys_start_addr + (sbi)->xip.fsoffset)
3586 +
3587 +#define AXFS_GET_INODE_NAME(sbi,inode_index) \
3588 + (char *)( \
3589 + (sbi)->strings.virt_addr \
3590 + + AXFS_GET_INODE_NAME_OFFSET(sbi,inode_index) \
3591 + )
3592 +
3593 +#define AXFS_GET_CBLOCK_ADDRESS(sbi, cnode_index)\
3594 + (unsigned long)( \
3595 + (sbi)->compressed.virt_addr \
3596 + + AXFS_GET_CBLOCK_OFFSET(sbi, cnode_index) \
3597 + )
3598 +
3599 +#define AXFS_GET_NODE_ADDRESS(sbi,node__index) \
3600 + (unsigned long)( \
3601 + (sbi)->node_index.virt_addr \
3602 + + AXFS_GET_NODE_INDEX(sbi, node__index) \
3603 + )
3604 +
3605 +#define AXFS_GET_BANODE_ADDRESS(sbi,banode_index) \
3606 + (unsigned long)( \
3607 + (sbi)->byte_aligned.virt_addr \
3608 + + AXFS_GET_BANODE_OFFSET(sbi, banode_index) \
3609 + )
3610 +
3611 +#define AXFS_FSOFFSET_2_DEVOFFSET(sbi,fsoffset) \
3612 + (( \
3613 + ((sbi)->phys_start_addr == 0) && ((sbi)->virt_start_addr == 0) \
3614 + ) ? (fsoffset) : (fsoffset - (sbi)->mmap_size) \
3615 + )
3616 +
3617 +#define AXFS_GET_CBLOCK_LENGTH(sbi,cblock_index) \
3618 + (u64)( \
3619 + (u64)AXFS_GET_CBLOCK_OFFSET(sbi, ((u64)(cblock_index)+(u64)1)) \
3620 + - (u64)AXFS_GET_CBLOCK_OFFSET(sbi, (cblock_index)) \
3621 + )
3622 +
3623 +#ifndef TRUE
3624 +#define TRUE 1
3625 +#endif
3626 +#ifndef FALSE
3627 +#define FALSE 0
3628 +#endif
3629 +
3630 +#endif