diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-12-05 12:55:53 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-12-05 12:55:53 -0800 |
commit | a7e526129f6ea298513ef4ce7aa6db08fc069d14 (patch) | |
tree | df86601ee9de6168e952725ae671afbccf520484 | |
parent | 53b1f08612996c52fb590090803ad0bc184d667c (diff) | |
download | ltsi-kernel-a7e526129f6ea298513ef4ce7aa6db08fc069d14.tar.gz |
axfs patches
-rw-r--r-- | patches.axfs/axfs-add-documentation.patch | 356 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs.h.patch | 120 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_bdev.c.patch | 195 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_fs.h.patch | 147 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_fs_sb.h.patch | 110 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_inode.c.patch | 660 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_mtd.c.patch | 376 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_physmem.c.patch | 89 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_profiling.c.patch | 630 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_super.c.patch | 1011 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_uml.c.patch | 71 | ||||
-rw-r--r-- | patches.axfs/axfs-axfs_uncompress.c.patch | 113 | ||||
-rw-r--r-- | patches.axfs/axfs-kconfigs-and-makefiles.patch | 85 | ||||
-rw-r--r-- | patches.axfs/axfs-mount-as-rootfs.patch | 93 | ||||
-rw-r--r-- | patches.axfs/axfs-xip-debugging-support.patch | 303 | ||||
-rw-r--r-- | series | 23 |
16 files changed, 4382 insertions, 0 deletions
diff --git a/patches.axfs/axfs-add-documentation.patch b/patches.axfs/axfs-add-documentation.patch new file mode 100644 index 00000000000000..49f96559a9cbf0 --- /dev/null +++ b/patches.axfs/axfs-add-documentation.patch @@ -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 index 00000000000000..8795fe7a5b887d --- /dev/null +++ b/patches.axfs/axfs-axfs.h.patch @@ -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 index 00000000000000..f77bc4b4ab0263 --- /dev/null +++ b/patches.axfs/axfs-axfs_bdev.c.patch @@ -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 index 00000000000000..1debd34fe11e34 --- /dev/null +++ b/patches.axfs/axfs-axfs_fs.h.patch @@ -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 index 00000000000000..719a7ff2fccfc5 --- /dev/null +++ b/patches.axfs/axfs-axfs_fs_sb.h.patch @@ -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 index 00000000000000..18c73ad6956508 --- /dev/null +++ b/patches.axfs/axfs-axfs_inode.c.patch @@ -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 index 00000000000000..9aaf564040fc1f --- /dev/null +++ b/patches.axfs/axfs-axfs_mtd.c.patch @@ -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 index 00000000000000..9a6c246b0e65d4 --- /dev/null +++ b/patches.axfs/axfs-axfs_physmem.c.patch @@ -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 index 00000000000000..a3573c05f5cb53 --- /dev/null +++ b/patches.axfs/axfs-axfs_profiling.c.patch @@ -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 index 00000000000000..0e9fcb50ee0b2e --- /dev/null +++ b/patches.axfs/axfs-axfs_super.c.patch @@ -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 index 00000000000000..3a3f205a05a7f9 --- /dev/null +++ b/patches.axfs/axfs-axfs_uml.c.patch @@ -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 index 00000000000000..fc2559479e0105 --- /dev/null +++ b/patches.axfs/axfs-axfs_uncompress.c.patch @@ -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 index 00000000000000..881aedbe3d51fc --- /dev/null +++ b/patches.axfs/axfs-kconfigs-and-makefiles.patch @@ -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 index 00000000000000..854e8e909aa872 --- /dev/null +++ b/patches.axfs/axfs-mount-as-rootfs.patch @@ -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 index 00000000000000..fb03b2fd06025f --- /dev/null +++ b/patches.axfs/axfs-xip-debugging-support.patch @@ -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; @@ -112,6 +112,28 @@ 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 # patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch @@ -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 + |