axfs patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Dec 2012 20:55:53 +0000 (12:55 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Dec 2012 20:55:53 +0000 (12:55 -0800)
16 files changed:
patches.axfs/axfs-add-documentation.patch [new file with mode: 0644]
patches.axfs/axfs-axfs.h.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_bdev.c.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_fs.h.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_fs_sb.h.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_inode.c.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_mtd.c.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_physmem.c.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_profiling.c.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_super.c.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_uml.c.patch [new file with mode: 0644]
patches.axfs/axfs-axfs_uncompress.c.patch [new file with mode: 0644]
patches.axfs/axfs-kconfigs-and-makefiles.patch [new file with mode: 0644]
patches.axfs/axfs-mount-as-rootfs.patch [new file with mode: 0644]
patches.axfs/axfs-xip-debugging-support.patch [new file with mode: 0644]
series

diff --git a/patches.axfs/axfs-add-documentation.patch b/patches.axfs/axfs-add-documentation.patch
new file mode 100644 (file)
index 0000000..49f9655
--- /dev/null
@@ -0,0 +1,356 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:50:56 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:15:14 +0530
+Subject: [PATCH v2 RESEND 14/15] AXFS: Add documentation
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF61CA.4020603@ap.sony.com>
+
+
+From: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+
+Documentation for AXFS.
+
+Signed-off-by: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ Documentation/filesystems/axfs.txt |  333 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 333 insertions(+)
+  create mode 100644 Documentation/filesystems/axfs.txt
+
+--- /dev/null
++++ b/Documentation/filesystems/axfs.txt
+@@ -0,0 +1,333 @@
++AXFS user manual
++
++
++1. Overview
++===========
++
++Advanced XIP File System (AXFS) is readonly file system for
++Linux. AXFS supports compression of file and execution of XIP
++(eXecute-In-Place).
++
++XIP can reduce system memory requirements. It doesn't load binary
++text to RAM and executes text directly from memory where they are
++stored. Devices such as NOR flash and memory which is directly
++addressable can be used.
++
++Whether a file is XIP or compressed can be specified in 1 page (4KB)
++units. By this, it is possible to make the image size smaller than a
++file system which is specified in file unit such as cramfs-xip.
++
++To determine which page in a file is XIP or compressed, AXFS provides
++profile utility.
++
++Refer to the following link for details of AXFS.
++
++  http://axfs.sourceforge.net/wordpress/
++  or:
++  http://elinux.org/AXFS
++
++
++2. AXFS specification overview
++==============================
++
++               Item                 |   cramfs-xip   |    AXFS
++-----------+------------------------+----------------+----------------
++           | Compression of data    |       Y        |      Y
++           +------------------------+----------------+----------------
++           |Compression of metadata |       N        |      N
++Compression+------------------------+----------------+----------------
++related    + Fragment processing    |       N        |      Y
++           +------------------------+----------------+----------------
++           |Change of compression   |       N        |      Y
++           |               algorithm|                |
++-----------+------------------------+----------------+----------------
++           |Restoration of mode     |       Y        |      Y
++           +------------------------+----------------+----------------
++           |Restoration of uid ,gid |       N        |      Y
++           +------------------------+----------------+----------------
++File       |Restoration of file     |       N        |      N
++related    |      modify date & time|                |
++           +------------------------+----------------+----------------
++           |Max Length of file name | 252 characters | 255 characters
++           +------------------------+----------------+----------------
++           |The maximum size of file| Less than 16MB | Less than 2GB *1
++           +------------------------+----------------+----------------
++           |The maximum size        |    256MB       | Less than 2GB *1
++           |          of file system|                |
++-----------+------------------------+----------------+----------------
++           |XIP Unit                |    File        | Page, file
++           +------------------------+----------------+----------------
++XIP related|Binary XIP              |       Y        |      Y
++           +------------------------+----------------+----------------
++           |Shared Library XIP      |       Y        |      Y
++           +------------------------+----------------+----------------
++           |XIP profile             |       N        |      Y
++-----------+------------------------+----------------+----------------
++           |Supporting byte order   |       N        |      Y *2
++Others     +------------------------+----------------+----------------
++           |Writable                |       N        |      N
++-----------+------------------------+----------------+----------------
++
++     *1. It is not confirmed on the actual device
++     *2. It is confirmed on source code but not tested on the actual device.
++
++
++3. AXFS configuration of kernel
++===============================
++
++Set it from make menuconfig of kernel as follows in order to use AXFS.
++
++  File systems  --->
++    Miscellaneous filesystems  --->
++      <*> Advanced XIP File System (AXFS) support (EXPERIMENTAL)
++      [*]   Profiling extensions for AXFS (EXPERIMENTAL)
++      [ ]   First Mount AXFS as Rootfs
++      [ ]   AXFS debugging support
++
++Enabling "Profiling extensions for AXFS" makes profile function of
++AXFS valid. A CSV file which specifies which file and which page of
++this file to be XIP can be created based on the profile information
++which can be acquired by this configuration.
++
++In case of making AXFS image as rootfs, kernel mounts AXFS image prior
++to NFS when booting if "First Mount AXFS as Rootfs" is set.
++
++
++4. Using AXFS
++=============
++
++There are 2 tools for AXFS. They are mkfs.axfs and axfs_csv2xml.rb.
++mkfs.axfs is a tool to create AXFS image. axfs_csv2xml.rb is a tool to
++convert profile data of AXFS to XML format file which can be read by
++mkfs.axfs. mkfs.axfs reads the specified XML file and set the pages to
++be XIP. The mkfs.axfs tool can also read the csv file format and set
++the pages to be XIP.
++
++4.1. Creating AXFS image
++------------------------
++
++AXFS image can be created by mkfs.axfs tool. Usage of mkfs.axfs is as
++follows :
++
++  mkfs.axfs [-h] [-i infile] dirname outfile
++
++  -h       : Output of help
++  -i infile: Specifies XML/CSV file of XIP information
++
++4.2. AXFS image
++---------------
++
++For example:
++
++  $ mkfs.axfs -i axfs-xip-profile.csv axfs-root-dir axfs-rootfs.image
++
++If it is successful, the following message will be outputted :
++
++    ......
++    number of files:                        501
++    number of 4KB nodes:                    2910
++    number of 4KB xip nodes:                235   <-
++    number of xip files:                    9     <-
++    ......
++    Total image size:                       8363941
++
++The above arrow parts are XIP information. In this case there are 9
++XIP files and the number of pages inside these XIP files are 235.
++
++4.3. Mounting and unmounting AXFS image
++---------------------------------------
++
++4.3.1. Mounting method
++----------------------
++
++The examples for mounting AXFS image are given below.
++
++4.3.1.1. AXFS mount on an embedded board: KZM-ARM11
++---------------------------------------------------
++
++The following example is to write AXFS image to NOR flash of KZM-ARM11
++target and then mount it.
++
++In this example, the AXFS image will be written to "root" partition of
++NOR flash.  From the following output of the kernel booting message,
++
++    physmap platform flash device: 04000000 at a0000000
++    ...
++    5 RedBoot partitions found on MTD device physmap-flash.0
++    Creating 5 MTD partitions on "physmap-flash.0":
++    0x00000000-0x00060000 : "RedBoot"
++    0x00080000-0x00280000 : "zImage"
++    0x00400000-0x01400000 : "root"     <-  /dev/mtd2
++    0x01400000-0x01600000 : "kernel"
++    0x03fe0000-0x03fff000 : "FIS directory"
++
++It is clear that the "root" partition size is 16MB and its physical
++address is between
++    0xa0400000-0xa1400000.
++
++AXFS image is assumed to be stored in /tmp/axfs.image.
++
++Flashcp is used in target.
++
++    $ flashcp -v /tmp/axfs.image /dev/mtd2
++    $ mount -t axfs -o physaddr=0xA0400000 none /mnt
++
++AXFS image can be unmounted by the following command :
++
++    $ umount /mnt
++
++4.3.1.2. AXFS mount on an embedded board : KZM-A9
++-------------------------------------------------
++
++The following example is to write AXFS image to RAM of KZM-A9
++and then mount it.
++
++From the following output of iomem that is read from proc entry
++
++   physmap platform RAM device: 0x50000000 to 0x5effffff
++
++   $ cat /proc/iomem
++   20000000-2000ffff : smsc911x.0
++   20000000-2000ffff : smsc911x
++   40000000-486fffff : System RAM
++   40020000-40375023 : Kernel text
++   4038e000-403f0ae3 : Kernel data
++   50000000-5effffff : System RAM  <--Load to RAM start address + 256MB offset
++   e1020000-e102002b : serial
++   e1030000-e103002b : serial
++   ...
++
++Boot the target with following boot parameter  and load axfs.image to RAM
++address 0x50000000.
++
++   console=ttyS1,115200n8 mem=240M rootfstype=axfs ip=on
++
++AXFS.image is assumed to stored in /tmp/axfs.image
++
++tools/axfs/bload.c is used to load axfs.image to System RAM address.
++
++    $ bload /tmp/axfs.image 0x50000000
++    $ mount -t axfs -o physaddr=0x50000000 none /mnt/
++
++AXFS image can be unmounted by the following command
++
++    $ umount /mnt/
++
++4.3.2. In case of rootfs
++------------------------
++
++The examples for mounting AXFS image as rootfs are given below.
++
++4.3.2.1. Mount AXFS as rootfs on KZM-ARM11
++------------------------------------------
++
++The following is an example of specifying /dev/mtd2 which is
++same as example in section 4.3.1.1 as rootfs in KZM-ARM11.
++Set the booting parameter of kernel as follows.
++
++  "console=ttymxc0 mem=128M root=/dev/null rootflags=physaddr=0xa0400000
++  rootfstype=axfs ip=on"
++
++If kernel option "First Mount AXFS as Rootfs" is set , kernel mounts
++AXFS image prior to NFS.
++
++4.3.2.2. Mount AXFS as rootfs on KZM-A9
++---------------------------------------
++
++Set the booting parameters of kernel as follows to mount axfs
++as rootfs for KZM-A9 Board.
++
++  "console=ttyS1,115200n8 root=/dev/null rootflags=physaddr=0x50000000
++   mem=240M rootfstype=axfs ip=on"
++
++kernel mounts AXFS prior to NFS on KZM-A9.
++
++4.4. XIP of AXFS
++----------------
++
++4.4.1. XIP of AXFS
++------------------
++
++XIP image can be created by specifying CSV file which contains the XIP
++information by "-i infile" option when creating AXFS image by
++mkfs.axfs tool.
++
++CSV file contains the following XIP information: file name to be XIP,
++size in page(4KB) unit and offset(page alignment) to be XIP in the
++file.
++
++In case of specifying the file size which is aligned by 4KB to size,
++the whole file becomes XIP.
++
++Whether to make the file in AXFS image compressed or XIP can be
++decided by profiling utility of AXFS.
++
++4.5. Profile utility of AXFS
++----------------------------
++
++Profile utility can be used if kernel option "Profiling extensions for
++AXFS" is set.
++
++With this option set, when AXFS image is mounted, /proc/ interface for
++profile will be created for each mounted image under /proc/axfs/.
++(e.g.: /proc/axfs/volume0)
++
++When Non-XIP program or library in AXFS image is executed, the
++information of executable pages which are paged in and out of RAM are
++recorded to profile.
++
++4.5.1. Acquiring profile data
++-----------------------------
++
++Data of this profile can be obtained by the following command.
++
++  $ cat /proc/axfs/volume0 > /tmp/axfs-xip.profile
++
++4.5.2. Converting profile data
++------------------------------
++
++Profile data of AXFS in CSV file format can be used by mkfs.axfs tool.
++
++
++5. Known problems
++=================
++
++  - 32 bit device file is not supported
++
++    A part of file system from Linux 2.6 supports 32 bit device file.
++    By using this, the value more than 255 can be set for major number
++    and minor number of device file.
++
++    AXFS supports only 16 bit device file.
++
++  - Sequence of mounting and unmounting several AXFS images
++
++    When AXFS profile option is set and several AXFS images are
++    mounted, error message will be outputted and profile of
++    /proc/axfs/ will not be deleted correctly unless unmounting is
++    done in the opposite sequence to the one of mounting.
++
++    e.g.:
++      When the following operation is done,
++
++       mount image 1 -> mount image 2 -> umount image 1 -> umount image 2
++
++      the following error message is outputted.
++
++       "axfs: Error removing proc file private data was NULL."
++
++      In this case, operate in the following sequence.
++
++       mount image 1 -> mount image 2 -> umount image 2 -> umount image 1
++
++
++6. Hints on using AXFS
++======================
++
++  - When using sytem RAM instead of NOR flash for loading and mounting
++    AXFS image, it should be made sure that the location where AXFS image
++    is being loaded is not used by any other component in the system.
++    For e.g. Just after the regular system RAM ('System RAM' from /proc/iomem)
++    there may be a memory which is reserved/isolated by dirvers using
++    memblock_remove().
++
diff --git a/patches.axfs/axfs-axfs.h.patch b/patches.axfs/axfs-axfs.h.patch
new file mode 100644 (file)
index 0000000..8795fe7
--- /dev/null
@@ -0,0 +1,120 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:32:57 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 16:57:13 +0530
+Subject: [PATCH v2 RESEND 02/15] AXFS: axfs.h
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5D91.3080207@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+The AXFS header.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs.h |   96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 96 insertions(+)
+  create mode 100644 fs/axfs/axfs.h
+
+--- /dev/null
++++ b/fs/axfs/axfs.h
+@@ -0,0 +1,96 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Eric Anderson
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *  Sujaya Srinivasan
++ *  Justin Treon
++ *
++ * Project url: http://axfs.sourceforge.net
++ */
++
++#ifndef AXFS_H
++#define AXFS_H
++
++#include <linux/axfs_fs.h>
++#include <linux/axfs_fs_sb.h>
++
++#include <linux/pagemap.h>
++#include <linux/fs.h>
++#include <linux/mount.h>
++
++/* axfs_inode.c */
++struct inode *axfs_create_vfs_inode(struct super_block *, int);
++u64 axfs_get_mode(struct axfs_super *sbi, u64 index);
++u64 axfs_get_uid(struct axfs_super *sbi, u64 index);
++u64 axfs_get_gid(struct axfs_super *sbi, u64 index);
++u64 axfs_get_inode_name_offset(struct axfs_super *sbi, u64 index);
++u64 axfs_get_inode_num_entries(struct axfs_super *sbi, u64 index);
++u64 axfs_get_inode_mode_index(struct axfs_super *sbi, u64 index);
++u64 axfs_get_inode_array_index(struct axfs_super *sbi, u64 index);
++char *axfs_get_inode_name(struct axfs_super *sbi, u64 index);
++
++/* axfs_super.c */
++u64 axfs_get_io_dev_size(struct super_block *sb);
++int axfs_fill_super(struct super_block *sb, void *data, int silent);
++
++struct dentry *axfs_get_sb(struct file_system_type *,
++                                      int, const char *, void *);
++int axfs_physaddr_is_valid(struct axfs_super *sbi);
++int axfs_virtaddr_is_valid(struct axfs_super *sbi);
++int axfs_is_iomem(struct axfs_super *sbi);
++int axfs_is_pointed(struct axfs_super *sbi);
++int axfs_can_xip(struct axfs_super *sbi);
++int axfs_is_physmem(struct axfs_super *sbi);
++int axfs_nodev(struct super_block *sb);
++u64 axfs_fsoffset_to_devoffset(struct axfs_super *sbi, u64 fsoffset);
++extern void kfree(const void *objp);
++
++/* axfs_profiling.c */
++void axfs_profiling_add(struct axfs_super *, unsigned long, unsigned int);
++int axfs_init_profiling(struct axfs_super *);
++int axfs_shutdown_profiling(struct axfs_super *);
++
++/* axfs_mtd.c */
++int axfs_copy_mtd(struct super_block *, void *, u64, u64);
++struct dentry *axfs_get_sb_mtd(struct file_system_type *, int ,
++                             const char *, struct axfs_super *);
++
++void axfs_kill_mtd_super(struct super_block *);
++int axfs_is_dev_mtd(char *, int *);
++int axfs_verify_mtd_sizes(struct super_block *sb, int *err);
++int axfs_map_mtd(struct super_block *);
++void axfs_unmap_mtd(struct super_block *);
++struct mtd_info *axfs_mtd(struct super_block *sb);
++struct mtd_info *axfs_mtd0(struct super_block *sb);
++struct mtd_info *axfs_mtd1(struct super_block *sb);
++int axfs_has_mtd(struct super_block *sb);
++
++/* axfs_bdev.c */
++void axfs_copy_block(struct super_block *, void *, u64, u64);
++struct dentry *axfs_get_sb_bdev(struct file_system_type *, int,
++                              const char *, struct axfs_super *);
++void axfs_kill_block_super(struct super_block *);
++int axfs_is_dev_bdev(char *);
++int axfs_verify_bdev_sizes(struct super_block *sb, int *err);
++struct block_device *axfs_bdev(struct super_block *sb);
++int axfs_has_bdev(struct super_block *sb);
++
++/* axfs_uml.c */
++int axfs_get_uml_address(char *, unsigned long *, unsigned long *);
++
++#ifndef NO_PHYSMEM
++/* axfs_physmem.c */
++void axfs_map_physmem(struct axfs_super *, unsigned long);
++void axfs_unmap_physmem(struct super_block *);
++#endif
++
++#endif
diff --git a/patches.axfs/axfs-axfs_bdev.c.patch b/patches.axfs/axfs-axfs_bdev.c.patch
new file mode 100644 (file)
index 0000000..f77bc4b
--- /dev/null
@@ -0,0 +1,195 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:49:36 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:13:54 +0530
+Subject: [PATCH v2 RESEND 12/15] AXFS: axfs_bdev.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF617A.9000300@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Allows axfs to use block devices or has dummy functions if block
+device support is compiled out of the kernel.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_bdev.c |  170 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 170 insertions(+)
+  create mode 100644 fs/axfs/axfs_bdev.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_bdev.c
+@@ -0,0 +1,170 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * axfs_bdev.c -
++ *   Allows axfs to use block devices or has dummy functions if block
++ *   device support is compiled out of the kernel.
++ *
++ */
++#include "axfs.h"
++
++#include <linux/mount.h>
++#ifdef CONFIG_BLOCK
++#include <linux/buffer_head.h>
++#include <linux/namei.h>
++
++struct block_device *axfs_bdev(struct super_block *sb)
++{
++      return sb->s_bdev;
++}
++
++int axfs_has_bdev(struct super_block *sb)
++{
++      if (axfs_bdev(sb) == NULL)
++              return false;
++
++      return true;
++}
++
++struct dentry *axfs_get_sb_bdev(struct file_system_type *fs_type, int flags,
++                   const char *dev_name, struct axfs_super *sbi)
++{
++      return mount_bdev(fs_type, flags, dev_name, sbi, axfs_fill_super);
++}
++
++void axfs_kill_block_super(struct super_block *sb)
++{
++      kill_block_super(sb);
++}
++
++void axfs_copy_block(struct super_block *sb, void *dst_addr, u64 fsoffset,
++                   u64 len)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      u64 boffset = axfs_fsoffset_to_devoffset(sbi, fsoffset);
++      u64 blksize = sb->s_blocksize;
++      unsigned long dst;
++      unsigned long src;
++      sector_t block;
++      size_t bytes;
++      struct buffer_head *bh;
++      u64 copied = 0;
++
++      if (len == 0)
++              return;
++
++      while (copied < len) {
++              /* Explicit casting for ARM linker errors. */
++              block = (sector_t) boffset + (sector_t) copied;
++              block = div64_u64(block, (sector_t) blksize);
++              bh = sb_bread(sb, block);
++              src = (unsigned long)bh->b_data;
++              dst = (unsigned long)dst_addr;
++              if (copied == 0) {
++                      /* Explicit casting for ARM linker errors. */
++                      bytes = (size_t) blksize;
++                      bytes -= (size_t) boffset % (size_t) blksize;
++                      if (bytes > len)
++                              bytes = len;
++                      /* Explicit casting for ARM linker errors. */
++                      src += (unsigned long)boffset % (unsigned long)blksize;
++              } else {
++                      dst += copied;
++                      if ((len - copied) < blksize)
++                              bytes = len - copied;
++                      else
++                              bytes = blksize;
++              }
++              memcpy((void *)dst, (void *)src, bytes);
++              copied += bytes;
++              brelse(bh);
++      }
++}
++
++int axfs_is_dev_bdev(char *path)
++{
++      struct nameidata nd;
++      int ret = false;
++
++      if (!path)
++              return false;
++      nd.flags |= LOOKUP_FOLLOW;
++      if (kern_path_parent(path, &nd))
++              return false;
++
++      if (S_ISBLK(nd.path.dentry->d_inode->i_mode))
++              ret = true;
++
++      path_put(&nd.path);
++      return ret;
++}
++
++int axfs_verify_bdev_sizes(struct super_block *sb, int *err)
++{
++      u64 io_dev_size;
++      loff_t bdev_size;
++
++      *err = 0;
++
++      if (!axfs_has_bdev(sb))
++              return false;
++
++      io_dev_size = axfs_get_io_dev_size(sb);
++
++      if (!io_dev_size)
++              return false;
++
++      bdev_size = i_size_read(axfs_bdev(sb)->bd_inode);
++      if (io_dev_size <= bdev_size)
++              return true;
++
++      printk(KERN_ERR "axfs: image (%lluB) doesn't fit in blkdev(%lluB)\n",
++             io_dev_size, bdev_size);
++      *err = -EIO;
++      return true;
++}
++
++#else
++
++int axfs_get_sb_bdev(struct file_system_type *fs_type, int flags,
++                   const char *dev_name, struct axfs_super *sbi,
++                   struct vfsmount *mnt, int *err)
++{
++      return false;
++}
++
++void axfs_kill_block_super(struct super_block *sb)
++{
++}
++
++int axfs_copy_block(struct super_block *sb, void *dst_addr, u64 fsoffset,
++                  u64 len)
++{
++      return -EINVAL;
++}
++
++int axfs_is_dev_bdev(char *path)
++{
++      return false;
++}
++
++int axfs_verify_bdev_sizes(struct super_block *sb, int *err)
++{
++      *err = 0;
++      return true;
++}
++
++#endif /* CONFIG_BLOCK */
diff --git a/patches.axfs/axfs-axfs_fs.h.patch b/patches.axfs/axfs-axfs_fs.h.patch
new file mode 100644 (file)
index 0000000..1debd34
--- /dev/null
@@ -0,0 +1,147 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:34:37 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 16:58:55 +0530
+Subject: [PATCH v2 RESEND 03/15] AXFS: axfs_fs.h
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5DF7.1040709@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+The AXFS on media superblock declaration.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ include/linux/axfs_fs.h |  124 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 124 insertions(+)
+  create mode 100644 include/linux/axfs_fs.h
+
+--- /dev/null
++++ b/include/linux/axfs_fs.h
+@@ -0,0 +1,124 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Eric Anderson
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *  Sujaya Srinivasan
++ *  Justin Treon
++ *
++ * Project url: http://axfs.sourceforge.net
++ */
++
++#ifndef AXFS_FS_H
++#define AXFS_FS_H
++
++#include <linux/axfs_fs_sb.h>
++
++#ifdef __KERNEL__
++#include <linux/rwsem.h>
++#endif
++#include <linux/errno.h>
++#include <linux/time.h>
++
++#include <linux/pagemap.h>
++#include <linux/fs.h>
++#include <linux/mount.h>
++
++#define AXFS_MAGIC    0x48A0E4CD      /* some random number */
++#define AXFS_SIGNATURE        "Advanced XIP FS"
++#define AXFS_MAXPATHLEN 255
++
++
++/* Uncompression interfaces to the underlying zlib */
++int axfs_uncompress_block(void *, int, void *, int);
++int axfs_uncompress_init(void);
++int axfs_uncompress_exit(void);
++
++struct axfs_profiling_data {
++      u64 inode_number;
++      unsigned long count;
++};
++
++enum axfs_node_types {
++      XIP = 0,
++      Compressed,
++      Byte_Aligned,
++};
++
++enum axfs_compression_types {
++      ZLIB = 0
++};
++
++/* on media struct describing a data region */
++struct axfs_region_desc_onmedia {
++      u64 fsoffset;
++      u64 size;
++      u64 compressed_size;
++      u64 max_index;
++      u8 table_byte_depth;
++      u8 incore;
++};
++
++/* on media format for the super block */
++struct axfs_super_onmedia {
++      __be32 magic;           /* 0x48A0E4CD - random number */
++      u8 signature[16];       /* "Advanced XIP FS" */
++      u8 digest[40];          /* sha1 digest for checking data integrity */
++      __be32 cblock_size;     /* maximum size of the block being compressed */
++      __be64 files;           /* number of inodes/files in fs */
++      __be64 size;            /* total image size */
++      __be64 blocks;          /* number of nodes in fs */
++      __be64 mmap_size;       /* size of the memory mapped part of image */
++      __be64 strings;         /* offset to strings region descriptor */
++      __be64 xip;             /* offset to xip region descriptor */
++      __be64 byte_aligned;    /* offset to the byte aligned region desc */
++      __be64 compressed;      /* offset to the compressed region desc */
++      __be64 node_type;       /* offset to node type region desc */
++      __be64 node_index;      /* offset to node index region desc */
++      __be64 cnode_offset;    /* offset to cnode offset region desc */
++      __be64 cnode_index;     /* offset to cnode index region desc */
++      __be64 banode_offset;   /* offset to banode offset region desc */
++      __be64 cblock_offset;   /* offset to cblock offset region desc */
++      __be64 inode_file_size; /* offset to inode file size desc */
++      __be64 inode_name_offset;/* offset to inode num_entries region desc */
++      __be64 inode_num_entries;/* offset to inode num_entries region desc */
++      __be64 inode_mode_index;/* offset to inode mode index region desc */
++      __be64 inode_array_index;/* offset to inode node index region desc */
++      __be64 modes;           /* offset to mode mode region desc */
++      __be64 uids;            /* offset to mode uid index region desc */
++      __be64 gids;            /* offset to mode gid index region desc */
++      u8 version_major;
++      u8 version_minor;
++      u8 version_sub;
++      u8 compression_type;    /* Identifies type of compression used on FS */
++      __be64 timestamp;       /* UNIX time_t of filesystem build time */
++      u8 page_shift;
++};
++
++#define AXFS_SB(sb) ((struct axfs_super *)((sb)->s_fs_info))
++
++static inline u64 axfs_bytetable_stitch(u8 depth, u8 *table, u64 index)
++{
++      u64 i;
++      u64 output = 0;
++      u64 byte = 0;
++      u64 j;
++      u64 bits;
++
++      for (i = 0; i < depth; i++) {
++              j = index * depth + i;
++              bits = 8 * (depth - i - 1);
++              byte = table[j];
++              output += byte << bits;
++      }
++      return output;
++}
++#endif
diff --git a/patches.axfs/axfs-axfs_fs_sb.h.patch b/patches.axfs/axfs-axfs_fs_sb.h.patch
new file mode 100644 (file)
index 0000000..719a7ff
--- /dev/null
@@ -0,0 +1,110 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:37:53 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:02:11 +0530
+Subject: [PATCH v2 RESEND 04/15] AXFS: axfs_fs_sb.h
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5EBB.7080202@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+The AXFS superblock declaration.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ include/linux/axfs_fs_sb.h |   87 +++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 87 insertions(+)
+  create mode 100644 include/linux/axfs_fs_sb.h
+
+--- /dev/null
++++ b/include/linux/axfs_fs_sb.h
+@@ -0,0 +1,87 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Eric Anderson
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *  Sujaya Srinivasan
++ *  Justin Treon
++ *
++ * Project url: http://axfs.sourceforge.net
++ */
++
++#ifndef AXFS_FS_SB_H
++#define AXFS_FS_SB_H
++
++#ifdef __KERNEL__
++#include <linux/rwsem.h>
++#endif
++#include <linux/errno.h>
++#include <linux/time.h>
++
++/* in memory region descriptor */
++struct axfs_region_desc {
++      u64 fsoffset;
++      u64 size;
++      u64 compressed_size;
++      u64 max_index;
++      void *virt_addr;
++      u8 table_byte_depth;
++      u8 incore;
++};
++
++/* axfs super-block data in memory */
++struct axfs_super {
++      u32 magic;
++      u8 version_major;
++      u8 version_minor;
++      u8 version_sub;
++      u8 padding;
++      u64 files;
++      u64 size;
++      u64 blocks;
++      u64 mmap_size;
++      struct axfs_region_desc strings;
++      struct axfs_region_desc xip;
++      struct axfs_region_desc compressed;
++      struct axfs_region_desc byte_aligned;
++      struct axfs_region_desc node_type;
++      struct axfs_region_desc node_index;
++      struct axfs_region_desc cnode_offset;
++      struct axfs_region_desc cnode_index;
++      struct axfs_region_desc banode_offset;
++      struct axfs_region_desc cblock_offset;
++      struct axfs_region_desc inode_file_size;
++      struct axfs_region_desc inode_name_offset;
++      struct axfs_region_desc inode_num_entries;
++      struct axfs_region_desc inode_mode_index;
++      struct axfs_region_desc inode_array_index;
++      struct axfs_region_desc modes;
++      struct axfs_region_desc uids;
++      struct axfs_region_desc gids;
++      unsigned long phys_start_addr;
++      unsigned long virt_start_addr;
++      char *second_dev;
++      unsigned long iomem_size;
++      void *mtd0;             /* primary device */
++      void *mtd1;             /* secondary device */
++      u32 cblock_size;
++      u64 current_cnode_index;
++      void *cblock_buffer[2];
++      struct rw_semaphore lock;
++      struct axfs_profiling_data *profile_data_ptr;
++      u8 profiling_on;        /* Determines if profiling is on or off */
++      u8 mtd_pointed;
++      u8 compression_type;
++      struct timespec timestamp;
++      u8 page_shift;
++};
++
++#endif
diff --git a/patches.axfs/axfs-axfs_inode.c.patch b/patches.axfs/axfs-axfs_inode.c.patch
new file mode 100644 (file)
index 0000000..18c73ad
--- /dev/null
@@ -0,0 +1,660 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:39:18 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:03:35 +0530
+Subject: [PATCH v2 RESEND 05/15] AXFS: axfs_inode.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5F0F.8010403@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Contains the most of the filesystem logic with the major exception
+of the mounting infrastructure.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_inode.c |  636 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 636 insertions(+)
+  create mode 100644 fs/axfs/axfs_inode.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_inode.c
+@@ -0,0 +1,636 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2009, 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Eric Anderson
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *  Sujaya Srinivasan
++ *  Justin Treon
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * Borrowed heavily from fs/cramfs/inode.c by Linus Torvalds
++ *
++ * axfs_inode.c -
++ *   Contains the most of the filesystem logic with the major exception of the
++ *   mounting infrastructure.
++ *
++ */
++#include "axfs.h"
++
++
++static const struct file_operations axfs_directory_operations;
++static const struct file_operations axfs_fops;
++static const struct address_space_operations axfs_aops;
++static struct inode_operations axfs_dir_inode_operations;
++static struct vm_operations_struct axfs_vm_ops;
++
++static inline u64 axfs_get_node_type(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->node_type.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->node_type.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_node_index(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->node_index.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->node_index.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_is_node_xip(struct axfs_super *sbi, u64 index)
++{
++      if (axfs_get_node_type(sbi, index) == XIP)
++              return true;
++
++      return false;
++}
++
++static inline u64 axfs_get_cnode_index(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->cnode_index.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->cnode_index.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_cnode_offset(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->cnode_offset.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->cnode_offset.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_banode_offset(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->banode_offset.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->banode_offset.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_cblock_offset(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->cblock_offset.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->cblock_offset.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_inode_file_size(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->inode_file_size.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->inode_file_size.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++u64 axfs_get_mode(struct axfs_super *sbi, u64 index)
++{
++      u64 mode = axfs_get_inode_mode_index(sbi, index);
++      u64 depth = sbi->modes.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->modes.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, mode);
++}
++
++u64 axfs_get_uid(struct axfs_super *sbi, u64 index)
++{
++      u64 mode = axfs_get_inode_mode_index(sbi, index);
++      u64 depth = sbi->uids.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->uids.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, mode);
++}
++
++u64 axfs_get_gid(struct axfs_super *sbi, u64 index)
++{
++      u64 mode = axfs_get_inode_mode_index(sbi, index);
++      u64 depth = sbi->gids.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->gids.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, mode);
++}
++
++u64 axfs_get_inode_name_offset(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->inode_name_offset.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->inode_name_offset.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++u64 axfs_get_inode_num_entries(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->inode_num_entries.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->inode_num_entries.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++u64 axfs_get_inode_mode_index(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->inode_mode_index.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->inode_mode_index.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++u64 axfs_get_inode_array_index(struct axfs_super *sbi, u64 index)
++{
++      u64 depth = sbi->inode_array_index.table_byte_depth;
++      u8 *vaddr = (u8 *) sbi->inode_array_index.virt_addr;
++
++      return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++char *axfs_get_inode_name(struct axfs_super *sbi, u64 index)
++{
++      u64 ofs = axfs_get_inode_name_offset(sbi, index);
++      u8 *virt = sbi->strings.virt_addr;
++
++      return (char *)(ofs + virt);
++}
++
++static inline u64 axfs_get_xip_region_physaddr(struct axfs_super *sbi)
++{
++      return sbi->phys_start_addr + sbi->xip.fsoffset;
++}
++
++static inline int axfs_region_is_vmalloc(struct axfs_super *sbi,
++                                       struct axfs_region_desc *region)
++{
++      u64 va = (u32) region->virt_addr;
++      u64 vo = (u64) region->fsoffset + (u64) sbi->virt_start_addr;
++
++      if (va == 0)
++              return false;
++
++      if (vo != va)
++              return true;
++
++      return false;
++}
++
++static int axfs_copy_data(struct super_block *sb, void *dst,
++                        struct axfs_region_desc *region, u64 offset, u64 len)
++{
++      u64 mmapped = 0;
++      u64 end = region->fsoffset + offset + len;
++      u64 begin = region->fsoffset + offset;
++      u64 left;
++      void *addr;
++      void *newdst;
++      struct axfs_super *sbi = AXFS_SB(sb);
++
++      if (len == 0)
++              return 0;
++
++      if (axfs_region_is_vmalloc(sbi, region)) {
++              mmapped = len;
++      } else if (region->virt_addr) {
++              if (sbi->mmap_size >= end)
++                      mmapped = len;
++              else if (sbi->mmap_size > begin)
++                      mmapped = sbi->mmap_size - begin;
++      }
++
++      if (mmapped) {
++              addr = (void *)(region->virt_addr + offset);
++              memcpy(dst, addr, mmapped);
++      }
++
++      newdst = (void *)(dst + mmapped);
++      left = len - mmapped;
++
++      if (left == 0)
++              return len;
++
++      if (axfs_has_bdev(sb))
++              axfs_copy_block(sb, newdst, begin + mmapped, left);
++      else if (axfs_has_mtd(sb))
++              return axfs_copy_mtd(sb, newdst, begin + mmapped, left);
++
++      return 0;
++}
++
++static int axfs_iget5_test(struct inode *inode, void *opaque)
++{
++      u64 *inode_number = (u64 *) opaque;
++
++      if (inode->i_sb == NULL) {
++              printk(KERN_ERR "axfs_iget5_test:"
++                     " the super block is set to null\n");
++      }
++      if (inode->i_ino == *inode_number)
++              return 1;       /* matches */
++      else
++              return 0;       /* does not match */
++}
++
++static int axfs_iget5_set(struct inode *inode, void *opaque)
++{
++      u64 *inode_number = (u64 *) opaque;
++
++      if (inode->i_sb == NULL) {
++              printk(KERN_ERR "axfs_iget5_set:"
++                     " the super block is set to null\n");
++      }
++      inode->i_ino = *inode_number;
++      return 0;
++}
++
++struct inode *axfs_create_vfs_inode(struct super_block *sb, int ino)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      struct inode *inode;
++      u64 size;
++
++      inode = iget5_locked(sb, ino, axfs_iget5_test, axfs_iget5_set, &ino);
++
++      if (!(inode && (inode->i_state & I_NEW)))
++              return inode;
++
++      inode->i_mode = axfs_get_mode(sbi, ino);
++      inode->i_uid = axfs_get_uid(sbi, ino);
++      size = axfs_get_inode_file_size(sbi, ino);
++      inode->i_size = size;
++      inode->i_blocks = axfs_get_inode_num_entries(sbi, ino);
++      inode->i_blkbits = PAGE_CACHE_SHIFT;
++      inode->i_gid = axfs_get_gid(sbi, ino);
++
++      inode->i_mtime = inode->i_atime = inode->i_ctime = sbi->timestamp;
++      inode->i_ino = ino;
++
++      if (S_ISREG(inode->i_mode)) {
++              inode->i_fop = &axfs_fops;
++              inode->i_data.a_ops = &axfs_aops;
++              inode->i_mapping->a_ops = &axfs_aops;
++      } else if (S_ISDIR(inode->i_mode)) {
++              inode->i_op = &axfs_dir_inode_operations;
++              inode->i_fop = &axfs_directory_operations;
++      } else if (S_ISLNK(inode->i_mode)) {
++              inode->i_op = &page_symlink_inode_operations;
++              inode->i_data.a_ops = &axfs_aops;
++      } else {
++              inode->i_size = 0;
++              inode->i_blocks = 0;
++              init_special_inode(inode, inode->i_mode, old_decode_dev(size));
++      }
++      unlock_new_inode(inode);
++
++      return inode;
++}
++
++static int axfs_get_xip_mem(struct address_space *mapping, pgoff_t offset,
++                          int create, void **kaddr, unsigned long *pfn)
++{
++      struct inode *inode = mapping->host;
++      struct super_block *sb = inode->i_sb;
++      struct axfs_super *sbi = AXFS_SB(sb);
++      u64 ino_number = inode->i_ino;
++      u64 ino_index, node_index;
++
++      ino_index = axfs_get_inode_array_index(sbi, ino_number);
++      ino_index += offset;
++
++      node_index = axfs_get_node_index(sbi, ino_index);
++
++      *kaddr = (void *)(sbi->xip.virt_addr + (node_index << PAGE_SHIFT));
++
++      if (axfs_region_is_vmalloc(sbi, &(sbi->xip))) {
++              *pfn = vmalloc_to_pfn(*kaddr);
++      } else if (axfs_physaddr_is_valid(sbi)) {
++              *pfn = (axfs_get_xip_region_physaddr(sbi) >> PAGE_SHIFT);
++              *pfn += node_index;
++      } else {
++              *pfn = page_to_pfn(virt_to_page(*kaddr));
++      }
++
++      return 0;
++}
++
++static int axfs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++
++      file_accessed(file);
++
++      vma->vm_ops = &axfs_vm_ops;
++
++#ifdef VM_MIXEDMAP
++#ifdef VM_CAN_NONLINEAR
++      vma->vm_flags |= VM_CAN_NONLINEAR | VM_MIXEDMAP;
++#else
++      vma->vm_flags |= VM_IO | VM_MIXEDMAP;
++#endif
++#else
++#ifdef VM_PFNMAP
++      vma->vm_flags |= VM_IO | VM_PFNMAP;
++#else
++      vma->vm_flags |= VM_IO;
++#endif
++#endif
++#ifdef VM_XIP
++      vma->vm_flags |= VM_XIP;
++#endif
++
++      return 0;
++}
++
++/* The loop does a handful of things:
++ * - First we see if they're the same length, if not we don't care.
++ * - Then, we do a strncmp on two same-length strings:
++ *  > -1 -> If the entry was in this directory, it would have been
++ *      right before this one.
++ *  >  1 -> It's somewhere farther along in this directory.
++ */
++static struct dentry *axfs_lookup(struct inode *dir, struct dentry *dentry,
++                                struct nameidata *nd)
++{
++      struct super_block *sb = dir->i_sb;
++      struct axfs_super *sbi = AXFS_SB(sb);
++      u64 ino_number = dir->i_ino;
++      u64 dir_index = 0;
++      u64 entry;
++      char *name;
++      int namelen, err;
++
++      while (dir_index < axfs_get_inode_num_entries(sbi, ino_number)) {
++              entry = axfs_get_inode_array_index(sbi, ino_number);
++              entry += dir_index;
++
++              name = axfs_get_inode_name(sbi, entry);
++              namelen = strlen(name);
++
++              dir_index++;
++
++              if (dentry->d_name.len != namelen)
++                      continue;
++
++              err = strncmp(dentry->d_name.name, name, namelen);
++
++              if (err < 0)
++                      break;
++
++              if (err > 0)
++                      continue;
++
++              d_add(dentry, axfs_create_vfs_inode(dir->i_sb, entry));
++              goto out;
++
++      }
++      d_add(dentry, NULL);
++
++out:
++      return NULL;
++}
++
++static int axfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
++{
++      struct inode *inode = filp->f_dentry->d_inode;
++      struct super_block *sb = inode->i_sb;
++      struct axfs_super *sbi = AXFS_SB(sb);
++      u64 ino_number = inode->i_ino;
++      u64 entry;
++      loff_t dir_index;
++      char *name;
++      int namelen, mode;
++      int err = 0;
++
++      /*
++       * Get the current index into the directory and verify it is not beyond
++       * the end of the list
++       */
++      dir_index = filp->f_pos;
++      if (dir_index >= axfs_get_inode_num_entries(sbi, ino_number))
++              goto out;
++
++      while (dir_index < axfs_get_inode_num_entries(sbi, ino_number)) {
++              entry = axfs_get_inode_array_index(sbi, ino_number) + dir_index;
++
++              name = axfs_get_inode_name(sbi, entry);
++              namelen = strlen(name);
++
++              mode = (int)axfs_get_mode(sbi, entry);
++              err = filldir(dirent, name, namelen, dir_index, entry, mode);
++
++              if (err)
++                      break;
++
++              dir_index++;
++              filp->f_pos = dir_index;
++      }
++
++out:
++      return 0;
++}
++
++/******************************************************************************
++ *
++ * axfs_fault
++ *
++ * Description: This function is mapped into the VMA operations vector, and
++ *          gets called on a page fault. Depending on whether the page
++ *          is XIP or compressed, xip_file_fault or filemap_fault is
++ *          called.  This function also logs when a fault occurs when
++ *          profiling is on.
++ *
++ * Parameters:
++ *    (IN) vma  - The virtual memory area corresponding to a file
++ *
++ *    (IN) vmf  - The fault info pass in by the fault handler
++ *
++ * Returns:
++ *    0 or error number
++ *
++ *****************************************************************************/
++static int axfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++      struct file *file = vma->vm_file;
++      struct inode *inode = file->f_dentry->d_inode;
++      struct super_block *sb = inode->i_sb;
++      struct axfs_super *sbi = AXFS_SB(sb);
++      u64 ino_number = inode->i_ino;
++      u64 array_index;
++
++      array_index = axfs_get_inode_array_index(sbi, ino_number) + vmf->pgoff;
++
++      /*
++       * if that pages are marked for write they will probably end up in RAM
++       * therefore we don't want their counts for being XIP'd
++       */
++      if (!(vma->vm_flags & VM_WRITE))
++              axfs_profiling_add(sbi, array_index, ino_number);
++
++      /*
++       * figure out if the node is XIP or compressed and call the
++       * appropriate function
++       */
++      if (axfs_is_node_xip(sbi, array_index))
++              return xip_file_fault(vma, vmf);
++      return filemap_fault(vma, vmf);
++}
++
++/******************************************************************************
++ *
++ * axfs_file_read
++ *
++ * Description: axfs_file_read is mapped into the file_operations vector for
++ *          all axfs files. It loops through the pages to be read and calls
++ *          either do_sync_read (if the page is a compressed one) or
++ *          xip_file_read (if the page is XIP).
++ *
++ * Parameters:
++ *    (IN) filp -  file to be read
++ *
++ *    (OUT) buf - user buffer that is filled with the data that we read.
++ *
++ *    (IN) len - length of file to be read
++ *
++ *    (IN) ppos - offset within the file to read from
++ *
++ * Returns:
++ *    actual size of data read.
++ *
++ *****************************************************************************/
++static ssize_t axfs_file_read(struct file *filp, char __user *buf, size_t len,
++                            loff_t *ppos)
++{
++      struct inode *inode = filp->f_dentry->d_inode;
++      struct super_block *sb = inode->i_sb;
++      struct axfs_super *sbi = AXFS_SB(sb);
++      size_t read = 0, total_read = 0;
++      size_t readlength, actual_size, file_size, remaining;
++      u64 ino_number = inode->i_ino;
++      u64 size, array_index;
++
++      file_size = axfs_get_inode_file_size(sbi, ino_number);
++      remaining = file_size - *ppos;
++      actual_size = len > remaining ? remaining : len;
++      readlength = actual_size < PAGE_SIZE ? actual_size : PAGE_SIZE;
++
++      for (size = actual_size; size > 0; size -= read) {
++              array_index = axfs_get_inode_array_index(sbi, ino_number);
++              array_index += *ppos >> PAGE_SHIFT;
++
++              if (axfs_is_node_xip(sbi, array_index))
++                      read = xip_file_read(filp, buf, readlength, ppos);
++              else
++                      read = do_sync_read(filp, buf, readlength, ppos);
++
++              buf += read;
++              total_read += read;
++
++              if ((len - total_read < PAGE_SIZE) && (total_read != len))
++                      readlength = len - total_read;
++      }
++
++      return total_read;
++}
++
++static int axfs_readpage(struct file *file, struct page *page)
++{
++      struct inode *inode = page->mapping->host;
++      struct super_block *sb = inode->i_sb;
++      struct axfs_super *sbi = AXFS_SB(sb);
++      u64 array_index, node_index, cnode_index, maxblock, ofs;
++      u64 ino_number = inode->i_ino;
++      u32 max_len, cnode_offset;
++      u32 cblk_size = sbi->cblock_size;
++      u32 len = 0;
++      u8 node_type;
++      void *pgdata;
++      void *src;
++      void *cblk0 = sbi->cblock_buffer[0];
++      void *cblk1 = sbi->cblock_buffer[1];
++
++      maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++      pgdata = kmap(page);
++
++      if (page->index >= maxblock)
++              goto out;
++
++      array_index = axfs_get_inode_array_index(sbi, ino_number);
++      array_index += page->index;
++
++      node_index = axfs_get_node_index(sbi, array_index);
++      node_type = axfs_get_node_type(sbi, array_index);
++
++      if (node_type == Compressed) {
++              /* node is in compessed region */
++              cnode_offset = axfs_get_cnode_offset(sbi, node_index);
++              cnode_index = axfs_get_cnode_index(sbi, node_index);
++              down_write(&sbi->lock);
++              if (cnode_index != sbi->current_cnode_index) {
++                      /* uncompress only necessary if different cblock */
++                      ofs = axfs_get_cblock_offset(sbi, cnode_index);
++                      len = axfs_get_cblock_offset(sbi, cnode_index + 1);
++                      len -= ofs;
++                      axfs_copy_data(sb, cblk1, &(sbi->compressed), ofs, len);
++                      axfs_uncompress_block(cblk0, cblk_size, cblk1, len);
++                      sbi->current_cnode_index = cnode_index;
++              }
++              downgrade_write(&sbi->lock);
++              max_len = cblk_size - cnode_offset;
++              len = max_len > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : max_len;
++              src = (void *)((unsigned long)cblk0 + cnode_offset);
++              memcpy(pgdata, src, len);
++              up_read(&sbi->lock);
++      } else if (node_type == Byte_Aligned) {
++              /* node is in BA region */
++              ofs = axfs_get_banode_offset(sbi, node_index);
++              max_len = sbi->byte_aligned.size - ofs;
++              len = max_len > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : max_len;
++              axfs_copy_data(sb, pgdata, &(sbi->byte_aligned), ofs, len);
++      } else {
++              /* node is XIP */
++              ofs = node_index << PAGE_SHIFT;
++              len = PAGE_CACHE_SIZE;
++              axfs_copy_data(sb, pgdata, &(sbi->xip), ofs, len);
++      }
++
++out:
++      memset(pgdata + len, 0, PAGE_CACHE_SIZE - len);
++      kunmap(page);
++      flush_dcache_page(page);
++      SetPageUptodate(page);
++      unlock_page(page);
++      return 0;
++}
++
++static const struct file_operations axfs_directory_operations = {
++      .llseek = generic_file_llseek,
++      .read = generic_read_dir,
++      .readdir = axfs_readdir,
++};
++
++static const struct file_operations axfs_fops = {
++      .read = axfs_file_read,
++      .aio_read = generic_file_aio_read,
++      .mmap = axfs_mmap,
++};
++
++static const struct address_space_operations axfs_aops = {
++      .readpage = axfs_readpage,
++      .get_xip_mem = axfs_get_xip_mem,
++};
++
++static struct inode_operations axfs_dir_inode_operations = {
++      .lookup = axfs_lookup,
++};
++
++static struct vm_operations_struct axfs_vm_ops = {
++      .fault = axfs_fault,
++};
diff --git a/patches.axfs/axfs-axfs_mtd.c.patch b/patches.axfs/axfs-axfs_mtd.c.patch
new file mode 100644 (file)
index 0000000..9aaf564
--- /dev/null
@@ -0,0 +1,376 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:40:42 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:04:58 +0530
+Subject: [PATCH v2 RESEND 06/15] AXFS: axfs_mtd.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5F62.3030809@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Allows axfs to use mtd devices or has dummy functions if mtd
+device support is compiled out of the kernel.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_mtd.c |  351 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 351 insertions(+)
+  create mode 100644 fs/axfs/axfs_mtd.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_mtd.c
+@@ -0,0 +1,351 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * axfs_mtd.c -
++ *   Allows axfs to use mtd devices or has dummy functions if mtd
++ *   device support is compiled out of the kernel.
++ */
++#include "axfs.h"
++
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/ctype.h>
++#include <linux/namei.h>
++
++#ifdef CONFIG_MTD
++#define AXFS_CONFIG_MTD
++#endif
++
++#ifdef AXFS_CONFIG_MTD
++#include <linux/mtd/super.h>
++
++struct mtd_info *axfs_mtd(struct super_block *sb)
++{
++      return (void *)sb->s_mtd;
++}
++
++struct mtd_info *axfs_mtd0(struct super_block *sb)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++
++      if (sbi->mtd0 != NULL)
++              return sbi->mtd0;
++      else
++              return axfs_mtd(sb);
++}
++
++struct mtd_info *axfs_mtd1(struct super_block *sb)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++
++      return sbi->mtd1;
++}
++
++int axfs_has_mtd(struct super_block *sb)
++{
++      if (sb->s_fs_info == NULL)
++              return false;
++
++      if (axfs_mtd0(sb))
++              return true;
++
++      if (axfs_mtd1(sb))
++              return true;
++
++      if (axfs_mtd(sb))
++              return true;
++
++      return false;
++}
++
++struct mtd_info *axfs_get_mtd_device(int mtdnr)
++{
++      struct mtd_info *device;
++
++      device = get_mtd_device(NULL, mtdnr);
++
++      if (!PTR_ERR(device))
++              return NULL;
++
++      return device;
++}
++
++int axfs_is_dev_mtd(char *path, int *mtdnr)
++{
++      char *off = NULL;
++      char *endptr = NULL;
++      char dev[] = "/dev/\0";
++      char mtd[] = "mtd\0";
++      char mtdblk[] = "mtdblock\0";
++
++      if (!path || !*path)
++              return false;
++
++      off = path;
++
++      if (strncmp(dev, off, strlen(dev)) == 0)
++              off += strlen(dev);
++
++      if (!strncmp(mtd, off, strlen(mtd)) && isdigit(off[strlen(mtd)]))
++              off += strlen(mtd);
++
++      if (!strncmp(mtdblk, off, strlen(mtdblk))
++          && isdigit(off[strlen(mtdblk)]))
++              off += strlen(mtdblk);
++
++      *mtdnr = simple_strtoul(off, &endptr, 0);
++
++      if (!*endptr)
++              return true;
++
++      return false;
++}
++
++static struct mtd_info *axfs_get_mtd_info(struct super_block *sb, u64 fsoffset)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++
++      if (fsoffset == 0)
++              return (struct mtd_info *)axfs_mtd0(sb);
++
++      if (fsoffset < sbi->mmap_size)
++              return (struct mtd_info *)axfs_mtd0(sb);
++
++      if (axfs_mtd1(sb) != NULL)
++              return (struct mtd_info *)axfs_mtd1(sb);
++
++      return (struct mtd_info *)axfs_mtd0(sb);
++}
++
++int axfs_copy_mtd(struct super_block *sb, void *dst, u64 fsoffset, u64 len)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      u64 offset = axfs_fsoffset_to_devoffset(sbi, fsoffset);
++      struct mtd_info *mtd;
++      u_char *mtdbuf = (u_char *) dst;
++      size_t retlen;
++      int err = 0;
++
++      if (len == 0)
++              return 0;
++
++      mtd = axfs_get_mtd_info(sb, fsoffset);
++      err = mtd_read(mtd, (loff_t) offset, (size_t) len, &retlen, mtdbuf);
++
++      if (len != retlen)
++              return -EIO;
++
++      return err;
++}
++
++/******************************************************************************
++ *
++ * axfs_map_mtd
++ *
++ * Description: When provided, uses the mtd point() capability to map allow
++ *          axfs a direct memory access to the filesystem.
++ *
++ * Parameters:
++ *    (IN) sb - pointer to the super_block structure
++ *
++ * Returns:
++ *    0 or error number
++ *
++ *****************************************************************************/
++int axfs_map_mtd(struct super_block *sb)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      struct mtd_info *mtd = (struct mtd_info *)axfs_mtd0(sb);
++      size_t retlen;
++      int err = 0;
++      void *virt;
++      resource_size_t phys;
++
++      err = mtd_point(mtd, 0, sbi->mmap_size, &retlen, &virt, &phys);
++      if (err)
++              return err;
++
++      if (retlen != sbi->mmap_size) {
++              mtd_unpoint(mtd, 0, retlen);
++              return -EINVAL;
++      }
++
++      sbi->virt_start_addr = (unsigned long)virt;
++      sbi->phys_start_addr = (unsigned long)phys;
++      sbi->mtd_pointed = true;
++
++      return 0;
++}
++
++void axfs_unmap_mtd(struct super_block *sb)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      struct mtd_info *mtd = (struct mtd_info *)axfs_mtd0(sb);
++
++      if (!sbi)
++              return;
++
++      if (axfs_mtd1(sb))
++              put_mtd_device((struct mtd_info *)axfs_mtd1(sb));
++
++      if (axfs_is_pointed(sbi)) {
++              mtd_unpoint(mtd, 0, sbi->mmap_size);
++      } else {
++              if (axfs_mtd0(sb))
++                      put_mtd_device((struct mtd_info *)axfs_mtd0(sb));
++      }
++}
++
++int axfs_verify_mtd_sizes(struct super_block *sb, int *err)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      struct mtd_info *mtd0 = (struct mtd_info *)axfs_mtd0(sb);
++      struct mtd_info *mtd1 = (struct mtd_info *)axfs_mtd1(sb);
++      u64 io_dev_size;
++
++      *err = 0;
++      io_dev_size = axfs_get_io_dev_size(sb);
++
++      if (!mtd0 && !mtd1)
++              return false;
++
++      /* One mtd device entirely mmaped */
++      if (sbi->mtd_pointed && !io_dev_size) {
++              if (sbi->mmap_size != sbi->size) {
++                      *err = -EINVAL;
++                      return false;
++              }
++
++              return true;
++      }
++
++      if (!io_dev_size)
++              return false;
++
++      /* filesystem split across two mtd devs */
++      if (mtd1) {
++              if (io_dev_size > mtd1->size)
++                      goto too_small;
++              else
++                      return true;
++      }
++
++      /* One mtd device partially mmaped, partially io */
++      if (sbi->mtd_pointed) {
++              if (sbi->size > mtd0->size)
++                      goto too_small;
++              else
++                      return true;
++      }
++
++      /* One mtd device as a IO dev or split with physaddr */
++      if (io_dev_size > mtd0->size)
++              goto too_small;
++
++      return true;
++
++too_small:
++      printk(KERN_ERR "axfs: filesystem extends beyond end of MTD, ");
++      printk(KERN_ERR "expected 0x%llx ", io_dev_size);
++      printk(KERN_ERR "got 0x%llu\n", (mtd1) ? mtd1->size : mtd0->size);
++      *err = -EINVAL;
++      return true;
++}
++
++struct dentry *axfs_get_sb_mtd(struct file_system_type *fs_type, int flags,
++                             const char *dev_name, struct axfs_super *sbi)
++{
++      int *err = ERR_PTR(-EINVAL);
++      int nflags, mtdnr;
++
++      if (axfs_is_dev_mtd(sbi->second_dev, &mtdnr)) {
++              sbi->mtd1 = (void *)axfs_get_mtd_device(mtdnr);
++              if (!sbi->mtd1) {
++                      *err = -EINVAL;
++                      return false;
++              }
++      }
++      nflags = flags & MS_SILENT;
++
++      return mount_mtd(fs_type, nflags, dev_name, sbi, axfs_fill_super);
++}
++
++void axfs_kill_mtd_super(struct super_block *sb)
++{
++      kill_mtd_super(sb);
++}
++#else
++struct mtd_info *axfs_mtd(struct super_block *sb)
++{
++      return NULL;
++}
++
++struct mtd_info *axfs_mtd0(struct super_block *sb)
++{
++      return NULL;
++}
++
++struct mtd_info *axfs_mtd1(struct super_block *sb)
++{
++      return NULL;
++}
++
++int axfs_has_mtd(struct super_block *sb)
++{
++      return false;
++}
++
++struct mtd_info *axfs_get_mtd_device(int mtdnr)
++{
++      return NULL;
++}
++
++int axfs_map_mtd(struct super_block *sb)
++{
++      return 0;
++}
++
++void axfs_unmap_mtd(struct super_block *sb)
++{
++}
++
++int axfs_copy_mtd(struct super_block *sb, void *dst, u64 fsoffset, u64 len)
++{
++      return -EINVAL;
++}
++
++struct dentry *axfs_get_sb_mtd(struct file_system_type *fs_type, int flags,
++                             const char *dev_name, struct axfs_super *sbi)
++{
++      return false;
++}
++
++int axfs_is_dev_mtd(char *path, int *mtdnr)
++{
++      return false;
++}
++
++void axfs_kill_mtd_super(struct super_block *sb)
++{
++}
++
++int axfs_verify_mtd_sizes(struct super_block *sb, int *err)
++{
++      *err = 0;
++      return true;
++}
++
++#endif /* CONFIG_MTD */
diff --git a/patches.axfs/axfs-axfs_physmem.c.patch b/patches.axfs/axfs-axfs_physmem.c.patch
new file mode 100644 (file)
index 0000000..9a6c246
--- /dev/null
@@ -0,0 +1,89 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:42:02 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:06:20 +0530
+Subject: [PATCH v2 RESEND 07/15] AXFS: axfs_physmem.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5FB4.4000102@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Allows axfs to use striaght memory or has dummy functions if
+this is a UML system.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_physmem.c |   65 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 65 insertions(+)
+  create mode 100644 fs/axfs/axfs_physmem.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_physmem.c
+@@ -0,0 +1,65 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * axfs_physmem.c -
++ *   Allows axfs to use striaght memory or has dummy functions if
++ *   this is a UML system.
++ */
++#include "axfs.h"
++
++#include <linux/fs.h>
++#ifdef CONFIG_UML
++
++void axfs_map_physmem(struct axfs_super *sbi, unsigned long size)
++{
++}
++
++void axfs_unmap_physmem(struct super_block *sb)
++{
++}
++
++#else
++#include <linux/io.h>
++
++#ifdef ioremap_cached
++#define AXFS_REMAP(a, b) (void __force *)ioremap_cached((a), (b))
++#else
++#define AXFS_REMAP(a, b) (void __force *)ioremap((a), (b))
++#endif /* ioremap_cached */
++
++void axfs_map_physmem(struct axfs_super *sbi, unsigned long size)
++{
++      void *addr;
++
++      if (axfs_is_physmem(sbi)) {
++              addr = AXFS_REMAP(sbi->phys_start_addr, size);
++              sbi->virt_start_addr = (unsigned long)addr;
++      }
++}
++
++void axfs_unmap_physmem(struct super_block *sb)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++
++      if (!sbi)
++              return;
++
++      if (axfs_is_physmem(sbi) && axfs_virtaddr_is_valid(sbi)) {
++              iounmap((void *)(sbi->virt_start_addr));
++              sbi->virt_start_addr = 0;
++      }
++}
++
++#endif /* CONFIG_UML */
diff --git a/patches.axfs/axfs-axfs_profiling.c.patch b/patches.axfs/axfs-axfs_profiling.c.patch
new file mode 100644 (file)
index 0000000..a3573c0
--- /dev/null
@@ -0,0 +1,630 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:43:37 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:07:55 +0530
+Subject: [PATCH v2 RESEND 08/15] AXFS: axfs_profiling.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF6013.3080100@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Tracks pages of files that enter the page cache.  Outputs through a proc
+file which generates a comma separated data file with path, page offset,
+count of times entered page cache.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_profiling.c |  605 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 605 insertions(+)
+  create mode 100644 fs/axfs/axfs_profiling.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_profiling.c
+@@ -0,0 +1,605 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Eric Anderson
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *  Sujaya Srinivasan
++ *  Justin Treon
++ *
++ * More info and current contacts at http://axfs.sourceforge.net
++ *
++ * axfs_profiling.c -
++ *   Tracks pages of files that enter the page cache.  Outputs through a proc
++ *   file which generates a comma separated data file with path, page offset,
++ *   count of times entered page cache.
++ */
++#include "axfs.h"
++
++#ifdef CONFIG_AXFS_PROFILING
++#include <linux/module.h>
++#include <linux/vmalloc.h>
++#include <linux/proc_fs.h>
++
++#define AXFS_PROC_DIR_NAME "axfs"
++
++struct axfs_profiling_manager {
++      struct axfs_profiling_data *profiling_data;
++      struct axfs_super *sbi;
++      u32 *dir_structure;
++      u32 size;
++};
++
++#define MAX_STRING_LEN 1024
++
++/* Handles for our Directory and File */
++static struct proc_dir_entry *axfs_proc_dir;
++static u32 proc_name_inc;
++
++/******************************************************************************
++ *
++ * axfs_init_profile_dir_structure
++ *
++ * Description:
++ *   Creates the structures for tracking the page usage data and creates the
++ *   proc file that will be used to get the data.
++ *
++ * Parameters:
++ *    (IN) manager - pointer to the profile manager for the filing system
++ *
++ *    (IN) num_inodes - number of files in the system
++ *
++ * Returns:
++ *    0
++ *
++ *****************************************************************************/
++static int axfs_init_profile_dir_structure(struct axfs_profiling_manager
++                                         *manager, u32 num_inodes)
++{
++
++      struct axfs_super *sbi = (struct axfs_super *)manager->sbi;
++      u32 child_index = 0, i, j;
++      u32 *dir_structure = manager->dir_structure;
++
++      /*
++       * loop through each inode in the image and find all
++       * of the directories and mark their children
++       */
++      for (i = 0; i < num_inodes; i++) {
++              /* determine if the entry is a directory */
++              if (!S_ISDIR(axfs_get_mode(sbi, i)))
++                      continue;
++
++              /* get the index number for this directory */
++              child_index = axfs_get_inode_array_index(sbi, i);
++
++              /* get the offset to its children */
++              for (j = 0; j < axfs_get_inode_num_entries(sbi, i); j++) {
++                      if (dir_structure[child_index + j] != 0) {
++                              printk(KERN_ERR
++                                     "axfs: ERROR inode was already set old "
++                                     "%lu new %lu\n", (unsigned long)
++                                     dir_structure[child_index + j],
++                                     (unsigned long)i);
++                      }
++                      dir_structure[child_index + j] = i;
++              }
++      }
++
++      return 0;
++}
++
++/******************************************************************************
++ *
++ * axfs_get_directory_path
++ *
++ * Description:
++ *   Determines the directory path of every file for printing the spreadsheet.
++ *
++ * Parameters:
++ *    (IN) manager - Pointer to axfs profile manager
++ *
++ *    (OUT) buffer - Pointer to the printable directory path for each file
++ *
++ *    (IN) inode_number - Inode number of file to look up
++ *
++ * Returns:
++ *    Size of the path to the file
++ *
++ *
++ **************************************************************************/
++static int axfs_get_directory_path(struct axfs_profiling_manager *manager,
++                                 char *buffer, u32 inode_number)
++{
++      u32 path_depth = 0;
++      u32 path_size = 0;
++      u32 string_len = 0;
++      u32 index = inode_number;
++      u32 dir_number;
++      u8 **path_array = NULL;
++      struct axfs_super *sbi = (struct axfs_super *)manager->sbi;
++      int i;
++
++      /*
++       * determine how deep the directory path is and how big the name
++       * string will be walk back until the root directory index is found
++       * (index 0 is root)
++       */
++      while (manager->dir_structure[index] != 0) {
++              path_depth++;
++              /* set the index to the index of the parent directory */
++              index = manager->dir_structure[index];
++      }
++
++      if (path_depth != 0) {
++              /*
++               * create an array that will hold a pointer for each of the
++               * directories names
++               */
++              path_array = vmalloc(path_depth * sizeof(*path_array));
++              if (path_array == NULL) {
++                      printk(KERN_DEBUG
++                             "axfs: directory_path vmalloc failed.\n");
++                      goto out;
++              }
++      }
++
++      index = manager->dir_structure[inode_number];
++      for (i = path_depth; i > 0; i--) {
++              /*
++               * get the array_index for the directory corresponding to
++               * index
++               */
++              dir_number = axfs_get_inode_array_index(sbi, index);
++
++              /* store a pointer to the name in the array */
++              path_array[(i - 1)] = (u8 *) axfs_get_inode_name(sbi, index);
++
++              index = manager->dir_structure[index];
++      }
++
++      /* now print out the directory structure from the begining */
++      string_len = sprintf(buffer, "./");
++      path_size += string_len;
++      for (i = 0; i < path_depth; i++) {
++              buffer = buffer + string_len;
++              string_len = sprintf(buffer, "%s/", (char *)path_array[i]);
++              path_size += string_len;
++      }
++
++      vfree(path_array);
++
++out:
++      return path_size;
++
++}
++
++static ssize_t axfs_procfile_read(char *buffer,
++                                char **buffer_location,
++                                off_t offset, int buffer_length, int *eof,
++                                void *data)
++{
++      struct axfs_profiling_manager *man;
++      struct axfs_profiling_data *profile;
++      struct axfs_super *sbi;
++      u64 array_index;
++      u64 loop_size, inode_page_offset, node_offset, inode_number;
++      u64 print_len = 0;
++      unsigned long addr;
++      int len = 0;
++      int i;
++      char *buff, *name = NULL;
++
++      man = (struct axfs_profiling_manager *)data;
++      sbi = man->sbi;
++
++      loop_size = man->size / sizeof(*profile);
++
++      /* If all data has been returned set EOF */
++      if (offset >= loop_size) {
++              *eof = 1;
++              return 0;
++      }
++
++      buff = buffer;
++      /* print as much as the buffer can take */
++      for (i = offset; i < loop_size; i++) {
++
++              if ((print_len + MAX_STRING_LEN) > buffer_length)
++                      break;
++              /* get the first profile data structure */
++              profile = &(man->profiling_data[i]);
++
++              if (profile->count == 0)
++                      continue;
++
++              inode_number = profile->inode_number;
++
++              /* file names can be duplicated so we must print out the path */
++              len = axfs_get_directory_path(man, buff, inode_number);
++
++              print_len += len;
++              buff += len;
++
++              /* get a pointer to the inode name */
++              array_index = axfs_get_inode_array_index(sbi, inode_number);
++              name = axfs_get_inode_name(sbi, inode_number);
++
++              /*
++               * need to convert the page number in the node area to
++               * the page number within the file
++               */
++              node_offset = i;
++              /*
++               * gives the offset of the node in the node list area
++               * then substract that from the
++               */
++              inode_page_offset = node_offset - array_index;
++
++              /* set everything up to print out */
++              addr = (unsigned long)(inode_page_offset * PAGE_SIZE);
++              len = sprintf(buff, "%s,%lu,%lu\n", name, addr, profile->count);
++
++              print_len += len;
++              buff += len;
++      }
++
++      /*
++       * return the number of items printed. This will be
++     * added to offset and passed back to us
++       */
++      *buffer_location = (char *)(i - offset);
++
++      return print_len;
++}
++
++static ssize_t axfs_procfile_write(struct file *file,
++                                 const char *buffer, unsigned long count,
++                                 void *data)
++{
++      struct axfs_profiling_manager *man_ptr =
++          (struct axfs_profiling_manager *)data;
++
++      if ((count >= 2) && (0 == memcmp(buffer, "on", 2))) {
++              man_ptr->sbi->profiling_on = true;
++      } else if ((count >= 3) && (0 == memcmp(buffer, "off", 3))) {
++              man_ptr->sbi->profiling_on = false;
++      } else if ((count >= 5) && (0 == memcmp(buffer, "clear", 5))) {
++              memset(man_ptr->profiling_data, 0, man_ptr->size);
++      } else {
++              printk(KERN_INFO
++                     "axfs: Unknown command.  Supported options are:\n");
++              printk(KERN_INFO "\t\"on\"\tTurn on profiling\n");
++              printk(KERN_INFO "\t\"off\"\tTurn off profiling\n");
++              printk(KERN_INFO "\t\"clear\"\tClear profiling buffer\n");
++      }
++
++      return count;
++}
++
++static int axfs_create_proc_directory(void)
++{
++      if (axfs_proc_dir == NULL) {
++              axfs_proc_dir = proc_mkdir(AXFS_PROC_DIR_NAME, NULL);
++              if (!axfs_proc_dir) {
++                      printk(KERN_WARNING
++                             "axfs: Failed to create directory\n");
++                      return false;
++              }
++      }
++      return true;
++}
++
++static void axfs_delete_proc_directory(void)
++{
++      /*
++       * Determine if there are any directory elements
++       * and remove if all of the proc files are removed.
++       */
++      if (axfs_proc_dir != NULL) {
++              if (axfs_proc_dir->subdir == NULL) {
++                      remove_proc_entry(AXFS_PROC_DIR_NAME, NULL);
++                      axfs_proc_dir = NULL;
++              }
++      }
++}
++
++/******************************************************************************
++ *
++ * axfs_delete_proc_file
++ *
++ * Description:
++ *   Will search through the proc directory for the correct proc file,
++ *   then delete it
++ *
++ * Parameters:
++ *    (IN) sbi- axfs superblock pointer to determine which proc file to remove
++ *
++ * Returns:
++ *    The profiling manager pointer for the proc file.
++ *
++ *****************************************************************************/
++static struct axfs_profiling_manager *axfs_delete_proc_file(struct axfs_super
++                                                          *sbi)
++{
++      struct proc_dir_entry *current_proc_file;
++      struct axfs_profiling_manager *manager;
++      void *rv = NULL;
++
++      if (!axfs_proc_dir)
++              return NULL;
++
++      /* Walk through the proc file entries to find the matching sbi */
++      current_proc_file = axfs_proc_dir->subdir;
++
++      while (current_proc_file != NULL) {
++              manager = current_proc_file->data;
++              if (manager == NULL) {
++                      printk(KERN_WARNING
++                             "axfs: Error removing proc file private "
++                             "data was NULL.\n");
++                      rv = NULL;
++                      break;
++              }
++              if (manager->sbi == sbi) {
++                      /* we found the match */
++                      remove_proc_entry(current_proc_file->name,
++                                        axfs_proc_dir);
++                      rv = (void *)manager;
++                      break;
++              }
++              current_proc_file = axfs_proc_dir->next;
++      }
++      return (struct axfs_profiling_manager *)rv;
++}
++
++/******************************************************************************
++ *
++ * axfs_register_profiling_proc
++ *
++ * Description:
++ *   Will register the instance of the proc file for a given volume.
++ *
++ * Parameters:
++ *    (IN) manager - Pointer to the profiling manager for the axfs volume
++ *
++ * Returns:
++ *    0 or error number
++ *
++ *****************************************************************************/
++static int axfs_register_profiling_proc(struct axfs_profiling_manager *manager)
++{
++      int rv = 0;
++      struct proc_dir_entry *proc_file;
++      char file_name[20];
++
++      if (!axfs_create_proc_directory()) {
++              rv = -ENOMEM;
++              goto out;
++      }
++
++      sprintf(file_name, "volume%d", proc_name_inc);
++      proc_file = create_proc_entry(file_name, (mode_t) 0644, axfs_proc_dir);
++      if (proc_file == NULL) {
++              remove_proc_entry(file_name, axfs_proc_dir);
++              axfs_delete_proc_directory();
++              rv = -ENOMEM;
++              goto out;
++      }
++
++      proc_name_inc++;
++      proc_file->read_proc = axfs_procfile_read;
++      proc_file->write_proc = axfs_procfile_write;
++      proc_file->mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
++      proc_file->uid = 0;
++      proc_file->gid = 0;
++      proc_file->data = manager;
++
++      printk(KERN_DEBUG "axfs: Proc entry created\n");
++
++out:
++      return rv;
++}
++
++/******************************************************************************
++ *
++ * axfs_unregister_profiling_proc
++ *
++ * Description:
++ *   Will unregister the instance of the proc file for the volume that was
++ *   mounted.  If this is the last volume mounted then the proc directory
++ *   will also be removed.
++ *
++ * Parameters:
++ *    (IN) sbi- axfs superblock pointer to determine which proc file to remove
++ *
++ * Returns:
++ *    The profiling manager pointer for the proc file.
++ *
++ *****************************************************************************/
++static struct axfs_profiling_manager *axfs_unregister_profiling_proc(struct
++                                                                   axfs_super
++                                                                   *sbi)
++{
++      struct axfs_profiling_manager *manager;
++      manager = axfs_delete_proc_file(sbi);
++      axfs_delete_proc_directory();
++      return manager;
++}
++
++/******************************************************************************
++ *
++ * axfs_init_profiling
++ *
++ * Description:
++ *   Creates the structures for tracking the page usage data and creates the
++ *   proc file that will be used to get the data.
++ *
++ * Parameters:
++ *    (IN) sbi- axfs superblock pointer
++ *
++ * Returns:
++ *    true or false
++ *
++ *****************************************************************************/
++int axfs_init_profiling(struct axfs_super *sbi)
++{
++
++      u32 num_nodes, num_inodes;
++      struct axfs_profiling_manager *manager = NULL;
++      struct axfs_profiling_data *profile_data = NULL;
++      int err = -ENOMEM;
++
++      /* determine the max number of pages in the FS */
++      num_nodes = sbi->blocks;
++      if (!num_nodes)
++              return 0;
++
++      manager = vmalloc(sizeof(*manager));
++      if (!manager)
++              goto out;
++
++      profile_data = vmalloc(num_nodes * sizeof(*profile_data));
++      if (!profile_data)
++              goto out;
++
++      memset(profile_data, 0, num_nodes * sizeof(*profile_data));
++
++      /* determine the max number of inodes in the FS */
++      num_inodes = sbi->files;
++
++      manager->dir_structure = vmalloc(num_inodes * sizeof(u32 *));
++      if (!manager->dir_structure)
++              goto out;
++
++      memset(manager->dir_structure, 0, (num_inodes * sizeof(u32 *)));
++
++      manager->profiling_data = profile_data;
++      manager->size = num_nodes * sizeof(*profile_data);
++      manager->sbi = sbi;
++      sbi->profiling_on = true;       /* Turn on profiling by default */
++      sbi->profile_data_ptr = profile_data;
++
++      err = axfs_init_profile_dir_structure(manager, num_inodes);
++      if (err)
++              goto out;
++
++      err = axfs_register_profiling_proc(manager);
++      if (err)
++              goto out;
++
++      return 0;
++
++out:
++      vfree(manager->dir_structure);
++      vfree(profile_data);
++      vfree(manager);
++      return err;
++}
++
++/******************************************************************************
++ *
++ * axfs_shutdown_profiling
++ *
++ * Description:
++ *   Remove the proc file for this volume and release the memory in the
++ *   profiling manager
++ *
++ * Parameters:
++ *    (IN) sbi- axfs superblock pointer
++ *
++ * Returns:
++ *    true or false
++ *
++ *****************************************************************************/
++int axfs_shutdown_profiling(struct axfs_super *sbi)
++{
++      struct axfs_profiling_manager *manager;
++      /*
++       * remove the proc file for this volume and release the memory in the
++       * profiling manager
++       */
++
++      if (!sbi)
++              return true;
++
++      if (!sbi->profile_data_ptr)
++              return true;
++
++      manager = axfs_unregister_profiling_proc(sbi);
++
++      if (manager == NULL)
++              return false;
++
++      vfree(manager->dir_structure);
++      vfree(manager->profiling_data);
++      vfree(manager);
++      return true;
++}
++
++/******************************************************************************
++ *
++ * axfs_profiling_add
++ *
++ * Description:
++ *    Log when a node is paged into memory by incrementing the count in the
++ *    array profile data structure.
++ *
++ * Parameters:
++ *    (IN) sbi- axfs superblock pointer
++ *
++ *    (IN) array_index - The offset into the nodes table of file (node number)
++ *
++ *    (IN) axfs_inode_number - Inode of the node to determine file name later
++ *
++ * Returns:
++ *    none
++ *
++ *****************************************************************************/
++void axfs_profiling_add(struct axfs_super *sbi, unsigned long array_index,
++                      unsigned int axfs_inode_number)
++{
++      unsigned long addr;
++      struct axfs_profiling_data *profile_data;
++
++      if (sbi->profiling_on != true)
++              return;
++
++      addr = (unsigned long)sbi->profile_data_ptr;
++      addr += array_index * sizeof(*profile_data);
++
++      profile_data = (struct axfs_profiling_data *)addr;
++
++      /* Record the inode number to determine the file name later. */
++      profile_data->inode_number = axfs_inode_number;
++
++      /* Increment the number of times the node has been paged in */
++      profile_data->count++;
++}
++
++#else
++
++int axfs_init_profiling(struct axfs_super *sbi)
++{
++      return 0;
++}
++
++int axfs_shutdown_profiling(struct axfs_super *sbi)
++{
++      return 0;
++}
++
++void axfs_profiling_add(struct axfs_super *sbi, unsigned long array_index,
++                      unsigned int axfs_inode_number)
++{
++}
++
++#endif /* CONFIG_AXFS_PROFILING */
diff --git a/patches.axfs/axfs-axfs_super.c.patch b/patches.axfs/axfs-axfs_super.c.patch
new file mode 100644 (file)
index 0000000..0e9fcb5
--- /dev/null
@@ -0,0 +1,1011 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:44:39 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:08:56 +0530
+Subject: [PATCH v2 RESEND 09/15] AXFS: axfs_super.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF6050.1060605@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Contains the core code used to mount the fs.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_super.c |  987 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 987 insertions(+)
+  create mode 100644 fs/axfs/axfs_super.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_super.c
+@@ -0,0 +1,987 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Eric Anderson
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *  Sujaya Srinivasan
++ *  Justin Treon
++ *
++ * More info and current contacts at http://axfs.sourceforge.net
++ *
++ * axfs_super.c -
++ *   Contains the core code used to mount the fs.
++ *
++ */
++#include "axfs.h"
++
++#include <linux/vmalloc.h>
++#include <linux/parser.h>
++#include <linux/statfs.h>
++#include <linux/module.h>
++#include <linux/mount.h>
++#include <linux/mtd/mtd.h>
++#include <linux/slab.h>
++
++static struct super_operations axfs_sops;
++
++static int axfs_is_region_compressed(struct axfs_region_desc *region)
++{
++      if (region->compressed_size > 0)
++              return true;
++
++      return false;
++}
++
++static int axfs_is_mmapable(struct axfs_super *sbi, u64 offset)
++{
++      if (sbi->mmap_size > offset)
++              return true;
++
++      return false;
++}
++
++static int axfs_is_region_mmapable(struct axfs_super *sbi,
++                                 struct axfs_region_desc *region)
++{
++      if (axfs_is_mmapable(sbi, region->fsoffset))
++              if (axfs_virtaddr_is_valid(sbi))
++                      return true;
++
++      return false;
++}
++
++static int axfs_is_offset_mmapable(struct axfs_super *sbi, u64 offset)
++{
++      if (axfs_is_mmapable(sbi, offset))
++              if (axfs_virtaddr_is_valid(sbi))
++                      return true;
++
++      return false;
++}
++
++static int axfs_is_region_incore(struct axfs_region_desc *region)
++{
++      if (region->incore > 0)
++              return true;
++
++      return false;
++}
++
++static int axfs_is_region_xip(struct axfs_super *sbi,
++                            struct axfs_region_desc *region)
++{
++      if (!axfs_can_xip(sbi))
++              return false;
++
++      if (!axfs_is_region_mmapable(sbi, region))
++              return false;
++
++      if (axfs_is_region_compressed(region))
++              return false;
++
++      if (axfs_is_region_incore(region))
++              return false;
++
++      return true;
++}
++
++int axfs_physaddr_is_valid(struct axfs_super *sbi)
++{
++      if (sbi->phys_start_addr > 0)
++              return true;
++
++      return false;
++}
++
++int axfs_virtaddr_is_valid(struct axfs_super *sbi)
++{
++      if (sbi->virt_start_addr > 0)
++              return true;
++
++      return false;
++}
++
++int axfs_is_iomem(struct axfs_super *sbi)
++{
++      if (sbi->iomem_size > 0)
++              return true;
++
++      return false;
++}
++
++int axfs_is_pointed(struct axfs_super *sbi)
++{
++      if (sbi->mtd_pointed > 0)
++              return true;
++
++      return false;
++}
++
++int axfs_can_xip(struct axfs_super *sbi)
++{
++      if (axfs_is_pointed(sbi)) {
++              if (!axfs_physaddr_is_valid(sbi))
++                      return false;
++      }
++
++      if (!axfs_virtaddr_is_valid(sbi))
++              return false;
++
++      return true;
++}
++
++int axfs_is_physmem(struct axfs_super *sbi)
++{
++      int phys = axfs_physaddr_is_valid(sbi);
++      int iomem = axfs_is_iomem(sbi);
++      int point = axfs_is_pointed(sbi);
++
++      if (phys && !iomem && !point)
++              return true;
++
++      return false;
++}
++
++u64 axfs_fsoffset_to_devoffset(struct axfs_super *sbi, u64 fsoffset)
++{
++      if (sbi->phys_start_addr == 0)
++              return fsoffset;
++
++      if (sbi->mtd1 == NULL || sbi->second_dev == NULL)
++              return fsoffset;
++
++      if (fsoffset >= sbi->mmap_size)
++              return fsoffset - sbi->mmap_size;
++
++      return fsoffset;
++}
++
++int axfs_nodev(struct super_block *sb)
++{
++      if (!axfs_has_mtd(sb) && !axfs_has_bdev(sb))
++              return true;
++
++      return false;
++}
++
++static void axfs_free_region(struct axfs_super *sbi,
++                           struct axfs_region_desc *region)
++{
++      if (!region)
++              return;
++
++      if (axfs_is_region_xip(sbi, region))
++              return;
++
++      vfree(region->virt_addr);
++}
++
++static struct axfs_super *axfs_get_sbi(void)
++{
++      struct axfs_super *sbi;
++
++      sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
++      if (sbi)
++              return sbi;
++
++      return ERR_PTR(-ENOMEM);
++}
++
++static void axfs_put_sbi(struct axfs_super *sbi)
++{
++      if (!sbi)
++              return;
++
++      axfs_shutdown_profiling(sbi);
++
++      axfs_free_region(sbi, &sbi->strings);
++      axfs_free_region(sbi, &sbi->xip);
++      axfs_free_region(sbi, &sbi->compressed);
++      axfs_free_region(sbi, &sbi->byte_aligned);
++      axfs_free_region(sbi, &sbi->node_type);
++      axfs_free_region(sbi, &sbi->node_index);
++      axfs_free_region(sbi, &sbi->cnode_offset);
++      axfs_free_region(sbi, &sbi->cnode_index);
++      axfs_free_region(sbi, &sbi->banode_offset);
++      axfs_free_region(sbi, &sbi->cblock_offset);
++      axfs_free_region(sbi, &sbi->inode_file_size);
++      axfs_free_region(sbi, &sbi->inode_name_offset);
++      axfs_free_region(sbi, &sbi->inode_num_entries);
++      axfs_free_region(sbi, &sbi->inode_mode_index);
++      axfs_free_region(sbi, &sbi->inode_array_index);
++      axfs_free_region(sbi, &sbi->modes);
++      axfs_free_region(sbi, &sbi->uids);
++      axfs_free_region(sbi, &sbi->gids);
++
++      kfree(sbi->second_dev);
++      vfree(sbi->cblock_buffer[0]);
++      vfree(sbi->cblock_buffer[1]);
++      kfree(sbi);
++}
++
++static void axfs_put_super(struct super_block *sb)
++{
++      axfs_unmap_mtd(sb);
++      axfs_put_sbi(AXFS_SB(sb));
++
++#ifndef NO_PHYSMEM
++      axfs_unmap_physmem(sb);
++#endif
++      sb->s_fs_info = NULL;
++}
++
++static void axfs_copy_mem(struct super_block *sb, void *buf, u64 fsoffset,
++                        u64 len)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      unsigned long addr;
++
++      addr = sbi->virt_start_addr + (unsigned long)fsoffset;
++
++      memcpy(buf, (void *)addr, (size_t) len);
++}
++
++static int axfs_copy_metadata(struct super_block *sb, void *buf, u64 fsoffset,
++                            u64 len)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      u64 end = fsoffset + len;
++      u64 a = sbi->mmap_size - fsoffset;
++      u64 b = end - sbi->mmap_size;
++      void *bb = (void *)((unsigned long)buf + (unsigned long)a);
++      int err = 0;
++
++      /* Catches case where sbi is not yet fully initialized. */
++      if ((sbi->magic == 0) && (sbi->virt_start_addr != 0)) {
++              axfs_copy_mem(sb, buf, fsoffset, len);
++              return 0;
++      }
++
++      if (fsoffset < sbi->mmap_size) {
++              if (end > sbi->mmap_size) {
++                      err = axfs_copy_metadata(sb, buf, fsoffset, a);
++                      if (err)
++                              return err;
++                      err = axfs_copy_metadata(sb, bb, sbi->mmap_size, b);
++              } else {
++                      if (axfs_is_offset_mmapable(sbi, fsoffset))
++                              axfs_copy_mem(sb, buf, fsoffset, len);
++                      else if (axfs_has_bdev(sb))
++                              axfs_copy_block(sb, buf, fsoffset, len);
++                      else if (axfs_has_mtd(sb))
++                              err = axfs_copy_mtd(sb, buf, fsoffset, len);
++              }
++      } else {
++              if (axfs_nodev(sb))
++                      axfs_copy_mem(sb, buf, fsoffset, len);
++              else if (axfs_has_bdev(sb))
++                      axfs_copy_block(sb, buf, fsoffset, len);
++              else if (axfs_has_mtd(sb))
++                      err = axfs_copy_mtd(sb, buf, fsoffset, len);
++      }
++      return err;
++}
++
++static int axfs_fill_region_data(struct super_block *sb,
++                               struct axfs_region_desc *region, int force)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      unsigned long addr;
++      void *buff = NULL;
++      void *vaddr;
++      int err = -ENOMEM;
++      u64 size = region->size;
++      u64 fsoffset = region->fsoffset;
++      u64 end = fsoffset + size;
++      u64 c_size = region->compressed_size;
++
++      if (size == 0)
++              return 0;
++
++      if (axfs_is_region_incore(region))
++              goto incore;
++
++      if (axfs_is_region_compressed(region))
++              goto incore;
++
++      if (axfs_is_region_xip(sbi, region)) {
++              if ((end > sbi->mmap_size) && (force))
++                      goto incore;
++              addr = sbi->virt_start_addr;
++              addr += (unsigned long)fsoffset;
++              region->virt_addr = (void *)addr;
++              return 0;
++      }
++
++      if (force)
++              goto incore;
++
++      region->virt_addr = NULL;
++      return 0;
++
++incore:
++      region->virt_addr = vmalloc(size);
++      if (!region->virt_addr)
++              goto out;
++      vaddr = region->virt_addr;
++
++      if (axfs_is_region_compressed(region)) {
++              buff = vmalloc(c_size);
++              if (!buff)
++                      goto out;
++              axfs_copy_metadata(sb, buff, fsoffset, c_size);
++              err = axfs_uncompress_block(vaddr, size, buff, c_size);
++              if (!err)
++                      goto out;
++              vfree(buff);
++      } else {
++              axfs_copy_metadata(sb, vaddr, fsoffset, size);
++      }
++
++      return 0;
++
++out:
++      vfree(buff);
++      vfree(region->virt_addr);
++      return err;
++}
++
++static int axfs_fill_region_data_ptrs(struct super_block *sb)
++{
++      int err;
++      struct axfs_super *sbi = AXFS_SB(sb);
++
++      err = axfs_fill_region_data(sb, &sbi->strings, true);
++      if (err)
++              goto out;
++
++      err = axfs_fill_region_data(sb, &sbi->xip, true);
++      if (err)
++              goto out;
++
++      err = axfs_fill_region_data(sb, &sbi->compressed, false);
++      if (err)
++              goto out;
++
++      err = axfs_fill_region_data(sb, &sbi->byte_aligned, false);
++      if (err)
++              goto out;
++
++      err = axfs_fill_region_data(sb, &sbi->node_type, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->node_index, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->cnode_offset, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->cnode_index, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->banode_offset, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->cblock_offset, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->inode_file_size, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->inode_name_offset, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->inode_num_entries, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->inode_mode_index, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->inode_array_index, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->modes, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->uids, true);
++      if (err)
++              goto out;
++      err = axfs_fill_region_data(sb, &sbi->gids, true);
++      if (err)
++              goto out;
++
++out:
++      return err;
++}
++
++static int axfs_init_cblock_buffers(struct axfs_super *sbi)
++{
++      sbi->current_cnode_index = -1;
++      sbi->cblock_buffer[0] = vmalloc(sbi->cblock_size);
++      sbi->cblock_buffer[1] = vmalloc(sbi->cblock_size);
++      if ((!sbi->cblock_buffer[0]) || (!sbi->cblock_buffer[1]))
++              return -ENOMEM;
++
++      return 0;
++}
++
++static int axfs_fixup_devices(struct super_block *sb)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      int err = 0;
++
++#ifndef NO_PHYSMEM
++      if (axfs_is_physmem(sbi)) {
++              axfs_map_physmem(sbi, sbi->mmap_size);
++      } else if (axfs_has_mtd(sb)) {
++#else
++      if (axfs_has_mtd(sb)) {
++#endif
++              err = axfs_map_mtd(sb);
++      } else if (axfs_is_iomem(sbi)) {
++              sbi->phys_start_addr = 0;
++      }
++
++      if (!(axfs_virtaddr_is_valid(sbi)))
++              sbi->mmap_size = 0;
++
++      return err;
++}
++
++static void axfs_fill_region_desc(struct super_block *sb,
++                                struct axfs_region_desc_onmedia *out,
++                                __be64 offset_be, struct axfs_region_desc *in)
++{
++      u64 offset = be64_to_cpu(offset_be);
++
++      axfs_copy_metadata(sb, (void *)out, offset, sizeof(*out));
++
++      in->fsoffset = be64_to_cpu(out->fsoffset);
++      in->size = be64_to_cpu(out->size);
++      in->compressed_size = be64_to_cpu(out->compressed_size);
++      in->max_index = be64_to_cpu(out->max_index);
++      in->table_byte_depth = out->table_byte_depth;
++      in->incore = out->incore;
++}
++
++static int axfs_fill_region_descriptors(struct super_block *sb,
++                                      struct axfs_super_onmedia *sbo)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      struct axfs_region_desc_onmedia *out;
++
++      out = kzalloc(sizeof(*out), GFP_KERNEL);
++      if (!out)
++              return -ENOMEM;
++
++      axfs_fill_region_desc(sb, out, sbo->strings, &sbi->strings);
++      axfs_fill_region_desc(sb, out, sbo->xip, &sbi->xip);
++      axfs_fill_region_desc(sb, out, sbo->compressed, &sbi->compressed);
++      axfs_fill_region_desc(sb, out, sbo->byte_aligned, &sbi->byte_aligned);
++      axfs_fill_region_desc(sb, out, sbo->node_type, &sbi->node_type);
++      axfs_fill_region_desc(sb, out, sbo->node_index, &sbi->node_index);
++      axfs_fill_region_desc(sb, out, sbo->cnode_offset, &sbi->cnode_offset);
++      axfs_fill_region_desc(sb, out, sbo->cnode_index, &sbi->cnode_index);
++      axfs_fill_region_desc(sb, out, sbo->banode_offset, &sbi->banode_offset);
++      axfs_fill_region_desc(sb, out, sbo->cblock_offset, &sbi->cblock_offset);
++      axfs_fill_region_desc(sb, out, sbo->inode_file_size,
++                            &sbi->inode_file_size);
++      axfs_fill_region_desc(sb, out, sbo->inode_name_offset,
++                            &sbi->inode_name_offset);
++      axfs_fill_region_desc(sb, out, sbo->inode_num_entries,
++                            &sbi->inode_num_entries);
++      axfs_fill_region_desc(sb, out, sbo->inode_mode_index,
++                            &sbi->inode_mode_index);
++      axfs_fill_region_desc(sb, out, sbo->inode_array_index,
++                            &sbi->inode_array_index);
++      axfs_fill_region_desc(sb, out, sbo->modes, &sbi->modes);
++      axfs_fill_region_desc(sb, out, sbo->uids, &sbi->uids);
++      axfs_fill_region_desc(sb, out, sbo->gids, &sbi->gids);
++
++      kfree(out);
++
++      return 0;
++}
++
++static int axfs_check_page_shift(struct axfs_super *sbi)
++{
++      if (sbi->page_shift != PAGE_SHIFT) {
++              printk(KERN_ERR "axfs: Filesystem is AXFS, however "
++                              "the page size does not match that\n"
++                              "of the system. Cowardly refusing "
++                              "to mount.\n");
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int axfs_check_compression_type(struct axfs_super *sbi)
++{
++      if (sbi->compression_type != ZLIB) {
++              printk(KERN_ERR "axfs: Unknown compression type "
++                              "specified in super block.\n");
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int axfs_get_onmedia_super(struct super_block *sb)
++{
++      int err;
++      struct axfs_super *sbi = AXFS_SB(sb);
++      struct axfs_super_onmedia *sbo;
++
++      sbo = kmalloc(sizeof(*sbo), GFP_KERNEL);
++      if (!sbo)
++              return -ENOMEM;
++
++#ifndef NO_PHYSMEM
++      axfs_map_physmem(sbi, sizeof(*sbo));
++#endif
++      axfs_copy_metadata(sb, (void *)sbo, 0, sizeof(*sbo));
++
++      /* Do sanity checks on the superblock */
++      if (be32_to_cpu(sbo->magic) != AXFS_MAGIC) {
++              printk(KERN_ERR "axfs: wrong magic: got %x, expected %x\n",
++                     be32_to_cpu(sbo->magic), AXFS_MAGIC);
++              err = -EINVAL;
++              goto out;
++      }
++
++      /* verify the signiture is correct */
++      if (strncmp(sbo->signature, AXFS_SIGNATURE, sizeof(AXFS_SIGNATURE))) {
++              printk(KERN_ERR "axfs: wrong signature: "
++                              "got '%s', expected '%s'\n",
++                     sbo->signature, AXFS_SIGNATURE);
++              err = -EINVAL;
++              goto out;
++      }
++
++      sbi->magic = be32_to_cpu(sbo->magic);
++      sbi->version_major = sbo->version_major;
++      sbi->version_minor = sbo->version_minor;
++      sbi->version_sub = sbo->version_sub;
++      sbi->files = be64_to_cpu(sbo->files);
++      sbi->size = be64_to_cpu(sbo->size);
++      sbi->blocks = be64_to_cpu(sbo->blocks);
++      sbi->mmap_size = be64_to_cpu(sbo->mmap_size);
++      sbi->cblock_size = be32_to_cpu(sbo->cblock_size);
++      sbi->timestamp.tv_sec = be64_to_cpu(sbo->timestamp);
++      sbi->timestamp.tv_nsec = 0;
++      sbi->compression_type = sbo->compression_type;
++      sbi->page_shift = sbo->page_shift;
++
++      err = axfs_check_page_shift(sbi);
++      if (err)
++              goto out;
++
++      err = axfs_check_compression_type(sbi);
++      if (err)
++              goto out;
++
++      /* If no block or MTD device, adjust mmapable to cover all image */
++      if (axfs_nodev(sb))
++              sbi->mmap_size = sbi->size;
++
++      err = axfs_fill_region_descriptors(sb, sbo);
++
++out:
++      kfree(sbo);
++#ifndef NO_PHYSMEM
++      axfs_unmap_physmem(sb);
++#endif
++      return err;
++}
++
++u64 axfs_get_io_dev_size(struct super_block *sb)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      return sbi->size - sbi->mmap_size;
++}
++
++/*
++ * Verify that the size of the IO segment of a split filesystem
++ * is less than or equal to that of the device containing it.
++ */
++static int axfs_verify_device_sizes(struct super_block *sb)
++{
++      int err;
++
++      if (axfs_verify_bdev_sizes(sb, &err))
++              goto out;
++
++      if (axfs_verify_mtd_sizes(sb, &err))
++              goto out;
++
++out:
++      return err;
++}
++
++/*
++ * Read the last four bytes of the volume and make sure the
++ * AXFS magic is present.
++ */
++static int axfs_verify_eofs_magic(struct super_block *sb)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      u32 eof_magic;
++      u64 fsoffset = sbi->size - sizeof(eof_magic);
++
++      if (axfs_copy_metadata(sb, &eof_magic, fsoffset, sizeof(eof_magic)))
++              return -EINVAL;
++
++      if (be32_to_cpu(eof_magic) == AXFS_MAGIC)
++              return 0;
++
++      printk(KERN_ERR "axfs: bad magic at end of image: got %x expected %x\n",
++             be32_to_cpu(eof_magic), AXFS_MAGIC);
++      return -EINVAL;
++}
++
++static int axfs_do_fill_super(struct super_block *sb)
++{
++      struct axfs_super *sbi = AXFS_SB(sb);
++      int err;
++
++      err = axfs_get_onmedia_super(sb);
++      if (err)
++              goto out;
++
++      err = axfs_fixup_devices(sb);
++      if (err)
++              goto out;
++
++      err = axfs_verify_device_sizes(sb);
++      if (err)
++              goto out;
++
++      err = axfs_verify_eofs_magic(sb);
++      if (err)
++              goto out;
++
++      err = axfs_fill_region_data_ptrs(sb);
++      if (err)
++              goto out;
++
++      /* Check that the root inode is in a sane state */
++      if (!S_ISDIR(axfs_get_mode(sbi, 0))) {
++              printk(KERN_ERR "axfs: root is not a directory\n");
++              err = -EINVAL;
++              goto out;
++      }
++
++      if (axfs_get_inode_num_entries(sbi, 0) == 0) {
++              printk(KERN_INFO "axfs: empty filesystem\n");
++              err = -EINVAL;
++              goto out;
++      }
++
++      err = axfs_init_cblock_buffers(sbi);
++      if (err)
++              goto out;
++
++      init_rwsem(&sbi->lock);
++
++      return 0;
++
++out:
++      return err;
++}
++
++int axfs_fill_super(struct super_block *sb, void *data, int silent)
++{
++      struct axfs_super *sbi;
++      struct inode *root;
++      int err;
++      struct axfs_super *sbi_in = (struct axfs_super *)data;
++
++      sbi = axfs_get_sbi();
++      if (IS_ERR(sbi))
++              return PTR_ERR(sbi);
++
++      sb->s_fs_info = (void *)sbi;
++
++      memcpy(sbi, sbi_in, sizeof(*sbi));
++
++      /* fully populate the incore superblock structures */
++      err = axfs_do_fill_super(sb);
++      if (err)
++              goto out;
++
++      sb->s_flags |= MS_RDONLY;
++
++      /* Setup the VFS super block now */
++      sb->s_op = &axfs_sops;
++      root = axfs_create_vfs_inode(sb, 0);
++      if (!root) {
++              err = -EINVAL;
++              goto out;
++      }
++
++      sb->s_root = d_make_root(root);
++      if (!sb->s_root) {
++              err = -EINVAL;
++              goto out;
++      }
++
++      err = axfs_init_profiling(sbi);
++      if (err)
++              goto out;
++
++      if (axfs_has_mtd(sb))
++              sbi->mtd0 = axfs_mtd(sb);
++      return 0;
++
++out:
++      axfs_put_super(sb);
++      return err;
++}
++
++static struct dentry  *
++axfs_get_sb_address(struct file_system_type *fs_type,
++                                      int flags, struct axfs_super *sbi)
++{
++      int mtdnr;
++      char *sd = sbi->second_dev;
++
++      if (sbi->phys_start_addr == 0)
++              return false;
++
++      if (sbi->phys_start_addr & (PAGE_SIZE - 1)) {
++              printk(KERN_ERR
++                     "axfs: address 0x%lx for axfs image isn't aligned "
++                     "to a page boundary\n", sbi->phys_start_addr);
++              return ERR_PTR(-EINVAL);
++      }
++
++      if (axfs_is_dev_mtd(sd, &mtdnr))
++              return axfs_get_sb_mtd(fs_type, flags, sd, sbi);
++      else if (axfs_is_dev_bdev(sd))
++              return axfs_get_sb_bdev(fs_type, flags, sd, sbi);
++      else
++              return mount_nodev(fs_type, flags, sbi, axfs_fill_super);
++
++}
++
++/* helpers for parse_axfs_options */
++enum {
++      OPTION_ERR,
++      OPTION_SECOND_DEV,
++      OPTION_PHYSICAL_ADDRESS_LOWER_X,
++      OPTION_PHYSICAL_ADDRESS_UPPER_X,
++      OPTION_IOMEM
++};
++
++/* helpers for parse_axfs_options */
++static match_table_t tokens = {
++      {OPTION_SECOND_DEV, "second_dev=%s"},
++      {OPTION_PHYSICAL_ADDRESS_LOWER_X, "physaddr=0x%s"},
++      {OPTION_PHYSICAL_ADDRESS_UPPER_X, "physaddr=0X%s"},
++      {OPTION_IOMEM, "iomem=%s"},
++      {OPTION_ERR, NULL}
++};
++
++static int axfs_check_options(char *options, struct axfs_super *sbi)
++{
++      int err = -EINVAL;
++      unsigned long address = 0;
++      char *iomem = NULL;
++      unsigned long length = 0;
++      char *p;
++      substring_t args[MAX_OPT_ARGS];
++
++      if (!options)
++              return 0;
++
++      if (!*options)
++              return 0;
++
++      while ((p = strsep(&options, ",")) != NULL) {
++              int token;
++              if (!*p)
++                      continue;
++
++              token = match_token(p, tokens, args);
++              switch (token) {
++              case OPTION_SECOND_DEV:
++                      sbi->second_dev = match_strdup(&args[0]);
++                      if (!(sbi->second_dev)) {
++                              err = -ENOMEM;
++                              goto out;
++                      }
++                      if (!*(sbi->second_dev))
++                              goto bad_value;
++                      break;
++              case OPTION_IOMEM:
++                      iomem = match_strdup(&args[0]);
++                      if (!(iomem)) {
++                              err = -ENOMEM;
++                              goto out;
++                      }
++                      if (!*iomem)
++                              goto bad_value;
++                      break;
++              case OPTION_PHYSICAL_ADDRESS_LOWER_X:
++              case OPTION_PHYSICAL_ADDRESS_UPPER_X:
++                      if (match_hex(&args[0], (int *)&address))
++                              goto out;
++                      if (!address)
++                              goto bad_value;
++                      break;
++              default:
++                      printk(KERN_ERR
++                             "axfs: unrecognized mount option '%s' "
++                             "or missing value\n", p);
++                      goto out;
++              }
++      }
++
++      if (iomem) {
++              if (address)
++                      goto out;
++              err = axfs_get_uml_address(iomem, &address, &length);
++              kfree(iomem);
++              sbi->iomem_size = length;
++              sbi->virt_start_addr = address;
++      }
++
++      sbi->phys_start_addr = address;
++      return 0;
++
++bad_value:
++      printk(KERN_ERR
++             "axfs: unrecognized mount option '%s' "
++             "or missing value\n", p);
++
++out:
++      kfree(iomem);
++      return err;
++}
++
++struct dentry *axfs_get_sb(struct file_system_type *fs_type, int flags,
++              const char *dev_name, void *data)
++{
++      struct axfs_super *sbi;
++      int err;
++      struct dentry *ret = ERR_PTR(-EINVAL);
++
++      sbi = axfs_get_sbi();
++      if (IS_ERR(sbi))
++              return ret;
++
++      err = axfs_check_options((char *)data, sbi);
++      if (err)
++              goto out;
++
++      /* First we check if we are mounting directly to memory */
++      ret = axfs_get_sb_address(fs_type, flags, sbi);
++      if (!(IS_ERR_OR_NULL(ret)))
++              goto out;
++
++      /* Next we assume there's a MTD device */
++      ret = axfs_get_sb_mtd(fs_type, flags, dev_name, sbi);
++      if (!(IS_ERR_OR_NULL(ret)))
++              goto out;
++
++      /* Now we assume it's a block device */
++      if (sbi->second_dev) {
++              printk(KERN_ERR
++                     "axfs: can't specify secondary block device %s because "
++                     "%s is assumed to be a block device\n", sbi->second_dev,
++                     dev_name);
++              err = -EINVAL;
++              goto out;
++      }
++      ret = axfs_get_sb_bdev(fs_type, flags, dev_name, sbi);
++      if (!(IS_ERR_OR_NULL(ret)))
++              goto out;
++      err = -EINVAL;
++
++out:
++      axfs_put_sbi(sbi);
++      return ret;
++}
++
++static void axfs_kill_super(struct super_block *sb)
++{
++      if (axfs_nodev(sb))
++              return kill_anon_super(sb);
++
++      if (axfs_has_mtd(sb))
++              axfs_kill_mtd_super(sb);
++
++      if (axfs_has_bdev(sb))
++              axfs_kill_block_super(sb);
++}
++
++static int axfs_remount(struct super_block *sb, int *flags, char *data)
++{
++      *flags |= MS_RDONLY;
++      return 0;
++}
++
++static int axfs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++      struct axfs_super *sbi = AXFS_SB(dentry->d_sb);
++
++      buf->f_type = AXFS_MAGIC;
++      buf->f_bsize = (1 << sbi->page_shift);
++      buf->f_blocks = sbi->blocks;
++      buf->f_bfree = 0;
++      buf->f_bavail = 0;
++      buf->f_files = sbi->files;
++      buf->f_ffree = 0;
++      buf->f_namelen = AXFS_MAXPATHLEN;
++      return 0;
++}
++
++static struct super_operations axfs_sops = {
++      .put_super = axfs_put_super,
++      .remount_fs = axfs_remount,
++      .statfs = axfs_statfs,
++};
++
++static struct file_system_type axfs_fs_type = {
++      .owner = THIS_MODULE,
++      .name = "axfs",
++      .mount = axfs_get_sb,
++      .kill_sb = axfs_kill_super,
++};
++
++static int __init init_axfs_fs(void)
++{
++      int err;
++
++      err = axfs_uncompress_init();
++      if (err)
++              return err;
++
++      err = register_filesystem(&axfs_fs_type);
++
++      if (!err)
++              return 0;
++
++      axfs_uncompress_exit();
++      return err;
++}
++
++static void __exit exit_axfs_fs(void)
++{
++      axfs_uncompress_exit();
++      unregister_filesystem(&axfs_fs_type);
++}
++
++module_init(init_axfs_fs);
++module_exit(exit_axfs_fs);
++MODULE_LICENSE("GPL");
diff --git a/patches.axfs/axfs-axfs_uml.c.patch b/patches.axfs/axfs-axfs_uml.c.patch
new file mode 100644 (file)
index 0000000..3a3f205
--- /dev/null
@@ -0,0 +1,71 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:46:32 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:10:49 +0530
+Subject: [PATCH v2 RESEND 10/15] AXFS: axfs_uml.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF60C1.5050301@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Allows axfs in a UML kernel to use find_iomem() interface for the XIP device
+or dummy functions if this is not a UML build.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_uml.c |   47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+  create mode 100644 fs/axfs/axfs_uml.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_uml.c
+@@ -0,0 +1,47 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ *  Jared Hulbert <jaredeh@gmail.com>
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * axfs_uml.c -
++ *   Allows axfs to a UML kernels find_iomem() interface as an XIP device or
++ *   dummy functions if this is not a UML build.
++ */
++#include "axfs.h"
++
++#ifdef CONFIG_UML
++#include <mem_user.h>
++int axfs_get_uml_address(char *iomem, unsigned long *address,
++                       unsigned long *length)
++{
++      *address = find_iomem(iomem, length);
++      if (!(*address)) {
++              printk(KERN_DEBUG "axfs: find_iomem() failed\n");
++              return -EINVAL;
++      }
++
++      if (*length < PAGE_SIZE) {
++              printk(KERN_DEBUG
++                     "axfs: iomem() too small, must be at least %li Bytes\n",
++                     PAGE_SIZE);
++              return -EINVAL;
++      }
++      return 0;
++}
++#else
++int axfs_get_uml_address(char *iomem, unsigned long *address,
++                       unsigned long *length)
++{
++      return 0;
++}
++#endif /* CONFIG_UML */
diff --git a/patches.axfs/axfs-axfs_uncompress.c.patch b/patches.axfs/axfs-axfs_uncompress.c.patch
new file mode 100644 (file)
index 0000000..fc25594
--- /dev/null
@@ -0,0 +1,113 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:47:49 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:12:07 +0530
+Subject: [PATCH v2 RESEND 11/15] AXFS: axfs_uncompress.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF610F.3000208@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+AXFS interfaces to the uncompression library
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_uncompress.c |   90 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 90 insertions(+)
+  create mode 100644 fs/axfs/axfs_uncompress.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_uncompress.c
+@@ -0,0 +1,90 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ *   Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ *   Modified in 2006 by Eric Anderson
++ *     from the cramfs sources fs/cramfs/uncompress.c
++ *
++ * (C) Copyright 1999 Linus Torvalds
++ *
++ * axfs_uncompress.c -
++ *  axfs interfaces to the uncompression library. There's really just
++ * three entrypoints:
++ *
++ *  - axfs_uncompress_init() - called to initialize the thing.
++ *  - axfs_uncompress_exit() - tell me when you're done
++ *  - axfs_uncompress_block() - uncompress a block.
++ *
++ * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
++ * only have one stream, and we'll initialize it only once even if it
++ * then is used by multiple filesystems.
++ *
++ */
++
++#include <linux/errno.h>
++#include <linux/vmalloc.h>
++#include <linux/zlib.h>
++#include <linux/init.h>
++#include <linux/mutex.h>
++
++static z_stream stream;
++static DEFINE_MUTEX(axfs_uncmp_mutex);
++
++int axfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
++{
++      int err;
++      int out;
++
++      mutex_lock(&axfs_uncmp_mutex);
++
++      stream.next_in = src;
++      stream.avail_in = srclen;
++
++      stream.next_out = dst;
++      stream.avail_out = dstlen;
++
++      err = zlib_inflateReset(&stream);
++      if (err != Z_OK) {
++              printk(KERN_ERR "axfs: zlib_inflateReset error %d\n", err);
++              zlib_inflateEnd(&stream);
++              zlib_inflateInit(&stream);
++      }
++
++      err = zlib_inflate(&stream, Z_FINISH);
++      if (err != Z_STREAM_END)
++              goto err;
++
++      out = stream.total_out;
++
++      mutex_unlock(&axfs_uncmp_mutex);
++
++      return out;
++
++err:
++
++      mutex_unlock(&axfs_uncmp_mutex);
++
++      printk(KERN_ERR "axfs: error %d while decompressing!\n", err);
++      printk(KERN_ERR "%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
++      return 0;
++}
++
++int __init axfs_uncompress_init(void)
++{
++
++      stream.workspace = vmalloc(zlib_inflate_workspacesize());
++      if (!stream.workspace)
++              return -ENOMEM;
++      stream.next_in = NULL;
++      stream.avail_in = 0;
++      zlib_inflateInit(&stream);
++
++      return 0;
++}
++
++int axfs_uncompress_exit(void)
++{
++      zlib_inflateEnd(&stream);
++      vfree(stream.workspace);
++      return 0;
++}
diff --git a/patches.axfs/axfs-kconfigs-and-makefiles.patch b/patches.axfs/axfs-kconfigs-and-makefiles.patch
new file mode 100644 (file)
index 0000000..881aedb
--- /dev/null
@@ -0,0 +1,85 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:29:51 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 16:54:09 +0530
+Subject: [PATCH v2 RESEND 01/15] AXFS: Kconfigs and Makefiles
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5CD9.2040206@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+The Kconfigs and Makefiles for AXFS
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/Kconfig       |    3 ++-
+ fs/Makefile      |    1 +
+ fs/axfs/Kconfig  |   18 ++++++++++++++++++
+ fs/axfs/Makefile |    8 ++++++++
+ 4 files changed, 29 insertions(+), 1 deletion(-)
+  create mode 100644 fs/axfs/Kconfig
+  create mode 100644 fs/axfs/Makefile
+
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -17,7 +17,7 @@ source "fs/ext4/Kconfig"
+ config FS_XIP
+ # execute in place
+       bool
+-      depends on EXT2_FS_XIP || PRAMFS_XIP
++      depends on EXT2_FS_XIP || PRAMFS_XIP || AXFS
+       default y
+ source "fs/jbd/Kconfig"
+@@ -221,6 +221,7 @@ source "fs/pstore/Kconfig"
+ source "fs/sysv/Kconfig"
+ source "fs/ufs/Kconfig"
+ source "fs/pramfs/Kconfig"
++source "fs/axfs/Kconfig"
+ source "fs/exofs/Kconfig"
+ endif # MISC_FILESYSTEMS
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -72,6 +72,7 @@ obj-$(CONFIG_EXT4_FS)                += ext4/
+ obj-$(CONFIG_JBD)             += jbd/
+ obj-$(CONFIG_JBD2)            += jbd2/
+ obj-$(CONFIG_CRAMFS)          += cramfs/
++obj-$(CONFIG_AXFS)            += axfs/
+ obj-$(CONFIG_SQUASHFS)                += squashfs/
+ obj-y                         += ramfs/
+ obj-$(CONFIG_HUGETLBFS)               += hugetlbfs/
+--- /dev/null
++++ b/fs/axfs/Kconfig
+@@ -0,0 +1,18 @@
++config AXFS
++      tristate "Advanced XIP File System (AXFS) support (EXPERIMENTAL)"
++      select FS_XIP
++      select ZLIB_INFLATE
++      help
++        The Advanced XIP File System or (AXFS) is a highly compressed
++        readonly filesystem like cramfs or squashfs.  It also can be
++        configured to store individual pages of files compressed or
++        uncompressed as XIP pages.  This allows for faster boot up and
++        application launch time with a smaller memory footprint.
++
++config AXFS_PROFILING
++      bool "Profiling extensions for AXFS (EXPERIMENTAL)"
++      depends on AXFS
++      help
++        Profiling tooling used to identify what pages in the filesystem
++        image are actually accessed and how much.
++
+--- /dev/null
++++ b/fs/axfs/Makefile
+@@ -0,0 +1,8 @@
++#
++# Makefile for axfs
++#
++
++obj-$(CONFIG_AXFS) += axfs.o
++
++axfs-y := axfs_inode.o axfs_super.o axfs_uncompress.o axfs_profiling.o \
++          axfs_uml.o axfs_mtd.o axfs_bdev.o axfs_physmem.o
diff --git a/patches.axfs/axfs-mount-as-rootfs.patch b/patches.axfs/axfs-mount-as-rootfs.patch
new file mode 100644 (file)
index 0000000..854e8e9
--- /dev/null
@@ -0,0 +1,93 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:51:22 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:15:41 +0530
+Subject: [PATCH v2 RESEND 15/15] AXFS: mount as rootfs
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF61E5.4080108@ap.sony.com>
+
+
+From: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+
+Add support to mount AXFS as root file system first.
+
+Signed-off-by: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/Kconfig      |   15 +++++++++++++++
+ fs/axfs/axfs_super.c |    6 ++++++
+ init/do_mounts.c     |   20 ++++++++++++++++++++
+ 3 files changed, 41 insertions(+)
+
+--- a/fs/axfs/Kconfig
++++ b/fs/axfs/Kconfig
+@@ -34,3 +34,18 @@ config AXFS_DEBUG_XIP_RECORDS_NUM
+       help
+         The number of records which /porc/axfs_xip can record. one record
+         takes about 64 bytes of memory.
++
++config AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
++      bool "First Mount AXFS as Rootfs"
++      depends on AXFS
++      help
++        Say Y if you have enabled axfs, and you want to mount the axfs
++        image as a root file system first when the kernel boots. This option
++        makes the kernel boottime a little faster when the command line is
++        properly set. Before having the kernel mount this axfs image
++        as a root file system, you must pass the command line parameter:
++        "root=/dev/null rootflags=physaddr=0x********" to the kernel
++        (replace 0x******** with the physical address location of the
++        axfs image to boot with).
++
++        If unsure, say N.
+--- a/fs/axfs/axfs_super.c
++++ b/fs/axfs/axfs_super.c
+@@ -884,6 +884,12 @@ struct dentry *axfs_get_sb(struct file_s
+       if (err)
+               goto out;
++#ifdef CONFIG_AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
++      printk(KERN_INFO "AXFS: Checking AXFS filesystem at virtaddr: 0x%08lx "
++                      "(physaddr=0x%08lx).\n", sbi->virt_start_addr,
++                      sbi->phys_start_addr);
++#endif
++
+       /* First we check if we are mounting directly to memory */
+       ret = axfs_get_sb_address(fs_type, flags, sbi);
+       if (!(IS_ERR_OR_NULL(ret)))
+--- a/init/do_mounts.c
++++ b/init/do_mounts.c
+@@ -439,6 +439,19 @@ static int __init mount_nfs_root(void)
+ }
+ #endif
++#ifdef CONFIG_AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
++static int __init mount_axfs_root(void)
++{
++      create_dev("/dev/root", ROOT_DEV);
++      if (root_mount_data &&
++          do_mount_root("/dev/root", "axfs", root_mountflags,
++                                      root_mount_data) == 0)
++              return 1;
++      return 0;
++}
++#endif
++
++
+ #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD)
+ void __init change_floppy(char *fmt, ...)
+ {
+@@ -471,6 +484,13 @@ void __init change_floppy(char *fmt, ...
+ void __init mount_root(void)
+ {
++#ifdef CONFIG_AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
++      if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
++              if (mount_axfs_root())
++                      return;
++              printk(KERN_ERR "VFS: Unable to mount axfs root.\n");
++      }
++#endif
+ #ifdef CONFIG_ROOT_NFS
+       if (ROOT_DEV == Root_NFS) {
+               if (mount_nfs_root())
diff --git a/patches.axfs/axfs-xip-debugging-support.patch b/patches.axfs/axfs-xip-debugging-support.patch
new file mode 100644 (file)
index 0000000..fb03b2f
--- /dev/null
@@ -0,0 +1,303 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:50:07 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:14:25 +0530
+Subject: [PATCH v2 RESEND 13/15] AXFS: XIP debugging support.
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF6199.7040801@ap.sony.com>
+
+
+From: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+
+This code augments debugg infrastructure for AXFS.
+It captures access of XIP mapped pages of files in a
+proc entry at /proc/axfs_xip.
+
+Signed-off-by: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/Kconfig            |   18 +++++
+ fs/axfs/Makefile           |    2 
+ fs/axfs/axfs_inode.c       |   35 +++++++++-
+ fs/axfs/axfs_super.c       |    4 -
+ fs/axfs/axfs_xip_profile.c |  154 +++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/axfs_fs.h    |    7 ++
+ 6 files changed, 216 insertions(+), 4 deletions(-)
+  create mode 100644 fs/axfs/axfs_xip_profile.c
+
+--- a/fs/axfs/Kconfig
++++ b/fs/axfs/Kconfig
+@@ -16,3 +16,21 @@ config AXFS_PROFILING
+         Profiling tooling used to identify what pages in the filesystem
+         image are actually accessed and how much.
++config AXFS_DEBUG
++      bool "AXFS debugging support"
++      depends on AXFS
++      help
++        If you are experiencing any problems with the AXFS filesystem, say
++        Y here.  This will create a profile entry at /proc/axfs_xip. In this
++        profile, the XIP mapped pages of files are recorded.
++
++        If unsure, say N.
++
++config AXFS_DEBUG_XIP_RECORDS_NUM
++      int "Number of axfs xip profile records (100 - 1000)"
++      range 100 1000
++      depends on AXFS_DEBUG
++      default 500
++      help
++        The number of records which /porc/axfs_xip can record. one record
++        takes about 64 bytes of memory.
+--- a/fs/axfs/Makefile
++++ b/fs/axfs/Makefile
+@@ -6,3 +6,5 @@ obj-$(CONFIG_AXFS) += axfs.o
+ axfs-y := axfs_inode.o axfs_super.o axfs_uncompress.o axfs_profiling.o \
+           axfs_uml.o axfs_mtd.o axfs_bdev.o axfs_physmem.o
++
++obj-$(CONFIG_AXFS_DEBUG) += axfs_xip_profile.o
+--- a/fs/axfs/axfs_inode.c
++++ b/fs/axfs/axfs_inode.c
+@@ -464,6 +464,10 @@ static int axfs_fault(struct vm_area_str
+       struct axfs_super *sbi = AXFS_SB(sb);
+       u64 ino_number = inode->i_ino;
+       u64 array_index;
++#ifdef CONFIG_AXFS_DEBUG
++      unsigned long xip_node_address, offset, length;
++      unsigned int numpages, count;
++#endif
+       array_index = axfs_get_inode_array_index(sbi, ino_number) + vmf->pgoff;
+@@ -474,12 +478,39 @@ static int axfs_fault(struct vm_area_str
+       if (!(vma->vm_flags & VM_WRITE))
+               axfs_profiling_add(sbi, array_index, ino_number);
++#ifdef CONFIG_AXFS_DEBUG
++      offset = vma->vm_pgoff;
++      length = vma->vm_end - vma->vm_start;
++
++      if (length > inode->i_size)
++              length = inode->i_size;
++
++      length = PAGE_ALIGN(length);
++      numpages = length >> PAGE_SHIFT;
++#endif
++
+       /*
+        * figure out if the node is XIP or compressed and call the
+        * appropriate function
+        */
+-      if (axfs_is_node_xip(sbi, array_index))
+-              return xip_file_fault(vma, vmf);
++#ifdef CONFIG_AXFS_DEBUG
++      for (count = 0; count < numpages; count++, array_index++) {
++#endif
++              if (axfs_is_node_xip(sbi, array_index)) {
++#ifdef CONFIG_AXFS_DEBUG
++                      xip_node_address  = axfs_get_xip_region_physaddr(sbi);
++                      xip_node_address += ((axfs_get_inode_num_entries(sbi, array_index)) << PAGE_SHIFT);
++                      axfs_xip_record((unsigned char *)file->f_dentry->d_name.name,
++                                      xip_node_address,
++                                      vma->vm_start + (PAGE_SIZE * count),
++                                      (unsigned int)(PAGE_SIZE),
++                                      pgprot_val(vma->vm_page_prot));
++#endif
++                      return xip_file_fault(vma, vmf);
++         }
++#ifdef CONFIG_AXFS_DEBUG
++      }
++#endif
+       return filemap_fault(vma, vmf);
+ }
+--- a/fs/axfs/axfs_super.c
++++ b/fs/axfs/axfs_super.c
+@@ -681,11 +681,11 @@ static int axfs_do_fill_super(struct sup
+               goto out;
+       }
++#ifdef CONFIG_AXFS_DEBUG
+       if (axfs_get_inode_num_entries(sbi, 0) == 0) {
+               printk(KERN_INFO "axfs: empty filesystem\n");
+-              err = -EINVAL;
+-              goto out;
+       }
++#endif
+       err = axfs_init_cblock_buffers(sbi);
+       if (err)
+--- /dev/null
++++ b/fs/axfs/axfs_xip_profile.c
+@@ -0,0 +1,154 @@
++/*
++ * fs/axfs/axfs_xip_profile.c
++ *
++ * profiler: /proc/axfs_xip
++ *
++ * Copyright 2005-2007 Sony Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
++ * MA  02110-1301, USA.
++ *
++ *
++ */
++
++#ifdef CONFIG_AXFS_DEBUG
++
++#include <linux/types.h>
++#include <linux/proc_fs.h>
++
++
++#ifndef CONFIG_AXFS_DEBUG_XIP_RECORDS_NUM
++#define CONFIG_AXFS_DEBUG_XIP_RECORDS_NUM 500
++#endif
++
++#define  RECORDS CONFIG_AXFS_DEBUG_XIP_RECORDS_NUM
++
++#define  MAX_FILE_NAME_LEN    48
++
++static DEFINE_SEMAPHORE(record_index_sem);
++
++/* each record is 64 bytes */
++struct axfs_xip_record {
++      char filename[MAX_FILE_NAME_LEN];       /* XIP mapped file name */
++      unsigned long physaddr; /* XIP mapped physaddr */
++      unsigned long virtaddr; /* XIP mapped virtaddr */
++      unsigned int size;      /* XIP mapped size */
++      unsigned long pgprot;   /* XIP mapped page prot */
++};
++
++static struct axfs_xip_record axfs_xip_records[RECORDS];
++static unsigned long record_index;
++
++/* record function */
++int axfs_xip_record(unsigned char *name, unsigned long physaddr,
++                  unsigned long virtaddr, unsigned int size,
++                  unsigned long pgprot)
++{
++
++      int namelen = 0;
++      if (down_interruptible(&record_index_sem))
++              return -EINTR;
++
++      if (record_index >= RECORDS)
++              goto out;
++
++      axfs_xip_records[record_index].physaddr = physaddr;
++      axfs_xip_records[record_index].virtaddr = virtaddr;
++      axfs_xip_records[record_index].size = size;
++      axfs_xip_records[record_index].pgprot = pgprot;
++      memset(axfs_xip_records[record_index].filename, 0, MAX_FILE_NAME_LEN);
++      namelen = strlen(name);
++      strncpy(axfs_xip_records[record_index].filename, name,
++              (namelen >= MAX_FILE_NAME_LEN) ? MAX_FILE_NAME_LEN-1 : namelen);
++
++      record_index++;
++
++out:
++      up(&record_index_sem);
++      return 0;
++}
++
++static int axfs_xip_record_to_string(struct axfs_xip_record *record,
++                              char *buf, int len)
++{
++
++      return snprintf(buf, len,
++                      "0x%08lx to 0x%08lx 0x%x 0x%lx %s\n",
++                      record->physaddr, record->virtaddr,
++                      record->size, record->pgprot, record->filename) ;
++}
++
++
++static unsigned int is_first_line = 1;
++#define PROFILE_HEADINGS "\nXIP: physaddr, virtaddr, size, pgprot, filename\n"
++#define HEADINGS_LEN sizeof(PROFILE_HEADINGS)
++
++static int axfs_xip_proc_read(char *page, char **start, off_t off, int count,
++                                int *eof, void *data)
++{
++      unsigned long tlen = 0;
++      unsigned long index = record_index;
++      struct axfs_xip_record *record;
++
++      if (down_interruptible(&record_index_sem))
++              return -EINTR;
++
++      if (off >= index) {
++              *eof = 1;
++              is_first_line = 1;
++              goto out;
++      }
++      record = &axfs_xip_records[off];
++
++      if (is_first_line) {
++              strncpy(page+tlen, PROFILE_HEADINGS, HEADINGS_LEN);
++              tlen += HEADINGS_LEN - 1;
++              is_first_line = 0;
++      }
++      tlen += axfs_xip_record_to_string(record, page+tlen, PAGE_SIZE-tlen);
++      *start = (char *)1;
++ out:
++      up(&record_index_sem);
++      return tlen > count ? 0 : tlen;
++}
++
++/* Write to Clear */
++static int axfs_xip_proc_write(struct file *file, const char *buffer,
++                               unsigned long count, void *data)
++{
++      if (down_interruptible(&record_index_sem))
++              return -EINTR;
++
++      record_index = 0;
++
++      up(&record_index_sem);
++      return count;
++}
++
++static int __init axfs_xip_proc_profile(void)
++{
++      struct proc_dir_entry *ent;
++      ent = create_proc_entry("axfs_xip", S_IFREG|S_IRUGO|S_IWUSR, NULL);
++      if (!ent) {
++              printk(KERN_ERR "create axfs_xip proc entry failed\n");
++              return -ENOMEM;
++      }
++      ent->read_proc = axfs_xip_proc_read;
++      ent->write_proc = axfs_xip_proc_write;
++      return 0;
++}
++late_initcall(axfs_xip_proc_profile);
++
++#endif /* CONFIG_AXFS_DEBUG */
+--- a/include/linux/axfs_fs.h
++++ b/include/linux/axfs_fs.h
+@@ -42,6 +42,13 @@ int axfs_uncompress_block(void *, int, v
+ int axfs_uncompress_init(void);
+ int axfs_uncompress_exit(void);
++#ifdef CONFIG_AXFS_DEBUG
++int axfs_xip_record(unsigned char *name, unsigned long physaddr,
++                                      unsigned long virtaddr,
++                                      unsigned int size,
++                                      unsigned long pgprot);
++#endif
++
+ struct axfs_profiling_data {
+       u64 inode_number;
+       unsigned long count;
diff --git a/series b/series
index 61664d011b8d470094f65212b0255a34f5dc9f7d..874b96dc6f4ed6fc93cb9b97a22405dbc8a27751 100644 (file)
--- a/series
+++ b/series
@@ -111,6 +111,28 @@ patches.pramfs/16-pramfs-ioctl-operations.patch
 patches.pramfs/17-pramfs-makefile-and-kconfig.patch
 
 
+#############################################################################
+# pramfs
+#
+# Currently broken, so don't enable, but leave here for the placeholder.
+#
+patches.axfs/axfs-kconfigs-and-makefiles.patch
+patches.axfs/axfs-axfs.h.patch
+patches.axfs/axfs-axfs_fs.h.patch
+patches.axfs/axfs-axfs_fs_sb.h.patch
+patches.axfs/axfs-axfs_inode.c.patch
+patches.axfs/axfs-axfs_mtd.c.patch
+patches.axfs/axfs-axfs_physmem.c.patch
+patches.axfs/axfs-axfs_profiling.c.patch
+patches.axfs/axfs-axfs_super.c.patch
+patches.axfs/axfs-axfs_uml.c.patch
+patches.axfs/axfs-axfs_uncompress.c.patch
+patches.axfs/axfs-axfs_bdev.c.patch
+patches.axfs/axfs-xip-debugging-support.patch
+patches.axfs/axfs-add-documentation.patch
+patches.axfs/axfs-mount-as-rootfs.patch
+
+
 #############################################################################
 # Marzen board support
 #
@@ -577,3 +599,4 @@ patches.at91/0251-ARM-at91-i2c-change-id-to-let-i2c-at91-work.patch
 patches.at91/0252-net-macb-align-ring-buffer-function-with-mainline.patch
 patches.at91/0253-net-macb-move-to-circ_buf-macros-and-fix-initial-con.patch
 
+