Magellan Linux

Contents 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 - (show annotations) (download)
Wed Sep 17 20:01:27 2008 UTC (15 years, 7 months ago) by niro
File size: 105524 byte(s)
-updated to axfs-svn24

1 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