Magellan Linux

Annotation of /trunk/kernel26-alx/patches-2.6.26-r1/0162-2.6.26-axfs-svn24.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 683 - (hide annotations) (download)
Wed Sep 17 20:01:27 2008 UTC (15 years, 8 months ago) by niro
File size: 105524 byte(s)
-updated to axfs-svn24

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