Magellan Linux

Annotation 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 - (hide annotations) (download)
Sun Apr 25 14:59:21 2010 UTC (14 years ago) by niro
File size: 98156 byte(s)
-added alx kernel

1 niro 1022 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