diff --git a/target/linux/xburst/patches-2.6.28/300-fs.patch b/target/linux/xburst/patches-2.6.28/300-fs.patch
deleted file mode 100644
index b9f825403..000000000
--- a/target/linux/xburst/patches-2.6.28/300-fs.patch
+++ /dev/null
@@ -1,47120 +0,0 @@
---- linux-2.6.24.7.old/fs/Kconfig 2009-04-12 18:05:07.000000000 +0200
-+++ linux-2.6.24.7/fs/Kconfig 2009-04-12 18:27:23.000000000 +0200
-@@ -1389,6 +1389,9 @@
-
- endchoice
-
-+# UBIFS File system configuration
-+source "fs/ubifs/Kconfig"
-+
- config CRAMFS
- tristate "Compressed ROM file system support (cramfs)"
- depends on BLOCK
---- linux-2.6.24.7.old/fs/Kconfig.orig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/Kconfig.orig 2009-04-12 18:01:55.000000000 +0200
-@@ -0,0 +1,2202 @@
-+#
-+# File system configuration
-+#
-+
-+menu "File systems"
-+
-+if BLOCK
-+
-+config EXT2_FS
-+ tristate "Second extended fs support"
-+ help
-+ Ext2 is a standard Linux file system for hard disks.
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called ext2.
-+
-+ If unsure, say Y.
-+
-+config EXT2_FS_XATTR
-+ bool "Ext2 extended attributes"
-+ depends on EXT2_FS
-+ help
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ for details).
-+
-+ If unsure, say N.
-+
-+config EXT2_FS_POSIX_ACL
-+ bool "Ext2 POSIX Access Control Lists"
-+ depends on EXT2_FS_XATTR
-+ select FS_POSIX_ACL
-+ help
-+ Posix Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ To learn more about Access Control Lists, visit the Posix ACLs for
-+ Linux website .
-+
-+ If you don't know what Access Control Lists are, say N
-+
-+config EXT2_FS_SECURITY
-+ bool "Ext2 Security Labels"
-+ depends on EXT2_FS_XATTR
-+ help
-+ Security labels support alternative access control models
-+ implemented by security modules like SELinux. This option
-+ enables an extended attribute handler for file security
-+ labels in the ext2 filesystem.
-+
-+ If you are not using a security module that requires using
-+ extended attributes for file security labels, say N.
-+
-+config EXT2_FS_XIP
-+ bool "Ext2 execute in place support"
-+ depends on EXT2_FS && MMU
-+ help
-+ Execute in place can be used on memory-backed block devices. If you
-+ enable this option, you can select to mount block devices which are
-+ capable of this feature without using the page cache.
-+
-+ If you do not use a block device that is capable of using this,
-+ or if unsure, say N.
-+
-+config FS_XIP
-+# execute in place
-+ bool
-+ depends on EXT2_FS_XIP
-+ default y
-+
-+config EXT3_FS
-+ tristate "Ext3 journalling file system support"
-+ select JBD
-+ help
-+ This is the journalling version of the Second extended file system
-+ (often called ext3), the de facto standard Linux file system
-+ (method to organize files on a storage device) for hard disks.
-+
-+ The journalling code included in this driver means you do not have
-+ to run e2fsck (file system checker) on your file systems after a
-+ crash. The journal keeps track of any changes that were being made
-+ at the time the system crashed, and can ensure that your file system
-+ is consistent without the need for a lengthy check.
-+
-+ Other than adding the journal to the file system, the on-disk format
-+ of ext3 is identical to ext2. It is possible to freely switch
-+ between using the ext3 driver and the ext2 driver, as long as the
-+ file system has been cleanly unmounted, or e2fsck is run on the file
-+ system.
-+
-+ To add a journal on an existing ext2 file system or change the
-+ behavior of ext3 file systems, you can use the tune2fs utility ("man
-+ tune2fs"). To modify attributes of files and directories on ext3
-+ file systems, use chattr ("man chattr"). You need to be using
-+ e2fsprogs version 1.20 or later in order to create ext3 journals
-+ (available at ).
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called ext3.
-+
-+config EXT3_FS_XATTR
-+ bool "Ext3 extended attributes"
-+ depends on EXT3_FS
-+ default y
-+ help
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ for details).
-+
-+ If unsure, say N.
-+
-+ You need this for POSIX ACL support on ext3.
-+
-+config EXT3_FS_POSIX_ACL
-+ bool "Ext3 POSIX Access Control Lists"
-+ depends on EXT3_FS_XATTR
-+ select FS_POSIX_ACL
-+ help
-+ Posix Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ To learn more about Access Control Lists, visit the Posix ACLs for
-+ Linux website .
-+
-+ If you don't know what Access Control Lists are, say N
-+
-+config EXT3_FS_SECURITY
-+ bool "Ext3 Security Labels"
-+ depends on EXT3_FS_XATTR
-+ help
-+ Security labels support alternative access control models
-+ implemented by security modules like SELinux. This option
-+ enables an extended attribute handler for file security
-+ labels in the ext3 filesystem.
-+
-+ If you are not using a security module that requires using
-+ extended attributes for file security labels, say N.
-+
-+config EXT4DEV_FS
-+ tristate "Ext4dev/ext4 extended fs support development (EXPERIMENTAL)"
-+ depends on EXPERIMENTAL
-+ select JBD2
-+ select CRC16
-+ help
-+ Ext4dev is a predecessor filesystem of the next generation
-+ extended fs ext4, based on ext3 filesystem code. It will be
-+ renamed ext4 fs later, once ext4dev is mature and stabilized.
-+
-+ Unlike the change from ext2 filesystem to ext3 filesystem,
-+ the on-disk format of ext4dev is not the same as ext3 any more:
-+ it is based on extent maps and it supports 48-bit physical block
-+ numbers. These combined on-disk format changes will allow
-+ ext4dev/ext4 to handle more than 16 TB filesystem volumes --
-+ a hard limit that ext3 cannot overcome without changing the
-+ on-disk format.
-+
-+ Other than extent maps and 48-bit block numbers, ext4dev also is
-+ likely to have other new features such as persistent preallocation,
-+ high resolution time stamps, and larger file support etc. These
-+ features will be added to ext4dev gradually.
-+
-+ To compile this file system support as a module, choose M here. The
-+ module will be called ext4dev.
-+
-+ If unsure, say N.
-+
-+config EXT4DEV_FS_XATTR
-+ bool "Ext4dev extended attributes"
-+ depends on EXT4DEV_FS
-+ default y
-+ help
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ for details).
-+
-+ If unsure, say N.
-+
-+ You need this for POSIX ACL support on ext4dev/ext4.
-+
-+config EXT4DEV_FS_POSIX_ACL
-+ bool "Ext4dev POSIX Access Control Lists"
-+ depends on EXT4DEV_FS_XATTR
-+ select FS_POSIX_ACL
-+ help
-+ POSIX Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ To learn more about Access Control Lists, visit the POSIX ACLs for
-+ Linux website .
-+
-+ If you don't know what Access Control Lists are, say N
-+
-+config EXT4DEV_FS_SECURITY
-+ bool "Ext4dev Security Labels"
-+ depends on EXT4DEV_FS_XATTR
-+ help
-+ Security labels support alternative access control models
-+ implemented by security modules like SELinux. This option
-+ enables an extended attribute handler for file security
-+ labels in the ext4dev/ext4 filesystem.
-+
-+ If you are not using a security module that requires using
-+ extended attributes for file security labels, say N.
-+
-+config JBD
-+ tristate
-+ help
-+ This is a generic journalling layer for block devices. It is
-+ currently used by the ext3 and OCFS2 file systems, but it could
-+ also be used to add journal support to other file systems or block
-+ devices such as RAID or LVM.
-+
-+ If you are using the ext3 or OCFS2 file systems, you need to
-+ say Y here. If you are not using ext3 OCFS2 then you will probably
-+ want to say N.
-+
-+ To compile this device as a module, choose M here: the module will be
-+ called jbd. If you are compiling ext3 or OCFS2 into the kernel,
-+ you cannot compile this code as a module.
-+
-+config JBD_DEBUG
-+ bool "JBD (ext3) debugging support"
-+ depends on JBD && DEBUG_FS
-+ help
-+ If you are using the ext3 journaled file system (or potentially any
-+ other file system/device using JBD), this option allows you to
-+ enable debugging output while the system is running, in order to
-+ help track down any problems you are having. By default the
-+ debugging output will be turned off.
-+
-+ If you select Y here, then you will be able to turn on debugging
-+ with "echo N > /sys/kernel/debug/jbd/jbd-debug", where N is a
-+ number between 1 and 5, the higher the number, the more debugging
-+ output is generated. To turn debugging off again, do
-+ "echo 0 > /sys/kernel/debug/jbd/jbd-debug".
-+
-+config JBD2
-+ tristate
-+ help
-+ This is a generic journaling layer for block devices that support
-+ both 32-bit and 64-bit block numbers. It is currently used by
-+ the ext4dev/ext4 filesystem, but it could also be used to add
-+ journal support to other file systems or block devices such
-+ as RAID or LVM.
-+
-+ If you are using ext4dev/ext4, you need to say Y here. If you are not
-+ using ext4dev/ext4 then you will probably want to say N.
-+
-+ To compile this device as a module, choose M here. The module will be
-+ called jbd2. If you are compiling ext4dev/ext4 into the kernel,
-+ you cannot compile this code as a module.
-+
-+config JBD2_DEBUG
-+ bool "JBD2 (ext4dev/ext4) debugging support"
-+ depends on JBD2 && DEBUG_FS
-+ help
-+ If you are using the ext4dev/ext4 journaled file system (or
-+ potentially any other filesystem/device using JBD2), this option
-+ allows you to enable debugging output while the system is running,
-+ in order to help track down any problems you are having.
-+ By default, the debugging output will be turned off.
-+
-+ If you select Y here, then you will be able to turn on debugging
-+ with "echo N > /sys/kernel/debug/jbd2/jbd2-debug", where N is a
-+ number between 1 and 5. The higher the number, the more debugging
-+ output is generated. To turn debugging off again, do
-+ "echo 0 > /sys/kernel/debug/jbd2/jbd2-debug".
-+
-+config FS_MBCACHE
-+# Meta block cache for Extended Attributes (ext2/ext3/ext4)
-+ tristate
-+ depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR
-+ default y if EXT2_FS=y || EXT3_FS=y || EXT4DEV_FS=y
-+ default m if EXT2_FS=m || EXT3_FS=m || EXT4DEV_FS=m
-+
-+config REISERFS_FS
-+ tristate "Reiserfs support"
-+ help
-+ Stores not just filenames but the files themselves in a balanced
-+ tree. Uses journalling.
-+
-+ Balanced trees are more efficient than traditional file system
-+ architectural foundations.
-+
-+ In general, ReiserFS is as fast as ext2, but is very efficient with
-+ large directories and small files. Additional patches are needed
-+ for NFS and quotas, please see for links.
-+
-+ It is more easily extended to have features currently found in
-+ database and keyword search systems than block allocation based file
-+ systems are. The next version will be so extended, and will support
-+ plugins consistent with our motto ``It takes more than a license to
-+ make source code open.''
-+
-+ Read to learn more about reiserfs.
-+
-+ Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com.
-+
-+ If you like it, you can pay us to add new features to it that you
-+ need, buy a support contract, or pay us to port it to another OS.
-+
-+config REISERFS_CHECK
-+ bool "Enable reiserfs debug mode"
-+ depends on REISERFS_FS
-+ help
-+ If you set this to Y, then ReiserFS will perform every check it can
-+ possibly imagine of its internal consistency throughout its
-+ operation. It will also go substantially slower. More than once we
-+ have forgotten that this was on, and then gone despondent over the
-+ latest benchmarks.:-) Use of this option allows our team to go all
-+ out in checking for consistency when debugging without fear of its
-+ effect on end users. If you are on the verge of sending in a bug
-+ report, say Y and you might get a useful error message. Almost
-+ everyone should say N.
-+
-+config REISERFS_PROC_INFO
-+ bool "Stats in /proc/fs/reiserfs"
-+ depends on REISERFS_FS && PROC_FS
-+ help
-+ Create under /proc/fs/reiserfs a hierarchy of files, displaying
-+ various ReiserFS statistics and internal data at the expense of
-+ making your kernel or module slightly larger (+8 KB). This also
-+ increases the amount of kernel memory required for each mount.
-+ Almost everyone but ReiserFS developers and people fine-tuning
-+ reiserfs or tracing problems should say N.
-+
-+config REISERFS_FS_XATTR
-+ bool "ReiserFS extended attributes"
-+ depends on REISERFS_FS
-+ help
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ for details).
-+
-+ If unsure, say N.
-+
-+config REISERFS_FS_POSIX_ACL
-+ bool "ReiserFS POSIX Access Control Lists"
-+ depends on REISERFS_FS_XATTR
-+ select FS_POSIX_ACL
-+ help
-+ Posix Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ To learn more about Access Control Lists, visit the Posix ACLs for
-+ Linux website .
-+
-+ If you don't know what Access Control Lists are, say N
-+
-+config REISERFS_FS_SECURITY
-+ bool "ReiserFS Security Labels"
-+ depends on REISERFS_FS_XATTR
-+ help
-+ Security labels support alternative access control models
-+ implemented by security modules like SELinux. This option
-+ enables an extended attribute handler for file security
-+ labels in the ReiserFS filesystem.
-+
-+ If you are not using a security module that requires using
-+ extended attributes for file security labels, say N.
-+
-+config JFS_FS
-+ tristate "JFS filesystem support"
-+ select NLS
-+ help
-+ This is a port of IBM's Journaled Filesystem . More information is
-+ available in the file .
-+
-+ If you do not intend to use the JFS filesystem, say N.
-+
-+config JFS_POSIX_ACL
-+ bool "JFS POSIX Access Control Lists"
-+ depends on JFS_FS
-+ select FS_POSIX_ACL
-+ help
-+ Posix Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ To learn more about Access Control Lists, visit the Posix ACLs for
-+ Linux website .
-+
-+ If you don't know what Access Control Lists are, say N
-+
-+config JFS_SECURITY
-+ bool "JFS Security Labels"
-+ depends on JFS_FS
-+ help
-+ Security labels support alternative access control models
-+ implemented by security modules like SELinux. This option
-+ enables an extended attribute handler for file security
-+ labels in the jfs filesystem.
-+
-+ If you are not using a security module that requires using
-+ extended attributes for file security labels, say N.
-+
-+config JFS_DEBUG
-+ bool "JFS debugging"
-+ depends on JFS_FS
-+ help
-+ If you are experiencing any problems with the JFS filesystem, say
-+ Y here. This will result in additional debugging messages to be
-+ written to the system log. Under normal circumstances, this
-+ results in very little overhead.
-+
-+config JFS_STATISTICS
-+ bool "JFS statistics"
-+ depends on JFS_FS
-+ help
-+ Enabling this option will cause statistics from the JFS file system
-+ to be made available to the user in the /proc/fs/jfs/ directory.
-+
-+config FS_POSIX_ACL
-+# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs)
-+#
-+# NOTE: you can implement Posix ACLs without these helpers (XFS does).
-+# Never use this symbol for ifdefs.
-+#
-+ bool
-+ default n
-+
-+source "fs/xfs/Kconfig"
-+source "fs/gfs2/Kconfig"
-+source "fs/yaffs2/Kconfig"
-+
-+config OCFS2_FS
-+ tristate "OCFS2 file system support"
-+ depends on NET && SYSFS
-+ select CONFIGFS_FS
-+ select JBD
-+ select CRC32
-+ help
-+ OCFS2 is a general purpose extent based shared disk cluster file
-+ system with many similarities to ext3. It supports 64 bit inode
-+ numbers, and has automatically extending metadata groups which may
-+ also make it attractive for non-clustered use.
-+
-+ You'll want to install the ocfs2-tools package in order to at least
-+ get "mount.ocfs2".
-+
-+ Project web page: http://oss.oracle.com/projects/ocfs2
-+ Tools web page: http://oss.oracle.com/projects/ocfs2-tools
-+ OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/
-+
-+ Note: Features which OCFS2 does not support yet:
-+ - extended attributes
-+ - quotas
-+ - cluster aware flock
-+ - Directory change notification (F_NOTIFY)
-+ - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
-+ - POSIX ACLs
-+ - readpages / writepages (not user visible)
-+
-+config OCFS2_DEBUG_MASKLOG
-+ bool "OCFS2 logging support"
-+ depends on OCFS2_FS
-+ default y
-+ help
-+ The ocfs2 filesystem has an extensive logging system. The system
-+ allows selection of events to log via files in /sys/o2cb/logmask/.
-+ This option will enlarge your kernel, but it allows debugging of
-+ ocfs2 filesystem issues.
-+
-+config OCFS2_DEBUG_FS
-+ bool "OCFS2 expensive checks"
-+ depends on OCFS2_FS
-+ default n
-+ help
-+ This option will enable expensive consistency checks. Enable
-+ this option for debugging only as it is likely to decrease
-+ performance of the filesystem.
-+
-+config MINI_FO
-+ tristate "Mini fanout overlay filesystem"
-+
-+config MINIX_FS
-+ tristate "Minix fs support"
-+ help
-+ Minix is a simple operating system used in many classes about OS's.
-+ The minix file system (method to organize files on a hard disk
-+ partition or a floppy disk) was the original file system for Linux,
-+ but has been superseded by the second extended file system ext2fs.
-+ You don't want to use the minix file system on your hard disk
-+ because of certain built-in restrictions, but it is sometimes found
-+ on older Linux floppy disks. This option will enlarge your kernel
-+ by about 28 KB. If unsure, say N.
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called minix. Note that the file system of your root
-+ partition (the one containing the directory /) cannot be compiled as
-+ a module.
-+
-+config ROMFS_FS
-+ tristate "ROM file system support"
-+ ---help---
-+ This is a very small read-only file system mainly intended for
-+ initial ram disks of installation disks, but it could be used for
-+ other read-only media as well. Read
-+ for details.
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called romfs. Note that the file system of your
-+ root partition (the one containing the directory /) cannot be a
-+ module.
-+
-+ If you don't know whether you need it, then you don't need it:
-+ answer N.
-+
-+endif
-+
-+config INOTIFY
-+ bool "Inotify file change notification support"
-+ default y
-+ ---help---
-+ Say Y here to enable inotify support. Inotify is a file change
-+ notification system and a replacement for dnotify. Inotify fixes
-+ numerous shortcomings in dnotify and introduces several new features
-+ including multiple file events, one-shot support, and unmount
-+ notification.
-+
-+ For more information, see
-+
-+ If unsure, say Y.
-+
-+config INOTIFY_USER
-+ bool "Inotify support for userspace"
-+ depends on INOTIFY
-+ default y
-+ ---help---
-+ Say Y here to enable inotify support for userspace, including the
-+ associated system calls. Inotify allows monitoring of both files and
-+ directories via a single open fd. Events are read from the file
-+ descriptor, which is also select()- and poll()-able.
-+
-+ For more information, see
-+
-+ If unsure, say Y.
-+
-+config QUOTA
-+ bool "Quota support"
-+ help
-+ If you say Y here, you will be able to set per user limits for disk
-+ usage (also called disk quotas). Currently, it works for the
-+ ext2, ext3, and reiserfs file system. ext3 also supports journalled
-+ quotas for which you don't need to run quotacheck(8) after an unclean
-+ shutdown.
-+ For further details, read the Quota mini-HOWTO, available from
-+ , or the documentation provided
-+ with the quota tools. Probably the quota support is only useful for
-+ multi user systems. If unsure, say N.
-+
-+config QUOTA_NETLINK_INTERFACE
-+ bool "Report quota messages through netlink interface"
-+ depends on QUOTA && NET
-+ help
-+ If you say Y here, quota warnings (about exceeding softlimit, reaching
-+ hardlimit, etc.) will be reported through netlink interface. If unsure,
-+ say Y.
-+
-+config PRINT_QUOTA_WARNING
-+ bool "Print quota warnings to console (OBSOLETE)"
-+ depends on QUOTA
-+ default y
-+ help
-+ If you say Y here, quota warnings (about exceeding softlimit, reaching
-+ hardlimit, etc.) will be printed to the process' controlling terminal.
-+ Note that this behavior is currently deprecated and may go away in
-+ future. Please use notification via netlink socket instead.
-+
-+config QFMT_V1
-+ tristate "Old quota format support"
-+ depends on QUOTA
-+ help
-+ This quota format was (is) used by kernels earlier than 2.4.22. If
-+ you have quota working and you don't want to convert to new quota
-+ format say Y here.
-+
-+config QFMT_V2
-+ tristate "Quota format v2 support"
-+ depends on QUOTA
-+ help
-+ This quota format allows using quotas with 32-bit UIDs/GIDs. If you
-+ need this functionality say Y here.
-+
-+config QUOTACTL
-+ bool
-+ depends on XFS_QUOTA || QUOTA
-+ default y
-+
-+config DNOTIFY
-+ bool "Dnotify support"
-+ default y
-+ help
-+ Dnotify is a directory-based per-fd file change notification system
-+ that uses signals to communicate events to user-space. There exist
-+ superior alternatives, but some applications may still rely on
-+ dnotify.
-+
-+ If unsure, say Y.
-+
-+config AUTOFS_FS
-+ tristate "Kernel automounter support"
-+ help
-+ The automounter is a tool to automatically mount remote file systems
-+ on demand. This implementation is partially kernel-based to reduce
-+ overhead in the already-mounted case; this is unlike the BSD
-+ automounter (amd), which is a pure user space daemon.
-+
-+ To use the automounter you need the user-space tools from the autofs
-+ package; you can find the location in .
-+ You also want to answer Y to "NFS file system support", below.
-+
-+ If you want to use the newer version of the automounter with more
-+ features, say N here and say Y to "Kernel automounter v4 support",
-+ below.
-+
-+ To compile this support as a module, choose M here: the module will be
-+ called autofs.
-+
-+ If you are not a part of a fairly large, distributed network, you
-+ probably do not need an automounter, and can say N here.
-+
-+config AUTOFS4_FS
-+ tristate "Kernel automounter version 4 support (also supports v3)"
-+ help
-+ The automounter is a tool to automatically mount remote file systems
-+ on demand. This implementation is partially kernel-based to reduce
-+ overhead in the already-mounted case; this is unlike the BSD
-+ automounter (amd), which is a pure user space daemon.
-+
-+ To use the automounter you need the user-space tools from
-+ ; you also
-+ want to answer Y to "NFS file system support", below.
-+
-+ To compile this support as a module, choose M here: the module will be
-+ called autofs4. You will need to add "alias autofs autofs4" to your
-+ modules configuration file.
-+
-+ If you are not a part of a fairly large, distributed network or
-+ don't have a laptop which needs to dynamically reconfigure to the
-+ local network, you probably do not need an automounter, and can say
-+ N here.
-+
-+config FUSE_FS
-+ tristate "Filesystem in Userspace support"
-+ help
-+ With FUSE it is possible to implement a fully functional filesystem
-+ in a userspace program.
-+
-+ There's also companion library: libfuse. This library along with
-+ utilities is available from the FUSE homepage:
-+
-+
-+ See for more information.
-+ See for needed library/utility version.
-+
-+ If you want to develop a userspace FS, or if you want to use
-+ a filesystem based on FUSE, answer Y or M.
-+
-+config GENERIC_ACL
-+ bool
-+ select FS_POSIX_ACL
-+
-+if BLOCK
-+menu "CD-ROM/DVD Filesystems"
-+
-+config ISO9660_FS
-+ tristate "ISO 9660 CDROM file system support"
-+ help
-+ This is the standard file system used on CD-ROMs. It was previously
-+ known as "High Sierra File System" and is called "hsfs" on other
-+ Unix systems. The so-called Rock-Ridge extensions which allow for
-+ long Unix filenames and symbolic links are also supported by this
-+ driver. If you have a CD-ROM drive and want to do more with it than
-+ just listen to audio CDs and watch its LEDs, say Y (and read
-+ and the CD-ROM-HOWTO,
-+ available from ), thereby
-+ enlarging your kernel by about 27 KB; otherwise say N.
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called isofs.
-+
-+config JOLIET
-+ bool "Microsoft Joliet CDROM extensions"
-+ depends on ISO9660_FS
-+ select NLS
-+ help
-+ Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system
-+ which allows for long filenames in unicode format (unicode is the
-+ new 16 bit character code, successor to ASCII, which encodes the
-+ characters of almost all languages of the world; see
-+ for more information). Say Y here if you
-+ want to be able to read Joliet CD-ROMs under Linux.
-+
-+config ZISOFS
-+ bool "Transparent decompression extension"
-+ depends on ISO9660_FS
-+ select ZLIB_INFLATE
-+ help
-+ This is a Linux-specific extension to RockRidge which lets you store
-+ data in compressed form on a CD-ROM and have it transparently
-+ decompressed when the CD-ROM is accessed. See
-+ for the tools
-+ necessary to create such a filesystem. Say Y here if you want to be
-+ able to read such compressed CD-ROMs.
-+
-+config UDF_FS
-+ tristate "UDF file system support"
-+ help
-+ This is the new file system used on some CD-ROMs and DVDs. Say Y if
-+ you intend to mount DVD discs or CDRW's written in packet mode, or
-+ if written to by other UDF utilities, such as DirectCD.
-+ Please read .
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called udf.
-+
-+ If unsure, say N.
-+
-+config UDF_NLS
-+ bool
-+ default y
-+ depends on (UDF_FS=m && NLS) || (UDF_FS=y && NLS=y)
-+
-+endmenu
-+endif
-+
-+if BLOCK
-+menu "DOS/FAT/NT Filesystems"
-+
-+config FAT_FS
-+ tristate
-+ select NLS
-+ help
-+ If you want to use one of the FAT-based file systems (the MS-DOS and
-+ VFAT (Windows 95) file systems), then you must say Y or M here
-+ to include FAT support. You will then be able to mount partitions or
-+ diskettes with FAT-based file systems and transparently access the
-+ files on them, i.e. MSDOS files will look and behave just like all
-+ other Unix files.
-+
-+ This FAT support is not a file system in itself, it only provides
-+ the foundation for the other file systems. You will have to say Y or
-+ M to at least one of "MSDOS fs support" or "VFAT fs support" in
-+ order to make use of it.
-+
-+ Another way to read and write MSDOS floppies and hard drive
-+ partitions from within Linux (but not transparently) is with the
-+ mtools ("man mtools") program suite. You don't need to say Y here in
-+ order to do that.
-+
-+ If you need to move large files on floppies between a DOS and a
-+ Linux box, say Y here, mount the floppy under Linux with an MSDOS
-+ file system and use GNU tar's M option. GNU tar is a program
-+ available for Unix and DOS ("man tar" or "info tar").
-+
-+ The FAT support will enlarge your kernel by about 37 KB. If unsure,
-+ say Y.
-+
-+ To compile this as a module, choose M here: the module will be called
-+ fat. Note that if you compile the FAT support as a module, you
-+ cannot compile any of the FAT-based file systems into the kernel
-+ -- they will have to be modules as well.
-+
-+config MSDOS_FS
-+ tristate "MSDOS fs support"
-+ select FAT_FS
-+ help
-+ This allows you to mount MSDOS partitions of your hard drive (unless
-+ they are compressed; to access compressed MSDOS partitions under
-+ Linux, you can either use the DOS emulator DOSEMU, described in the
-+ DOSEMU-HOWTO, available from
-+ , or try dmsdosfs in
-+ . If you
-+ intend to use dosemu with a non-compressed MSDOS partition, say Y
-+ here) and MSDOS floppies. This means that file access becomes
-+ transparent, i.e. the MSDOS files look and behave just like all
-+ other Unix files.
-+
-+ If you have Windows 95 or Windows NT installed on your MSDOS
-+ partitions, you should use the VFAT file system (say Y to "VFAT fs
-+ support" below), or you will not be able to see the long filenames
-+ generated by Windows 95 / Windows NT.
-+
-+ This option will enlarge your kernel by about 7 KB. If unsure,
-+ answer Y. This will only work if you said Y to "DOS FAT fs support"
-+ as well. To compile this as a module, choose M here: the module will
-+ be called msdos.
-+
-+config VFAT_FS
-+ tristate "VFAT (Windows-95) fs support"
-+ select FAT_FS
-+ help
-+ This option provides support for normal Windows file systems with
-+ long filenames. That includes non-compressed FAT-based file systems
-+ used by Windows 95, Windows 98, Windows NT 4.0, and the Unix
-+ programs from the mtools package.
-+
-+ The VFAT support enlarges your kernel by about 10 KB and it only
-+ works if you said Y to the "DOS FAT fs support" above. Please read
-+ the file for details. If
-+ unsure, say Y.
-+
-+ To compile this as a module, choose M here: the module will be called
-+ vfat.
-+
-+config FAT_DEFAULT_CODEPAGE
-+ int "Default codepage for FAT"
-+ depends on MSDOS_FS || VFAT_FS
-+ default 437
-+ help
-+ This option should be set to the codepage of your FAT filesystems.
-+ It can be overridden with the "codepage" mount option.
-+ See for more information.
-+
-+config FAT_DEFAULT_IOCHARSET
-+ string "Default iocharset for FAT"
-+ depends on VFAT_FS
-+ default "iso8859-1"
-+ help
-+ Set this to the default input/output character set you'd
-+ like FAT to use. It should probably match the character set
-+ that most of your FAT filesystems use, and can be overridden
-+ with the "iocharset" mount option for FAT filesystems.
-+ Note that "utf8" is not recommended for FAT filesystems.
-+ If unsure, you shouldn't set "utf8" here.
-+ See for more information.
-+
-+config NTFS_FS
-+ tristate "NTFS file system support"
-+ select NLS
-+ help
-+ NTFS is the file system of Microsoft Windows NT, 2000, XP and 2003.
-+
-+ Saying Y or M here enables read support. There is partial, but
-+ safe, write support available. For write support you must also
-+ say Y to "NTFS write support" below.
-+
-+ There are also a number of user-space tools available, called
-+ ntfsprogs. These include ntfsundelete and ntfsresize, that work
-+ without NTFS support enabled in the kernel.
-+
-+ This is a rewrite from scratch of Linux NTFS support and replaced
-+ the old NTFS code starting with Linux 2.5.11. A backport to
-+ the Linux 2.4 kernel series is separately available as a patch
-+ from the project web site.
-+
-+ For more information see
-+ and .
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called ntfs.
-+
-+ If you are not using Windows NT, 2000, XP or 2003 in addition to
-+ Linux on your computer it is safe to say N.
-+
-+config NTFS_DEBUG
-+ bool "NTFS debugging support"
-+ depends on NTFS_FS
-+ help
-+ If you are experiencing any problems with the NTFS file system, say
-+ Y here. This will result in additional consistency checks to be
-+ performed by the driver as well as additional debugging messages to
-+ be written to the system log. Note that debugging messages are
-+ disabled by default. To enable them, supply the option debug_msgs=1
-+ at the kernel command line when booting the kernel or as an option
-+ to insmod when loading the ntfs module. Once the driver is active,
-+ you can enable debugging messages by doing (as root):
-+ echo 1 > /proc/sys/fs/ntfs-debug
-+ Replacing the "1" with "0" would disable debug messages.
-+
-+ If you leave debugging messages disabled, this results in little
-+ overhead, but enabling debug messages results in very significant
-+ slowdown of the system.
-+
-+ When reporting bugs, please try to have available a full dump of
-+ debugging messages while the misbehaviour was occurring.
-+
-+config NTFS_RW
-+ bool "NTFS write support"
-+ depends on NTFS_FS
-+ help
-+ This enables the partial, but safe, write support in the NTFS driver.
-+
-+ The only supported operation is overwriting existing files, without
-+ changing the file length. No file or directory creation, deletion or
-+ renaming is possible. Note only non-resident files can be written to
-+ so you may find that some very small files (<500 bytes or so) cannot
-+ be written to.
-+
-+ While we cannot guarantee that it will not damage any data, we have
-+ so far not received a single report where the driver would have
-+ damaged someones data so we assume it is perfectly safe to use.
-+
-+ Note: While write support is safe in this version (a rewrite from
-+ scratch of the NTFS support), it should be noted that the old NTFS
-+ write support, included in Linux 2.5.10 and before (since 1997),
-+ is not safe.
-+
-+ This is currently useful with TopologiLinux. TopologiLinux is run
-+ on top of any DOS/Microsoft Windows system without partitioning your
-+ hard disk. Unlike other Linux distributions TopologiLinux does not
-+ need its own partition. For more information see
-+
-+
-+ It is perfectly safe to say N here.
-+
-+endmenu
-+endif
-+
-+menu "Pseudo filesystems"
-+
-+config PROC_FS
-+ bool "/proc file system support" if EMBEDDED
-+ default y
-+ help
-+ This is a virtual file system providing information about the status
-+ of the system. "Virtual" means that it doesn't take up any space on
-+ your hard disk: the files are created on the fly by the kernel when
-+ you try to access them. Also, you cannot read the files with older
-+ version of the program less: you need to use more or cat.
-+
-+ It's totally cool; for example, "cat /proc/interrupts" gives
-+ information about what the different IRQs are used for at the moment
-+ (there is a small number of Interrupt ReQuest lines in your computer
-+ that are used by the attached devices to gain the CPU's attention --
-+ often a source of trouble if two devices are mistakenly configured
-+ to use the same IRQ). The program procinfo to display some
-+ information about your system gathered from the /proc file system.
-+
-+ Before you can use the /proc file system, it has to be mounted,
-+ meaning it has to be given a location in the directory hierarchy.
-+ That location should be /proc. A command such as "mount -t proc proc
-+ /proc" or the equivalent line in /etc/fstab does the job.
-+
-+ The /proc file system is explained in the file
-+ and on the proc(5) manpage
-+ ("man 5 proc").
-+
-+ This option will enlarge your kernel by about 67 KB. Several
-+ programs depend on this, so everyone should say Y here.
-+
-+config PROC_KCORE
-+ bool "/proc/kcore support" if !ARM
-+ depends on PROC_FS && MMU
-+
-+config PROC_VMCORE
-+ bool "/proc/vmcore support (EXPERIMENTAL)"
-+ depends on PROC_FS && EXPERIMENTAL && CRASH_DUMP
-+ default y
-+ help
-+ Exports the dump image of crashed kernel in ELF format.
-+
-+config PROC_SYSCTL
-+ bool "Sysctl support (/proc/sys)" if EMBEDDED
-+ depends on PROC_FS
-+ select SYSCTL
-+ default y
-+ ---help---
-+ The sysctl interface provides a means of dynamically changing
-+ certain kernel parameters and variables on the fly without requiring
-+ a recompile of the kernel or reboot of the system. The primary
-+ interface is through /proc/sys. If you say Y here a tree of
-+ modifiable sysctl entries will be generated beneath the
-+ /proc/sys directory. They are explained in the files
-+ in . Note that enabling this
-+ option will enlarge the kernel by at least 8 KB.
-+
-+ As it is generally a good thing, you should say Y here unless
-+ building a kernel for install/rescue disks or your system is very
-+ limited in memory.
-+
-+config SYSFS
-+ bool "sysfs file system support" if EMBEDDED
-+ default y
-+ help
-+ The sysfs filesystem is a virtual filesystem that the kernel uses to
-+ export internal kernel objects, their attributes, and their
-+ relationships to one another.
-+
-+ Users can use sysfs to ascertain useful information about the running
-+ kernel, such as the devices the kernel has discovered on each bus and
-+ which driver each is bound to. sysfs can also be used to tune devices
-+ and other kernel subsystems.
-+
-+ Some system agents rely on the information in sysfs to operate.
-+ /sbin/hotplug uses device and object attributes in sysfs to assist in
-+ delegating policy decisions, like persistently naming devices.
-+
-+ sysfs is currently used by the block subsystem to mount the root
-+ partition. If sysfs is disabled you must specify the boot device on
-+ the kernel boot command line via its major and minor numbers. For
-+ example, "root=03:01" for /dev/hda1.
-+
-+ Designers of embedded systems may wish to say N here to conserve space.
-+
-+config TMPFS
-+ bool "Virtual memory file system support (former shm fs)"
-+ help
-+ Tmpfs is a file system which keeps all files in virtual memory.
-+
-+ Everything in tmpfs is temporary in the sense that no files will be
-+ created on your hard drive. The files live in memory and swap
-+ space. If you unmount a tmpfs instance, everything stored therein is
-+ lost.
-+
-+ See for details.
-+
-+config TMPFS_POSIX_ACL
-+ bool "Tmpfs POSIX Access Control Lists"
-+ depends on TMPFS
-+ select GENERIC_ACL
-+ help
-+ POSIX Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ To learn more about Access Control Lists, visit the POSIX ACLs for
-+ Linux website .
-+
-+ If you don't know what Access Control Lists are, say N.
-+
-+config HUGETLBFS
-+ bool "HugeTLB file system support"
-+ depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || BROKEN
-+ help
-+ hugetlbfs is a filesystem backing for HugeTLB pages, based on
-+ ramfs. For architectures that support it, say Y here and read
-+ for details.
-+
-+ If unsure, say N.
-+
-+config HUGETLB_PAGE
-+ def_bool HUGETLBFS
-+
-+config CONFIGFS_FS
-+ tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)"
-+ depends on SYSFS && EXPERIMENTAL
-+ help
-+ configfs is a ram-based filesystem that provides the converse
-+ of sysfs's functionality. Where sysfs is a filesystem-based
-+ view of kernel objects, configfs is a filesystem-based manager
-+ of kernel objects, or config_items.
-+
-+ Both sysfs and configfs can and should exist together on the
-+ same system. One is not a replacement for the other.
-+
-+endmenu
-+
-+menu "Miscellaneous filesystems"
-+
-+config ADFS_FS
-+ tristate "ADFS file system support (EXPERIMENTAL)"
-+ depends on BLOCK && EXPERIMENTAL
-+ help
-+ The Acorn Disc Filing System is the standard file system of the
-+ RiscOS operating system which runs on Acorn's ARM-based Risc PC
-+ systems and the Acorn Archimedes range of machines. If you say Y
-+ here, Linux will be able to read from ADFS partitions on hard drives
-+ and from ADFS-formatted floppy discs. If you also want to be able to
-+ write to those devices, say Y to "ADFS write support" below.
-+
-+ The ADFS partition should be the first partition (i.e.,
-+ /dev/[hs]d?1) on each of your drives. Please read the file
-+ for further details.
-+
-+ To compile this code as a module, choose M here: the module will be
-+ called adfs.
-+
-+ If unsure, say N.
-+
-+config ADFS_FS_RW
-+ bool "ADFS write support (DANGEROUS)"
-+ depends on ADFS_FS
-+ help
-+ If you say Y here, you will be able to write to ADFS partitions on
-+ hard drives and ADFS-formatted floppy disks. This is experimental
-+ codes, so if you're unsure, say N.
-+
-+config AFFS_FS
-+ tristate "Amiga FFS file system support (EXPERIMENTAL)"
-+ depends on BLOCK && EXPERIMENTAL
-+ help
-+ The Fast File System (FFS) is the common file system used on hard
-+ disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20). Say Y
-+ if you want to be able to read and write files from and to an Amiga
-+ FFS partition on your hard drive. Amiga floppies however cannot be
-+ read with this driver due to an incompatibility of the floppy
-+ controller used in an Amiga and the standard floppy controller in
-+ PCs and workstations. Read
-+ and .
-+
-+ With this driver you can also mount disk files used by Bernd
-+ Schmidt's Un*X Amiga Emulator
-+ ().
-+ If you want to do this, you will also need to say Y or M to "Loop
-+ device support", above.
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called affs. If unsure, say N.
-+
-+config ECRYPT_FS
-+ tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
-+ depends on EXPERIMENTAL && KEYS && CRYPTO && NET
-+ help
-+ Encrypted filesystem that operates on the VFS layer. See
-+ to learn more about
-+ eCryptfs. Userspace components are required and can be
-+ obtained from .
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called ecryptfs.
-+
-+config HFS_FS
-+ tristate "Apple Macintosh file system support (EXPERIMENTAL)"
-+ depends on BLOCK && EXPERIMENTAL
-+ select NLS
-+ help
-+ If you say Y here, you will be able to mount Macintosh-formatted
-+ floppy disks and hard drive partitions with full read-write access.
-+ Please read to learn about
-+ the available mount options.
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called hfs.
-+
-+config HFSPLUS_FS
-+ tristate "Apple Extended HFS file system support"
-+ depends on BLOCK
-+ select NLS
-+ select NLS_UTF8
-+ help
-+ If you say Y here, you will be able to mount extended format
-+ Macintosh-formatted hard drive partitions with full read-write access.
-+
-+ This file system is often called HFS+ and was introduced with
-+ MacOS 8. It includes all Mac specific filesystem data such as
-+ data forks and creator codes, but it also has several UNIX
-+ style features such as file ownership and permissions.
-+
-+config BEFS_FS
-+ tristate "BeOS file system (BeFS) support (read only) (EXPERIMENTAL)"
-+ depends on BLOCK && EXPERIMENTAL
-+ select NLS
-+ help
-+ The BeOS File System (BeFS) is the native file system of Be, Inc's
-+ BeOS. Notable features include support for arbitrary attributes
-+ on files and directories, and database-like indices on selected
-+ attributes. (Also note that this driver doesn't make those features
-+ available at this time). It is a 64 bit filesystem, so it supports
-+ extremely large volumes and files.
-+
-+ If you use this filesystem, you should also say Y to at least one
-+ of the NLS (native language support) options below.
-+
-+ If you don't know what this is about, say N.
-+
-+ To compile this as a module, choose M here: the module will be
-+ called befs.
-+
-+config BEFS_DEBUG
-+ bool "Debug BeFS"
-+ depends on BEFS_FS
-+ help
-+ If you say Y here, you can use the 'debug' mount option to enable
-+ debugging output from the driver.
-+
-+config BFS_FS
-+ tristate "BFS file system support (EXPERIMENTAL)"
-+ depends on BLOCK && EXPERIMENTAL
-+ help
-+ Boot File System (BFS) is a file system used under SCO UnixWare to
-+ allow the bootloader access to the kernel image and other important
-+ files during the boot process. It is usually mounted under /stand
-+ and corresponds to the slice marked as "STAND" in the UnixWare
-+ partition. You should say Y if you want to read or write the files
-+ on your /stand slice from within Linux. You then also need to say Y
-+ to "UnixWare slices support", below. More information about the BFS
-+ file system is contained in the file
-+ .
-+
-+ If you don't know what this is about, say N.
-+
-+ To compile this as a module, choose M here: the module will be called
-+ bfs. Note that the file system of your root partition (the one
-+ containing the directory /) cannot be compiled as a module.
-+
-+
-+
-+config EFS_FS
-+ tristate "EFS file system support (read only) (EXPERIMENTAL)"
-+ depends on BLOCK && EXPERIMENTAL
-+ help
-+ EFS is an older file system used for non-ISO9660 CD-ROMs and hard
-+ disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer
-+ uses the XFS file system for hard disk partitions however).
-+
-+ This implementation only offers read-only access. If you don't know
-+ what all this is about, it's safe to say N. For more information
-+ about EFS see its home page at .
-+
-+ To compile the EFS file system support as a module, choose M here: the
-+ module will be called efs.
-+
-+config JFFS2_FS
-+ tristate "Journalling Flash File System v2 (JFFS2) support"
-+ select CRC32
-+ depends on MTD
-+ help
-+ JFFS2 is the second generation of the Journalling Flash File System
-+ for use on diskless embedded devices. It provides improved wear
-+ levelling, compression and support for hard links. You cannot use
-+ this on normal block devices, only on 'MTD' devices.
-+
-+ Further information on the design and implementation of JFFS2 is
-+ available at .
-+
-+config JFFS2_FS_DEBUG
-+ int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)"
-+ depends on JFFS2_FS
-+ default "0"
-+ help
-+ This controls the amount of debugging messages produced by the JFFS2
-+ code. Set it to zero for use in production systems. For evaluation,
-+ testing and debugging, it's advisable to set it to one. This will
-+ enable a few assertions and will print debugging messages at the
-+ KERN_DEBUG loglevel, where they won't normally be visible. Level 2
-+ is unlikely to be useful - it enables extra debugging in certain
-+ areas which at one point needed debugging, but when the bugs were
-+ located and fixed, the detailed messages were relegated to level 2.
-+
-+ If reporting bugs, please try to have available a full dump of the
-+ messages at debug level 1 while the misbehaviour was occurring.
-+
-+config JFFS2_FS_WRITEBUFFER
-+ bool "JFFS2 write-buffering support"
-+ depends on JFFS2_FS
-+ default y
-+ help
-+ This enables the write-buffering support in JFFS2.
-+
-+ This functionality is required to support JFFS2 on the following
-+ types of flash devices:
-+ - NAND flash
-+ - NOR flash with transparent ECC
-+ - DataFlash
-+
-+config JFFS2_FS_WBUF_VERIFY
-+ bool "Verify JFFS2 write-buffer reads"
-+ depends on JFFS2_FS_WRITEBUFFER
-+ default n
-+ help
-+ This causes JFFS2 to read back every page written through the
-+ write-buffer, and check for errors.
-+
-+config JFFS2_SUMMARY
-+ bool "JFFS2 summary support (EXPERIMENTAL)"
-+ depends on JFFS2_FS && EXPERIMENTAL
-+ default n
-+ help
-+ This feature makes it possible to use summary information
-+ for faster filesystem mount.
-+
-+ The summary information can be inserted into a filesystem image
-+ by the utility 'sumtool'.
-+
-+ If unsure, say 'N'.
-+
-+config JFFS2_FS_XATTR
-+ bool "JFFS2 XATTR support (EXPERIMENTAL)"
-+ depends on JFFS2_FS && EXPERIMENTAL
-+ default n
-+ help
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ for details).
-+
-+ If unsure, say N.
-+
-+config JFFS2_FS_POSIX_ACL
-+ bool "JFFS2 POSIX Access Control Lists"
-+ depends on JFFS2_FS_XATTR
-+ default y
-+ select FS_POSIX_ACL
-+ help
-+ Posix Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ To learn more about Access Control Lists, visit the Posix ACLs for
-+ Linux website .
-+
-+ If you don't know what Access Control Lists are, say N
-+
-+config JFFS2_FS_SECURITY
-+ bool "JFFS2 Security Labels"
-+ depends on JFFS2_FS_XATTR
-+ default y
-+ help
-+ Security labels support alternative access control models
-+ implemented by security modules like SELinux. This option
-+ enables an extended attribute handler for file security
-+ labels in the jffs2 filesystem.
-+
-+ If you are not using a security module that requires using
-+ extended attributes for file security labels, say N.
-+
-+config JFFS2_COMPRESSION_OPTIONS
-+ bool "Advanced compression options for JFFS2"
-+ depends on JFFS2_FS
-+ default n
-+ help
-+ Enabling this option allows you to explicitly choose which
-+ compression modules, if any, are enabled in JFFS2. Removing
-+ compressors can mean you cannot read existing file systems,
-+ and enabling experimental compressors can mean that you
-+ write a file system which cannot be read by a standard kernel.
-+
-+ If unsure, you should _definitely_ say 'N'.
-+
-+config JFFS2_ZLIB
-+ bool "JFFS2 ZLIB compression support" if JFFS2_COMPRESSION_OPTIONS
-+ select ZLIB_INFLATE
-+ select ZLIB_DEFLATE
-+ depends on JFFS2_FS
-+ default y
-+ help
-+ Zlib is designed to be a free, general-purpose, legally unencumbered,
-+ lossless data-compression library for use on virtually any computer
-+ hardware and operating system. See for
-+ further information.
-+
-+ Say 'Y' if unsure.
-+
-+config JFFS2_LZO
-+ bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS
-+ select LZO_COMPRESS
-+ select LZO_DECOMPRESS
-+ depends on JFFS2_FS
-+ default n
-+ help
-+ minilzo-based compression. Generally works better than Zlib.
-+
-+ This feature was added in July, 2007. Say 'N' if you need
-+ compatibility with older bootloaders or kernels.
-+
-+config JFFS2_RTIME
-+ bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
-+ depends on JFFS2_FS
-+ default y
-+ help
-+ Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
-+
-+config JFFS2_RUBIN
-+ bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
-+ depends on JFFS2_FS
-+ default n
-+ help
-+ RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
-+
-+choice
-+ prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
-+ default JFFS2_CMODE_PRIORITY
-+ depends on JFFS2_FS
-+ help
-+ You can set here the default compression mode of JFFS2 from
-+ the available compression modes. Don't touch if unsure.
-+
-+config JFFS2_CMODE_NONE
-+ bool "no compression"
-+ help
-+ Uses no compression.
-+
-+config JFFS2_CMODE_PRIORITY
-+ bool "priority"
-+ help
-+ Tries the compressors in a predefined order and chooses the first
-+ successful one.
-+
-+config JFFS2_CMODE_SIZE
-+ bool "size (EXPERIMENTAL)"
-+ help
-+ Tries all compressors and chooses the one which has the smallest
-+ result.
-+
-+config JFFS2_CMODE_FAVOURLZO
-+ bool "Favour LZO"
-+ help
-+ Tries all compressors and chooses the one which has the smallest
-+ result but gives some preference to LZO (which has faster
-+ decompression) at the expense of size.
-+
-+endchoice
-+
-+config CRAMFS
-+ tristate "Compressed ROM file system support (cramfs)"
-+ depends on BLOCK
-+ select ZLIB_INFLATE
-+ help
-+ Saying Y here includes support for CramFs (Compressed ROM File
-+ System). CramFs is designed to be a simple, small, and compressed
-+ file system for ROM based embedded systems. CramFs is read-only,
-+ limited to 256MB file systems (with 16MB files), and doesn't support
-+ 16/32 bits uid/gid, hard links and timestamps.
-+
-+ See and
-+ for further information.
-+
-+ To compile this as a module, choose M here: the module will be called
-+ cramfs. Note that the root file system (the one containing the
-+ directory /) cannot be compiled as a module.
-+
-+ If unsure, say N.
-+
-+config SQUASHFS
-+ tristate "SquashFS 3.0 - Squashed file system support"
-+ select ZLIB_INFLATE
-+ help
-+ Saying Y here includes support for SquashFS 3.0 (a Compressed Read-Only File
-+ System). Squashfs is a highly compressed read-only filesystem for Linux.
-+ It uses zlib compression to compress both files, inodes and directories.
-+ Inodes in the system are very small and all blocks are packed to minimise
-+ data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
-+ SquashFS 3.0 supports 64 bit filesystems and files (larger than 4GB), full
-+ uid/gid information, hard links and timestamps.
-+
-+ Squashfs is intended for general read-only filesystem use, for archival
-+ use (i.e. in cases where a .tar.gz file may be used), and in embedded
-+ systems where low overhead is needed. Further information and filesystem tools
-+ are available from http://squashfs.sourceforge.net.
-+
-+ If you want to compile this as a module ( = code which can be
-+ inserted in and removed from the running kernel whenever you want),
-+ say M here and read . The module
-+ will be called squashfs. Note that the root file system (the one
-+ containing the directory /) cannot be compiled as a module.
-+
-+ If unsure, say N.
-+
-+config SQUASHFS_EMBEDDED
-+
-+ bool "Additional options for memory-constrained systems"
-+ depends on SQUASHFS
-+ default n
-+ help
-+ Saying Y here allows you to specify cache sizes and how Squashfs
-+ allocates memory. This is only intended for memory constrained
-+ systems.
-+
-+ If unsure, say N.
-+
-+config SQUASHFS_FRAGMENT_CACHE_SIZE
-+ int "Number of fragments cached" if SQUASHFS_EMBEDDED
-+ depends on SQUASHFS
-+ default "3"
-+ help
-+ By default SquashFS caches the last 3 fragments read from
-+ the filesystem. Increasing this amount may mean SquashFS
-+ has to re-read fragments less often from disk, at the expense
-+ of extra system memory. Decreasing this amount will mean
-+ SquashFS uses less memory at the expense of extra reads from disk.
-+
-+ Note there must be at least one cached fragment. Anything
-+ much more than three will probably not make much difference.
-+
-+config SQUASHFS_VMALLOC
-+ bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
-+ depends on SQUASHFS
-+ default n
-+ help
-+ By default SquashFS uses kmalloc to obtain fragment cache memory.
-+ Kmalloc memory is the standard kernel allocator, but it can fail
-+ on memory constrained systems. Because of the way Vmalloc works,
-+ Vmalloc can succeed when kmalloc fails. Specifying this option
-+ will make SquashFS always use Vmalloc to allocate the
-+ fragment cache memory.
-+
-+ If unsure, say N.
-+
-+config VXFS_FS
-+ tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
-+ depends on BLOCK
-+ help
-+ FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
-+ file system format. VERITAS VxFS(TM) is the standard file system
-+ of SCO UnixWare (and possibly others) and optionally available
-+ for Sunsoft Solaris, HP-UX and many other operating systems.
-+ Currently only readonly access is supported.
-+
-+ NOTE: the file system type as used by mount(1), mount(2) and
-+ fstab(5) is 'vxfs' as it describes the file system format, not
-+ the actual driver.
-+
-+ To compile this as a module, choose M here: the module will be
-+ called freevxfs. If unsure, say N.
-+
-+
-+config HPFS_FS
-+ tristate "OS/2 HPFS file system support"
-+ depends on BLOCK
-+ help
-+ OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
-+ is the file system used for organizing files on OS/2 hard disk
-+ partitions. Say Y if you want to be able to read files from and
-+ write files to an OS/2 HPFS partition on your hard drive. OS/2
-+ floppies however are in regular MSDOS format, so you don't need this
-+ option in order to be able to read them. Read
-+ .
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called hpfs. If unsure, say N.
-+
-+
-+
-+config QNX4FS_FS
-+ tristate "QNX4 file system support (read only)"
-+ depends on BLOCK
-+ help
-+ This is the file system used by the real-time operating systems
-+ QNX 4 and QNX 6 (the latter is also called QNX RTP).
-+ Further information is available at .
-+ Say Y if you intend to mount QNX hard disks or floppies.
-+ Unless you say Y to "QNX4FS read-write support" below, you will
-+ only be able to read these file systems.
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called qnx4.
-+
-+ If you don't know whether you need it, then you don't need it:
-+ answer N.
-+
-+config QNX4FS_RW
-+ bool "QNX4FS write support (DANGEROUS)"
-+ depends on QNX4FS_FS && EXPERIMENTAL && BROKEN
-+ help
-+ Say Y if you want to test write support for QNX4 file systems.
-+
-+ It's currently broken, so for now:
-+ answer N.
-+
-+
-+
-+config SYSV_FS
-+ tristate "System V/Xenix/V7/Coherent file system support"
-+ depends on BLOCK
-+ help
-+ SCO, Xenix and Coherent are commercial Unix systems for Intel
-+ machines, and Version 7 was used on the DEC PDP-11. Saying Y
-+ here would allow you to read from their floppies and hard disk
-+ partitions.
-+
-+ If you have floppies or hard disk partitions like that, it is likely
-+ that they contain binaries from those other Unix systems; in order
-+ to run these binaries, you will want to install linux-abi which is
-+ a set of kernel modules that lets you run SCO, Xenix, Wyse,
-+ UnixWare, Dell Unix and System V programs under Linux. It is
-+ available via FTP (user: ftp) from
-+ ).
-+ NOTE: that will work only for binaries from Intel-based systems;
-+ PDP ones will have to wait until somebody ports Linux to -11 ;-)
-+
-+ If you only intend to mount files from some other Unix over the
-+ network using NFS, you don't need the System V file system support
-+ (but you need NFS file system support obviously).
-+
-+ Note that this option is generally not needed for floppies, since a
-+ good portable way to transport files and directories between unixes
-+ (and even other operating systems) is given by the tar program ("man
-+ tar" or preferably "info tar"). Note also that this option has
-+ nothing whatsoever to do with the option "System V IPC". Read about
-+ the System V file system in
-+ .
-+ Saying Y here will enlarge your kernel by about 27 KB.
-+
-+ To compile this as a module, choose M here: the module will be called
-+ sysv.
-+
-+ If you haven't heard about all of this before, it's safe to say N.
-+
-+
-+
-+config UFS_FS
-+ tristate "UFS file system support (read only)"
-+ depends on BLOCK
-+ help
-+ BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
-+ OpenBSD and NeXTstep) use a file system called UFS. Some System V
-+ Unixes can create and mount hard disk partitions and diskettes using
-+ this file system as well. Saying Y here will allow you to read from
-+ these partitions; if you also want to write to them, say Y to the
-+ experimental "UFS file system write support", below. Please read the
-+ file for more information.
-+
-+ The recently released UFS2 variant (used in FreeBSD 5.x) is
-+ READ-ONLY supported.
-+
-+ If you only intend to mount files from some other Unix over the
-+ network using NFS, you don't need the UFS file system support (but
-+ you need NFS file system support obviously).
-+
-+ Note that this option is generally not needed for floppies, since a
-+ good portable way to transport files and directories between unixes
-+ (and even other operating systems) is given by the tar program ("man
-+ tar" or preferably "info tar").
-+
-+ When accessing NeXTstep files, you may need to convert them from the
-+ NeXT character set to the Latin1 character set; use the program
-+ recode ("info recode") for this purpose.
-+
-+ To compile the UFS file system support as a module, choose M here: the
-+ module will be called ufs.
-+
-+ If you haven't heard about all of this before, it's safe to say N.
-+
-+config UFS_FS_WRITE
-+ bool "UFS file system write support (DANGEROUS)"
-+ depends on UFS_FS && EXPERIMENTAL
-+ help
-+ Say Y here if you want to try writing to UFS partitions. This is
-+ experimental, so you should back up your UFS partitions beforehand.
-+
-+config UFS_DEBUG
-+ bool "UFS debugging"
-+ depends on UFS_FS
-+ help
-+ If you are experiencing any problems with the UFS filesystem, say
-+ Y here. This will result in _many_ additional debugging messages to be
-+ written to the system log.
-+
-+endmenu
-+
-+menuconfig NETWORK_FILESYSTEMS
-+ bool "Network File Systems"
-+ default y
-+ depends on NET
-+ ---help---
-+ Say Y here to get to see options for network filesystems and
-+ filesystem-related networking code, such as NFS daemon and
-+ RPCSEC security modules.
-+ This option alone does not add any kernel code.
-+
-+ If you say N, all options in this submenu will be skipped and
-+ disabled; if unsure, say Y here.
-+
-+if NETWORK_FILESYSTEMS
-+
-+config NFS_FS
-+ tristate "NFS file system support"
-+ depends on INET
-+ select LOCKD
-+ select SUNRPC
-+ select NFS_ACL_SUPPORT if NFS_V3_ACL
-+ help
-+ If you are connected to some other (usually local) Unix computer
-+ (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing
-+ on that computer (the NFS server) using the Network File Sharing
-+ protocol, say Y. "Mounting files" means that the client can access
-+ the files with usual UNIX commands as if they were sitting on the
-+ client's hard disk. For this to work, the server must run the
-+ programs nfsd and mountd (but does not need to have NFS file system
-+ support enabled in its kernel). NFS is explained in the Network
-+ Administrator's Guide, available from
-+ , on its man page: "man
-+ nfs", and in the NFS-HOWTO.
-+
-+ A superior but less widely used alternative to NFS is provided by
-+ the Coda file system; see "Coda file system support" below.
-+
-+ If you say Y here, you should have said Y to TCP/IP networking also.
-+ This option would enlarge your kernel by about 27 KB.
-+
-+ To compile this file system support as a module, choose M here: the
-+ module will be called nfs.
-+
-+ If you are configuring a diskless machine which will mount its root
-+ file system over NFS at boot time, say Y here and to "Kernel
-+ level IP autoconfiguration" above and to "Root file system on NFS"
-+ below. You cannot compile this driver as a module in this case.
-+ There are two packages designed for booting diskless machines over
-+ the net: netboot, available from
-+ , and Etherboot,
-+ available from .
-+
-+ If you don't know what all this is about, say N.
-+
-+config NFS_V3
-+ bool "Provide NFSv3 client support"
-+ depends on NFS_FS
-+ help
-+ Say Y here if you want your NFS client to be able to speak version
-+ 3 of the NFS protocol.
-+
-+ If unsure, say Y.
-+
-+config NFS_V3_ACL
-+ bool "Provide client support for the NFSv3 ACL protocol extension"
-+ depends on NFS_V3
-+ help
-+ Implement the NFSv3 ACL protocol extension for manipulating POSIX
-+ Access Control Lists. The server should also be compiled with
-+ the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option.
-+
-+ If unsure, say N.
-+
-+config NFS_V4
-+ bool "Provide NFSv4 client support (EXPERIMENTAL)"
-+ depends on NFS_FS && EXPERIMENTAL
-+ select RPCSEC_GSS_KRB5
-+ help
-+ Say Y here if you want your NFS client to be able to speak the newer
-+ version 4 of the NFS protocol.
-+
-+ Note: Requires auxiliary userspace daemons which may be found on
-+ http://www.citi.umich.edu/projects/nfsv4/
-+
-+ If unsure, say N.
-+
-+config NFS_DIRECTIO
-+ bool "Allow direct I/O on NFS files"
-+ depends on NFS_FS
-+ help
-+ This option enables applications to perform uncached I/O on files
-+ in NFS file systems using the O_DIRECT open() flag. When O_DIRECT
-+ is set for a file, its data is not cached in the system's page
-+ cache. Data is moved to and from user-level application buffers
-+ directly. Unlike local disk-based file systems, NFS O_DIRECT has
-+ no alignment restrictions.
-+
-+ Unless your program is designed to use O_DIRECT properly, you are
-+ much better off allowing the NFS client to manage data caching for
-+ you. Misusing O_DIRECT can cause poor server performance or network
-+ storms. This kernel build option defaults OFF to avoid exposing
-+ system administrators unwittingly to a potentially hazardous
-+ feature.
-+
-+ For more details on NFS O_DIRECT, see fs/nfs/direct.c.
-+
-+ If unsure, say N. This reduces the size of the NFS client, and
-+ causes open() to return EINVAL if a file residing in NFS is
-+ opened with the O_DIRECT flag.
-+
-+config NFSD
-+ tristate "NFS server support"
-+ depends on INET
-+ select LOCKD
-+ select SUNRPC
-+ select EXPORTFS
-+ select NFSD_V2_ACL if NFSD_V3_ACL
-+ select NFS_ACL_SUPPORT if NFSD_V2_ACL
-+ select NFSD_TCP if NFSD_V4
-+ select CRYPTO_MD5 if NFSD_V4
-+ select CRYPTO if NFSD_V4
-+ select FS_POSIX_ACL if NFSD_V4
-+ help
-+ If you want your Linux box to act as an NFS *server*, so that other
-+ computers on your local network which support NFS can access certain
-+ directories on your box transparently, you have two options: you can
-+ use the self-contained user space program nfsd, in which case you
-+ should say N here, or you can say Y and use the kernel based NFS
-+ server. The advantage of the kernel based solution is that it is
-+ faster.
-+
-+ In either case, you will need support software; the respective
-+ locations are given in the file in the
-+ NFS section.
-+
-+ If you say Y here, you will get support for version 2 of the NFS
-+ protocol (NFSv2). If you also want NFSv3, say Y to the next question
-+ as well.
-+
-+ Please read the NFS-HOWTO, available from
-+ .
-+
-+ To compile the NFS server support as a module, choose M here: the
-+ module will be called nfsd. If unsure, say N.
-+
-+config NFSD_V2_ACL
-+ bool
-+ depends on NFSD
-+
-+config NFSD_V3
-+ bool "Provide NFSv3 server support"
-+ depends on NFSD
-+ help
-+ If you would like to include the NFSv3 server as well as the NFSv2
-+ server, say Y here. If unsure, say Y.
-+
-+config NFSD_V3_ACL
-+ bool "Provide server support for the NFSv3 ACL protocol extension"
-+ depends on NFSD_V3
-+ help
-+ Implement the NFSv3 ACL protocol extension for manipulating POSIX
-+ Access Control Lists on exported file systems. NFS clients should
-+ be compiled with the NFSv3 ACL protocol extension; see the
-+ CONFIG_NFS_V3_ACL option. If unsure, say N.
-+
-+config NFSD_V4
-+ bool "Provide NFSv4 server support (EXPERIMENTAL)"
-+ depends on NFSD && NFSD_V3 && EXPERIMENTAL
-+ select RPCSEC_GSS_KRB5
-+ help
-+ If you would like to include the NFSv4 server as well as the NFSv2
-+ and NFSv3 servers, say Y here. This feature is experimental, and
-+ should only be used if you are interested in helping to test NFSv4.
-+ If unsure, say N.
-+
-+config NFSD_TCP
-+ bool "Provide NFS server over TCP support"
-+ depends on NFSD
-+ default y
-+ help
-+ If you want your NFS server to support TCP connections, say Y here.
-+ TCP connections usually perform better than the default UDP when
-+ the network is lossy or congested. If unsure, say Y.
-+
-+config ROOT_NFS
-+ bool "Root file system on NFS"
-+ depends on NFS_FS=y && IP_PNP
-+ help
-+ If you want your Linux box to mount its whole root file system (the
-+ one containing the directory /) from some other computer over the
-+ net via NFS (presumably because your box doesn't have a hard disk),
-+ say Y. Read for details. It is
-+ likely that in this case, you also want to say Y to "Kernel level IP
-+ autoconfiguration" so that your box can discover its network address
-+ at boot time.
-+
-+ Most people say N here.
-+
-+config LOCKD
-+ tristate
-+
-+config LOCKD_V4
-+ bool
-+ depends on NFSD_V3 || NFS_V3
-+ default y
-+
-+config EXPORTFS
-+ tristate
-+
-+config NFS_ACL_SUPPORT
-+ tristate
-+ select FS_POSIX_ACL
-+
-+config NFS_COMMON
-+ bool
-+ depends on NFSD || NFS_FS
-+ default y
-+
-+config SUNRPC
-+ tristate
-+
-+config SUNRPC_GSS
-+ tristate
-+
-+config SUNRPC_XPRT_RDMA
-+ tristate "RDMA transport for sunrpc (EXPERIMENTAL)"
-+ depends on SUNRPC && INFINIBAND && EXPERIMENTAL
-+ default m
-+ help
-+ Adds a client RPC transport for supporting kernel NFS over RDMA
-+ mounts, including Infiniband and iWARP. Experimental.
-+
-+config SUNRPC_BIND34
-+ bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)"
-+ depends on SUNRPC && EXPERIMENTAL
-+ help
-+ Provides kernel support for querying rpcbind servers via versions 3
-+ and 4 of the rpcbind protocol. The kernel automatically falls back
-+ to version 2 if a remote rpcbind service does not support versions
-+ 3 or 4.
-+
-+ If unsure, say N to get traditional behavior (version 2 rpcbind
-+ requests only).
-+
-+config RPCSEC_GSS_KRB5
-+ tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)"
-+ depends on SUNRPC && EXPERIMENTAL
-+ select SUNRPC_GSS
-+ select CRYPTO
-+ select CRYPTO_MD5
-+ select CRYPTO_DES
-+ select CRYPTO_CBC
-+ help
-+ Provides for secure RPC calls by means of a gss-api
-+ mechanism based on Kerberos V5. This is required for
-+ NFSv4.
-+
-+ Note: Requires an auxiliary userspace daemon which may be found on
-+ http://www.citi.umich.edu/projects/nfsv4/
-+
-+ If unsure, say N.
-+
-+config RPCSEC_GSS_SPKM3
-+ tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)"
-+ depends on SUNRPC && EXPERIMENTAL
-+ select SUNRPC_GSS
-+ select CRYPTO
-+ select CRYPTO_MD5
-+ select CRYPTO_DES
-+ select CRYPTO_CAST5
-+ select CRYPTO_CBC
-+ help
-+ Provides for secure RPC calls by means of a gss-api
-+ mechanism based on the SPKM3 public-key mechanism.
-+
-+ Note: Requires an auxiliary userspace daemon which may be found on
-+ http://www.citi.umich.edu/projects/nfsv4/
-+
-+ If unsure, say N.
-+
-+config SMB_FS
-+ tristate "SMB file system support (to mount Windows shares etc.)"
-+ depends on INET
-+ select NLS
-+ help
-+ SMB (Server Message Block) is the protocol Windows for Workgroups
-+ (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share
-+ files and printers over local networks. Saying Y here allows you to
-+ mount their file systems (often called "shares" in this context) and
-+ access them just like any other Unix directory. Currently, this
-+ works only if the Windows machines use TCP/IP as the underlying
-+ transport protocol, and not NetBEUI. For details, read
-+ and the SMB-HOWTO,
-+ available from .
-+
-+ Note: if you just want your box to act as an SMB *server* and make
-+ files and printing services available to Windows clients (which need
-+ to have a TCP/IP stack), you don't need to say Y here; you can use
-+ the program SAMBA (available from )
-+ for that.
-+
-+ General information about how to connect Linux, Windows machines and
-+ Macs is on the WWW at .
-+
-+ To compile the SMB support as a module, choose M here: the module will
-+ be called smbfs. Most people say N, however.
-+
-+config SMB_NLS_DEFAULT
-+ bool "Use a default NLS"
-+ depends on SMB_FS
-+ help
-+ Enabling this will make smbfs use nls translations by default. You
-+ need to specify the local charset (CONFIG_NLS_DEFAULT) in the nls
-+ settings and you need to give the default nls for the SMB server as
-+ CONFIG_SMB_NLS_REMOTE.
-+
-+ The nls settings can be changed at mount time, if your smbmount
-+ supports that, using the codepage and iocharset parameters.
-+
-+ smbmount from samba 2.2.0 or later supports this.
-+
-+config SMB_NLS_REMOTE
-+ string "Default Remote NLS Option"
-+ depends on SMB_NLS_DEFAULT
-+ default "cp437"
-+ help
-+ This setting allows you to specify a default value for which
-+ codepage the server uses. If this field is left blank no
-+ translations will be done by default. The local codepage/charset
-+ default to CONFIG_NLS_DEFAULT.
-+
-+ The nls settings can be changed at mount time, if your smbmount
-+ supports that, using the codepage and iocharset parameters.
-+
-+ smbmount from samba 2.2.0 or later supports this.
-+
-+config CIFS
-+ tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)"
-+ depends on INET
-+ select NLS
-+ help
-+ This is the client VFS module for the Common Internet File System
-+ (CIFS) protocol which is the successor to the Server Message Block
-+ (SMB) protocol, the native file sharing mechanism for most early
-+ PC operating systems. The CIFS protocol is fully supported by
-+ file servers such as Windows 2000 (including Windows 2003, NT 4
-+ and Windows XP) as well by Samba (which provides excellent CIFS
-+ server support for Linux and many other operating systems). Limited
-+ support for OS/2 and Windows ME and similar servers is provided as well.
-+
-+ The intent of the cifs module is to provide an advanced
-+ network file system client for mounting to CIFS compliant servers,
-+ including support for dfs (hierarchical name space), secure per-user
-+ session establishment, safe distributed caching (oplock), optional
-+ packet signing, Unicode and other internationalization improvements.
-+ If you need to mount to Samba or Windows from this machine, say Y.
-+
-+config CIFS_STATS
-+ bool "CIFS statistics"
-+ depends on CIFS
-+ help
-+ Enabling this option will cause statistics for each server share
-+ mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
-+
-+config CIFS_STATS2
-+ bool "Extended statistics"
-+ depends on CIFS_STATS
-+ help
-+ Enabling this option will allow more detailed statistics on SMB
-+ request timing to be displayed in /proc/fs/cifs/DebugData and also
-+ allow optional logging of slow responses to dmesg (depending on the
-+ value of /proc/fs/cifs/cifsFYI, see fs/cifs/README for more details).
-+ These additional statistics may have a minor effect on performance
-+ and memory utilization.
-+
-+ Unless you are a developer or are doing network performance analysis
-+ or tuning, say N.
-+
-+config CIFS_WEAK_PW_HASH
-+ bool "Support legacy servers which use weaker LANMAN security"
-+ depends on CIFS
-+ help
-+ Modern CIFS servers including Samba and most Windows versions
-+ (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
-+ security mechanisms. These hash the password more securely
-+ than the mechanisms used in the older LANMAN version of the
-+ SMB protocol needed to establish sessions with old SMB servers.
-+
-+ Enabling this option allows the cifs module to mount to older
-+ LANMAN based servers such as OS/2 and Windows 95, but such
-+ mounts may be less secure than mounts using NTLM or more recent
-+ security mechanisms if you are on a public network. Unless you
-+ have a need to access old SMB servers (and are on a private
-+ network) you probably want to say N. Even if this support
-+ is enabled in the kernel build, they will not be used
-+ automatically. At runtime LANMAN mounts are disabled but
-+ can be set to required (or optional) either in
-+ /proc/fs/cifs (see fs/cifs/README for more detail) or via an
-+ option on the mount command. This support is disabled by
-+ default in order to reduce the possibility of a downgrade
-+ attack.
-+
-+ If unsure, say N.
-+
-+config CIFS_XATTR
-+ bool "CIFS extended attributes"
-+ depends on CIFS
-+ help
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ for details). CIFS maps the name of
-+ extended attributes beginning with the user namespace prefix
-+ to SMB/CIFS EAs. EAs are stored on Windows servers without the
-+ user namespace prefix, but their names are seen by Linux cifs clients
-+ prefaced by the user namespace prefix. The system namespace
-+ (used by some filesystems to store ACLs) is not supported at
-+ this time.
-+
-+ If unsure, say N.
-+
-+config CIFS_POSIX
-+ bool "CIFS POSIX Extensions"
-+ depends on CIFS_XATTR
-+ help
-+ Enabling this option will cause the cifs client to attempt to
-+ negotiate a newer dialect with servers, such as Samba 3.0.5
-+ or later, that optionally can handle more POSIX like (rather
-+ than Windows like) file behavior. It also enables
-+ support for POSIX ACLs (getfacl and setfacl) to servers
-+ (such as Samba 3.10 and later) which can negotiate
-+ CIFS POSIX ACL support. If unsure, say N.
-+
-+config CIFS_DEBUG2
-+ bool "Enable additional CIFS debugging routines"
-+ depends on CIFS
-+ help
-+ Enabling this option adds a few more debugging routines
-+ to the cifs code which slightly increases the size of
-+ the cifs module and can cause additional logging of debug
-+ messages in some error paths, slowing performance. This
-+ option can be turned off unless you are debugging
-+ cifs problems. If unsure, say N.
-+
-+config CIFS_EXPERIMENTAL
-+ bool "CIFS Experimental Features (EXPERIMENTAL)"
-+ depends on CIFS && EXPERIMENTAL
-+ help
-+ Enables cifs features under testing. These features are
-+ experimental and currently include DFS support and directory
-+ change notification ie fcntl(F_DNOTIFY), as well as the upcall
-+ mechanism which will be used for Kerberos session negotiation
-+ and uid remapping. Some of these features also may depend on
-+ setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental
-+ (which is disabled by default). See the file fs/cifs/README
-+ for more details. If unsure, say N.
-+
-+config CIFS_UPCALL
-+ bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
-+ depends on CIFS_EXPERIMENTAL
-+ depends on KEYS
-+ help
-+ Enables an upcall mechanism for CIFS which will be used to contact
-+ userspace helper utilities to provide SPNEGO packaged Kerberos
-+ tickets which are needed to mount to certain secure servers
-+ (for which more secure Kerberos authentication is required). If
-+ unsure, say N.
-+
-+config NCP_FS
-+ tristate "NCP file system support (to mount NetWare volumes)"
-+ depends on IPX!=n || INET
-+ help
-+ NCP (NetWare Core Protocol) is a protocol that runs over IPX and is
-+ used by Novell NetWare clients to talk to file servers. It is to
-+ IPX what NFS is to TCP/IP, if that helps. Saying Y here allows you
-+ to mount NetWare file server volumes and to access them just like
-+ any other Unix directory. For details, please read the file
-+ in the kernel source and
-+ the IPX-HOWTO from .
-+
-+ You do not have to say Y here if you want your Linux box to act as a
-+ file *server* for Novell NetWare clients.
-+
-+ General information about how to connect Linux, Windows machines and
-+ Macs is on the WWW at .
-+
-+ To compile this as a module, choose M here: the module will be called
-+ ncpfs. Say N unless you are connected to a Novell network.
-+
-+source "fs/ncpfs/Kconfig"
-+
-+config CODA_FS
-+ tristate "Coda file system support (advanced network fs)"
-+ depends on INET
-+ help
-+ Coda is an advanced network file system, similar to NFS in that it
-+ enables you to mount file systems of a remote server and access them
-+ with regular Unix commands as if they were sitting on your hard
-+ disk. Coda has several advantages over NFS: support for
-+ disconnected operation (e.g. for laptops), read/write server
-+ replication, security model for authentication and encryption,
-+ persistent client caches and write back caching.
-+
-+ If you say Y here, your Linux box will be able to act as a Coda
-+ *client*. You will need user level code as well, both for the
-+ client and server. Servers are currently user level, i.e. they need
-+ no kernel support. Please read
-+ and check out the Coda
-+ home page .
-+
-+ To compile the coda client support as a module, choose M here: the
-+ module will be called coda.
-+
-+config CODA_FS_OLD_API
-+ bool "Use 96-bit Coda file identifiers"
-+ depends on CODA_FS
-+ help
-+ A new kernel-userspace API had to be introduced for Coda v6.0
-+ to support larger 128-bit file identifiers as needed by the
-+ new realms implementation.
-+
-+ However this new API is not backward compatible with older
-+ clients. If you really need to run the old Coda userspace
-+ cache manager then say Y.
-+
-+ For most cases you probably want to say N.
-+
-+config AFS_FS
-+ tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
-+ depends on INET && EXPERIMENTAL
-+ select AF_RXRPC
-+ help
-+ If you say Y here, you will get an experimental Andrew File System
-+ driver. It currently only supports unsecured read-only AFS access.
-+
-+ See for more information.
-+
-+ If unsure, say N.
-+
-+config AFS_DEBUG
-+ bool "AFS dynamic debugging"
-+ depends on AFS_FS
-+ help
-+ Say Y here to make runtime controllable debugging messages appear.
-+
-+ See for more information.
-+
-+ If unsure, say N.
-+
-+config 9P_FS
-+ tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
-+ depends on INET && NET_9P && EXPERIMENTAL
-+ help
-+ If you say Y here, you will get experimental support for
-+ Plan 9 resource sharing via the 9P2000 protocol.
-+
-+ See for more information.
-+
-+ If unsure, say N.
-+
-+endif # NETWORK_FILESYSTEMS
-+
-+if BLOCK
-+menu "Partition Types"
-+
-+source "fs/partitions/Kconfig"
-+
-+endmenu
-+endif
-+
-+source "fs/nls/Kconfig"
-+source "fs/dlm/Kconfig"
-+
-+endmenu
-+
---- linux-2.6.24.7.old/fs/fs-writeback.c 2008-05-07 01:22:34.000000000 +0200
-+++ linux-2.6.24.7/fs/fs-writeback.c 2009-04-12 18:13:57.000000000 +0200
-@@ -386,8 +386,6 @@
- * WB_SYNC_HOLD is a hack for sys_sync(): reattach the inode to sb->s_dirty so
- * that it can be located for waiting on in __writeback_single_inode().
- *
-- * Called under inode_lock.
-- *
- * If `bdi' is non-zero then we're being asked to writeback a specific queue.
- * This function assumes that the blockdev superblock's inodes are backed by
- * a variety of queues, so all inodes are searched. For other superblocks,
-@@ -403,11 +401,12 @@
- * on the writer throttling path, and we get decent balancing between many
- * throttled threads: we don't want them all piling up on inode_sync_wait.
- */
--static void
--sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
-+void generic_sync_sb_inodes(struct super_block *sb,
-+ struct writeback_control *wbc)
- {
- const unsigned long start = jiffies; /* livelock avoidance */
-
-+ spin_lock(&inode_lock);
- if (!wbc->for_kupdate || list_empty(&sb->s_io))
- queue_io(sb, wbc->older_than_this);
-
-@@ -482,8 +481,16 @@
- if (wbc->nr_to_write <= 0)
- break;
- }
-+ spin_unlock(&inode_lock);
- return; /* Leave any unwritten inodes on s_io */
- }
-+EXPORT_SYMBOL_GPL(generic_sync_sb_inodes);
-+
-+static void sync_sb_inodes(struct super_block *sb,
-+ struct writeback_control *wbc)
-+{
-+ generic_sync_sb_inodes(sb, wbc);
-+}
-
- /*
- * Start writeback of dirty pagecache data against all unlocked inodes.
-@@ -524,11 +531,8 @@
- * be unmounted by the time it is released.
- */
- if (down_read_trylock(&sb->s_umount)) {
-- if (sb->s_root) {
-- spin_lock(&inode_lock);
-+ if (sb->s_root)
- sync_sb_inodes(sb, wbc);
-- spin_unlock(&inode_lock);
-- }
- up_read(&sb->s_umount);
- }
- spin_lock(&sb_lock);
-@@ -566,9 +570,7 @@
- (inodes_stat.nr_inodes - inodes_stat.nr_unused) +
- nr_dirty + nr_unstable;
- wbc.nr_to_write += wbc.nr_to_write / 2; /* Bit more for luck */
-- spin_lock(&inode_lock);
- sync_sb_inodes(sb, &wbc);
-- spin_unlock(&inode_lock);
- }
-
- /*
---- linux-2.6.24.7.old/fs/ubifs/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/Kconfig 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,71 @@
-+config UBIFS_FS
-+ tristate "UBIFS file system support"
-+ select CRC16
-+ select CRC32
-+ depends on MTD_UBI
-+ help
-+ UBIFS is a file system for flash devices which works on top of UBI.
-+
-+config UBIFS_FS_XATTR
-+ bool "Extended attributes support"
-+ depends on UBIFS_FS
-+ help
-+ This option enables support of extended attributes.
-+
-+config UBIFS_FS_ADVANCED_COMPR
-+ bool "Advanced compression options"
-+ depends on UBIFS_FS
-+ help
-+ This option allows to explicitly choose which compressions, if any,
-+ are enabled in UBIFS. Removing compressors means inbility to read
-+ existing file systems.
-+
-+ If unsure, say 'N'.
-+
-+config UBIFS_FS_LZO
-+ bool "LZO compression support" if UBIFS_FS_ADVANCED_COMPR
-+ select CRYPTO
-+ select CRYPTO_LZO
-+ depends on UBIFS_FS
-+ default y
-+ help
-+ LZO compressor is generally faster then zlib but compresses worse.
-+ Say 'Y' if unsure.
-+
-+config UBIFS_FS_ZLIB
-+ bool "ZLIB compression support" if UBIFS_FS_ADVANCED_COMPR
-+ select CRYPTO
-+ select CRYPTO_DEFLATE
-+ depends on UBIFS_FS
-+ default y
-+ help
-+ Zlib copresses better then LZO but it is slower. Say 'Y' if unsure.
-+
-+# Debugging-related stuff
-+config UBIFS_FS_DEBUG
-+ bool "Enable debugging"
-+ depends on UBIFS_FS
-+ select DEBUG_FS
-+ select KALLSYMS_ALL
-+ help
-+ This option enables UBIFS debugging.
-+
-+config UBIFS_FS_DEBUG_MSG_LVL
-+ int "Default message level (0 = no extra messages, 3 = lots)"
-+ depends on UBIFS_FS_DEBUG
-+ default "0"
-+ help
-+ This controls the amount of debugging messages produced by UBIFS.
-+ If reporting bugs, please try to have available a full dump of the
-+ messages at level 1 while the misbehaviour was occurring. Level 2
-+ may become necessary if level 1 messages were not enough to find the
-+ bug. Generally Level 3 should be avoided.
-+
-+config UBIFS_FS_DEBUG_CHKS
-+ bool "Enable extra checks"
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ If extra checks are enabled UBIFS will check the consistency of its
-+ internal data structures during operation. However, UBIFS performance
-+ is dramatically slower when this option is selected especially if the
-+ file system is large.
---- linux-2.6.24.7.old/fs/ubifs/Kconfig.debug 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/Kconfig.debug 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,173 @@
-+# UBIFS debugging configuration options, part of fs/ubifs/Kconfig
-+
-+config UBIFS_FS_DEBUG
-+ bool "Enable debugging"
-+ default n
-+ depends on UBIFS_FS
-+ select DEBUG_FS
-+ select KALLSYMS_ALL
-+ help
-+ This option enables UBIFS debugging.
-+
-+menu "Debugging messages"
-+ depends on UBIFS_FS_DEBUG
-+
-+config UBIFS_FS_DEBUG_MSG_GEN
-+ bool "General messages"
-+ default n
-+ help
-+ This option enables general debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_JRN
-+ bool "Journal messages"
-+ default n
-+ help
-+ This option enables detailed journal debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_CMT
-+ bool "Commit messages"
-+ default n
-+ help
-+ This option enables detailed journal commit debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_BUDG
-+ bool "Budgeting messages"
-+ default n
-+ help
-+ This option enables detailed budgeting debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_LOG
-+ bool "Log messages"
-+ default n
-+ help
-+ This option enables detailed journal log debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_TNC
-+ bool "Tree Node Cache (TNC) messages"
-+ default n
-+ help
-+ This option enables detailed TNC debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_LP
-+ bool "LEB properties (lprops) messages"
-+ default n
-+ help
-+ This option enables detailed lprops debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_FIND
-+ bool "LEB search messages"
-+ default n
-+ help
-+ This option enables detailed LEB search debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_MNT
-+ bool "Mount messages"
-+ default n
-+ help
-+ This option enables detailed mount debugging messages, including
-+ recovery messages.
-+
-+config UBIFS_FS_DEBUG_MSG_IO
-+ bool "Input/output messages"
-+ default n
-+ help
-+ This option enables detailed I/O debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_GC
-+ bool "Garbage collection messages"
-+ default n
-+ help
-+ This option enables detailed garbage collection debugging messages.
-+
-+config UBIFS_FS_DEBUG_MSG_SCAN
-+ bool "Scan messages"
-+ default n
-+ help
-+ This option enables detailed scan debugging messages.
-+
-+endmenu
-+
-+menu "Extra self-checks"
-+ depends on UBIFS_FS_DEBUG
-+
-+config UBIFS_FS_DEBUG_CHK_MEMPRESS
-+ bool "Create memory pressure"
-+ default n
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ This option causes kernel memory pressure in order to make TNC shrinker
-+ run.
-+
-+config UBIFS_FS_DEBUG_CHK_LPROPS
-+ bool "Check LEB properties (lprops)"
-+ default n
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ This option enables a function which runs during journal commit and
-+ checks that the dirty and free space is correct for every LEB. Note,
-+ this option makes UBIFS scan whole media before each commit which is
-+ very slow.
-+
-+config UBIFS_FS_DEBUG_CHK_TNC
-+ bool "Check Tree Node Cache (TNC)"
-+ default n
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ This option enables a function which runs after every
-+ TNC insert / delete and checks that the TNC nodes are correct.
-+
-+config UBIFS_FS_DEBUG_CHK_ORPH
-+ bool "Check orphan area"
-+ default n
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ This option enables a function which runs during journal commit and
-+ checks that the orphan area is correct.
-+
-+config UBIFS_FS_DEBUG_CHK_IDX_SZ
-+ bool "Check indexing tree size"
-+ default n
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ This option enables checking of the znode size accounting variables.
-+
-+config UBIFS_FS_DEBUG_CHK_OLD_IDX
-+ bool "Check old indexing tree"
-+ default n
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ This option enables checking of the old indexing tree which must be
-+ intact to allow recovery in the event of an unclean unmount.
-+
-+config UBIFS_FS_DEBUG_CHK_OTHER
-+ bool "Other checks"
-+ default n
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ This option enables different checks which are light-weight and do not
-+ affect file-system performance too much.
-+
-+endmenu
-+
-+config UBIFS_FS_DEBUG_FORCE_IN_THE_GAPS
-+ bool "Force in-the-gaps commit method"
-+ default n
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ This option makes UBIFS use the in-the-gap commit method much more
-+ often than it is normally used (normally it is used only as fall-back
-+ method when there is no space to do the "normal" commit method). It
-+ is useful to run tests with this option enabled from time to time
-+ because it may reveal UBIFS bugs which would otherwise be really
-+ difficult to hit.
-+
-+config UBIFS_FS_DEBUG_TEST_RCVRY
-+ bool "Simulate random device removal (recovery testing)"
-+ default n
-+ depends on UBIFS_FS_DEBUG
-+ help
-+ This option provides the ability to test recovery from unclean
-+ unmounts. It causes UBIFS to simulate device removal. At a some
-+ random point UBIFS will switch to "failure mode" after which all I/O
-+ operations will fail. UBIFS can then be unmounted and mounted again
-+ at which point "failure mode" is switched off and recovery ensues.
---- linux-2.6.24.7.old/fs/ubifs/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/Makefile 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,9 @@
-+obj-$(CONFIG_UBIFS_FS) += ubifs.o
-+
-+ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o
-+ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
-+ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
-+ubifs-y += recovery.o ioctl.o compat.o lpt_commit.o tnc_misc.o
-+
-+ubifs-$(CONFIG_UBIFS_FS_DEBUG) += debug.o
-+ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
---- linux-2.6.24.7.old/fs/ubifs/budget.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/budget.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,871 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file implements the budgeting unit which is responsible for UBIFS space
-+ * management.
-+ *
-+ * Factors such as compression, wasted space at the ends of LEBs, space in other
-+ * journal heads, the effect of updates on the index, and so on, make it
-+ * impossible to accurately predict the amount of space needed. Consequently
-+ * approximations are used.
-+ */
-+
-+#include "ubifs.h"
-+#include
-+#include
-+
-+/*
-+ * When pessimistic budget calculations say that there is no enough space,
-+ * UBIFS starts writing back dirty inodes and pages, doing garbage collection,
-+ * or committing. The below constants define maximum number of times UBIFS
-+ * repeats the operations.
-+ */
-+#define MAX_SHRINK_RETRIES 8
-+#define MAX_GC_RETRIES 4
-+#define MAX_CMT_RETRIES 2
-+#define MAX_NOSPC_RETRIES 1
-+
-+/*
-+ * The below constant defines amount of dirty pages which should be written
-+ * back at when trying to shrink the liability.
-+ */
-+#define NR_TO_WRITE 16
-+
-+/**
-+ * struct retries_info - information about re-tries while making free space.
-+ * @prev_liability: previous liability
-+ * @shrink_cnt: how many times the liability was shrinked
-+ * @shrink_retries: count of liability shrink re-tries (increased when
-+ * liability does not shrink)
-+ * @try_gc: GC should be tried first
-+ * @gc_retries: how many times GC was run
-+ * @cmt_retries: how many times commit has been done
-+ * @nospc_retries: how many times GC returned %-ENOSPC
-+ *
-+ * Since we consider budgeting to be the fast-path, and this structure has to
-+ * be allocated on stack and zeroed out, we make it smaller using bit-fields.
-+ */
-+struct retries_info {
-+ long long prev_liability;
-+ unsigned int shrink_cnt;
-+ unsigned int shrink_retries:5;
-+ unsigned int try_gc:1;
-+ unsigned int gc_retries:4;
-+ unsigned int cmt_retries:3;
-+ unsigned int nospc_retries:1;
-+};
-+
-+/* TODO: remove compatibility stuff as late as possible */
-+#ifndef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE
-+/**
-+ * shrink_liability - write-back some dirty pages/inodes.
-+ * @c: UBIFS file-system description object
-+ * @nr_to_write: how many dirty pages to write-back
-+ *
-+ * This function shrinks UBIFS liability by means of writing back some amount
-+ * of dirty inodes and their pages. Returns the amount of pages which were
-+ * written back. The returned value does not include dirty inodes which were
-+ * synchronized.
-+ *
-+ * Note, this function synchronizes even VFS inodes which are locked
-+ * (@i_mutex) by the caller of the budgeting function, because write-back does
-+ * not touch @i_mutex.
-+ */
-+static int shrink_liability(struct ubifs_info *c, int nr_to_write)
-+{
-+ struct writeback_control wbc = {
-+ .sync_mode = WB_SYNC_NONE,
-+ .range_end = LLONG_MAX,
-+ .nr_to_write = nr_to_write,
-+ };
-+
-+ generic_sync_sb_inodes(c->vfs_sb, &wbc);
-+ dbg_budg("%ld pages were written back", nr_to_write - wbc.nr_to_write);
-+ return nr_to_write - wbc.nr_to_write;
-+}
-+
-+
-+/**
-+ * run_gc - run garbage collector.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function runs garbage collector to make some more free space. Returns
-+ * zero if a free LEB has been produced, %-EAGAIN if commit is required, and a
-+ * negative error code in case of failure.
-+ */
-+static int run_gc(struct ubifs_info *c)
-+{
-+ int err, lnum;
-+
-+ /* Make some free space by garbage-collecting dirty space */
-+ down_read(&c->commit_sem);
-+ lnum = ubifs_garbage_collect(c, 1);
-+ up_read(&c->commit_sem);
-+ if (lnum < 0)
-+ return lnum;
-+
-+ /* GC freed one LEB, return it to lprops */
-+ dbg_budg("GC freed LEB %d", lnum);
-+ err = ubifs_return_leb(c, lnum);
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+/**
-+ * make_free_space - make more free space on the file-system.
-+ * @c: UBIFS file-system description object
-+ * @ri: information about previous invocations of this function
-+ *
-+ * This function is called when an operation cannot be budgeted because there
-+ * is supposedly no free space. But in most cases there is some free space:
-+ * o budgeting is pessimistic, so it always budgets more then it is actually
-+ * needed, so shrinking the liability is one way to make free space - the
-+ * cached data will take less space then it was budgeted for;
-+ * o GC may turn some dark space into free space (budgeting treats dark space
-+ * as not available);
-+ * o commit may free some LEB, i.e., turn freeable LEBs into free LEBs.
-+ *
-+ * So this function tries to do the above. Returns %-EAGAIN if some free space
-+ * was presumably made and the caller has to re-try budgeting the operation.
-+ * Returns %-ENOSPC if it couldn't do more free space, and other negative error
-+ * codes on failures.
-+ */
-+static int make_free_space(struct ubifs_info *c, struct retries_info *ri)
-+{
-+ int err;
-+
-+ /*
-+ * If we have some dirty pages and inodes (liability), try to write
-+ * them back unless this was tried too many times without effect
-+ * already.
-+ */
-+ if (ri->shrink_retries < MAX_SHRINK_RETRIES && !ri->try_gc) {
-+ long long liability;
-+
-+ spin_lock(&c->space_lock);
-+ liability = c->budg_idx_growth + c->budg_data_growth +
-+ c->budg_dd_growth;
-+ spin_unlock(&c->space_lock);
-+
-+ if (ri->prev_liability >= liability) {
-+ /* Liability does not shrink, next time try GC then */
-+ ri->shrink_retries += 1;
-+ if (ri->gc_retries < MAX_GC_RETRIES)
-+ ri->try_gc = 1;
-+ dbg_budg("liability did not shrink: retries %d of %d",
-+ ri->shrink_retries, MAX_SHRINK_RETRIES);
-+ }
-+
-+ dbg_budg("force write-back (count %d)", ri->shrink_cnt);
-+ shrink_liability(c, NR_TO_WRITE + ri->shrink_cnt);
-+
-+ ri->prev_liability = liability;
-+ ri->shrink_cnt += 1;
-+ return -EAGAIN;
-+ }
-+
-+ /*
-+ * Try to run garbage collector unless it was already tried too many
-+ * times.
-+ */
-+ if (ri->gc_retries < MAX_GC_RETRIES) {
-+ ri->gc_retries += 1;
-+ dbg_budg("run GC, retries %d of %d",
-+ ri->gc_retries, MAX_GC_RETRIES);
-+
-+ ri->try_gc = 0;
-+ err = run_gc(c);
-+ if (!err)
-+ return -EAGAIN;
-+
-+ if (err == -EAGAIN) {
-+ dbg_budg("GC asked to commit");
-+ err = ubifs_run_commit(c);
-+ if (err)
-+ return err;
-+ return -EAGAIN;
-+ }
-+
-+ if (err != -ENOSPC)
-+ return err;
-+
-+ /*
-+ * GC could not make any progress. If this is the first time,
-+ * then it makes sense to try to commit, because it might make
-+ * some dirty space.
-+ */
-+ dbg_budg("GC returned -ENOSPC, retries %d",
-+ ri->nospc_retries);
-+ if (ri->nospc_retries >= MAX_NOSPC_RETRIES)
-+ return err;
-+ ri->nospc_retries += 1;
-+ }
-+
-+ /* Neither GC nor write-back helped, try to commit */
-+ if (ri->cmt_retries < MAX_CMT_RETRIES) {
-+ ri->cmt_retries += 1;
-+ dbg_budg("run commit, retries %d of %d",
-+ ri->cmt_retries, MAX_CMT_RETRIES);
-+ err = ubifs_run_commit(c);
-+ if (err)
-+ return err;
-+ return -EAGAIN;
-+ }
-+
-+ return -ENOSPC;
-+}
-+#endif /* UBIFS_COMPAT_USE_OLD_PREPARE_WRITE */
-+
-+/**
-+ * ubifs_calc_min_idx_lebs - calculate amount of eraseblocks for the index.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function calculates and returns the number of eraseblocks which should
-+ * be kept for index usage.
-+ */
-+int ubifs_calc_min_idx_lebs(struct ubifs_info *c)
-+{
-+ int ret;
-+ uint64_t idx_size;
-+
-+ idx_size = c->old_idx_sz + c->budg_idx_growth + c->budg_uncommitted_idx;
-+
-+ /* And make sure we have twice the index size of space reserved */
-+ idx_size <<= 1;
-+
-+ /*
-+ * We do not maintain 'old_idx_size' as 'old_idx_lebs'/'old_idx_bytes'
-+ * pair, nor similarly the two variables for the new index size, so we
-+ * have to do this costly 64-bit division on fast-path.
-+ */
-+ if (do_div(idx_size, c->leb_size - c->max_idx_node_sz))
-+ ret = idx_size + 1;
-+ else
-+ ret = idx_size;
-+ /*
-+ * The index head is not available for the in-the-gaps method, so add an
-+ * extra LEB to compensate.
-+ */
-+ ret += 1;
-+ /*
-+ * At present the index needs at least 2 LEBs: one for the index head
-+ * and one for in-the-gaps method (which currently does not cater for
-+ * the index head and so excludes it from consideration).
-+ */
-+ if (ret < 2)
-+ ret = 2;
-+ return ret;
-+}
-+
-+/**
-+ * ubifs_calc_available - calculate available FS space.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function calculates and returns amount of FS space available for use.
-+ */
-+long long ubifs_calc_available(const struct ubifs_info *c)
-+{
-+ long long available, subtract_lebs;
-+
-+ /*
-+ * Force the amount available to the total size reported if the used
-+ * space is zero.
-+ */
-+ if (c->lst.total_used <= UBIFS_INO_NODE_SZ &&
-+ c->budg_data_growth + c->budg_dd_growth == 0) {
-+ /* Do the same calculation as for c->block_cnt */
-+ available = c->main_lebs - 2;
-+ available *= c->leb_size - c->dark_wm;
-+ return available;
-+ }
-+
-+ available = c->main_bytes - c->lst.total_used;
-+
-+ /*
-+ * Now 'available' contains theoretically available flash space
-+ * assuming there is no index, so we have to subtract the space which
-+ * is reserved for the index.
-+ */
-+ subtract_lebs = c->min_idx_lebs;
-+
-+ /* Take into account that GC reserves one LEB for its own needs */
-+ subtract_lebs += 1;
-+
-+ /*
-+ * The GC journal head LEB is not really accessible. And since
-+ * different write types go to different heads, we may count only on
-+ * one head's space.
-+ */
-+ subtract_lebs += c->jhead_cnt - 1;
-+
-+ /* We also reserve one LEB for deletions, which bypass budgeting */
-+ subtract_lebs += 1;
-+
-+ available -= subtract_lebs * c->leb_size;
-+
-+ /* Subtract the dead space which is not available for use */
-+ available -= c->lst.total_dead;
-+
-+ /*
-+ * Subtract dark space, which might or might not be usable - it depends
-+ * on the data which we have on the media and which will be written. If
-+ * this is a lot of uncompressed or not-compressible data, the dark
-+ * space cannot be used.
-+ */
-+ available -= c->lst.total_dark;
-+
-+ /*
-+ * However, there is more dark space. The index may be bigger than
-+ * min_idx_lebs. Those extra LEBs are assumed to be available, but
-+ * their dark space is not included in total_dark, so it is subtracted
-+ * here.
-+ */
-+ if (c->lst.idx_lebs > c->min_idx_lebs) {
-+ subtract_lebs = c->lst.idx_lebs - c->min_idx_lebs;
-+ available -= subtract_lebs * c->dark_wm;
-+ }
-+
-+ return available;
-+}
-+
-+/**
-+ * rp_can_write - check whether the user is allowed to write.
-+ * @c: UBIFS file-system description object
-+ * @avail: available space on FS
-+ *
-+ * UBIFS has so-called "reserved pool" which is flash space reserved
-+ * for the superuser and for uses whose UID/GID is recorded in UBIFS superblock.
-+ * This function checks whether current user is allowed to write
-+ * to the file-system - it returns %1 if there is plenty of space or the user
-+ * is eligible to use the reserved pool and %0 otherwise.
-+ */
-+static int rp_can_write(struct ubifs_info *c, long long avail)
-+{
-+ if (avail > c->rp_size || current->fsuid == c->rp_uid ||
-+ capable(CAP_SYS_RESOURCE) ||
-+ (c->rp_gid != 0 && in_group_p(c->rp_gid)))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/**
-+ * do_budget_space - reserve flash space for index and data growth.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function makes sure UBIFS has enough free eraseblocks for index growth
-+ * and data.
-+ *
-+ * When budgeting index space, UBIFS reserves twice as more LEBs as the index
-+ * would take if it was consolidated and written to the flash. This guarantees
-+ * that the "in-the-gaps" commit method always succeeds and UBIFS will always
-+ * be able to commit dirty index. So this function basically adds amount of
-+ * budgeted index space to the size of the current index, multiplies this by 2,
-+ * and makes sure this does not exceed the amount of free eraseblocks.
-+ *
-+ * Notes about @c->min_idx_lebs and @c->lst.idx_lebs variables:
-+ * o @c->lst.idx_lebs is the number of LEBs the index currently uses. It might
-+ * be large, because UBIFS does not do any index consolidation as long as
-+ * there is free space. IOW, the index may take a lot of LEBs, but the LEBs
-+ * will contain a lot of dirt.
-+ * o @c->min_idx_lebs is the the index presumably takes. IOW, the index may be
-+ * consolidated to take up to @c->min_idx_lebs LEBs.
-+ *
-+ * This function returns zero in case of success, and %-ENOSPC in case of
-+ * failure.
-+ */
-+static int do_budget_space(struct ubifs_info *c)
-+{
-+ long long outstanding, available;
-+ int lebs, rsvd_idx_lebs, min_idx_lebs;
-+
-+ /* First budget index space */
-+ min_idx_lebs = ubifs_calc_min_idx_lebs(c);
-+
-+ /* Now 'min_idx_lebs' contains number of LEBs to reserve */
-+ if (min_idx_lebs > c->lst.idx_lebs)
-+ rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
-+ else
-+ rsvd_idx_lebs = 0;
-+
-+ /*
-+ * The number of LEBs that are available to be used by the index is:
-+ *
-+ * @c->lst.empty_lebs + @c->freeable_cnt + @c->idx_gc_cnt -
-+ * @c->lst.taken_empty_lebs
-+ *
-+ * @empty_lebs are available because they are empty. @freeable_cnt are
-+ * available because they contain only free and dirty space and the
-+ * index allocation always occurs after wbufs are synch'ed.
-+ * @idx_gc_cnt are available because they are index LEBs that have been
-+ * garbage collected (including trivial GC) and are awaiting the commit
-+ * before they can be unmapped - note that the in-the-gaps method will
-+ * grab these if it needs them. @taken_empty_lebs are empty_lebs that
-+ * have already been allocated for some purpose (also includes those
-+ * LEBs on the @idx_gc list).
-+ *
-+ * Note, @taken_empty_lebs may temporarily be higher by one because of
-+ * the way we serialize LEB allocations and budgeting. See a comment in
-+ * 'ubifs_find_free_space()'.
-+ */
-+ lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
-+ c->lst.taken_empty_lebs;
-+ if (unlikely(rsvd_idx_lebs > lebs)) {
-+ dbg_budg("out of indexing space: min_idx_lebs %d (old %d), "
-+ "rsvd_idx_lebs %d", min_idx_lebs, c->min_idx_lebs,
-+ rsvd_idx_lebs);
-+ return -ENOSPC;
-+ }
-+
-+ available = ubifs_calc_available(c);
-+ outstanding = c->budg_data_growth + c->budg_dd_growth;
-+
-+ if (unlikely(available < outstanding)) {
-+ dbg_budg("out of data space: available %lld, outstanding %lld",
-+ available, outstanding);
-+ return -ENOSPC;
-+ }
-+
-+ if (!rp_can_write(c, available - outstanding))
-+ return -ENOSPC;
-+
-+ c->min_idx_lebs = min_idx_lebs;
-+ return 0;
-+}
-+
-+/**
-+ * calc_idx_growth - calculate approximate index growth from budgeting request.
-+ * @c: UBIFS file-system description object
-+ * @req: budgeting request
-+ *
-+ * For now we assume each new node adds one znode. But this is rather poor
-+ * approximation, though.
-+ */
-+static int calc_idx_growth(const struct ubifs_info *c,
-+ const struct ubifs_budget_req *req)
-+{
-+ int znodes;
-+
-+ znodes = req->new_ino + (req->new_page << UBIFS_BLOCKS_PER_PAGE_SHIFT) +
-+ req->new_dent;
-+ return znodes * c->max_idx_node_sz;
-+}
-+
-+/**
-+ * calc_data_growth - calculate approximate amount of new data from budgeting
-+ * request.
-+ * @c: UBIFS file-system description object
-+ * @req: budgeting request
-+ */
-+static int calc_data_growth(const struct ubifs_info *c,
-+ const struct ubifs_budget_req *req)
-+{
-+ int data_growth;
-+
-+ data_growth = req->new_ino ? c->inode_budget : 0;
-+ if (req->new_page)
-+ data_growth += c->page_budget;
-+ if (req->new_dent)
-+ data_growth += c->dent_budget;
-+ data_growth += req->new_ino_d;
-+
-+ return data_growth;
-+}
-+
-+/**
-+ * calc_dd_growth - calculate approximate amount of data which makes other data
-+ * dirty from budgeting request.
-+ * @c: UBIFS file-system description object
-+ * @req: budgeting request
-+ */
-+static int calc_dd_growth(const struct ubifs_info *c,
-+ const struct ubifs_budget_req *req)
-+{
-+ int dd_growth;
-+
-+ dd_growth = req->dirtied_page ? c->page_budget : 0;
-+
-+ if (req->dirtied_ino)
-+ dd_growth += c->inode_budget << (req->dirtied_ino - 1);
-+ if (req->mod_dent)
-+ dd_growth += c->dent_budget;
-+ dd_growth += req->dirtied_ino_d;
-+
-+ return dd_growth;
-+}
-+
-+/**
-+ * ubifs_budget_space - ensure there is enough space to complete an operation.
-+ * @c: UBIFS file-system description object
-+ * @req: budget request
-+ *
-+ * This function allocates budget for an operation. It uses pessimistic
-+ * approximation of how much flash space the operation needs. The goal of this
-+ * function is to make sure UBIFS always has flash space to flush all dirty
-+ * pages, dirty inodes, and dirty znodes (liability). This function may force
-+ * commit, garbage-collection or write-back. Returns zero in case of success,
-+ * %-ENOSPC if there is no free space and other negative error codes in case of
-+ * failures.
-+ */
-+int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req)
-+{
-+ int uninitialized_var(cmt_retries), uninitialized_var(wb_retries);
-+ int err, idx_growth, data_growth, dd_growth;
-+ struct retries_info ri;
-+
-+ data_growth = calc_data_growth(c, req);
-+ dd_growth = calc_dd_growth(c, req);
-+ if (!data_growth && !dd_growth)
-+ return 0;
-+ idx_growth = calc_idx_growth(c, req);
-+ memset(&ri, 0, sizeof(struct retries_info));
-+
-+again:
-+ spin_lock(&c->space_lock);
-+ ubifs_assert(c->budg_idx_growth >= 0);
-+ ubifs_assert(c->budg_data_growth >= 0);
-+ ubifs_assert(c->budg_dd_growth >= 0);
-+
-+ c->budg_idx_growth += idx_growth;
-+ c->budg_data_growth += data_growth;
-+ c->budg_dd_growth += dd_growth;
-+
-+ err = do_budget_space(c);
-+ if (unlikely(err)) {
-+ /* Restore the old values */
-+ c->budg_idx_growth -= idx_growth;
-+ c->budg_data_growth -= data_growth;
-+ c->budg_dd_growth -= dd_growth;
-+ spin_unlock(&c->space_lock);
-+
-+ goto make_space;
-+ }
-+
-+ req->idx_growth = idx_growth;
-+ req->data_growth = data_growth;
-+ req->dd_growth = dd_growth;
-+ spin_unlock(&c->space_lock);
-+
-+ return 0;
-+
-+make_space:
-+/* TODO: remove compatibility stuff as late as possible */
-+#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE
-+ err = ubifs_make_free_space(c, &ri, req->locked_pg);
-+#else
-+ err = make_free_space(c, &ri);
-+#endif
-+
-+ if (err == -EAGAIN) {
-+ dbg_budg("try again");
-+ cond_resched();
-+ goto again;
-+ } else if (err == -ENOSPC)
-+ dbg_budg("FS is full, -ENOSPC");
-+ else
-+ ubifs_err("cannot budget space, error %d", err);
-+
-+ return err;
-+}
-+
-+/**
-+ * ubifs_release_budget - release budgeted free space.
-+ * @c: UBIFS file-system description object
-+ * @req: budget request
-+ *
-+ * This function releases the space budgeted by 'ubifs_budget_space()'. Note,
-+ * since the index changes (which were budgeted for in @req->idx_growth) will
-+ * only be written to the media on commit, this function moves the index budget
-+ * from @c->budg_idx_growth to @c->budg_uncommitted_idx. The latter will be
-+ * zeroed by the commit operation.
-+ */
-+void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req)
-+{
-+ if (!req->data_growth && !req->dd_growth)
-+ return;
-+
-+ if (req->idx_growth == -1)
-+ req->idx_growth = calc_idx_growth(c, req);
-+
-+ spin_lock(&c->space_lock);
-+ c->budg_idx_growth -= req->idx_growth;
-+ c->budg_uncommitted_idx += req->idx_growth;
-+ c->budg_data_growth -= req->data_growth;
-+ c->budg_dd_growth -= req->dd_growth;
-+ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
-+
-+ ubifs_assert(c->budg_idx_growth >= 0);
-+ ubifs_assert(c->budg_data_growth >= 0);
-+ ubifs_assert(c->min_idx_lebs < c->main_lebs);
-+ spin_unlock(&c->space_lock);
-+}
-+
-+/**
-+ * ubifs_convert_page_budget - convert budget of a new page.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function converts budget which was allocated for a new page of data to
-+ * the budget of changing an existing page of data. The latter is not larger
-+ * then the former, so this function only does simple re-calculation and does
-+ * not involve any write-back.
-+ */
-+void ubifs_convert_page_budget(struct ubifs_info *c)
-+{
-+ spin_lock(&c->space_lock);
-+ /* Release the index growth reservation */
-+ c->budg_idx_growth -= c->max_idx_node_sz << UBIFS_BLOCKS_PER_PAGE_SHIFT;
-+ /* Release the data growth reservation */
-+ c->budg_data_growth -= c->page_budget;
-+ /* Increase the dirty data growth reservation instead */
-+ c->budg_dd_growth += c->page_budget;
-+ /* And re-calculate the indexing space reservation */
-+ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
-+ spin_unlock(&c->space_lock);
-+}
-+
-+/**
-+ * ubifs_budget_inode_op - budget an operation on inode.
-+ * @c: UBIFS file-system description object
-+ * @inode: VFS inode which will be made dirty by the operation
-+ * @req: budget request of the operation
-+ *
-+ * This function is called to get budget for an operation which changes an
-+ * inode. The inode may be in dirty or clean state. The former means there is
-+ * no need to allocate the budget as it has already been allocated before. The
-+ * latter means that the inode change budget has to be allocated.
-+ *
-+ * The caller has to pass the inode which is going to be changed. This function
-+ * acquires budget the for as described in @req plus the budget for changing
-+ * the inode dirty, if needed. Returns zero in case of success, %-ENOSPC if
-+ * there is no more flash space, and other negative error codes in case of
-+ * failure.
-+ *
-+ * Note, upon exit, this function leaves the inode locked, and the
-+ * 'ubifs_release_ino_dirty()' or 'ubifs_release_ino_clean()' function has to
-+ * be called to unlock it.
-+ */
-+int ubifs_budget_inode_op(struct ubifs_info *c, struct inode *inode,
-+ struct ubifs_budget_req *req)
-+{
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+ int err, old = req->dirtied_ino;
-+
-+ ubifs_assert(req->dirtied_ino <= 3);
-+ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 3);
-+
-+again:
-+ /*
-+ * If the inode is clean, it will be dirtied by this operation and we
-+ * have to budget for this.
-+ */
-+ req->dirtied_ino += !ui->dirty;
-+ if (req->dirtied_ino > old)
-+ req->dirtied_ino_d += ui->data_len;
-+
-+ /*
-+ * Note, if the budget request does not actually request anything
-+ * (i.e., @req contains only zeroes), 'ubifs_budget_space()' will
-+ * return almost straight away.
-+ */
-+ err = ubifs_budget_space(c, req);
-+ if (unlikely(err))
-+ return err;
-+
-+ mutex_lock(&ui->budg_mutex);
-+
-+ if (req->dirtied_ino != old + !ui->dirty) {
-+ /* The inode has probably been written back meanwhile */
-+ ubifs_release_budget(c, req);
-+ mutex_unlock(&ui->budg_mutex);
-+ req->dirtied_ino = old;
-+ req->dirtied_ino_d -= ui->data_len;
-+ goto again;
-+ }
-+
-+ UBIFS_DBG(ui->budgeted = 1);
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_release_ino_dirty - release budget of a "dirtying" operation.
-+ * @c: UBIFS file-system description object
-+ * @inode: VFS inode the operation worked on
-+ * @req: budget to release
-+ *
-+ * This function has to be called at the end of VFS operations which acquired
-+ * budget via 'ubifs_budget_inode_op()'. It assumes that the inode has been
-+ * marked as dirty and will be synchronized later by write-back, so it does not
-+ * release the budget of the inode.
-+ *
-+ * Note, this function also avoids releasing page budgets which are released
-+ * separately.
-+ */
-+void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode,
-+ struct ubifs_budget_req *req)
-+{
-+ ubifs_assert(req->dirtied_ino <= 4);
-+ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
-+ ubifs_assert(req->idx_growth >= 0);
-+ ubifs_assert(req->data_growth >= 0);
-+ ubifs_assert(req->dd_growth >= 0);
-+
-+ if (req->dirtied_ino) {
-+ req->dd_growth -= c->inode_budget;
-+ req->dd_growth -= req->dirtied_ino_d;
-+ }
-+
-+ if (req->dirtied_page) {
-+ req->dd_growth -= c->page_budget;
-+ ubifs_assert(req->new_page == 0);
-+ } else if (req->new_page) {
-+ req->idx_growth -=
-+ c->max_idx_node_sz << UBIFS_BLOCKS_PER_PAGE_SHIFT;
-+ req->data_growth -= c->page_budget;
-+ ubifs_assert(req->dirtied_page == 0);
-+ }
-+
-+ ubifs_assert(req->dd_growth >= 0);
-+ ubifs_release_budget(c, req);
-+ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
-+}
-+
-+/**
-+ * ubifs_cancel_ino_op - cancel budget of an operation on inode.
-+ * @c: UBIFS file-system description object
-+ * @inode: VFS inode the operation worked on
-+ * @req: budget to release
-+ *
-+ * This function has to be called if the operation failed and whole budget has
-+ * to be released, including the budget for inode which would had been
-+ * dirtied. It is important not to mark the inode dirty before calling this
-+ * function.
-+ */
-+void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
-+ struct ubifs_budget_req *req)
-+{
-+ ubifs_assert(req->dirtied_ino <= 4);
-+ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
-+ ubifs_assert(req->idx_growth >= 0);
-+ ubifs_assert(req->data_growth >= 0);
-+ ubifs_assert(req->dd_growth >= 0);
-+
-+ ubifs_release_budget(c, req);
-+ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
-+}
-+
-+/**
-+ * ubifs_release_ino_clean - release budget of a "cleaning" operation.
-+ * @c: UBIFS file-system description object
-+ * @inode: VFS inode the operation worked on
-+ * @req: budget to release
-+ *
-+ * This function has to be called at the end of VFS operations which acquired
-+ * budget via 'ubifs_budget_inode_op()'. It assumed the operation synchronized
-+ * the inode, so it marks the inode clean, unlocks it and releases whole budget.
-+ *
-+ * Note, this function also avoids releasing page budgets which are released
-+ * separately.
-+ */
-+void ubifs_release_ino_clean(struct ubifs_info *c, struct inode *inode,
-+ struct ubifs_budget_req *req)
-+{
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+
-+ ubifs_assert(req->dirtied_ino <= 4);
-+ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
-+ ubifs_assert(req->idx_growth >= 0);
-+ ubifs_assert(req->data_growth >= 0);
-+ ubifs_assert(req->dd_growth >= 0);
-+ ubifs_assert(!req->dirtied_page);
-+ ubifs_assert(!req->new_page);
-+ UBIFS_DBG(ui->budgeted = 0);
-+
-+ ubifs_release_budget(c, req);
-+ if (ui->dirty) {
-+ ui->dirty = 0;
-+ /*
-+ * Note, VFS still treats the inode as dirty and
-+ * 'ubifs_write_inode()' will be called, but it'll do nothing
-+ * because @ui->dirty is %0.
-+ */
-+ atomic_long_dec(&c->dirty_ino_cnt);
-+ }
-+ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
-+}
-+
-+/**
-+ * ubifs_release_new_page_budget - release budget of a new page.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This is a helper function which releases budget corresponding to the budget
-+ * of one new page of data.
-+ */
-+void ubifs_release_new_page_budget(struct ubifs_info *c)
-+{
-+ struct ubifs_budget_req req = { .new_page = 1,
-+ .idx_growth = -1,
-+ .data_growth = c->page_budget };
-+
-+ ubifs_release_budget(c, &req);
-+}
-+
-+/**
-+ * ubifs_budg_get_free_space - return amount of free space.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns amount of free space on the file-system.
-+ */
-+long long ubifs_budg_get_free_space(struct ubifs_info *c)
-+{
-+ int min_idx_lebs, rsvd_idx_lebs;
-+ long long available, outstanding, free;
-+
-+ /* Do exactly the same calculations as in 'do_budget_space()' */
-+ spin_lock(&c->space_lock);
-+ min_idx_lebs = ubifs_calc_min_idx_lebs(c);
-+
-+ if (min_idx_lebs > c->lst.idx_lebs)
-+ rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
-+ else
-+ rsvd_idx_lebs = 0;
-+
-+ if (rsvd_idx_lebs > c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt
-+ - c->lst.taken_empty_lebs) {
-+ spin_unlock(&c->space_lock);
-+ return 0;
-+ }
-+
-+ c->min_idx_lebs = min_idx_lebs;
-+ available = ubifs_calc_available(c);
-+ outstanding = c->budg_data_growth + c->budg_dd_growth;
-+ spin_unlock(&c->space_lock);
-+
-+ if (available > outstanding)
-+ free = ubifs_reported_space(c, available - outstanding);
-+ else
-+ free = 0;
-+
-+ return free;
-+}
---- linux-2.6.24.7.old/fs/ubifs/build.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/build.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1423 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file implements UBIFS initialization, mount and un-mount. Some
-+ * initialization stuff which is rather large and complex is placed at
-+ * corresponding subsystems, but most of it is here.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include "ubifs.h"
-+
-+/* Slab cache for UBIFS inodes */
-+struct kmem_cache *ubifs_inode_slab;
-+
-+/* TODO: remove compatibility stuff as late as possible */
-+#ifndef UBIFS_COMPAT_NO_SHRINKER
-+/* UBIFS TNC shrinker description */
-+static struct shrinker ubifs_shrinker_info = {
-+ .shrink = ubifs_shrinker,
-+ .seeks = DEFAULT_SEEKS,
-+};
-+#endif
-+
-+/**
-+ * init_constants_early - initialize UBIFS constants.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function initialize UBIFS constants which do not need the superblock to
-+ * be read. It also checks that the UBI volume satisfies basic UBIFS
-+ * requirements. Returns zero in case of success and a negative error code in
-+ * case of failure.
-+ */
-+static int init_constants_early(struct ubifs_info *c)
-+{
-+ if (c->vi.corrupted) {
-+ ubifs_warn("UBI volume is corrupted - read-only mode");
-+ c->ro_media = 1;
-+ }
-+
-+ if (c->di.ro_mode) {
-+ ubifs_msg("read-only UBI device");
-+ c->ro_media = 1;
-+ }
-+
-+ if (c->vi.vol_type == UBI_STATIC_VOLUME) {
-+ ubifs_msg("static UBI volume - read-only mode");
-+ c->ro_media = 1;
-+ }
-+
-+ c->leb_cnt = c->vi.size;
-+ c->leb_size = c->vi.usable_leb_size;
-+ c->half_leb_size = c->leb_size / 2;
-+ c->min_io_size = c->di.min_io_size;
-+ c->min_io_shift = fls(c->min_io_size) - 1;
-+
-+ if (c->leb_size < UBIFS_MIN_LEB_SZ) {
-+ ubifs_err("too small LEBs (%d bytes), min. is %d bytes",
-+ c->leb_size, UBIFS_MIN_LEB_SZ);
-+ return -EINVAL;
-+ }
-+
-+ if (c->leb_cnt < UBIFS_MIN_LEB_CNT) {
-+ ubifs_err("too few LEBs (%d), min. is %d",
-+ c->leb_cnt, UBIFS_MIN_LEB_CNT);
-+ return -EINVAL;
-+ }
-+
-+ if (!is_power_of_2(c->min_io_size)) {
-+ ubifs_err("bad min. I/O size %d", c->min_io_size);
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * UBIFS aligns all node to 8-byte boundary, so to make function in
-+ * io.c simpler, assume minimum I/O unit size to be 8 bytes if it is
-+ * less than 8.
-+ */
-+ if (c->min_io_size < 8) {
-+ c->min_io_size = 8;
-+ c->min_io_shift = 3;
-+ }
-+
-+ c->ref_node_alsz = ALIGN(UBIFS_REF_NODE_SZ, c->min_io_size);
-+ c->mst_node_alsz = ALIGN(UBIFS_MST_NODE_SZ, c->min_io_size);
-+
-+ /*
-+ * Initialize node length ranges which are mostly needed for node
-+ * length validation.
-+ */
-+ c->ranges[UBIFS_PAD_NODE].len = UBIFS_PAD_NODE_SZ;
-+ c->ranges[UBIFS_SB_NODE].len = UBIFS_SB_NODE_SZ;
-+ c->ranges[UBIFS_MST_NODE].len = UBIFS_MST_NODE_SZ;
-+ c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ;
-+ c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ;
-+ c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ;
-+
-+ c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ;
-+ c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ;
-+ c->ranges[UBIFS_ORPH_NODE].min_len =
-+ UBIFS_ORPH_NODE_SZ + sizeof(__le64);
-+ c->ranges[UBIFS_ORPH_NODE].max_len = c->leb_size;
-+ c->ranges[UBIFS_DENT_NODE].min_len = UBIFS_DENT_NODE_SZ;
-+ c->ranges[UBIFS_DENT_NODE].max_len = UBIFS_MAX_DENT_NODE_SZ;
-+ c->ranges[UBIFS_XENT_NODE].min_len = UBIFS_XENT_NODE_SZ;
-+ c->ranges[UBIFS_XENT_NODE].max_len = UBIFS_MAX_XENT_NODE_SZ;
-+ c->ranges[UBIFS_DATA_NODE].min_len = UBIFS_DATA_NODE_SZ;
-+ c->ranges[UBIFS_DATA_NODE].max_len = UBIFS_MAX_DATA_NODE_SZ;
-+ /*
-+ * Minimum indexing node size is amended later when superblock is
-+ * read and the key length is known.
-+ */
-+ c->ranges[UBIFS_IDX_NODE].min_len = UBIFS_IDX_NODE_SZ + UBIFS_BRANCH_SZ;
-+ /*
-+ * Maximum indexing node size is amended later when superblock is
-+ * read and the fanout is known.
-+ */
-+ c->ranges[UBIFS_IDX_NODE].max_len = INT_MAX;
-+
-+ /*
-+ * Initialize dead and dark LEB space watermarks.
-+ *
-+ * Dead space is the space which cannot be used. Its watermark is
-+ * equivalent to min. I/O unit or minimum node size if it is greater
-+ * then min. I/O unit.
-+ *
-+ * Dark space is the space which might be used, or might not, depending
-+ * on which node should be written to the LEB. Its watermark is
-+ * equivalent to maximum UBIFS node size.
-+ */
-+ c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size);
-+ c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size);
-+
-+ return 0;
-+}
-+
-+/**
-+ * bud_wbuf_callback - bud LEB write-buffer synchronization call-back.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB the write-buffer was synchronized to
-+ * @free: how many free bytes left in this LEB
-+ * @pad: how many bytes were padded
-+ *
-+ * This is a callback function which is called by the I/O unit when the
-+ * write-buffer is synchronized. We need this to correctly maintain space
-+ * accounting in bud logical eraseblocks. This function returns zero in case of
-+ * success and a negative error code in case of failure.
-+ *
-+ * This function actually belongs to the journal, but we keep it here because
-+ * we want to keep it static.
-+ */
-+static int bud_wbuf_callback(struct ubifs_info *c, int lnum, int free, int pad)
-+{
-+ return ubifs_update_one_lp(c, lnum, free, pad, 0, 0);
-+}
-+
-+/*
-+ * init_constants_late - initialize UBIFS constants.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This is a helper function which initializes various UBIFS constants after
-+ * the superblock has been read. It also checks various UBIFS parameters and
-+ * makes sure they are all right. Returns zero in case of success and a
-+ * negative error code in case of failure.
-+ */
-+static int init_constants_late(struct ubifs_info *c)
-+{
-+ int tmp, err;
-+ uint64_t tmp64;
-+
-+ c->main_bytes = c->main_lebs * c->leb_size;
-+
-+ c->max_znode_sz = sizeof(struct ubifs_znode) +
-+ c->fanout * sizeof(struct ubifs_zbranch);
-+
-+ tmp = ubifs_idx_node_sz(c, 1);
-+ c->ranges[UBIFS_IDX_NODE].min_len = tmp;
-+ c->min_idx_node_sz = ALIGN(tmp, 8);
-+
-+ tmp = ubifs_idx_node_sz(c, c->fanout);
-+ c->ranges[UBIFS_IDX_NODE].max_len = tmp;
-+ c->max_idx_node_sz = ALIGN(tmp, 8);
-+
-+ /* Make sure LEB size is large enough to fit full commit */
-+ tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt;
-+ tmp = ALIGN(tmp, c->min_io_size);
-+ if (tmp > c->leb_size) {
-+ dbg_err("too small LEB size %d, at least %d needed",
-+ c->leb_size, tmp);
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * Make sure that the log is large enough to fit reference nodes for
-+ * all buds plus one reserved LEB.
-+ */
-+ tmp64 = c->max_bud_bytes;
-+ tmp = do_div(tmp64, c->leb_size);
-+ c->max_bud_cnt = tmp64 + !!tmp;
-+ tmp = (c->ref_node_alsz * c->max_bud_cnt + c->leb_size - 1);
-+ tmp /= c->leb_size;
-+ tmp += 1;
-+ if (c->log_lebs < tmp) {
-+ dbg_err("too small log %d LEBs, required min. %d LEBs",
-+ c->log_lebs, tmp);
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * When budgeting we assume worst-case scenarios when the pages are not
-+ * be compressed and direntries are of the maximum size.
-+ *
-+ * Note, data, which may be stored in inodes is budgeted separately, so
-+ * it is not included into 'c->inode_budget'.
-+ *
-+ * c->page_budget is PAGE_CACHE_SIZE + UBIFS_CH_SZ * blocks_per_page
-+ */
-+ c->page_budget = PAGE_CACHE_SIZE + UBIFS_CH_SZ;
-+ c->inode_budget = UBIFS_INO_NODE_SZ;
-+ c->dent_budget = UBIFS_MAX_DENT_NODE_SZ;
-+
-+ /*
-+ * When the amount of flash space used by buds becomes
-+ * 'c->max_bud_bytes', UBIFS just blocks all writers and starts commit.
-+ * The writers are unblocked when the commit is finished. To avoid
-+ * writers to be blocked UBIFS initiates background commit in advance,
-+ * when number of bud bytes becomes above the limit defined below.
-+ */
-+ c->bg_bud_bytes = (c->max_bud_bytes * 13) >> 4;
-+
-+ /*
-+ * Ensure minimum journal size. All the bytes in the journal heads are
-+ * considered to be used, when calculating the current journal usage.
-+ * Consequently, if the journal is too small, UBIFS will treat it as
-+ * always full.
-+ */
-+ tmp64 = (uint64_t)(c->jhead_cnt + 1) * c->leb_size + 1;
-+ if (c->bg_bud_bytes < tmp64)
-+ c->bg_bud_bytes = tmp64;
-+ if (c->max_bud_bytes < tmp64 + c->leb_size)
-+ c->max_bud_bytes = tmp64 + c->leb_size;
-+
-+ err = ubifs_calc_lpt_geom(c);
-+ if (err)
-+ return err;
-+
-+ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
-+
-+ /*
-+ * Calculate total amount of FS blocks. This number is not used
-+ * internally because it does not make much sense for UBIFS, but it is
-+ * necessary to report something for the 'statfs()' call.
-+ *
-+ * Subtract the LEB reserved for GC and the LEB which is reserved for
-+ * deletions.
-+ *
-+ * Review 'ubifs_calc_available()' if changing this calculation.
-+ */
-+ tmp64 = c->main_lebs - 2;
-+ tmp64 *= c->leb_size - c->dark_wm;
-+ tmp64 = ubifs_reported_space(c, tmp64);
-+ c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
-+
-+ return 0;
-+}
-+
-+/**
-+ * care_about_gc_lnum - take care about reserved GC LEB.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function ensures that the LEB reserved for garbage collection is
-+ * unmapped and is marked as "taken" in lprops. We also have to set free space
-+ * to LEB size and dirty space to zero, because lprops may contain out-of-date
-+ * information if the file-system was un-mounted before it has been committed.
-+ * This function returns zero in case of success and a negative error code in
-+ * case of failure.
-+ */
-+static int care_about_gc_lnum(struct ubifs_info *c)
-+{
-+ int err;
-+
-+ if (c->gc_lnum == -1) {
-+ ubifs_err("no LEB for GC");
-+ return -EINVAL;
-+ }
-+
-+ err = ubifs_leb_unmap(c, c->gc_lnum);
-+ if (err)
-+ return err;
-+
-+ /* And we have to tell lprops that this LEB is taken */
-+ err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0,
-+ LPROPS_TAKEN, 0, 0);
-+ return err;
-+}
-+
-+/**
-+ * alloc_wbufs - allocate write-buffers.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This helper function allocates and initializes UBIFS write-buffers. Returns
-+ * zero in case of success and %-ENOMEM in case of failure.
-+ */
-+static int alloc_wbufs(struct ubifs_info *c)
-+{
-+ int i, err;
-+
-+ c->jheads = kzalloc(c->jhead_cnt * sizeof(struct ubifs_jhead),
-+ GFP_KERNEL);
-+ if (!c->jheads)
-+ return -ENOMEM;
-+
-+ /* Initialize journal heads */
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ INIT_LIST_HEAD(&c->jheads[i].buds_list);
-+ err = ubifs_wbuf_init(c, &c->jheads[i].wbuf);
-+ if (err)
-+ return err;
-+
-+ c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback;
-+ c->jheads[i].wbuf.jhead = i;
-+ }
-+
-+ c->jheads[BASEHD].wbuf.dtype = UBI_SHORTTERM;
-+ /*
-+ * Garbage Collector head likely contains long-term data and
-+ * does not need to be synchronized by timer.
-+ */
-+ c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
-+ c->jheads[GCHD].wbuf.timeout = 0;
-+
-+ sprintf(c->bgt_name, "%s%d_%d", SYNCER_BG_NAME,
-+ c->vi.ubi_num, c->vi.vol_id);
-+
-+ return 0;
-+}
-+
-+/**
-+ * free_wbufs - free write-buffers.
-+ * @c: UBIFS file-system description object
-+ */
-+static void free_wbufs(struct ubifs_info *c)
-+{
-+ int i;
-+
-+ if (c->jheads) {
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ kfree(c->jheads[i].wbuf.buf);
-+ kfree(c->jheads[i].wbuf.inodes);
-+ }
-+ kfree(c->jheads);
-+ c->jheads = NULL;
-+ }
-+}
-+
-+/**
-+ * free_orphans - free orphans.
-+ * @c: UBIFS file-system description object
-+ */
-+static void free_orphans(struct ubifs_info *c)
-+{
-+ struct ubifs_orphan *orph;
-+
-+ while (c->orph_dnext) {
-+ orph = c->orph_dnext;
-+ c->orph_dnext = orph->dnext;
-+ list_del(&orph->list);
-+ kfree(orph);
-+ }
-+
-+ while (!list_empty(&c->orph_list)) {
-+ orph = list_entry(c->orph_list.next, struct ubifs_orphan, list);
-+ list_del(&orph->list);
-+ kfree(orph);
-+ dbg_err("orphan list not empty at unmount");
-+ }
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->orph_buf);
-+#else
-+ vfree(c->orph_buf);
-+#endif
-+ c->orph_buf = NULL;
-+}
-+
-+/**
-+ * free_buds - free per-bud objects.
-+ * @c: UBIFS file-system description object
-+ */
-+static void free_buds(struct ubifs_info *c)
-+{
-+ struct rb_node *this = c->buds.rb_node;
-+ struct ubifs_bud *bud;
-+
-+ while (this) {
-+ if (this->rb_left)
-+ this = this->rb_left;
-+ else if (this->rb_right)
-+ this = this->rb_right;
-+ else {
-+ bud = rb_entry(this, struct ubifs_bud, rb);
-+ this = rb_parent(this);
-+ if (this) {
-+ if (this->rb_left == &bud->rb)
-+ this->rb_left = NULL;
-+ else
-+ this->rb_right = NULL;
-+ }
-+ kfree(bud);
-+ }
-+ }
-+}
-+
-+/**
-+ * check_volume_empty - check if the UBI volume is empty.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function checks if the UBIFS volume is empty by looking if its LEBs are
-+ * mapped or not. The result of checking is stored in the @c->empty variable.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+static int check_volume_empty(struct ubifs_info *c)
-+{
-+ int lnum, err;
-+
-+ c->empty = 1;
-+ for (lnum = 0; lnum < c->leb_cnt; lnum++) {
-+ err = ubi_is_mapped(c->ubi, lnum);
-+ if (unlikely(err < 0))
-+ return err;
-+ if (err == 1) {
-+ c->empty = 0;
-+ break;
-+ }
-+
-+ cond_resched();
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * mount_ubifs - mount UBIFS file-system.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function mounts UBIFS file system. Returns zero in case of success and
-+ * a negative error code in case of failure.
-+ *
-+ * Note, the function does not de-allocate resources it it fails half way
-+ * through, and the caller has to do this instead.
-+ */
-+static int mount_ubifs(struct ubifs_info *c)
-+{
-+ struct super_block *sb = c->vfs_sb;
-+ int err, mounted_read_only = (sb->s_flags & MS_RDONLY);
-+ unsigned long long x;
-+ size_t sz;
-+
-+ err = init_constants_early(c);
-+ if (err)
-+ return err;
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->dbg_buf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ c->dbg_buf = vmalloc(c->leb_size);
-+#endif
-+ if (!c->dbg_buf)
-+ return -ENOMEM;
-+#endif
-+
-+ err = check_volume_empty(c);
-+ if (err)
-+ return err;
-+
-+ if (c->empty && (mounted_read_only || c->ro_media)) {
-+ /*
-+ * This UBI volume is empty, and read-only, or the file system
-+ * is mounted read-only - we cannot format it.
-+ */
-+ ubifs_err("can't format empty UBI volume: read-only %s",
-+ c->ro_media ? "UBI volume" : "mount");
-+ return -EROFS;
-+ }
-+
-+ if (c->ro_media && !mounted_read_only) {
-+ ubifs_err("cannot mount read-write - read-only media");
-+ return -EROFS;
-+ }
-+
-+ /*
-+ * The requirement for the buffer is that it should fit indexing B-tree
-+ * height amount of integers. We assume the height if the TNC tree will
-+ * never exceed 64.
-+ */
-+ c->bottom_up_buf = kmalloc(BOTTOM_UP_HEIGHT * sizeof(int), GFP_KERNEL);
-+ if (!c->bottom_up_buf)
-+ return -ENOMEM;
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->sbuf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ c->sbuf = vmalloc(c->leb_size);
-+#endif
-+ if (!c->sbuf)
-+ return -ENOMEM;
-+
-+ if (!mounted_read_only) {
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->ileb_buf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ c->ileb_buf = vmalloc(c->leb_size);
-+#endif
-+ if (!c->ileb_buf)
-+ return -ENOMEM;
-+ }
-+
-+ err = ubifs_read_superblock(c);
-+ if (err)
-+ return err;
-+
-+ /*
-+ * Make sure the compressor which is set as the default on in the
-+ * superblock was actually compiled in.
-+ */
-+ if (!ubifs_compr_present(c->default_compr)) {
-+ ubifs_warn("'%s' compressor is set by superblock, but not "
-+ "compiled in", ubifs_compr_name(c->default_compr));
-+ c->default_compr = UBIFS_COMPR_NONE;
-+ }
-+
-+ dbg_failure_mode_registration(c);
-+
-+ err = init_constants_late(c);
-+ if (err)
-+ return err;
-+
-+ sz = ALIGN(c->max_idx_node_sz, c->min_io_size);
-+ sz = ALIGN(sz + c->max_idx_node_sz, c->min_io_size);
-+ c->cbuf = kmalloc(sz, GFP_NOFS);
-+ if (!c->cbuf)
-+ return -ENOMEM;
-+
-+ if (!mounted_read_only) {
-+ err = alloc_wbufs(c);
-+ if (err)
-+ return err;
-+
-+ /* Create background thread */
-+ c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name);
-+ if (!c->bgt)
-+ c->bgt = ERR_PTR(-EINVAL);
-+ if (IS_ERR(c->bgt)) {
-+ err = PTR_ERR(c->bgt);
-+ c->bgt = NULL;
-+ ubifs_err("cannot spawn \"%s\", error %d",
-+ c->bgt_name, err);
-+ return err;
-+ }
-+ }
-+
-+ err = ubifs_read_master(c);
-+ if (err)
-+ return err;
-+
-+ if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
-+ ubifs_msg("recovery needed");
-+ c->need_recovery = 1;
-+ if (!mounted_read_only) {
-+ err = ubifs_recover_inl_heads(c, c->sbuf);
-+ if (err)
-+ return err;
-+ }
-+ } else if (!mounted_read_only) {
-+ /*
-+ * Set the "dirty" flag so that if we reboot uncleanly we
-+ * will notice this immediately on the next mount.
-+ */
-+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
-+ err = ubifs_write_master(c);
-+ if (err)
-+ return err;
-+ }
-+
-+ err = ubifs_lpt_init(c, 1, !mounted_read_only);
-+ if (err)
-+ return err;
-+
-+ err = dbg_check_idx_size(c, c->old_idx_sz);
-+ if (err)
-+ return err;
-+
-+ err = ubifs_replay_journal(c);
-+ if (err)
-+ return err;
-+
-+ if (!mounted_read_only) {
-+ int lnum;
-+
-+ if (c->need_recovery)
-+ err = ubifs_recover_gc_lnum(c);
-+ else
-+ err = care_about_gc_lnum(c);
-+ if (err)
-+ return err;
-+ err = ubifs_mount_orphans(c, c->need_recovery);
-+ if (err)
-+ return err;
-+
-+ /* Check for enough log space */
-+ lnum = c->lhead_lnum + 1;
-+ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs)
-+ lnum = UBIFS_LOG_LNUM;
-+ if (lnum == c->ltail_lnum) {
-+ err = ubifs_consolidate_log(c);
-+ if (err)
-+ return err;
-+ }
-+
-+ /* Check for enough free space */
-+ if (ubifs_calc_available(c) <= 0) {
-+ ubifs_err("insufficient available space");
-+ return -EINVAL;
-+ }
-+
-+ err = dbg_check_lprops(c);
-+ if (err)
-+ return err;
-+ }
-+
-+ if (c->need_recovery) {
-+ err = ubifs_recover_size(c);
-+ if (err)
-+ return err;
-+ }
-+
-+ spin_lock(&ubifs_infos_lock);
-+ list_add_tail(&c->infos_list, &ubifs_infos);
-+ spin_unlock(&ubifs_infos_lock);
-+
-+ if (c->need_recovery) {
-+ if (mounted_read_only)
-+ ubifs_msg("recovery deferred");
-+ else {
-+ c->need_recovery = 0;
-+ ubifs_msg("recovery completed");
-+ }
-+ }
-+
-+ ubifs_msg("mounted UBI device %d, volume %d", c->vi.ubi_num,
-+ c->vi.vol_id);
-+ if (mounted_read_only)
-+ ubifs_msg("mounted read-only");
-+ ubifs_msg("minimal I/O unit size: %d bytes", c->min_io_size);
-+ ubifs_msg("logical eraseblock size: %d bytes (%d KiB)",
-+ c->leb_size, c->leb_size / 1024);
-+ x = (unsigned long long)c->main_lebs * c->leb_size;
-+ ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, "
-+ "%d LEBs)", x, x >> 10, x >> 20, c->main_lebs);
-+ x = (unsigned long long)c->log_lebs * c->leb_size + c->max_bud_bytes;
-+ ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, "
-+ "%d LEBs)", x, x >> 10, x >> 20,
-+ c->log_lebs + c->max_bud_cnt);
-+ ubifs_msg("data journal heads: %d",
-+ c->jhead_cnt - NONDATA_JHEADS_CNT);
-+ ubifs_msg("default compressor: %s",
-+ ubifs_compr_name(c->default_compr));
-+
-+ dbg_msg("compiled on: " __DATE__ " at " __TIME__);
-+ dbg_msg("fast unmount: %d", c->fast_unmount);
-+ dbg_msg("big_lpt %d", c->big_lpt);
-+ dbg_msg("log LEBs: %d (%d - %d)",
-+ c->log_lebs, UBIFS_LOG_LNUM, c->log_last);
-+ dbg_msg("LPT area LEBs: %d (%d - %d)",
-+ c->lpt_lebs, c->lpt_first, c->lpt_last);
-+ dbg_msg("orphan area LEBs: %d (%d - %d)",
-+ c->orph_lebs, c->orph_first, c->orph_last);
-+ dbg_msg("main area LEBs: %d (%d - %d)",
-+ c->main_lebs, c->main_first, c->leb_cnt - 1);
-+ dbg_msg("index LEBs: %d", c->lst.idx_lebs);
-+ dbg_msg("total index bytes: %lld (%lld KiB, %lld MiB)",
-+ c->old_idx_sz, c->old_idx_sz >> 10, c->old_idx_sz >> 20);
-+ dbg_msg("key hash type: %d", c->key_hash_type);
-+ dbg_msg("tree fanout: %d", c->fanout);
-+ dbg_msg("reserved GC LEB: %d", c->gc_lnum);
-+ dbg_msg("first main LEB: %d", c->main_first);
-+ dbg_msg("dead watermark: %d", c->dead_wm);
-+ dbg_msg("dark watermark: %d", c->dark_wm);
-+ x = c->main_lebs * c->dark_wm;
-+ dbg_msg("max. dark space: %lld (%lld KiB, %lld MiB)",
-+ x, x >> 10, x >> 20);
-+ dbg_msg("maximum bud bytes: %lld (%lld KiB, %lld MiB)",
-+ c->max_bud_bytes, c->max_bud_bytes >> 10,
-+ c->max_bud_bytes >> 20);
-+ dbg_msg("BG commit bud bytes: %lld (%lld KiB, %lld MiB)",
-+ c->bg_bud_bytes, c->bg_bud_bytes >> 10,
-+ c->bg_bud_bytes >> 20);
-+ dbg_msg("current bud bytes %lld (%lld KiB, %lld MiB)",
-+ c->bud_bytes, c->bud_bytes >> 10, c->bud_bytes >> 20);
-+ dbg_msg("max. seq. number: %llu", c->max_sqnum);
-+ dbg_msg("commit number: %llu", c->cmt_no);
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_umount - un-mount UBIFS file-system.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Note, this function is called to free allocated resourced when un-mounting,
-+ * as well as free resources when an error occurred while we were half way
-+ * through mounting (error path cleanup function). So it has to make sure the
-+ * resource was actually allocated before freeing it.
-+ */
-+void ubifs_umount(struct ubifs_info *c)
-+{
-+ dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num,
-+ c->vi.vol_id);
-+
-+ ubifs_destroy_size_tree(c);
-+
-+ if (c->bgt)
-+ kthread_stop(c->bgt);
-+
-+ free_buds(c);
-+ ubifs_destroy_idx_gc(c);
-+ ubifs_tnc_close(c);
-+
-+ free_wbufs(c);
-+ free_orphans(c);
-+ ubifs_lpt_free(c, 0);
-+
-+ while (!list_empty(&c->unclean_leb_list)) {
-+ struct ubifs_unclean_leb *ucleb;
-+
-+ ucleb = list_entry(c->unclean_leb_list.next,
-+ struct ubifs_unclean_leb, list);
-+ list_del(&ucleb->list);
-+ kfree(ucleb);
-+ }
-+
-+ while (!list_empty(&c->old_buds)) {
-+ struct ubifs_bud *bud;
-+
-+ bud = list_entry(c->old_buds.next, struct ubifs_bud, list);
-+ list_del(&bud->list);
-+ kfree(bud);
-+ }
-+
-+ kfree(c->rcvrd_mst_node);
-+ kfree(c->mst_node);
-+ kfree(c->bottom_up_buf);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->sbuf);
-+ UBIFS_DBG(kfree(c->dbg_buf));
-+ kfree(c->ileb_buf);
-+#else
-+ vfree(c->sbuf);
-+ UBIFS_DBG(vfree(c->dbg_buf));
-+ vfree(c->ileb_buf);
-+#endif
-+ dbg_failure_mode_deregistration(c);
-+}
-+
-+/**
-+ * ubifs_remount_rw - re-mount in read-write mode.
-+ * @c: UBIFS file-system description object
-+ *
-+ * UBIFS avoids allocating many unnecessary resources when mounted in read-only
-+ * mode. This function allocates the needed resources and re-mounts UBIFS in
-+ * read-write mode.
-+ */
-+int ubifs_remount_rw(struct ubifs_info *c)
-+{
-+ int err, lnum;
-+
-+ if (c->ro_media)
-+ return -EINVAL;
-+
-+ mutex_lock(&c->umount_mutex);
-+ c->remounting_rw = 1;
-+
-+ /* Check for enough free space */
-+ if (ubifs_calc_available(c) <= 0) {
-+ ubifs_err("insufficient available space");
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (c->old_leb_cnt != c->leb_cnt) {
-+ struct ubifs_sb_node *sup;
-+
-+ sup = ubifs_read_sb_node(c);
-+ if (IS_ERR(sup)) {
-+ err = PTR_ERR(sup);
-+ goto out;
-+ }
-+ sup->leb_cnt = cpu_to_le32(c->leb_cnt);
-+ err = ubifs_write_sb_node(c, sup);
-+ if (err)
-+ goto out;
-+ }
-+
-+ if (c->need_recovery) {
-+ ubifs_msg("completing deferred recovery");
-+ err = ubifs_write_rcvrd_mst_node(c);
-+ if (err)
-+ goto out;
-+ err = ubifs_recover_size(c);
-+ if (err)
-+ goto out;
-+ err = ubifs_clean_lebs(c, c->sbuf);
-+ if (err)
-+ goto out;
-+ err = ubifs_recover_inl_heads(c, c->sbuf);
-+ if (err)
-+ goto out;
-+ }
-+
-+ if (!(c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY))) {
-+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
-+ err = ubifs_write_master(c);
-+ if (err)
-+ goto out;
-+ }
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->ileb_buf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ c->ileb_buf = vmalloc(c->leb_size);
-+#endif
-+ if (!c->ileb_buf) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ err = ubifs_lpt_init(c, 0, 1);
-+ if (err)
-+ goto out;
-+
-+ err = alloc_wbufs(c);
-+ if (err)
-+ goto out;
-+
-+ ubifs_create_buds_lists(c);
-+
-+ /* Create background thread */
-+ c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name);
-+ if (!c->bgt)
-+ c->bgt = ERR_PTR(-EINVAL);
-+ if (IS_ERR(c->bgt)) {
-+ err = PTR_ERR(c->bgt);
-+ c->bgt = NULL;
-+ ubifs_err("cannot spawn \"%s\", error %d",
-+ c->bgt_name, err);
-+ return err;
-+ }
-+
-+ if (c->need_recovery)
-+ err = ubifs_recover_gc_lnum(c);
-+ else
-+ err = care_about_gc_lnum(c);
-+ if (err)
-+ goto out;
-+
-+ err = ubifs_mount_orphans(c, c->need_recovery);
-+ if (err)
-+ goto out;
-+ /* Check for enough log space */
-+ lnum = c->lhead_lnum + 1;
-+ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs)
-+ lnum = UBIFS_LOG_LNUM;
-+ if (lnum == c->ltail_lnum) {
-+ err = ubifs_consolidate_log(c);
-+ if (err)
-+ goto out;
-+ }
-+
-+ if (c->need_recovery) {
-+ c->need_recovery = 0;
-+ ubifs_msg("deferred recovery completed");
-+ }
-+
-+ dbg_gen("re-mounted read-write");
-+ c->vfs_sb->s_flags &= ~MS_RDONLY;
-+ c->remounting_rw = 0;
-+ mutex_unlock(&c->umount_mutex);
-+ return 0;
-+
-+out:
-+ free_orphans(c);
-+ if (c->bgt) {
-+ kthread_stop(c->bgt);
-+ c->bgt = NULL;
-+ }
-+ free_wbufs(c);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->ileb_buf);
-+#else
-+ vfree(c->ileb_buf);
-+#endif
-+ c->ileb_buf = NULL;
-+ ubifs_lpt_free(c, 1);
-+ c->remounting_rw = 0;
-+ mutex_unlock(&c->umount_mutex);
-+ return err;
-+}
-+
-+/**
-+ * commit_on_unmount - commit the journal when un-mounting.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function is called during un-mounting and it commits the journal unless
-+ * the "fast unmount" mode is enabled. It also avoids committing the journal if
-+ * it contains too few data.
-+ *
-+ * Sometimes recovery requires the journal to be committed at least once, and
-+ * this function takes care about this.
-+ */
-+static void commit_on_unmount(struct ubifs_info *c)
-+{
-+ if (!c->fast_unmount) {
-+ long long bud_bytes;
-+
-+ spin_lock(&c->buds_lock);
-+ bud_bytes = c->bud_bytes;
-+ spin_unlock(&c->buds_lock);
-+ if (bud_bytes > c->leb_size)
-+ ubifs_run_commit(c);
-+ }
-+
-+ if (c->recovery_needs_commit)
-+ ubifs_recovery_commit(c);
-+}
-+
-+/**
-+ * ubifs_remount_ro - re-mount in read-only mode.
-+ * @c: UBIFS file-system description object
-+ *
-+ * We rely on VFS to have stopped writing. Possibly the background thread could
-+ * be running a commit, however kthread_stop will wait in that case.
-+ */
-+void ubifs_remount_ro(struct ubifs_info *c)
-+{
-+ int i, err;
-+
-+ ubifs_assert(!c->need_recovery);
-+
-+ commit_on_unmount(c);
-+
-+ mutex_lock(&c->umount_mutex);
-+ if (c->bgt) {
-+ kthread_stop(c->bgt);
-+ c->bgt = NULL;
-+ }
-+
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ ubifs_wbuf_sync(&c->jheads[i].wbuf);
-+ del_timer_sync(&c->jheads[i].wbuf.timer);
-+ }
-+
-+ if (!c->ro_media) {
-+ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
-+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
-+ c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
-+ err = ubifs_write_master(c);
-+ if (err)
-+ ubifs_ro_mode(c, err);
-+ }
-+
-+ ubifs_destroy_idx_gc(c);
-+ free_wbufs(c);
-+ free_orphans(c);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->ileb_buf);
-+#else
-+ vfree(c->ileb_buf);
-+#endif
-+ c->ileb_buf = NULL;
-+ ubifs_lpt_free(c, 1);
-+ mutex_unlock(&c->umount_mutex);
-+}
-+
-+/**
-+ * open_ubi - parse UBI device name string and open the UBI device.
-+ * @c: UBIFS file-system description object
-+ * @name: UBI volume name
-+ * @mode: UBI volume open mode
-+ *
-+ * There are several ways to specify UBI volumes when mounting UBIFS:
-+ * o ubiX_Y - UBI device number X, volume Y;
-+ * o ubiY - UBI device number 0, volume Y;
-+ * o ubiX:NAME - mount UBI device X, volume with name NAME;
-+ * o ubi:NAME - mount UBI device 0, volume with name NAME.
-+ *
-+ * Alternative '!' separator may be used instead of ':' (because some shells
-+ * like busybox may interpret ':' as an NFS host name separator). This function
-+ * returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+static int open_ubi(struct ubifs_info *c, const char *name, int mode)
-+{
-+ int dev, vol;
-+ char *endptr;
-+
-+ if (name[0] != 'u' || name[1] != 'b' || name[2] != 'i')
-+ return -EINVAL;
-+
-+ if ((name[3] == ':' || name[3] == '!') && name[4] != '\0') {
-+ /* ubi:NAME method */
-+ c->ubi = ubi_open_volume_nm(0, name + 4, mode);
-+ if (IS_ERR(c->ubi))
-+ return PTR_ERR(c->ubi);
-+ } else if (isdigit(name[3])) {
-+ dev = simple_strtoul(name + 3, &endptr, 0);
-+ if (*endptr == '\0') {
-+ /* ubiY method */
-+ c->ubi = ubi_open_volume(0, dev, mode);
-+ if (IS_ERR(c->ubi))
-+ return PTR_ERR(c->ubi);
-+ } else if (*endptr == '_' && isdigit(endptr[1])) {
-+ /* ubiX_Y method */
-+ vol = simple_strtoul(endptr + 1, &endptr, 0);
-+ if (*endptr != '\0')
-+ return -EINVAL;
-+ c->ubi = ubi_open_volume(dev, vol, mode);
-+ if (IS_ERR(c->ubi))
-+ return PTR_ERR(c->ubi);
-+ } else if ((*endptr == ':' || *endptr == '!') &&
-+ endptr[1] != '\0') {
-+ /* ubiX:NAME method */
-+ c->ubi = ubi_open_volume_nm(dev, ++endptr, mode);
-+ if (IS_ERR(c->ubi))
-+ return PTR_ERR(c->ubi);
-+ }
-+ }
-+
-+ if (!c->ubi)
-+ return -EINVAL;
-+
-+ ubi_get_volume_info(c->ubi, &c->vi);
-+ ubi_get_device_info(c->vi.ubi_num, &c->di);
-+ return 0;
-+}
-+
-+static int sb_test(struct super_block *sb, void *data)
-+{
-+ dev_t *dev = data;
-+
-+ return sb->s_dev == *dev;
-+}
-+
-+static int sb_set(struct super_block *sb, void *data)
-+{
-+ return 0;
-+}
-+
-+/*
-+ * UBIFS mount options.
-+ *
-+ * Opt_fast_unmount: do not run a journal commit before un-mounting
-+ * Opt_norm_unmount: run a journal commit before un-mounting
-+ * Opt_err: just end of array marker
-+ */
-+enum {
-+ Opt_fast_unmount,
-+ Opt_norm_unmount,
-+ Opt_err,
-+};
-+
-+static match_table_t tokens = {
-+ {Opt_fast_unmount, "fast_unmount"},
-+ {Opt_norm_unmount, "norm_unmount"},
-+ {Opt_err, NULL},
-+};
-+
-+/**
-+ * ubifs_parse_options - parse mount parameters.
-+ * @c: UBIFS file-system description object
-+ * @options: parameters to parse
-+ * @is_remount: non-zero if this is FS re-mount
-+ *
-+ * This function parses UBIFS mount options and returns zero in case success
-+ * and a negative error code in case of failure.
-+ */
-+int ubifs_parse_options(struct ubifs_info *c, char *options, int is_remount)
-+{
-+ char *p;
-+ substring_t args[MAX_OPT_ARGS];
-+
-+ if (!options)
-+ return 0;
-+
-+ while ((p = strsep(&options, ",")) != NULL) {
-+ int token;
-+
-+ if (!*p)
-+ continue;
-+
-+ token = match_token(p, tokens, args);
-+ switch (token) {
-+ case Opt_fast_unmount:
-+ c->mount_opts.unmount_mode = 2;
-+ c->fast_unmount = 1;
-+ break;
-+ case Opt_norm_unmount:
-+ c->mount_opts.unmount_mode = 1;
-+ c->fast_unmount = 0;
-+ break;
-+ default:
-+ ubifs_err("unrecognized mount option \"%s\" "
-+ "or missing value", p);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int ubifs_get_sb(struct file_system_type *fs_type, int flags,
-+ const char *name, void *data, struct vfsmount *mnt)
-+{
-+ int err;
-+ struct super_block *sb;
-+ struct ubifs_info *c;
-+ struct inode *root;
-+
-+ dbg_gen("name %s, flags %#x", name, flags);
-+
-+ c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL);
-+ if (!c)
-+ return -ENOMEM;
-+
-+ spin_lock_init(&c->cnt_lock);
-+ spin_lock_init(&c->cs_lock);
-+ spin_lock_init(&c->buds_lock);
-+ spin_lock_init(&c->space_lock);
-+ spin_lock_init(&c->orphan_lock);
-+ init_rwsem(&c->commit_sem);
-+ mutex_init(&c->lp_mutex);
-+ mutex_init(&c->tnc_mutex);
-+ mutex_init(&c->log_mutex);
-+ mutex_init(&c->mst_mutex);
-+ mutex_init(&c->umount_mutex);
-+ init_waitqueue_head(&c->cmt_wq);
-+ c->buds = RB_ROOT;
-+ c->old_idx = RB_ROOT;
-+ c->size_tree = RB_ROOT;
-+ c->orph_tree = RB_ROOT;
-+ INIT_LIST_HEAD(&c->infos_list);
-+ INIT_LIST_HEAD(&c->idx_gc);
-+ INIT_LIST_HEAD(&c->replay_list);
-+ INIT_LIST_HEAD(&c->replay_buds);
-+ INIT_LIST_HEAD(&c->uncat_list);
-+ INIT_LIST_HEAD(&c->empty_list);
-+ INIT_LIST_HEAD(&c->freeable_list);
-+ INIT_LIST_HEAD(&c->frdi_idx_list);
-+ INIT_LIST_HEAD(&c->unclean_leb_list);
-+ INIT_LIST_HEAD(&c->old_buds);
-+ INIT_LIST_HEAD(&c->orph_list);
-+ INIT_LIST_HEAD(&c->orph_new);
-+
-+ c->highest_inum = UBIFS_FIRST_INO;
-+ get_random_bytes(&c->vfs_gen, sizeof(int));
-+ c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM;
-+
-+ err = ubifs_parse_options(c, data, 0);
-+ if (err)
-+ goto out_free;
-+
-+ /*
-+ * Get UBI device number and volume ID. Mount it read-only so far
-+ * because this might be a new mount point, and UBI allows only one
-+ * read-write user at a time.
-+ */
-+ err = open_ubi(c, name, UBI_READONLY);
-+ if (err) {
-+ ubifs_err("cannot open \"%s\", error %d", name, err);
-+ goto out_free;
-+ }
-+
-+ dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
-+
-+ sb = sget(fs_type, &sb_test, &sb_set, &c->vi.cdev);
-+ if (IS_ERR(sb)) {
-+ err = PTR_ERR(sb);
-+ goto out_close;
-+ }
-+
-+ if (sb->s_root) {
-+ /* A new mount point for already mounted UBIFS */
-+ dbg_gen("this ubi volume is already mounted");
-+ err = simple_set_mnt(mnt, sb);
-+ goto out_close;
-+ }
-+
-+ /* Re-open the UBI device in read-write mode */
-+ ubi_close_volume(c->ubi);
-+ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE);
-+ if (IS_ERR(c->ubi)) {
-+ err = PTR_ERR(c->ubi);
-+ goto out_free;
-+ }
-+
-+ c->vfs_sb = sb;
-+ sb->s_fs_info = c;
-+ sb->s_magic = UBIFS_SUPER_MAGIC;
-+ sb->s_blocksize = UBIFS_BLOCK_SIZE;
-+ sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT;
-+ sb->s_dev = c->vi.cdev;
-+ sb->s_maxbytes = c->max_inode_sz =
-+ min_t(uint64_t, MAX_LFS_FILESIZE, UBIFS_MAX_INODE_SZ);
-+ sb->s_op = &ubifs_super_operations;
-+ sb->s_flags = flags;
-+
-+ mutex_lock(&c->umount_mutex);
-+ err = mount_ubifs(c);
-+ if (err) {
-+ ubifs_assert(err < 0);
-+ goto out_umount;
-+ }
-+
-+ /* Read the root inode */
-+ root = ubifs_iget(sb, UBIFS_ROOT_INO);
-+ if (IS_ERR(root)) {
-+ err = PTR_ERR(root);
-+ goto out_umount;
-+ }
-+
-+ sb->s_root = d_alloc_root(root);
-+ if (!sb->s_root)
-+ goto out_iput;
-+
-+ mutex_unlock(&c->umount_mutex);
-+
-+ /* We do not support atime */
-+ sb->s_flags |= MS_ACTIVE | MS_NOATIME;
-+ return simple_set_mnt(mnt, sb);
-+
-+out_iput:
-+ iput(root);
-+out_umount:
-+ spin_lock(&ubifs_infos_lock);
-+ if (c->infos_list.next)
-+ list_del(&c->infos_list);
-+ spin_unlock(&ubifs_infos_lock);
-+ ubifs_umount(c);
-+ mutex_unlock(&c->umount_mutex);
-+ up_write(&sb->s_umount);
-+ sb->s_root = NULL;
-+ deactivate_super(sb);
-+out_close:
-+ ubi_close_volume(c->ubi);
-+out_free:
-+ kfree(c);
-+ return err;
-+}
-+
-+static void ubifs_kill_sb(struct super_block *sb)
-+{
-+ struct ubifs_info *c = sb->s_fs_info;
-+
-+ if (sb->s_root != NULL && !(sb->s_flags & MS_RDONLY))
-+ commit_on_unmount(c);
-+ /* The un-mount routine is actually done in put_super() */
-+ generic_shutdown_super(sb);
-+}
-+
-+static struct file_system_type ubifs_fs_type = {
-+ .name = "ubifs",
-+ .owner = THIS_MODULE,
-+ .get_sb = ubifs_get_sb,
-+ .kill_sb = ubifs_kill_sb
-+};
-+
-+/*
-+ * Inode slab cache constructor.
-+ *
-+ * TODO: remove backward compatibility as late as possible
-+ */
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
-+static void inode_slab_ctor(void *obj, struct kmem_cache *cachep,
-+ unsigned long flags)
-+#else
-+static void inode_slab_ctor(struct kmem_cache *cachep, void *obj)
-+#endif
-+{
-+ struct ubifs_inode *inode = obj;
-+ inode_init_once(&inode->vfs_inode);
-+}
-+
-+static int __init ubifs_init(void)
-+{
-+ int err;
-+
-+ BUILD_BUG_ON(sizeof(struct ubifs_ch) != 24);
-+
-+ /* Make sure node sizes are 8-byte aligned */
-+ BUILD_BUG_ON(UBIFS_CH_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_INO_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_DENT_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_XENT_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_DATA_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_SB_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MST_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_REF_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_CS_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_ORPH_NODE_SZ & 7);
-+
-+ BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MAX_NODE_SZ & 7);
-+ BUILD_BUG_ON(MIN_WRITE_SZ & 7);
-+
-+ /* Check min. node size */
-+ BUILD_BUG_ON(UBIFS_INO_NODE_SZ < MIN_WRITE_SZ);
-+ BUILD_BUG_ON(UBIFS_DENT_NODE_SZ < MIN_WRITE_SZ);
-+ BUILD_BUG_ON(UBIFS_XENT_NODE_SZ < MIN_WRITE_SZ);
-+ BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ < MIN_WRITE_SZ);
-+
-+ BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ > UBIFS_MAX_NODE_SZ);
-+ BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ > UBIFS_MAX_NODE_SZ);
-+ BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ > UBIFS_MAX_NODE_SZ);
-+ BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ > UBIFS_MAX_NODE_SZ);
-+
-+ /* We do not support multiple pages per block ATM */
-+ BUILD_BUG_ON(UBIFS_BLOCK_SIZE != PAGE_CACHE_SIZE);
-+
-+ /* Defined node sizes */
-+ BUILD_BUG_ON(UBIFS_SB_NODE_SZ != 4096);
-+ BUILD_BUG_ON(UBIFS_MST_NODE_SZ != 512);
-+ BUILD_BUG_ON(UBIFS_INO_NODE_SZ != 160);
-+ BUILD_BUG_ON(UBIFS_REF_NODE_SZ != 64);
-+
-+ err = bdi_init(&ubifs_backing_dev_info);
-+ if (err)
-+ return err;
-+
-+ err = register_filesystem(&ubifs_fs_type);
-+ if (err) {
-+ ubifs_err("cannot register file system, error %d", err);
-+ goto out;
-+ }
-+
-+ err = -ENOMEM;
-+ ubifs_inode_slab = kmem_cache_create("ubifs_inode_slab",
-+ sizeof(struct ubifs_inode), 0,
-+ SLAB_MEM_SPREAD | SLAB_RECLAIM_ACCOUNT,
-+ &inode_slab_ctor UBIFSCOMPATNULL);
-+ if (!ubifs_inode_slab)
-+ goto out_reg;
-+
-+ register_shrinker(&ubifs_shrinker_info);
-+ dbg_mempressure_init();
-+
-+ err = ubifs_compressors_init();
-+ if (err)
-+ goto out_compr;
-+
-+ return 0;
-+
-+out_compr:
-+ dbg_mempressure_exit();
-+ unregister_shrinker(&ubifs_shrinker_info);
-+ kmem_cache_destroy(ubifs_inode_slab);
-+out_reg:
-+ unregister_filesystem(&ubifs_fs_type);
-+out:
-+ bdi_destroy(&ubifs_backing_dev_info);
-+ return err;
-+}
-+/* late_initcall to let compressors initialize first */
-+late_initcall(ubifs_init);
-+
-+static void __exit ubifs_exit(void)
-+{
-+ ubifs_assert(list_empty(&ubifs_infos));
-+ ubifs_assert(atomic_long_read(&ubifs_clean_zn_cnt) == 0);
-+
-+ ubifs_compressors_exit();
-+ dbg_mempressure_exit();
-+ unregister_shrinker(&ubifs_shrinker_info);
-+ kmem_cache_destroy(ubifs_inode_slab);
-+ unregister_filesystem(&ubifs_fs_type);
-+ bdi_destroy(&ubifs_backing_dev_info);
-+ dbg_leak_report();
-+}
-+module_exit(ubifs_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(__stringify(UBIFS_VERSION));
-+MODULE_AUTHOR("Artem Bityutskiy, Adrian Hunter");
-+MODULE_DESCRIPTION("UBIFS - UBI File System");
---- linux-2.6.24.7.old/fs/ubifs/commit.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/commit.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,718 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file implements functions that manage the running of the commit process.
-+ * Each affected module has its own functions to accomplish their part in the
-+ * commit and those functions are called here.
-+ *
-+ * The commit is the process whereby all updates to the index and LEB properties
-+ * are written out together and the journal becomes empty. This keeps the
-+ * file system consistent - at all times the state can be recreated by reading
-+ * the index and LEB properties and then replaying the journal.
-+ *
-+ * The commit is split into two parts named "commit start" and "commit end".
-+ * During commit start, the commit process has exclusive access to the journal
-+ * by holding the commit semaphore down for writing. As few I/O operations as
-+ * possible are performed during commit start, instead the nodes that are to be
-+ * written are merely identified. During commit end, the commit semaphore is no
-+ * longer held and the journal is again in operation, allowing users to continue
-+ * to use the file system while the bulk of the commit I/O is performed. The
-+ * purpose of this two-step approach is to prevent the commit from causing any
-+ * latency blips. Note that in any case, the commit does not prevent lookups
-+ * (as permitted by the TNC mutex), or access to VFS data structures e.g. page
-+ * cache.
-+ */
-+
-+#include
-+#include
-+#include "ubifs.h"
-+
-+/**
-+ * do_commit - commit the journal.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function implements UBIFS commit. It has to be called with commit lock
-+ * locked. Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+static int do_commit(struct ubifs_info *c)
-+{
-+ int err, new_ltail_lnum, old_ltail_lnum, i;
-+ struct ubifs_zbranch zroot;
-+ struct ubifs_lp_stats lst;
-+
-+ dbg_cmt("start");
-+ if (c->ro_media) {
-+ err = -EROFS;
-+ goto out_up;
-+ }
-+
-+ c->recovery_needs_commit = 0;
-+
-+ /* Sync all write buffers (necessary for recovery) */
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
-+ if (err)
-+ goto out_up;
-+ }
-+
-+ err = ubifs_gc_start_commit(c);
-+ if (err)
-+ goto out_up;
-+ err = dbg_check_lprops(c);
-+ if (err)
-+ goto out_up;
-+ err = ubifs_log_start_commit(c, &new_ltail_lnum);
-+ if (err)
-+ goto out_up;
-+ err = ubifs_tnc_start_commit(c, &zroot);
-+ if (err)
-+ goto out_up;
-+ err = ubifs_lpt_start_commit(c);
-+ if (err)
-+ goto out_up;
-+ err = ubifs_orphan_start_commit(c);
-+ if (err)
-+ goto out_up;
-+
-+ ubifs_get_lp_stats(c, &lst);
-+
-+ up_write(&c->commit_sem);
-+
-+ err = ubifs_tnc_end_commit(c);
-+ if (err)
-+ goto out;
-+ err = ubifs_lpt_end_commit(c);
-+ if (err)
-+ goto out;
-+ err = ubifs_orphan_end_commit(c);
-+ if (err)
-+ goto out;
-+ old_ltail_lnum = c->ltail_lnum;
-+ err = ubifs_log_end_commit(c, new_ltail_lnum);
-+ if (err)
-+ goto out;
-+ err = dbg_check_old_index(c, &zroot);
-+ if (err)
-+ goto out;
-+
-+ mutex_lock(&c->mst_mutex);
-+ c->mst_node->cmt_no = cpu_to_le64(++c->cmt_no);
-+ c->mst_node->log_lnum = cpu_to_le32(new_ltail_lnum);
-+ c->mst_node->root_lnum = cpu_to_le32(zroot.lnum);
-+ c->mst_node->root_offs = cpu_to_le32(zroot.offs);
-+ c->mst_node->root_len = cpu_to_le32(zroot.len);
-+ c->mst_node->ihead_lnum = cpu_to_le32(c->ihead_lnum);
-+ c->mst_node->ihead_offs = cpu_to_le32(c->ihead_offs);
-+ c->mst_node->index_size = cpu_to_le64(c->old_idx_sz);
-+ c->mst_node->lpt_lnum = cpu_to_le32(c->lpt_lnum);
-+ c->mst_node->lpt_offs = cpu_to_le32(c->lpt_offs);
-+ c->mst_node->nhead_lnum = cpu_to_le32(c->nhead_lnum);
-+ c->mst_node->nhead_offs = cpu_to_le32(c->nhead_offs);
-+ c->mst_node->ltab_lnum = cpu_to_le32(c->ltab_lnum);
-+ c->mst_node->ltab_offs = cpu_to_le32(c->ltab_offs);
-+ c->mst_node->lsave_lnum = cpu_to_le32(c->lsave_lnum);
-+ c->mst_node->lsave_offs = cpu_to_le32(c->lsave_offs);
-+ c->mst_node->lscan_lnum = cpu_to_le32(c->lscan_lnum);
-+ c->mst_node->empty_lebs = cpu_to_le32(lst.empty_lebs);
-+ c->mst_node->idx_lebs = cpu_to_le32(lst.idx_lebs);
-+ c->mst_node->total_free = cpu_to_le64(lst.total_free);
-+ c->mst_node->total_dirty = cpu_to_le64(lst.total_dirty);
-+ c->mst_node->total_used = cpu_to_le64(lst.total_used);
-+ c->mst_node->total_dead = cpu_to_le64(lst.total_dead);
-+ c->mst_node->total_dark = cpu_to_le64(lst.total_dark);
-+ if (c->no_orphs)
-+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
-+ else
-+ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_NO_ORPHS);
-+ err = ubifs_write_master(c);
-+ mutex_unlock(&c->mst_mutex);
-+ if (err)
-+ goto out;
-+
-+ err = ubifs_log_post_commit(c, old_ltail_lnum);
-+ if (err)
-+ goto out;
-+ err = ubifs_gc_end_commit(c);
-+ if (err)
-+ goto out;
-+ err = ubifs_lpt_post_commit(c);
-+ if (err)
-+ goto out;
-+
-+ spin_lock(&c->cs_lock);
-+ c->cmt_state = COMMIT_RESTING;
-+ wake_up(&c->cmt_wq);
-+ dbg_cmt("commit end");
-+ spin_unlock(&c->cs_lock);
-+
-+ return 0;
-+
-+out_up:
-+ up_write(&c->commit_sem);
-+out:
-+ ubifs_err("commit failed, error %d", err);
-+ spin_lock(&c->cs_lock);
-+ c->cmt_state = COMMIT_BROKEN;
-+ wake_up(&c->cmt_wq);
-+ spin_unlock(&c->cs_lock);
-+ ubifs_ro_mode(c, err);
-+ return err;
-+}
-+
-+/**
-+ * run_bg_commit - run background commit if it is needed.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function runs background commit if it is needed. Returns zero in case
-+ * of success and a negative error code in case of failure.
-+ */
-+static int run_bg_commit(struct ubifs_info *c)
-+{
-+ spin_lock(&c->cs_lock);
-+ /*
-+ * Run background commit only if background commit was requested or if
-+ * commit is required.
-+ */
-+ if (c->cmt_state != COMMIT_BACKGROUND &&
-+ c->cmt_state != COMMIT_REQUIRED)
-+ goto out;
-+ spin_unlock(&c->cs_lock);
-+
-+ down_write(&c->commit_sem);
-+ spin_lock(&c->cs_lock);
-+ if (c->cmt_state == COMMIT_REQUIRED)
-+ c->cmt_state = COMMIT_RUNNING_REQUIRED;
-+ else if (c->cmt_state == COMMIT_BACKGROUND)
-+ c->cmt_state = COMMIT_RUNNING_BACKGROUND;
-+ else
-+ goto out_cmt_unlock;
-+ spin_unlock(&c->cs_lock);
-+
-+ return do_commit(c);
-+
-+out_cmt_unlock:
-+ up_write(&c->commit_sem);
-+out:
-+ spin_unlock(&c->cs_lock);
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_bg_thread - UBIFS background thread function.
-+ * @info: points to the file-system description object
-+ *
-+ * This function implements various file-system background activities:
-+ * o when a write-buffer timer expires it synchronizes the appropriate
-+ * write-buffer;
-+ * o when the journal is about to be full, it starts in-advance commit.
-+ *
-+ * Note, other stuff like background garbage collection may be added here in
-+ * future.
-+ */
-+int ubifs_bg_thread(void *info)
-+{
-+ int err;
-+ struct ubifs_info *c = info;
-+
-+ ubifs_msg("background thread \"%s\" started, PID %d",
-+ c->bgt_name, current->pid);
-+ set_freezable();
-+
-+ while (1) {
-+ if (kthread_should_stop())
-+ break;
-+
-+ if (try_to_freeze())
-+ continue;
-+
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ /* Check if there is something to do */
-+ if (!c->need_bgt) {
-+ /*
-+ * Nothing prevents us from going sleep now and
-+ * be never woken up and block the task which
-+ * could wait in 'kthread_stop()' forever.
-+ */
-+ if (kthread_should_stop())
-+ break;
-+ schedule();
-+ continue;
-+ } else
-+ __set_current_state(TASK_RUNNING);
-+
-+ c->need_bgt = 0;
-+ err = ubifs_bg_wbufs_sync(c);
-+ if (err)
-+ ubifs_ro_mode(c, err);
-+
-+ run_bg_commit(c);
-+ cond_resched();
-+ }
-+
-+ dbg_msg("background thread \"%s\" stops", c->bgt_name);
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_commit_required - set commit state to "required".
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function is called if a commit is required but cannot be done from the
-+ * calling function, so it is just flagged instead.
-+ */
-+void ubifs_commit_required(struct ubifs_info *c)
-+{
-+ spin_lock(&c->cs_lock);
-+ switch (c->cmt_state) {
-+ case COMMIT_RESTING:
-+ case COMMIT_BACKGROUND:
-+ dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state),
-+ dbg_cstate(COMMIT_REQUIRED));
-+ c->cmt_state = COMMIT_REQUIRED;
-+ break;
-+ case COMMIT_RUNNING_BACKGROUND:
-+ dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state),
-+ dbg_cstate(COMMIT_RUNNING_REQUIRED));
-+ c->cmt_state = COMMIT_RUNNING_REQUIRED;
-+ break;
-+ case COMMIT_REQUIRED:
-+ case COMMIT_RUNNING_REQUIRED:
-+ case COMMIT_BROKEN:
-+ break;
-+ }
-+ spin_unlock(&c->cs_lock);
-+}
-+
-+/**
-+ * ubifs_request_bg_commit - notify the background thread to do a commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function is called if the journal is full enough to make a commit
-+ * worthwhile, so background thread is kicked to start it.
-+ */
-+void ubifs_request_bg_commit(struct ubifs_info *c)
-+{
-+ spin_lock(&c->cs_lock);
-+ if (c->cmt_state == COMMIT_RESTING) {
-+ dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state),
-+ dbg_cstate(COMMIT_BACKGROUND));
-+ c->cmt_state = COMMIT_BACKGROUND;
-+ spin_unlock(&c->cs_lock);
-+ ubifs_wake_up_bgt(c);
-+ } else
-+ spin_unlock(&c->cs_lock);
-+}
-+
-+/**
-+ * wait_for_commit - wait for commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function sleeps until the commit operation is no longer running.
-+ */
-+static int wait_for_commit(struct ubifs_info *c)
-+{
-+ dbg_cmt("pid %d goes sleep", current->pid);
-+
-+ /*
-+ * The following sleeps if the condition is false, and will be woken
-+ * when the commit ends. It is possible, although very unlikely, that we
-+ * will wake up and see the subsequent commit running, rather than the
-+ * one we were waiting for, and go back to sleep. However, we will be
-+ * woken again, so there is no danger of sleeping forever.
-+ */
-+ wait_event(c->cmt_wq, c->cmt_state != COMMIT_RUNNING_BACKGROUND &&
-+ c->cmt_state != COMMIT_RUNNING_REQUIRED);
-+ dbg_cmt("commit finished, pid %d woke up", current->pid);
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_run_commit - run or wait for commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function runs commit and returns zero in case of success and a negative
-+ * error code in case of failure.
-+ */
-+int ubifs_run_commit(struct ubifs_info *c)
-+{
-+ int err = 0;
-+
-+ spin_lock(&c->cs_lock);
-+ if (c->cmt_state == COMMIT_BROKEN) {
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (c->cmt_state == COMMIT_RUNNING_BACKGROUND)
-+ /*
-+ * We set the commit state to 'running required' to indicate
-+ * that we want it to complete as quickly as possible.
-+ */
-+ c->cmt_state = COMMIT_RUNNING_REQUIRED;
-+
-+ if (c->cmt_state == COMMIT_RUNNING_REQUIRED) {
-+ spin_unlock(&c->cs_lock);
-+ return wait_for_commit(c);
-+ }
-+ spin_unlock(&c->cs_lock);
-+
-+ /* Ok, the commit is indeed needed */
-+
-+ down_write(&c->commit_sem);
-+ spin_lock(&c->cs_lock);
-+ /*
-+ * Since we unlocked 'c->cs_lock', the state may have changed, so
-+ * re-check it.
-+ */
-+ if (c->cmt_state == COMMIT_BROKEN) {
-+ err = -EINVAL;
-+ goto out_cmt_unlock;
-+ }
-+
-+ if (c->cmt_state == COMMIT_RUNNING_BACKGROUND)
-+ c->cmt_state = COMMIT_RUNNING_REQUIRED;
-+
-+ if (c->cmt_state == COMMIT_RUNNING_REQUIRED) {
-+ up_write(&c->commit_sem);
-+ spin_unlock(&c->cs_lock);
-+ return wait_for_commit(c);
-+ }
-+ c->cmt_state = COMMIT_RUNNING_REQUIRED;
-+ spin_unlock(&c->cs_lock);
-+
-+ err = do_commit(c);
-+ return err;
-+
-+out_cmt_unlock:
-+ up_write(&c->commit_sem);
-+out:
-+ spin_unlock(&c->cs_lock);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_recovery_commit - if needed, ensure a commit has run since recovery.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function ensures that a commit has been run since recovery and before
-+ * unmounting cleanly. Errors are ignored because in that case a subsequent
-+ * unmount will not be clean.
-+ *
-+ * The recovery needs a commit when it updates TNC directly without there being
-+ * a corresponding record of the change in the journal. In that case, if UBIFS
-+ * were to unmount cleanly without having run a commit, the TNC changes would
-+ * be lost.
-+ */
-+void ubifs_recovery_commit(struct ubifs_info *c)
-+{
-+ spin_lock(&c->cs_lock);
-+ if (!c->recovery_needs_commit ||
-+ c->cmt_state == COMMIT_BROKEN ||
-+ c->cmt_state == COMMIT_RUNNING_BACKGROUND ||
-+ c->cmt_state == COMMIT_RUNNING_REQUIRED) {
-+ spin_unlock(&c->cs_lock);
-+ return;
-+ }
-+ spin_unlock(&c->cs_lock);
-+ down_write(&c->commit_sem);
-+ spin_lock(&c->cs_lock);
-+ if (!c->recovery_needs_commit ||
-+ c->cmt_state == COMMIT_BROKEN ||
-+ c->cmt_state == COMMIT_RUNNING_BACKGROUND ||
-+ c->cmt_state == COMMIT_RUNNING_REQUIRED) {
-+ spin_unlock(&c->cs_lock);
-+ up_write(&c->commit_sem);
-+ return;
-+ }
-+ c->cmt_state = COMMIT_RUNNING_REQUIRED;
-+ spin_unlock(&c->cs_lock);
-+ do_commit(c);
-+}
-+
-+/**
-+ * ubifs_gc_should_commit - determine if it is time for GC to run commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function is called by garbage collection to determine if commit should
-+ * be run. If commit state is @COMMIT_BACKGROUND, which means that the journal
-+ * is full enough to start commit, this function returns true. It is not
-+ * absolutely necessary to commit yet, but it feels like this should be better
-+ * then to keep doing GC. This function returns %1 if GC has to initiate commit
-+ * and %0 if not.
-+ */
-+int ubifs_gc_should_commit(struct ubifs_info *c)
-+{
-+ int ret = 0;
-+
-+ spin_lock(&c->cs_lock);
-+ if (c->cmt_state == COMMIT_BACKGROUND) {
-+ dbg_cmt("commit required now");
-+ c->cmt_state = COMMIT_REQUIRED;
-+ } else
-+ dbg_cmt("commit not requested");
-+ if (c->cmt_state == COMMIT_REQUIRED)
-+ ret = 1;
-+ spin_unlock(&c->cs_lock);
-+ return ret;
-+}
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+/**
-+ * struct idx_node - hold index nodes during index tree traversal.
-+ * @list: list
-+ * @iip: index in parent (slot number of this indexing node in the parent
-+ * indexing node)
-+ * @upper_key: all keys in this indexing node have to be less or equivalent to
-+ * this key
-+ * @idx: index node (8-byte aligned because all node structures must be 8-byte
-+ * aligned)
-+ */
-+struct idx_node {
-+ struct list_head list;
-+ int iip;
-+ union ubifs_key upper_key;
-+ struct ubifs_idx_node idx __attribute__((aligned(8)));
-+};
-+
-+/**
-+ * dbg_old_index_check_init - get information for the next old index check.
-+ * @c: UBIFS file-system description object
-+ * @zroot: root of the index
-+ *
-+ * This function records information about the index that will be needed for the
-+ * next old index check i.e. 'dbg_check_old_index()'.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot)
-+{
-+ struct ubifs_idx_node *idx;
-+ int lnum, offs, len, err = 0;
-+
-+ c->old_zroot = *zroot;
-+
-+ lnum = c->old_zroot.lnum;
-+ offs = c->old_zroot.offs;
-+ len = c->old_zroot.len;
-+
-+ idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
-+ if (!idx)
-+ return -ENOMEM;
-+
-+ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
-+ if (err)
-+ goto out;
-+
-+ c->old_zroot_level = le16_to_cpu(idx->level);
-+ c->old_zroot_sqnum = le64_to_cpu(idx->ch.sqnum);
-+out:
-+ kfree(idx);
-+ return err;
-+}
-+
-+/**
-+ * dbg_check_old_index - check the old copy of the index.
-+ * @c: UBIFS file-system description object
-+ * @zroot: root of the new index
-+ *
-+ * In order to be able to recover from an unclean unmount, a complete copy of
-+ * the index must exist on flash. This is the "old" index. The commit process
-+ * must write the "new" index to flash without overwriting or destroying any
-+ * part of the old index. This function is run at commit end in order to check
-+ * that the old index does indeed exist completely intact.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
-+{
-+ int lnum, offs, len, err = 0, uninitialized_var(last_level), child_cnt;
-+ int first = 1, iip;
-+ union ubifs_key lower_key, upper_key, l_key, u_key;
-+ unsigned long long uninitialized_var(last_sqnum);
-+ struct ubifs_idx_node *idx;
-+ struct list_head list;
-+ struct idx_node *i;
-+ size_t sz;
-+
-+ if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
-+ goto out;
-+
-+ INIT_LIST_HEAD(&list);
-+
-+ sz = sizeof(struct idx_node) + ubifs_idx_node_sz(c, c->fanout) -
-+ UBIFS_IDX_NODE_SZ;
-+
-+ /* Start at the old zroot */
-+ lnum = c->old_zroot.lnum;
-+ offs = c->old_zroot.offs;
-+ len = c->old_zroot.len;
-+ iip = 0;
-+
-+ /*
-+ * Traverse the index tree preorder depth-first i.e. do a node and then
-+ * its subtrees from left to right.
-+ */
-+ while (1) {
-+ struct ubifs_branch *br;
-+
-+ /* Get the next index node */
-+ i = kmalloc(sz, GFP_NOFS);
-+ if (!i) {
-+ err = -ENOMEM;
-+ goto out_free;
-+ }
-+ i->iip = iip;
-+ /* Keep the index nodes on our path in a linked list */
-+ list_add_tail(&i->list, &list);
-+ /* Read the index node */
-+ idx = &i->idx;
-+ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
-+ if (err)
-+ goto out_free;
-+ /* Validate index node */
-+ child_cnt = le16_to_cpu(idx->child_cnt);
-+ if (child_cnt < 1 || child_cnt > c->fanout) {
-+ err = 1;
-+ goto out_dump;
-+ }
-+ if (first) {
-+ first = 0;
-+ /* Check root level and sqnum */
-+ if (le16_to_cpu(idx->level) != c->old_zroot_level) {
-+ err = 2;
-+ goto out_dump;
-+ }
-+ if (le64_to_cpu(idx->ch.sqnum) != c->old_zroot_sqnum) {
-+ err = 3;
-+ goto out_dump;
-+ }
-+ /* Set last values as though root had a parent */
-+ last_level = le16_to_cpu(idx->level) + 1;
-+ last_sqnum = le64_to_cpu(idx->ch.sqnum) + 1;
-+ key_read(c, ubifs_idx_key(c, idx), &lower_key);
-+ highest_ino_key(c, &upper_key, INUM_WATERMARK);
-+ }
-+ key_copy(c, &upper_key, &i->upper_key);
-+ if (le16_to_cpu(idx->level) != last_level - 1) {
-+ err = 3;
-+ goto out_dump;
-+ }
-+ /*
-+ * The index is always written bottom up hence a child's sqnum
-+ * is always less than the parents.
-+ */
-+ if (le64_to_cpu(idx->ch.sqnum) >= last_sqnum) {
-+ err = 4;
-+ goto out_dump;
-+ }
-+ /* Check key range */
-+ key_read(c, ubifs_idx_key(c, idx), &l_key);
-+ br = ubifs_idx_branch(c, idx, child_cnt - 1);
-+ key_read(c, &br->key, &u_key);
-+ if (keys_cmp(c, &lower_key, &l_key) > 0) {
-+ err = 5;
-+ goto out_dump;
-+ }
-+ if (keys_cmp(c, &upper_key, &u_key) < 0) {
-+ err = 6;
-+ goto out_dump;
-+ }
-+ if (keys_cmp(c, &upper_key, &u_key) == 0)
-+ if (!is_hash_key(c, &u_key)) {
-+ err = 7;
-+ goto out_dump;
-+ }
-+ /* Go to next index node */
-+ if (le16_to_cpu(idx->level) == 0) {
-+ /* At the bottom, so go up until can go right */
-+ while (1) {
-+ /* Drop the bottom of the list */
-+ list_del(&i->list);
-+ kfree(i);
-+ /* No more list means we are done */
-+ if (list_empty(&list))
-+ goto out;
-+ /* Look at the new bottom */
-+ i = list_entry(list.prev, struct idx_node,
-+ list);
-+ idx = &i->idx;
-+ /* Can we go right */
-+ if (iip + 1 < le16_to_cpu(idx->child_cnt)) {
-+ iip = iip + 1;
-+ break;
-+ } else
-+ /* Nope, so go up again */
-+ iip = i->iip;
-+ }
-+ } else
-+ /* Go down left */
-+ iip = 0;
-+ /*
-+ * We have the parent in 'idx' and now we set up for reading the
-+ * child pointed to by slot 'iip'.
-+ */
-+ last_level = le16_to_cpu(idx->level);
-+ last_sqnum = le64_to_cpu(idx->ch.sqnum);
-+ br = ubifs_idx_branch(c, idx, iip);
-+ lnum = le32_to_cpu(br->lnum);
-+ offs = le32_to_cpu(br->offs);
-+ len = le32_to_cpu(br->len);
-+ key_read(c, &br->key, &lower_key);
-+ if (iip + 1 < le16_to_cpu(idx->child_cnt)) {
-+ br = ubifs_idx_branch(c, idx, iip + 1);
-+ key_read(c, &br->key, &upper_key);
-+ } else
-+ key_copy(c, &i->upper_key, &upper_key);
-+ }
-+out:
-+ err = dbg_old_index_check_init(c, zroot);
-+ if (err)
-+ goto out_free;
-+
-+ return 0;
-+
-+out_dump:
-+ dbg_err("dumping index node (iip=%d)", i->iip);
-+ dbg_dump_node(c, idx);
-+ list_del(&i->list);
-+ kfree(i);
-+ if (!list_empty(&list)) {
-+ i = list_entry(list.prev, struct idx_node, list);
-+ dbg_err("dumping parent index node");
-+ dbg_dump_node(c, &i->idx);
-+ }
-+out_free:
-+ while (!list_empty(&list)) {
-+ i = list_entry(list.next, struct idx_node, list);
-+ list_del(&i->list);
-+ kfree(i);
-+ }
-+ ubifs_err("failed, error %d", err);
-+ if (err > 0)
-+ err = -EINVAL;
-+ return err;
-+}
-+
-+#endif /* CONFIG_UBIFS_FS_DEBUG */
---- linux-2.6.24.7.old/fs/ubifs/compat.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/compat.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,480 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy
-+ * Adrian Hunter
-+ */
-+
-+#include "ubifs.h"
-+#include
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
-+#define BYTES_PER_LINE 32
-+
-+/**
-+ * ubifs_hexdump - dump a buffer.
-+ * @ptr: the buffer to dump
-+ * @size: buffer size which must be multiple of 4 bytes
-+ */
-+void ubifs_hexdump(const void *ptr, int size)
-+{
-+ int i, k = 0, rows, columns;
-+ const uint8_t *p = ptr;
-+
-+ rows = size / BYTES_PER_LINE + size % BYTES_PER_LINE;
-+ for (i = 0; i < rows; i++) {
-+ int j;
-+
-+ cond_resched();
-+ columns = min(size - k, BYTES_PER_LINE) / 4;
-+ if (columns == 0)
-+ break;
-+ printk(KERN_DEBUG "%5d: ", i * BYTES_PER_LINE);
-+ for (j = 0; j < columns; j++) {
-+ int n, N;
-+
-+ N = size - k > 4 ? 4 : size - k;
-+ for (n = 0; n < N; n++)
-+ printk("%02x", p[k++]);
-+ printk(" ");
-+ }
-+ printk("\n");
-+ }
-+}
-+#endif /* LINUX_VERSION_CODE < 2.6.23 */
-+
-+#ifdef UBIFS_COMPAT_USE_OLD_IGET
-+struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
-+{
-+ struct inode *inode;
-+
-+ inode = iget(sb, inum);
-+ if (!inode) {
-+ make_bad_inode(inode);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ return inode;
-+}
-+
-+int validate_inode(struct ubifs_info *c, const struct inode *inode);
-+
-+void ubifs_read_inode(struct inode *inode)
-+{
-+ int err;
-+ union ubifs_key key;
-+ struct ubifs_ino_node *ino;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+
-+ dbg_gen("inode %lu", inode->i_ino);
-+ ubifs_assert(inode->i_state & I_LOCK);
-+
-+ ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
-+ if (!ino) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ ino_key_init(c, &key, inode->i_ino);
-+
-+ err = ubifs_tnc_lookup(c, &key, ino);
-+ if (err)
-+ goto out_ino;
-+
-+ inode->i_flags |= (S_NOCMTIME | S_NOATIME);
-+ inode->i_nlink = le32_to_cpu(ino->nlink);
-+ inode->i_uid = le32_to_cpu(ino->uid);
-+ inode->i_gid = le32_to_cpu(ino->gid);
-+ inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec);
-+ inode->i_atime.tv_nsec = le32_to_cpu(ino->atime_nsec);
-+ inode->i_mtime.tv_sec = (int64_t)le64_to_cpu(ino->mtime_sec);
-+ inode->i_mtime.tv_nsec = le32_to_cpu(ino->mtime_nsec);
-+ inode->i_ctime.tv_sec = (int64_t)le64_to_cpu(ino->ctime_sec);
-+ inode->i_ctime.tv_nsec = le32_to_cpu(ino->ctime_nsec);
-+ inode->i_mode = le32_to_cpu(ino->mode);
-+ inode->i_size = le64_to_cpu(ino->size);
-+
-+ ui->data_len = le32_to_cpu(ino->data_len);
-+ ui->flags = le32_to_cpu(ino->flags);
-+ ui->compr_type = le16_to_cpu(ino->compr_type);
-+ ui->creat_sqnum = le64_to_cpu(ino->creat_sqnum);
-+ ui->xattr_cnt = le32_to_cpu(ino->xattr_cnt);
-+ ui->xattr_size = le64_to_cpu(ino->xattr_size);
-+ ui->xattr_names = le32_to_cpu(ino->xattr_names);
-+
-+ err = validate_inode(c, inode);
-+ if (err)
-+ goto out_invalid;
-+
-+ switch (inode->i_mode & S_IFMT) {
-+ case S_IFREG:
-+ inode->i_mapping->a_ops = &ubifs_file_address_operations;
-+ inode->i_op = &ubifs_file_inode_operations;
-+ inode->i_fop = &ubifs_file_operations;
-+ if (ui->data_len != 0) {
-+ err = 10;
-+ goto out_invalid;
-+ }
-+ break;
-+ case S_IFDIR:
-+ inode->i_op = &ubifs_dir_inode_operations;
-+ inode->i_fop = &ubifs_dir_operations;
-+ if (ui->data_len != 0) {
-+ err = 11;
-+ goto out_invalid;
-+ }
-+ break;
-+ case S_IFLNK:
-+ inode->i_op = &ubifs_symlink_inode_operations;
-+ if (ui->data_len <= 0 || ui->data_len > UBIFS_MAX_INO_DATA) {
-+ err = 12;
-+ goto out_invalid;
-+ }
-+ ui->data = kmalloc(ui->data_len + 1, GFP_KERNEL);
-+ if (!ui->data) {
-+ err = -ENOMEM;
-+ goto out_ino;
-+ }
-+ memcpy(ui->data, ino->data, ui->data_len);
-+ ((char *)ui->data)[ui->data_len] = '\0';
-+ break;
-+ case S_IFBLK:
-+ case S_IFCHR:
-+ {
-+ dev_t rdev;
-+ union ubifs_dev_desc *dev;
-+
-+ ui->data = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
-+ if (!ui->data) {
-+ err = -ENOMEM;
-+ goto out_ino;
-+ }
-+
-+ dev = (union ubifs_dev_desc *)ino->data;
-+ if (ui->data_len == sizeof(dev->new)) {
-+ rdev = new_decode_dev(__le32_to_cpu(dev->new));
-+ } else if (ui->data_len == sizeof(dev->huge)) {
-+ rdev = huge_decode_dev(__le64_to_cpu(dev->huge));
-+ } else {
-+ err = 13;
-+ goto out_invalid;
-+ }
-+ inode->i_op = &ubifs_file_inode_operations;
-+ init_special_inode(inode, inode->i_mode, rdev);
-+ break;
-+ }
-+ case S_IFSOCK:
-+ case S_IFIFO:
-+ inode->i_op = &ubifs_file_inode_operations;
-+ init_special_inode(inode, inode->i_mode, 0);
-+ if (ui->data_len != 0) {
-+ err = 14;
-+ goto out_invalid;
-+ }
-+ break;
-+ default:
-+ err = 15;
-+ goto out_invalid;
-+ }
-+
-+ ubifs_set_inode_flags(inode);
-+ kfree(ino);
-+ return;
-+
-+out_invalid:
-+ ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err);
-+ dbg_dump_inode(c, inode);
-+ dbg_dump_node(c, ino);
-+ err = -EINVAL;
-+out_ino:
-+ kfree(ino);
-+out:
-+ ubifs_err("failed to read inode %lu, error %d", inode->i_ino, err);
-+ make_bad_inode(inode);
-+ return;
-+}
-+#endif /* UBIFS_COMPAT_USE_OLD_IGET */
-+
-+#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE
-+int ubifs_prepare_write(struct file *file, struct page *page, unsigned from,
-+ unsigned to)
-+{
-+ struct inode *inode = page->mapping->host;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
-+ struct ubifs_budget_req req;
-+ int err;
-+
-+ ubifs_assert(PageLocked(page));
-+ ubifs_assert(mutex_is_locked(&inode->i_mutex));
-+ ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
-+
-+ if (c->ro_media)
-+ return -EINVAL;
-+
-+ if (!PageUptodate(page)) {
-+ /*
-+ * The page is not loaded from the flash and has to be loaded
-+ * unless we are writing all of it.
-+ */
-+ if (from == 0 && to == PAGE_CACHE_SIZE)
-+ /*
-+ * Set the PG_checked flag to make the further code
-+ * allocate full budget, because we do not know whether
-+ * the page exists on the flash media or not.
-+ */
-+ SetPageChecked(page);
-+ else {
-+ err = do_readpage(page);
-+ if (err)
-+ return err;
-+ }
-+
-+ SetPageUptodate(page);
-+ ClearPageError(page);
-+ }
-+
-+ memset(&req, 0, sizeof(struct ubifs_budget_req));
-+ if (!PagePrivate(page)) {
-+ /*
-+ * If the PG_Checked flag is set, the page corresponds to a
-+ * hole or to a place beyond the inode. In this case we have to
-+ * budget for a new page, otherwise for a dirtied page.
-+ */
-+ if (PageChecked(page))
-+ req.new_page = 1;
-+ else
-+ req.dirtied_page = 1;
-+ } else
-+ req.locked_pg = 1;
-+
-+ if (pos > inode->i_size)
-+ /*
-+ * We are writing beyond the file which means we are going to
-+ * change inode size and make the inode dirty. And in turn,
-+ * this means we have to budget for making the inode dirty.
-+ *
-+ * Note, if the inode is already dirty,
-+ * 'ubifs_budget_inode_op()' will not allocate any budget,
-+ * but will just lock the @budg_mutex of the inode to prevent
-+ * it from becoming clean before we have changed its size,
-+ * which is going to happen in 'ubifs_write_end()'.
-+ */
-+ err = ubifs_budget_inode_op(c, inode, &req);
-+ else
-+ /*
-+ * The inode is not going to be marked as dirty by this write
-+ * operation, do do not budget for this.
-+ */
-+ err = ubifs_budget_space(c, &req);
-+
-+ return err;
-+}
-+
-+int ubifs_commit_write(struct file *file, struct page *page, unsigned from,
-+ unsigned to)
-+{
-+ struct inode *inode = page->mapping->host;
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
-+
-+ dbg_gen("ino %lu, pg %lu, offs %lld-%lld (in pg: %u-%u, %u bytes) "
-+ "flags %#lx", inode->i_ino, page->index, pos - to + from,
-+ pos, from, to, to - from, page->flags);
-+ ubifs_assert(PageUptodate(page));
-+ ubifs_assert(mutex_is_locked(&inode->i_mutex));
-+
-+ if (!PagePrivate(page)) {
-+ SetPagePrivate(page);
-+ atomic_long_inc(&c->dirty_pg_cnt);
-+ __set_page_dirty_nobuffers(page);
-+ }
-+
-+ if (pos > inode->i_size) {
-+ i_size_write(inode, pos);
-+
-+ /*
-+ * Note, we do not set 'I_DIRTY_PAGES' (which means that the
-+ * inode has dirty pages), this has been done in
-+ * '__set_page_dirty_nobuffers()'.
-+ */
-+ mark_inode_dirty_sync(inode);
-+
-+ /*
-+ * The inode has been marked dirty, unlock it. This is a bit
-+ * hacky because normally we would have to call
-+ * 'ubifs_release_ino_dirty()'. But we know there is nothing
-+ * to release because page's budget will be released
-+ * in 'ubifs_write_inode()', so just unlock the inode here for
-+ * optimization.
-+ */
-+ mutex_unlock(&ui->budg_mutex);
-+ }
-+
-+ return 0;
-+}
-+
-+#include
-+
-+#define MAX_SHRINK_RETRIES 8
-+#define MAX_GC_RETRIES 4
-+#define MAX_CMT_RETRIES 2
-+#define MAX_NOSPC_RETRIES 1
-+#define NR_TO_WRITE 16
-+
-+struct retries_info {
-+ long long prev_liability;
-+ unsigned int shrink_cnt;
-+ unsigned int shrink_retries:5;
-+ unsigned int try_gc:1;
-+ unsigned int gc_retries:4;
-+ unsigned int cmt_retries:3;
-+ unsigned int nospc_retries:1;
-+};
-+
-+static int shrink_liability(struct ubifs_info *c, int nr_to_write,
-+ int locked_pg)
-+{
-+ struct writeback_control wbc = {
-+ .sync_mode = WB_SYNC_NONE,
-+ .range_end = LLONG_MAX,
-+ .nr_to_write = nr_to_write,
-+ .skip_locked_pages = locked_pg,
-+ };
-+
-+ writeback_inodes_sb(c->vfs_sb, &wbc);
-+ dbg_budg("%ld pages were written back", nr_to_write - wbc.nr_to_write);
-+ return nr_to_write - wbc.nr_to_write;
-+}
-+
-+static int run_gc(struct ubifs_info *c)
-+{
-+ int err, lnum;
-+
-+ /* Make some free space by garbage-collecting dirty space */
-+ down_read(&c->commit_sem);
-+ lnum = ubifs_garbage_collect(c, 1);
-+ up_read(&c->commit_sem);
-+ if (lnum < 0)
-+ return lnum;
-+
-+ /* GC freed one LEB, return it to lprops */
-+ dbg_budg("GC freed LEB %d", lnum);
-+ err = ubifs_return_leb(c, lnum);
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+int ubifs_make_free_space(struct ubifs_info *c, struct retries_info *ri,
-+ int locked_pg)
-+{
-+ int err;
-+
-+ /*
-+ * If we have some dirty pages and inodes (liability), try to write
-+ * them back unless this was tried too many times without effect
-+ * already.
-+ */
-+ if (ri->shrink_retries < MAX_SHRINK_RETRIES && !ri->try_gc) {
-+ long long liability;
-+
-+ spin_lock(&c->space_lock);
-+ liability = c->budg_idx_growth + c->budg_data_growth +
-+ c->budg_dd_growth;
-+ spin_unlock(&c->space_lock);
-+
-+ if (ri->prev_liability >= liability) {
-+ /* Liability does not shrink, next time try GC then */
-+ ri->shrink_retries += 1;
-+ if (ri->gc_retries < MAX_GC_RETRIES)
-+ ri->try_gc = 1;
-+ dbg_budg("liability did not shrink: retries %d of %d",
-+ ri->shrink_retries, MAX_SHRINK_RETRIES);
-+ }
-+
-+ dbg_budg("force write-back (count %d)", ri->shrink_cnt);
-+ shrink_liability(c, NR_TO_WRITE + ri->shrink_cnt, locked_pg);
-+
-+ ri->prev_liability = liability;
-+ ri->shrink_cnt += 1;
-+ return -EAGAIN;
-+ }
-+
-+ /*
-+ * Try to run garbage collector unless it was already tried too many
-+ * times.
-+ */
-+ if (ri->gc_retries < MAX_GC_RETRIES) {
-+ ri->gc_retries += 1;
-+ dbg_budg("run GC, retries %d of %d",
-+ ri->gc_retries, MAX_GC_RETRIES);
-+
-+ ri->try_gc = 0;
-+ err = run_gc(c);
-+ if (!err)
-+ return -EAGAIN;
-+
-+ if (err == -EAGAIN) {
-+ dbg_budg("GC asked to commit");
-+ err = ubifs_run_commit(c);
-+ if (err)
-+ return err;
-+ return -EAGAIN;
-+ }
-+
-+ if (err != -ENOSPC)
-+ return err;
-+
-+ /*
-+ * GC could not make any progress. If this is the first time,
-+ * then it makes sense to try to commit, because it might make
-+ * some dirty space.
-+ */
-+ dbg_budg("GC returned -ENOSPC, retries %d",
-+ ri->nospc_retries);
-+ if (ri->nospc_retries >= MAX_NOSPC_RETRIES)
-+ return err;
-+ ri->nospc_retries += 1;
-+ }
-+
-+ /* Neither GC nor write-back helped, try to commit */
-+ if (ri->cmt_retries < MAX_CMT_RETRIES) {
-+ ri->cmt_retries += 1;
-+ dbg_budg("run commit, retries %d of %d",
-+ ri->cmt_retries, MAX_CMT_RETRIES);
-+ err = ubifs_run_commit(c);
-+ if (err)
-+ return err;
-+ return -EAGAIN;
-+ }
-+
-+ return -ENOSPC;
-+}
-+
-+#endif /* UBIFS_COMPAT_USE_OLD_PREPARE_WRITE */
-+
-+#ifdef UBIFS_COMPAT_NO_SHARED_MMAP
-+int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ return generic_file_readonly_mmap(file, vma);
-+}
-+#endif /* UBIFS_COMPAT_NO_SHARED_MMAP */
---- linux-2.6.24.7.old/fs/ubifs/compat.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/compat.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,88 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Author: Artem Bityutskiy
-+ * Adrian Hunter
-+ */
-+
-+#ifndef __UBIFS_COMPAT_H__
-+#define __UBIFS_COMPAT_H__
-+
-+#include
-+
-+struct inode;
-+struct file;
-+struct page;
-+struct ubifs_info;
-+struct retries_info;
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
-+/* iget() does not exist since 2.6.25 */
-+#define UBIFS_COMPAT_USE_OLD_IGET
-+void ubifs_read_inode(struct inode *inode);
-+#endif
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
-+/*
-+ * We have write_begin() write_end() instead of prepare_write(), commit_write()
-+ * since 2.6.24.
-+ */
-+#define UBIFS_COMPAT_USE_OLD_PREPARE_WRITE
-+#define do_readpage(page) ubifs_do_readpage(page)
-+int ubifs_do_readpage(struct page *page);
-+int ubifs_prepare_write(struct file *file, struct page *page, unsigned from,
-+ unsigned to);
-+int ubifs_commit_write(struct file *file, struct page *page, unsigned from,
-+ unsigned to);
-+int ubifs_make_free_space(struct ubifs_info *c, struct retries_info *ri,
-+ int locked_pg);
-+#define bdi_init(x) 0
-+#define bdi_destroy(x)
-+#endif
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
-+#define UBIFS_COMPAT_NO_SHRINKER
-+#define register_shrinker(x)
-+#define unregister_shrinker(x)
-+#define dbg_mempressure_init()
-+#define dbg_mempressure_exit()
-+#define set_freezable()
-+#define is_owner_or_cap(inode) \
-+ ((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER))
-+/* This is to hide slab cache interface changes - destructor was dropped */
-+#define UBIFSCOMPATNULL ,NULL
-+#else
-+#define UBIFSCOMPATNULL
-+#endif
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
-+#define uninitialized_var(x) x = x
-+/* print_hex_dump() did not exist in kernel prior to 2.6.22 */
-+#define print_hex_dump(a, b, c, f, e, buf, len, g) ubifs_hexdump(buf, len)
-+void ubifs_hexdump(const void *ptr, int size);
-+/*
-+ * Older kernel have no '->page_mkwrite()' call-back in
-+ * 'struct vm_operations_struct', so we just do not support writeble mmaps. The
-+ * support can be added if someone needs it badly, though.
-+ */
-+int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma);
-+#define UBIFS_COMPAT_NO_SHARED_MMAP
-+#endif
-+
-+
-+#endif /* !__UBIFS_COMPAT_H__ */
---- linux-2.6.24.7.old/fs/ubifs/compress.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/compress.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,253 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ * Copyright (C) 2006, 2007 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ * Zoltan Sogor
-+ */
-+
-+/*
-+ * This file provides a single place to access to compression and
-+ * decompression.
-+ */
-+
-+#include
-+#include "ubifs.h"
-+
-+/* Fake description object for the "none" compressor */
-+static struct ubifs_compressor none_compr = {
-+ .compr_type = UBIFS_COMPR_NONE,
-+ .name = "no compression",
-+ .capi_name = "",
-+};
-+
-+#ifdef CONFIG_UBIFS_FS_LZO
-+static DEFINE_MUTEX(lzo_mutex);
-+
-+static struct ubifs_compressor lzo_compr = {
-+ .compr_type = UBIFS_COMPR_LZO,
-+ .comp_mutex = &lzo_mutex,
-+ .name = "LZO",
-+ .capi_name = "lzo",
-+};
-+#else
-+static struct ubifs_compressor lzo_compr = {
-+ .compr_type = UBIFS_COMPR_LZO,
-+ .name = "LZO",
-+};
-+#endif
-+
-+#ifdef CONFIG_UBIFS_FS_ZLIB
-+static DEFINE_MUTEX(deflate_mutex);
-+static DEFINE_MUTEX(inflate_mutex);
-+
-+static struct ubifs_compressor zlib_compr = {
-+ .compr_type = UBIFS_COMPR_ZLIB,
-+ .comp_mutex = &deflate_mutex,
-+ .decomp_mutex = &inflate_mutex,
-+ .name = "zlib",
-+ .capi_name = "deflate",
-+};
-+#else
-+static struct ubifs_compressor zlib_compr = {
-+ .compr_type = UBIFS_COMPR_ZLIB,
-+ .name = "zlib",
-+};
-+#endif
-+
-+/* All UBIFS compressors */
-+struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
-+
-+/**
-+ * ubifs_compress - compress data.
-+ * @in_buf: data to compress
-+ * @in_len: length of the data to compress
-+ * @out_buf: output buffer where compressed data should be stored
-+ * @out_len: output buffer length is returned here
-+ * @compr_type: type of compression to use on enter, actually used compression
-+ * type on exit
-+ *
-+ * This function compresses input buffer @in_buf of length @in_len and stores
-+ * the result in the output buffer @out_buf and the resulting length in
-+ * @out_len. If the input buffer does not compress, it is just copied to the
-+ * @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE or if
-+ * compression error occurred.
-+ *
-+ * Note, if the input buffer was not compressed, it is copied to the output
-+ * buffer and %UBIFS_COMPR_NONE is returned in @compr_type.
-+ *
-+ * This functions returns %0 on success or a negative error code on failure.
-+ */
-+void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
-+ int *compr_type)
-+{
-+ int err;
-+ struct ubifs_compressor *compr = ubifs_compressors[*compr_type];
-+
-+ if (*compr_type == UBIFS_COMPR_NONE)
-+ goto no_compr;
-+
-+ /* If the input data is small, do not even try to compress it */
-+ if (in_len < UBIFS_MIN_COMPR_LEN)
-+ goto no_compr;
-+
-+ if (compr->comp_mutex)
-+ mutex_lock(compr->comp_mutex);
-+ err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf,
-+ out_len);
-+ if (compr->comp_mutex)
-+ mutex_unlock(compr->comp_mutex);
-+ if (unlikely(err)) {
-+ ubifs_warn("cannot compress %d bytes, compressor %s, "
-+ "error %d, leave data uncompressed",
-+ in_len, compr->name, err);
-+ goto no_compr;
-+ }
-+
-+ /*
-+ * Presently, we just require that compression results in less data,
-+ * rather than any defined minimum compression ratio or amount.
-+ */
-+ if (ALIGN(*out_len, 8) >= ALIGN(in_len, 8))
-+ goto no_compr;
-+
-+ return;
-+
-+no_compr:
-+ memcpy(out_buf, in_buf, in_len);
-+ *out_len = in_len;
-+ *compr_type = UBIFS_COMPR_NONE;
-+}
-+
-+/**
-+ * ubifs_decompress - decompress data.
-+ * @in_buf: data to decompress
-+ * @in_len: length of the data to decompress
-+ * @out_buf: output buffer where decompressed data should
-+ * @out_len: output length is returned here
-+ * @compr_type: type of compression
-+ *
-+ * This function decompresses data from buffer @in_buf into buffer @out_buf.
-+ * The length of the uncompressed data is returned in @out_len. This functions
-+ * returns %0 on success or a negative error code on failure.
-+ */
-+int ubifs_decompress(const void *in_buf, int in_len, void *out_buf,
-+ int *out_len, int compr_type)
-+{
-+ int err;
-+ struct ubifs_compressor *compr;
-+
-+ if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
-+ ubifs_err("invalid compression type %d", compr_type);
-+ return -EINVAL;
-+ }
-+
-+ compr = ubifs_compressors[compr_type];
-+
-+ if (unlikely(!compr->capi_name)) {
-+ ubifs_err("%s compression is not compiled in", compr->name);
-+ return -EINVAL;
-+ }
-+
-+ if (compr_type == UBIFS_COMPR_NONE) {
-+ memcpy(out_buf, in_buf, in_len);
-+ *out_len = in_len;
-+ return 0;
-+ }
-+
-+ if (compr->decomp_mutex)
-+ mutex_lock(compr->decomp_mutex);
-+ err = crypto_comp_decompress(compr->cc, in_buf, in_len, out_buf,
-+ out_len);
-+ if (compr->decomp_mutex)
-+ mutex_unlock(compr->decomp_mutex);
-+ if (err)
-+ ubifs_err("cannot decompress %d bytes, compressor %s, "
-+ "error %d", in_len, compr->name, err);
-+
-+ return err;
-+}
-+
-+/**
-+ * compr_init - initialize a compressor.
-+ * @compr: compressor description object
-+ *
-+ * This function initializes the requested compressor and returns zero in case
-+ * of success or a negative error code in case of failure.
-+ */
-+static int __init compr_init(struct ubifs_compressor *compr)
-+{
-+ if (compr->capi_name) {
-+ compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
-+ if (IS_ERR(compr->cc)) {
-+ ubifs_err("cannot initialize compressor %s, error %ld",
-+ compr->name, PTR_ERR(compr->cc));
-+ return PTR_ERR(compr->cc);
-+ }
-+ }
-+
-+ ubifs_compressors[compr->compr_type] = compr;
-+ return 0;
-+}
-+
-+/**
-+ * compr_exit - de-initialize a compressor.
-+ * @compr: compressor description object
-+ */
-+static void compr_exit(struct ubifs_compressor *compr)
-+{
-+ if (compr->capi_name)
-+ crypto_free_comp(compr->cc);
-+ return;
-+}
-+
-+/**
-+ * ubifs_compressors_init - initialize UBIFS compressors.
-+ *
-+ * This function initializes the compressor which were compiled in. Returns
-+ * zero in case of success and a negative error code in case of failure.
-+ */
-+int __init ubifs_compressors_init(void)
-+{
-+ int err;
-+
-+ err = compr_init(&lzo_compr);
-+ if (err)
-+ return err;
-+
-+ err = compr_init(&zlib_compr);
-+ if (err)
-+ goto out_lzo;
-+
-+ ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr;
-+ return 0;
-+
-+out_lzo:
-+ compr_exit(&lzo_compr);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_compressors_exit - de-initialize UBIFS compressors.
-+ */
-+void __exit ubifs_compressors_exit(void)
-+{
-+ compr_exit(&lzo_compr);
-+ compr_exit(&zlib_compr);
-+}
---- linux-2.6.24.7.old/fs/ubifs/debug.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/debug.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1517 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file implements most of the debugging stuff which is compiled in only
-+ * when it is enabled. But some debugging check functions are implemented in
-+ * corresponding subsystem, just because they are closely related and utilize
-+ * various local functions of those subsystems.
-+ */
-+
-+#define UBIFS_DBG_PRESERVE_UBI
-+
-+#include "ubifs.h"
-+#include
-+#include
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+DEFINE_SPINLOCK(dbg_lock);
-+
-+static char dbg_key_buf0[128];
-+static char dbg_key_buf1[128];
-+
-+unsigned int ubifs_msg_flags = UBIFS_MSG_FLAGS_DEFAULT;
-+unsigned int ubifs_chk_flags = UBIFS_CHK_FLAGS_DEFAULT;
-+unsigned int ubifs_tst_flags;
-+
-+module_param_named(debug_msgs, ubifs_msg_flags, uint, S_IRUGO | S_IWUSR);
-+module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR);
-+module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR);
-+
-+MODULE_PARM_DESC(debug_msgs, "Debug message type flags");
-+MODULE_PARM_DESC(debug_chks, "Debug check flags");
-+MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
-+
-+static const char *get_key_fmt(int fmt)
-+{
-+ switch (fmt) {
-+ case UBIFS_SIMPLE_KEY_FMT:
-+ return "simple";
-+ default:
-+ return "unknown/invalid format";
-+ }
-+}
-+
-+static const char *get_key_hash(int hash)
-+{
-+ switch (hash) {
-+ case UBIFS_KEY_HASH_R5:
-+ return "R5";
-+ case UBIFS_KEY_HASH_TEST:
-+ return "test";
-+ default:
-+ return "unknown/invalid name hash";
-+ }
-+}
-+
-+static const char *get_key_type(int type)
-+{
-+ switch (type) {
-+ case UBIFS_INO_KEY:
-+ return "inode";
-+ case UBIFS_DENT_KEY:
-+ return "direntry";
-+ case UBIFS_XENT_KEY:
-+ return "xentry";
-+ case UBIFS_DATA_KEY:
-+ return "data";
-+ case UBIFS_TRUN_KEY:
-+ return "truncate";
-+ default:
-+ return "unknown/invalid key";
-+ }
-+}
-+
-+static void sprintf_key(const struct ubifs_info *c, const union ubifs_key *key,
-+ char *buffer)
-+{
-+ char *p = buffer;
-+ int type = key_type(c, key);
-+
-+ if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) {
-+ switch (type) {
-+ case UBIFS_INO_KEY:
-+ sprintf(p, "(%lu, %s)", key_ino(c, key),
-+ get_key_type(type));
-+ break;
-+ case UBIFS_DENT_KEY:
-+ case UBIFS_XENT_KEY:
-+ sprintf(p, "(%lu, %s, %#08x)", key_ino(c, key),
-+ get_key_type(type), key_hash(c, key));
-+ break;
-+ case UBIFS_DATA_KEY:
-+ sprintf(p, "(%lu, %s, %u)", key_ino(c, key),
-+ get_key_type(type), key_block(c, key));
-+ break;
-+ case UBIFS_TRUN_KEY:
-+ sprintf(p, "(%lu, %s)",
-+ key_ino(c, key), get_key_type(type));
-+ break;
-+ default:
-+ sprintf(p, "(bad key type: %#08x, %#08x)",
-+ key->u32[0], key->u32[1]);
-+ }
-+ } else
-+ sprintf(p, "bad key format %d", c->key_fmt);
-+}
-+
-+const char *dbg_key_str0(const struct ubifs_info *c, const union ubifs_key *key)
-+{
-+ /* dbg_lock must be held */
-+ sprintf_key(c, key, dbg_key_buf0);
-+ return dbg_key_buf0;
-+}
-+
-+const char *dbg_key_str1(const struct ubifs_info *c, const union ubifs_key *key)
-+{
-+ /* dbg_lock must be held */
-+ sprintf_key(c, key, dbg_key_buf1);
-+ return dbg_key_buf1;
-+}
-+
-+const char *dbg_ntype(int type)
-+{
-+ switch (type) {
-+ case UBIFS_PAD_NODE:
-+ return "padding node";
-+ case UBIFS_SB_NODE:
-+ return "superblock node";
-+ case UBIFS_MST_NODE:
-+ return "master node";
-+ case UBIFS_REF_NODE:
-+ return "reference node";
-+ case UBIFS_INO_NODE:
-+ return "inode node";
-+ case UBIFS_DENT_NODE:
-+ return "direntry node";
-+ case UBIFS_XENT_NODE:
-+ return "xentry node";
-+ case UBIFS_DATA_NODE:
-+ return "data node";
-+ case UBIFS_TRUN_NODE:
-+ return "truncate node";
-+ case UBIFS_IDX_NODE:
-+ return "indexing node";
-+ case UBIFS_CS_NODE:
-+ return "commit start node";
-+ case UBIFS_ORPH_NODE:
-+ return "orphan node";
-+ default:
-+ return "unknown node";
-+ }
-+}
-+
-+static const char *dbg_gtype(int type)
-+{
-+ switch (type) {
-+ case UBIFS_NO_NODE_GROUP:
-+ return "no node group";
-+ case UBIFS_IN_NODE_GROUP:
-+ return "in node group";
-+ case UBIFS_LAST_OF_NODE_GROUP:
-+ return "last of node group";
-+ default:
-+ return "unknown";
-+ }
-+}
-+
-+const char *dbg_cstate(int cmt_state)
-+{
-+ switch (cmt_state) {
-+ case COMMIT_RESTING:
-+ return "commit resting";
-+ case COMMIT_BACKGROUND:
-+ return "background commit requested";
-+ case COMMIT_REQUIRED:
-+ return "commit required";
-+ case COMMIT_RUNNING_BACKGROUND:
-+ return "BACKGROUND commit running";
-+ case COMMIT_RUNNING_REQUIRED:
-+ return "commit running and required";
-+ case COMMIT_BROKEN:
-+ return "broken commit";
-+ default:
-+ return "unknown commit state";
-+ }
-+}
-+
-+static void dump_ch(const struct ubifs_ch *ch)
-+{
-+ printk(KERN_DEBUG "\tmagic %#x\n", le32_to_cpu(ch->magic));
-+ printk(KERN_DEBUG "\tcrc %#x\n", le32_to_cpu(ch->crc));
-+ printk(KERN_DEBUG "\tnode_type %d (%s)\n", ch->node_type,
-+ dbg_ntype(ch->node_type));
-+ printk(KERN_DEBUG "\tgroup_type %d (%s)\n", ch->group_type,
-+ dbg_gtype(ch->group_type));
-+ printk(KERN_DEBUG "\tsqnum %llu\n",
-+ (unsigned long long)le64_to_cpu(ch->sqnum));
-+ printk(KERN_DEBUG "\tlen %u\n", le32_to_cpu(ch->len));
-+}
-+
-+void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode)
-+{
-+ const struct ubifs_inode *ui = ubifs_inode(inode);
-+
-+ printk(KERN_DEBUG "inode %lu\n", inode->i_ino);
-+ printk(KERN_DEBUG "size %llu\n",
-+ (unsigned long long)i_size_read(inode));
-+ printk(KERN_DEBUG "nlink %u\n", inode->i_nlink);
-+ printk(KERN_DEBUG "uid %u\n", (unsigned int)inode->i_uid);
-+ printk(KERN_DEBUG "gid %u\n", (unsigned int)inode->i_gid);
-+ printk(KERN_DEBUG "atime %u.%u\n",
-+ (unsigned int)inode->i_atime.tv_sec,
-+ (unsigned int)inode->i_atime.tv_nsec);
-+ printk(KERN_DEBUG "mtime %u.%u\n",
-+ (unsigned int)inode->i_mtime.tv_sec,
-+ (unsigned int)inode->i_mtime.tv_nsec);
-+ printk(KERN_DEBUG "ctime %u.%u\n",
-+ (unsigned int)inode->i_ctime.tv_sec,
-+ (unsigned int)inode->i_ctime.tv_nsec);
-+ printk(KERN_DEBUG "creat_sqnum %llu\n", ui->creat_sqnum);
-+ printk(KERN_DEBUG "xattr_size %lld\n", ui->xattr_size);
-+ printk(KERN_DEBUG "xattr_cnt %d\n", ui->xattr_cnt);
-+ printk(KERN_DEBUG "xattr_names %d\n", ui->xattr_names);
-+ printk(KERN_DEBUG "dirty %u\n", ui->dirty);
-+ printk(KERN_DEBUG "xattr %u\n", ui->xattr);
-+ printk(KERN_DEBUG "flags %d\n", ui->flags);
-+ printk(KERN_DEBUG "compr_type %d\n", ui->compr_type);
-+ printk(KERN_DEBUG "data_len %d\n", ui->data_len);
-+}
-+
-+void dbg_dump_node(const struct ubifs_info *c, const void *node)
-+{
-+ int i, n;
-+ union ubifs_key key;
-+ const struct ubifs_ch *ch = node;
-+
-+ if (dbg_failure_mode)
-+ return;
-+
-+ /* If the magic is incorrect, just hexdump the first bytes */
-+ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) {
-+ printk(KERN_DEBUG "Not a node, first %zu bytes:", UBIFS_CH_SZ);
-+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-+ (void *)node, UBIFS_CH_SZ, 1);
-+ return;
-+ }
-+
-+ spin_lock(&dbg_lock);
-+ dump_ch(node);
-+
-+ switch (ch->node_type) {
-+ case UBIFS_PAD_NODE:
-+ {
-+ const struct ubifs_pad_node *pad = node;
-+
-+ printk(KERN_DEBUG "\tpad_len %u\n",
-+ le32_to_cpu(pad->pad_len));
-+ break;
-+ }
-+ case UBIFS_SB_NODE:
-+ {
-+ const struct ubifs_sb_node *sup = node;
-+ unsigned int sup_flags = le32_to_cpu(sup->flags);
-+
-+ printk(KERN_DEBUG "\tkey_hash %d (%s)\n",
-+ (int)sup->key_hash, get_key_hash(sup->key_hash));
-+ printk(KERN_DEBUG "\tkey_fmt %d (%s)\n",
-+ (int)sup->key_fmt, get_key_fmt(sup->key_fmt));
-+ printk(KERN_DEBUG "\tflags %#x\n", sup_flags);
-+ printk(KERN_DEBUG "\t big_lpt %u\n",
-+ !!(sup_flags & UBIFS_FLG_BIGLPT));
-+ printk(KERN_DEBUG "\tmin_io_size %u\n",
-+ le32_to_cpu(sup->min_io_size));
-+ printk(KERN_DEBUG "\tleb_size %u\n",
-+ le32_to_cpu(sup->leb_size));
-+ printk(KERN_DEBUG "\tleb_cnt %u\n",
-+ le32_to_cpu(sup->leb_cnt));
-+ printk(KERN_DEBUG "\tmax_leb_cnt %u\n",
-+ le32_to_cpu(sup->max_leb_cnt));
-+ printk(KERN_DEBUG "\tmax_bud_bytes %llu\n",
-+ (unsigned long long)le64_to_cpu(sup->max_bud_bytes));
-+ printk(KERN_DEBUG "\tlog_lebs %u\n",
-+ le32_to_cpu(sup->log_lebs));
-+ printk(KERN_DEBUG "\tlpt_lebs %u\n",
-+ le32_to_cpu(sup->lpt_lebs));
-+ printk(KERN_DEBUG "\torph_lebs %u\n",
-+ le32_to_cpu(sup->orph_lebs));
-+ printk(KERN_DEBUG "\tjhead_cnt %u\n",
-+ le32_to_cpu(sup->jhead_cnt));
-+ printk(KERN_DEBUG "\tfanout %u\n",
-+ le32_to_cpu(sup->fanout));
-+ printk(KERN_DEBUG "\tlsave_cnt %u\n",
-+ le32_to_cpu(sup->lsave_cnt));
-+ printk(KERN_DEBUG "\tdefault_compr %u\n",
-+ (int)le16_to_cpu(sup->default_compr));
-+ printk(KERN_DEBUG "\trp_size %llu\n",
-+ (unsigned long long)le64_to_cpu(sup->rp_size));
-+ printk(KERN_DEBUG "\trp_uid %u\n",
-+ le32_to_cpu(sup->rp_uid));
-+ printk(KERN_DEBUG "\trp_gid %u\n",
-+ le32_to_cpu(sup->rp_gid));
-+ printk(KERN_DEBUG "\tfmt_version %u\n",
-+ le32_to_cpu(sup->fmt_version));
-+ printk(KERN_DEBUG "\ttime_gran %u\n",
-+ le32_to_cpu(sup->time_gran));
-+ break;
-+ }
-+ case UBIFS_MST_NODE:
-+ {
-+ const struct ubifs_mst_node *mst = node;
-+
-+ printk(KERN_DEBUG "\thighest_inum %llu\n",
-+ (unsigned long long)le64_to_cpu(mst->highest_inum));
-+ printk(KERN_DEBUG "\tcommit number %llu\n",
-+ (unsigned long long)le64_to_cpu(mst->cmt_no));
-+ printk(KERN_DEBUG "\tflags %#x\n",
-+ le32_to_cpu(mst->flags));
-+ printk(KERN_DEBUG "\tlog_lnum %u\n",
-+ le32_to_cpu(mst->log_lnum));
-+ printk(KERN_DEBUG "\troot_lnum %u\n",
-+ le32_to_cpu(mst->root_lnum));
-+ printk(KERN_DEBUG "\troot_offs %u\n",
-+ le32_to_cpu(mst->root_offs));
-+ printk(KERN_DEBUG "\troot_len %u\n",
-+ le32_to_cpu(mst->root_len));
-+ printk(KERN_DEBUG "\tgc_lnum %u\n",
-+ le32_to_cpu(mst->gc_lnum));
-+ printk(KERN_DEBUG "\tihead_lnum %u\n",
-+ le32_to_cpu(mst->ihead_lnum));
-+ printk(KERN_DEBUG "\tihead_offs %u\n",
-+ le32_to_cpu(mst->ihead_offs));
-+ printk(KERN_DEBUG "\tindex_size %u\n",
-+ le32_to_cpu(mst->index_size));
-+ printk(KERN_DEBUG "\tlpt_lnum %u\n",
-+ le32_to_cpu(mst->lpt_lnum));
-+ printk(KERN_DEBUG "\tlpt_offs %u\n",
-+ le32_to_cpu(mst->lpt_offs));
-+ printk(KERN_DEBUG "\tnhead_lnum %u\n",
-+ le32_to_cpu(mst->nhead_lnum));
-+ printk(KERN_DEBUG "\tnhead_offs %u\n",
-+ le32_to_cpu(mst->nhead_offs));
-+ printk(KERN_DEBUG "\tltab_lnum %u\n",
-+ le32_to_cpu(mst->ltab_lnum));
-+ printk(KERN_DEBUG "\tltab_offs %u\n",
-+ le32_to_cpu(mst->ltab_offs));
-+ printk(KERN_DEBUG "\tlsave_lnum %u\n",
-+ le32_to_cpu(mst->lsave_lnum));
-+ printk(KERN_DEBUG "\tlsave_offs %u\n",
-+ le32_to_cpu(mst->lsave_offs));
-+ printk(KERN_DEBUG "\tlscan_lnum %u\n",
-+ le32_to_cpu(mst->lscan_lnum));
-+ printk(KERN_DEBUG "\tleb_cnt %u\n",
-+ le32_to_cpu(mst->leb_cnt));
-+ printk(KERN_DEBUG "\tempty_lebs %u\n",
-+ le32_to_cpu(mst->empty_lebs));
-+ printk(KERN_DEBUG "\tidx_lebs %u\n",
-+ le32_to_cpu(mst->idx_lebs));
-+ printk(KERN_DEBUG "\ttotal_free %llu\n",
-+ (unsigned long long)le64_to_cpu(mst->total_free));
-+ printk(KERN_DEBUG "\ttotal_dirty %llu\n",
-+ (unsigned long long)le64_to_cpu(mst->total_dirty));
-+ printk(KERN_DEBUG "\ttotal_used %llu\n",
-+ (unsigned long long)le64_to_cpu(mst->total_used));
-+ printk(KERN_DEBUG "\ttotal_dead %llu\n",
-+ (unsigned long long)le64_to_cpu(mst->total_dead));
-+ printk(KERN_DEBUG "\ttotal_dark %llu\n",
-+ (unsigned long long)le64_to_cpu(mst->total_dark));
-+ break;
-+ }
-+ case UBIFS_REF_NODE:
-+ {
-+ const struct ubifs_ref_node *ref = node;
-+
-+ printk(KERN_DEBUG "\tlnum %u\n",
-+ le32_to_cpu(ref->lnum));
-+ printk(KERN_DEBUG "\toffs %u\n",
-+ le32_to_cpu(ref->offs));
-+ printk(KERN_DEBUG "\tjhead %u\n",
-+ le32_to_cpu(ref->jhead));
-+ break;
-+ }
-+ case UBIFS_INO_NODE:
-+ {
-+ const struct ubifs_ino_node *ino = node;
-+
-+ key_read(c, &ino->key, &key);
-+ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
-+ printk(KERN_DEBUG "\tsize %llu\n",
-+ (unsigned long long)le64_to_cpu(ino->size));
-+ printk(KERN_DEBUG "\tnlink %u\n",
-+ le32_to_cpu(ino->nlink));
-+ printk(KERN_DEBUG "\tatime %lld.%u\n",
-+ (long long)le64_to_cpu(ino->atime_sec),
-+ le32_to_cpu(ino->atime_nsec));
-+ printk(KERN_DEBUG "\tmtime %lld.%u\n",
-+ (long long)le64_to_cpu(ino->mtime_sec),
-+ le32_to_cpu(ino->mtime_nsec));
-+ printk(KERN_DEBUG "\tctime %lld.%u\n",
-+ (long long)le64_to_cpu(ino->ctime_sec),
-+ le32_to_cpu(ino->ctime_nsec));
-+ printk(KERN_DEBUG "\tuid %u\n",
-+ le32_to_cpu(ino->uid));
-+ printk(KERN_DEBUG "\tgid %u\n",
-+ le32_to_cpu(ino->gid));
-+ printk(KERN_DEBUG "\tmode %u\n",
-+ le32_to_cpu(ino->mode));
-+ printk(KERN_DEBUG "\tflags %#x\n",
-+ le32_to_cpu(ino->flags));
-+ printk(KERN_DEBUG "\txattr_cnt %u\n",
-+ le32_to_cpu(ino->xattr_cnt));
-+ printk(KERN_DEBUG "\txattr_size %llu\n",
-+ (unsigned long long)le64_to_cpu(ino->xattr_size));
-+ printk(KERN_DEBUG "\txattr_names %u\n",
-+ le32_to_cpu(ino->xattr_names));
-+ printk(KERN_DEBUG "\tcompr_type %#x\n",
-+ (int)le16_to_cpu(ino->compr_type));
-+ printk(KERN_DEBUG "\tdata len %u\n",
-+ le32_to_cpu(ino->data_len));
-+ break;
-+ }
-+ case UBIFS_DENT_NODE:
-+ case UBIFS_XENT_NODE:
-+ {
-+ const struct ubifs_dent_node *dent = node;
-+ int nlen = le16_to_cpu(dent->nlen);
-+
-+ key_read(c, &dent->key, &key);
-+ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
-+ printk(KERN_DEBUG "\tinum %llu\n",
-+ (unsigned long long)le64_to_cpu(dent->inum));
-+ printk(KERN_DEBUG "\ttype %d\n", (int)dent->type);
-+ printk(KERN_DEBUG "\tnlen %d\n", nlen);
-+ printk(KERN_DEBUG "\tname ");
-+
-+ if (nlen > UBIFS_MAX_NLEN) {
-+ nlen = UBIFS_MAX_NLEN;
-+ printk(KERN_DEBUG "\tWarning! Node is corrupted\n");
-+ }
-+
-+ for (i = 0; i < nlen && dent->name[i]; i++)
-+ printk("%c", dent->name[i]);
-+ printk("\n");
-+
-+ break;
-+ }
-+ case UBIFS_DATA_NODE:
-+ {
-+ const struct ubifs_data_node *dn = node;
-+ int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ;
-+
-+ key_read(c, &dn->key, &key);
-+ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
-+ printk(KERN_DEBUG "\tsize %u\n",
-+ le32_to_cpu(dn->size));
-+ printk(KERN_DEBUG "\tcompr_typ %d\n",
-+ (int)le16_to_cpu(dn->compr_type));
-+ printk(KERN_DEBUG "\tdata size %d\n",
-+ dlen);
-+ printk(KERN_DEBUG "\tdata:\n");
-+ print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET, 32, 1,
-+ (void *)&dn->data, dlen, 0);
-+ break;
-+ }
-+ case UBIFS_TRUN_NODE:
-+ {
-+ const struct ubifs_trun_node *trun = node;
-+
-+ key_read(c, &trun->key, &key);
-+ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
-+ printk(KERN_DEBUG "\told_size %llu\n",
-+ (unsigned long long)le64_to_cpu(trun->old_size));
-+ printk(KERN_DEBUG "\tnew_size %llu\n",
-+ (unsigned long long)le64_to_cpu(trun->new_size));
-+ break;
-+ }
-+ case UBIFS_IDX_NODE:
-+ {
-+ const struct ubifs_idx_node *idx = node;
-+
-+ n = le16_to_cpu(idx->child_cnt);
-+ printk(KERN_DEBUG "\tchild_cnt %d\n", n);
-+ printk(KERN_DEBUG "\tlevel %d\n",
-+ (int)le16_to_cpu(idx->level));
-+ printk(KERN_DEBUG "\tBranches:\n");
-+
-+ for (i = 0; i < n && i < c->fanout - 1; i++) {
-+ const struct ubifs_branch *br;
-+
-+ br = ubifs_idx_branch(c, idx, i);
-+ key_read(c, &br->key, &key);
-+ printk(KERN_DEBUG "\t%d: LEB %d:%d len %d key %s\n",
-+ i, le32_to_cpu(br->lnum), le32_to_cpu(br->offs),
-+ le32_to_cpu(br->len), DBGKEY(&key));
-+ }
-+ break;
-+ }
-+ case UBIFS_CS_NODE:
-+ break;
-+ case UBIFS_ORPH_NODE:
-+ {
-+ const struct ubifs_orph_node *orph = node;
-+
-+ printk(KERN_DEBUG "\tcommit number %llu\n",
-+ (unsigned long long)
-+ le64_to_cpu(orph->cmt_no) & LLONG_MAX);
-+ printk(KERN_DEBUG "\tlast node flag %llu\n",
-+ (unsigned long long)(le64_to_cpu(orph->cmt_no)) >> 63);
-+ n = (le32_to_cpu(ch->len) - UBIFS_ORPH_NODE_SZ) >> 3;
-+ printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n);
-+ for (i = 0; i < n; i++)
-+ printk(KERN_DEBUG "\t ino %llu\n",
-+ le64_to_cpu(orph->inos[i]));
-+ break;
-+ }
-+ default:
-+ printk(KERN_DEBUG "node type %d was not recognized\n",
-+ (int)ch->node_type);
-+ }
-+ spin_unlock(&dbg_lock);
-+}
-+
-+void dbg_dump_budget_req(const struct ubifs_budget_req *req)
-+{
-+ spin_lock(&dbg_lock);
-+ printk(KERN_DEBUG "Budgeting request: new_ino %d, dirtied_ino %d\n",
-+ req->new_ino, req->dirtied_ino);
-+ printk(KERN_DEBUG "\tnew_ino_d %d, dirtied_ino_d %d\n",
-+ req->new_ino_d, req->dirtied_ino_d);
-+ printk(KERN_DEBUG "\tnew_page %d, dirtied_page %d\n",
-+ req->new_page, req->dirtied_page);
-+ printk(KERN_DEBUG "\tnew_dent %d, mod_dent %d\n",
-+ req->new_dent, req->mod_dent);
-+/* TODO: remove compatibility stuff as late as possible */
-+#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE
-+ printk(KERN_DEBUG "\tlocked_pg %d idx_growth %d\n",
-+ req->locked_pg, req->idx_growth);
-+#else
-+ printk(KERN_DEBUG "\tidx_growth %d\n", req->idx_growth);
-+#endif
-+ printk(KERN_DEBUG "\tdata_growth %d dd_growth %d\n",
-+ req->data_growth, req->dd_growth);
-+ spin_unlock(&dbg_lock);
-+}
-+
-+void dbg_dump_lstats(const struct ubifs_lp_stats *lst)
-+{
-+ spin_lock(&dbg_lock);
-+ printk(KERN_DEBUG "Lprops statistics: empty_lebs %d, idx_lebs %d\n",
-+ lst->empty_lebs, lst->idx_lebs);
-+ printk(KERN_DEBUG "\ttaken_empty_lebs %d, total_free %lld, "
-+ "total_dirty %lld\n", lst->taken_empty_lebs, lst->total_free,
-+ lst->total_dirty);
-+ printk(KERN_DEBUG "\ttotal_used %lld, total_dark %lld, "
-+ "total_dead %lld\n", lst->total_used, lst->total_dark,
-+ lst->total_dead);
-+ spin_unlock(&dbg_lock);
-+}
-+
-+void dbg_dump_budg(struct ubifs_info *c)
-+{
-+ int i;
-+ struct rb_node *rb;
-+ struct ubifs_bud *bud;
-+ struct ubifs_gced_idx_leb *idx_gc;
-+
-+ spin_lock(&dbg_lock);
-+ printk(KERN_DEBUG "Budgeting info: budg_data_growth %lld, "
-+ "budg_dd_growth %lld, budg_idx_growth %lld\n",
-+ c->budg_data_growth, c->budg_dd_growth, c->budg_idx_growth);
-+ printk(KERN_DEBUG "\tdata budget sum %lld, total budget sum %lld, "
-+ "freeable_cnt %d\n", c->budg_data_growth + c->budg_dd_growth,
-+ c->budg_data_growth + c->budg_dd_growth + c->budg_idx_growth,
-+ c->freeable_cnt);
-+ printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %lld, "
-+ "calc_idx_sz %lld, idx_gc_cnt %d\n", c->min_idx_lebs,
-+ c->old_idx_sz, c->calc_idx_sz, c->idx_gc_cnt);
-+ printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_ino_cnt %ld, "
-+ "dirty_zn_cnt %ld, clean_zn_cnt %ld\n",
-+ atomic_long_read(&c->dirty_pg_cnt),
-+ atomic_long_read(&c->dirty_ino_cnt),
-+ atomic_long_read(&c->dirty_zn_cnt),
-+ atomic_long_read(&c->clean_zn_cnt));
-+ printk(KERN_DEBUG "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n",
-+ c->dark_wm, c->dead_wm, c->max_idx_node_sz);
-+ printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n",
-+ c->gc_lnum, c->ihead_lnum);
-+ for (i = 0; i < c->jhead_cnt; i++)
-+ printk(KERN_DEBUG "\tjhead %d\t LEB %d\n",
-+ c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum);
-+ for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) {
-+ bud = rb_entry(rb, struct ubifs_bud, rb);
-+ printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum);
-+ }
-+ list_for_each_entry(bud, &c->old_buds, list)
-+ printk(KERN_DEBUG "\told bud LEB %d\n", bud->lnum);
-+ list_for_each_entry(idx_gc, &c->idx_gc, list)
-+ printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n",
-+ idx_gc->lnum, idx_gc->unmap);
-+ printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state);
-+ spin_unlock(&dbg_lock);
-+}
-+
-+void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
-+{
-+ printk(KERN_DEBUG "LEB %d lprops: free %d, dirty %d (used %d), "
-+ "flags %#x\n", lp->lnum, lp->free, lp->dirty,
-+ c->leb_size - lp->free - lp->dirty, lp->flags);
-+}
-+
-+void dbg_dump_lprops(struct ubifs_info *c)
-+{
-+ int lnum, err;
-+ struct ubifs_lprops lp;
-+ struct ubifs_lp_stats lst;
-+
-+ printk(KERN_DEBUG "Dumping LEB properties\n");
-+ ubifs_get_lp_stats(c, &lst);
-+ dbg_dump_lstats(&lst);
-+
-+ for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) {
-+ err = ubifs_read_one_lp(c, lnum, &lp);
-+ if (err)
-+ ubifs_err("cannot read lprops for LEB %d", lnum);
-+
-+ dbg_dump_lprop(c, &lp);
-+ }
-+}
-+
-+void dbg_dump_leb(const struct ubifs_info *c, int lnum)
-+{
-+ struct ubifs_scan_leb *sleb;
-+ struct ubifs_scan_node *snod;
-+
-+ if (dbg_failure_mode)
-+ return;
-+
-+ printk(KERN_DEBUG "Dumping LEB %d\n", lnum);
-+
-+ sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
-+ if (IS_ERR(sleb)) {
-+ ubifs_err("scan error %d", (int)PTR_ERR(sleb));
-+ return;
-+ }
-+
-+ printk(KERN_DEBUG "LEB %d has %d nodes ending at %d\n", lnum,
-+ sleb->nodes_cnt, sleb->endpt);
-+
-+ list_for_each_entry(snod, &sleb->nodes, list) {
-+ cond_resched();
-+ printk(KERN_DEBUG "Dumping node at LEB %d:%d len %d\n", lnum,
-+ snod->offs, snod->len);
-+ dbg_dump_node(c, snod->node);
-+ }
-+
-+ ubifs_scan_destroy(sleb);
-+ return;
-+}
-+
-+void dbg_dump_znode(const struct ubifs_info *c,
-+ const struct ubifs_znode *znode)
-+{
-+ int n;
-+ const struct ubifs_zbranch *zbr;
-+
-+ spin_lock(&dbg_lock);
-+ if (znode->parent)
-+ zbr = &znode->parent->zbranch[znode->iip];
-+ else
-+ zbr = &c->zroot;
-+
-+ printk(KERN_DEBUG "znode %p, LEB %d:%d len %d parent %p iip %d level %d"
-+ " child_cnt %d flags %lx\n", znode, zbr->lnum, zbr->offs,
-+ zbr->len, znode->parent, znode->iip, znode->level,
-+ znode->child_cnt, znode->flags);
-+
-+ if (znode->child_cnt <= 0 || znode->child_cnt > c->fanout) {
-+ spin_unlock(&dbg_lock);
-+ return;
-+ }
-+
-+ printk(KERN_DEBUG "zbranches:\n");
-+ for (n = 0; n < znode->child_cnt; n++) {
-+ cond_resched();
-+
-+ zbr = &znode->zbranch[n];
-+ if (znode->level > 0)
-+ printk(KERN_DEBUG "\t%d: znode %p LEB %d:%d len %d key "
-+ "%s\n", n, zbr->znode, zbr->lnum,
-+ zbr->offs, zbr->len,
-+ DBGKEY(&zbr->key));
-+ else
-+ printk(KERN_DEBUG "\t%d: LNC %p LEB %d:%d len %d key "
-+ "%s\n", n, zbr->znode, zbr->lnum,
-+ zbr->offs, zbr->len,
-+ DBGKEY(&zbr->key));
-+ }
-+ spin_unlock(&dbg_lock);
-+}
-+
-+void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
-+{
-+ int i;
-+
-+ printk(KERN_DEBUG "Dumping heap cat %d (%d elements)\n",
-+ cat, heap->cnt);
-+ for (i = 0; i < heap->cnt; i++) {
-+ struct ubifs_lprops *lprops = heap->arr[i];
-+
-+ printk(KERN_DEBUG "\t%d. LEB %d hpos %d free %d dirty %d "
-+ "flags %d\n", i, lprops->lnum, lprops->hpos,
-+ lprops->free, lprops->dirty, lprops->flags);
-+ }
-+}
-+
-+void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
-+ struct ubifs_nnode *parent, int iip)
-+{
-+ int i;
-+
-+ printk(KERN_DEBUG "Dumping pnode:\n");
-+ printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n",
-+ (size_t)pnode, (size_t)parent, (size_t)pnode->cnext);
-+ printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n",
-+ pnode->flags, iip, pnode->level, pnode->num);
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ struct ubifs_lprops *lp = &pnode->lprops[i];
-+
-+ printk(KERN_DEBUG "\t%d: free %d dirty %d flags %d lnum %d\n",
-+ i, lp->free, lp->dirty, lp->flags, lp->lnum);
-+ }
-+}
-+
-+void dbg_dump_tnc(struct ubifs_info *c)
-+{
-+ struct ubifs_znode *znode;
-+ int level;
-+
-+ printk(KERN_DEBUG "\n");
-+ printk(KERN_DEBUG "Dumping the TNC tree\n");
-+ znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL);
-+ level = znode->level;
-+ printk(KERN_DEBUG "== Level %d ==\n", level);
-+ while (znode) {
-+ if (level != znode->level) {
-+ level = znode->level;
-+ printk(KERN_DEBUG "== Level %d ==\n", level);
-+ }
-+ dbg_dump_znode(c, znode);
-+ znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode);
-+ }
-+
-+ printk(KERN_DEBUG "\n");
-+}
-+
-+/*
-+ * dbg_check_dir - check directory inode size.
-+ * @c: UBIFS file-system description object
-+ * @dir: the directory to calculate size for
-+ * @size: the result is returned here
-+ *
-+ * This function makes sure that directory size is correct. Returns zero
-+ * in case of success and a negative error code in case of failure.
-+ *
-+ * Note, it is good idea to make sure the @dir->i_mutex is locked before
-+ * calling this function.
-+ */
-+int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir)
-+{
-+ union ubifs_key key;
-+ struct ubifs_dent_node *dent, *pdent = NULL;
-+ struct qstr nm = { .name = NULL };
-+ loff_t size = UBIFS_INO_NODE_SZ;
-+
-+ if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
-+ return 0;
-+
-+ if (!S_ISDIR(dir->i_mode))
-+ return 0;
-+
-+ lowest_dent_key(c, &key, dir->i_ino);
-+ while (1) {
-+ int err;
-+
-+ dent = ubifs_tnc_next_ent(c, &key, &nm);
-+ if (IS_ERR(dent)) {
-+ err = PTR_ERR(dent);
-+ if (err == -ENOENT)
-+ break;
-+ return err;
-+ }
-+
-+ nm.name = dent->name;
-+ nm.len = le16_to_cpu(dent->nlen);
-+ size += CALC_DENT_SIZE(nm.len);
-+ kfree(pdent);
-+ pdent = dent;
-+ key_read(c, &dent->key, &key);
-+ }
-+
-+ kfree(pdent);
-+
-+ if (i_size_read(dir) != size) {
-+ ubifs_err("bad directory dir %lu size %llu, "
-+ "calculated %llu", dir->i_ino,
-+ (unsigned long long)i_size_read(dir),
-+ (unsigned long long)size);
-+ dump_stack();
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * dbg_check_key_order - make sure that colliding keys are properly ordered.
-+ * @c: UBIFS file-system description object
-+ * @zbr1: first zbranch
-+ * @zbr1: following zbranch
-+ *
-+ * In UBIFS indexing B-tree colliding keys has to be sorted in binary order of
-+ * names of the direntries/xentries which are referred by the keys. This
-+ * function reads direntries/xentries referred by @zbr1 and @zbr2 and makes
-+ * sure the name of direntry/xentry referred by @zbr1 is less than
-+ * direntry/xentry referred by @zbr2. Returns zero if this is true, %1 if not,
-+ * and a negative error code in case of failure.
-+ */
-+static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
-+ struct ubifs_zbranch *zbr2)
-+{
-+ int err, nlen1, nlen2, cmp;
-+ struct ubifs_dent_node *dent1, *dent2;
-+ union ubifs_key key;
-+
-+ ubifs_assert(!keys_cmp(c, &zbr1->key, &zbr2->key));
-+ dent1 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
-+ if (!dent1)
-+ return -ENOMEM;
-+ dent2 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
-+ if (!dent2) {
-+ err = -ENOMEM;
-+ goto out_free;
-+ }
-+
-+ err = dbg_read_leaf_nolock(c, zbr1, dent1);
-+ if (err)
-+ goto out_free;
-+ err = ubifs_validate_entry(c, dent1);
-+ if (err)
-+ goto out_free;
-+
-+ err = dbg_read_leaf_nolock(c, zbr2, dent2);
-+ if (err)
-+ goto out_free;
-+ err = ubifs_validate_entry(c, dent2);
-+ if (err)
-+ goto out_free;
-+
-+ /* Make sure node keys are the same as in zbranch */
-+ err = 1;
-+ key_read(c, &dent1->key, &key);
-+ if (keys_cmp(c, &zbr1->key, &key)) {
-+ dbg_err("1st entry at %d:%d has key %s", zbr1->lnum,
-+ zbr1->offs, DBGKEY(&key));
-+ dbg_err("but it should have key %s according to tnc",
-+ DBGKEY(&zbr1->key));
-+ dbg_dump_node(c, dent1);
-+ goto out_free;
-+ }
-+
-+ key_read(c, &dent2->key, &key);
-+ if (keys_cmp(c, &zbr2->key, &key)) {
-+ dbg_err("2nd entry at %d:%d has key %s", zbr1->lnum,
-+ zbr1->offs, DBGKEY(&key));
-+ dbg_err("but it should have key %s according to tnc",
-+ DBGKEY(&zbr2->key));
-+ dbg_dump_node(c, dent2);
-+ goto out_free;
-+ }
-+
-+ nlen1 = le16_to_cpu(dent1->nlen);
-+ nlen2 = le16_to_cpu(dent2->nlen);
-+
-+ cmp = memcmp(dent1->name, dent2->name, min_t(int, nlen1, nlen2));
-+ if (cmp < 0 || (cmp == 0 && nlen1 < nlen2)) {
-+ err = 0;
-+ goto out_free;
-+ }
-+ if (cmp == 0 && nlen1 == nlen2)
-+ dbg_err("2 xent/dent nodes with the same name");
-+ else
-+ dbg_err("bad order of colliding key %s",
-+ DBGKEY(&key));
-+
-+ dbg_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs);
-+ dbg_dump_node(c, dent1);
-+ dbg_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs);
-+ dbg_dump_node(c, dent2);
-+
-+out_free:
-+ kfree(dent2);
-+ kfree(dent1);
-+ return err;
-+}
-+
-+/**
-+ * dbg_check_znode - check if znode is all right.
-+ * @c: UBIFS file-system description object
-+ * @zbr: zbranch which points to this znode
-+ *
-+ * This function makes sure that znode referred to by @zbr is all right.
-+ * Returns zero if it is, and %-EINVAL if it is not.
-+ */
-+static int dbg_check_znode(struct ubifs_info *c, struct ubifs_zbranch *zbr)
-+{
-+ struct ubifs_znode *znode = zbr->znode;
-+ struct ubifs_znode *zp = znode->parent;
-+ int n, err, cmp;
-+
-+ if (znode->child_cnt <= 0 || znode->child_cnt > c->fanout) {
-+ err = 1;
-+ goto out;
-+ }
-+ if (znode->level < 0) {
-+ err = 2;
-+ goto out;
-+ }
-+ if (znode->iip < 0 || znode->iip >= c->fanout) {
-+ err = 3;
-+ goto out;
-+ }
-+
-+ if (zbr->len == 0)
-+ /* Only dirty zbranch may have no on-flash nodes */
-+ if (!ubifs_zn_dirty(znode)) {
-+ err = 4;
-+ goto out;
-+ }
-+
-+ if (ubifs_zn_dirty(znode)) {
-+ /*
-+ * If znode is dirty, its parent has to be dirty as well. The
-+ * order of the operation is important, so we have to have
-+ * memory barriers.
-+ */
-+ smp_mb();
-+ if (zp && !ubifs_zn_dirty(zp)) {
-+ /*
-+ * The dirty flag is atomic and is cleared outside the
-+ * TNC mutex, so znode's dirty flag may now have
-+ * been cleared. The child is always cleared before the
-+ * parent, so we just need to check again.
-+ */
-+ smp_mb();
-+ if (ubifs_zn_dirty(znode)) {
-+ err = 5;
-+ goto out;
-+ }
-+ }
-+ }
-+
-+ if (zp) {
-+ const union ubifs_key *min, *max;
-+
-+ if (znode->level != zp->level - 1) {
-+ err = 6;
-+ goto out;
-+ }
-+
-+ /* Make sure the 'parent' pointer in our znode is correct */
-+ err = ubifs_search_zbranch(c, zp, &zbr->key, &n);
-+ if (!err) {
-+ /* This zbranch does not exist in the parent */
-+ err = 7;
-+ goto out;
-+ }
-+
-+ if (znode->iip >= zp->child_cnt) {
-+ err = 8;
-+ goto out;
-+ }
-+
-+ if (znode->iip != n) {
-+ /* This may happen only in case of collisions */
-+ if (keys_cmp(c, &zp->zbranch[n].key,
-+ &zp->zbranch[znode->iip].key)) {
-+ err = 9;
-+ goto out;
-+ }
-+ n = znode->iip;
-+ }
-+
-+ /*
-+ * Make sure that the first key in our znode is greater than or
-+ * equal to the key in the pointing zbranch.
-+ */
-+ min = &zbr->key;
-+ cmp = keys_cmp(c, min, &znode->zbranch[0].key);
-+ if (cmp == 1) {
-+ err = 10;
-+ goto out;
-+ }
-+
-+ if (n + 1 < zp->child_cnt) {
-+ max = &zp->zbranch[n + 1].key;
-+
-+ /*
-+ * Make sure the last key in our znode is less or
-+ * equivalent than the the key in zbranch which goes
-+ * after our pointing zbranch.
-+ */
-+ cmp = keys_cmp(c, max,
-+ &znode->zbranch[znode->child_cnt - 1].key);
-+ if (cmp == -1) {
-+ err = 11;
-+ goto out;
-+ }
-+ }
-+ } else {
-+ /* This may only be root znode */
-+ if (zbr != &c->zroot) {
-+ err = 12;
-+ goto out;
-+ }
-+ }
-+
-+ /*
-+ * Make sure that next key is greater or equivalent then the previous
-+ * one.
-+ */
-+ for (n = 1; n < znode->child_cnt; n++) {
-+ cmp = keys_cmp(c, &znode->zbranch[n - 1].key,
-+ &znode->zbranch[n].key);
-+ if (cmp > 0) {
-+ err = 13;
-+ goto out;
-+ }
-+ if (cmp == 0) {
-+ /* This can only be keys with colliding hash */
-+ if (!is_hash_key(c, &znode->zbranch[n].key)) {
-+ err = 14;
-+ goto out;
-+ }
-+
-+ if (znode->level != 0 || c->replaying)
-+ continue;
-+
-+ /*
-+ * Colliding keys should follow binary order of
-+ * corresponding xentry/dentry names.
-+ */
-+ err = dbg_check_key_order(c, &znode->zbranch[n - 1],
-+ &znode->zbranch[n]);
-+ if (err < 0)
-+ return err;
-+ if (err) {
-+ err = 15;
-+ goto out;
-+ }
-+ }
-+ }
-+
-+ for (n = 0; n < znode->child_cnt; n++) {
-+ if (!znode->zbranch[n].znode &&
-+ (znode->zbranch[n].lnum == 0 ||
-+ znode->zbranch[n].len == 0)) {
-+ err = 16;
-+ goto out;
-+ }
-+
-+ if (znode->zbranch[n].lnum != 0 &&
-+ znode->zbranch[n].len == 0) {
-+ err = 17;
-+ goto out;
-+ }
-+
-+ if (znode->zbranch[n].lnum == 0 &&
-+ znode->zbranch[n].len != 0) {
-+ err = 18;
-+ goto out;
-+ }
-+
-+ if (znode->zbranch[n].lnum == 0 &&
-+ znode->zbranch[n].offs != 0) {
-+ err = 19;
-+ goto out;
-+ }
-+
-+ if (znode->level != 0 && znode->zbranch[n].znode)
-+ if (znode->zbranch[n].znode->parent != znode) {
-+ err = 20;
-+ goto out;
-+ }
-+ }
-+
-+ return 0;
-+
-+out:
-+ ubifs_err("failed, error %d", err);
-+ ubifs_msg("dump of the znode");
-+ dbg_dump_znode(c, znode);
-+ if (zp) {
-+ ubifs_msg("dump of the parent znode");
-+ dbg_dump_znode(c, zp);
-+ }
-+ dump_stack();
-+ return -EINVAL;
-+}
-+
-+/**
-+ * dbg_check_tnc - check TNC tree.
-+ * @c: UBIFS file-system description object
-+ * @extra: do extra checks that are possible at start commit
-+ *
-+ * This function traverses whole TNC tree and checks every znode. Returns zero
-+ * if everything is all right and %-EINVAL if something is wrong with TNC.
-+ */
-+int dbg_check_tnc(struct ubifs_info *c, int extra)
-+{
-+ struct ubifs_znode *znode;
-+ long clean_cnt = 0, dirty_cnt = 0;
-+ int err, last;
-+
-+ if (!(ubifs_chk_flags & UBIFS_CHK_TNC))
-+ return 0;
-+
-+ ubifs_assert(mutex_is_locked(&c->tnc_mutex));
-+ if (!c->zroot.znode)
-+ return 0;
-+
-+ znode = ubifs_tnc_postorder_first(c->zroot.znode);
-+ while (1) {
-+ struct ubifs_znode *prev;
-+ struct ubifs_zbranch *zbr;
-+
-+ if (!znode->parent)
-+ zbr = &c->zroot;
-+ else
-+ zbr = &znode->parent->zbranch[znode->iip];
-+
-+ err = dbg_check_znode(c, zbr);
-+ if (err)
-+ return err;
-+
-+ if (extra) {
-+ if (ubifs_zn_dirty(znode))
-+ dirty_cnt += 1;
-+ else
-+ clean_cnt += 1;
-+ }
-+
-+ prev = znode;
-+ znode = ubifs_tnc_postorder_next(znode);
-+ if (!znode)
-+ break;
-+
-+ /*
-+ * If the last key of this znode is equivalent to the first key
-+ * of the next znode (collision), then check order of the keys.
-+ */
-+ last = prev->child_cnt - 1;
-+ if (prev->level == 0 && znode->level == 0 && !c->replaying &&
-+ !keys_cmp(c, &prev->zbranch[last].key,
-+ &znode->zbranch[0].key)) {
-+ err = dbg_check_key_order(c, &prev->zbranch[last],
-+ &znode->zbranch[0]);
-+ if (err < 0)
-+ return err;
-+ if (err) {
-+ ubifs_msg("first znode");
-+ dbg_dump_znode(c, prev);
-+ ubifs_msg("second znode");
-+ dbg_dump_znode(c, znode);
-+ return -EINVAL;
-+ }
-+ }
-+ }
-+
-+ if (extra) {
-+ if (clean_cnt != atomic_long_read(&c->clean_zn_cnt)) {
-+ ubifs_err("incorrect clean_zn_cnt %ld, calculated %ld",
-+ atomic_long_read(&c->clean_zn_cnt),
-+ clean_cnt);
-+ return -EINVAL;
-+ }
-+ if (dirty_cnt != atomic_long_read(&c->dirty_zn_cnt)) {
-+ ubifs_err("incorrect dirty_zn_cnt %ld, calculated %ld",
-+ atomic_long_read(&c->dirty_zn_cnt),
-+ dirty_cnt);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int dbg_add_size(struct ubifs_info *c, struct ubifs_znode *znode,
-+ void *priv)
-+{
-+ long long *idx_size = priv;
-+ int add;
-+
-+ add = ubifs_idx_node_sz(c, znode->child_cnt);
-+ add = ALIGN(add, 8);
-+ *idx_size += add;
-+ return 0;
-+}
-+
-+int dbg_check_idx_size(struct ubifs_info *c, long long idx_size)
-+{
-+ int err;
-+ long long calc = 0;
-+
-+ if (!(ubifs_chk_flags & UBIFS_CHK_IDX_SZ))
-+ return 0;
-+
-+ err = dbg_walk_index(c, NULL, dbg_add_size, &calc);
-+ if (err) {
-+ ubifs_err("error %d while walking the index", err);
-+ return err;
-+ }
-+
-+ if (calc != idx_size) {
-+ ubifs_err("index size check failed");
-+ ubifs_err("calculated size is %lld, should be %lld",
-+ calc, idx_size);
-+ dump_stack();
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int invocation_cnt;
-+
-+int dbg_force_in_the_gaps(void)
-+{
-+ if (!dbg_force_in_the_gaps_enabled)
-+ return 0;
-+ /* Force in-the-gaps every 8th commit */
-+ return !((invocation_cnt++) & 0x7);
-+}
-+
-+#endif /* CONFIG_UBIFS_FS_DEBUG */
-+
-+/* Failure mode for recovery testing */
-+
-+#define chance(n, d) (simple_rand() <= (n) * 32768LL / (d))
-+
-+struct failure_mode_info {
-+ struct list_head list;
-+ struct ubifs_info *c;
-+};
-+
-+static LIST_HEAD(fmi_list);
-+static DEFINE_SPINLOCK(fmi_lock);
-+
-+static unsigned int next;
-+
-+static int simple_rand(void)
-+{
-+ if (next == 0)
-+ next = current->pid;
-+ next = next * 1103515245 + 12345;
-+ return (next >> 16) & 32767;
-+}
-+
-+void dbg_failure_mode_registration(struct ubifs_info *c)
-+{
-+ struct failure_mode_info *fmi;
-+
-+ fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS);
-+ if (!fmi) {
-+ dbg_err("Failed to register failure mode - no memory");
-+ return;
-+ }
-+ fmi->c = c;
-+ spin_lock(&fmi_lock);
-+ list_add_tail(&fmi->list, &fmi_list);
-+ spin_unlock(&fmi_lock);
-+}
-+
-+void dbg_failure_mode_deregistration(struct ubifs_info *c)
-+{
-+ struct failure_mode_info *fmi, *tmp;
-+
-+ spin_lock(&fmi_lock);
-+ list_for_each_entry_safe(fmi, tmp, &fmi_list, list)
-+ if (fmi->c == c) {
-+ list_del(&fmi->list);
-+ kfree(fmi);
-+ }
-+ spin_unlock(&fmi_lock);
-+}
-+
-+static struct ubifs_info *dbg_find_info(struct ubi_volume_desc *desc)
-+{
-+ struct failure_mode_info *fmi;
-+
-+ spin_lock(&fmi_lock);
-+ list_for_each_entry(fmi, &fmi_list, list)
-+ if (fmi->c->ubi == desc) {
-+ struct ubifs_info *c = fmi->c;
-+
-+ spin_unlock(&fmi_lock);
-+ return c;
-+ }
-+ spin_unlock(&fmi_lock);
-+ return NULL;
-+}
-+
-+static int in_failure_mode(struct ubi_volume_desc *desc)
-+{
-+ struct ubifs_info *c = dbg_find_info(desc);
-+
-+ if (c)
-+ return c->failure_mode;
-+ return 0;
-+}
-+
-+static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
-+{
-+ struct ubifs_info *c = dbg_find_info(desc);
-+
-+ if (!c || !dbg_failure_mode)
-+ return 0;
-+ if (c->failure_mode)
-+ return 1;
-+ if (!c->fail_cnt) {
-+ /* First call - decide delay to failure */
-+ if (chance(1, 2)) {
-+ unsigned int delay = 1 << (simple_rand() >> 11);
-+
-+ if (chance(1, 2)) {
-+ c->fail_delay = 1;
-+ c->fail_timeout = jiffies +
-+ msecs_to_jiffies(delay);
-+ dbg_rcvry("failing after %ums", delay);
-+ } else {
-+ c->fail_delay = 2;
-+ c->fail_cnt_max = delay;
-+ dbg_rcvry("failing after %u calls", delay);
-+ }
-+ }
-+ c->fail_cnt += 1;
-+ }
-+ /* Determine if failure delay has expired */
-+ if (c->fail_delay == 1) {
-+ if (time_before(jiffies, c->fail_timeout))
-+ return 0;
-+ } else if (c->fail_delay == 2)
-+ if (c->fail_cnt++ < c->fail_cnt_max)
-+ return 0;
-+ if (lnum == UBIFS_SB_LNUM) {
-+ if (write) {
-+ if (chance(1, 2))
-+ return 0;
-+ } else if (chance(19, 20))
-+ return 0;
-+ dbg_rcvry("failing in super block LEB %d", lnum);
-+ } else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) {
-+ if (chance(19, 20))
-+ return 0;
-+ dbg_rcvry("failing in master LEB %d", lnum);
-+ } else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) {
-+ if (write) {
-+ if (chance(99, 100))
-+ return 0;
-+ } else if (chance(399, 400))
-+ return 0;
-+ dbg_rcvry("failing in log LEB %d", lnum);
-+ } else if (lnum >= c->lpt_first && lnum <= c->lpt_last) {
-+ if (write) {
-+ if (chance(7, 8))
-+ return 0;
-+ } else if (chance(19, 20))
-+ return 0;
-+ dbg_rcvry("failing in LPT LEB %d", lnum);
-+ } else if (lnum >= c->orph_first && lnum <= c->orph_last) {
-+ if (write) {
-+ if (chance(1, 2))
-+ return 0;
-+ } else if (chance(9, 10))
-+ return 0;
-+ dbg_rcvry("failing in orphan LEB %d", lnum);
-+ } else if (lnum == c->ihead_lnum) {
-+ if (chance(99, 100))
-+ return 0;
-+ dbg_rcvry("failing in index head LEB %d", lnum);
-+ } else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) {
-+ if (chance(9, 10))
-+ return 0;
-+ dbg_rcvry("failing in GC head LEB %d", lnum);
-+ } else if (write && !RB_EMPTY_ROOT(&c->buds) &&
-+ !ubifs_search_bud(c, lnum)) {
-+ if (chance(19, 20))
-+ return 0;
-+ dbg_rcvry("failing in non-bud LEB %d", lnum);
-+ } else if (c->cmt_state == COMMIT_RUNNING_BACKGROUND ||
-+ c->cmt_state == COMMIT_RUNNING_REQUIRED) {
-+ if (chance(999, 1000))
-+ return 0;
-+ dbg_rcvry("failing in bud LEB %d commit running", lnum);
-+ } else {
-+ if (chance(9999, 10000))
-+ return 0;
-+ dbg_rcvry("failing in bud LEB %d commit not running", lnum);
-+ }
-+ ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum);
-+ c->failure_mode = 1;
-+ dump_stack();
-+ return 1;
-+}
-+
-+static void cut_data(const void *buf, int len)
-+{
-+ int flen, i;
-+ unsigned char *p = (void *)buf;
-+
-+ flen = (len * (long long)simple_rand()) >> 15;
-+ for (i = flen; i < len; i++)
-+ p[i] = 0xff;
-+}
-+
-+int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
-+ int len, int check)
-+{
-+ if (in_failure_mode(desc))
-+ return -EIO;
-+ return ubi_leb_read(desc, lnum, buf, offset, len, check);
-+}
-+
-+int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
-+ int offset, int len, int dtype)
-+{
-+ int err;
-+
-+ if (in_failure_mode(desc))
-+ return -EIO;
-+ if (do_fail(desc, lnum, 1))
-+ cut_data(buf, len);
-+ err = ubi_leb_write(desc, lnum, buf, offset, len, dtype);
-+ if (err)
-+ return err;
-+ if (in_failure_mode(desc))
-+ return -EIO;
-+ return 0;
-+}
-+
-+int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
-+ int len, int dtype)
-+{
-+ int err;
-+
-+ if (do_fail(desc, lnum, 1))
-+ return -EIO;
-+ err = ubi_leb_change(desc, lnum, buf, len, dtype);
-+ if (err)
-+ return err;
-+ if (do_fail(desc, lnum, 1))
-+ return -EIO;
-+ return 0;
-+}
-+
-+int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum)
-+{
-+ int err;
-+
-+ if (do_fail(desc, lnum, 0))
-+ return -EIO;
-+ err = ubi_leb_erase(desc, lnum);
-+ if (err)
-+ return err;
-+ if (do_fail(desc, lnum, 0))
-+ return -EIO;
-+ return 0;
-+}
-+
-+int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum)
-+{
-+ int err;
-+
-+ if (do_fail(desc, lnum, 0))
-+ return -EIO;
-+ err = ubi_leb_unmap(desc, lnum);
-+ if (err)
-+ return err;
-+ if (do_fail(desc, lnum, 0))
-+ return -EIO;
-+ return 0;
-+}
-+
-+int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum)
-+{
-+ if (in_failure_mode(desc))
-+ return -EIO;
-+ return ubi_is_mapped(desc, lnum);
-+}
---- linux-2.6.24.7.old/fs/ubifs/debug.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/debug.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,392 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+#ifndef __UBIFS_DEBUG_H__
-+#define __UBIFS_DEBUG_H__
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+#define UBIFS_DBG(op) op
-+
-+#define ubifs_assert(expr) do { \
-+ if (unlikely(!(expr))) { \
-+ printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
-+ __func__, __LINE__, current->pid); \
-+ dbg_dump_stack(); \
-+ } \
-+} while (0)
-+
-+#define ubifs_assert_cmt_locked(c) do { \
-+ if (unlikely(down_write_trylock(&(c)->commit_sem))) { \
-+ up_write(&(c)->commit_sem); \
-+ printk(KERN_CRIT "commit lock is not locked!\n"); \
-+ ubifs_assert(0); \
-+ } \
-+} while (0)
-+
-+#define dbg_dump_stack() do { \
-+ if (!dbg_failure_mode) \
-+ dump_stack(); \
-+} while (0)
-+
-+/* Generic debugging messages */
-+#define dbg_msg(fmt, ...) do { \
-+ spin_lock(&dbg_lock); \
-+ printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", current->pid, \
-+ __func__, ##__VA_ARGS__); \
-+ spin_unlock(&dbg_lock); \
-+} while (0)
-+
-+#define dbg_do_msg(typ, fmt, ...) do { \
-+ if (ubifs_msg_flags & typ) \
-+ dbg_msg(fmt, ##__VA_ARGS__); \
-+} while (0)
-+
-+#define dbg_err(fmt, ...) do { \
-+ spin_lock(&dbg_lock); \
-+ ubifs_err(fmt, ##__VA_ARGS__); \
-+ spin_unlock(&dbg_lock); \
-+} while (0)
-+
-+const char *dbg_key_str0(const struct ubifs_info *c,
-+ const union ubifs_key *key);
-+const char *dbg_key_str1(const struct ubifs_info *c,
-+ const union ubifs_key *key);
-+
-+/*
-+ * DBGKEY macros require dbg_lock to be held, which it is in the dbg message
-+ * macros.
-+ */
-+#define DBGKEY(key) dbg_key_str0(c, (key))
-+#define DBGKEY1(key) dbg_key_str1(c, (key))
-+
-+/* General messages */
-+#define dbg_gen(fmt, ...) dbg_do_msg(UBIFS_MSG_GEN, fmt, ##__VA_ARGS__)
-+
-+/* Additional journal messages */
-+#define dbg_jnl(fmt, ...) dbg_do_msg(UBIFS_MSG_JNL, fmt, ##__VA_ARGS__)
-+
-+/* Additional TNC messages */
-+#define dbg_tnc(fmt, ...) dbg_do_msg(UBIFS_MSG_TNC, fmt, ##__VA_ARGS__)
-+
-+/* Additional lprops messages */
-+#define dbg_lp(fmt, ...) dbg_do_msg(UBIFS_MSG_LP, fmt, ##__VA_ARGS__)
-+
-+/* Additional LEB find messages */
-+#define dbg_find(fmt, ...) dbg_do_msg(UBIFS_MSG_FIND, fmt, ##__VA_ARGS__)
-+
-+/* Additional mount messages */
-+#define dbg_mnt(fmt, ...) dbg_do_msg(UBIFS_MSG_MNT, fmt, ##__VA_ARGS__)
-+
-+/* Additional I/O messages */
-+#define dbg_io(fmt, ...) dbg_do_msg(UBIFS_MSG_IO, fmt, ##__VA_ARGS__)
-+
-+/* Additional commit messages */
-+#define dbg_cmt(fmt, ...) dbg_do_msg(UBIFS_MSG_CMT, fmt, ##__VA_ARGS__)
-+
-+/* Additional budgeting messages */
-+#define dbg_budg(fmt, ...) dbg_do_msg(UBIFS_MSG_BUDG, fmt, ##__VA_ARGS__)
-+
-+/* Additional log messages */
-+#define dbg_log(fmt, ...) dbg_do_msg(UBIFS_MSG_LOG, fmt, ##__VA_ARGS__)
-+
-+/* Additional gc messages */
-+#define dbg_gc(fmt, ...) dbg_do_msg(UBIFS_MSG_GC, fmt, ##__VA_ARGS__)
-+
-+/* Additional scan messages */
-+#define dbg_scan(fmt, ...) dbg_do_msg(UBIFS_MSG_SCAN, fmt, ##__VA_ARGS__)
-+
-+/* Additional recovery messages */
-+#define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__)
-+
-+/*
-+ * Debugging message type flags (must match msg_type_names in debug.c).
-+ *
-+ * UBIFS_MSG_GEN: general messages
-+ * UBIFS_MSG_JNL: journal messages
-+ * UBIFS_MSG_MNT: mount messages
-+ * UBIFS_MSG_CMT: commit messages
-+ * UBIFS_MSG_FIND: LEB find messages
-+ * UBIFS_MSG_BUDG: budgeting messages
-+ * UBIFS_MSG_GC: garbage collection messages
-+ * UBIFS_MSG_TNC: TNC messages
-+ * UBIFS_MSG_LP: lprops messages
-+ * UBIFS_MSG_IO: I/O messages
-+ * UBIFS_MSG_LOG: log messages
-+ * UBIFS_MSG_SCAN: scan messages
-+ * UBIFS_MSG_RCVRY: recovery messages
-+ */
-+enum {
-+ UBIFS_MSG_GEN = 0x1,
-+ UBIFS_MSG_JNL = 0x2,
-+ UBIFS_MSG_MNT = 0x4,
-+ UBIFS_MSG_CMT = 0x8,
-+ UBIFS_MSG_FIND = 0x10,
-+ UBIFS_MSG_BUDG = 0x20,
-+ UBIFS_MSG_GC = 0x40,
-+ UBIFS_MSG_TNC = 0x80,
-+ UBIFS_MSG_LP = 0x100,
-+ UBIFS_MSG_IO = 0x200,
-+ UBIFS_MSG_LOG = 0x400,
-+ UBIFS_MSG_SCAN = 0x800,
-+ UBIFS_MSG_RCVRY = 0x1000,
-+};
-+
-+/* Debugging message type flags for each default debug message level */
-+#define UBIFS_MSG_LVL_0 0
-+#define UBIFS_MSG_LVL_1 0x1
-+#define UBIFS_MSG_LVL_2 0x7f
-+#define UBIFS_MSG_LVL_3 0xffff
-+
-+/*
-+ * Debugging check flags (must match chk_names in debug.c).
-+ *
-+ * UBIFS_CHK_GEN: general checks
-+ * UBIFS_CHK_TNC: check TNC
-+ * UBIFS_CHK_IDX_SZ: check index size
-+ * UBIFS_CHK_ORPH: check orphans
-+ * UBIFS_CHK_OLD_IDX: check the old index
-+ * UBIFS_CHK_LPROPS: check lprops
-+ */
-+enum {
-+ UBIFS_CHK_GEN = 0x1,
-+ UBIFS_CHK_TNC = 0x2,
-+ UBIFS_CHK_IDX_SZ = 0x4,
-+ UBIFS_CHK_ORPH = 0x8,
-+ UBIFS_CHK_OLD_IDX = 0x10,
-+ UBIFS_CHK_LPROPS = 0x20,
-+};
-+
-+/*
-+ * Special testing flags (must match tst_names in debug.c).
-+ *
-+ * UBIFS_TST_FORCE_IN_THE_GAPS: force the use of in-the-gaps method
-+ * UBIFS_TST_RCVRY: failure mode for recovery testing
-+ */
-+enum {
-+ UBIFS_TST_FORCE_IN_THE_GAPS = 0x2,
-+ UBIFS_TST_RCVRY = 0x4,
-+};
-+
-+#if CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 1
-+#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_1
-+#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 2
-+#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_2
-+#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 3
-+#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_3
-+#else
-+#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_0
-+#endif
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG_CHKS
-+#define UBIFS_CHK_FLAGS_DEFAULT 0xffffffff
-+#else
-+#define UBIFS_CHK_FLAGS_DEFAULT 0
-+#endif
-+
-+extern spinlock_t dbg_lock;
-+
-+extern unsigned int ubifs_msg_flags;
-+extern unsigned int ubifs_chk_flags;
-+extern unsigned int ubifs_tst_flags;
-+
-+/* Dump functions */
-+
-+const char *dbg_ntype(int type);
-+const char *dbg_cstate(int cmt_state);
-+const char *dbg_get_key_dump(const struct ubifs_info *c,
-+ const union ubifs_key *key);
-+void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode);
-+void dbg_dump_node(const struct ubifs_info *c, const void *node);
-+void dbg_dump_budget_req(const struct ubifs_budget_req *req);
-+void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
-+void dbg_dump_budg(struct ubifs_info *c);
-+void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
-+void dbg_dump_lprops(struct ubifs_info *c);
-+void dbg_dump_leb(const struct ubifs_info *c, int lnum);
-+void dbg_dump_znode(const struct ubifs_info *c,
-+ const struct ubifs_znode *znode);
-+void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat);
-+void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
-+ struct ubifs_nnode *parent, int iip);
-+void dbg_dump_tnc(struct ubifs_info *c);
-+
-+/* Checking helper functions */
-+
-+typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
-+ struct ubifs_zbranch *zbr, void *priv);
-+typedef int (*dbg_znode_callback)(struct ubifs_info *c,
-+ struct ubifs_znode *znode, void *priv);
-+
-+int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
-+ dbg_znode_callback znode_cb, void *priv);
-+int dbg_read_leaf_nolock(struct ubifs_info *c, struct ubifs_zbranch *zbr,
-+ void *node);
-+
-+/* Checking functions */
-+
-+int dbg_check_lprops(struct ubifs_info *c);
-+
-+int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot);
-+int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot);
-+
-+int dbg_check_cats(struct ubifs_info *c);
-+
-+int dbg_check_ltab(struct ubifs_info *c);
-+
-+int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir);
-+
-+int dbg_check_tnc(struct ubifs_info *c, int extra);
-+
-+int dbg_check_idx_size(struct ubifs_info *c, long long idx_size);
-+
-+void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
-+ int add_pos);
-+
-+int dbg_check_lprops(struct ubifs_info *c);
-+int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
-+ int row, int col);
-+
-+/* Force the use of in-the-gaps method for testing */
-+
-+#define dbg_force_in_the_gaps_enabled \
-+ (ubifs_tst_flags & UBIFS_TST_FORCE_IN_THE_GAPS)
-+
-+int dbg_force_in_the_gaps(void);
-+
-+/* Failure mode for recovery testing */
-+
-+#define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY)
-+
-+void dbg_failure_mode_registration(struct ubifs_info *c);
-+void dbg_failure_mode_deregistration(struct ubifs_info *c);
-+
-+#ifndef UBIFS_DBG_PRESERVE_UBI
-+
-+#define ubi_leb_read dbg_leb_read
-+#define ubi_leb_write dbg_leb_write
-+#define ubi_leb_change dbg_leb_change
-+#define ubi_leb_erase dbg_leb_erase
-+#define ubi_leb_unmap dbg_leb_unmap
-+#define ubi_is_mapped dbg_is_mapped
-+
-+#endif
-+
-+int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
-+ int len, int check);
-+int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
-+ int offset, int len, int dtype);
-+int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
-+ int len, int dtype);
-+int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum);
-+int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum);
-+int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum);
-+
-+static inline int dbg_read(struct ubi_volume_desc *desc, int lnum, char *buf,
-+ int offset, int len)
-+{
-+ return dbg_leb_read(desc, lnum, buf, offset, len, 0);
-+}
-+
-+static inline int dbg_write(struct ubi_volume_desc *desc, int lnum,
-+ const void *buf, int offset, int len)
-+{
-+ return dbg_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
-+}
-+
-+static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
-+ const void *buf, int len)
-+{
-+ return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
-+}
-+
-+#else /* !CONFIG_UBIFS_FS_DEBUG */
-+
-+#define UBIFS_DBG(op)
-+#define ubifs_assert(expr) ({})
-+#define ubifs_assert_cmt_locked(c)
-+#define dbg_dump_stack()
-+#define dbg_err(fmt, ...) ({})
-+#define dbg_msg(fmt, ...) ({})
-+#define dbg_key(c, key, fmt, ...) ({})
-+
-+#define dbg_gen(fmt, ...) ({})
-+#define dbg_jnl(fmt, ...) ({})
-+#define dbg_tnc(fmt, ...) ({})
-+#define dbg_lp(fmt, ...) ({})
-+#define dbg_find(fmt, ...) ({})
-+#define dbg_mnt(fmt, ...) ({})
-+#define dbg_io(fmt, ...) ({})
-+#define dbg_cmt(fmt, ...) ({})
-+#define dbg_budg(fmt, ...) ({})
-+#define dbg_log(fmt, ...) ({})
-+#define dbg_gc(fmt, ...) ({})
-+#define dbg_scan(fmt, ...) ({})
-+#define dbg_rcvry(fmt, ...) ({})
-+
-+#define dbg_ntype(type) ""
-+#define dbg_cstate(cmt_state) ""
-+#define dbg_get_key_dump(c, key) ({})
-+#define dbg_dump_inode(c, inode) ({})
-+#define dbg_dump_node(c, node) ({})
-+#define dbg_dump_budget_req(req) ({})
-+#define dbg_dump_lstats(lst) ({})
-+#define dbg_dump_budg(c) ({})
-+#define dbg_dump_lprop(c, lp) ({})
-+#define dbg_dump_lprops(c) ({})
-+#define dbg_dump_leb(c, lnum) ({})
-+#define dbg_dump_znode(c, znode) ({})
-+#define dbg_dump_heap(c, heap, cat) ({})
-+#define dbg_dump_pnode(c, pnode, parent, iip) ({})
-+#define dbg_dump_tnc(c) ({})
-+
-+#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0
-+#define dbg_read_leaf_nolock(c, zbr, node) 0
-+
-+#define dbg_old_index_check_init(c, zroot) 0
-+#define dbg_check_old_index(c, zroot) 0
-+
-+#define dbg_check_cats(c) 0
-+
-+#define dbg_check_ltab(c) 0
-+
-+#define dbg_check_dir_size(c, dir) 0
-+
-+#define dbg_check_tnc(c, x) 0
-+
-+#define dbg_check_idx_size(c, idx_size) 0
-+
-+#define dbg_check_heap(c, heap, cat, add_pos) ({})
-+
-+#define dbg_check_lprops(c) 0
-+#define dbg_check_lpt_nodes(c, cnode, row, col) 0
-+
-+#define dbg_force_in_the_gaps_enabled 0
-+#define dbg_force_in_the_gaps() 0
-+
-+#define dbg_failure_mode 0
-+#define dbg_failure_mode_registration(c) ({})
-+#define dbg_failure_mode_deregistration(c) ({})
-+
-+#endif /* !CONFIG_UBIFS_FS_DEBUG */
-+
-+#endif /* !__UBIFS_DEBUG_H__ */
---- linux-2.6.24.7.old/fs/ubifs/dir.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/dir.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1017 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ * Copyright (C) 2006, 2007 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ * Zoltan Sogor
-+ */
-+
-+/*
-+ * This file implements directory operations.
-+ *
-+ * All FS operations in this file allocate budget before writing anything to the
-+ * media. If they fail to allocate it, the error is returned. The only
-+ * exceptions are 'ubifs_unlink()' and 'ubifs_rmdir()' which keep working even
-+ * if they unable to allocate the budget, because deletion %-ENOSPC failure is
-+ * not what users are usually ready to get. UBIFS budgeting subsystem has some
-+ * space reserved for these purposes.
-+ *
-+ * All operations in this file change the parent inode, e.g., 'ubifs_link()'
-+ * changes ctime and nlink of the parent inode. The parent inode is written to
-+ * the media straight away - it is not marked as dirty and there is no
-+ * write-back for it. This was done to simplify file-system recovery which
-+ * would otherwise be very difficult to do. So instead of marking the parent
-+ * inode dirty, the operations mark it clean.
-+ */
-+
-+#include "ubifs.h"
-+
-+/*
-+ * Provide backing_dev_info in order to disable readahead. For UBIFS, I/O is
-+ * not deferred, it is done immediately in readpage, which means the user would
-+ * have to wait not just for their own I/O but the readahead I/O as well i.e.
-+ * completely pointless.
-+ */
-+struct backing_dev_info ubifs_backing_dev_info = {
-+ .ra_pages = 0, /* Set to zero to disable readahead */
-+ .state = 0,
-+ .capabilities = BDI_CAP_MAP_COPY,
-+ .unplug_io_fn = default_unplug_io_fn,
-+};
-+
-+/**
-+ * inherit_flags - inherit flags of the parent inode.
-+ * @dir: parent inode
-+ * @mode: new inode mode flags
-+ *
-+ * This is a helper function for 'ubifs_new_inode()' which inherits flag of the
-+ * parent directory inode @dir. UBIFS inodes inherit the following flags:
-+ * o %UBIFS_COMPR_FL, which is useful to switch compression on/of on
-+ * sub-directory basis;
-+ * o %UBIFS_SYNC_FL - useful for the same reasons;
-+ * o %UBIFS_DIRSYNC_FL - similar, but relevant only to directories.
-+ *
-+ * This function returns the inherited flags.
-+ */
-+static int inherit_flags(const struct inode *dir, int mode)
-+{
-+ int flags;
-+ const struct ubifs_inode *ui = ubifs_inode(dir);
-+
-+ if (!S_ISDIR(dir->i_mode))
-+ /*
-+ * The parent is not a directory, which means that an extended
-+ * attribute inode is being created. No flags.
-+ */
-+ return 0;
-+
-+ flags = ui->flags & (UBIFS_COMPR_FL | UBIFS_SYNC_FL | UBIFS_DIRSYNC_FL);
-+ if (!S_ISDIR(mode))
-+ /* The "DIRSYNC" flag only applies to directories */
-+ flags &= ~UBIFS_DIRSYNC_FL;
-+
-+ return flags;
-+}
-+
-+/**
-+ * ubifs_new_inode - allocate new UBIFS inode object.
-+ * @c: UBIFS file-system description object
-+ * @dir: parent directory inode
-+ * @mode: inode mode flags
-+ *
-+ * This function finds an unused inode number, allocates new inode and
-+ * initializes it. Returns new inode in case of success and an error code in
-+ * case of failure.
-+ */
-+struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
-+ int mode)
-+{
-+ struct inode *inode;
-+ struct ubifs_inode *ui;
-+
-+ inode = new_inode(c->vfs_sb);
-+ if (!inode)
-+ return ERR_PTR(-ENOMEM);
-+
-+ /*
-+ * Set 'S_NOCMTIME' to prevent VFS form updating [mc]time of inodes and
-+ * marking them dirty in file write path (see 'file_update_time()').
-+ * UBIFS has to fully control "clean <-> dirty" transitions of inodes
-+ * to make budgeting work.
-+ */
-+ inode->i_flags |= (S_NOCMTIME);
-+
-+ inode->i_uid = current->fsuid;
-+ if (dir->i_mode & S_ISGID) {
-+ inode->i_gid = dir->i_gid;
-+ if (S_ISDIR(mode))
-+ mode |= S_ISGID;
-+ } else
-+ inode->i_gid = current->fsgid;
-+ inode->i_mode = mode;
-+ inode->i_mtime = inode->i_atime = inode->i_ctime =
-+ ubifs_current_time(inode);
-+ inode->i_mapping->nrpages = 0;
-+ /* Disable readahead */
-+ inode->i_mapping->backing_dev_info = &ubifs_backing_dev_info;
-+
-+ switch (mode & S_IFMT) {
-+ case S_IFREG:
-+ inode->i_mapping->a_ops = &ubifs_file_address_operations;
-+ inode->i_op = &ubifs_file_inode_operations;
-+ inode->i_fop = &ubifs_file_operations;
-+ break;
-+ case S_IFDIR:
-+ inode->i_op = &ubifs_dir_inode_operations;
-+ inode->i_fop = &ubifs_dir_operations;
-+ inode->i_size = UBIFS_INO_NODE_SZ;
-+ break;
-+ case S_IFLNK:
-+ inode->i_op = &ubifs_symlink_inode_operations;
-+ break;
-+ case S_IFSOCK:
-+ case S_IFIFO:
-+ case S_IFBLK:
-+ case S_IFCHR:
-+ inode->i_op = &ubifs_file_inode_operations;
-+ break;
-+ default:
-+ BUG();
-+ }
-+
-+ ui = ubifs_inode(inode);
-+ ui->flags = inherit_flags(dir, mode);
-+ ubifs_set_inode_flags(inode);
-+
-+ if (S_ISREG(mode))
-+ ui->compr_type = c->default_compr;
-+ else
-+ ui->compr_type = UBIFS_COMPR_NONE;
-+
-+ spin_lock(&c->cnt_lock);
-+ /* Inode number overflow is currently not supported */
-+ if (c->highest_inum >= INUM_WARN_WATERMARK) {
-+ if (c->highest_inum >= INUM_WATERMARK) {
-+ spin_unlock(&c->cnt_lock);
-+ ubifs_err("out of inode numbers");
-+ make_bad_inode(inode);
-+ iput(inode);
-+ return ERR_PTR(-EINVAL);
-+ }
-+ ubifs_warn("running out of inode numbers (current %lu, max %d)",
-+ c->highest_inum, INUM_WATERMARK);
-+ }
-+
-+ inode->i_ino = ++c->highest_inum;
-+ inode->i_generation = ++c->vfs_gen;
-+ /*
-+ * The creation sequence number remains with this inode for its
-+ * lifetime. All nodes for this inode have a greater sequence number,
-+ * and so it is possible to distinguish obsolete nodes belonging to a
-+ * previous incarnation of the same inode number - for example, for the
-+ * purpose of rebuilding the index.
-+ */
-+ ui->creat_sqnum = ++c->max_sqnum;
-+ spin_unlock(&c->cnt_lock);
-+
-+ return inode;
-+}
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm)
-+{
-+ if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
-+ return 0;
-+ if (le16_to_cpu(dent->nlen) != nm->len)
-+ return -EINVAL;
-+ if (memcmp(dent->name, nm->name, nm->len))
-+ return -EINVAL;
-+ return 0;
-+}
-+
-+#else
-+
-+#define dbg_check_name(dent, nm) 0
-+
-+#endif
-+
-+static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
-+ struct nameidata *nd)
-+{
-+ int err;
-+ union ubifs_key key;
-+ struct inode *inode = NULL;
-+ struct ubifs_dent_node *dent;
-+ struct ubifs_info *c = dir->i_sb->s_fs_info;
-+
-+ dbg_gen("'%.*s' in dir ino %lu",
-+ dentry->d_name.len, dentry->d_name.name, dir->i_ino);
-+
-+ if (dentry->d_name.len > UBIFS_MAX_NLEN)
-+ return ERR_PTR(-ENAMETOOLONG);
-+
-+ dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
-+ if (!dent)
-+ return ERR_PTR(-ENOMEM);
-+
-+ dent_key_init(c, &key, dir->i_ino, &dentry->d_name);
-+
-+ err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name);
-+ if (err) {
-+ if (err == -ENOENT) {
-+ dbg_gen("not found");
-+ goto done;
-+ }
-+ goto out;
-+ }
-+
-+ if (dbg_check_name(dent, &dentry->d_name)) {
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum));
-+ if (IS_ERR(inode)) {
-+ /*
-+ * This should not happen. Probably the file-system needs
-+ * checking.
-+ */
-+ err = PTR_ERR(inode);
-+ ubifs_err("dead directory entry '%.*s', error %d",
-+ dentry->d_name.len, dentry->d_name.name, err);
-+ ubifs_ro_mode(c, err);
-+ goto out;
-+ }
-+
-+done:
-+ kfree(dent);
-+ /*
-+ * Note, d_splice_alias() would be required instead if we supported
-+ * NFS.
-+ */
-+ d_add(dentry, inode);
-+ return NULL;
-+
-+out:
-+ kfree(dent);
-+ return ERR_PTR(err);
-+}
-+
-+static int ubifs_create(struct inode *dir, struct dentry *dentry, int mode,
-+ struct nameidata *nd)
-+{
-+ struct inode *inode;
-+ struct ubifs_info *c = dir->i_sb->s_fs_info;
-+ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };
-+ int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
-+
-+ dbg_gen("dent '%.*s', mode %#x in dir ino %lu",
-+ dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);
-+
-+ inode = ubifs_new_inode(c, dir, mode);
-+ if (IS_ERR(inode))
-+ return PTR_ERR(inode);
-+
-+ err = ubifs_budget_inode_op(c, dir, &req);
-+ if (err)
-+ goto out;
-+
-+ dir->i_size += sz_change;
-+
-+ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
-+ IS_DIRSYNC(dir), 0);
-+ if (err)
-+ goto out_budg;
-+
-+ insert_inode_hash(inode);
-+ d_instantiate(dentry, inode);
-+ ubifs_release_ino_clean(c, dir, &req);
-+ return 0;
-+
-+out_budg:
-+ dir->i_size -= sz_change;
-+ ubifs_cancel_ino_op(c, dir, &req);
-+ ubifs_err("cannot create regular file, error %d", err);
-+out:
-+ make_bad_inode(inode);
-+ iput(inode);
-+ return err;
-+}
-+
-+/**
-+ * vfs_dent_type - get VFS directory entry type.
-+ * @type: UBIFS directory entry type
-+ *
-+ * This function converts UBIFS directory entry type into VFS directory entry
-+ * type.
-+ */
-+static unsigned int vfs_dent_type(uint8_t type)
-+{
-+ switch (type) {
-+ case UBIFS_ITYPE_REG:
-+ return DT_REG;
-+ case UBIFS_ITYPE_DIR:
-+ return DT_DIR;
-+ case UBIFS_ITYPE_LNK:
-+ return DT_LNK;
-+ case UBIFS_ITYPE_BLK:
-+ return DT_BLK;
-+ case UBIFS_ITYPE_CHR:
-+ return DT_CHR;
-+ case UBIFS_ITYPE_FIFO:
-+ return DT_FIFO;
-+ case UBIFS_ITYPE_SOCK:
-+ return DT_SOCK;
-+ default:
-+ BUG();
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * The classical Unix view for directory is that it is a linear array of
-+ * (name, inode number) entries. Linux/VFS assumes this model as well.
-+ * Particularly, 'readdir()' call wants us to return a directory entry offset
-+ * which later may be used to continue 'readdir()'ing the directory or to
-+ * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this
-+ * model because directory entries are identified by keys, which may collide.
-+ *
-+ * UBIFS uses directory entry hash value for directory offsets, so
-+ * 'seekdir()'/'telldir()' may not always work because of possible key
-+ * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work
-+ * properly by means of saving full directory entry name in the private field
-+ * of the file description object.
-+ *
-+ * This means that UBIFS cannot support NFS which requires full
-+ * 'seekdir()'/'telldir()' support.
-+ */
-+static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
-+{
-+ int err, over = 0;
-+ struct qstr nm;
-+ union ubifs_key key;
-+ struct ubifs_dent_node *dent;
-+ struct inode *dir = file->f_path.dentry->d_inode;
-+ struct ubifs_info *c = dir->i_sb->s_fs_info;
-+
-+ dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
-+
-+ if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
-+ /*
-+ * The directory was seek'ed to a senseless position or there
-+ * are no more entries.
-+ */
-+ return 0;
-+
-+ /* File positions 0 and 1 correspond to "." and ".." */
-+ if (file->f_pos == 0) {
-+ ubifs_assert(!file->private_data);
-+ over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR);
-+ if (over)
-+ return 0;
-+ file->f_pos = 1;
-+ }
-+
-+ if (file->f_pos == 1) {
-+ ubifs_assert(!file->private_data);
-+ over = filldir(dirent, "..", 2, 1,
-+ parent_ino(file->f_path.dentry), DT_DIR);
-+ if (over)
-+ return 0;
-+
-+ /* Find the first entry in TNC and save it */
-+ lowest_dent_key(c, &key, dir->i_ino);
-+ nm.name = NULL;
-+ dent = ubifs_tnc_next_ent(c, &key, &nm);
-+ if (IS_ERR(dent)) {
-+ err = PTR_ERR(dent);
-+ goto out;
-+ }
-+
-+ file->f_pos = key_hash_flash(c, &dent->key);
-+ file->private_data = dent;
-+ }
-+
-+ dent = file->private_data;
-+ if (!dent) {
-+ /*
-+ * The directory was seek'ed to and is now readdir'ed.
-+ * Find the entry corresponding to @file->f_pos or the
-+ * closest one.
-+ */
-+ dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
-+ nm.name = NULL;
-+ dent = ubifs_tnc_next_ent(c, &key, &nm);
-+ if (IS_ERR(dent)) {
-+ err = PTR_ERR(dent);
-+ goto out;
-+ }
-+ file->f_pos = key_hash_flash(c, &dent->key);
-+ file->private_data = dent;
-+ }
-+
-+ while (1) {
-+ dbg_gen("feed '%s', ino %llu, new f_pos %#x",
-+ dent->name, le64_to_cpu(dent->inum),
-+ key_hash_flash(c, &dent->key));
-+ ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum);
-+
-+ nm.len = le16_to_cpu(dent->nlen);
-+ over = filldir(dirent, dent->name, nm.len, file->f_pos,
-+ le64_to_cpu(dent->inum),
-+ vfs_dent_type(dent->type));
-+ if (over)
-+ return 0;
-+
-+ /* Switch to the next entry */
-+ key_read(c, &dent->key, &key);
-+ nm.name = dent->name;
-+ dent = ubifs_tnc_next_ent(c, &key, &nm);
-+ if (IS_ERR(dent)) {
-+ err = PTR_ERR(dent);
-+ goto out;
-+ }
-+
-+ kfree(file->private_data);
-+ file->f_pos = key_hash_flash(c, &dent->key);
-+ file->private_data = dent;
-+ cond_resched();
-+ }
-+
-+out:
-+ if (err != -ENOENT) {
-+ ubifs_err("cannot find next direntry, error %d", err);
-+ return err;
-+ }
-+
-+ kfree(file->private_data);
-+ file->private_data = NULL;
-+ file->f_pos = 2;
-+ return 0;
-+}
-+
-+/* If a directory is seeked, we have to free saved readdir() state */
-+loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ kfree(file->private_data);
-+ file->private_data = NULL;
-+ return generic_file_llseek(file, offset, origin);
-+}
-+
-+/* Free saved readdir() state when the directory is closed */
-+static int ubifs_dir_release(struct inode *dir, struct file *file)
-+{
-+ kfree(file->private_data);
-+ file->private_data = NULL;
-+ return 0;
-+}
-+
-+static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
-+ struct dentry *dentry)
-+{
-+ struct ubifs_info *c = dir->i_sb->s_fs_info;
-+ struct inode *inode = old_dentry->d_inode;
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+ struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 1,
-+ .dirtied_ino_d = ui->data_len };
-+ int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
-+
-+ dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu",
-+ dentry->d_name.len, dentry->d_name.name, inode->i_ino,
-+ inode->i_nlink, dir->i_ino);
-+
-+ err = ubifs_budget_inode_op(c, dir, &req);
-+ if (err)
-+ return err;
-+
-+ inc_nlink(inode);
-+ dir->i_size += sz_change;
-+ inode->i_ctime = dir->i_mtime = dir->i_ctime =
-+ ubifs_current_time(inode);
-+
-+ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
-+ IS_DIRSYNC(dir), 0);
-+ if (err)
-+ goto out_budg;
-+
-+ atomic_inc(&inode->i_count);
-+ d_instantiate(dentry, inode);
-+ ubifs_release_ino_clean(c, dir, &req);
-+ return 0;
-+
-+out_budg:
-+ dir->i_size -= sz_change;
-+ ubifs_cancel_ino_op(c, dir, &req);
-+ drop_nlink(inode);
-+ iput(inode);
-+ return err;
-+}
-+
-+static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
-+{
-+ struct ubifs_info *c = dir->i_sb->s_fs_info;
-+ struct inode *inode = dentry->d_inode;
-+ struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 1 };
-+ int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
-+ int err, budgeted = 1;
-+
-+ dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu",
-+ dentry->d_name.len, dentry->d_name.name, inode->i_ino,
-+ inode->i_nlink, dir->i_ino);
-+
-+ err = ubifs_budget_inode_op(c, dir, &req);
-+ if (err) {
-+ if (err != -ENOSPC)
-+ return err;
-+ err = 0;
-+ budgeted = 0;
-+ }
-+
-+ dir->i_size -= sz_change;
-+ dir->i_mtime = dir->i_ctime = ubifs_current_time(dir);
-+
-+ inode->i_ctime = dir->i_ctime;
-+ drop_nlink(inode);
-+
-+ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1,
-+ IS_DIRSYNC(dir), 0);
-+ if (err)
-+ goto out_budg;
-+
-+ if (budgeted)
-+ ubifs_release_ino_clean(c, dir, &req);
-+
-+ return 0;
-+
-+out_budg:
-+ dir->i_size += sz_change;
-+ inc_nlink(inode);
-+ if (budgeted)
-+ ubifs_cancel_ino_op(c, dir, &req);
-+ return err;
-+}
-+
-+/**
-+ * check_dir_empty - check if a directory is empty or not.
-+ * @c: UBIFS file-system description object
-+ * @dir: VFS inode object of the directory to check
-+ *
-+ * This function checks if directory @dir is empty. Returns zero if the
-+ * directory is empty, %-ENOTEMPTY if it is not, and other negative error codes
-+ * in case of of errors.
-+ */
-+static int check_dir_empty(struct ubifs_info *c, struct inode *dir)
-+{
-+ struct qstr nm = { .name = NULL };
-+ struct ubifs_dent_node *dent;
-+ union ubifs_key key;
-+ int err;
-+
-+ lowest_dent_key(c, &key, dir->i_ino);
-+ dent = ubifs_tnc_next_ent(c, &key, &nm);
-+ if (IS_ERR(dent)) {
-+ err = PTR_ERR(dent);
-+ if (err == -ENOENT)
-+ err = 0;
-+ } else {
-+ kfree(dent);
-+ err = -ENOTEMPTY;
-+ }
-+
-+ return err;
-+}
-+
-+static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
-+{
-+ struct ubifs_info *c = dir->i_sb->s_fs_info;
-+ struct inode *inode = dentry->d_inode;
-+ struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 1 };
-+ int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
-+ int err, budgeted = 0;
-+
-+ dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len,
-+ dentry->d_name.name, inode->i_ino, dir->i_ino);
-+
-+ err = check_dir_empty(c, dentry->d_inode);
-+ if (err)
-+ return err;
-+
-+ budgeted = 1;
-+ err = ubifs_budget_inode_op(c, dir, &req);
-+ if (err) {
-+ if (err != -ENOSPC)
-+ return err;
-+ budgeted = 0;
-+ }
-+
-+ dir->i_size -= sz_change;
-+ dir->i_mtime = dir->i_ctime = ubifs_current_time(dir);
-+ drop_nlink(dir);
-+
-+ inode->i_size = 0;
-+ inode->i_ctime = dir->i_ctime;
-+ clear_nlink(inode);
-+
-+ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1,
-+ IS_DIRSYNC(dir), 0);
-+ if (err)
-+ goto out_budg;
-+
-+ if (budgeted)
-+ ubifs_release_ino_clean(c, dir, &req);
-+
-+ return 0;
-+
-+out_budg:
-+ dir->i_size += sz_change;
-+ inc_nlink(dir);
-+ inc_nlink(inode);
-+ inc_nlink(inode);
-+ if (budgeted)
-+ ubifs_cancel_ino_op(c, dir, &req);
-+ return err;
-+}
-+
-+static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-+{
-+ struct inode *inode;
-+ struct ubifs_info *c = dir->i_sb->s_fs_info;
-+ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };
-+ int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
-+
-+ dbg_gen("dent '%.*s', mode %#x in dir ino %lu",
-+ dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);
-+
-+ err = ubifs_budget_inode_op(c, dir, &req);
-+ if (err)
-+ return err;
-+
-+ inode = ubifs_new_inode(c, dir, S_IFDIR | mode);
-+ if (IS_ERR(inode)) {
-+ err = PTR_ERR(inode);
-+ goto out_budg;
-+ }
-+
-+ insert_inode_hash(inode);
-+ inc_nlink(inode);
-+
-+ dir->i_mtime = dir->i_ctime = ubifs_current_time(dir);
-+ dir->i_size += sz_change;
-+ inc_nlink(dir);
-+
-+ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
-+ IS_DIRSYNC(dir), 0);
-+ if (err) {
-+ ubifs_err("cannot create directory, error %d", err);
-+ goto out_inode;
-+ }
-+
-+ d_instantiate(dentry, inode);
-+ ubifs_release_ino_clean(c, dir, &req);
-+ return 0;
-+
-+out_inode:
-+ dir->i_size -= sz_change;
-+ drop_nlink(dir);
-+ make_bad_inode(inode);
-+ iput(inode);
-+out_budg:
-+ ubifs_cancel_ino_op(c, dir, &req);
-+ return err;
-+}
-+
-+static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
-+ int mode, dev_t rdev)
-+{
-+ struct inode *inode;
-+ struct ubifs_info *c = dir->i_sb->s_fs_info;
-+ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };
-+ union ubifs_dev_desc *dev = NULL;
-+ int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
-+ int err, devlen = 0;
-+
-+ dbg_gen("dent '%.*s' in dir ino %lu",
-+ dentry->d_name.len, dentry->d_name.name, dir->i_ino);
-+
-+ if (!new_valid_dev(rdev))
-+ return -EINVAL;
-+
-+ if (S_ISBLK(mode) || S_ISCHR(mode)) {
-+ dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
-+ if (!dev)
-+ return -ENOMEM;
-+ devlen = ubifs_encode_dev(dev, rdev);
-+ }
-+
-+ err = ubifs_budget_inode_op(c, dir, &req);
-+ if (err) {
-+ kfree(dev);
-+ return err;
-+ }
-+
-+ inode = ubifs_new_inode(c, dir, mode);
-+ if (IS_ERR(inode)) {
-+ kfree(dev);
-+ err = PTR_ERR(inode);
-+ goto out_budg;
-+ }
-+
-+ init_special_inode(inode, inode->i_mode, rdev);
-+
-+ inode->i_size = devlen;
-+ ubifs_inode(inode)->data = dev;
-+ ubifs_inode(inode)->data_len = devlen;
-+
-+ dir->i_size += sz_change;
-+
-+ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
-+ IS_DIRSYNC(dir), 0);
-+ if (err)
-+ goto out_inode;
-+
-+ insert_inode_hash(inode);
-+ d_instantiate(dentry, inode);
-+ ubifs_release_ino_clean(c, dir, &req);
-+ return 0;
-+
-+out_inode:
-+ dir->i_size -= sz_change;
-+ make_bad_inode(inode);
-+ iput(inode);
-+out_budg:
-+ ubifs_cancel_ino_op(c, dir, &req);
-+ return err;
-+}
-+
-+static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
-+ const char *symname)
-+{
-+ struct inode *inode;
-+ struct ubifs_inode *ui;
-+ struct ubifs_info *c = dir->i_sb->s_fs_info;
-+ int err, len = strlen(symname);
-+ int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
-+ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
-+ .new_ino_d = len };
-+
-+ dbg_gen("dent '%.*s', target '%s' in dir ino %lu", dentry->d_name.len,
-+ dentry->d_name.name, symname, dir->i_ino);
-+
-+ if (len > UBIFS_MAX_INO_DATA)
-+ return -ENAMETOOLONG;
-+
-+ err = ubifs_budget_inode_op(c, dir, &req);
-+ if (err)
-+ return err;
-+
-+ inode = ubifs_new_inode(c, dir, S_IFLNK | S_IRWXUGO);
-+ if (IS_ERR(inode)) {
-+ err = PTR_ERR(inode);
-+ goto out_budg;
-+ }
-+
-+ ui = ubifs_inode(inode);
-+ ui->data = kmalloc(len + 1, GFP_NOFS);
-+ if (!ui->data) {
-+ err = -ENOMEM;
-+ goto out_inode;
-+ }
-+
-+ memcpy(ui->data, symname, len);
-+ ((char *)ui->data)[len] = '\0';
-+ /*
-+ * The terminating zero byte is not written to the flash media and it
-+ * is put just to make later in-memory string processing simpler. Thus,
-+ * data length is @len, not @len + %1.
-+ */
-+ ui->data_len = len;
-+ inode->i_size = len;
-+
-+ dir->i_size += sz_change;
-+
-+ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0,
-+ IS_DIRSYNC(dir), 0);
-+ if (err)
-+ goto out_dir;
-+
-+ insert_inode_hash(inode);
-+ d_instantiate(dentry, inode);
-+ ubifs_release_ino_clean(c, dir, &req);
-+ return 0;
-+
-+out_dir:
-+ dir->i_size -= sz_change;
-+out_inode:
-+ make_bad_inode(inode);
-+ iput(inode);
-+out_budg:
-+ ubifs_cancel_ino_op(c, dir, &req);
-+ return err;
-+}
-+
-+static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+ struct inode *new_dir, struct dentry *new_dentry)
-+{
-+ struct ubifs_info *c = old_dir->i_sb->s_fs_info;
-+ struct inode *old_inode = old_dentry->d_inode;
-+ struct inode *new_inode = new_dentry->d_inode;
-+ int err, move = (new_dir != old_dir);
-+ int is_dir = S_ISDIR(old_inode->i_mode);
-+ int unlink = !!new_inode;
-+ int dirsync = (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir));
-+ int new_sz = CALC_DENT_SIZE(new_dentry->d_name.len);
-+ int old_sz = CALC_DENT_SIZE(old_dentry->d_name.len);
-+ struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1 };
-+ struct timespec time = ubifs_current_time(old_dir);
-+
-+ dbg_gen("dent '%.*s' ino %lu in dir ino %lu to dent '%.*s' in "
-+ "dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name,
-+ old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len,
-+ new_dentry->d_name.name, new_dir->i_ino);
-+
-+ if (unlink && is_dir) {
-+ err = check_dir_empty(c, new_inode);
-+ if (err)
-+ return err;
-+ }
-+
-+ if (move) {
-+ req.dirtied_ino = 1;
-+ if (unlink) {
-+ req.dirtied_ino += 2;
-+ req.dirtied_ino_d = ubifs_inode(new_inode)->data_len;
-+ }
-+ }
-+
-+ /*
-+ * Note, rename may write @new_dir inode if the directory entry is
-+ * moved there. And if the @new_dir is dirty, we do not bother to make
-+ * it clean. It could be done, but requires extra coding which does not
-+ * seem to be really worth it.
-+ */
-+ err = ubifs_budget_inode_op(c, old_dir, &req);
-+ if (err)
-+ return err;
-+
-+ /*
-+ * Like most other Unix systems, set the ctime for inodes on a
-+ * rename.
-+ */
-+ old_inode->i_ctime = time;
-+
-+ /*
-+ * If we moved a directory to another parent directory, decrement
-+ * 'i_nlink' of the old parent. Also, update 'i_size' of the old parent
-+ * as well as its [mc]time.
-+ */
-+ if (is_dir && move)
-+ drop_nlink(old_dir);
-+ old_dir->i_size -= old_sz;
-+ old_dir->i_mtime = old_dir->i_ctime = time;
-+ new_dir->i_mtime = new_dir->i_ctime = time;
-+
-+ /*
-+ * If we moved a directory object to new directory, parent's 'i_nlink'
-+ * should be adjusted.
-+ */
-+ if (move && is_dir)
-+ inc_nlink(new_dir);
-+
-+ /*
-+ * And finally, if we unlinked a direntry which happened to have the
-+ * same name as the moved direntry, we have to decrement 'i_nlink' of
-+ * the unlinked inode and change its ctime.
-+ */
-+ if (unlink) {
-+ /*
-+ * Directories cannot have hard-links, so if this is a
-+ * directory, decrement its 'i_nlink' twice because an empty
-+ * directory has 'i_nlink' 2.
-+ */
-+ if (is_dir)
-+ drop_nlink(new_inode);
-+ new_inode->i_ctime = time;
-+ drop_nlink(new_inode);
-+ } else
-+ new_dir->i_size += new_sz;
-+
-+ err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry,
-+ dirsync);
-+ if (err)
-+ goto out_inode;
-+
-+ ubifs_release_ino_clean(c, old_dir, &req);
-+ return 0;
-+
-+out_inode:
-+ if (unlink) {
-+ if (is_dir)
-+ inc_nlink(new_inode);
-+ inc_nlink(new_inode);
-+ } else
-+ new_dir->i_size -= new_sz;
-+ old_dir->i_size += old_sz;
-+ if (is_dir && move) {
-+ drop_nlink(new_dir);
-+ inc_nlink(old_dir);
-+ }
-+ ubifs_cancel_ino_op(c, old_dir, &req);
-+ return err;
-+}
-+
-+int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
-+ struct kstat *stat)
-+{
-+ struct inode *inode = dentry->d_inode;
-+ loff_t size;
-+
-+ stat->dev = inode->i_sb->s_dev;
-+ stat->ino = inode->i_ino;
-+ stat->mode = inode->i_mode;
-+ stat->nlink = inode->i_nlink;
-+ stat->uid = inode->i_uid;
-+ stat->gid = inode->i_gid;
-+ stat->rdev = inode->i_rdev;
-+ stat->atime = inode->i_atime;
-+ stat->mtime = inode->i_mtime;
-+ stat->ctime = inode->i_ctime;
-+ stat->blksize = UBIFS_BLOCK_SIZE;
-+ stat->size = i_size_read(inode);
-+
-+ spin_lock(&inode->i_lock);
-+ size = ubifs_inode(inode)->xattr_size;
-+ spin_unlock(&inode->i_lock);
-+
-+ /*
-+ * Unfortunately, the 'stat()' system call was designed for block
-+ * device based file systems, and it is not appropriate for UBIFS,
-+ * because UBIFS does not have notion of "block". For example, it is
-+ * difficult to tell how many block a directory takes - it actually
-+ * takes less than 300 bytes, but we have to round it to block size,
-+ * which introduces large mistake. This makes utilities like 'du' to
-+ * report completely senseless numbers. This is the reason why UBIFS
-+ * goes the same way as JFFS2 - it reports zero blocks for everything
-+ * but regular files, which makes more sense than reporting completely
-+ * wrong sizes.
-+ */
-+ if (S_ISREG(inode->i_mode))
-+ size += stat->size;
-+
-+ size = ALIGN(size, UBIFS_BLOCK_SIZE);
-+ /*
-+ * Note, user-space expects 512-byte blocks count irrespectively of what
-+ * was reported in @stat->size.
-+ */
-+ stat->blocks = size >> 9;
-+
-+ return 0;
-+}
-+
-+struct inode_operations ubifs_dir_inode_operations = {
-+ .lookup = ubifs_lookup,
-+ .create = ubifs_create,
-+ .link = ubifs_link,
-+ .symlink = ubifs_symlink,
-+ .unlink = ubifs_unlink,
-+ .mkdir = ubifs_mkdir,
-+ .rmdir = ubifs_rmdir,
-+ .mknod = ubifs_mknod,
-+ .rename = ubifs_rename,
-+ .setattr = ubifs_setattr,
-+ .getattr = ubifs_getattr,
-+#ifdef CONFIG_UBIFS_FS_XATTR
-+ .setxattr = ubifs_setxattr,
-+ .getxattr = ubifs_getxattr,
-+ .listxattr = ubifs_listxattr,
-+ .removexattr = ubifs_removexattr,
-+#endif
-+};
-+
-+struct file_operations ubifs_dir_operations = {
-+ .llseek = ubifs_dir_llseek,
-+ .release = ubifs_dir_release,
-+ .read = generic_read_dir,
-+ .readdir = ubifs_readdir,
-+ .fsync = ubifs_fsync,
-+ .unlocked_ioctl = ubifs_ioctl,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = ubifs_compat_ioctl,
-+#endif
-+};
---- linux-2.6.24.7.old/fs/ubifs/file.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/file.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,983 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file implements VFS file and inode operations of regular files, device
-+ * nodes and symlinks as well as address space operations.
-+ *
-+ * UBIFS uses 2 page flags: PG_private and PG_checked. PG_private is set if the
-+ * page is dirty and is used for budgeting purposes - dirty pages should not be
-+ * budgeted. The PG_checked flag is set if full budgeting is required for the
-+ * page e.g., when it corresponds to a file hole or it is just beyond the file
-+ * size. The budgeting is done in 'ubifs_write_begin()', because it is OK to
-+ * fail in this function, and the budget is released in 'ubifs_write_end()'. So
-+ * the PG_private and PG_checked flags carry the information about how the page
-+ * was budgeted, to make it possible to release the budget properly.
-+ *
-+ * A thing to keep in mind: inode's 'i_mutex' is locked in most VFS operations
-+ * we implement. However, this is not true for '->writepage()', which might be
-+ * called with 'i_mutex' unlocked. For example, when pdflush is performing
-+ * write-back, it calls 'writepage()' with unlocked 'i_mutex', although the
-+ * inode has 'I_LOCK' flag in this case. At "normal" work-paths 'i_mutex' is
-+ * locked in '->writepage', e.g. in "sys_write -> alloc_pages -> direct reclaim
-+ * path'. So, in '->writepage()' we are only guaranteed that the page is
-+ * locked.
-+ *
-+ * Similarly, 'i_mutex' does not have to be locked in readpage(), e.g.,
-+ * readahead path does not have it locked ("sys_read -> generic_file_aio_read
-+ * -> ondemand_readahead -> readpage"). In case of readahead, 'I_LOCK' flag is
-+ * not set as well.
-+ *
-+ * This, for example means that there might be 2 concurrent '->writepage()'
-+ * calls for the same inode, but different inode dirty pages.
-+ */
-+
-+#include "ubifs.h"
-+#include
-+
-+static int read_block(struct inode *inode, void *addr, unsigned int block,
-+ struct ubifs_data_node *dn)
-+{
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ int err, len, out_len;
-+ union ubifs_key key;
-+ unsigned int dlen;
-+
-+ data_key_init(c, &key, inode->i_ino, block);
-+ err = ubifs_tnc_lookup(c, &key, dn);
-+ if (err) {
-+ if (err == -ENOENT)
-+ /* Not found, so it must be a hole */
-+ memset(addr, 0, UBIFS_BLOCK_SIZE);
-+ return err;
-+ }
-+
-+ ubifs_assert(dn->ch.sqnum > ubifs_inode(inode)->creat_sqnum);
-+
-+ len = le32_to_cpu(dn->size);
-+ if (len <= 0 || len > UBIFS_BLOCK_SIZE)
-+ goto dump;
-+
-+ dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
-+ out_len = UBIFS_BLOCK_SIZE;
-+ err = ubifs_decompress(&dn->data, dlen, addr, &out_len,
-+ le16_to_cpu(dn->compr_type));
-+ if (err || len != out_len)
-+ goto dump;
-+
-+ /*
-+ * Data length can be less than a full block, even for blocks that are
-+ * not the last in the file (e.g., as a result of making a hole and
-+ * appending data). Ensure that the remainder is zeroed out.
-+ */
-+ if (len < UBIFS_BLOCK_SIZE)
-+ memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
-+
-+ return 0;
-+
-+dump:
-+ ubifs_err("bad data node (block %u, inode %lu)",
-+ block, inode->i_ino);
-+ dbg_dump_node(c, dn);
-+ return -EINVAL;
-+}
-+
-+/* TODO: remove compatibility stuff as late as possible */
-+#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE
-+int ubifs_do_readpage(struct page *page)
-+#else
-+static int do_readpage(struct page *page)
-+#endif
-+{
-+ void *addr;
-+ int err = 0, i;
-+ unsigned int block, beyond;
-+ struct ubifs_data_node *dn;
-+ struct inode *inode = page->mapping->host;
-+ loff_t i_size = i_size_read(inode);
-+
-+ dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx",
-+ inode->i_ino, page->index, i_size, page->flags);
-+ ubifs_assert(!PageChecked(page));
-+ ubifs_assert(!PagePrivate(page));
-+
-+ addr = kmap(page);
-+
-+ block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
-+ beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
-+ if (block >= beyond) {
-+ /* Reading beyond inode */
-+ SetPageChecked(page);
-+ memset(addr, 0, PAGE_CACHE_SIZE);
-+ goto out;
-+ }
-+
-+ dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
-+ if (!dn) {
-+ err = -ENOMEM;
-+ goto error;
-+ }
-+
-+ i = 0;
-+ while (1) {
-+ int ret;
-+
-+ if (block >= beyond) {
-+ /* Reading beyond inode */
-+ err = -ENOENT;
-+ memset(addr, 0, UBIFS_BLOCK_SIZE);
-+ } else {
-+ ret = read_block(inode, addr, block, dn);
-+ if (ret) {
-+ err = ret;
-+ if (err != -ENOENT)
-+ break;
-+ }
-+ }
-+ if (++i >= UBIFS_BLOCKS_PER_PAGE)
-+ break;
-+ block += 1;
-+ addr += UBIFS_BLOCK_SIZE;
-+ }
-+ if (err) {
-+ if (err == -ENOENT) {
-+ /* Not found, so it must be a hole */
-+ SetPageChecked(page);
-+ dbg_gen("hole");
-+ goto out_free;
-+ }
-+ ubifs_err("cannot read page %lu of inode %lu, error %d",
-+ page->index, inode->i_ino, err);
-+ goto error;
-+ }
-+
-+out_free:
-+ kfree(dn);
-+out:
-+ SetPageUptodate(page);
-+ ClearPageError(page);
-+ flush_dcache_page(page);
-+ kunmap(page);
-+ return 0;
-+
-+error:
-+ kfree(dn);
-+ ClearPageUptodate(page);
-+ SetPageError(page);
-+ flush_dcache_page(page);
-+ kunmap(page);
-+ return err;
-+}
-+
-+/* TODO: remove compatibility stuff as late as possible */
-+#ifndef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE
-+
-+static int ubifs_write_begin(struct file *file, struct address_space *mapping,
-+ loff_t pos, unsigned len, unsigned flags,
-+ struct page **pagep, void **fsdata)
-+{
-+ struct inode *inode = mapping->host;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-+ struct ubifs_budget_req req = { .new_page = 1 };
-+ loff_t i_size = i_size_read(inode);
-+ int uninitialized_var(err);
-+ struct page *page;
-+
-+ ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
-+
-+ if (unlikely(c->ro_media))
-+ return -EROFS;
-+
-+ /*
-+ * We are about to have a page of data written and we have to budget for
-+ * this. The very important point here is that we have to budget before
-+ * locking the page, because budgeting may force write-back, which
-+ * would wait on locked pages and deadlock if we had the page locked.
-+ *
-+ * At this point we do not know anything about the page of data we are
-+ * going to change, so assume the biggest budget (i.e., assume that
-+ * this is a new page of data and it does not override an older page of
-+ * data in the inode). Later the budget will be amended if this is not
-+ * true.
-+ */
-+ if (pos + len > i_size)
-+ /*
-+ * We are writing beyond the file which means we are going to
-+ * change inode size and make the inode dirty. And in turn,
-+ * this means we have to budget for making the inode dirty.
-+ *
-+ * Note, if the inode is already dirty,
-+ * 'ubifs_budget_inode_op()' will not allocate any budget,
-+ * but will just lock the @budg_mutex of the inode to prevent
-+ * it from becoming clean before we have changed its size,
-+ * which is going to happen in 'ubifs_write_end()'.
-+ */
-+ err = ubifs_budget_inode_op(c, inode, &req);
-+ else
-+ /*
-+ * The inode is not going to be marked as dirty by this write
-+ * operation, do not budget for this.
-+ */
-+ err = ubifs_budget_space(c, &req);
-+ if (unlikely(err))
-+ return err;
-+
-+ page = __grab_cache_page(mapping, index);
-+ if (unlikely(!page)) {
-+ err = -ENOMEM;
-+ goto out_release;
-+ }
-+
-+ if (!PageUptodate(page)) {
-+ /*
-+ * The page is not loaded from the flash and has to be loaded
-+ * unless we are writing all of it.
-+ */
-+ if (!(pos & PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE)
-+ /*
-+ * Set the PG_checked flag to make the further code
-+ * assume the page is new.
-+ */
-+ SetPageChecked(page);
-+ else {
-+ err = do_readpage(page);
-+ if (err)
-+ goto out_unlock;
-+ }
-+
-+ SetPageUptodate(page);
-+ ClearPageError(page);
-+ }
-+
-+ if (PagePrivate(page))
-+ /*
-+ * The page is dirty, which means it was budgeted twice:
-+ * o first time the budget was allocated by the task which
-+ * made the page dirty and set the PG_private flag;
-+ * o and then we budgeted for it for the second time at the
-+ * very beginning of this function.
-+ *
-+ * So what we have to do is to release the page budget we
-+ * allocated.
-+ *
-+ * Note, the page write operation may change the inode length,
-+ * which makes it dirty and means the budget should be
-+ * allocated. This was done above in the "pos + len > i_size"
-+ * case. If this was done, we do not free the the inode budget,
-+ * because we cannot as we are really going to mark it dirty in
-+ * the 'ubifs_write_end()' function.
-+ */
-+ ubifs_release_new_page_budget(c);
-+ else if (!PageChecked(page))
-+ /*
-+ * The page is not new, which means we are changing the page
-+ * which already exists on the media. This means that changing
-+ * the page does not make the amount of indexing information
-+ * larger, and this part of the budget which we have already
-+ * acquired may be released.
-+ */
-+ ubifs_convert_page_budget(c);
-+
-+ *pagep = page;
-+ return 0;
-+
-+out_unlock:
-+ unlock_page(page);
-+ page_cache_release(page);
-+out_release:
-+ if (pos + len > i_size)
-+ ubifs_cancel_ino_op(c, inode, &req);
-+ else
-+ ubifs_release_budget(c, &req);
-+ return err;
-+}
-+
-+static int ubifs_write_end(struct file *file, struct address_space *mapping,
-+ loff_t pos, unsigned len, unsigned copied,
-+ struct page *page, void *fsdata)
-+{
-+ struct inode *inode = mapping->host;
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ loff_t i_size = i_size_read(inode);
-+
-+ dbg_gen("ino %lu, pos %llu, pg %lu, len %u, copied %d, i_size %lld",
-+ inode->i_ino, pos, page->index, len, copied, i_size);
-+
-+ if (unlikely(copied < len && len == PAGE_CACHE_SIZE)) {
-+ /*
-+ * VFS copied less data to the page that it intended and
-+ * declared in its '->write_begin()' call via the @len
-+ * argument. If the page was not up-to-date, and @len was
-+ * @PAGE_CACHE_SIZE, the 'ubifs_write_begin()' function did
-+ * not load it from the media (for optimization reasons). This
-+ * means that part of the page contains garbage. So read the
-+ * page now.
-+ */
-+ dbg_gen("copied %d instead of %d, read page and repeat",
-+ copied, len);
-+
-+ if (pos + len > i_size)
-+ /* See a comment below about this hacky unlock */
-+ mutex_unlock(&ui->budg_mutex);
-+
-+ copied = do_readpage(page);
-+
-+ /*
-+ * Return 0 to force VFS to repeat the whole operation, or the
-+ * error code if 'do_readpage()' failed.
-+ */
-+ goto out;
-+ }
-+
-+ if (!PagePrivate(page)) {
-+ SetPagePrivate(page);
-+ atomic_long_inc(&c->dirty_pg_cnt);
-+ __set_page_dirty_nobuffers(page);
-+ }
-+
-+ if (pos + len > i_size) {
-+ i_size_write(inode, pos + len);
-+
-+ /*
-+ * Note, we do not set @I_DIRTY_PAGES (which means that the
-+ * inode has dirty pages), this has been done in
-+ * '__set_page_dirty_nobuffers()'.
-+ */
-+ mark_inode_dirty_sync(inode);
-+
-+ /*
-+ * The inode has been marked dirty, unlock it. This is a bit
-+ * hacky because normally we would have to call
-+ * 'ubifs_release_ino_dirty()'. But we know there is nothing
-+ * to release because page's budget will be released in
-+ * 'ubifs_write_page()' and inode's budget will be released in
-+ * 'ubifs_write_inode()', so just unlock the inode here for
-+ * optimization.
-+ */
-+ mutex_unlock(&ui->budg_mutex);
-+ }
-+
-+out:
-+ unlock_page(page);
-+ page_cache_release(page);
-+ return copied;
-+}
-+
-+#endif /* UBIFS_COMPAT_USE_OLD_PREPARE_WRITE */
-+
-+static int ubifs_readpage(struct file *file, struct page *page)
-+{
-+ do_readpage(page);
-+ unlock_page(page);
-+ return 0;
-+}
-+
-+/**
-+ * release_existing_page_budget - release budget of an existing page.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This is a helper function which releases budget corresponding to the budget
-+ * of changing one one page of data which already exists on the flash media.
-+ *
-+ * This function was not moved to "budget.c" because there is only one user.
-+ */
-+static void release_existing_page_budget(struct ubifs_info *c)
-+{
-+ struct ubifs_budget_req req = { .dd_growth = c->page_budget};
-+
-+ ubifs_release_budget(c, &req);
-+}
-+
-+static int do_writepage(struct page *page, int len)
-+{
-+ int err = 0, i, blen;
-+ unsigned int block;
-+ void *addr;
-+ union ubifs_key key;
-+ struct inode *inode = page->mapping->host;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+
-+ /* Update radix tree tags */
-+ set_page_writeback(page);
-+
-+ addr = kmap(page);
-+
-+ block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
-+ i = 0;
-+ while (len) {
-+ blen = min_t(int, len, UBIFS_BLOCK_SIZE);
-+ data_key_init(c, &key, inode->i_ino, block);
-+ err = ubifs_jnl_write_data(c, inode, &key, addr, blen);
-+ if (err)
-+ break;
-+ if (++i >= UBIFS_BLOCKS_PER_PAGE)
-+ break;
-+ block += 1;
-+ addr += blen;
-+ len -= blen;
-+ }
-+ if (err) {
-+ SetPageError(page);
-+ ubifs_err("cannot write page %lu of inode %lu, error %d",
-+ page->index, inode->i_ino, err);
-+ ubifs_ro_mode(c, err);
-+ }
-+
-+ ubifs_assert(PagePrivate(page));
-+ if (PageChecked(page))
-+ ubifs_release_new_page_budget(c);
-+ else
-+ release_existing_page_budget(c);
-+
-+ atomic_long_dec(&c->dirty_pg_cnt);
-+ ClearPagePrivate(page);
-+ ClearPageChecked(page);
-+
-+ kunmap(page);
-+ unlock_page(page);
-+ end_page_writeback(page);
-+
-+ return err;
-+}
-+
-+static int ubifs_writepage(struct page *page, struct writeback_control *wbc)
-+{
-+ struct inode *inode = page->mapping->host;
-+ loff_t i_size = i_size_read(inode);
-+ pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
-+ int len;
-+ void *kaddr;
-+
-+ dbg_gen("ino %lu, pg %lu, pg flags %#lx",
-+ inode->i_ino, page->index, page->flags);
-+ ubifs_assert(PagePrivate(page));
-+
-+ /* Is the page fully inside i_size? */
-+ if (page->index < end_index)
-+ return do_writepage(page, PAGE_CACHE_SIZE);
-+
-+ /* Is the page fully outside i_size? (truncate in progress) */
-+ len = i_size & (PAGE_CACHE_SIZE - 1);
-+ if (page->index >= end_index + 1 || !len) {
-+ unlock_page(page);
-+ return 0;
-+ }
-+
-+ /*
-+ * The page straddles i_size. It must be zeroed out on each and every
-+ * writepage invocation because it may be mmapped. "A file is mapped
-+ * in multiples of the page size. For a file that is not a multiple of
-+ * the page size, the remaining memory is zeroed when mapped, and
-+ * writes to that region are not written out to the file."
-+ */
-+ kaddr = kmap_atomic(page, KM_USER0);
-+ memset(kaddr + len, 0, PAGE_CACHE_SIZE - len);
-+ flush_dcache_page(page);
-+ kunmap_atomic(kaddr, KM_USER0);
-+
-+ return do_writepage(page, len);
-+}
-+
-+static int ubifs_trunc(struct inode *inode, loff_t new_size)
-+{
-+ loff_t old_size;
-+ int err;
-+
-+ dbg_gen("ino %lu, size %lld -> %lld",
-+ inode->i_ino, inode->i_size, new_size);
-+ old_size = inode->i_size;
-+
-+ err = vmtruncate(inode, new_size);
-+ if (err)
-+ return err;
-+
-+ if (new_size < old_size) {
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ int offset = new_size & (UBIFS_BLOCK_SIZE - 1);
-+
-+ if (offset) {
-+ pgoff_t index = new_size >> PAGE_CACHE_SHIFT;
-+ struct page *page;
-+
-+ page = find_lock_page(inode->i_mapping, index);
-+ if (page) {
-+ if (PageDirty(page)) {
-+ ubifs_assert(PagePrivate(page));
-+
-+ clear_page_dirty_for_io(page);
-+ if (UBIFS_BLOCKS_PER_PAGE_SHIFT)
-+ offset = new_size &
-+ (PAGE_CACHE_SIZE - 1);
-+ err = do_writepage(page, offset);
-+ page_cache_release(page);
-+ if (err)
-+ return err;
-+ /*
-+ * We could now tell ubifs_jnl_truncate
-+ * not to read the last block.
-+ */
-+ } else {
-+ /*
-+ * We could 'kmap()' the page and
-+ * pass the data to ubifs_jnl_truncate
-+ * to save it from having to read it.
-+ */
-+ unlock_page(page);
-+ page_cache_release(page);
-+ }
-+ }
-+ }
-+ err = ubifs_jnl_truncate(c, inode->i_ino, old_size, new_size);
-+ if (err)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
-+{
-+ unsigned int ia_valid = attr->ia_valid;
-+ struct inode *inode = dentry->d_inode;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ struct ubifs_budget_req req;
-+ int truncation, err = 0;
-+
-+ dbg_gen("ino %lu, ia_valid %#x", inode->i_ino, ia_valid);
-+ err = inode_change_ok(inode, attr);
-+ if (err)
-+ return err;
-+
-+ memset(&req, 0, sizeof(struct ubifs_budget_req));
-+
-+ /*
-+ * If this is truncation, and we do not truncate on a block boundary,
-+ * budget for changing one data block, because the last block will be
-+ * re-written.
-+ */
-+ truncation = (ia_valid & ATTR_SIZE) && attr->ia_size != inode->i_size;
-+ if (truncation && attr->ia_size < inode->i_size &&
-+ (attr->ia_size & (UBIFS_BLOCK_SIZE - 1)))
-+ req.dirtied_page = 1;
-+
-+ err = ubifs_budget_inode_op(c, inode, &req);
-+ if (err)
-+ return err;
-+
-+ if (truncation) {
-+ err = ubifs_trunc(inode, attr->ia_size);
-+ if (err) {
-+ ubifs_cancel_ino_op(c, inode, &req);
-+ return err;
-+ }
-+
-+ inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
-+ }
-+
-+ if (ia_valid & ATTR_UID)
-+ inode->i_uid = attr->ia_uid;
-+ if (ia_valid & ATTR_GID)
-+ inode->i_gid = attr->ia_gid;
-+ if (ia_valid & ATTR_ATIME)
-+ inode->i_atime = timespec_trunc(attr->ia_atime,
-+ inode->i_sb->s_time_gran);
-+ if (ia_valid & ATTR_MTIME)
-+ inode->i_mtime = timespec_trunc(attr->ia_mtime,
-+ inode->i_sb->s_time_gran);
-+ if (ia_valid & ATTR_CTIME)
-+ inode->i_ctime = timespec_trunc(attr->ia_ctime,
-+ inode->i_sb->s_time_gran);
-+ if (ia_valid & ATTR_MODE) {
-+ umode_t mode = attr->ia_mode;
-+
-+ if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
-+ mode &= ~S_ISGID;
-+ inode->i_mode = mode;
-+ }
-+
-+ mark_inode_dirty_sync(inode);
-+ ubifs_release_ino_dirty(c, inode, &req);
-+
-+ if (req.dirtied_page) {
-+ /*
-+ * Truncation code does not make the reenacted page dirty, it
-+ * just changes it on journal level, so we have to release page
-+ * change budget.
-+ */
-+ memset(&req, 0, sizeof(struct ubifs_budget_req));
-+ req.dd_growth = c->page_budget;
-+ ubifs_release_budget(c, &req);
-+ }
-+
-+ if (IS_SYNC(inode))
-+ err = write_inode_now(inode, 1);
-+
-+ return err;
-+}
-+
-+static void ubifs_invalidatepage(struct page *page, unsigned long offset)
-+{
-+ struct inode *inode = page->mapping->host;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ struct ubifs_budget_req req;
-+
-+ ubifs_assert(PagePrivate(page));
-+ if (offset)
-+ /* Partial page remains dirty */
-+ return;
-+
-+ memset(&req, 0, sizeof(struct ubifs_budget_req));
-+ if (PageChecked(page)) {
-+ req.new_page = 1;
-+ req.idx_growth = -1;
-+ req.data_growth = c->page_budget;
-+ } else
-+ req.dd_growth = c->page_budget;
-+ ubifs_release_budget(c, &req);
-+
-+ atomic_long_dec(&c->dirty_pg_cnt);
-+ ClearPagePrivate(page);
-+ ClearPageChecked(page);
-+}
-+
-+static void *ubifs_follow_link(struct dentry *dentry, struct nameidata *nd)
-+{
-+ struct ubifs_inode *ui = ubifs_inode(dentry->d_inode);
-+
-+ nd_set_link(nd, ui->data);
-+ return NULL;
-+}
-+
-+int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync)
-+{
-+ struct inode *inode = dentry->d_inode;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ int err;
-+
-+ dbg_gen("syncing inode %lu", inode->i_ino);
-+
-+ /* Synchronize the inode and dirty pages */
-+ err = write_inode_now(inode, 1);
-+ if (err)
-+ return err;
-+
-+ /*
-+ * Some data related to this inode may still sit in a write-buffer.
-+ * Flush them.
-+ */
-+ err = ubifs_sync_wbufs_by_inodes(c, &inode, 1);
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+/**
-+ * mctime_update_needed - check if mtime or ctime update is needed.
-+ * @inode: the inode to do the check for
-+ * @now: current time
-+ *
-+ * This helper function checks if the inode mtime/ctime should be updated or
-+ * not. If current values of the time-stamps are within the UBIFS inode time
-+ * granularity, they are not updated. This is an optimization.
-+ */
-+static inline int mctime_update_needed(struct inode *inode,
-+ struct timespec *now)
-+{
-+ if (!timespec_equal(&inode->i_mtime, now) ||
-+ !timespec_equal(&inode->i_ctime, now))
-+ return 1;
-+ return 0;
-+}
-+
-+/**
-+ * update_ctime - update mtime and ctime of an inode.
-+ * @c: UBIFS file-system description object
-+ * @inode: inode to update
-+ *
-+ * This function updates mtime and ctime of the inode if it is not equivalent to
-+ * current time. Returns zero in case of success and a negative error code in
-+ * case of failure.
-+ */
-+static int update_mctime(struct ubifs_info *c, struct inode *inode)
-+{
-+ struct timespec now = ubifs_current_time(inode);
-+
-+ if (mctime_update_needed(inode, &now)) {
-+ struct ubifs_budget_req req;
-+ int err;
-+
-+ memset(&req, 0, sizeof(struct ubifs_budget_req));
-+ err = ubifs_budget_inode_op(c, inode, &req);
-+ if (err)
-+ return err;
-+
-+ inode->i_mtime = inode->i_ctime = now;
-+ mark_inode_dirty_sync(inode);
-+ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
-+ }
-+
-+ return 0;
-+}
-+
-+static ssize_t ubifs_write(struct file *file, const char __user *buf,
-+ size_t len, loff_t *ppos)
-+{
-+ int err;
-+ ssize_t ret;
-+ struct inode *inode = file->f_mapping->host;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+
-+ err = update_mctime(c, inode);
-+ if (err)
-+ return err;
-+
-+ ret = do_sync_write(file, buf, len, ppos);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (ret > 0 && IS_SYNC(inode)) {
-+ err = ubifs_sync_wbufs_by_inodes(c, &inode, 1);
-+ if (err)
-+ return err;
-+ }
-+
-+ return ret;
-+}
-+
-+static ssize_t ubifs_aio_write(struct kiocb *iocb, const struct iovec *iov,
-+ unsigned long nr_segs, loff_t pos)
-+{
-+ int err;
-+ ssize_t ret;
-+ struct inode *inode = iocb->ki_filp->f_mapping->host;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+
-+ err = update_mctime(c, inode);
-+ if (err)
-+ return err;
-+
-+ ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (ret > 0 && IS_SYNC(inode)) {
-+ err = ubifs_sync_wbufs_by_inodes(c, &inode, 1);
-+ if (err)
-+ return err;
-+ }
-+
-+ return ret;
-+}
-+
-+static int ubifs_set_page_dirty(struct page *page)
-+{
-+ int ret;
-+
-+ ret = __set_page_dirty_nobuffers(page);
-+ /*
-+ * An attempt to dirty a page without budgeting for it - should not
-+ * happen.
-+ */
-+ ubifs_assert(ret == 0);
-+ return ret;
-+}
-+
-+static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
-+{
-+ /*
-+ * An attempt to release a dirty page without budgeting for it - should
-+ * not happen.
-+ */
-+ if (PageWriteback(page))
-+ return 0;
-+ ubifs_assert(PagePrivate(page));
-+ ubifs_assert(0);
-+ ClearPagePrivate(page);
-+ ClearPageChecked(page);
-+ return 1;
-+}
-+
-+#ifndef UBIFS_COMPAT_NO_SHARED_MMAP
-+
-+/*
-+ * mmap()d file has taken write protection fault and is being made
-+ * writable. UBIFS must ensure page is budgeted for.
-+ */
-+static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page)
-+{
-+ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ struct timespec now = ubifs_current_time(inode);
-+ struct ubifs_budget_req req = { .new_page = 1 };
-+ int err, update_time;
-+
-+ dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index,
-+ i_size_read(inode));
-+ ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
-+
-+ if (unlikely(c->ro_media))
-+ return -EROFS;
-+
-+ /*
-+ * We have not locked @page so far so we may budget for changing the
-+ * page. Note, we cannot do this after we locked the page, because
-+ * budgeting may cause write-back which would cause deadlock.
-+ *
-+ * At the moment we do not know whether the page is dirty or not, so we
-+ * assume that it is not and budget for a new page. We could look at
-+ * the @PG_private flag and figure this out, but we may race with write
-+ * back and the page state may change by the time we lock it, so this
-+ * would need additional care. We do not bother with this at the
-+ * moment, although it might be good idea to do. Instead, we allocate
-+ * budget for a new page and amend it later on if the page was in fact
-+ * dirty.
-+ *
-+ * The budgeting-related logic of this function is similar to what we
-+ * do in 'ubifs_write_begin()' and 'ubifs_write_end()'. Glance there
-+ * for more comments.
-+ */
-+ if (mctime_update_needed(inode, &now)) {
-+ /*
-+ * We have to change inode time stamp which requires extra
-+ * budgeting.
-+ */
-+ update_time = 1;
-+ err = ubifs_budget_inode_op(c, inode, &req);
-+ } else {
-+ update_time = 0;
-+ err = ubifs_budget_space(c, &req);
-+ }
-+ if (unlikely(err)) {
-+ if (err == -ENOSPC)
-+ ubifs_warn("out of space for mmapped file "
-+ "(inode number %lu)", inode->i_ino);
-+ return err;
-+ }
-+
-+ lock_page(page);
-+ if (unlikely(page->mapping != inode->i_mapping ||
-+ page_offset(page) > i_size_read(inode))) {
-+ /* Page got truncated out from underneath us */
-+ err = -EINVAL;
-+ goto out_unlock;
-+ }
-+
-+ if (PagePrivate(page))
-+ ubifs_release_new_page_budget(c);
-+ else {
-+ if (!PageChecked(page))
-+ ubifs_convert_page_budget(c);
-+ SetPagePrivate(page);
-+ atomic_long_inc(&c->dirty_pg_cnt);
-+ __set_page_dirty_nobuffers(page);
-+ }
-+
-+ if (update_time) {
-+ inode->i_mtime = inode->i_ctime = now;
-+ mark_inode_dirty_sync(inode);
-+ mutex_unlock(&ubifs_inode(inode)->budg_mutex);
-+ }
-+
-+ unlock_page(page);
-+ return 0;
-+
-+out_unlock:
-+ unlock_page(page);
-+ if (update_time)
-+ ubifs_cancel_ino_op(c, inode, &req);
-+ else
-+ ubifs_release_budget(c, &req);
-+ return err;
-+}
-+
-+struct vm_operations_struct ubifs_file_vm_ops = {
-+#if (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,22))
-+ .nopage = filemap_nopage,
-+#else
-+ .fault = filemap_fault,
-+#endif
-+ .page_mkwrite = ubifs_vm_page_mkwrite,
-+};
-+
-+static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ int err;
-+
-+ /* 'generic_file_mmap()' takes care of NOMMU case */
-+ err = generic_file_mmap(file, vma);
-+ if (err)
-+ return err;
-+ vma->vm_ops = &ubifs_file_vm_ops;
-+ return 0;
-+}
-+#endif
-+
-+struct address_space_operations ubifs_file_address_operations = {
-+ .readpage = ubifs_readpage,
-+ .writepage = ubifs_writepage,
-+/* TODO: remove compatibility stuff as late as possible */
-+#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE
-+ .prepare_write = ubifs_prepare_write,
-+ .commit_write = ubifs_commit_write,
-+#else
-+ .write_begin = ubifs_write_begin,
-+ .write_end = ubifs_write_end,
-+#endif
-+ .invalidatepage = ubifs_invalidatepage,
-+ .set_page_dirty = ubifs_set_page_dirty,
-+ .releasepage = ubifs_releasepage,
-+};
-+
-+struct inode_operations ubifs_file_inode_operations = {
-+ .setattr = ubifs_setattr,
-+ .getattr = ubifs_getattr,
-+#ifdef CONFIG_UBIFS_FS_XATTR
-+ .setxattr = ubifs_setxattr,
-+ .getxattr = ubifs_getxattr,
-+ .listxattr = ubifs_listxattr,
-+ .removexattr = ubifs_removexattr,
-+#endif
-+};
-+
-+struct inode_operations ubifs_symlink_inode_operations = {
-+ .readlink = generic_readlink,
-+ .follow_link = ubifs_follow_link,
-+ .setattr = ubifs_setattr,
-+ .getattr = ubifs_getattr,
-+};
-+
-+struct file_operations ubifs_file_operations = {
-+ .llseek = generic_file_llseek,
-+ .read = do_sync_read,
-+ .write = ubifs_write,
-+ .aio_read = generic_file_aio_read,
-+ .aio_write = ubifs_aio_write,
-+ .mmap = ubifs_file_mmap,
-+ .fsync = ubifs_fsync,
-+ .unlocked_ioctl = ubifs_ioctl,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = ubifs_compat_ioctl,
-+#endif
-+};
---- linux-2.6.24.7.old/fs/ubifs/find.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/find.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,971 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file contains functions for finding LEBs for various purposes e.g.
-+ * garbage collection. In general, lprops category heaps and lists are used
-+ * for fast access, falling back on scanning the LPT as a last resort.
-+ */
-+
-+#include
-+#include "ubifs.h"
-+
-+/**
-+ * struct scan_data - data provided to scan callback functions
-+ * @min_space: minimum number of bytes for which to scan
-+ * @pick_free: whether it is OK to scan for empty LEBs
-+ * @lnum: LEB number found is returned here
-+ * @exclude_index: whether to exclude index LEBs
-+ */
-+struct scan_data {
-+ int min_space;
-+ int pick_free;
-+ int lnum;
-+ int exclude_index;
-+};
-+
-+/**
-+ * valuable - determine whether LEB properties are valuable.
-+ * @c: the UBIFS file-system description object
-+ * @lprops: LEB properties
-+ *
-+ * This function return %1 if the LEB properties should be added to the LEB
-+ * properties tree in memory. Otherwise %0 is returned.
-+ */
-+static int valuable(struct ubifs_info *c, const struct ubifs_lprops *lprops)
-+{
-+ int n, cat = lprops->flags & LPROPS_CAT_MASK;
-+ struct ubifs_lpt_heap *heap;
-+
-+ switch (cat) {
-+ case LPROPS_DIRTY:
-+ case LPROPS_DIRTY_IDX:
-+ case LPROPS_FREE:
-+ heap = &c->lpt_heap[cat - 1];
-+ if (heap->cnt < heap->max_cnt)
-+ return 1;
-+ if (lprops->free + lprops->dirty >= c->dark_wm)
-+ return 1;
-+ return 0;
-+ case LPROPS_EMPTY:
-+ n = c->lst.empty_lebs + c->freeable_cnt -
-+ c->lst.taken_empty_lebs;
-+ if (n < c->lsave_cnt)
-+ return 1;
-+ return 0;
-+ case LPROPS_FREEABLE:
-+ return 1;
-+ case LPROPS_FRDI_IDX:
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * scan_for_dirty_cb - dirty space scan callback.
-+ * @c: the UBIFS file-system description object
-+ * @lprops: LEB properties to scan
-+ * @in_tree: whether the LEB properties are in main memory
-+ * @data: information passed to and from the caller of the scan
-+ *
-+ * This function returns a code that indicates whether the scan should continue
-+ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
-+ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
-+ * (%LPT_SCAN_STOP).
-+ */
-+static int scan_for_dirty_cb(struct ubifs_info *c,
-+ const struct ubifs_lprops *lprops, int in_tree,
-+ struct scan_data *data)
-+{
-+ int ret = LPT_SCAN_CONTINUE;
-+
-+ /* Exclude LEBs that are currently in use */
-+ if (lprops->flags & LPROPS_TAKEN)
-+ return LPT_SCAN_CONTINUE;
-+ /* Determine whether to add these LEB properties to the tree */
-+ if (!in_tree && valuable(c, lprops))
-+ ret |= LPT_SCAN_ADD;
-+ /* Exclude LEBs with too little space */
-+ if (lprops->free + lprops->dirty < data->min_space)
-+ return ret;
-+ /* If specified, exclude index LEBs */
-+ if (data->exclude_index && lprops->flags & LPROPS_INDEX)
-+ return ret;
-+ /* If specified, exclude empty or freeable LEBs */
-+ if (!data->pick_free && lprops->free + lprops->dirty == c->leb_size)
-+ return ret;
-+ /* Exclude LEBs with too little dirty space (unless it is empty) */
-+ if (lprops->dirty < c->dead_wm && lprops->free != c->leb_size)
-+ return ret;
-+ /* Finally we found space */
-+ data->lnum = lprops->lnum;
-+ return LPT_SCAN_ADD | LPT_SCAN_STOP;
-+}
-+
-+/**
-+ * scan_for_dirty - find a data LEB with free space.
-+ * @c: the UBIFS file-system description object
-+ * @min_space: minimum amount free plus dirty space the returned LEB has to
-+ * have
-+ * @pick_free: if it is OK to return a free or freeable LEB
-+ * @exclude_index: whether to exclude index LEBs
-+ *
-+ * This function returns a pointer to the LEB properties found or a negative
-+ * error code.
-+ */
-+static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
-+ int min_space, int pick_free,
-+ int exclude_index)
-+{
-+ const struct ubifs_lprops *lprops;
-+ struct ubifs_lpt_heap *heap;
-+ struct scan_data data;
-+ int err, i;
-+
-+ /* There may be an LEB with enough dirty space on the free heap */
-+ heap = &c->lpt_heap[LPROPS_FREE - 1];
-+ for (i = 0; i < heap->cnt; i++) {
-+ lprops = heap->arr[i];
-+ if (lprops->free + lprops->dirty < min_space)
-+ continue;
-+ if (lprops->dirty < c->dead_wm)
-+ continue;
-+ return lprops;
-+ }
-+ /*
-+ * A LEB may have fallen off of the bottom of the dirty heap, and ended
-+ * up as uncategorized even though it has enough dirty space for us now,
-+ * so check the uncategorized list. N.B. neither empty nor freeable LEBs
-+ * can end up as uncategorized because they are kept on lists not
-+ * finite-sized heaps.
-+ */
-+ list_for_each_entry(lprops, &c->uncat_list, list) {
-+ if (lprops->flags & LPROPS_TAKEN)
-+ continue;
-+ if (lprops->free + lprops->dirty < min_space)
-+ continue;
-+ if (exclude_index && (lprops->flags & LPROPS_INDEX))
-+ continue;
-+ if (lprops->dirty < c->dead_wm)
-+ continue;
-+ return lprops;
-+ }
-+ /* We have looked everywhere in main memory, now scan the flash */
-+ if (c->pnodes_have >= c->pnode_cnt)
-+ /* All pnodes are in memory, so skip scan */
-+ return ERR_PTR(-ENOSPC);
-+ data.min_space = min_space;
-+ data.pick_free = pick_free;
-+ data.lnum = -1;
-+ data.exclude_index = exclude_index;
-+ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
-+ (ubifs_lpt_scan_callback)scan_for_dirty_cb,
-+ &data);
-+ if (err)
-+ return ERR_PTR(err);
-+ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
-+ c->lscan_lnum = data.lnum;
-+ lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
-+ if (IS_ERR(lprops))
-+ return lprops;
-+ ubifs_assert(lprops->lnum == data.lnum);
-+ ubifs_assert(lprops->free + lprops->dirty >= min_space);
-+ ubifs_assert(lprops->dirty >= c->dead_wm);
-+ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-+ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
-+ return lprops;
-+}
-+
-+/**
-+ * ubifs_find_dirty_leb - find a dirty LEB for the Garbage Collector.
-+ * @c: the UBIFS file-system description object
-+ * @ret_lp: LEB properties are returned here on exit
-+ * @min_space: minimum amount free plus dirty space the returned LEB has to
-+ * have
-+ * @pick_free: controls whether it is OK to pick empty or index LEBs
-+ *
-+ * This function tries to find a dirty logical eraseblock which has at least
-+ * @min_space free and dirty space. It prefers to take an LEB from the dirty or
-+ * dirty index heap, and it falls-back to LPT scanning if the heaps are empty
-+ * or do not have an LEB which satisfies the @min_space criteria.
-+ *
-+ * Note:
-+ * o LEBs which have less than dead watermark of dirty space are never picked
-+ * by this function;
-+ *
-+ * Returns zero and the LEB properties of
-+ * found dirty LEB in case of success, %-ENOSPC if no dirty LEB was found and a
-+ * negative error code in case of other failures. The returned LEB is marked as
-+ * "taken".
-+ *
-+ * The additional @pick_free argument controls if this function has to return a
-+ * free or freeable LEB if one is present. For example, GC must to set it to %1,
-+ * when called from the journal space reservation function, because the
-+ * appearance of free space may coincide with the loss of enough dirty space
-+ * for GC to succeed anyway.
-+ *
-+ * In contrast, if the Garbage Collector is called from budgeting, it should
-+ * just make free space, not return LEBs which are already free or freeable.
-+ *
-+ * In addition @pick_free is set to %2 by the recovery process in order to
-+ * recover gc_lnum in which case an index LEB must not be returned.
-+ */
-+int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
-+ int min_space, int pick_free)
-+{
-+ int err = 0, sum, exclude_index = pick_free == 2 ? 1 : 0;
-+ const struct ubifs_lprops *lp = NULL, *idx_lp = NULL;
-+ struct ubifs_lpt_heap *heap, *idx_heap;
-+
-+ ubifs_get_lprops(c);
-+
-+ if (pick_free) {
-+ int lebs, rsvd_idx_lebs = 0;
-+
-+ spin_lock(&c->space_lock);
-+ lebs = c->lst.empty_lebs;
-+ lebs += c->freeable_cnt - c->lst.taken_empty_lebs;
-+
-+ /*
-+ * Note, the index may consume more LEBs than have been reserved
-+ * for it. It is OK because it might be consolidated by GC.
-+ * But if the index takes fewer LEBs than it is reserved for it,
-+ * this function must avoid picking those reserved LEBs.
-+ */
-+ if (c->min_idx_lebs >= c->lst.idx_lebs) {
-+ rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs;
-+ exclude_index = 1;
-+ }
-+ spin_unlock(&c->space_lock);
-+
-+ /* Check if there are enough free LEBs for the index */
-+ if (rsvd_idx_lebs < lebs) {
-+ /* OK, try to find an empty LEB */
-+ lp = ubifs_fast_find_empty(c);
-+ if (lp)
-+ goto found;
-+
-+ /* Or a freeable LEB */
-+ lp = ubifs_fast_find_freeable(c);
-+ if (lp)
-+ goto found;
-+ } else
-+ /*
-+ * We cannot pick free/freeable LEBs in the below code.
-+ */
-+ pick_free = 0;
-+ } else {
-+ spin_lock(&c->space_lock);
-+ exclude_index = (c->min_idx_lebs >= c->lst.idx_lebs);
-+ spin_unlock(&c->space_lock);
-+ }
-+
-+ /* Look on the dirty and dirty index heaps */
-+ heap = &c->lpt_heap[LPROPS_DIRTY - 1];
-+ idx_heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
-+
-+ if (idx_heap->cnt && !exclude_index) {
-+ idx_lp = idx_heap->arr[0];
-+ sum = idx_lp->free + idx_lp->dirty;
-+ /*
-+ * Since we reserve twice as more space for the index than it
-+ * actually takes, it does not make sense to pick indexing LEBs
-+ * with less than half LEB of dirty space.
-+ */
-+ if (sum < min_space || sum < c->half_leb_size)
-+ idx_lp = NULL;
-+ }
-+
-+ if (heap->cnt) {
-+ lp = heap->arr[0];
-+ if (lp->dirty + lp->free < min_space)
-+ lp = NULL;
-+ }
-+
-+ /* Pick the LEB with most space */
-+ if (idx_lp && lp) {
-+ if (idx_lp->free + idx_lp->dirty >= lp->free + lp->dirty)
-+ lp = idx_lp;
-+ } else if (idx_lp && !lp)
-+ lp = idx_lp;
-+
-+ if (lp) {
-+ ubifs_assert(lp->dirty >= c->dead_wm);
-+ goto found;
-+ }
-+
-+ /* Did not find a dirty LEB on the dirty heaps, have to scan */
-+ dbg_find("scanning LPT for a dirty LEB");
-+ lp = scan_for_dirty(c, min_space, pick_free, exclude_index);
-+ if (IS_ERR(lp)) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+ ubifs_assert(lp->dirty >= c->dead_wm);
-+
-+found:
-+ dbg_find("found LEB %d, free %d, dirty %d, flags %#x",
-+ lp->lnum, lp->free, lp->dirty, lp->flags);
-+
-+ lp = ubifs_change_lp(c, lp, -1, -1, lp->flags | LPROPS_TAKEN, 0);
-+ if (IS_ERR(lp)) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+
-+ memcpy(ret_lp, lp, sizeof(struct ubifs_lprops));
-+
-+out:
-+ ubifs_release_lprops(c);
-+ return err;
-+}
-+
-+/**
-+ * scan_for_free_cb - free space scan callback.
-+ * @c: the UBIFS file-system description object
-+ * @lprops: LEB properties to scan
-+ * @in_tree: whether the LEB properties are in main memory
-+ * @data: information passed to and from the caller of the scan
-+ *
-+ * This function returns a code that indicates whether the scan should continue
-+ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
-+ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
-+ * (%LPT_SCAN_STOP).
-+ */
-+static int scan_for_free_cb(struct ubifs_info *c,
-+ const struct ubifs_lprops *lprops, int in_tree,
-+ struct scan_data *data)
-+{
-+ int ret = LPT_SCAN_CONTINUE;
-+
-+ /* Exclude LEBs that are currently in use */
-+ if (lprops->flags & LPROPS_TAKEN)
-+ return LPT_SCAN_CONTINUE;
-+ /* Determine whether to add these LEB properties to the tree */
-+ if (!in_tree && valuable(c, lprops))
-+ ret |= LPT_SCAN_ADD;
-+ /* Exclude index LEBs */
-+ if (lprops->flags & LPROPS_INDEX)
-+ return ret;
-+ /* Exclude LEBs with too little space */
-+ if (lprops->free < data->min_space)
-+ return ret;
-+ /* If specified, exclude empty LEBs */
-+ if (!data->pick_free && lprops->free == c->leb_size)
-+ return ret;
-+ /*
-+ * LEBs that have only free and dirty space must not be allocated
-+ * because they may have been unmapped already or they may have data
-+ * that is obsolete only because of nodes that are still sitting in a
-+ * wbuf.
-+ */
-+ if (lprops->free + lprops->dirty == c->leb_size && lprops->dirty > 0)
-+ return ret;
-+ /* Finally we found space */
-+ data->lnum = lprops->lnum;
-+ return LPT_SCAN_ADD | LPT_SCAN_STOP;
-+}
-+
-+/**
-+ * do_find_free_space - find a data LEB with free space.
-+ * @c: the UBIFS file-system description object
-+ * @min_space: minimum amount of free space required
-+ * @pick_free: whether it is OK to scan for empty LEBs
-+ * @squeeze: whether to try to find space in a non-empty LEB first
-+ *
-+ * This function returns a pointer to the LEB properties found or a negative
-+ * error code.
-+ */
-+static
-+const struct ubifs_lprops *do_find_free_space(struct ubifs_info *c,
-+ int min_space, int pick_free,
-+ int squeeze)
-+{
-+ const struct ubifs_lprops *lprops;
-+ struct ubifs_lpt_heap *heap;
-+ struct scan_data data;
-+ int err, i;
-+
-+ if (squeeze) {
-+ lprops = ubifs_fast_find_free(c);
-+ if (lprops && lprops->free >= min_space)
-+ return lprops;
-+ }
-+ if (pick_free) {
-+ lprops = ubifs_fast_find_empty(c);
-+ if (lprops)
-+ return lprops;
-+ }
-+ if (!squeeze) {
-+ lprops = ubifs_fast_find_free(c);
-+ if (lprops && lprops->free >= min_space)
-+ return lprops;
-+ }
-+ /* There may be an LEB with enough free space on the dirty heap */
-+ heap = &c->lpt_heap[LPROPS_DIRTY - 1];
-+ for (i = 0; i < heap->cnt; i++) {
-+ lprops = heap->arr[i];
-+ if (lprops->free >= min_space)
-+ return lprops;
-+ }
-+ /*
-+ * A LEB may have fallen off of the bottom of the free heap, and ended
-+ * up as uncategorized even though it has enough free space for us now,
-+ * so check the uncategorized list. N.B. neither empty nor freeable LEBs
-+ * can end up as uncategorized because they are kept on lists not
-+ * finite-sized heaps.
-+ */
-+ list_for_each_entry(lprops, &c->uncat_list, list) {
-+ if (lprops->flags & LPROPS_TAKEN)
-+ continue;
-+ if (lprops->flags & LPROPS_INDEX)
-+ continue;
-+ if (lprops->free >= min_space)
-+ return lprops;
-+ }
-+ /* We have looked everywhere in main memory, now scan the flash */
-+ if (c->pnodes_have >= c->pnode_cnt)
-+ /* All pnodes are in memory, so skip scan */
-+ return ERR_PTR(-ENOSPC);
-+ data.min_space = min_space;
-+ data.pick_free = pick_free;
-+ data.lnum = -1;
-+ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
-+ (ubifs_lpt_scan_callback)scan_for_free_cb,
-+ &data);
-+ if (err)
-+ return ERR_PTR(err);
-+ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
-+ c->lscan_lnum = data.lnum;
-+ lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
-+ if (IS_ERR(lprops))
-+ return lprops;
-+ ubifs_assert(lprops->lnum == data.lnum);
-+ ubifs_assert(lprops->free >= min_space);
-+ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-+ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
-+ return lprops;
-+}
-+
-+/**
-+ * ubifs_find_free_space - find a data LEB with free space.
-+ * @c: the UBIFS file-system description object
-+ * @min_space: minimum amount of required free space
-+ * @free: contains amount of free space in the LEB on exit
-+ * @squeeze: whether to try to find space in a non-empty LEB first
-+ *
-+ * This function looks for an LEB with at least @min_space bytes of free space.
-+ * It tries to find an empty LEB if possible. If no empty LEBs are available,
-+ * this function searches for a non-empty data LEB. The returned LEB is marked
-+ * as "taken".
-+ *
-+ * This function returns found LEB number in case of success, %-ENOSPC if it
-+ * failed to find a LEB with @min_space bytes of free space and other a negative
-+ * error codes in case of failure.
-+ */
-+int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free,
-+ int squeeze)
-+{
-+ const struct ubifs_lprops *lprops;
-+ int lebs, rsvd_idx_lebs, pick_free = 0, err, lnum, flags;
-+
-+ dbg_find("min_space %d", min_space);
-+ ubifs_assert(min_space > 0 && min_space <= c->dark_wm);
-+
-+ ubifs_get_lprops(c);
-+
-+ /* Check if there are enough empty LEBs for commit */
-+ spin_lock(&c->space_lock);
-+ if (c->min_idx_lebs > c->lst.idx_lebs)
-+ rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs;
-+ else
-+ rsvd_idx_lebs = 0;
-+ lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
-+ c->lst.taken_empty_lebs;
-+ ubifs_assert(lebs + c->lst.idx_lebs >= c->min_idx_lebs);
-+ if (rsvd_idx_lebs < lebs)
-+ /*
-+ * OK to allocate an empty LEB, but we still don't want to go
-+ * looking for one if there aren't any.
-+ */
-+ if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
-+ pick_free = 1;
-+ /*
-+ * Because we release the space lock, we must account
-+ * for this allocation here. After the LEB properties
-+ * flags have been updated, we subtract one. Note, the
-+ * result of this is that lprops also decreases
-+ * @taken_empty_lebs in 'ubifs_change_lp()', so it is
-+ * off by one for a short period of time which may
-+ * introduce a small disturbance to budgeting
-+ * calculations, but this is harmless because at the
-+ * worst case this would make the budgeting subsystem
-+ * be more pessimistic than needed.
-+ *
-+ * Fundamentally, this is about serialization of the
-+ * budgeting and lprops subsystems. We could make the
-+ * @space_lock a mutex and avoid dropping it before
-+ * calling 'ubifs_change_lp()', but mutex is more
-+ * heavy-weight, and we want budgeting to be as fast as
-+ * possible.
-+ */
-+ c->lst.taken_empty_lebs += 1;
-+ }
-+ spin_unlock(&c->space_lock);
-+
-+ lprops = do_find_free_space(c, min_space, pick_free, squeeze);
-+ if (IS_ERR(lprops)) {
-+ err = PTR_ERR(lprops);
-+ goto out;
-+ }
-+
-+ lnum = lprops->lnum;
-+ flags = lprops->flags | LPROPS_TAKEN;
-+
-+ lprops = ubifs_change_lp(c, lprops, -1, -1, flags, 0);
-+ if (IS_ERR(lprops)) {
-+ err = PTR_ERR(lprops);
-+ goto out;
-+ }
-+
-+ if (pick_free) {
-+ spin_lock(&c->space_lock);
-+ c->lst.taken_empty_lebs -= 1;
-+ spin_unlock(&c->space_lock);
-+ }
-+
-+ *free = lprops->free;
-+ ubifs_release_lprops(c);
-+
-+ if (*free == c->leb_size) {
-+ /*
-+ * Ensure that empty LEBs have been unmapped. They may not have
-+ * been, for example, because of an unclean unmount. Also
-+ * LEBs that were freeable LEBs (free + dirty == leb_size) will
-+ * not have been unmapped.
-+ */
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ }
-+
-+ dbg_find("found LEB %d, free %d", lnum, *free);
-+ ubifs_assert(*free >= min_space);
-+ return lnum;
-+
-+out:
-+ if (pick_free) {
-+ spin_lock(&c->space_lock);
-+ c->lst.taken_empty_lebs -= 1;
-+ spin_unlock(&c->space_lock);
-+ }
-+ ubifs_release_lprops(c);
-+ return err;
-+}
-+
-+/**
-+ * scan_for_idx_cb - callback used by the scan for a free LEB for the index.
-+ * @c: the UBIFS file-system description object
-+ * @lprops: LEB properties to scan
-+ * @in_tree: whether the LEB properties are in main memory
-+ * @data: information passed to and from the caller of the scan
-+ *
-+ * This function returns a code that indicates whether the scan should continue
-+ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
-+ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
-+ * (%LPT_SCAN_STOP).
-+ */
-+static int scan_for_idx_cb(struct ubifs_info *c,
-+ const struct ubifs_lprops *lprops, int in_tree,
-+ struct scan_data *data)
-+{
-+ int ret = LPT_SCAN_CONTINUE;
-+
-+ /* Exclude LEBs that are currently in use */
-+ if (lprops->flags & LPROPS_TAKEN)
-+ return LPT_SCAN_CONTINUE;
-+ /* Determine whether to add these LEB properties to the tree */
-+ if (!in_tree && valuable(c, lprops))
-+ ret |= LPT_SCAN_ADD;
-+ /* Exclude index LEBS */
-+ if (lprops->flags & LPROPS_INDEX)
-+ return ret;
-+ /* Exclude LEBs that cannot be made empty */
-+ if (lprops->free + lprops->dirty != c->leb_size)
-+ return ret;
-+ /*
-+ * We are allocating for the index so it is safe to allocate LEBs with
-+ * only free and dirty space, because write buffers are sync'd at commit
-+ * start.
-+ */
-+ data->lnum = lprops->lnum;
-+ return LPT_SCAN_ADD | LPT_SCAN_STOP;
-+}
-+
-+/**
-+ * scan_for_leb_for_idx - scan for a free LEB for the index.
-+ * @c: the UBIFS file-system description object
-+ */
-+static const struct ubifs_lprops *scan_for_leb_for_idx(struct ubifs_info *c)
-+{
-+ struct ubifs_lprops *lprops;
-+ struct scan_data data;
-+ int err;
-+
-+ data.lnum = -1;
-+ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
-+ (ubifs_lpt_scan_callback)scan_for_idx_cb,
-+ &data);
-+ if (err)
-+ return ERR_PTR(err);
-+ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
-+ c->lscan_lnum = data.lnum;
-+ lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
-+ if (IS_ERR(lprops))
-+ return lprops;
-+ ubifs_assert(lprops->lnum == data.lnum);
-+ ubifs_assert(lprops->free + lprops->dirty == c->leb_size);
-+ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-+ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
-+ return lprops;
-+}
-+
-+/**
-+ * ubifs_find_free_leb_for_idx - find a free LEB for the index.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function looks for a free LEB and returns that LEB number. The returned
-+ * LEB is marked as "taken", "index".
-+ *
-+ * Only empty LEBs are allocated. This is for two reasons. First, the commit
-+ * calculates the number of LEBs to allocate based on the assumption that they
-+ * will be empty. Secondly, free space at the end of an index LEB is not
-+ * guaranteed to be empty because it may have been used by the in-the-gaps
-+ * method prior to an unclean unmount.
-+ *
-+ * If no LEB is found %-ENOSPC is returned. For other failures another negative
-+ * error code is returned.
-+ */
-+int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
-+{
-+ const struct ubifs_lprops *lprops;
-+ int lnum = -1, err, flags;
-+
-+ ubifs_get_lprops(c);
-+
-+ lprops = ubifs_fast_find_empty(c);
-+ if (!lprops) {
-+ lprops = ubifs_fast_find_freeable(c);
-+ if (!lprops) {
-+ ubifs_assert(c->freeable_cnt == 0);
-+ if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
-+ lprops = scan_for_leb_for_idx(c);
-+ if (IS_ERR(lprops)) {
-+ err = PTR_ERR(lprops);
-+ goto out;
-+ }
-+ }
-+ }
-+ }
-+
-+ if (!lprops) {
-+ err = -ENOSPC;
-+ goto out;
-+ }
-+
-+ lnum = lprops->lnum;
-+
-+ dbg_find("found LEB %d, free %d, dirty %d, flags %#x",
-+ lnum, lprops->free, lprops->dirty, lprops->flags);
-+
-+ flags = lprops->flags | LPROPS_TAKEN | LPROPS_INDEX;
-+ lprops = ubifs_change_lp(c, lprops, c->leb_size, 0, flags, 0);
-+ if (IS_ERR(lprops)) {
-+ err = PTR_ERR(lprops);
-+ goto out;
-+ }
-+
-+ ubifs_release_lprops(c);
-+
-+ /*
-+ * Ensure that empty LEBs have been unmapped. They may not have been,
-+ * for example, because of an unclean unmount. Also LEBs that were
-+ * freeable LEBs (free + dirty == leb_size) will not have been unmapped.
-+ */
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err) {
-+ ubifs_change_one_lp(c, lnum, -1, -1, 0,
-+ LPROPS_TAKEN | LPROPS_INDEX, 0);
-+ return err;
-+ }
-+
-+ return lnum;
-+
-+out:
-+ ubifs_release_lprops(c);
-+ return err;
-+}
-+
-+static int cmp_dirty_idx(const struct ubifs_lprops **a,
-+ const struct ubifs_lprops **b)
-+{
-+ const struct ubifs_lprops *lpa = *a;
-+ const struct ubifs_lprops *lpb = *b;
-+
-+ return lpa->dirty + lpa->free - lpb->dirty - lpb->free;
-+}
-+
-+static void swap_dirty_idx(struct ubifs_lprops **a, struct ubifs_lprops **b,
-+ int size)
-+{
-+ struct ubifs_lprops *t = *a;
-+
-+ *a = *b;
-+ *b = t;
-+}
-+
-+/**
-+ * ubifs_save_dirty_idx_lnums - save an array of the most dirty index LEB nos.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function is called each commit to create an array of LEB numbers of
-+ * dirty index LEBs sorted in order of dirty and free space. This is used by
-+ * the in-the-gaps method of TNC commit.
-+ */
-+int ubifs_save_dirty_idx_lnums(struct ubifs_info *c)
-+{
-+ int i;
-+
-+ ubifs_get_lprops(c);
-+ /* Copy the LPROPS_DIRTY_IDX heap */
-+ c->dirty_idx.cnt = c->lpt_heap[LPROPS_DIRTY_IDX - 1].cnt;
-+ memcpy(c->dirty_idx.arr, c->lpt_heap[LPROPS_DIRTY_IDX - 1].arr,
-+ sizeof(void *) * c->dirty_idx.cnt);
-+ /* Sort it so that the dirtiest is now at the end */
-+ sort(c->dirty_idx.arr, c->dirty_idx.cnt, sizeof(void *),
-+ (int (*)(const void *, const void *))cmp_dirty_idx,
-+ (void (*)(void *, void *, int))swap_dirty_idx);
-+ dbg_find("found %d dirty index LEBs", c->dirty_idx.cnt);
-+ if (c->dirty_idx.cnt)
-+ dbg_find("dirtiest index LEB is %d with dirty %d and free %d",
-+ c->dirty_idx.arr[c->dirty_idx.cnt - 1]->lnum,
-+ c->dirty_idx.arr[c->dirty_idx.cnt - 1]->dirty,
-+ c->dirty_idx.arr[c->dirty_idx.cnt - 1]->free);
-+ /* Replace the lprops pointers with LEB numbers */
-+ for (i = 0; i < c->dirty_idx.cnt; i++)
-+ c->dirty_idx.arr[i] = (void *)(size_t)c->dirty_idx.arr[i]->lnum;
-+ ubifs_release_lprops(c);
-+ return 0;
-+}
-+
-+/**
-+ * scan_dirty_idx_cb - callback used by the scan for a dirty index LEB.
-+ * @c: the UBIFS file-system description object
-+ * @lprops: LEB properties to scan
-+ * @in_tree: whether the LEB properties are in main memory
-+ * @data: information passed to and from the caller of the scan
-+ *
-+ * This function returns a code that indicates whether the scan should continue
-+ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
-+ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
-+ * (%LPT_SCAN_STOP).
-+ */
-+static int scan_dirty_idx_cb(struct ubifs_info *c,
-+ const struct ubifs_lprops *lprops, int in_tree,
-+ struct scan_data *data)
-+{
-+ int ret = LPT_SCAN_CONTINUE;
-+
-+ /* Exclude LEBs that are currently in use */
-+ if (lprops->flags & LPROPS_TAKEN)
-+ return LPT_SCAN_CONTINUE;
-+ /* Determine whether to add these LEB properties to the tree */
-+ if (!in_tree && valuable(c, lprops))
-+ ret |= LPT_SCAN_ADD;
-+ /* Exclude non-index LEBs */
-+ if (!(lprops->flags & LPROPS_INDEX))
-+ return ret;
-+ /* Exclude LEBs with too little space */
-+ if (lprops->free + lprops->dirty < c->min_idx_node_sz)
-+ return ret;
-+ /* Finally we found space */
-+ data->lnum = lprops->lnum;
-+ return LPT_SCAN_ADD | LPT_SCAN_STOP;
-+}
-+
-+/**
-+ * find_dirty_idx_leb - find a dirty index LEB.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function returns LEB number upon success and a negative error code upon
-+ * failure. In particular, -ENOSPC is returned if a dirty index LEB is not
-+ * found.
-+ *
-+ * Note that this function scans the entire LPT but it is called very rarely.
-+ */
-+static int find_dirty_idx_leb(struct ubifs_info *c)
-+{
-+ const struct ubifs_lprops *lprops;
-+ struct ubifs_lpt_heap *heap;
-+ struct scan_data data;
-+ int err, i, ret;
-+
-+ /* Check all structures in memory first */
-+ data.lnum = -1;
-+ heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
-+ for (i = 0; i < heap->cnt; i++) {
-+ lprops = heap->arr[i];
-+ ret = scan_dirty_idx_cb(c, lprops, 1, &data);
-+ if (ret & LPT_SCAN_STOP)
-+ goto found;
-+ }
-+ list_for_each_entry(lprops, &c->frdi_idx_list, list) {
-+ ret = scan_dirty_idx_cb(c, lprops, 1, &data);
-+ if (ret & LPT_SCAN_STOP)
-+ goto found;
-+ }
-+ list_for_each_entry(lprops, &c->uncat_list, list) {
-+ ret = scan_dirty_idx_cb(c, lprops, 1, &data);
-+ if (ret & LPT_SCAN_STOP)
-+ goto found;
-+ }
-+ if (c->pnodes_have >= c->pnode_cnt)
-+ /* All pnodes are in memory, so skip scan */
-+ return -ENOSPC;
-+ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
-+ (ubifs_lpt_scan_callback)scan_dirty_idx_cb,
-+ &data);
-+ if (err)
-+ return err;
-+found:
-+ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
-+ c->lscan_lnum = data.lnum;
-+ lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
-+ if (IS_ERR(lprops))
-+ return PTR_ERR(lprops);
-+ ubifs_assert(lprops->lnum == data.lnum);
-+ ubifs_assert(lprops->free + lprops->dirty >= c->min_idx_node_sz);
-+ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-+ ubifs_assert((lprops->flags & LPROPS_INDEX));
-+
-+ dbg_find("found dirty LEB %d, free %d, dirty %d, flags %#x",
-+ lprops->lnum, lprops->free, lprops->dirty, lprops->flags);
-+
-+ lprops = ubifs_change_lp(c, lprops, -1, -1,
-+ lprops->flags | LPROPS_TAKEN, 0);
-+ if (IS_ERR(lprops))
-+ return PTR_ERR(lprops);
-+
-+ return lprops->lnum;
-+}
-+
-+/**
-+ * get_idx_gc_leb - try to get a LEB number from trivial GC.
-+ * @c: the UBIFS file-system description object
-+ */
-+static int get_idx_gc_leb(struct ubifs_info *c)
-+{
-+ const struct ubifs_lprops *lp;
-+ int err, lnum;
-+
-+ err = ubifs_get_idx_gc_leb(c);
-+ if (err < 0)
-+ return err;
-+ lnum = err;
-+ /*
-+ * The LEB was due to be unmapped after the commit but
-+ * it is needed now for this commit.
-+ */
-+ lp = ubifs_lpt_lookup_dirty(c, lnum);
-+ if (unlikely(IS_ERR(lp)))
-+ return PTR_ERR(lp);
-+ lp = ubifs_change_lp(c, lp, -1, -1, lp->flags | LPROPS_INDEX, -1);
-+ if (unlikely(IS_ERR(lp)))
-+ return PTR_ERR(lp);
-+ dbg_find("LEB %d, dirty %d and free %d flags %#x",
-+ lp->lnum, lp->dirty, lp->free, lp->flags);
-+ return lnum;
-+}
-+
-+/**
-+ * find_dirtiest_idx_leb - find dirtiest index LEB from dirtiest array.
-+ * @c: the UBIFS file-system description object
-+ */
-+static int find_dirtiest_idx_leb(struct ubifs_info *c)
-+{
-+ const struct ubifs_lprops *lp;
-+ int lnum;
-+
-+ while (1) {
-+ if (!c->dirty_idx.cnt)
-+ return -ENOSPC;
-+ /* The lprops pointers were replaced by LEB numbers */
-+ lnum = (size_t)c->dirty_idx.arr[--c->dirty_idx.cnt];
-+ lp = ubifs_lpt_lookup(c, lnum);
-+ if (IS_ERR(lp))
-+ return PTR_ERR(lp);
-+ if ((lp->flags & LPROPS_TAKEN) || !(lp->flags & LPROPS_INDEX))
-+ continue;
-+ lp = ubifs_change_lp(c, lp, -1, -1,
-+ lp->flags | LPROPS_TAKEN, 0);
-+ if (IS_ERR(lp))
-+ return PTR_ERR(lp);
-+ break;
-+ }
-+ dbg_find("LEB %d, dirty %d and free %d flags %#x", lp->lnum, lp->dirty,
-+ lp->free, lp->flags);
-+ ubifs_assert(lp->flags | LPROPS_TAKEN);
-+ ubifs_assert(lp->flags | LPROPS_INDEX);
-+ return lnum;
-+}
-+
-+/**
-+ * ubifs_find_dirty_idx_leb - try to find dirtiest index LEB as at last commit.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function attempts to find an untaken index LEB with the most free and
-+ * dirty space that can be used without overwriting index nodes that were in the
-+ * last index committed.
-+ */
-+int ubifs_find_dirty_idx_leb(struct ubifs_info *c)
-+{
-+ int err;
-+
-+ ubifs_get_lprops(c);
-+
-+ /*
-+ * We made an array of the dirtiest index LEB numbers as at the start of
-+ * last commit. Try that array first.
-+ */
-+ err = find_dirtiest_idx_leb(c);
-+
-+ /* Next try scanning the entire LPT */
-+ if (err == -ENOSPC)
-+ err = find_dirty_idx_leb(c);
-+
-+ /* Finally take any index LEBs awaiting trivial GC */
-+ if (err == -ENOSPC)
-+ err = get_idx_gc_leb(c);
-+
-+ ubifs_release_lprops(c);
-+ return err;
-+}
---- linux-2.6.24.7.old/fs/ubifs/gc.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/gc.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,762 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file implements garbage collection. The procedure for garbage collection
-+ * is different depending on whether a LEB as an index LEB (contains index
-+ * nodes) or not. For non-index LEBs, garbage collection finds a LEB which
-+ * contains a lot of dirty space (obsolete nodes), and copies the non-obsolete
-+ * nodes to the journal, at which point the garbage-collected LEB is free to be
-+ * reused. For index LEBs, garbage collection marks the non-obsolete index nodes
-+ * dirty in the TNC, and after the next commit, the garbage-collected LEB is
-+ * to be reused. Garbage collection will cause the number of dirty index nodes
-+ * to grow, however sufficient space is reserved for the index to ensure the
-+ * commit will never run out of space.
-+ */
-+
-+#include
-+#include "ubifs.h"
-+
-+/*
-+ * GC tries to optimize the way it fit nodes to available space, and it sorts
-+ * nodes a little. The below constants are watermarks which define "large",
-+ * "medium", and "small" nodes.
-+ */
-+#define MEDIUM_NODE_WM (UBIFS_BLOCK_SIZE / 4)
-+#define SMALL_NODE_WM UBIFS_MAX_DENT_NODE_SZ
-+
-+/*
-+ * GC may need to move more then one LEB to make progress. The below constants
-+ * define "soft" and "hard" limits on the number of LEBs the garbage collector
-+ * may move.
-+ */
-+#define SOFT_LEBS_LIMIT 4
-+#define HARD_LEBS_LIMIT 32
-+
-+/**
-+ * switch_gc_head - switch the garbage collection journal head.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer to write
-+ * @len: length of the buffer to write
-+ * @lnum: LEB number written is returned here
-+ * @offs: offset written is returned here
-+ *
-+ * This function switch the GC head to the next LEB which is reserved in
-+ * @c->gc_lnum. Returns %0 in case of success, %-EAGAIN if commit is required,
-+ * and other negative error code in case of failures.
-+ */
-+static int switch_gc_head(struct ubifs_info *c)
-+{
-+ int err, gc_lnum = c->gc_lnum;
-+ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
-+
-+ ubifs_assert(gc_lnum != -1);
-+ dbg_gc("switch GC head from LEB %d:%d to LEB %d (waste %d bytes)",
-+ wbuf->lnum, wbuf->offs + wbuf->used, gc_lnum,
-+ c->leb_size - wbuf->offs - wbuf->used);
-+
-+ err = ubifs_wbuf_sync_nolock(wbuf);
-+ if (err)
-+ return err;
-+
-+ /*
-+ * The GC write-buffer was synchronized, we may safely unmap
-+ * 'c->gc_lnum'.
-+ */
-+ err = ubifs_leb_unmap(c, gc_lnum);
-+ if (err)
-+ return err;
-+
-+ err = ubifs_add_bud_to_log(c, GCHD, gc_lnum, 0);
-+ if (err)
-+ return err;
-+
-+ c->gc_lnum = -1;
-+ err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0, UBI_LONGTERM);
-+ return err;
-+}
-+
-+/**
-+ * move_nodes - move nodes.
-+ * @c: UBIFS file-system description object
-+ * @sleb: describes nodes to move
-+ *
-+ * This function moves valid nodes from data LEB described by @sleb to the GC
-+ * journal head. The obsolete nodes are dropped.
-+ *
-+ * When moving nodes we have to deal with classical bin-packing problem: the
-+ * space in the current GC journal head LEB and in @c->gc_lnum are the "bins",
-+ * where the nodes in the @sleb->nodes list are the elements which should be
-+ * fit optimally to the bins. This function uses the "first fit decreasing"
-+ * strategy, although it does not really sort the nodes but just split them on
-+ * 3 classes - large, medium, and small, so they are roughly sorted.
-+ *
-+ * This function returns zero in case of success, %-EAGAIN if commit is
-+ * required, and other negative error codes in case of other failures.
-+ */
-+static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
-+{
-+ struct ubifs_scan_node *snod, *tmp;
-+ struct list_head large, medium, small;
-+ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
-+ int avail, err, min = INT_MAX;
-+
-+ INIT_LIST_HEAD(&large);
-+ INIT_LIST_HEAD(&medium);
-+ INIT_LIST_HEAD(&small);
-+
-+ list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
-+ struct list_head *lst;
-+
-+ ubifs_assert(snod->type != UBIFS_IDX_NODE);
-+ ubifs_assert(snod->type != UBIFS_REF_NODE);
-+ ubifs_assert(snod->type != UBIFS_CS_NODE);
-+
-+ err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum,
-+ snod->offs, 0);
-+ if (err < 0)
-+ goto out;
-+
-+ lst = &snod->list;
-+ list_del(lst);
-+ if (!err) {
-+ /* The node is obsolete, remove it from the list */
-+ kfree(snod);
-+ continue;
-+ }
-+
-+ /*
-+ * Sort the list of nodes so that large nodes go first, and
-+ * small nodes go last.
-+ */
-+ if (snod->len > MEDIUM_NODE_WM)
-+ list_add(lst, &large);
-+ else if (snod->len > SMALL_NODE_WM)
-+ list_add(lst, &medium);
-+ else
-+ list_add(lst, &small);
-+
-+ /* And find the smallest node */
-+ if (snod->len < min)
-+ min = snod->len;
-+ }
-+
-+ /*
-+ * Join the tree lists so that we'd have one roughly sorted list
-+ * ('large' will be the head of the joined list).
-+ */
-+ list_splice(&medium, large.prev);
-+ list_splice(&small, large.prev);
-+
-+ if (wbuf->lnum == -1) {
-+ /*
-+ * The GC journal head is not set, because it is the first GC
-+ * invocation since mount.
-+ */
-+ err = switch_gc_head(c);
-+ if (err)
-+ goto out;
-+ }
-+
-+ /* Write nodes to their new location. Use the first-fit strategy */
-+ while (1) {
-+ avail = c->leb_size - wbuf->offs - wbuf->used;
-+ list_for_each_entry_safe(snod, tmp, &large, list) {
-+ int new_lnum, new_offs;
-+
-+ if (avail < min)
-+ break;
-+
-+ if (snod->len > avail)
-+ /* This node does not fit */
-+ continue;
-+
-+ cond_resched();
-+
-+ new_lnum = wbuf->lnum;
-+ new_offs = wbuf->offs + wbuf->used;
-+ err = ubifs_wbuf_write_nolock(wbuf, snod->node,
-+ snod->len);
-+
-+ err = ubifs_tnc_replace(c, &snod->key, sleb->lnum,
-+ snod->offs, new_lnum, new_offs,
-+ snod->len);
-+ if (err)
-+ goto out;
-+
-+ avail = c->leb_size - wbuf->offs - wbuf->used;
-+ list_del(&snod->list);
-+ kfree(snod);
-+ }
-+
-+ if (list_empty(&large))
-+ break;
-+
-+ /*
-+ * Waste the rest of the space in the LEB and switch to the
-+ * next LEB.
-+ */
-+ err = switch_gc_head(c);
-+ if (err)
-+ goto out;
-+ }
-+
-+ return 0;
-+
-+out:
-+ list_for_each_entry_safe(snod, tmp, &large, list) {
-+ list_del(&snod->list);
-+ kfree(snod);
-+ }
-+ return err;
-+}
-+
-+/**
-+ * gc_sync_wbufs - sync write-buffers for GC.
-+ * @c: UBIFS file-system description object
-+ *
-+ * We must guarantee that obsoleting nodes are on flash. Unfortunately they may
-+ * be in a write-buffer instead. That is, a node could be written to a
-+ * write-buffer, obsoleting another node in a LEB that is GC'd. If that LEB is
-+ * erased before the write-buffer is sync'd and then there is an unclean
-+ * unmount, then an existing node is lost. To avoid this, we sync all
-+ * write-buffers.
-+ *
-+ * This function returns %0 on success or a negative error code on failure.
-+ */
-+static int gc_sync_wbufs(struct ubifs_info *c)
-+{
-+ int err, i;
-+
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ if (i == GCHD)
-+ continue;
-+ err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
-+ if (err)
-+ return err;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_garbage_collect_leb - garbage-collect a logical eraseblock.
-+ * @c: UBIFS file-system description object
-+ * @lp: describes the LEB to garbage collect
-+ *
-+ * This function garbage-collects an LEB and returns one of the @LEB_FREED,
-+ * @LEB_RETAINED, etc positive codes in case of success, %-EAGAIN if commit is
-+ * required, and other negative error codes in case of failures.
-+ */
-+int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
-+{
-+ struct ubifs_scan_leb *sleb;
-+ struct ubifs_scan_node *snod;
-+ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
-+ int err = 0, lnum = lp->lnum;
-+
-+ ubifs_assert(c->gc_lnum != -1 || wbuf->offs + wbuf->used == 0 ||
-+ c->need_recovery);
-+ ubifs_assert(c->gc_lnum != lnum);
-+ ubifs_assert(wbuf->lnum != lnum);
-+
-+ /*
-+ * We scan the entire LEB even though we only really need to scan up to
-+ * (c->leb_size - lp->free).
-+ */
-+ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
-+ if (IS_ERR(sleb))
-+ return PTR_ERR(sleb);
-+
-+ ubifs_assert(!list_empty(&sleb->nodes));
-+ snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
-+
-+ if (snod->type == UBIFS_IDX_NODE) {
-+ struct ubifs_gced_idx_leb *idx_gc;
-+
-+ dbg_gc("indexing LEB %d (free %d, dirty %d)",
-+ lnum, lp->free, lp->dirty);
-+ list_for_each_entry(snod, &sleb->nodes, list) {
-+ struct ubifs_idx_node *idx = snod->node;
-+ int level = le16_to_cpu(idx->level);
-+
-+ ubifs_assert(snod->type == UBIFS_IDX_NODE);
-+ key_read(c, ubifs_idx_key(c, idx), &snod->key);
-+ err = ubifs_dirty_idx_node(c, &snod->key, level, lnum,
-+ snod->offs);
-+ if (err)
-+ goto out;
-+ }
-+
-+ idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS);
-+ if (!idx_gc) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ idx_gc->lnum = lnum;
-+ idx_gc->unmap = 0;
-+ list_add(&idx_gc->list, &c->idx_gc);
-+
-+ /*
-+ * Don't release the LEB until after the next commit, because
-+ * it may contain date which is needed for recovery. So
-+ * although we freed this LEB, it will become usable only after
-+ * the commit.
-+ */
-+ err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0,
-+ LPROPS_INDEX, 1);
-+ if (err)
-+ goto out;
-+ err = LEB_FREED_IDX;
-+ } else {
-+ dbg_gc("data LEB %d (free %d, dirty %d)",
-+ lnum, lp->free, lp->dirty);
-+
-+ err = move_nodes(c, sleb);
-+ if (err)
-+ goto out;
-+
-+ err = gc_sync_wbufs(c);
-+ if (err)
-+ goto out;
-+
-+ err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0);
-+ if (err)
-+ goto out;
-+
-+ if (c->gc_lnum == -1) {
-+ c->gc_lnum = lnum;
-+ err = LEB_RETAINED;
-+ } else {
-+ err = ubifs_wbuf_sync_nolock(wbuf);
-+ if (err)
-+ goto out;
-+
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ goto out;
-+
-+ err = LEB_FREED;
-+ }
-+ }
-+
-+out:
-+ ubifs_scan_destroy(sleb);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_garbage_collect - UBIFS garbage collector.
-+ * @c: UBIFS file-system description object
-+ * @anyway: do GC even if there are free LEBs
-+ *
-+ * This function does out-of-place garbage collection. The return codes are:
-+ * o positive LEB number if the LEB has been freed and may be used;
-+ * o %-EAGAIN if the caller has to run commit;
-+ * o %-ENOSPC if GC failed to make any progress;
-+ * o other negative error codes in case of other errors.
-+ *
-+ * Garbage collector writes data to the journal when GC'ing data LEBs, and just
-+ * marking indexing nodes dirty when GC'ing indexing LEBs. Thus, at some point
-+ * commit may be required. But commit cannot be run from inside GC, because the
-+ * caller might be holding the commit lock, so %-EAGAIN is returned instead;
-+ * And this error code means that the caller has to run commit, and re-run GC
-+ * if there is still no free space.
-+ *
-+ * There are many reasons why this function may return %-EAGAIN:
-+ * o the log is full and there is no space to write an LEB reference for
-+ * @c->gc_lnum;
-+ * o the journal is too large and exceeds size limitations;
-+ * o GC moved indexing LEBs, but they can be used only after the commit;
-+ * o the shrinker fails to find clean znodes to free and requests the commit;
-+ * o etc.
-+ *
-+ * Note, if the file-system is close to be full, this function may return
-+ * %-EAGAIN infinitely, so the caller has to limit amount of re-invocations of
-+ * the function. E.g., this happens if the limits on the journal size are too
-+ * tough and GC writes too much to the journal before an LEB is freed. This
-+ * might also mean that the journal is too large, and the TNC becomes to big,
-+ * so that the shrinker is constantly called, finds not clean znodes to free,
-+ * and requests commit. Well, this may also happen if the journal is all right,
-+ * but another kernel process consumes too much memory. Anyway, infinite
-+ * %-EAGAIN may happen, but in some extreme/misconfiguration cases.
-+ */
-+int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
-+{
-+ int i, err, ret, min_space = c->dead_wm;
-+ struct ubifs_lprops lp;
-+ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
-+
-+ ubifs_assert_cmt_locked(c);
-+
-+ if (ubifs_gc_should_commit(c))
-+ return -EAGAIN;
-+
-+ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
-+ /* We expect the write-buffer to be empty on entry */
-+ ubifs_assert(!wbuf->used);
-+
-+ for (i = 0; ; i++) {
-+ int space_before = c->leb_size - wbuf->offs - wbuf->used;
-+ int space_after;
-+
-+ cond_resched();
-+
-+ /* Give the commit an opportunity to run */
-+ if (ubifs_gc_should_commit(c)) {
-+ ret = -EAGAIN;
-+ break;
-+ }
-+
-+ if (i > SOFT_LEBS_LIMIT && !list_empty(&c->idx_gc)) {
-+ /*
-+ * We've done enough iterations. Indexing LEBs were
-+ * moved and will be available after the commit.
-+ */
-+ dbg_gc("soft limit, some index LEBs GC'ed, -EAGAIN");
-+ ubifs_commit_required(c);
-+ ret = -EAGAIN;
-+ break;
-+ }
-+
-+ if (i > HARD_LEBS_LIMIT) {
-+ /*
-+ * We've moved too many LEBs and have not made
-+ * progress, give up.
-+ */
-+ dbg_gc("hard limit, -ENOSPC");
-+ ret = -ENOSPC;
-+ break;
-+ }
-+
-+ /*
-+ * Empty and freeable LEBs can turn up while we waited for
-+ * the wbuf lock, or while we have been running GC. In that
-+ * case, we should just return one of those instead of
-+ * continuing to GC dirty LEBs. Hence we request
-+ * 'ubifs_find_dirty_leb()' to return an empty LEB if it can.
-+ */
-+ ret = ubifs_find_dirty_leb(c, &lp, min_space, anyway ? 0 : 1);
-+ if (ret) {
-+ if (ret == -ENOSPC)
-+ dbg_gc("no more dirty LEBs");
-+ break;
-+ }
-+
-+ dbg_gc("found LEB %d: free %d, dirty %d, sum %d "
-+ "(min. space %d)", lp.lnum, lp.free, lp.dirty,
-+ lp.free + lp.dirty, min_space);
-+
-+ if (lp.free + lp.dirty == c->leb_size) {
-+ /* An empty LEB was returned */
-+ dbg_gc("LEB %d is free, return it", lp.lnum);
-+ /*
-+ * ubifs_find_dirty_leb() doesn't return freeable index
-+ * LEBs.
-+ */
-+ ubifs_assert(!(lp.flags & LPROPS_INDEX));
-+ if (lp.free != c->leb_size) {
-+ /*
-+ * Write buffers must be sync'd before
-+ * unmapping freeable LEBs, because one of them
-+ * may contain data which obsoletes something
-+ * in 'lp.pnum'.
-+ */
-+ ret = gc_sync_wbufs(c);
-+ if (ret)
-+ goto out;
-+ ret = ubifs_change_one_lp(c, lp.lnum,
-+ c->leb_size, 0, 0, 0,
-+ 0);
-+ if (ret)
-+ goto out;
-+ }
-+ ret = ubifs_leb_unmap(c, lp.lnum);
-+ if (ret)
-+ goto out;
-+ ret = lp.lnum;
-+ break;
-+ }
-+
-+ space_before = c->leb_size - wbuf->offs - wbuf->used;
-+ if (wbuf->lnum == -1)
-+ space_before = 0;
-+
-+ ret = ubifs_garbage_collect_leb(c, &lp);
-+ if (ret < 0) {
-+ if (ret == -EAGAIN || ret == -ENOSPC) {
-+ /*
-+ * These codes are not errors, so we have to
-+ * return the LEB to lprops. But if the
-+ * 'ubifs_return_leb()' function fails, its
-+ * failure code is propagated to the caller
-+ * instead of the original '-EAGAIN' or
-+ * '-ENOSPC'.
-+ */
-+ err = ubifs_return_leb(c, lp.lnum);
-+ if (err)
-+ ret = err;
-+ break;
-+ }
-+ goto out;
-+ }
-+
-+ if (ret == LEB_FREED) {
-+ /* An LEB has been freed and is ready for use */
-+ dbg_gc("LEB %d freed, return", lp.lnum);
-+ ret = lp.lnum;
-+ break;
-+ }
-+
-+ if (ret == LEB_FREED_IDX) {
-+ /*
-+ * This was an indexing LEB and it cannot be
-+ * immediately used. And instead of requesting the
-+ * commit straight away, we try to garbage collect some
-+ * more.
-+ */
-+ dbg_gc("indexing LEB %d freed, continue", lp.lnum);
-+ continue;
-+ }
-+
-+ ubifs_assert(ret == LEB_RETAINED);
-+ space_after = c->leb_size - wbuf->offs - wbuf->used;
-+ dbg_gc("LEB %d retained, freed %d bytes", lp.lnum,
-+ space_after - space_before);
-+
-+ if (space_after > space_before) {
-+ /* GC makes progress, keep working */
-+ min_space >>= 1;
-+ if (min_space < c->dead_wm)
-+ min_space = c->dead_wm;
-+ continue;
-+ }
-+
-+ dbg_gc("did not make progress");
-+
-+ /*
-+ * GC moved an LEB bud have not done any progress. This means
-+ * that the previous GC head LEB contained too few free space
-+ * and the LEB which was GC'ed contained only large nodes which
-+ * did not fit that space.
-+ *
-+ * We can do 2 things:
-+ * 1. pick another LEB in a hope it'll contain a small node
-+ * which will fit the space we have at the end of current GC
-+ * head LEB, but there is no guarantee, so we try this out
-+ * unless we have already been working for too long;
-+ * 2. request an LEB with more dirty space, which will force
-+ * 'ubifs_find_dirty_leb()' to start scanning the lprops
-+ * table, instead of just picking one from the heap
-+ * (previously it already picked the dirtiest LEB).
-+ */
-+ if (i < SOFT_LEBS_LIMIT) {
-+ dbg_gc("try again");
-+ continue;
-+ }
-+
-+ min_space <<= 1;
-+ if (min_space > c->dark_wm)
-+ min_space = c->dark_wm;
-+ dbg_gc("set min. space to %d", min_space);
-+ }
-+
-+ if (ret == -ENOSPC && !list_empty(&c->idx_gc)) {
-+ dbg_gc("no space, some index LEBs GC'ed, -EAGAIN");
-+ ubifs_commit_required(c);
-+ ret = -EAGAIN;
-+ }
-+
-+ err = ubifs_wbuf_sync_nolock(wbuf);
-+ if (!err)
-+ err = ubifs_leb_unmap(c, c->gc_lnum);
-+ if (err)
-+ ret = err;
-+ mutex_unlock(&wbuf->io_mutex);
-+ return ret;
-+
-+out:
-+ ubifs_assert(ret < 0);
-+ ubifs_assert(ret != -ENOSPC && ret != -EAGAIN);
-+ ubifs_wbuf_sync_nolock(wbuf);
-+ mutex_unlock(&wbuf->io_mutex);
-+ ubifs_return_leb(c, lp.lnum);
-+ return ret;
-+}
-+
-+/**
-+ * ubifs_gc_start_commit - garbage collection at start of commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * If a LEB has only dirty and free space, then we may safely unmap it and make
-+ * it free. Note, we cannot do this with indexing LEBs because dirty space may
-+ * correspond index nodes that are required for recovery. In that case, the
-+ * LEB cannot be unmapped until after the next commit.
-+ *
-+ * This function returns %0 upon success and a negative error code upon failure.
-+ */
-+int ubifs_gc_start_commit(struct ubifs_info *c)
-+{
-+ struct ubifs_gced_idx_leb *idx_gc;
-+ const struct ubifs_lprops *lp;
-+ int err = 0, flags;
-+
-+ ubifs_get_lprops(c);
-+
-+ /*
-+ * Unmap (non-index) freeable LEBs. Note that recovery requires that all
-+ * wbufs are sync'd before this, which is done in 'do_commit()'.
-+ */
-+ while (1) {
-+ lp = ubifs_fast_find_freeable(c);
-+ if (unlikely(IS_ERR(lp))) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+ if (!lp)
-+ break;
-+ ubifs_assert(!(lp->flags & LPROPS_TAKEN));
-+ ubifs_assert(!(lp->flags & LPROPS_INDEX));
-+ err = ubifs_leb_unmap(c, lp->lnum);
-+ if (err)
-+ goto out;
-+ lp = ubifs_change_lp(c, lp, c->leb_size, 0, lp->flags, 0);
-+ if (unlikely(IS_ERR(lp))) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+ ubifs_assert(!(lp->flags & LPROPS_TAKEN));
-+ ubifs_assert(!(lp->flags & LPROPS_INDEX));
-+ }
-+
-+ /* Mark GC'd index LEBs OK to unmap after this commit finishes */
-+ list_for_each_entry(idx_gc, &c->idx_gc, list)
-+ idx_gc->unmap = 1;
-+
-+ /* Record index freeable LEBs for unmapping after commit */
-+ while (1) {
-+ lp = ubifs_fast_find_frdi_idx(c);
-+ if (unlikely(IS_ERR(lp))) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+ if (!lp)
-+ break;
-+ idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS);
-+ if (!idx_gc) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+ ubifs_assert(!(lp->flags & LPROPS_TAKEN));
-+ ubifs_assert(lp->flags & LPROPS_INDEX);
-+ /* Don't release the LEB until after the next commit */
-+ flags = (lp->flags | LPROPS_TAKEN) ^ LPROPS_INDEX;
-+ lp = ubifs_change_lp(c, lp, c->leb_size, 0, flags, 1);
-+ if (unlikely(IS_ERR(lp))) {
-+ err = PTR_ERR(lp);
-+ kfree(idx_gc);
-+ goto out;
-+ }
-+ ubifs_assert(lp->flags & LPROPS_TAKEN);
-+ ubifs_assert(!(lp->flags & LPROPS_INDEX));
-+ idx_gc->lnum = lp->lnum;
-+ idx_gc->unmap = 1;
-+ list_add(&idx_gc->list, &c->idx_gc);
-+ }
-+out:
-+ ubifs_release_lprops(c);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_gc_end_commit - garbage collection at end of commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function completes out-of-place garbage collection of index LEBs.
-+ */
-+int ubifs_gc_end_commit(struct ubifs_info *c)
-+{
-+ struct ubifs_gced_idx_leb *idx_gc, *tmp;
-+ struct ubifs_wbuf *wbuf;
-+ int err = 0;
-+
-+ wbuf = &c->jheads[GCHD].wbuf;
-+ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
-+ list_for_each_entry_safe(idx_gc, tmp, &c->idx_gc, list)
-+ if (idx_gc->unmap) {
-+ dbg_gc("LEB %d", idx_gc->lnum);
-+ err = ubifs_leb_unmap(c, idx_gc->lnum);
-+ if (err)
-+ goto out;
-+ err = ubifs_change_one_lp(c, idx_gc->lnum, -1, -1, 0,
-+ LPROPS_TAKEN, -1);
-+ if (err)
-+ goto out;
-+ list_del(&idx_gc->list);
-+ kfree(idx_gc);
-+ }
-+out:
-+ mutex_unlock(&wbuf->io_mutex);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_destroy_idx_gc - destroy idx_gc list.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function destroys the idx_gc list. It is called when unmounting or
-+ * remounting read-only so locks are not needed.
-+ */
-+void ubifs_destroy_idx_gc(struct ubifs_info *c)
-+{
-+ while (!list_empty(&c->idx_gc)) {
-+ struct ubifs_gced_idx_leb *idx_gc;
-+
-+ idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb,
-+ list);
-+ c->idx_gc_cnt -= 1;
-+ list_del(&idx_gc->list);
-+ kfree(idx_gc);
-+ }
-+
-+}
-+
-+/**
-+ * ubifs_get_idx_gc_leb - get a LEB from GC'd index LEB list.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Called during start commit so locks are not needed.
-+ */
-+int ubifs_get_idx_gc_leb(struct ubifs_info *c)
-+{
-+ struct ubifs_gced_idx_leb *idx_gc;
-+ int lnum;
-+
-+ if (list_empty(&c->idx_gc))
-+ return -ENOSPC;
-+ idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, list);
-+ lnum = idx_gc->lnum;
-+ /* c->idx_gc_cnt is updated by the caller when lprops are updated */
-+ list_del(&idx_gc->list);
-+ kfree(idx_gc);
-+ return lnum;
-+}
---- linux-2.6.24.7.old/fs/ubifs/io.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/io.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,921 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ * Copyright (C) 2006, 2007 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ * Zoltan Sogor
-+ */
-+
-+/*
-+ * This file implements UBIFS I/O subsystem which provides various I/O-related
-+ * helper functions (reading/writing/checking/validating nodes) and implements
-+ * write-buffering support. Write buffers help to save space which otherwise
-+ * would have been wasted for padding to the nearest minimal I/O unit boundary.
-+ * Instead, data first goes to the write-buffer and is flushed when the
-+ * buffer is full or when it is not used for some time (by timer). This is
-+ * similarto the mechanism is used by JFFS2.
-+ *
-+ * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by
-+ * mutexes defined inside these objects. Since sometimes upper-level code
-+ * has to lock the write-buffer (e.g. journal space reservation code), many
-+ * functions related to write-buffers have "nolock" suffix which means that the
-+ * caller has to lock the write-buffer before calling this function.
-+ *
-+ * UBIFS stores nodes at 64 bit-aligned addresses. If the node length is not
-+ * aligned, UBIFS starts the next node from the aligned address, and the padded
-+ * bytes may contain any rubbish. In other words, UBIFS does not put padding
-+ * bytes in those small gaps. Common headers of nodes store real node lengths,
-+ * not aligned lengths. Indexing nodes also store real lengths in branches.
-+ *
-+ * UBIFS uses padding when it pads to the next min. I/O unit. In this case it
-+ * uses padding nodes or padding bytes, if the padding node does not fit.
-+ *
-+ * All UBIFS nodes are protected by CRC checksums and UBIFS checks all nodes
-+ * every time they are read from the flash media.
-+ */
-+
-+#include
-+#include "ubifs.h"
-+
-+/**
-+ * ubifs_check_node - check node.
-+ * @c: UBIFS file-system description object
-+ * @buf: node to check
-+ * @lnum: logical eraseblock number
-+ * @offs: offset within the logical eraseblock
-+ * @quiet: print no messages
-+ *
-+ * This function checks node magic number and CRC checksum. This function also
-+ * validates node length to prevent UBIFS from becoming crazy when an attacker
-+ * feeds it a file-system image with incorrect nodes. For example, too large
-+ * node length in the common header could cause UBIFS to read memory outside of
-+ * allocated buffer when checking the CRC checksum.
-+ *
-+ * This function returns zero in case of success %-EUCLEAN in case of bad CRC
-+ * or magic.
-+ */
-+int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
-+ int offs, int quiet)
-+{
-+ int err = -EINVAL, type, node_len;
-+ uint32_t crc, node_crc, magic;
-+ const struct ubifs_ch *ch = buf;
-+
-+ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
-+ ubifs_assert(!(offs & 7) && offs < c->leb_size);
-+
-+ magic = le32_to_cpu(ch->magic);
-+ if (magic != UBIFS_NODE_MAGIC) {
-+ if (!quiet)
-+ ubifs_err("bad magic %#08x, expected %#08x",
-+ magic, UBIFS_NODE_MAGIC);
-+ err = -EUCLEAN;
-+ goto out;
-+ }
-+
-+ type = ch->node_type;
-+ if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) {
-+ if (!quiet)
-+ ubifs_err("bad node type %d", type);
-+ goto out;
-+ }
-+
-+ node_len = le32_to_cpu(ch->len);
-+ if (node_len + offs > c->leb_size)
-+ goto out_len;
-+
-+ if (c->ranges[type].max_len == 0) {
-+ if (node_len != c->ranges[type].len)
-+ goto out_len;
-+ } else if (node_len < c->ranges[type].min_len ||
-+ node_len > c->ranges[type].max_len)
-+ goto out_len;
-+
-+ crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
-+ node_crc = le32_to_cpu(ch->crc);
-+ if (crc != node_crc) {
-+ if (!quiet)
-+ ubifs_err("bad CRC: calculated %#08x, read %#08x",
-+ crc, node_crc);
-+ err = -EUCLEAN;
-+ goto out;
-+ }
-+
-+ return 0;
-+
-+out_len:
-+ if (!quiet)
-+ ubifs_err("bad node length %d", node_len);
-+out:
-+ if (!quiet) {
-+ ubifs_err("bad node at LEB %d:%d", lnum, offs);
-+ dbg_dump_node(c, buf);
-+ dbg_dump_stack();
-+ }
-+ return err;
-+}
-+
-+/**
-+ * ubifs_pad - pad flash space.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer to put padding to
-+ * @pad: how many bytes to pad
-+ *
-+ * The flash media obliges us to write only in chunks of %c->min_io_size and
-+ * when we have to write less data we add padding node to the write-buffer and
-+ * pad it to the next minimal I/O unit's boundary. Padding nodes help when the
-+ * media is being scanned. If the amount of wasted space is not enough to fit a
-+ * padding node which takes %UBIFS_PAD_NODE_SZ bytes, we write padding bytes
-+ * pattern (%UBIFS_PADDING_BYTE).
-+ *
-+ * Padding nodes are also used to fill gaps when the "commit-in-gaps" method is
-+ * used.
-+ */
-+void ubifs_pad(const struct ubifs_info *c, void *buf, int pad)
-+{
-+ uint32_t crc;
-+
-+ ubifs_assert(pad >= 0 && !(pad & 7));
-+
-+ if (pad >= UBIFS_PAD_NODE_SZ) {
-+ struct ubifs_ch *ch = buf;
-+ struct ubifs_pad_node *pad_node = buf;
-+
-+ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
-+ ch->node_type = UBIFS_PAD_NODE;
-+ ch->group_type = UBIFS_NO_NODE_GROUP;
-+ ch->padding[0] = ch->padding[1] = 0;
-+ ch->sqnum = 0;
-+ ch->len = cpu_to_le32(UBIFS_PAD_NODE_SZ);
-+ pad -= UBIFS_PAD_NODE_SZ;
-+ pad_node->pad_len = cpu_to_le32(pad);
-+ crc = crc32(UBIFS_CRC32_INIT, buf + 8, UBIFS_PAD_NODE_SZ - 8);
-+ ch->crc = cpu_to_le32(crc);
-+ memset(buf + UBIFS_PAD_NODE_SZ, 0, pad);
-+ } else if (pad > 0)
-+ /* Too little space, padding node won't fit */
-+ memset(buf, UBIFS_PADDING_BYTE, pad);
-+}
-+
-+/**
-+ * next_sqnum - get next sequence number.
-+ * @c: UBIFS file-system description object
-+ */
-+static unsigned long long next_sqnum(struct ubifs_info *c)
-+{
-+ unsigned long long sqnum;
-+
-+ spin_lock(&c->cnt_lock);
-+ sqnum = ++c->max_sqnum;
-+ spin_unlock(&c->cnt_lock);
-+
-+ if (unlikely(sqnum >= SQNUM_WARN_WATERMARK)) {
-+ if (sqnum >= SQNUM_WATERMARK) {
-+ ubifs_err("sequence number overflow %llu, end of life",
-+ sqnum);
-+ ubifs_ro_mode(c, -EINVAL);
-+ }
-+ ubifs_warn("running out of sequence numbers, end of life soon");
-+ }
-+
-+ return sqnum;
-+}
-+
-+/**
-+ * ubifs_prepare_node - prepare node to be written to flash.
-+ * @c: UBIFS file-system description object
-+ * @node: the node to pad
-+ * @len: node length
-+ * @pad: if the buffer has to be padded
-+ *
-+ * This function prepares node at @node to be written to the media - it
-+ * calculates node CRC, fills the common header, and adds proper padding up to
-+ * the next minimum I/O unit if @pad is not zero.
-+ */
-+void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad)
-+{
-+ uint32_t crc;
-+ struct ubifs_ch *ch = node;
-+ unsigned long long sqnum = next_sqnum(c);
-+
-+ ubifs_assert(len >= UBIFS_CH_SZ);
-+
-+ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
-+ ch->len = cpu_to_le32(len);
-+ ch->group_type = UBIFS_NO_NODE_GROUP;
-+ ch->sqnum = cpu_to_le64(sqnum);
-+ ch->padding[0] = ch->padding[1] = 0;
-+ crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8);
-+ ch->crc = cpu_to_le32(crc);
-+
-+ if (pad) {
-+ len = ALIGN(len, 8);
-+ pad = ALIGN(len, c->min_io_size) - len;
-+ ubifs_pad(c, node + len, pad);
-+ }
-+}
-+
-+/**
-+ * ubifs_prep_grp_node - prepare node of a group to be written to flash.
-+ * @c: UBIFS file-system description object
-+ * @node: the node to pad
-+ * @len: node length
-+ * @last: indicates the last node of the group
-+ *
-+ * This function prepares node at @node to be written to the media - it
-+ * calculates node CRC and fills the common header.
-+ */
-+void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last)
-+{
-+ uint32_t crc;
-+ struct ubifs_ch *ch = node;
-+ unsigned long long sqnum = next_sqnum(c);
-+
-+ ubifs_assert(len >= UBIFS_CH_SZ);
-+
-+ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
-+ ch->len = cpu_to_le32(len);
-+ if (last)
-+ ch->group_type = UBIFS_LAST_OF_NODE_GROUP;
-+ else
-+ ch->group_type = UBIFS_IN_NODE_GROUP;
-+ ch->sqnum = cpu_to_le64(sqnum);
-+ ch->padding[0] = ch->padding[1] = 0;
-+ crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8);
-+ ch->crc = cpu_to_le32(crc);
-+}
-+
-+/**
-+ * wbuf_timer_callback - write-buffer timer callback function.
-+ * @data: timer data (write-buffer descriptor)
-+ *
-+ * This function is called when the write-buffer timer expires.
-+ */
-+static void wbuf_timer_callback_nolock(unsigned long data)
-+{
-+ struct ubifs_wbuf *wbuf = (struct ubifs_wbuf *)data;
-+
-+ wbuf->need_sync = 1;
-+ wbuf->c->need_wbuf_sync = 1;
-+ ubifs_wake_up_bgt(wbuf->c);
-+}
-+
-+/**
-+ * new_wbuf_timer - start new write-buffer timer.
-+ * @wbuf: write-buffer descriptor
-+ */
-+static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
-+{
-+ ubifs_assert(!timer_pending(&wbuf->timer));
-+
-+ if (!wbuf->timeout)
-+ return;
-+
-+ wbuf->timer.expires = jiffies + wbuf->timeout;
-+ add_timer(&wbuf->timer);
-+}
-+
-+/**
-+ * cancel_wbuf_timer - cancel write-buffer timer.
-+ * @wbuf: write-buffer descriptor
-+ */
-+static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
-+{
-+ /*
-+ * If the syncer is waiting for the lock (from the background thread's
-+ * context) and another task is changing write-buffer then the syncing
-+ * should be canceled.
-+ */
-+ wbuf->need_sync = 0;
-+ del_timer(&wbuf->timer);
-+}
-+
-+/**
-+ * ubifs_wbuf_sync_nolock - synchronize write-buffer.
-+ * @wbuf: write-buffer to synchronize
-+ *
-+ * This function synchronizes write-buffer @buf and returns zero in case of
-+ * success or a negative error code in case of failure.
-+ */
-+int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
-+{
-+ struct ubifs_info *c = wbuf->c;
-+ int err, dirt;
-+
-+ cancel_wbuf_timer_nolock(wbuf);
-+ if (!wbuf->used || wbuf->lnum == -1)
-+ /* Write-buffer is empty or not seeked */
-+ return 0;
-+
-+ dbg_io("LEB %d:%d, %d bytes",
-+ wbuf->lnum, wbuf->offs, wbuf->used);
-+ ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
-+ ubifs_assert(!(wbuf->avail & 7));
-+ ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
-+
-+ if (c->ro_media)
-+ return -EROFS;
-+
-+ ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail);
-+ err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
-+ c->min_io_size, wbuf->dtype);
-+ if (err) {
-+ ubifs_err("cannot write %d bytes to LEB %d:%d",
-+ c->min_io_size, wbuf->lnum, wbuf->offs);
-+ dbg_dump_stack();
-+ return err;
-+ }
-+
-+ dirt = wbuf->avail;
-+
-+ spin_lock(&wbuf->lock);
-+ wbuf->offs += c->min_io_size;
-+ wbuf->avail = c->min_io_size;
-+ wbuf->used = 0;
-+ wbuf->next_ino = 0;
-+ spin_unlock(&wbuf->lock);
-+
-+ if (wbuf->sync_callback)
-+ err = wbuf->sync_callback(c, wbuf->lnum,
-+ c->leb_size - wbuf->offs, dirt);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_wbuf_seek_nolock - seek write-buffer.
-+ * @wbuf: write-buffer
-+ * @lnum: logical eraseblock number to seek to
-+ * @offs: logical eraseblock offset to seek to
-+ * @dtype: data type
-+ *
-+ * This function targets the write buffer to logical eraseblock @lnum:@offs.
-+ * The write-buffer is synchronized if it is not empty. Returns zero in case of
-+ * success and a negative error code in case of failure.
-+ */
-+int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
-+ int dtype)
-+{
-+ const struct ubifs_info *c = wbuf->c;
-+
-+ dbg_io("LEB %d:%d", lnum, offs);
-+ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt);
-+ ubifs_assert(offs >= 0 && offs <= c->leb_size);
-+ ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7));
-+ ubifs_assert(lnum != wbuf->lnum);
-+
-+ if (wbuf->used > 0) {
-+ int err = ubifs_wbuf_sync_nolock(wbuf);
-+
-+ if (err)
-+ return err;
-+ }
-+
-+ spin_lock(&wbuf->lock);
-+ wbuf->lnum = lnum;
-+ wbuf->offs = offs;
-+ wbuf->avail = c->min_io_size;
-+ wbuf->used = 0;
-+ spin_unlock(&wbuf->lock);
-+ wbuf->dtype = dtype;
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_bg_wbufs_sync - synchronize write-buffers.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function is called by background thread to synchronize write-buffers.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+int ubifs_bg_wbufs_sync(struct ubifs_info *c)
-+{
-+ int err, i;
-+
-+ if (!c->need_wbuf_sync)
-+ return 0;
-+ c->need_wbuf_sync = 0;
-+
-+ if (c->ro_media) {
-+ err = -EROFS;
-+ goto out_timers;
-+ }
-+
-+ dbg_io("synchronize");
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;
-+
-+ cond_resched();
-+
-+ /*
-+ * If the mutex is locked then wbuf is being changed, so
-+ * synchronization is not necessary.
-+ */
-+ if (mutex_is_locked(&wbuf->io_mutex))
-+ continue;
-+
-+ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
-+ if (!wbuf->need_sync) {
-+ mutex_unlock(&wbuf->io_mutex);
-+ continue;
-+ }
-+
-+ err = ubifs_wbuf_sync_nolock(wbuf);
-+ mutex_unlock(&wbuf->io_mutex);
-+ if (err) {
-+ ubifs_err("cannot sync write-buffer, error %d", err);
-+ ubifs_ro_mode(c, err);
-+ goto out_timers;
-+ }
-+ }
-+
-+ return 0;
-+
-+out_timers:
-+ /* Cancel all timers to prevent repeated errors */
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;
-+
-+ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
-+ cancel_wbuf_timer_nolock(wbuf);
-+ mutex_unlock(&wbuf->io_mutex);
-+ }
-+ return err;
-+}
-+
-+/**
-+ * ubifs_wbuf_write_nolock - write data to flash via write-buffer.
-+ * @wbuf: write-buffer
-+ * @buf: node to write
-+ * @len: node length
-+ *
-+ * This function writes data to flash via write-buffer @wbuf. This means that
-+ * the last piece of the node won't reach the flash media immediately if it
-+ * does not take whole minimal I/O unit. Instead, the node will sit in RAM
-+ * until the write-buffer is synchronized (e.g., by timer).
-+ *
-+ * This function returns zero in case of success and a negative error code in
-+ * case of failure. If the node cannot be written because there is no more
-+ * space in this logical eraseblock, %-ENOSPC is returned.
-+ */
-+int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
-+{
-+ struct ubifs_info *c = wbuf->c;
-+ int err, written, n, aligned_len = ALIGN(len, 8), offs;
-+
-+ dbg_io("%d bytes (%s) to wbuf at LEB %d:%d", len,
-+ dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->lnum,
-+ wbuf->offs + wbuf->used);
-+ ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
-+ ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
-+ ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
-+ ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
-+ ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
-+
-+ if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
-+ err = -ENOSPC;
-+ goto out;
-+ }
-+
-+ cancel_wbuf_timer_nolock(wbuf);
-+
-+ if (c->ro_media)
-+ return -EROFS;
-+
-+ if (aligned_len <= wbuf->avail) {
-+ /*
-+ * The node is not very large and fits entirely within
-+ * write-buffer.
-+ */
-+ memcpy(wbuf->buf + wbuf->used, buf, len);
-+
-+ if (aligned_len == wbuf->avail) {
-+ dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum,
-+ wbuf->offs);
-+ err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
-+ wbuf->offs, c->min_io_size,
-+ wbuf->dtype);
-+ if (err)
-+ goto out;
-+
-+ spin_lock(&wbuf->lock);
-+ wbuf->offs += c->min_io_size;
-+ wbuf->avail = c->min_io_size;
-+ wbuf->used = 0;
-+ wbuf->next_ino = 0;
-+ spin_unlock(&wbuf->lock);
-+ } else {
-+ spin_lock(&wbuf->lock);
-+ wbuf->avail -= aligned_len;
-+ wbuf->used += aligned_len;
-+ spin_unlock(&wbuf->lock);
-+ }
-+
-+ goto exit;
-+ }
-+
-+ /*
-+ * The node is large enough and does not fit entirely within current
-+ * minimal I/O unit. We have to fill and flush write-buffer and switch
-+ * to the next min. I/O unit.
-+ */
-+ dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, wbuf->offs);
-+ memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
-+ err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
-+ c->min_io_size, wbuf->dtype);
-+ if (err)
-+ goto out;
-+
-+ offs = wbuf->offs + c->min_io_size;
-+ len -= wbuf->avail;
-+ aligned_len -= wbuf->avail;
-+ written = wbuf->avail;
-+
-+ /*
-+ * The remaining data may take more whole min. I/O units, so write the
-+ * remains multiple to min. I/O unit size directly to the flash media.
-+ * We align node length to 8-byte boundary because we anyway flash wbuf
-+ * if the remaining space is less than 8 bytes.
-+ */
-+ n = aligned_len >> c->min_io_shift;
-+ if (n) {
-+ n <<= c->min_io_shift;
-+ dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum, offs);
-+ err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written, offs, n,
-+ wbuf->dtype);
-+ if (err)
-+ goto out;
-+ offs += n;
-+ aligned_len -= n;
-+ len -= n;
-+ written += n;
-+ }
-+
-+ spin_lock(&wbuf->lock);
-+ if (aligned_len)
-+ /*
-+ * And now we have what's left and what does not take whole
-+ * min. I/O unit, so write it to the write-buffer and we are
-+ * done.
-+ */
-+ memcpy(wbuf->buf, buf + written, len);
-+
-+ wbuf->offs = offs;
-+ wbuf->used = aligned_len;
-+ wbuf->avail = c->min_io_size - aligned_len;
-+ wbuf->next_ino = 0;
-+ spin_unlock(&wbuf->lock);
-+
-+exit:
-+ if (wbuf->sync_callback) {
-+ int free = c->leb_size - wbuf->offs - wbuf->used;
-+
-+ err = wbuf->sync_callback(c, wbuf->lnum, free, 0);
-+ if (err)
-+ goto out;
-+ }
-+
-+ if (wbuf->used)
-+ new_wbuf_timer_nolock(wbuf);
-+
-+ return 0;
-+
-+out:
-+ ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
-+ len, wbuf->lnum, wbuf->offs, err);
-+ dbg_dump_node(c, buf);
-+ dbg_dump_stack();
-+ dbg_dump_leb(c, wbuf->lnum);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_write_node - write node to the media.
-+ * @c: UBIFS file-system description object
-+ * @buf: the node to write
-+ * @len: node length
-+ * @lnum: logical eraseblock number
-+ * @offs: offset within the logical eraseblock
-+ * @dtype: node life-time hint (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
-+ *
-+ * This function automatically fills node magic number, assigns sequence
-+ * number, and calculates node CRC checksum. The length of the @buf buffer has
-+ * to be aligned to the minimal I/O unit size. This function automatically
-+ * appends padding node and padding bytes if needed. Returns zero in case of
-+ * success and a negative error code in case of failure.
-+ */
-+int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
-+ int offs, int dtype)
-+{
-+ int err, buf_len = ALIGN(len, c->min_io_size);
-+
-+ dbg_io("LEB %d:%d, %s, length %d (aligned %d)",
-+ lnum, offs, dbg_ntype(((struct ubifs_ch *)buf)->node_type), len,
-+ buf_len);
-+ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
-+ ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
-+
-+ if (c->ro_media)
-+ return -EROFS;
-+
-+ ubifs_prepare_node(c, buf, len, 1);
-+ err = ubi_leb_write(c->ubi, lnum, buf, offs, buf_len, dtype);
-+ if (err) {
-+ ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
-+ buf_len, lnum, offs, err);
-+ dbg_dump_node(c, buf);
-+ dbg_dump_stack();
-+ }
-+
-+ return err;
-+}
-+
-+/**
-+ * ubifs_read_node_wbuf - read node from the media or write-buffer.
-+ * @wbuf: wbuf to check for un-written data
-+ * @buf: buffer to read to
-+ * @type: node type
-+ * @len: node length
-+ * @lnum: logical eraseblock number
-+ * @offs: offset within the logical eraseblock
-+ *
-+ * This function reads a node of known type and length, checks it and stores
-+ * in @buf. If the node partially or fully sits in the write-buffer, this
-+ * function takes data from the buffer, otherwise it reads the flash media.
-+ * Returns zero in case of success, %-EUCLEAN if CRC mismatched and a negative
-+ * error code in case of failure.
-+ */
-+int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
-+ int lnum, int offs)
-+{
-+ const struct ubifs_info *c = wbuf->c;
-+ int err, rlen, overlap;
-+ struct ubifs_ch *ch = buf;
-+
-+ dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
-+ ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
-+ ubifs_assert(!(offs & 7) && offs < c->leb_size);
-+ ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
-+
-+ spin_lock(&wbuf->lock);
-+ overlap = (lnum == wbuf->lnum && offs + len > wbuf->offs);
-+ if (!overlap) {
-+ /* We may safely unlock the write-buffer and read the data */
-+ spin_unlock(&wbuf->lock);
-+ return ubifs_read_node(c, buf, type, len, lnum, offs);
-+ }
-+
-+ /* Don't read under wbuf */
-+ rlen = wbuf->offs - offs;
-+ if (rlen < 0)
-+ rlen = 0;
-+
-+ /* Copy the rest from the write-buffer */
-+ memcpy(buf + rlen, wbuf->buf + offs + rlen - wbuf->offs, len - rlen);
-+ spin_unlock(&wbuf->lock);
-+
-+ if (rlen > 0) {
-+ /* Read everything that goes before write-buffer */
-+ err = ubi_read(c->ubi, lnum, buf, offs, rlen);
-+ if (err && err != -EBADMSG) {
-+ ubifs_err("failed to read node %d from LEB %d:%d, "
-+ "error %d", type, lnum, offs, err);
-+ dbg_dump_stack();
-+ return err;
-+ }
-+ }
-+
-+ err = ubifs_check_node(c, buf, lnum, offs, 0);
-+ if (err) {
-+ ubifs_err("expected node type %d", type);
-+ return err;
-+ }
-+
-+ if (type != ch->node_type) {
-+ ubifs_err("bad node type (%d but expected %d)",
-+ ch->node_type, type);
-+ goto out;
-+ }
-+
-+ rlen = le32_to_cpu(ch->len);
-+ if (rlen != len) {
-+ ubifs_err("bad node length %d, expected %d", rlen, len);
-+ goto out;
-+ }
-+
-+ return 0;
-+
-+out:
-+ ubifs_err("bad node at LEB %d:%d", lnum, offs);
-+ dbg_dump_node(c, buf);
-+ dbg_dump_stack();
-+ return -EINVAL;
-+}
-+
-+/**
-+ * ubifs_read_node - read node.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer to read to
-+ * @type: node type
-+ * @len: node length (not aligned)
-+ * @lnum: logical eraseblock number
-+ * @offs: offset within the logical eraseblock
-+ *
-+ * This function reads a node of known type and and length, checks it and
-+ * stores in @buf. Returns zero in case of success, %-EUCLEAN if CRC mismatched
-+ * and a negative error code in case of failure.
-+ */
-+int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
-+ int lnum, int offs)
-+{
-+ int err, l;
-+ struct ubifs_ch *ch = buf;
-+
-+ dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
-+ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
-+ ubifs_assert(len >= UBIFS_CH_SZ && offs + len <= c->leb_size);
-+ ubifs_assert(!(offs & 7) && offs < c->leb_size);
-+ ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
-+
-+ err = ubi_read(c->ubi, lnum, buf, offs, len);
-+ if (err && err != -EBADMSG) {
-+ ubifs_err("cannot read node %d from LEB %d:%d, error %d",
-+ type, lnum, offs, err);
-+ return err;
-+ }
-+
-+ err = ubifs_check_node(c, buf, lnum, offs, 0);
-+ if (err) {
-+ ubifs_err("expected node type %d", type);
-+ return err;
-+ }
-+
-+ if (type != ch->node_type) {
-+ ubifs_err("bad node type (%d but expected %d)",
-+ ch->node_type, type);
-+ goto out;
-+ }
-+
-+ l = le32_to_cpu(ch->len);
-+ if (l != len) {
-+ ubifs_err("bad node length %d, expected %d", l, len);
-+ goto out;
-+ }
-+
-+ return 0;
-+
-+out:
-+ ubifs_err("bad node at LEB %d:%d", lnum, offs);
-+ dbg_dump_node(c, buf);
-+ dbg_dump_stack();
-+ return -EINVAL;
-+}
-+
-+/**
-+ * ubifs_wbuf_init - initialize write-buffer.
-+ * @c: UBIFS file-system description object
-+ * @wbuf: write-buffer to initialize
-+ *
-+ * This function initializes write buffer. Returns zero in case of success
-+ * %-ENOMEM in case of failure.
-+ */
-+int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
-+{
-+ size_t size;
-+
-+ wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL);
-+ if (!wbuf->buf)
-+ return -ENOMEM;
-+
-+ size = (c->min_io_size / UBIFS_CH_SZ + 1) * sizeof(ino_t);
-+ wbuf->inodes = kmalloc(size, GFP_KERNEL);
-+ if (!wbuf->inodes) {
-+ kfree(wbuf->buf);
-+ wbuf->buf = NULL;
-+ return -ENOMEM;
-+ }
-+
-+ wbuf->used = 0;
-+ wbuf->lnum = wbuf->offs = -1;
-+ wbuf->avail = c->min_io_size;
-+ wbuf->dtype = UBI_UNKNOWN;
-+ wbuf->sync_callback = NULL;
-+ mutex_init(&wbuf->io_mutex);
-+ spin_lock_init(&wbuf->lock);
-+
-+ wbuf->c = c;
-+ init_timer(&wbuf->timer);
-+ wbuf->timer.function = wbuf_timer_callback_nolock;
-+ wbuf->timer.data = (unsigned long)wbuf;
-+ wbuf->timeout = DEFAULT_WBUF_TIMEOUT;
-+ wbuf->next_ino = 0;
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array.
-+ * @wbuf: the write-buffer whereto add
-+ * @inum: the inode number
-+ *
-+ * This function adds an inode number to the inode array of the write-buffer.
-+ */
-+void ubifs_wbuf_add_ino_nolock(struct ubifs_wbuf *wbuf, ino_t inum)
-+{
-+ if (!wbuf->buf)
-+ /* NOR flash or something similar */
-+ return;
-+
-+ spin_lock(&wbuf->lock);
-+ if (wbuf->used)
-+ wbuf->inodes[wbuf->next_ino++] = inum;
-+ spin_unlock(&wbuf->lock);
-+}
-+
-+/**
-+ * wbuf_has_ino - returns if the wbuf contains data from the inode.
-+ * @wbuf: the write-buffer
-+ * @inum: the inode number
-+ *
-+ * This function returns with %1 if the write-buffer contains some data from the
-+ * given inode otherwise it returns with %0.
-+ */
-+static int wbuf_has_ino(struct ubifs_wbuf *wbuf, ino_t inum)
-+{
-+ int i, ret = 0;
-+
-+ spin_lock(&wbuf->lock);
-+ for (i = 0; i < wbuf->next_ino; i++)
-+ if (inum == wbuf->inodes[i]) {
-+ ret = 1;
-+ break;
-+ }
-+ spin_unlock(&wbuf->lock);
-+
-+ return ret;
-+}
-+
-+/**
-+ * ubifs_sync_wbufs_by_inodes - synchronize write-buffers which have data.
-+ * belonging to specified inodes.
-+ * @c: UBIFS file-system description object
-+ * @inodes: array of inodes
-+ * @count: number of elements in @inodes
-+ *
-+ * This function synchronizes write-buffers which contain nodes belonging to
-+ * any inode specified in @inodes array. Returns zero in case of success and a
-+ * negative error code in case of failure.
-+ */
-+int ubifs_sync_wbufs_by_inodes(struct ubifs_info *c,
-+ struct inode * const *inodes, int count)
-+{
-+ int i, j, err = 0;
-+
-+ ubifs_assert(count);
-+
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;
-+
-+ if (i == GCHD)
-+ /*
-+ * GC head is special, do not look at it. Even if the
-+ * head contains something related to this inode, it is
-+ * a _copy_ of corresponding on-flash node which sits
-+ * somewhere else.
-+ */
-+ continue;
-+
-+ for (j = 0; j < count && !err; j++)
-+ if (wbuf_has_ino(wbuf, inodes[j]->i_ino)) {
-+ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
-+ if (wbuf_has_ino(wbuf, inodes[j]->i_ino))
-+ err = ubifs_wbuf_sync_nolock(wbuf);
-+ mutex_unlock(&wbuf->io_mutex);
-+ break;
-+ }
-+
-+ if (err) {
-+ ubifs_ro_mode(c, err);
-+ break;
-+ }
-+ }
-+
-+ return err;
-+}
---- linux-2.6.24.7.old/fs/ubifs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/ioctl.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,204 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ * Copyright (C) 2006, 2007 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Zoltan Sogor
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/* This file implements EXT2-compatible extended attribute ioctl() calls */
-+
-+#include
-+#include
-+#include "ubifs.h"
-+
-+/**
-+ * ubifs_set_inode_flags - set VFS inode flags.
-+ * @inode: VFS inode to set flags for
-+ *
-+ * This function propagates flags from UBIFS inode object to VFS inode object.
-+ */
-+void ubifs_set_inode_flags(struct inode *inode)
-+{
-+ unsigned int flags = ubifs_inode(inode)->flags;
-+
-+ inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_DIRSYNC);
-+ if (flags & UBIFS_SYNC_FL)
-+ inode->i_flags |= S_SYNC;
-+ if (flags & UBIFS_APPEND_FL)
-+ inode->i_flags |= S_APPEND;
-+ if (flags & UBIFS_IMMUTABLE_FL)
-+ inode->i_flags |= S_IMMUTABLE;
-+ if (flags & UBIFS_DIRSYNC_FL)
-+ inode->i_flags |= S_DIRSYNC;
-+}
-+
-+/*
-+ * ioctl2ubifs - convert ioctl inode flags to UBIFS inode flags.
-+ * @ioctl_flags: flags to convert
-+ *
-+ * This function convert ioctl flags (@FS_COMPR_FL, etc) to UBIFS inode flags
-+ * (@UBIFS_COMPR_FL, etc).
-+ */
-+static int ioctl2ubifs(int ioctl_flags)
-+{
-+ int ubifs_flags = 0;
-+
-+ if (ioctl_flags & FS_COMPR_FL)
-+ ubifs_flags |= UBIFS_COMPR_FL;
-+ if (ioctl_flags & FS_SYNC_FL)
-+ ubifs_flags |= UBIFS_SYNC_FL;
-+ if (ioctl_flags & FS_APPEND_FL)
-+ ubifs_flags |= UBIFS_APPEND_FL;
-+ if (ioctl_flags & FS_IMMUTABLE_FL)
-+ ubifs_flags |= UBIFS_IMMUTABLE_FL;
-+ if (ioctl_flags & FS_DIRSYNC_FL)
-+ ubifs_flags |= UBIFS_DIRSYNC_FL;
-+
-+ return ubifs_flags;
-+}
-+
-+/*
-+ * ubifs2ioctl - convert UBIFS inode flags to ioctl inode flags.
-+ * @ubifs_flags: flags to convert
-+ *
-+ * This function convert UBIFS (@UBIFS_COMPR_FL, etc) to ioctl flags
-+ * (@FS_COMPR_FL, etc).
-+ */
-+static int ubifs2ioctl(int ubifs_flags)
-+{
-+ int ioctl_flags = 0;
-+
-+ if (ubifs_flags & UBIFS_COMPR_FL)
-+ ioctl_flags |= FS_COMPR_FL;
-+ if (ubifs_flags & UBIFS_SYNC_FL)
-+ ioctl_flags |= FS_SYNC_FL;
-+ if (ubifs_flags & UBIFS_APPEND_FL)
-+ ioctl_flags |= FS_APPEND_FL;
-+ if (ubifs_flags & UBIFS_IMMUTABLE_FL)
-+ ioctl_flags |= FS_IMMUTABLE_FL;
-+ if (ubifs_flags & UBIFS_DIRSYNC_FL)
-+ ioctl_flags |= FS_DIRSYNC_FL;
-+
-+ return ioctl_flags;
-+}
-+
-+static int setflags(struct inode *inode, int flags)
-+{
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ struct ubifs_budget_req req;
-+ int oldflags, err;
-+
-+ mutex_lock(&inode->i_mutex);
-+
-+ memset(&req, 0 , sizeof(struct ubifs_budget_req));
-+ err = ubifs_budget_inode_op(c, inode, &req);
-+ if (err)
-+ goto out;
-+
-+ /*
-+ * The IMMUTABLE and APPEND_ONLY flags can only be changed by
-+ * the relevant capability.
-+ */
-+ oldflags = ubifs2ioctl(ui->flags);
-+ if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
-+ if (!capable(CAP_LINUX_IMMUTABLE)) {
-+ err = -EPERM;
-+ goto out_budg;
-+ }
-+ }
-+
-+ ui->flags = ioctl2ubifs(flags);
-+ ubifs_set_inode_flags(inode);
-+
-+ inode->i_ctime = ubifs_current_time(inode);
-+ mark_inode_dirty_sync(inode);
-+
-+ ubifs_release_ino_dirty(c, inode, &req);
-+
-+ if (IS_SYNC(inode))
-+ err = write_inode_now(inode, 1);
-+
-+ mutex_unlock(&inode->i_mutex);
-+ return err;
-+
-+out_budg:
-+ ubifs_cancel_ino_op(c, inode, &req);
-+out:
-+ ubifs_err("can't modify inode %lu attributes", inode->i_ino);
-+ mutex_unlock(&inode->i_mutex);
-+ return err;
-+}
-+
-+long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ int flags;
-+ struct inode *inode = file->f_path.dentry->d_inode;
-+
-+ switch (cmd) {
-+ case FS_IOC_GETFLAGS:
-+ flags = ubifs2ioctl(ubifs_inode(inode)->flags);
-+
-+ return put_user(flags, (int __user *) arg);
-+
-+ case FS_IOC_SETFLAGS: {
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+
-+ if (!is_owner_or_cap(inode))
-+ return -EACCES;
-+
-+ if (get_user(flags, (int __user *) arg))
-+ return -EFAULT;
-+
-+ if (!S_ISDIR(inode->i_mode))
-+ flags &= ~FS_DIRSYNC_FL;
-+
-+ return setflags(inode, flags);
-+ }
-+
-+ default:
-+ return -ENOTTY;
-+ }
-+}
-+
-+#ifdef CONFIG_COMPAT
-+long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ int err;
-+
-+ switch (cmd) {
-+ case FS_IOC32_GETFLAGS:
-+ cmd = FS_IOC_GETFLAGS;
-+ break;
-+ case FS_IOC32_SETFLAGS:
-+ cmd = FS_IOC_SETFLAGS;
-+ break;
-+ default:
-+ return -ENOIOCTLCMD;
-+ }
-+
-+ lock_kernel();
-+ err = ubifs_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
-+ unlock_kernel();
-+
-+ return err;
-+}
-+#endif
---- linux-2.6.24.7.old/fs/ubifs/journal.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/journal.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1275 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file implements UBIFS journal.
-+ *
-+ * The journal consists of 2 parts - the log and bud LEBs. The log has fixed
-+ * length and position, while a bud logical eraseblock is any LEB in the main
-+ * area. Buds contain file system data - data nodes, inode nodes, etc. The log
-+ * contains only references to buds and some other stuff like commit
-+ * start node. The idea is that when we commit the journal, we do
-+ * not copy the data, the buds just become indexed. Since after the commit the
-+ * nodes in bud eraseblocks become leaf nodes of the file system index tree, we
-+ * use term "bud". Analogy is obvious, bud eraseblocks contain nodes which will
-+ * become leafs in the future.
-+ *
-+ * The journal is multi-headed because we want to write data to the journal as
-+ * optimally as possible. It is nice to have nodes belonging to the same inode
-+ * in one LEB, so we may write data owned by different inodes to different
-+ * journal heads, although at present only one data head is used.
-+ *
-+ * For recovery reasons, the base head contains all inode nodes, all directory
-+ * entry nodes and all truncate nodes. This means that the other heads contain
-+ * only data nodes.
-+ *
-+ * Bud LEBs may be half-indexed. For example, if the bud was not full at the
-+ * time of commit, the bud is retained to continue to be used in the journal,
-+ * even though the "front" of the LEB is now indexed. In that case, the log
-+ * reference contains the offset where the bud starts for the purposes of the
-+ * journal.
-+ *
-+ * The journal size has to be limited, because the larger is the journal, the
-+ * longer it takes to mount UBIFS (scanning the journal) and the more memory it
-+ * takes (indexing in the TNC).
-+ *
-+ * Note, all the journal write operations like 'ubifs_jnl_update()' here, which
-+ * write multiple UBIFS nodes to the journal at one go, are atomic with respect
-+ * to unclean reboots. Should the unclean reboot happen, the recovery code drops
-+ * all the nodes.
-+ */
-+
-+#include "ubifs.h"
-+
-+/**
-+ * zero_ino_node_unused - zero out unused fields of an on-flash inode node.
-+ * @ino: the inode to zero out
-+ */
-+static inline void zero_ino_node_unused(struct ubifs_ino_node *ino)
-+{
-+ memset(ino->padding, 0, 26);
-+}
-+
-+/**
-+ * zero_dent_node_unused - zero out unused fields of an on-flash directory
-+ * entry node.
-+ * @ino: the directory entry to zero out
-+ */
-+static inline void zero_dent_node_unused(struct ubifs_dent_node *dent)
-+{
-+ dent->padding1 = 0;
-+ memset(dent->padding2, 0, 4);
-+}
-+
-+/**
-+ * zero_data_node_unused - zero out unused fields of an on-flash data node.
-+ * @ino: the data node to zero out
-+ */
-+static inline void zero_data_node_unused(struct ubifs_data_node *data)
-+{
-+ memset(data->padding, 0, 2);
-+}
-+
-+/**
-+ * reserve_space - reserve space in the journal.
-+ * @c: UBIFS file-system description object
-+ * @jhead: journal head number
-+ * @len: node length
-+ *
-+ * This function reserves space in journal head @head. If the reservation
-+ * succeeded, the journal head stays locked and later has to be unlocked using
-+ * 'release_head()'. 'write_node()' and 'write_head()' functions also unlock
-+ * it. Returns zero in case of success, %-EAGAIN if commit has to be done, and
-+ * other negative error codes in case of other failures.
-+ */
-+static int reserve_space(struct ubifs_info *c, int jhead, int len)
-+{
-+ int err = 0, err1, retries = 0, avail, lnum, offs, free, squeeze;
-+ struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf;
-+
-+ /*
-+ * Typically, the base head has smaller nodes written to it, so it is
-+ * better to try to allocate space at the ends of eraseblocks. This is
-+ * what the squeeze parameter does.
-+ */
-+ squeeze = (jhead == BASEHD);
-+again:
-+ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
-+ avail = c->leb_size - wbuf->offs - wbuf->used;
-+
-+ if (wbuf->lnum != -1 && avail >= len)
-+ return 0;
-+
-+ /*
-+ * Write buffer wasn't seek'ed or there is no enough space - look for an
-+ * LEB with some empty space.
-+ */
-+ lnum = ubifs_find_free_space(c, len, &free, squeeze);
-+ if (lnum >= 0) {
-+ /* Found an LEB, add it to the journal head */
-+ offs = c->leb_size - free;
-+ err = ubifs_add_bud_to_log(c, jhead, lnum, offs);
-+ if (err)
-+ goto out_return;
-+ /* A new bud was successfully allocated and added to the log */
-+ goto out;
-+ }
-+
-+ err = lnum;
-+ if (err != -ENOSPC)
-+ goto out_unlock;
-+
-+ /*
-+ * No free space, we have to run garbage collector to make
-+ * some. But the write-buffer mutex has to be unlocked because
-+ * GC have to sync write buffers, which may lead a deadlock.
-+ */
-+ dbg_jnl("no free space jhead %d, run GC", jhead);
-+ mutex_unlock(&wbuf->io_mutex);
-+
-+ lnum = ubifs_garbage_collect(c, 0);
-+ if (lnum < 0) {
-+ err = lnum;
-+ if (err != -ENOSPC)
-+ return err;
-+
-+ /*
-+ * GC could not make a free LEB. But someone else may
-+ * have allocated new bud for this journal head,
-+ * because we dropped the 'io_mutex', so try once
-+ * again.
-+ */
-+ dbg_jnl("GC couldn't make a free LEB for jhead %d", jhead);
-+ if (retries++ < 2) {
-+ dbg_jnl("retry (%d)", retries);
-+ goto again;
-+ }
-+
-+ dbg_jnl("return -ENOSPC");
-+ return err;
-+ }
-+
-+ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
-+ dbg_jnl("got LEB %d for jhead %d", lnum, jhead);
-+ avail = c->leb_size - wbuf->offs - wbuf->used;
-+
-+ if (wbuf->lnum != -1 && avail >= len) {
-+ /*
-+ * Someone else has switched the journal head and we have
-+ * enough space now. This happens when more then one process is
-+ * trying to write to the same journal head at the same time.
-+ */
-+ dbg_jnl("return LEB %d back, already have LEB %d:%d",
-+ lnum, wbuf->lnum, wbuf->offs + wbuf->used);
-+ err = ubifs_return_leb(c, lnum);
-+ if (err)
-+ goto out_unlock;
-+ return 0;
-+ }
-+
-+ err = ubifs_add_bud_to_log(c, jhead, lnum, 0);
-+ if (err)
-+ goto out_return;
-+ offs = 0;
-+
-+out:
-+ err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, UBI_SHORTTERM);
-+ if (err)
-+ goto out_unlock;
-+
-+ return 0;
-+
-+out_unlock:
-+ mutex_unlock(&wbuf->io_mutex);
-+ return err;
-+
-+out_return:
-+ /* An error occurred and the LEB has to be returned to lprops */
-+ ubifs_assert(err < 0);
-+ err1 = ubifs_return_leb(c, lnum);
-+ if (err1 && err == -EAGAIN)
-+ /*
-+ * Return original error code 'err' only if it is not
-+ * '-EAGAIN', which is not really an error. Otherwise, return
-+ * the error code of 'ubifs_return_leb()'.
-+ */
-+ err = err1;
-+ mutex_unlock(&wbuf->io_mutex);
-+ return err;
-+}
-+
-+/**
-+ * write_node - write node to a journal head.
-+ * @c: UBIFS file-system description object
-+ * @jhead: journal head
-+ * @node: node to write
-+ * @len: node length
-+ * @lnum: LEB number written is returned here
-+ * @offs: offset written is returned here
-+ *
-+ * This function writes a node to reserved space of journal head @jhead.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+static int write_node(struct ubifs_info *c, int jhead, void *node, int len,
-+ int *lnum, int *offs)
-+{
-+ struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf;
-+
-+ ubifs_assert(jhead != GCHD);
-+
-+ *lnum = c->jheads[jhead].wbuf.lnum;
-+ *offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used;
-+
-+ dbg_jnl("jhead %d, LEB %d:%d, len %d", jhead, *lnum, *offs, len);
-+ ubifs_prepare_node(c, node, len, 0);
-+
-+ return ubifs_wbuf_write_nolock(wbuf, node, len);
-+}
-+
-+/**
-+ * write_head - write data to a journal head.
-+ * @c: UBIFS file-system description object
-+ * @jhead: journal head
-+ * @buf: buffer to write
-+ * @len: length to write
-+ * @lnum: LEB number written is returned here
-+ * @offs: offset written is returned here
-+ * @sync: non-zero if the write-buffer has to by synchronized
-+ *
-+ * This function is the same as 'write_node()' but it does not assume the
-+ * buffer it is writing is a node, so it does not prepare it (which means
-+ * initializing common header and calculating CRC).
-+ */
-+static int write_head(struct ubifs_info *c, int jhead, void *buf, int len,
-+ int *lnum, int *offs, int sync)
-+{
-+ int err;
-+ struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf;
-+
-+ ubifs_assert(jhead != GCHD);
-+
-+ *lnum = c->jheads[jhead].wbuf.lnum;
-+ *offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used;
-+ dbg_jnl("jhead %d, LEB %d:%d, len %d", jhead, *lnum, *offs, len);
-+
-+ err = ubifs_wbuf_write_nolock(wbuf, buf, len);
-+ if (err)
-+ return err;
-+ if (sync)
-+ err = ubifs_wbuf_sync_nolock(wbuf);
-+ return err;
-+}
-+
-+/**
-+ * make_reservation - reserve journal space.
-+ * @c: UBIFS file-system description object
-+ * @jhead: journal head
-+ * @len: how many bytes to reserve
-+ *
-+ * This function makes space reservation in journal head @jhead. The function
-+ * takes the commit lock and locks the journal head, and the caller has to
-+ * unlock the head and finish the reservation with 'finish_reservation()'.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ *
-+ * Note, the journal head may be unlocked as soon as the data is written, while
-+ * the commit lock has to be released after the data has been added to the
-+ * TNC.
-+ */
-+static int make_reservation(struct ubifs_info *c, int jhead, int len)
-+{
-+ int err, cmt_retries = 0, nospc_retries = 0;
-+
-+ ubifs_assert(len <= c->dark_wm);
-+
-+again:
-+ down_read(&c->commit_sem);
-+ err = reserve_space(c, jhead, len);
-+ if (!err)
-+ return 0;
-+ up_read(&c->commit_sem);
-+
-+ if (err == -ENOSPC) {
-+ /*
-+ * GC could not make any progress. We should try to commit
-+ * once because it could make some dirty space and GC would
-+ * make progress, so make the error -EAGAIN so that the below
-+ * will commit and re-try.
-+ */
-+ if (nospc_retries++ < 2) {
-+ dbg_jnl("no space, retry");
-+ err = -EAGAIN;
-+ }
-+
-+ /*
-+ * This means that the budgeting is incorrect. We always have
-+ * to be able to write to the media, because all operations are
-+ * budgeted. Deletions are not budgeted, though, but we reserve
-+ * an extra LEB for them.
-+ */
-+ }
-+
-+ if (err != -EAGAIN)
-+ goto out;
-+
-+ /*
-+ * -EAGAIN means that the journal is full or too large, or the above
-+ * code wants to do one commit. Do this and re-try.
-+ */
-+ if (cmt_retries > 128) {
-+ /*
-+ * This should not happen unless the journal size limitations
-+ * are too tough.
-+ */
-+ ubifs_err("stuck in space allocation");
-+ err = -ENOSPC;
-+ goto out;
-+ } else if (cmt_retries > 32)
-+ ubifs_warn("too many space allocation re-tries (%d)",
-+ cmt_retries);
-+
-+ dbg_jnl("-EAGAIN, commit and retry (retried %d times)",
-+ cmt_retries);
-+ cmt_retries += 1;
-+
-+ err = ubifs_run_commit(c);
-+ if (err)
-+ return err;
-+ goto again;
-+
-+out:
-+ ubifs_err("cannot reserve %d bytes in jhead %d, error %d",
-+ len, jhead, err);
-+ if (err == -ENOSPC) {
-+ /* This are some budgeting problems, print useful information */
-+ down_write(&c->commit_sem);
-+ spin_lock(&c->space_lock);
-+ dbg_dump_stack();
-+ dbg_dump_budg(c);
-+ spin_unlock(&c->space_lock);
-+ dbg_dump_lprops(c);
-+ cmt_retries = dbg_check_lprops(c);
-+ up_write(&c->commit_sem);
-+ }
-+
-+ return err;
-+}
-+
-+/**
-+ * release_head - release a journal head.
-+ * @c: UBIFS file-system description object
-+ * @jhead: journal head
-+ *
-+ * This function releases journal head @jhead which was locked by
-+ * the 'make_reservation()' function. It has to be called after each successful
-+ * 'make_reservation()' invocation.
-+ */
-+static inline void release_head(struct ubifs_info *c, int jhead)
-+{
-+ mutex_unlock(&c->jheads[jhead].wbuf.io_mutex);
-+}
-+
-+/**
-+ * finish_reservation - finish a reservation.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function finishes journal space reservation. It must be called after
-+ * 'make_reservation()'.
-+ */
-+static void finish_reservation(struct ubifs_info *c)
-+{
-+ up_read(&c->commit_sem);
-+}
-+
-+/**
-+ * get_dent_type - translate VFS inode mode to UBIFS directory entry type.
-+ * @mode: inode mode
-+ */
-+static int get_dent_type(int mode)
-+{
-+ switch (mode & S_IFMT) {
-+ case S_IFREG:
-+ return UBIFS_ITYPE_REG;
-+ case S_IFDIR:
-+ return UBIFS_ITYPE_DIR;
-+ case S_IFLNK:
-+ return UBIFS_ITYPE_LNK;
-+ case S_IFBLK:
-+ return UBIFS_ITYPE_BLK;
-+ case S_IFCHR:
-+ return UBIFS_ITYPE_CHR;
-+ case S_IFIFO:
-+ return UBIFS_ITYPE_FIFO;
-+ case S_IFSOCK:
-+ return UBIFS_ITYPE_SOCK;
-+ default:
-+ BUG();
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * pack_inode - pack an inode node.
-+ * @c: UBIFS file-system description object
-+ * @ino: buffer in which to pack inode node
-+ * @inode: inode to pack
-+ * @last: indicates the last node of the group
-+ * @last_reference: non-zero if this is a deletion inode
-+ */
-+static void pack_inode(struct ubifs_info *c, struct ubifs_ino_node *ino,
-+ const struct inode *inode, int last, int last_reference)
-+{
-+ int data_len = 0;
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+
-+ ino->ch.node_type = UBIFS_INO_NODE;
-+ ino_key_init_flash(c, &ino->key, inode->i_ino);
-+ ino->creat_sqnum = cpu_to_le64(ui->creat_sqnum);
-+ ino->size = cpu_to_le64(i_size_read(inode));
-+ ino->nlink = cpu_to_le32(inode->i_nlink);
-+ ino->atime_sec = cpu_to_le64(inode->i_atime.tv_sec);
-+ ino->atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
-+ ino->ctime_sec = cpu_to_le64(inode->i_ctime.tv_sec);
-+ ino->ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
-+ ino->mtime_sec = cpu_to_le64(inode->i_mtime.tv_sec);
-+ ino->mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
-+ ino->uid = cpu_to_le32(inode->i_uid);
-+ ino->gid = cpu_to_le32(inode->i_gid);
-+ ino->mode = cpu_to_le32(inode->i_mode);
-+ ino->flags = cpu_to_le32(ui->flags);
-+ ino->compr_type = cpu_to_le16(ui->compr_type);
-+ ino->xattr_cnt = cpu_to_le32(ui->xattr_cnt);
-+ ino->xattr_size = cpu_to_le64(ui->xattr_size);
-+ ino->xattr_names = cpu_to_le32(ui->xattr_names);
-+ ino->data_len = cpu_to_le32(ui->data_len);
-+ zero_ino_node_unused(ino);
-+
-+ /*
-+ * Drop the attached data if this is a deletion inode, the data is not
-+ * needed anymore.
-+ */
-+ if (!last_reference) {
-+ memcpy(ino->data, ui->data, ui->data_len);
-+ data_len = ui->data_len;
-+ }
-+
-+ ubifs_prep_grp_node(c, ino, UBIFS_INO_NODE_SZ + data_len, last);
-+}
-+
-+/**
-+ * ubifs_jnl_update - update inode.
-+ * @c: UBIFS file-system description object
-+ * @dir: parent inode or host inode in case of extended attributes
-+ * @nm: directory entry name
-+ * @inode: inode
-+ * @deletion: indicates a directory entry deletion i.e unlink or rmdir
-+ * @sync: non-zero if the write-buffer has to be synchronized
-+ * @xent: non-zero if the directory entry is an extended attribute entry
-+ *
-+ * This function updates an inode by writing a directory entry (or extended
-+ * attribute entry), the inode itself, and the parent directory inode (or the
-+ * host inode) to the journal.
-+ *
-+ * The function writes the host inode @dir last, which is important in case of
-+ * extended attributes. Indeed, then we guarantee that if the host inode gets
-+ * synchronized, and the write-buffer it sits in gets flushed, the extended
-+ * attribute inode gets flushed too. And this is exactly what the user expects -
-+ * synchronizing the host inode synchronizes its extended attributes.
-+ * Similarly, this guarantees that if @dir is synchronized, its directory entry
-+ * corresponding to @nm gets synchronized too.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
-+ const struct qstr *nm, const struct inode *inode,
-+ int deletion, int sync, int xent)
-+{
-+ int err, dlen, ilen, len, lnum, ino_offs, dent_offs;
-+ int aligned_dlen, aligned_ilen;
-+ int last_reference = !!(deletion && inode->i_nlink == 0);
-+ struct ubifs_dent_node *dent;
-+ struct ubifs_ino_node *ino;
-+ union ubifs_key dent_key, ino_key;
-+
-+ dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu",
-+ inode->i_ino, nm->len, nm->name, ubifs_inode(inode)->data_len,
-+ dir->i_ino);
-+ ubifs_assert(ubifs_inode(dir)->data_len == 0);
-+
-+ dlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
-+ ilen = UBIFS_INO_NODE_SZ;
-+
-+ /*
-+ * If the last reference to the inode is being deleted, then there is no
-+ * need to attach and write inode data, it is being deleted anyway.
-+ */
-+ if (!last_reference)
-+ ilen += ubifs_inode(inode)->data_len;
-+
-+ aligned_dlen = ALIGN(dlen, 8);
-+ aligned_ilen = ALIGN(ilen, 8);
-+
-+ len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ;
-+
-+ dent = kmalloc(len, GFP_NOFS);
-+ if (!dent)
-+ return -ENOMEM;
-+
-+ /* Make reservation before allocating sequence numbers */
-+ err = make_reservation(c, BASEHD, len);
-+ if (err)
-+ goto out_free;
-+
-+ if (!xent) {
-+ dent->ch.node_type = UBIFS_DENT_NODE;
-+ dent_key_init(c, &dent_key, dir->i_ino, nm);
-+ } else {
-+ dent->ch.node_type = UBIFS_XENT_NODE;
-+ xent_key_init(c, &dent_key, dir->i_ino, nm);
-+ }
-+
-+ key_write(c, &dent_key, dent->key);
-+ dent->inum = deletion ? 0 : cpu_to_le64(inode->i_ino);
-+ dent->type = get_dent_type(inode->i_mode);
-+ dent->nlen = cpu_to_le16(nm->len);
-+ memcpy(dent->name, nm->name, nm->len);
-+ dent->name[nm->len] = '\0';
-+ zero_dent_node_unused(dent);
-+ ubifs_prep_grp_node(c, dent, dlen, 0);
-+
-+ ino = (void *)dent + aligned_dlen;
-+ pack_inode(c, ino, inode, 0, last_reference);
-+
-+ ino = (void *)ino + aligned_ilen;
-+ pack_inode(c, ino, dir, 1, 0);
-+
-+ if (last_reference) {
-+ err = ubifs_add_orphan(c, inode->i_ino);
-+ if (err) {
-+ release_head(c, BASEHD);
-+ goto out_finish;
-+ }
-+ }
-+
-+ err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync);
-+ if (!sync && !err) {
-+ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf;
-+
-+ ubifs_wbuf_add_ino_nolock(wbuf, inode->i_ino);
-+ ubifs_wbuf_add_ino_nolock(wbuf, dir->i_ino);
-+ }
-+ release_head(c, BASEHD);
-+ kfree(dent);
-+ if (err)
-+ goto out_ro;
-+
-+ if (deletion) {
-+ err = ubifs_tnc_remove_nm(c, &dent_key, nm);
-+ if (err)
-+ goto out_ro;
-+ err = ubifs_add_dirt(c, lnum, dlen);
-+ } else
-+ err = ubifs_tnc_add_nm(c, &dent_key, lnum, dent_offs, dlen, nm);
-+ if (err)
-+ goto out_ro;
-+
-+ /*
-+ * Note, we do not remove the inode from TNC even if the last reference
-+ * to it has just been deleted, because the inode may still be opened.
-+ * Instead, the inode has been added to orphan lists and the orphan
-+ * subsystem will take further care about it.
-+ */
-+ ino_key_init(c, &ino_key, inode->i_ino);
-+ ino_offs = dent_offs + aligned_dlen;
-+ err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, ilen);
-+ if (err)
-+ goto out_ro;
-+
-+ ino_key_init(c, &ino_key, dir->i_ino);
-+ ino_offs += aligned_ilen;
-+ err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, UBIFS_INO_NODE_SZ);
-+ if (err)
-+ goto out_ro;
-+
-+ finish_reservation(c);
-+ return 0;
-+
-+out_finish:
-+ finish_reservation(c);
-+out_free:
-+ kfree(dent);
-+ return err;
-+
-+out_ro:
-+ ubifs_ro_mode(c, err);
-+ if (last_reference)
-+ ubifs_delete_orphan(c, inode->i_ino);
-+ finish_reservation(c);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_jnl_write_data - write a data node to the journal.
-+ * @c: UBIFS file-system description object
-+ * @inode: inode the data node belongs to
-+ * @key: node key
-+ * @buf: buffer to write
-+ * @len: data length (must not exceed %UBIFS_BLOCK_SIZE)
-+ *
-+ * This function writes a data node to the journal. Returns %0 if the data node
-+ * was successfully written, and a negative error code in case of failure.
-+ */
-+int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
-+ const union ubifs_key *key, const void *buf, int len)
-+{
-+ int err, lnum, offs, compr_type, out_len;
-+ int dlen = UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR;
-+ const struct ubifs_inode *ui = ubifs_inode(inode);
-+ struct ubifs_data_node *data;
-+
-+ dbg_jnl("ino %lu, blk %u, len %d, key %s", key_ino(c, key),
-+ key_block(c, key), len, DBGKEY(key));
-+ ubifs_assert(len <= UBIFS_BLOCK_SIZE);
-+
-+ data = kmalloc(dlen, GFP_NOFS);
-+ if (!data)
-+ return -ENOMEM;
-+
-+ data->ch.node_type = UBIFS_DATA_NODE;
-+ key_write(c, key, &data->key);
-+ data->size = cpu_to_le32(len);
-+ zero_data_node_unused(data);
-+
-+ if (!(ui->flags && UBIFS_COMPR_FL))
-+ /* Compression is disabled for this inode */
-+ compr_type = UBIFS_COMPR_NONE;
-+ else
-+ compr_type = ui->compr_type;
-+
-+ out_len = dlen - UBIFS_DATA_NODE_SZ;
-+ ubifs_compress(buf, len, &data->data, &out_len, &compr_type);
-+ ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
-+
-+ dlen = UBIFS_DATA_NODE_SZ + out_len;
-+ data->compr_type = cpu_to_le16(compr_type);
-+
-+ /* Make reservation before allocating sequence numbers */
-+ err = make_reservation(c, DATAHD, dlen);
-+ if (err)
-+ goto out_free;
-+
-+ err = write_node(c, DATAHD, data, dlen, &lnum, &offs);
-+ if (!err)
-+ ubifs_wbuf_add_ino_nolock(&c->jheads[DATAHD].wbuf,
-+ key_ino(c, key));
-+ release_head(c, DATAHD);
-+ if (err)
-+ goto out_ro;
-+
-+ err = ubifs_tnc_add(c, key, lnum, offs, dlen);
-+ if (err)
-+ goto out_ro;
-+
-+ finish_reservation(c);
-+ kfree(data);
-+ return 0;
-+
-+out_ro:
-+ ubifs_ro_mode(c, err);
-+ finish_reservation(c);
-+out_free:
-+ kfree(data);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_jnl_write_inode - flush inode to the journal.
-+ * @c: UBIFS file-system description object
-+ * @inode: inode to flush
-+ * @last_reference: inode has been deleted
-+ * @sync: non-zero if the write-buffer has to be synchronized
-+ *
-+ * This function writes inode @inode to the journal (to the base head). Returns
-+ * zero in case of success and a negative error code in case of failure.
-+ */
-+int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode,
-+ int last_reference, int sync)
-+{
-+ int err, len, lnum, offs;
-+ struct ubifs_ino_node *ino;
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+
-+ dbg_jnl("ino %lu%s", inode->i_ino,
-+ last_reference ? " (last reference)" : "");
-+ if (last_reference)
-+ ubifs_assert(inode->i_nlink == 0);
-+
-+ /* If the inode is deleted, do not write the attached data */
-+ len = UBIFS_INO_NODE_SZ;
-+ if (!last_reference)
-+ len += ui->data_len;
-+ ino = kmalloc(len, GFP_NOFS);
-+ if (!ino)
-+ return -ENOMEM;
-+
-+ /* Make reservation before allocating sequence numbers */
-+ err = make_reservation(c, BASEHD, len);
-+ if (err)
-+ goto out_free;
-+
-+ pack_inode(c, ino, inode, 1, last_reference);
-+
-+ err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync);
-+ if (!sync && !err)
-+ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf,
-+ inode->i_ino);
-+ release_head(c, BASEHD);
-+ if (err)
-+ goto out_ro;
-+
-+ if (last_reference) {
-+ err = ubifs_tnc_remove_ino(c, inode->i_ino);
-+ if (err)
-+ goto out_ro;
-+ ubifs_delete_orphan(c, inode->i_ino);
-+ err = ubifs_add_dirt(c, lnum, len);
-+ } else {
-+ union ubifs_key key;
-+
-+ ino_key_init(c, &key, inode->i_ino);
-+ err = ubifs_tnc_add(c, &key, lnum, offs, len);
-+ }
-+ if (err)
-+ goto out_ro;
-+
-+ finish_reservation(c);
-+ kfree(ino);
-+ return 0;
-+
-+out_ro:
-+ ubifs_ro_mode(c, err);
-+ finish_reservation(c);
-+out_free:
-+ kfree(ino);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_jnl_rename - rename a directory entry.
-+ * @c: UBIFS file-system description object
-+ * @old_dir: parent inode of directory entry to rename
-+ * @old_dentry: directory entry to rename
-+ * @new_dir: parent inode of directory entry to rename
-+ * @new_dentry: new directory entry (or directory entry to replace)
-+ * @sync: non-zero if the write-buffer has to be synchronized
-+ *
-+ * Returns zero in case of success and a negative error code in case of failure.
-+ */
-+int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
-+ const struct dentry *old_dentry,
-+ const struct inode *new_dir,
-+ const struct dentry *new_dentry, int sync)
-+{
-+ const struct inode *old_inode = old_dentry->d_inode;
-+ const struct inode *new_inode = new_dentry->d_inode;
-+ int err, dlen1, dlen2, ilen, lnum, offs, len;
-+ int aligned_dlen1, aligned_dlen2, plen = UBIFS_INO_NODE_SZ;
-+ int last_reference = !!(new_inode && new_inode->i_nlink == 0);
-+ struct ubifs_dent_node *dent, *dent2;
-+ void *p;
-+ union ubifs_key key;
-+
-+ dbg_jnl("dent '%.*s' in dir ino %lu to dent '%.*s' in dir ino %lu",
-+ old_dentry->d_name.len, old_dentry->d_name.name,
-+ old_dir->i_ino, new_dentry->d_name.len,
-+ new_dentry->d_name.name, new_dir->i_ino);
-+
-+ ubifs_assert(ubifs_inode(old_dir)->data_len == 0);
-+ ubifs_assert(ubifs_inode(new_dir)->data_len == 0);
-+
-+ dlen1 = UBIFS_DENT_NODE_SZ + new_dentry->d_name.len + 1;
-+ dlen2 = UBIFS_DENT_NODE_SZ + old_dentry->d_name.len + 1;
-+ if (new_inode) {
-+ ilen = UBIFS_INO_NODE_SZ;
-+ if (!last_reference)
-+ ilen += ubifs_inode(new_inode)->data_len;
-+ } else
-+ ilen = 0;
-+
-+ aligned_dlen1 = ALIGN(dlen1, 8);
-+ aligned_dlen2 = ALIGN(dlen2, 8);
-+
-+ len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8);
-+ if (old_dir != new_dir)
-+ len += plen;
-+
-+ dent = kmalloc(len, GFP_NOFS);
-+ if (!dent)
-+ return -ENOMEM;
-+
-+ /* Make reservation before allocating sequence numbers */
-+ err = make_reservation(c, BASEHD, len);
-+ if (err)
-+ goto out_free;
-+
-+ /* Make new dent */
-+ dent->ch.node_type = UBIFS_DENT_NODE;
-+ dent_key_init_flash(c, &dent->key, new_dir->i_ino, &new_dentry->d_name);
-+ dent->inum = cpu_to_le64(old_inode->i_ino);
-+ dent->type = get_dent_type(old_inode->i_mode);
-+ dent->nlen = cpu_to_le16(new_dentry->d_name.len);
-+ memcpy(dent->name, new_dentry->d_name.name, new_dentry->d_name.len);
-+ dent->name[new_dentry->d_name.len] = '\0';
-+ zero_dent_node_unused(dent);
-+ ubifs_prep_grp_node(c, dent, dlen1, 0);
-+
-+ dent2 = (void *)dent + aligned_dlen1;
-+
-+ /* Make deletion dent */
-+ dent2->ch.node_type = UBIFS_DENT_NODE;
-+ dent_key_init_flash(c, &dent2->key, old_dir->i_ino,
-+ &old_dentry->d_name);
-+ dent2->inum = 0;
-+ dent2->type = DT_UNKNOWN;
-+ dent2->nlen = cpu_to_le16(old_dentry->d_name.len);
-+ memcpy(dent2->name, old_dentry->d_name.name, old_dentry->d_name.len);
-+ dent2->name[old_dentry->d_name.len] = '\0';
-+ zero_dent_node_unused(dent2);
-+ ubifs_prep_grp_node(c, dent2, dlen2, 0);
-+
-+ p = (void *)dent2 + aligned_dlen2;
-+ if (new_inode) {
-+ pack_inode(c, p, new_inode, 0, last_reference);
-+ p += ALIGN(ilen, 8);
-+ }
-+
-+ if (old_dir == new_dir)
-+ pack_inode(c, p, old_dir, 1, 0);
-+ else {
-+ pack_inode(c, p, old_dir, 0, 0);
-+ p += ALIGN(plen, 8);
-+ pack_inode(c, p, new_dir, 1, 0);
-+ }
-+
-+ if (last_reference) {
-+ err = ubifs_add_orphan(c, new_inode->i_ino);
-+ if (err) {
-+ release_head(c, BASEHD);
-+ goto out_finish;
-+ }
-+ }
-+
-+ err = write_head(c, BASEHD, dent, len, &lnum, &offs, sync);
-+ if (!sync && !err) {
-+ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf;
-+
-+ ubifs_wbuf_add_ino_nolock(wbuf, new_dir->i_ino);
-+ ubifs_wbuf_add_ino_nolock(wbuf, old_dir->i_ino);
-+ if (new_inode)
-+ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf,
-+ new_inode->i_ino);
-+ }
-+ release_head(c, BASEHD);
-+ if (err)
-+ goto out_ro;
-+
-+ dent_key_init(c, &key, new_dir->i_ino, &new_dentry->d_name);
-+ err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, &new_dentry->d_name);
-+ if (err)
-+ goto out_ro;
-+
-+ err = ubifs_add_dirt(c, lnum, dlen2);
-+ if (err)
-+ goto out_ro;
-+
-+ dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
-+ err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name);
-+ if (err)
-+ goto out_ro;
-+
-+ offs += aligned_dlen1 + aligned_dlen2;
-+ if (new_inode) {
-+ ino_key_init(c, &key, new_inode->i_ino);
-+ err = ubifs_tnc_add(c, &key, lnum, offs, ilen);
-+ if (err)
-+ goto out_ro;
-+ offs += ALIGN(ilen, 8);
-+ }
-+
-+ ino_key_init(c, &key, old_dir->i_ino);
-+ err = ubifs_tnc_add(c, &key, lnum, offs, plen);
-+ if (err)
-+ goto out_ro;
-+
-+ if (old_dir != new_dir) {
-+ offs += ALIGN(plen, 8);
-+ ino_key_init(c, &key, new_dir->i_ino);
-+ err = ubifs_tnc_add(c, &key, lnum, offs, plen);
-+ if (err)
-+ goto out_ro;
-+ }
-+
-+ finish_reservation(c);
-+ kfree(dent);
-+ return 0;
-+
-+out_ro:
-+ ubifs_ro_mode(c, err);
-+ if (last_reference)
-+ ubifs_delete_orphan(c, new_inode->i_ino);
-+out_finish:
-+ finish_reservation(c);
-+out_free:
-+ kfree(dent);
-+ return err;
-+}
-+
-+/**
-+ * recomp_data_node - re-compress a truncated data node.
-+ * @dn: data node to re-compress
-+ * @new_len: new length
-+ *
-+ * This function is used when an inode is truncated and the last data node of
-+ * the inode has to be re-compressed and re-written.
-+ */
-+static int recomp_data_node(struct ubifs_data_node *dn, int *new_len)
-+{
-+ void *buf;
-+ int err, len, compr_type, out_len;
-+
-+ out_len = le32_to_cpu(dn->size);
-+ buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS);
-+ if (!buf)
-+ return -ENOMEM;
-+
-+ len = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
-+ compr_type = le16_to_cpu(dn->compr_type);
-+ err = ubifs_decompress(&dn->data, len, buf, &out_len, compr_type);
-+ if (err)
-+ goto out;
-+
-+ ubifs_compress(buf, *new_len, &dn->data, &out_len, &compr_type);
-+ ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
-+ dn->compr_type = cpu_to_le16(compr_type);
-+ dn->size = cpu_to_le32(*new_len);
-+ *new_len = UBIFS_DATA_NODE_SZ + out_len;
-+out:
-+ kfree(buf);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_jnl_truncate - update the journal for a truncation.
-+ * @c: UBIFS file-system description object
-+ * @inum: inode number of inode being truncated
-+ * @old_size: old size
-+ * @new_size: new size
-+ *
-+ * When the size of a file decreases due to truncation, a truncation node is
-+ * written, the journal tree is updated, and the last data block is re-written
-+ * if it has been affected.
-+ *
-+ * This function returns %0 in the case of success, and a negative error code in
-+ * case of failure.
-+ */
-+int ubifs_jnl_truncate(struct ubifs_info *c, ino_t inum,
-+ loff_t old_size, loff_t new_size)
-+{
-+ union ubifs_key key, to_key;
-+ struct ubifs_trun_node *trun;
-+ struct ubifs_data_node *uninitialized_var(dn);
-+ int err, dlen, len, lnum, offs, bit, sz;
-+ unsigned int blk;
-+
-+ dbg_jnl("ino %lu, size %lld -> %lld", inum, old_size, new_size);
-+
-+ sz = UBIFS_TRUN_NODE_SZ + UBIFS_MAX_DATA_NODE_SZ * WORST_COMPR_FACTOR;
-+ trun = kmalloc(sz, GFP_NOFS);
-+ if (!trun)
-+ return -ENOMEM;
-+
-+ trun->ch.node_type = UBIFS_TRUN_NODE;
-+ trun_key_init_flash(c, &trun->key, inum);
-+ trun->old_size = cpu_to_le64(old_size);
-+ trun->new_size = cpu_to_le64(new_size);
-+
-+ dlen = new_size & (UBIFS_BLOCK_SIZE - 1);
-+
-+ if (dlen) {
-+ /* Get last data block so it can be truncated */
-+ dn = (void *)trun + ALIGN(UBIFS_TRUN_NODE_SZ, 8);
-+ blk = new_size / UBIFS_BLOCK_SIZE;
-+ data_key_init(c, &key, inum, blk);
-+ dbg_jnl("last block key %s", DBGKEY(&key));
-+ err = ubifs_tnc_lookup(c, &key, dn);
-+ if (err == -ENOENT)
-+ dlen = 0; /* Not found (so it is a hole) */
-+ else if (err)
-+ goto out_free;
-+ else {
-+ if (le32_to_cpu(dn->size) <= dlen)
-+ dlen = 0; /* Nothing to do */
-+ else {
-+ int compr_type = le16_to_cpu(dn->compr_type);
-+
-+ if (compr_type != UBIFS_COMPR_NONE) {
-+ err = recomp_data_node(dn, &dlen);
-+ if (err)
-+ goto out_free;
-+ } else {
-+ dn->size = cpu_to_le32(dlen);
-+ dlen += UBIFS_DATA_NODE_SZ;
-+ }
-+ zero_data_node_unused(dn);
-+ }
-+ }
-+ }
-+
-+ if (dlen)
-+ len = ALIGN(UBIFS_TRUN_NODE_SZ, 8) + dlen;
-+ else
-+ len = UBIFS_TRUN_NODE_SZ;
-+
-+ /* Must make reservation before allocating sequence numbers */
-+ err = make_reservation(c, BASEHD, len);
-+ if (err)
-+ goto out_free;
-+
-+ ubifs_prepare_node(c, trun, UBIFS_TRUN_NODE_SZ, 0);
-+ if (dlen)
-+ ubifs_prepare_node(c, dn, dlen, 0);
-+
-+ err = write_head(c, BASEHD, trun, len, &lnum, &offs, 0);
-+ if (!err)
-+ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, inum);
-+ release_head(c, BASEHD);
-+ if (err)
-+ goto out_ro;
-+
-+ if (dlen) {
-+ offs += ALIGN(UBIFS_TRUN_NODE_SZ, 8);
-+ err = ubifs_tnc_add(c, &key, lnum, offs, dlen);
-+ if (err)
-+ goto out_ro;
-+ }
-+
-+ err = ubifs_add_dirt(c, lnum, UBIFS_TRUN_NODE_SZ);
-+ if (err)
-+ goto out_ro;
-+
-+ bit = new_size & (UBIFS_BLOCK_SIZE - 1);
-+
-+ blk = new_size / UBIFS_BLOCK_SIZE + (bit ? 1 : 0);
-+ data_key_init(c, &key, inum, blk);
-+
-+ bit = old_size & (UBIFS_BLOCK_SIZE - 1);
-+
-+ blk = old_size / UBIFS_BLOCK_SIZE - (bit ? 0: 1);
-+ data_key_init(c, &to_key, inum, blk);
-+
-+ err = ubifs_tnc_remove_range(c, &key, &to_key);
-+ if (err)
-+ goto out_ro;
-+
-+ finish_reservation(c);
-+ kfree(trun);
-+ return 0;
-+
-+out_ro:
-+ ubifs_ro_mode(c, err);
-+ finish_reservation(c);
-+out_free:
-+ kfree(trun);
-+ return err;
-+}
-+
-+#ifdef CONFIG_UBIFS_FS_XATTR
-+
-+int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
-+ const struct inode *inode, const struct qstr *nm,
-+ int sync)
-+{
-+ int err, xlen, hlen, len, lnum, xent_offs, aligned_xlen;
-+ struct ubifs_dent_node *xent;
-+ struct ubifs_ino_node *ino;
-+ union ubifs_key xent_key, key1, key2;
-+
-+ dbg_jnl("host %lu, xattr ino %lu, name '%s', data len %d",
-+ host->i_ino, inode->i_ino, nm->name,
-+ ubifs_inode(inode)->data_len);
-+ ubifs_assert(inode->i_nlink == 0);
-+
-+ /*
-+ * Since we are deleting the inode, we do not bother to attach any data
-+ * to it and assume its length is %UBIFS_INO_NODE_SZ.
-+ */
-+ xlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
-+ aligned_xlen = ALIGN(xlen, 8);
-+ hlen = ubifs_inode(host)->data_len + UBIFS_INO_NODE_SZ;
-+ len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8);
-+
-+ xent = kmalloc(len, GFP_NOFS);
-+ if (!xent)
-+ return -ENOMEM;
-+
-+ /* Make reservation before allocating sequence numbers */
-+ err = make_reservation(c, BASEHD, len);
-+ if (err) {
-+ kfree(xent);
-+ return err;
-+ }
-+
-+ xent->ch.node_type = UBIFS_XENT_NODE;
-+ xent_key_init(c, &xent_key, host->i_ino, nm);
-+ key_write(c, &xent_key, xent->key);
-+ xent->inum = 0;
-+ xent->type = get_dent_type(inode->i_mode);
-+ xent->nlen = cpu_to_le16(nm->len);
-+ memcpy(xent->name, nm->name, nm->len);
-+ xent->name[nm->len] = '\0';
-+ zero_dent_node_unused(xent);
-+ ubifs_prep_grp_node(c, xent, xlen, 0);
-+
-+ ino = (void *)xent + aligned_xlen;
-+ pack_inode(c, ino, inode, 0, 1);
-+
-+ ino = (void *)ino + UBIFS_INO_NODE_SZ;
-+ pack_inode(c, ino, host, 1, 0);
-+
-+ err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync);
-+ if (!sync && !err)
-+ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, host->i_ino);
-+ release_head(c, BASEHD);
-+ kfree(xent);
-+ if (err)
-+ goto out_ro;
-+
-+ /* Remove the extended attribute entry from TNC */
-+ err = ubifs_tnc_remove_nm(c, &xent_key, nm);
-+ if (err)
-+ goto out_ro;
-+ err = ubifs_add_dirt(c, lnum, xlen);
-+ if (err)
-+ goto out_ro;
-+
-+ /*
-+ * Remove all nodes belonging to the extended attribute inode from TNC.
-+ * Well, there actually must be only one node - the inode itself.
-+ */
-+ lowest_ino_key(c, &key1, inode->i_ino);
-+ highest_ino_key(c, &key2, inode->i_ino);
-+ err = ubifs_tnc_remove_range(c, &key1, &key2);
-+ if (err)
-+ goto out_ro;
-+ err = ubifs_add_dirt(c, lnum, UBIFS_INO_NODE_SZ);
-+ if (err)
-+ goto out_ro;
-+
-+ /* And update TNC with the new host inode position */
-+ ino_key_init(c, &key1, host->i_ino);
-+ err = ubifs_tnc_add(c, &key1, lnum, xent_offs + len - hlen, hlen);
-+ if (err)
-+ goto out_ro;
-+
-+ finish_reservation(c);
-+ return 0;
-+
-+out_ro:
-+ ubifs_ro_mode(c, err);
-+ finish_reservation(c);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_jnl_write_2_inodes - write 2 inodes to the journal.
-+ * @c: UBIFS file-system description object
-+ * @inode1: first inode to write
-+ * @inode2: second inode to write
-+ * @sync: non-zero if the write-buffer has to be synchronized
-+ *
-+ * This function writes 2 inodes @inode1 and @inode2 to the journal (to the
-+ * base head - first @inode1, then @inode2). Returns zero in case of success
-+ * and a negative error code in case of failure.
-+ */
-+int ubifs_jnl_write_2_inodes(struct ubifs_info *c, const struct inode *inode1,
-+ const struct inode *inode2, int sync)
-+{
-+ int err, len1, len2, aligned_len, aligned_len1, lnum, offs;
-+ struct ubifs_ino_node *ino;
-+ union ubifs_key key;
-+
-+ dbg_jnl("ino %lu, ino %lu", inode1->i_ino, inode2->i_ino);
-+ ubifs_assert(inode1->i_nlink > 0);
-+ ubifs_assert(inode2->i_nlink > 0);
-+
-+ len1 = UBIFS_INO_NODE_SZ + ubifs_inode(inode1)->data_len;
-+ len2 = UBIFS_INO_NODE_SZ + ubifs_inode(inode2)->data_len;
-+ aligned_len1 = ALIGN(len1, 8);
-+ aligned_len = aligned_len1 + ALIGN(len2, 8);
-+
-+ ino = kmalloc(aligned_len, GFP_NOFS);
-+ if (!ino)
-+ return -ENOMEM;
-+
-+ /* Make reservation before allocating sequence numbers */
-+ err = make_reservation(c, BASEHD, aligned_len);
-+ if (err)
-+ goto out_free;
-+
-+ pack_inode(c, ino, inode1, 0, 0);
-+ pack_inode(c, (void *)ino + aligned_len1, inode2, 1, 0);
-+
-+ err = write_head(c, BASEHD, ino, aligned_len, &lnum, &offs, 0);
-+ if (!sync && !err) {
-+ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf;
-+
-+ ubifs_wbuf_add_ino_nolock(wbuf, inode1->i_ino);
-+ ubifs_wbuf_add_ino_nolock(wbuf, inode2->i_ino);
-+ }
-+ release_head(c, BASEHD);
-+ if (err)
-+ goto out_ro;
-+
-+ ino_key_init(c, &key, inode1->i_ino);
-+ err = ubifs_tnc_add(c, &key, lnum, offs, len1);
-+ if (err)
-+ goto out_ro;
-+
-+ ino_key_init(c, &key, inode2->i_ino);
-+ err = ubifs_tnc_add(c, &key, lnum, offs + aligned_len1, len2);
-+ if (err)
-+ goto out_ro;
-+
-+ finish_reservation(c);
-+ kfree(ino);
-+ return 0;
-+
-+out_ro:
-+ ubifs_ro_mode(c, err);
-+ finish_reservation(c);
-+out_free:
-+ kfree(ino);
-+ return err;
-+}
-+
-+#endif /* CONFIG_UBIFS_FS_XATTR */
---- linux-2.6.24.7.old/fs/ubifs/key.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/key.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,566 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This header contains various key-related definitions and helper function.
-+ * UBIFS allows several key schemes, so we access key fields only via these
-+ * helpers. At the moment only one key scheme is supported.
-+ *
-+ * Simple key scheme
-+ * ~~~~~~~~~~~~~~~~~
-+ *
-+ * Keys are 64-bits long. First 32-bits are inode number (parent inode number
-+ * in case of direntry key). Next 3 bits are node type. The last 29 bits are
-+ * 4KiB offset in case of inode node, and direntry hash in case of a direntry
-+ * node. We use "r5" hash borrowed from reiserfs.
-+ */
-+
-+#ifndef __UBIFS_KEY_H__
-+#define __UBIFS_KEY_H__
-+
-+/**
-+ * key_r5_hash - R5 hash function (borrowed from reiserfs).
-+ * @s: direntry name
-+ * @len: name length
-+ */
-+static inline uint32_t key_r5_hash(const char *s, int len)
-+{
-+ uint32_t a = 0;
-+ const signed char *str = (const signed char *)s;
-+
-+ while (*str) {
-+ a += *str << 4;
-+ a += *str >> 4;
-+ a *= 11;
-+ str++;
-+ }
-+
-+ /* TODO: change this to
-+ * a &= UBIFS_S_KEY_HASH_MASK; */
-+ a &= 0x1FFFFFFF;
-+
-+ /*
-+ * We use hash values as offset in directories, so values %0 and %1 are
-+ * reserved for "." and "..". %2 is reserved for "end of readdir"
-+ * marker.
-+ */
-+ if (unlikely(a >= 0 && a <= 2))
-+ a += 3;
-+ return a;
-+}
-+
-+/**
-+ * tmp_key_r5_hash - R5 hash function (borrowed from reiserfs).
-+ * @s: direntry name
-+ * @len: name length
-+ * TODO: this should die soon
-+ */
-+static inline uint32_t tmp_key_r5_hash(const char *s, int len)
-+{
-+ uint32_t a = 0;
-+ const signed char *str = (const signed char *)s;
-+
-+ while (*str) {
-+ a += *str << 4;
-+ a += *str >> 4;
-+ a *= 11;
-+ str++;
-+ }
-+
-+ a &= 0x01FFFFFF;
-+
-+ /*
-+ * We use hash values as offset in directories, so values %0 and %1 are
-+ * reserved for "." and "..". %2 is reserved for possible future use.
-+ */
-+ if (unlikely(a >= 0 && a <= 2))
-+ a += 3;
-+ return a;
-+}
-+
-+/**
-+ * key_test_hash - testing hash function.
-+ * @str: direntry name
-+ * @len: name length
-+ */
-+static inline uint32_t key_test_hash(const char *str, int len)
-+{
-+ uint32_t a = 0;
-+
-+ len = min_t(uint32_t, len, 4);
-+ memcpy(&a, str, len);
-+ /* TODO: change this to
-+ * a &= UBIFS_S_KEY_HASH_MASK; */
-+ a &= 0x1FFFFFFF;
-+ if (unlikely(a >= 0 && a <= 2))
-+ a += 3;
-+ return a;
-+}
-+
-+/**
-+ * ino_key_init - initialize inode key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void ino_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS;
-+}
-+
-+/**
-+ * ino_key_init_flash - initialize on-flash inode key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void ino_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum)
-+{
-+ union ubifs_key *key = k;
-+
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS);
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * lowest_ino_key - get the lowest possible inode key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void lowest_ino_key(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = 0;
-+}
-+
-+/**
-+ * highest_ino_key - get the highest possible inode key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void highest_ino_key(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = 0xffffffff;
-+}
-+
-+/**
-+ * dent_key_init - initialize directory entry key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: parent inode number
-+ * @nm: direntry name and length
-+ */
-+static inline void dent_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ const struct qstr *nm)
-+{
-+ uint32_t hash = c->key_hash(nm->name, nm->len);
-+
-+ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
-+ key->u32[0] = inum;
-+ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
-+}
-+
-+/**
-+ * dent_key_init_hash - initialize directory entry key without re-calculating
-+ * hash function.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: parent inode number
-+ * @hash: direntry name hash
-+ */
-+static inline void dent_key_init_hash(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ uint32_t hash)
-+{
-+ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
-+ key->u32[0] = inum;
-+ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
-+}
-+
-+/**
-+ * dent_key_init_flash - initialize on-flash directory entry key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: parent inode number
-+ * @nm: direntry name and length
-+ */
-+static inline void dent_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum, const struct qstr *nm)
-+{
-+ union ubifs_key *key = k;
-+ uint32_t hash = c->key_hash(nm->name, nm->len);
-+
-+ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(hash |
-+ (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS));
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * lowest_dent_key - get the lowest possible directory entry key.
-+ * @c: UBIFS file-system description object
-+ * @key: where to store the lowest key
-+ * @inum: parent inode number
-+ */
-+static inline void lowest_dent_key(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS;
-+}
-+
-+/**
-+ * xent_key_init - initialize extended attribute entry key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: host inode number
-+ * @nm: extended attribute entry name and length
-+ */
-+static inline void xent_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ const struct qstr *nm)
-+{
-+ uint32_t hash = c->key_hash(nm->name, nm->len);
-+
-+ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
-+ key->u32[0] = inum;
-+ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
-+}
-+
-+/**
-+ * xent_key_init_hash - initialize extended attribute entry key without
-+ * re-calculating hash function.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: host inode number
-+ * @hash: extended attribute entry name hash
-+ */
-+static inline void xent_key_init_hash(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ uint32_t hash)
-+{
-+ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
-+ key->u32[0] = inum;
-+ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
-+}
-+
-+/**
-+ * xent_key_init_flash - initialize on-flash extended attribute entry key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: host inode number
-+ * @nm: extended attribute entry name and length
-+ */
-+static inline void xent_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum, const struct qstr *nm)
-+{
-+ union ubifs_key *key = k;
-+ uint32_t hash = c->key_hash(nm->name, nm->len);
-+
-+ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(hash |
-+ (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS));
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * lowest_xent_key - get the lowest possible extended attribute entry key.
-+ * @c: UBIFS file-system description object
-+ * @key: where to store the lowest key
-+ * @inum: host inode number
-+ */
-+static inline void lowest_xent_key(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS;
-+}
-+
-+/**
-+ * data_key_init - initialize data key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ * @block: block number
-+ */
-+static inline void data_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ unsigned int block)
-+{
-+ ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK));
-+ key->u32[0] = inum;
-+ key->u32[1] = block | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS);
-+}
-+
-+/**
-+ * data_key_init_flash - initialize on-flash data key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: inode number
-+ * @block: block number
-+ */
-+static inline void data_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum, unsigned int block)
-+{
-+ union ubifs_key *key = k;
-+
-+ ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK));
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(block |
-+ (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS));
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * trun_key_init - initialize truncation node key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void trun_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS;
-+}
-+
-+/**
-+ * trun_key_init_flash - initialize on-flash truncation node key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void trun_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum)
-+{
-+ union ubifs_key *key = k;
-+
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS);
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * key_type - get key type.
-+ * @c: UBIFS file-system description object
-+ * @key: key to get type of
-+ */
-+static inline int key_type(const struct ubifs_info *c,
-+ const union ubifs_key *key)
-+{
-+ return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS;
-+}
-+
-+/**
-+ * key_type_flash - get type of a on-flash formatted key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to get type of
-+ */
-+static inline int key_type_flash(const struct ubifs_info *c, const void *k)
-+{
-+ const union ubifs_key *key = k;
-+
-+ return le32_to_cpu(key->u32[1]) >> UBIFS_S_KEY_BLOCK_BITS;
-+}
-+
-+/**
-+ * key_ino - fetch inode number from key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to fetch inode number from
-+ */
-+static inline ino_t key_ino(const struct ubifs_info *c, const void *k)
-+{
-+ const union ubifs_key *key = k;
-+
-+ return key->u32[0];
-+}
-+
-+/**
-+ * key_ino_flash - fetch inode number from an on-flash formatted key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to fetch inode number from
-+ */
-+static inline ino_t key_ino_flash(const struct ubifs_info *c, const void *k)
-+{
-+ const union ubifs_key *key = k;
-+
-+ return le32_to_cpu(key->j32[0]);
-+}
-+
-+/**
-+ * key_hash - get directory entry hash.
-+ * @c: UBIFS file-system description object
-+ * @key: the key to get hash from
-+ */
-+static inline int key_hash(const struct ubifs_info *c,
-+ const union ubifs_key *key)
-+{
-+ return key->u32[1] & UBIFS_S_KEY_HASH_MASK;
-+}
-+
-+/**
-+ * key_hash_flash - get directory entry hash from an on-flash formatted key.
-+ * @c: UBIFS file-system description object
-+ * @k: the key to get hash from
-+ */
-+static inline int key_hash_flash(const struct ubifs_info *c, const void *k)
-+{
-+ const union ubifs_key *key = k;
-+
-+ return le32_to_cpu(key->j32[1]) & UBIFS_S_KEY_HASH_MASK;
-+}
-+
-+/**
-+ * key_block - get data block number.
-+ * @c: UBIFS file-system description object
-+ * @key: the key to get the block number from
-+ */
-+static inline unsigned int key_block(const struct ubifs_info *c,
-+ const union ubifs_key *key)
-+{
-+ return key->u32[1] & UBIFS_S_KEY_BLOCK_MASK;
-+}
-+
-+/**
-+ * key_read - transform a key to in-memory format.
-+ * @c: UBIFS file-system description object
-+ * @from: the key to transform
-+ * @to: the key to store the result
-+ */
-+static inline void key_read(const struct ubifs_info *c, const void *from,
-+ union ubifs_key *to)
-+{
-+ const union ubifs_key *f = from;
-+
-+ to->u32[0] = le32_to_cpu(f->j32[0]);
-+ to->u32[1] = le32_to_cpu(f->j32[1]);
-+}
-+
-+/**
-+ * key_write - transform a key from in-memory format.
-+ * @c: UBIFS file-system description object
-+ * @from: the key to transform
-+ * @to: the key to store the result
-+ */
-+static inline void key_write(const struct ubifs_info *c,
-+ const union ubifs_key *from, void *to)
-+{
-+ union ubifs_key *t = to;
-+
-+ t->j32[0] = cpu_to_le32(from->u32[0]);
-+ t->j32[1] = cpu_to_le32(from->u32[1]);
-+ memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * key_write_idx - transform a key from in-memory format for the index.
-+ * @c: UBIFS file-system description object
-+ * @from: the key to transform
-+ * @to: the key to store the result
-+ */
-+static inline void key_write_idx(const struct ubifs_info *c,
-+ const union ubifs_key *from, void *to)
-+{
-+ union ubifs_key *t = to;
-+
-+ t->j32[0] = cpu_to_le32(from->u32[0]);
-+ t->j32[1] = cpu_to_le32(from->u32[1]);
-+}
-+
-+/**
-+ * key_copy - copy a key.
-+ * @c: UBIFS file-system description object
-+ * @from: the key to copy from
-+ * @to: the key to copy to
-+ */
-+static inline void key_copy(const struct ubifs_info *c,
-+ const union ubifs_key *from, union ubifs_key *to)
-+{
-+ to->u64[0] = from->u64[0];
-+}
-+
-+/**
-+ * keys_cmp - compare keys.
-+ * @c: UBIFS file-system description object
-+ * @key1: the first key to compare
-+ * @key2: the second key to compare
-+ *
-+ * This function compares 2 keys and returns %-1 if @key1 is less than
-+ * @key2, 0 if the keys are equivalent and %1 if @key1 is greater than @key2.
-+ */
-+static inline int keys_cmp(const struct ubifs_info *c,
-+ const union ubifs_key *key1,
-+ const union ubifs_key *key2)
-+{
-+ if (key1->u32[0] < key2->u32[0])
-+ return -1;
-+ if (key1->u32[0] > key2->u32[0])
-+ return 1;
-+ if (key1->u32[1] < key2->u32[1])
-+ return -1;
-+ if (key1->u32[1] > key2->u32[1])
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/**
-+ * is_hash_key - is a key vulnerable to hash collisions.
-+ * @c: UBIFS file-system description object
-+ * @key: key
-+ *
-+ * This function returns %1 if @key is a hashed key or %0 otherwise.
-+ */
-+static inline int is_hash_key(const struct ubifs_info *c,
-+ const union ubifs_key *key)
-+{
-+ int type = key_type(c, key);
-+
-+ return type == UBIFS_DENT_KEY || type == UBIFS_XENT_KEY;
-+}
-+
-+/**
-+ * key_max_inode_size - get maximum file size allowed by current key format.
-+ * @c: UBIFS file-system description object
-+ */
-+static inline unsigned long long key_max_inode_size(const struct ubifs_info *c)
-+{
-+ switch (c->key_fmt) {
-+ case UBIFS_SIMPLE_KEY_FMT:
-+ return (1ULL << UBIFS_S_KEY_BLOCK_BITS) * UBIFS_BLOCK_SIZE;
-+ default:
-+ return 0;
-+ }
-+}
-+#endif /* !__UBIFS_KEY_H__ */
---- linux-2.6.24.7.old/fs/ubifs/log.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/log.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,803 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file is a part of UBIFS journal implementation and contains various
-+ * functions which manipulate the log. The log is a fixed area on the flash
-+ * which does not contain any data but refers to buds. The log is a part of the
-+ * journal.
-+ */
-+
-+#include "ubifs.h"
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+static int dbg_check_bud_bytes(struct ubifs_info *c);
-+#else
-+#define dbg_check_bud_bytes(c) 0
-+#endif
-+
-+/**
-+ * ubifs_search_bud - search bud LEB.
-+ * @c: UBIFS file-system description object
-+ * @lnum: logical eraseblock number to search
-+ *
-+ * This function searches bud LEB @lnum. Returns bud description object in case
-+ * of success and %NULL if there is no bud with this LEB number.
-+ */
-+struct ubifs_bud *ubifs_search_bud(struct ubifs_info *c, int lnum)
-+{
-+ struct rb_node *p;
-+ struct ubifs_bud *bud;
-+
-+ spin_lock(&c->buds_lock);
-+ p = c->buds.rb_node;
-+ while (p) {
-+ bud = rb_entry(p, struct ubifs_bud, rb);
-+ if (lnum < bud->lnum)
-+ p = p->rb_left;
-+ else if (lnum > bud->lnum)
-+ p = p->rb_right;
-+ else {
-+ spin_unlock(&c->buds_lock);
-+ return bud;
-+ }
-+ }
-+ spin_unlock(&c->buds_lock);
-+ return NULL;
-+}
-+
-+/**
-+ * ubifs_get_wbuf - get the wbuf associated with a LEB, if there is one.
-+ * @c: UBIFS file-system description object
-+ * @lnum: logical eraseblock number to search
-+ *
-+ * This functions returns the wbuf for @lnum or %NULL if there is not one.
-+ */
-+struct ubifs_wbuf *ubifs_get_wbuf(struct ubifs_info *c, int lnum)
-+{
-+ struct rb_node *p;
-+ struct ubifs_bud *bud;
-+ int jhead;
-+
-+ if (!c->jheads)
-+ return NULL;
-+
-+ spin_lock(&c->buds_lock);
-+ p = c->buds.rb_node;
-+ while (p) {
-+ bud = rb_entry(p, struct ubifs_bud, rb);
-+ if (lnum < bud->lnum)
-+ p = p->rb_left;
-+ else if (lnum > bud->lnum)
-+ p = p->rb_right;
-+ else {
-+ jhead = bud->jhead;
-+ spin_unlock(&c->buds_lock);
-+ return &c->jheads[jhead].wbuf;
-+ }
-+ }
-+ spin_unlock(&c->buds_lock);
-+ return NULL;
-+}
-+
-+/**
-+ * next_log_lnum - switch to the next log LEB.
-+ * @c: UBIFS file-system description object
-+ * @lnum: current log LEB
-+ */
-+static inline int next_log_lnum(const struct ubifs_info *c, int lnum)
-+{
-+ lnum += 1;
-+ if (lnum > c->log_last)
-+ lnum = UBIFS_LOG_LNUM;
-+
-+ return lnum;
-+}
-+
-+/**
-+ * empty_log_bytes - calculate amount of empty space in the log.
-+ * @c: UBIFS file-system description object
-+ */
-+static inline long long empty_log_bytes(const struct ubifs_info *c)
-+{
-+ long long h, t;
-+
-+ h = c->lhead_lnum * c->leb_size + c->lhead_offs;
-+ t = c->ltail_lnum * c->leb_size;
-+
-+ if (h >= t)
-+ return c->log_bytes - h + t;
-+ else
-+ return t - h;
-+}
-+
-+/**
-+ * ubifs_add_bud - add bud LEB to the tree of buds and its journal head list.
-+ * @c: UBIFS file-system description object
-+ * @bud: the bud to add
-+ */
-+void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
-+{
-+ struct rb_node **p, *parent = NULL;
-+ struct ubifs_bud *b;
-+ struct ubifs_jhead *jhead;
-+
-+ spin_lock(&c->buds_lock);
-+ p = &c->buds.rb_node;
-+ while (*p) {
-+ parent = *p;
-+ b = rb_entry(parent, struct ubifs_bud, rb);
-+ ubifs_assert(bud->lnum != b->lnum);
-+ if (bud->lnum < b->lnum)
-+ p = &(*p)->rb_left;
-+ else
-+ p = &(*p)->rb_right;
-+ }
-+
-+ rb_link_node(&bud->rb, parent, p);
-+ rb_insert_color(&bud->rb, &c->buds);
-+ if (c->jheads) {
-+ jhead = &c->jheads[bud->jhead];
-+ list_add_tail(&bud->list, &jhead->buds_list);
-+ } else
-+ ubifs_assert(c->replaying && (c->vfs_sb->s_flags & MS_RDONLY));
-+
-+ /*
-+ * Note, although this is a new bud, we anyway account this space now,
-+ * before any data has been written to it, because this is about to
-+ * guarantee fixed mount time, and this bud will anyway be read and
-+ * scanned.
-+ */
-+ c->bud_bytes += c->leb_size - bud->start;
-+
-+ dbg_log("LEB %d:%d, jhead %d, bud_bytes %lld", bud->lnum,
-+ bud->start, bud->jhead, c->bud_bytes);
-+ spin_unlock(&c->buds_lock);
-+}
-+
-+/**
-+ * ubifs_create_buds_lists - create journal head buds lists for remount rw.
-+ * @c: UBIFS file-system description object
-+ */
-+void ubifs_create_buds_lists(struct ubifs_info *c)
-+{
-+ struct rb_node *p;
-+
-+ spin_lock(&c->buds_lock);
-+ p = rb_first(&c->buds);
-+ while (p) {
-+ struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb);
-+ struct ubifs_jhead *jhead = &c->jheads[bud->jhead];
-+
-+ list_add_tail(&bud->list, &jhead->buds_list);
-+ p = rb_next(p);
-+ }
-+ spin_unlock(&c->buds_lock);
-+}
-+
-+/**
-+ * ubifs_add_bud_to_log - add a new bud to the log.
-+ * @c: UBIFS file-system description object
-+ * @jhead: journal head the bud belongs to
-+ * @lnum: LEB number of the bud
-+ * @offs: starting offset of the bud
-+ *
-+ * This function writes reference node for the new bud LEB @lnum it to the log,
-+ * and adds it to the buds tress. It also makes sure that log size does not
-+ * exceed the 'c->max_bud_bytes' limit. Returns zero in case of success,
-+ * %-EAGAIN if commit is required, and a negative error codes in case of
-+ * failure.
-+ */
-+int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
-+{
-+ int err;
-+ struct ubifs_bud *bud;
-+ struct ubifs_ref_node *ref;
-+
-+ bud = kmalloc(sizeof(struct ubifs_bud), GFP_NOFS);
-+ if (!bud)
-+ return -ENOMEM;
-+ ref = kzalloc(c->ref_node_alsz, GFP_NOFS);
-+ if (!ref) {
-+ kfree(bud);
-+ return -ENOMEM;
-+ }
-+
-+ mutex_lock(&c->log_mutex);
-+ /* Make sure we have enough space in the log */
-+ if (empty_log_bytes(c) - c->ref_node_alsz < c->min_log_bytes) {
-+ dbg_log("not enough log space - %lld, required %d",
-+ empty_log_bytes(c), c->min_log_bytes);
-+ ubifs_commit_required(c);
-+ err = -EAGAIN;
-+ goto out_unlock;
-+ }
-+
-+ /*
-+ * Make sure the the amount of space in buds will not exceed
-+ * 'c->max_bud_bytes' limit, because we want to guarantee mount time
-+ * limits.
-+ *
-+ * It is not necessary to hold @c->buds_lock when reading @c->bud_bytes
-+ * because we are holding @c->log_mutex. All @c->bud_bytes take place
-+ * when both @c->log_mutex and @c->bud_bytes are locked.
-+ */
-+ if (c->bud_bytes + c->leb_size - offs > c->max_bud_bytes) {
-+ dbg_log("bud bytes %lld (%lld max), require commit",
-+ c->bud_bytes, c->max_bud_bytes);
-+ ubifs_commit_required(c);
-+ err = -EAGAIN;
-+ goto out_unlock;
-+ }
-+
-+ /*
-+ * If the journal is full enough - start background commit. Note, it is
-+ * OK to read 'c->cmt_state' without spinlock because integer reads
-+ * are atomic in the kernel.
-+ */
-+ if (c->bud_bytes >= c->bg_bud_bytes &&
-+ c->cmt_state == COMMIT_RESTING) {
-+ dbg_log("bud bytes %lld (%lld max), initiate BG commit",
-+ c->bud_bytes, c->max_bud_bytes);
-+ ubifs_request_bg_commit(c);
-+ }
-+
-+ bud->lnum = lnum;
-+ bud->start = offs;
-+ bud->jhead = jhead;
-+
-+ ref->ch.node_type = UBIFS_REF_NODE;
-+ ref->lnum = cpu_to_le32(bud->lnum);
-+ ref->offs = cpu_to_le32(bud->start);
-+ ref->jhead = cpu_to_le32(jhead);
-+
-+ if (c->lhead_offs > c->leb_size - c->ref_node_alsz) {
-+ c->lhead_lnum = next_log_lnum(c, c->lhead_lnum);
-+ c->lhead_offs = 0;
-+ }
-+
-+ if (c->lhead_offs == 0) {
-+ /* Must ensure next log LEB has been unmapped */
-+ err = ubifs_leb_unmap(c, c->lhead_lnum);
-+ if (err)
-+ goto out_unlock;
-+ }
-+
-+ if (bud->start == 0) {
-+ /*
-+ * Before writing the LEB reference which refers an empty LEB
-+ * to the log, we have to make sure it is mapped, because
-+ * otherwise we'd risk to refer an LEB with garbage in case of
-+ * an unclean reboot, because the target LEB might have been
-+ * unmapped, but not yet physically erased.
-+ */
-+ err = ubi_leb_map(c->ubi, bud->lnum, UBI_SHORTTERM);
-+ if (err)
-+ goto out_unlock;
-+ }
-+
-+ dbg_log("write ref LEB %d:%d",
-+ c->lhead_lnum, c->lhead_offs);
-+ err = ubifs_write_node(c, ref, UBIFS_REF_NODE_SZ, c->lhead_lnum,
-+ c->lhead_offs, UBI_SHORTTERM);
-+ c->lhead_offs += c->ref_node_alsz;
-+ if (err)
-+ goto out_unlock;
-+
-+ ubifs_add_bud(c, bud);
-+
-+ mutex_unlock(&c->log_mutex);
-+ kfree(ref);
-+ return 0;
-+
-+out_unlock:
-+ mutex_unlock(&c->log_mutex);
-+ kfree(ref);
-+ kfree(bud);
-+ return err;
-+}
-+
-+/**
-+ * remove_buds - remove used buds.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function removes use buds from the buds tree. It does not remove the
-+ * buds which are pointed to by journal heads.
-+ */
-+static void remove_buds(struct ubifs_info *c)
-+{
-+ struct rb_node *p;
-+
-+ ubifs_assert(list_empty(&c->old_buds));
-+ c->cmt_bud_bytes = 0;
-+ spin_lock(&c->buds_lock);
-+ p = rb_first(&c->buds);
-+ while (p) {
-+ struct rb_node *p1 = p;
-+ struct ubifs_bud *bud;
-+ struct ubifs_wbuf *wbuf;
-+
-+ p = rb_next(p);
-+ bud = rb_entry(p1, struct ubifs_bud, rb);
-+ wbuf = &c->jheads[bud->jhead].wbuf;
-+
-+ if (wbuf->lnum == bud->lnum) {
-+ /*
-+ * Do not remove buds which are pointed to by journal
-+ * heads (non-closed buds).
-+ */
-+ c->cmt_bud_bytes += wbuf->offs - bud->start;
-+ dbg_log("preserve %d:%d, jhead %d, bud bytes %d, "
-+ "cmt_bud_bytes %lld", bud->lnum, bud->start,
-+ bud->jhead, wbuf->offs - bud->start,
-+ c->cmt_bud_bytes);
-+ bud->start = wbuf->offs;
-+ } else {
-+ c->cmt_bud_bytes += c->leb_size - bud->start;
-+ dbg_log("remove %d:%d, jhead %d, bud bytes %d, "
-+ "cmt_bud_bytes %lld", bud->lnum, bud->start,
-+ bud->jhead, c->leb_size - bud->start,
-+ c->cmt_bud_bytes);
-+ rb_erase(p1, &c->buds);
-+ list_del(&bud->list);
-+ /*
-+ * If the commit does not finish, the recovery will need
-+ * to replay the journal, in which case the old buds
-+ * must be unchanged. Do not release them until post
-+ * commit i.e. do not allow them to be garbage
-+ * collected.
-+ */
-+ list_add(&bud->list, &c->old_buds);
-+ }
-+ }
-+ spin_unlock(&c->buds_lock);
-+}
-+
-+/**
-+ * ubifs_log_start_commit - start commit.
-+ * @c: UBIFS file-system description object
-+ * @ltail_lnum: return new log tail LEB number
-+ *
-+ * The commit operation starts with writing "commit start" node to the log and
-+ * reference nodes for all journal heads which will define new journal after
-+ * the commit has been finished. The commit start and reference nodes are
-+ * written in one go to the nearest empty log LEB (hence, when commit is
-+ * finished UBIFS may safely unmap all the previous log LEBs). This function
-+ * returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum)
-+{
-+ void *buf;
-+ struct ubifs_cs_node *cs;
-+ struct ubifs_ref_node *ref;
-+ int err, i, max_len, len;
-+
-+ err = dbg_check_bud_bytes(c);
-+ if (err)
-+ return err;
-+
-+ max_len = UBIFS_CS_NODE_SZ + c->jhead_cnt * UBIFS_REF_NODE_SZ;
-+ max_len = ALIGN(max_len, c->min_io_size);
-+ buf = cs = kmalloc(max_len, GFP_NOFS);
-+ if (!buf)
-+ return -ENOMEM;
-+
-+ cs->ch.node_type = UBIFS_CS_NODE;
-+ cs->cmt_no = cpu_to_le64(c->cmt_no + 1);
-+ ubifs_prepare_node(c, cs, UBIFS_CS_NODE_SZ, 0);
-+
-+ /*
-+ * Note, we do not lock 'c->log_mutex' because this is the commit start
-+ * phase and we are exclusively using the log. And we do not lock
-+ * write-buffer because nobody can write to the file-system at this
-+ * phase.
-+ */
-+
-+ len = UBIFS_CS_NODE_SZ;
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ int lnum = c->jheads[i].wbuf.lnum;
-+ int offs = c->jheads[i].wbuf.offs;
-+
-+ if (lnum == -1 || offs == c->leb_size)
-+ continue;
-+
-+ dbg_log("add ref to LEB %d:%d for jhead %d", lnum, offs, i);
-+ ref = buf + len;
-+ ref->ch.node_type = UBIFS_REF_NODE;
-+ ref->lnum = cpu_to_le32(lnum);
-+ ref->offs = cpu_to_le32(offs);
-+ ref->jhead = cpu_to_le32(i);
-+
-+ ubifs_prepare_node(c, ref, UBIFS_REF_NODE_SZ, 0);
-+ len += UBIFS_REF_NODE_SZ;
-+ }
-+
-+ ubifs_pad(c, buf + len, ALIGN(len, c->min_io_size) - len);
-+
-+ /* Switch to the next log LEB */
-+ if (c->lhead_offs) {
-+ c->lhead_lnum = next_log_lnum(c, c->lhead_lnum);
-+ c->lhead_offs = 0;
-+ }
-+
-+ if (c->lhead_offs == 0) {
-+ /* Must ensure next LEB has been unmapped */
-+ err = ubifs_leb_unmap(c, c->lhead_lnum);
-+ if (err)
-+ goto out;
-+ }
-+
-+ len = ALIGN(len, c->min_io_size);
-+ dbg_log("writing commit start at LEB %d:0, len %d", c->lhead_lnum, len);
-+ err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len, UBI_SHORTTERM);
-+ if (err)
-+ goto out;
-+
-+ *ltail_lnum = c->lhead_lnum;
-+
-+ c->lhead_offs += len;
-+ if (c->lhead_offs == c->leb_size) {
-+ c->lhead_lnum = next_log_lnum(c, c->lhead_lnum);
-+ c->lhead_offs = 0;
-+ }
-+
-+ remove_buds(c);
-+
-+ /*
-+ * We have started the commit and now users may use the rest of the log
-+ * for new writes.
-+ */
-+ c->min_log_bytes = 0;
-+
-+out:
-+ kfree(buf);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_log_end_commit - end commit.
-+ * @c: UBIFS file-system description object
-+ * @ltail_lnum: new log tail LEB number
-+ *
-+ * This function is called on when the commit operation was finished. It
-+ * moves log tail to new position and unmaps LEBs which contain obsolete data.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum)
-+{
-+ int err;
-+
-+ /*
-+ * At this phase we have to lock 'c->log_mutex' because UBIFS allows FS
-+ * writes during commit. Its only short "commit" start phase when
-+ * writers are blocked.
-+ */
-+ mutex_lock(&c->log_mutex);
-+
-+ dbg_log("old tail was LEB %d:0, new tail is LEB %d:0",
-+ c->ltail_lnum, ltail_lnum);
-+
-+ c->ltail_lnum = ltail_lnum;
-+ /*
-+ * The commit is finished and from now on it must be guaranteed that
-+ * there is always enough space for the next commit.
-+ */
-+ c->min_log_bytes = c->leb_size;
-+
-+ spin_lock(&c->buds_lock);
-+ c->bud_bytes -= c->cmt_bud_bytes;
-+ spin_unlock(&c->buds_lock);
-+
-+ err = dbg_check_bud_bytes(c);
-+
-+ mutex_unlock(&c->log_mutex);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_log_post_commit - things to do after commit is completed.
-+ * @c: UBIFS file-system description object
-+ * @old_ltail_lnum: old log tail LEB number
-+ *
-+ * Release buds only after commit is completed, because they must be unchanged
-+ * if recovery is needed.
-+ *
-+ * Unmap log LEBs only after commit is completed, because they may be needed for
-+ * recovery.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_log_post_commit(struct ubifs_info *c, int old_ltail_lnum)
-+{
-+ int lnum, err = 0;
-+
-+ while (!list_empty(&c->old_buds)) {
-+ struct ubifs_bud *bud;
-+
-+ bud = list_entry(c->old_buds.next, struct ubifs_bud, list);
-+ err = ubifs_return_leb(c, bud->lnum);
-+ if (err)
-+ return err;
-+ list_del(&bud->list);
-+ kfree(bud);
-+ }
-+ mutex_lock(&c->log_mutex);
-+ for (lnum = old_ltail_lnum; lnum != c->ltail_lnum;
-+ lnum = next_log_lnum(c, lnum)) {
-+ dbg_log("unmap log LEB %d", lnum);
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ goto out;
-+ }
-+out:
-+ mutex_unlock(&c->log_mutex);
-+ return err;
-+}
-+
-+/**
-+ * struct done_ref - references that have been done.
-+ * @rb: rb-tree node
-+ * @lnum: LEB number
-+ */
-+struct done_ref {
-+ struct rb_node rb;
-+ int lnum;
-+};
-+
-+/**
-+ * done_already - determine if a reference has been done already.
-+ * @done_tree: rb-tree to store references that have been done
-+ * @lnum: LEB number of reference
-+ *
-+ * This function returns %1 if the reference has been done, %0 if not, otherwise
-+ * a negative error code is returned.
-+ */
-+static int done_already(struct rb_root *done_tree, int lnum)
-+{
-+ struct rb_node **p = &done_tree->rb_node, *parent = NULL;
-+ struct done_ref *dr;
-+
-+ while (*p) {
-+ parent = *p;
-+ dr = rb_entry(parent, struct done_ref, rb);
-+ if (lnum < dr->lnum)
-+ p = &(*p)->rb_left;
-+ else if (lnum > dr->lnum)
-+ p = &(*p)->rb_right;
-+ else
-+ return 1;
-+ }
-+
-+ dr = kzalloc(sizeof(struct done_ref), GFP_NOFS);
-+ if (!dr)
-+ return -ENOMEM;
-+
-+ dr->lnum = lnum;
-+
-+ rb_link_node(&dr->rb, parent, p);
-+ rb_insert_color(&dr->rb, done_tree);
-+
-+ return 0;
-+}
-+
-+/**
-+ * destroy_done_tree - destroy the done tree.
-+ * @done_tree: done tree to destroy
-+ */
-+static void destroy_done_tree(struct rb_root *done_tree)
-+{
-+ struct rb_node *this = done_tree->rb_node;
-+ struct done_ref *dr;
-+
-+ while (this) {
-+ if (this->rb_left) {
-+ this = this->rb_left;
-+ continue;
-+ } else if (this->rb_right) {
-+ this = this->rb_right;
-+ continue;
-+ }
-+ dr = rb_entry(this, struct done_ref, rb);
-+ this = rb_parent(this);
-+ if (this) {
-+ if (this->rb_left == &dr->rb)
-+ this->rb_left = NULL;
-+ else
-+ this->rb_right = NULL;
-+ }
-+ kfree(dr);
-+ }
-+}
-+
-+/**
-+ * add_node - add a node to the consolidated log.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer to which to add
-+ * @lnum: LEB number to which to write is passed and returned here
-+ * @offs: offset to where to write is passed and returned here
-+ * @node: node to add
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int add_node(struct ubifs_info *c, void *buf, int *lnum, int *offs,
-+ void *node)
-+{
-+ struct ubifs_ch *ch = node;
-+ int len = le32_to_cpu(ch->len), remains = c->leb_size - *offs;
-+
-+ if (len > remains) {
-+ int sz = ALIGN(*offs, c->min_io_size), err;
-+
-+ ubifs_pad(c, buf + *offs, sz - *offs);
-+ err = ubi_leb_change(c->ubi, *lnum, buf, sz, UBI_SHORTTERM);
-+ if (err)
-+ return err;
-+ *lnum = next_log_lnum(c, *lnum);
-+ *offs = 0;
-+ }
-+ memcpy(buf + *offs, node, len);
-+ *offs += ALIGN(len, 8);
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_consolidate_log - consolidate the log.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Repeated failed commits could cause the log to be full, but at least 1 LEB is
-+ * needed for commit. This function rewrites the reference nodes in the log
-+ * omitting duplicates, and failed CS nodes, and leaving no gaps.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_consolidate_log(struct ubifs_info *c)
-+{
-+ struct ubifs_scan_leb *sleb;
-+ struct ubifs_scan_node *snod;
-+ struct rb_root done_tree = RB_ROOT;
-+ int lnum, err, first = 1, write_lnum, offs = 0;
-+ void *buf;
-+
-+ dbg_rcvry("log tail LEB %d, log head LEB %d", c->ltail_lnum,
-+ c->lhead_lnum);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ buf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ buf = vmalloc(c->leb_size);
-+#endif
-+ if (!buf)
-+ return -ENOMEM;
-+ lnum = c->ltail_lnum;
-+ write_lnum = lnum;
-+ while (1) {
-+ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
-+ if (IS_ERR(sleb)) {
-+ err = PTR_ERR(sleb);
-+ goto out_free;
-+ }
-+ list_for_each_entry(snod, &sleb->nodes, list) {
-+ switch (snod->type) {
-+ case UBIFS_REF_NODE: {
-+ struct ubifs_ref_node *ref = snod->node;
-+ int ref_lnum = le32_to_cpu(ref->lnum);
-+
-+ err = done_already(&done_tree, ref_lnum);
-+ if (err < 0)
-+ goto out_scan;
-+ if (err != 1) {
-+ err = add_node(c, buf, &write_lnum,
-+ &offs, snod->node);
-+ if (err)
-+ goto out_scan;
-+ }
-+ break;
-+ }
-+ case UBIFS_CS_NODE:
-+ if (!first)
-+ break;
-+ err = add_node(c, buf, &write_lnum, &offs,
-+ snod->node);
-+ if (err)
-+ goto out_scan;
-+ first = 0;
-+ break;
-+ }
-+ }
-+ ubifs_scan_destroy(sleb);
-+ if (lnum == c->lhead_lnum)
-+ break;
-+ lnum = next_log_lnum(c, lnum);
-+ }
-+ if (offs) {
-+ int sz = ALIGN(offs, c->min_io_size);
-+
-+ ubifs_pad(c, buf + offs, sz - offs);
-+ err = ubi_leb_change(c->ubi, write_lnum, buf, sz,
-+ UBI_SHORTTERM);
-+ if (err)
-+ goto out_free;
-+ offs = ALIGN(offs, c->min_io_size);
-+ }
-+ destroy_done_tree(&done_tree);
-+ vfree(buf);
-+ if (write_lnum == c->lhead_lnum) {
-+ ubifs_err("log is too full");
-+ return -EINVAL;
-+ }
-+ /* Unmap remaining LEBs */
-+ lnum = write_lnum;
-+ do {
-+ lnum = next_log_lnum(c, lnum);
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ } while (lnum != c->lhead_lnum);
-+ c->lhead_lnum = write_lnum;
-+ c->lhead_offs = offs;
-+ dbg_rcvry("new log head at %d:%d", c->lhead_lnum, c->lhead_offs);
-+ return 0;
-+
-+out_scan:
-+ ubifs_scan_destroy(sleb);
-+out_free:
-+ destroy_done_tree(&done_tree);
-+ vfree(buf);
-+ return err;
-+}
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+/**
-+ * dbg_check_bud_bytes - make sure bud bytes calculation are all right.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function makes sure the amount of flash space used by closed buds
-+ * ('c->bud_bytes' is correct). Returns zero in case of success and %-EINVAL in
-+ * case of failure.
-+ */
-+static int dbg_check_bud_bytes(struct ubifs_info *c)
-+{
-+ int i, err = 0;
-+ struct ubifs_bud *bud;
-+ long long bud_bytes = 0;
-+
-+ if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
-+ return 0;
-+
-+ spin_lock(&c->buds_lock);
-+ for (i = 0; i < c->jhead_cnt; i++)
-+ list_for_each_entry(bud, &c->jheads[i].buds_list, list)
-+ bud_bytes += c->leb_size - bud->start;
-+
-+ if (c->bud_bytes != bud_bytes) {
-+ ubifs_err("bad bud_bytes %lld, calculated %lld",
-+ c->bud_bytes, bud_bytes);
-+ err = -EINVAL;
-+ }
-+ spin_unlock(&c->buds_lock);
-+
-+ return err;
-+}
-+
-+#endif /* CONFIG_UBIFS_FS_DEBUG */
---- linux-2.6.24.7.old/fs/ubifs/lprops.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/lprops.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1353 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file implements the functions that access LEB properties and their
-+ * categories. LEBs are categorized based on the needs of UBIFS, and the
-+ * categories are stored as either heaps or lists to provide a fast way of
-+ * finding a LEB in a particular category. For example, UBIFS may need to find
-+ * an empty LEB for the journal, or a very dirty LEB for garbage collection.
-+ */
-+
-+#include "ubifs.h"
-+
-+/**
-+ * get_heap_comp_val - get the LEB properties value for heap comparisons.
-+ * @lprops: LEB properties
-+ * @cat: LEB category
-+ */
-+static int get_heap_comp_val(struct ubifs_lprops *lprops, int cat)
-+{
-+ switch (cat) {
-+ case LPROPS_FREE:
-+ return lprops->free;
-+ case LPROPS_DIRTY_IDX:
-+ return lprops->free + lprops->dirty;
-+ default:
-+ return lprops->dirty;
-+ }
-+}
-+
-+/**
-+ * move_up_lpt_heap - move a new heap entry up as far as possible.
-+ * @c: UBIFS file-system description object
-+ * @heap: LEB category heap
-+ * @lprops: LEB properties to move
-+ * @cat: LEB category
-+ *
-+ * New entries to a heap are added at the bottom and then moved up until the
-+ * parent's value is greater. In the case of LPT's category heaps, the value
-+ * is either the amount of free space or the amount of dirty space, depending
-+ * on the category.
-+ */
-+static void move_up_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap,
-+ struct ubifs_lprops *lprops, int cat)
-+{
-+ int val1, val2, hpos;
-+
-+ hpos = lprops->hpos;
-+ if (!hpos)
-+ return; /* Already top of the heap */
-+ val1 = get_heap_comp_val(lprops, cat);
-+ /* Compare to parent and, if greater, move up the heap */
-+ do {
-+ int ppos = (hpos - 1) / 2;
-+
-+ val2 = get_heap_comp_val(heap->arr[ppos], cat);
-+ if (val2 >= val1)
-+ return;
-+ /* Greater than parent so move up */
-+ heap->arr[ppos]->hpos = hpos;
-+ heap->arr[hpos] = heap->arr[ppos];
-+ heap->arr[ppos] = lprops;
-+ lprops->hpos = ppos;
-+ hpos = ppos;
-+ } while (hpos);
-+}
-+
-+/**
-+ * adjust_lpt_heap - move a changed heap entry up or down the heap.
-+ * @c: UBIFS file-system description object
-+ * @heap: LEB category heap
-+ * @lprops: LEB properties to move
-+ * @hpos: heap position of @lprops
-+ * @cat: LEB category
-+ *
-+ * Changed entries in a heap are moved up or down until the parent's value is
-+ * greater. In the case of LPT's category heaps, the value is either the amount
-+ * of free space or the amount of dirty space, depending on the category.
-+ */
-+static void adjust_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap,
-+ struct ubifs_lprops *lprops, int hpos, int cat)
-+{
-+ int val1, val2, val3, cpos;
-+
-+ val1 = get_heap_comp_val(lprops, cat);
-+ /* Compare to parent and, if greater than parent, move up the heap */
-+ if (hpos) {
-+ int ppos = (hpos - 1) / 2;
-+
-+ val2 = get_heap_comp_val(heap->arr[ppos], cat);
-+ if (val1 > val2) {
-+ /* Greater than parent so move up */
-+ while (1) {
-+ heap->arr[ppos]->hpos = hpos;
-+ heap->arr[hpos] = heap->arr[ppos];
-+ heap->arr[ppos] = lprops;
-+ lprops->hpos = ppos;
-+ hpos = ppos;
-+ if (!hpos)
-+ return;
-+ ppos = (hpos - 1) / 2;
-+ val2 = get_heap_comp_val(heap->arr[ppos], cat);
-+ if (val1 <= val2)
-+ return;
-+ /* Still greater than parent so keep going */
-+ }
-+ }
-+ }
-+ /* Not greater than parent, so compare to children */
-+ while (1) {
-+ /* Compare to left child */
-+ cpos = hpos * 2 + 1;
-+ if (cpos >= heap->cnt)
-+ return;
-+ val2 = get_heap_comp_val(heap->arr[cpos], cat);
-+ if (val1 < val2) {
-+ /* Less than left child, so promote biggest child */
-+ if (cpos + 1 < heap->cnt) {
-+ val3 = get_heap_comp_val(heap->arr[cpos + 1],
-+ cat);
-+ if (val3 > val2)
-+ cpos += 1; /* Right child is bigger */
-+ }
-+ heap->arr[cpos]->hpos = hpos;
-+ heap->arr[hpos] = heap->arr[cpos];
-+ heap->arr[cpos] = lprops;
-+ lprops->hpos = cpos;
-+ hpos = cpos;
-+ continue;
-+ }
-+ /* Compare to right child */
-+ cpos += 1;
-+ if (cpos >= heap->cnt)
-+ return;
-+ val3 = get_heap_comp_val(heap->arr[cpos], cat);
-+ if (val1 < val3) {
-+ /* Less than right child, so promote right child */
-+ heap->arr[cpos]->hpos = hpos;
-+ heap->arr[hpos] = heap->arr[cpos];
-+ heap->arr[cpos] = lprops;
-+ lprops->hpos = cpos;
-+ hpos = cpos;
-+ continue;
-+ }
-+ return;
-+ }
-+}
-+
-+/**
-+ * add_to_lpt_heap - add LEB properties to a LEB category heap.
-+ * @c: UBIFS file-system description object
-+ * @lprops: LEB properties to add
-+ * @cat: LEB category
-+ *
-+ * This function returns %1 if @lprops is added to the heap for LEB category
-+ * @cat, otherwise %0 is returned because the heap is full.
-+ */
-+static int add_to_lpt_heap(struct ubifs_info *c, struct ubifs_lprops *lprops,
-+ int cat)
-+{
-+ struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1];
-+
-+ if (heap->cnt >= heap->max_cnt) {
-+ const int b = LPT_HEAP_SZ / 2 - 1;
-+ int cpos, val1, val2;
-+
-+ /* Compare to some other LEB on the bottom of heap */
-+ /* Pick a position kind of randomly */
-+ cpos = (((size_t)lprops >> 4) & b) + b;
-+ ubifs_assert(cpos >= b);
-+ ubifs_assert(cpos < LPT_HEAP_SZ);
-+ ubifs_assert(cpos < heap->cnt);
-+
-+ val1 = get_heap_comp_val(lprops, cat);
-+ val2 = get_heap_comp_val(heap->arr[cpos], cat);
-+ if (val1 > val2) {
-+ struct ubifs_lprops *lp;
-+
-+ lp = heap->arr[cpos];
-+ lp->flags &= ~LPROPS_CAT_MASK;
-+ lp->flags |= LPROPS_UNCAT;
-+ list_add(&lp->list, &c->uncat_list);
-+ lprops->hpos = cpos;
-+ heap->arr[cpos] = lprops;
-+ move_up_lpt_heap(c, heap, lprops, cat);
-+ dbg_check_heap(c, heap, cat, lprops->hpos);
-+ return 1; /* Added to heap */
-+ }
-+ dbg_check_heap(c, heap, cat, -1);
-+ return 0; /* Not added to heap */
-+ } else {
-+ lprops->hpos = heap->cnt++;
-+ heap->arr[lprops->hpos] = lprops;
-+ move_up_lpt_heap(c, heap, lprops, cat);
-+ dbg_check_heap(c, heap, cat, lprops->hpos);
-+ return 1; /* Added to heap */
-+ }
-+}
-+
-+/**
-+ * remove_from_lpt_heap - remove LEB properties from a LEB category heap.
-+ * @c: UBIFS file-system description object
-+ * @lprops: LEB properties to remove
-+ * @cat: LEB category
-+ */
-+static void remove_from_lpt_heap(struct ubifs_info *c,
-+ struct ubifs_lprops *lprops, int cat)
-+{
-+ struct ubifs_lpt_heap *heap;
-+ int hpos = lprops->hpos;
-+
-+ heap = &c->lpt_heap[cat - 1];
-+ ubifs_assert(hpos >= 0 && hpos < heap->cnt);
-+ ubifs_assert(heap->arr[hpos] == lprops);
-+ heap->cnt -= 1;
-+ if (hpos < heap->cnt) {
-+ heap->arr[hpos] = heap->arr[heap->cnt];
-+ heap->arr[hpos]->hpos = hpos;
-+ adjust_lpt_heap(c, heap, heap->arr[hpos], hpos, cat);
-+ }
-+ dbg_check_heap(c, heap, cat, -1);
-+}
-+
-+/**
-+ * lpt_heap_replace - replace lprops in a category heap.
-+ * @c: UBIFS file-system description object
-+ * @old_lprops: LEB properties to replace
-+ * @new_lprops: LEB properties with which to replace
-+ * @cat: LEB category
-+ *
-+ * During commit it is sometimes necessary to copy a pnode (see dirty_cow_pnode)
-+ * and the lprops that the pnode contains. When that happens, references in
-+ * the category heaps to those lprops must be updated to point to the new
-+ * lprops. This function does that.
-+ */
-+static void lpt_heap_replace(struct ubifs_info *c,
-+ struct ubifs_lprops *old_lprops,
-+ struct ubifs_lprops *new_lprops, int cat)
-+{
-+ struct ubifs_lpt_heap *heap;
-+ int hpos = new_lprops->hpos;
-+
-+ heap = &c->lpt_heap[cat - 1];
-+ heap->arr[hpos] = new_lprops;
-+}
-+
-+/**
-+ * ubifs_add_to_cat - add LEB properties to a category list or heap.
-+ * @c: UBIFS file-system description object
-+ * @lprops: LEB properties to add
-+ * @cat: LEB category to which to add
-+ *
-+ * LEB properties are categorized to enable fast find operations.
-+ */
-+void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
-+ int cat)
-+{
-+ switch (cat) {
-+ case LPROPS_DIRTY:
-+ case LPROPS_DIRTY_IDX:
-+ case LPROPS_FREE:
-+ if (add_to_lpt_heap(c, lprops, cat))
-+ break;
-+ /* No more room on heap so make it uncategorized */
-+ cat = LPROPS_UNCAT;
-+ /* Fall through */
-+ case LPROPS_UNCAT:
-+ list_add(&lprops->list, &c->uncat_list);
-+ break;
-+ case LPROPS_EMPTY:
-+ list_add(&lprops->list, &c->empty_list);
-+ break;
-+ case LPROPS_FREEABLE:
-+ list_add(&lprops->list, &c->freeable_list);
-+ c->freeable_cnt += 1;
-+ break;
-+ case LPROPS_FRDI_IDX:
-+ list_add(&lprops->list, &c->frdi_idx_list);
-+ break;
-+ default:
-+ ubifs_assert(0);
-+ }
-+ lprops->flags &= ~LPROPS_CAT_MASK;
-+ lprops->flags |= cat;
-+}
-+
-+/**
-+ * ubifs_remove_from_cat - remove LEB properties from a category list or heap.
-+ * @c: UBIFS file-system description object
-+ * @lprops: LEB properties to remove
-+ * @cat: LEB category from which to remove
-+ *
-+ * LEB properties are categorized to enable fast find operations.
-+ */
-+static void ubifs_remove_from_cat(struct ubifs_info *c,
-+ struct ubifs_lprops *lprops, int cat)
-+{
-+ switch (cat) {
-+ case LPROPS_DIRTY:
-+ case LPROPS_DIRTY_IDX:
-+ case LPROPS_FREE:
-+ remove_from_lpt_heap(c, lprops, cat);
-+ break;
-+ case LPROPS_FREEABLE:
-+ c->freeable_cnt -= 1;
-+ ubifs_assert(c->freeable_cnt >= 0);
-+ /* Fall through */
-+ case LPROPS_UNCAT:
-+ case LPROPS_EMPTY:
-+ case LPROPS_FRDI_IDX:
-+ ubifs_assert(!list_empty(&lprops->list));
-+ list_del(&lprops->list);
-+ break;
-+ default:
-+ ubifs_assert(0);
-+ }
-+}
-+
-+/**
-+ * ubifs_replace_cat - replace lprops in a category list or heap.
-+ * @c: UBIFS file-system description object
-+ * @old_lprops: LEB properties to replace
-+ * @new_lprops: LEB properties with which to replace
-+ *
-+ * During commit it is sometimes necessary to copy a pnode (see dirty_cow_pnode)
-+ * and the lprops that the pnode contains. When that happens, references in
-+ * category lists and heaps must be replaced. This function does that.
-+ */
-+void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops,
-+ struct ubifs_lprops *new_lprops)
-+{
-+ int cat;
-+
-+ cat = new_lprops->flags & LPROPS_CAT_MASK;
-+ switch (cat) {
-+ case LPROPS_DIRTY:
-+ case LPROPS_DIRTY_IDX:
-+ case LPROPS_FREE:
-+ lpt_heap_replace(c, old_lprops, new_lprops, cat);
-+ break;
-+ case LPROPS_UNCAT:
-+ case LPROPS_EMPTY:
-+ case LPROPS_FREEABLE:
-+ case LPROPS_FRDI_IDX:
-+ list_replace(&old_lprops->list, &new_lprops->list);
-+ break;
-+ default:
-+ ubifs_assert(0);
-+ }
-+}
-+
-+/**
-+ * ubifs_ensure_cat - ensure LEB properties are categorized.
-+ * @c: UBIFS file-system description object
-+ * @lprops: LEB properties
-+ *
-+ * A LEB may have fallen off of the bottom of a heap, and ended up as
-+ * uncategorized even though it has enough space for us now. If that is the case
-+ * this function will put the LEB back onto a heap.
-+ */
-+void ubifs_ensure_cat(struct ubifs_info *c, struct ubifs_lprops *lprops)
-+{
-+ int cat = lprops->flags & LPROPS_CAT_MASK;
-+
-+ if (cat != LPROPS_UNCAT)
-+ return;
-+ cat = ubifs_categorize_lprops(c, lprops);
-+ if (cat == LPROPS_UNCAT)
-+ return;
-+ ubifs_remove_from_cat(c, lprops, LPROPS_UNCAT);
-+ ubifs_add_to_cat(c, lprops, cat);
-+}
-+
-+/**
-+ * ubifs_categorize_lprops - categorize LEB properties.
-+ * @c: UBIFS file-system description object
-+ * @lprops: LEB properties to categorize
-+ *
-+ * LEB properties are categorized to enable fast find operations. This function
-+ * returns the LEB category to which the LEB properties belong. Note however
-+ * that if the LEB category is stored as a heap and the heap is full, the
-+ * LEB properties may have their category changed to %LPROPS_UNCAT.
-+ */
-+int ubifs_categorize_lprops(const struct ubifs_info *c,
-+ const struct ubifs_lprops *lprops)
-+{
-+ if (lprops->flags & LPROPS_TAKEN)
-+ return LPROPS_UNCAT;
-+
-+ if (lprops->free == c->leb_size) {
-+ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
-+ return LPROPS_EMPTY;
-+ }
-+
-+ if (lprops->free + lprops->dirty == c->leb_size) {
-+ if (lprops->flags & LPROPS_INDEX)
-+ return LPROPS_FRDI_IDX;
-+ else
-+ return LPROPS_FREEABLE;
-+ }
-+
-+ if (lprops->flags & LPROPS_INDEX) {
-+ if (lprops->dirty + lprops->free >= c->min_idx_node_sz)
-+ return LPROPS_DIRTY_IDX;
-+ } else {
-+ if (lprops->dirty >= c->dead_wm &&
-+ lprops->dirty > lprops->free)
-+ return LPROPS_DIRTY;
-+ if (lprops->free > 0)
-+ return LPROPS_FREE;
-+ }
-+
-+ return LPROPS_UNCAT;
-+}
-+
-+/**
-+ * change_category - change LEB properties category.
-+ * @c: UBIFS file-system description object
-+ * @lprops: LEB properties to recategorize
-+ *
-+ * LEB properties are categorized to enable fast find operations. When the LEB
-+ * properties change they must be recategorized.
-+ */
-+static void change_category(struct ubifs_info *c, struct ubifs_lprops *lprops)
-+{
-+ int old_cat = lprops->flags & LPROPS_CAT_MASK;
-+ int new_cat = ubifs_categorize_lprops(c, lprops);
-+
-+ if (old_cat == new_cat) {
-+ struct ubifs_lpt_heap *heap = &c->lpt_heap[new_cat - 1];
-+
-+ /* lprops on a heap now must be moved up or down */
-+ if (new_cat < 1 || new_cat > LPROPS_HEAP_CNT)
-+ return; /* Not on a heap */
-+ heap = &c->lpt_heap[new_cat - 1];
-+ adjust_lpt_heap(c, heap, lprops, lprops->hpos, new_cat);
-+ } else {
-+ ubifs_remove_from_cat(c, lprops, old_cat);
-+ ubifs_add_to_cat(c, lprops, new_cat);
-+ }
-+}
-+
-+/**
-+ * ubifs_get_lprops - get reference to LEB properties.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function locks lprops. Lprops have to be unlocked by
-+ * 'ubifs_release_lprops()'.
-+ */
-+void ubifs_get_lprops(struct ubifs_info *c)
-+{
-+ mutex_lock(&c->lp_mutex);
-+}
-+
-+/**
-+ * calc_dark - calculate LEB dark space size.
-+ * @c: the UBIFS file-system description object
-+ * @spc: amount of free and dirty space in the LEB
-+ *
-+ * This function calculates amount of dark space in an LEB which has @spc bytes
-+ * of free and dirty space. Returns the calculations result.
-+ *
-+ * Dark space is the space which is not always usable - it depends on which
-+ * nodes are written in which order. E.g., if an LEB has only 512 free bytes,
-+ * it is dark space, because it cannot fit a large data node. So UBIFS cannot
-+ * count on this LEB and treat these 512 bytes as usable because it is not true
-+ * if, for example, only big chunks of uncompressible data will be written to
-+ * the FS.
-+ */
-+static int calc_dark(struct ubifs_info *c, int spc)
-+{
-+ ubifs_assert(!(spc & 7));
-+
-+ if (spc < c->dark_wm)
-+ return spc;
-+
-+ /*
-+ * If we have slightly more space then the dark space watermark, we can
-+ * anyway safely assume it we'll be able to write a node of the
-+ * smallest size there.
-+ */
-+ if (spc - c->dark_wm < MIN_WRITE_SZ)
-+ return spc - MIN_WRITE_SZ;
-+
-+ return c->dark_wm;
-+}
-+
-+/**
-+ * is_lprops_dirty - determine if LEB properties are dirty.
-+ * @c: the UBIFS file-system description object
-+ * @lprops: LEB properties to test
-+ */
-+static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops)
-+{
-+ struct ubifs_pnode *pnode;
-+ int pos;
-+
-+ pos = (lprops->lnum - c->main_first) & (UBIFS_LPT_FANOUT - 1);
-+ pnode = (struct ubifs_pnode *)container_of(lprops - pos,
-+ struct ubifs_pnode,
-+ lprops[0]);
-+ return !test_bit(COW_ZNODE, &pnode->flags) &&
-+ test_bit(DIRTY_CNODE, &pnode->flags);
-+}
-+
-+/**
-+ * ubifs_change_lp - change LEB properties.
-+ * @c: the UBIFS file-system description object
-+ * @lp: LEB properties to change
-+ * @free: new free space amount
-+ * @dirty: new dirty space amount
-+ * @flags: new flags
-+ * @idx_gc_cnt: change to the count of idx_gc list
-+ *
-+ * This function changes LEB properties. This function does not change a LEB
-+ * property (@free, @dirty or @flag) if the value passed is %-1.
-+ *
-+ * This function returns a pointer to the updated LEB properties on success
-+ * and a negative error code on failure. N.B. the LEB properties may have had to
-+ * be copied (due to COW) and consequently the pointer returned may not be the
-+ * same as the pointer passed.
-+ */
-+const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
-+ const struct ubifs_lprops *lp,
-+ int free, int dirty, int flags,
-+ int idx_gc_cnt)
-+{
-+ /*
-+ * This is the only function that is allowed to change lprops, so we
-+ * discard the const qualifier.
-+ */
-+ struct ubifs_lprops *lprops = (struct ubifs_lprops *)lp;
-+
-+ dbg_lp("LEB %d, free %d, dirty %d, flags %d",
-+ lprops->lnum, free, dirty, flags);
-+
-+ ubifs_assert(mutex_is_locked(&c->lp_mutex));
-+ ubifs_assert(c->lst.empty_lebs >= 0 &&
-+ c->lst.empty_lebs <= c->main_lebs);
-+ ubifs_assert(c->freeable_cnt >= 0);
-+ ubifs_assert(c->freeable_cnt <= c->main_lebs);
-+ ubifs_assert(c->lst.taken_empty_lebs >= 0);
-+ ubifs_assert(c->lst.taken_empty_lebs <= c->lst.empty_lebs);
-+ ubifs_assert(!(c->lst.total_free & 7) && !(c->lst.total_dirty & 7));
-+ ubifs_assert(!(c->lst.total_dead & 7) && !(c->lst.total_dark & 7));
-+ ubifs_assert(!(c->lst.total_used & 7));
-+
-+ if (!is_lprops_dirty(c, lprops)) {
-+ lprops = ubifs_lpt_lookup_dirty(c, lprops->lnum);
-+ if (IS_ERR(lprops))
-+ return lprops;
-+ } else
-+ ubifs_assert(lprops == ubifs_lpt_lookup_dirty(c, lprops->lnum));
-+
-+ ubifs_assert(!(lprops->free & 7) && !(lprops->dirty & 7));
-+
-+ spin_lock(&c->space_lock);
-+
-+ if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size)
-+ c->lst.taken_empty_lebs -= 1;
-+
-+ if (!(lprops->flags & LPROPS_INDEX)) {
-+ int old_spc;
-+
-+ old_spc = lprops->free + lprops->dirty;
-+ if (old_spc < c->dead_wm)
-+ c->lst.total_dead -= old_spc;
-+ else
-+ c->lst.total_dark -= calc_dark(c, old_spc);
-+
-+ c->lst.total_used -= c->leb_size - old_spc;
-+ }
-+
-+ if (free != -1) {
-+ free = ALIGN(free, 8);
-+ c->lst.total_free += free - lprops->free;
-+
-+ /* Increase or decrease empty LEBs counter if needed */
-+ if (free == c->leb_size) {
-+ if (lprops->free != c->leb_size)
-+ c->lst.empty_lebs += 1;
-+ } else if (lprops->free == c->leb_size)
-+ c->lst.empty_lebs -= 1;
-+ lprops->free = free;
-+ }
-+
-+ if (dirty != -1) {
-+ dirty = ALIGN(dirty, 8);
-+ c->lst.total_dirty += dirty - lprops->dirty;
-+ lprops->dirty = dirty;
-+ }
-+
-+ if (flags != -1) {
-+ /* Take care about indexing LEBs counter if needed */
-+ if ((lprops->flags & LPROPS_INDEX)) {
-+ if (!(flags & LPROPS_INDEX))
-+ c->lst.idx_lebs -= 1;
-+ } else if (flags & LPROPS_INDEX)
-+ c->lst.idx_lebs += 1;
-+ lprops->flags = flags;
-+ }
-+
-+ if (!(lprops->flags & LPROPS_INDEX)) {
-+ int new_spc;
-+
-+ new_spc = lprops->free + lprops->dirty;
-+ if (new_spc < c->dead_wm)
-+ c->lst.total_dead += new_spc;
-+ else
-+ c->lst.total_dark += calc_dark(c, new_spc);
-+
-+ c->lst.total_used += c->leb_size - new_spc;
-+ }
-+
-+ if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size)
-+ c->lst.taken_empty_lebs += 1;
-+
-+ change_category(c, lprops);
-+
-+ c->idx_gc_cnt += idx_gc_cnt;
-+
-+ spin_unlock(&c->space_lock);
-+
-+ return lprops;
-+}
-+
-+/**
-+ * ubifs_release_lprops - release lprops lock.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function has to be called after each 'ubifs_get_lprops()' call to
-+ * unlock lprops.
-+ */
-+void ubifs_release_lprops(struct ubifs_info *c)
-+{
-+ ubifs_assert(mutex_is_locked(&c->lp_mutex));
-+ ubifs_assert(c->lst.empty_lebs >= 0 &&
-+ c->lst.empty_lebs <= c->main_lebs);
-+
-+ mutex_unlock(&c->lp_mutex);
-+}
-+
-+/**
-+ * ubifs_get_lp_stats - get lprops statistics.
-+ * @c: UBIFS file-system description object
-+ * @st: return statistics
-+ */
-+void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *st)
-+{
-+ spin_lock(&c->space_lock);
-+ memcpy(st, &c->lst, sizeof(struct ubifs_lp_stats));
-+ spin_unlock(&c->space_lock);
-+}
-+
-+/**
-+ * ubifs_change_one_lp - change LEB properties.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB to change properties for
-+ * @free: amount of free space
-+ * @dirty: amount of dirty space
-+ * @flags_set: flags to set
-+ * @flags_clean: flags to clean
-+ * @idx_gc_cnt: change to the count of idx_gc list
-+ *
-+ * This function changes properties of LEB @lnum. It is a helper wrapper over
-+ * 'ubifs_change_lp()' which hides lprops get/release. The arguments are the
-+ * same as in case of 'ubifs_change_lp()'. Returns zero in case of success and
-+ * a negative error code in case of failure.
-+ */
-+int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
-+ int flags_set, int flags_clean, int idx_gc_cnt)
-+{
-+ int err = 0, flags;
-+ const struct ubifs_lprops *lp;
-+
-+ ubifs_get_lprops(c);
-+
-+ lp = ubifs_lpt_lookup_dirty(c, lnum);
-+ if (IS_ERR(lp)) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+
-+ flags = (lp->flags | flags_set) & ~flags_clean;
-+ lp = ubifs_change_lp(c, lp, free, dirty, flags, idx_gc_cnt);
-+ if (IS_ERR(lp))
-+ err = PTR_ERR(lp);
-+
-+out:
-+ ubifs_release_lprops(c);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_update_one_lp - update LEB properties.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB to change properties for
-+ * @free: amount of free space
-+ * @dirty: amount of dirty space to add
-+ * @flags_set: flags to set
-+ * @flags_clean: flags to clean
-+ *
-+ * This function is the same as 'ubifs_change_one_lp()' but @dirty is added to
-+ * current dirty space, not substitutes it.
-+ */
-+int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
-+ int flags_set, int flags_clean)
-+{
-+ int err = 0, flags;
-+ const struct ubifs_lprops *lp;
-+
-+ ubifs_get_lprops(c);
-+
-+ lp = ubifs_lpt_lookup_dirty(c, lnum);
-+ if (IS_ERR(lp)) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+
-+ flags = (lp->flags | flags_set) & ~flags_clean;
-+ lp = ubifs_change_lp(c, lp, free, lp->dirty + dirty, flags, 0);
-+ if (IS_ERR(lp))
-+ err = PTR_ERR(lp);
-+
-+out:
-+ ubifs_release_lprops(c);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_read_one_lp - read LEB properties.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB to read properties for
-+ * @lp: where to store read properties
-+ *
-+ * This helper function reads properties of a LEB @lnum and stores them in @lp.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp)
-+{
-+ int err = 0;
-+ const struct ubifs_lprops *lpp;
-+
-+ ubifs_get_lprops(c);
-+
-+ lpp = ubifs_lpt_lookup(c, lnum);
-+ if (IS_ERR(lpp)) {
-+ err = PTR_ERR(lpp);
-+ goto out;
-+ }
-+
-+ memcpy(lp, lpp, sizeof(struct ubifs_lprops));
-+
-+out:
-+ ubifs_release_lprops(c);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_fast_find_free - try to find a LEB with free space quickly.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function returns LEB properties for a LEB with free space or %NULL if
-+ * the function is unable to find a LEB quickly.
-+ */
-+const struct ubifs_lprops *ubifs_fast_find_free(struct ubifs_info *c)
-+{
-+ struct ubifs_lprops *lprops;
-+ struct ubifs_lpt_heap *heap;
-+
-+ ubifs_assert(mutex_is_locked(&c->lp_mutex));
-+
-+ heap = &c->lpt_heap[LPROPS_FREE - 1];
-+ if (heap->cnt == 0)
-+ return NULL;
-+
-+ lprops = heap->arr[0];
-+ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-+ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
-+ return lprops;
-+}
-+
-+/**
-+ * ubifs_fast_find_empty - try to find an empty LEB quickly.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function returns LEB properties for an empty LEB or %NULL if the
-+ * function is unable to find an empty LEB quickly.
-+ */
-+const struct ubifs_lprops *ubifs_fast_find_empty(struct ubifs_info *c)
-+{
-+ struct ubifs_lprops *lprops;
-+
-+ ubifs_assert(mutex_is_locked(&c->lp_mutex));
-+
-+ if (list_empty(&c->empty_list))
-+ return NULL;
-+
-+ lprops = list_entry(c->empty_list.next, struct ubifs_lprops, list);
-+ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-+ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
-+ ubifs_assert(lprops->free == c->leb_size);
-+ return lprops;
-+}
-+
-+/**
-+ * ubifs_fast_find_freeable - try to find a freeable LEB quickly.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function returns LEB properties for a freeable LEB or %NULL if the
-+ * function is unable to find a freeable LEB quickly.
-+ */
-+const struct ubifs_lprops *ubifs_fast_find_freeable(struct ubifs_info *c)
-+{
-+ struct ubifs_lprops *lprops;
-+
-+ ubifs_assert(mutex_is_locked(&c->lp_mutex));
-+
-+ if (list_empty(&c->freeable_list))
-+ return NULL;
-+
-+ lprops = list_entry(c->freeable_list.next, struct ubifs_lprops, list);
-+ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-+ ubifs_assert(!(lprops->flags & LPROPS_INDEX));
-+ ubifs_assert(lprops->free + lprops->dirty == c->leb_size);
-+ ubifs_assert(c->freeable_cnt > 0);
-+ return lprops;
-+}
-+
-+/**
-+ * ubifs_fast_find_frdi_idx - try to find a freeable index LEB quickly.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function returns LEB properties for a freeable index LEB or %NULL if the
-+ * function is unable to find a freeable index LEB quickly.
-+ */
-+const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c)
-+{
-+ struct ubifs_lprops *lprops;
-+
-+ ubifs_assert(mutex_is_locked(&c->lp_mutex));
-+
-+ if (list_empty(&c->frdi_idx_list))
-+ return NULL;
-+
-+ lprops = list_entry(c->frdi_idx_list.next, struct ubifs_lprops, list);
-+ ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-+ ubifs_assert((lprops->flags & LPROPS_INDEX));
-+ ubifs_assert(lprops->free + lprops->dirty == c->leb_size);
-+ return lprops;
-+}
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+/**
-+ * dbg_check_cats - check category heaps and lists.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int dbg_check_cats(struct ubifs_info *c)
-+{
-+ struct ubifs_lprops *lprops;
-+ struct list_head *pos;
-+ int i, cat;
-+
-+ if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
-+ return 0;
-+
-+ list_for_each_entry(lprops, &c->empty_list, list) {
-+ if (lprops->free != c->leb_size) {
-+ ubifs_err("non-empty LEB %d on empty list "
-+ "(free %d dirty %d flags %d)", lprops->lnum,
-+ lprops->free, lprops->dirty, lprops->flags);
-+ return -EINVAL;
-+ }
-+ if (lprops->flags & LPROPS_TAKEN) {
-+ ubifs_err("taken LEB %d on empty list "
-+ "(free %d dirty %d flags %d)", lprops->lnum,
-+ lprops->free, lprops->dirty, lprops->flags);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ i = 0;
-+ list_for_each_entry(lprops, &c->freeable_list, list) {
-+ if (lprops->free + lprops->dirty != c->leb_size) {
-+ ubifs_err("non-freeable LEB %d on freeable list "
-+ "(free %d dirty %d flags %d)", lprops->lnum,
-+ lprops->free, lprops->dirty, lprops->flags);
-+ return -EINVAL;
-+ }
-+ if (lprops->flags & LPROPS_TAKEN) {
-+ ubifs_err("taken LEB %d on freeable list "
-+ "(free %d dirty %d flags %d)", lprops->lnum,
-+ lprops->free, lprops->dirty, lprops->flags);
-+ return -EINVAL;
-+ }
-+ i += 1;
-+ }
-+ if (i != c->freeable_cnt) {
-+ ubifs_err("freeable list count %d expected %d", i,
-+ c->freeable_cnt);
-+ return -EINVAL;
-+ }
-+
-+ i = 0;
-+ list_for_each(pos, &c->idx_gc)
-+ i += 1;
-+ if (i != c->idx_gc_cnt) {
-+ ubifs_err("idx_gc list count %d expected %d", i,
-+ c->idx_gc_cnt);
-+ return -EINVAL;
-+ }
-+
-+ list_for_each_entry(lprops, &c->frdi_idx_list, list) {
-+ if (lprops->free + lprops->dirty != c->leb_size) {
-+ ubifs_err("non-freeable LEB %d on frdi_idx list "
-+ "(free %d dirty %d flags %d)", lprops->lnum,
-+ lprops->free, lprops->dirty, lprops->flags);
-+ return -EINVAL;
-+ }
-+ if (lprops->flags & LPROPS_TAKEN) {
-+ ubifs_err("taken LEB %d on frdi_idx list "
-+ "(free %d dirty %d flags %d)", lprops->lnum,
-+ lprops->free, lprops->dirty, lprops->flags);
-+ return -EINVAL;
-+ }
-+ if (!(lprops->flags & LPROPS_INDEX)) {
-+ ubifs_err("non-index LEB %d on frdi_idx list "
-+ "(free %d dirty %d flags %d)", lprops->lnum,
-+ lprops->free, lprops->dirty, lprops->flags);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ for (cat = 1; cat <= LPROPS_HEAP_CNT; cat++) {
-+ struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1];
-+
-+ for (i = 0; i < heap->cnt; i++) {
-+ lprops = heap->arr[i];
-+ if (!lprops) {
-+ ubifs_err("null ptr in LPT heap cat %d", cat);
-+ return -EINVAL;
-+ }
-+ if (lprops->hpos != i) {
-+ ubifs_err("bad ptr in LPT heap cat %d", cat);
-+ return -EINVAL;
-+ }
-+ if (lprops->flags & LPROPS_TAKEN) {
-+ ubifs_err("taken LEB in LPT heap cat %d", cat);
-+ return -EINVAL;
-+ }
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
-+ int add_pos)
-+{
-+ int i = 0, j, err = 0;
-+
-+ if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
-+ return;
-+
-+ for (i = 0; i < heap->cnt; i++) {
-+ struct ubifs_lprops *lprops = heap->arr[i];
-+ struct ubifs_lprops *lp;
-+
-+ if (i != add_pos)
-+ if ((lprops->flags & LPROPS_CAT_MASK) != cat) {
-+ err = 1;
-+ goto out;
-+ }
-+ if (lprops->hpos != i) {
-+ err = 2;
-+ goto out;
-+ }
-+ lp = ubifs_lpt_lookup(c, lprops->lnum);
-+ if (IS_ERR(lp)) {
-+ err = 3;
-+ goto out;
-+ }
-+ if (lprops != lp) {
-+ dbg_msg("lprops %zx lp %zx lprops->lnum %d lp->lnum %d",
-+ (size_t)lprops, (size_t)lp, lprops->lnum,
-+ lp->lnum);
-+ err = 4;
-+ goto out;
-+ }
-+ for (j = 0; j < i; j++) {
-+ lp = heap->arr[j];
-+ if (lp == lprops) {
-+ err = 5;
-+ goto out;
-+ }
-+ if (lp->lnum == lprops->lnum) {
-+ err = 6;
-+ goto out;
-+ }
-+ }
-+ }
-+out:
-+ if (err) {
-+ dbg_msg("failed cat %d hpos %d err %d", cat, i, err);
-+ dbg_dump_stack();
-+ dbg_dump_heap(c, heap, cat);
-+ }
-+}
-+
-+/**
-+ * struct scan_check_data - data provided to scan callback function.
-+ * @lst: LEB properties statistics
-+ * @err: error code
-+ */
-+struct scan_check_data {
-+ struct ubifs_lp_stats lst;
-+ int err;
-+};
-+
-+/**
-+ * scan_check_cb - scan callback.
-+ * @c: the UBIFS file-system description object
-+ * @lp: LEB properties to scan
-+ * @in_tree: whether the LEB properties are in main memory
-+ * @data: information passed to and from the caller of the scan
-+ *
-+ * This function returns a code that indicates whether the scan should continue
-+ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
-+ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop
-+ * (%LPT_SCAN_STOP).
-+ */
-+static int scan_check_cb(struct ubifs_info *c,
-+ const struct ubifs_lprops *lp, int in_tree,
-+ struct scan_check_data *data)
-+{
-+ struct ubifs_scan_leb *sleb;
-+ struct ubifs_scan_node *snod;
-+ struct ubifs_lp_stats *lst = &data->lst;
-+ int cat, lnum = lp->lnum, is_idx = 0, used = 0, free, dirty;
-+
-+ cat = lp->flags & LPROPS_CAT_MASK;
-+ if (cat != LPROPS_UNCAT) {
-+ cat = ubifs_categorize_lprops(c, lp);
-+ if (cat != (lp->flags & LPROPS_CAT_MASK)) {
-+ ubifs_err("bad LEB category %d expected %d",
-+ (lp->flags & LPROPS_CAT_MASK), cat);
-+ goto out;
-+ }
-+ }
-+
-+ /* Check lp is on its category list (if it has one) */
-+ if (in_tree) {
-+ struct list_head *list = NULL;
-+
-+ switch (cat) {
-+ case LPROPS_EMPTY:
-+ list = &c->empty_list;
-+ break;
-+ case LPROPS_FREEABLE:
-+ list = &c->freeable_list;
-+ break;
-+ case LPROPS_FRDI_IDX:
-+ list = &c->frdi_idx_list;
-+ break;
-+ case LPROPS_UNCAT:
-+ list = &c->uncat_list;
-+ break;
-+ }
-+ if (list) {
-+ struct ubifs_lprops *lprops;
-+ int found = 0;
-+
-+ list_for_each_entry(lprops, list, list) {
-+ if (lprops == lp) {
-+ found = 1;
-+ break;
-+ }
-+ }
-+ if (!found) {
-+ ubifs_err("bad LPT list (category %d)", cat);
-+ goto out;
-+ }
-+ }
-+ }
-+
-+ /* Check lp is on its category heap (if it has one) */
-+ if (in_tree && cat > 0 && cat <= LPROPS_HEAP_CNT) {
-+ struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1];
-+
-+ if ((lp->hpos != -1 && heap->arr[lp->hpos]->lnum != lnum) ||
-+ lp != heap->arr[lp->hpos]) {
-+ ubifs_err("bad LPT heap (category %d)", cat);
-+ goto out;
-+ }
-+ }
-+
-+ sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
-+ if (IS_ERR(sleb)) {
-+ /*
-+ * After an unclean unmount, empty and freeable LEBs
-+ * may contain garbage.
-+ */
-+ if (lp->free == c->leb_size) {
-+ ubifs_err("scan errors were in empty LEB "
-+ "- continuing checking");
-+ lst->empty_lebs += 1;
-+ lst->total_free += c->leb_size;
-+ lst->total_dark += calc_dark(c, c->leb_size);
-+ return LPT_SCAN_CONTINUE;
-+ }
-+
-+ if (lp->free + lp->dirty == c->leb_size &&
-+ !(lp->flags & LPROPS_INDEX)) {
-+ ubifs_err("scan errors were in freeable LEB "
-+ "- continuing checking");
-+ lst->total_free += lp->free;
-+ lst->total_dirty += lp->dirty;
-+ lst->total_dark += calc_dark(c, c->leb_size);
-+ return LPT_SCAN_CONTINUE;
-+ }
-+ data->err = PTR_ERR(sleb);
-+ return LPT_SCAN_STOP;
-+ }
-+
-+ is_idx = -1;
-+ list_for_each_entry(snod, &sleb->nodes, list) {
-+ int found, level = 0;
-+
-+ cond_resched();
-+
-+ if (is_idx == -1)
-+ is_idx = (snod->type == UBIFS_IDX_NODE) ? 1 : 0;
-+
-+ if (is_idx && snod->type != UBIFS_IDX_NODE) {
-+ ubifs_err("indexing node in data LEB %d:%d",
-+ lnum, snod->offs);
-+ goto out_destroy;
-+ }
-+
-+ if (snod->type == UBIFS_IDX_NODE) {
-+ struct ubifs_idx_node *idx = snod->node;
-+
-+ key_read(c, ubifs_idx_key(c, idx), &snod->key);
-+ level = le16_to_cpu(idx->level);
-+ }
-+
-+ found = ubifs_tnc_has_node(c, &snod->key, level, lnum,
-+ snod->offs, is_idx);
-+ if (found) {
-+ if (found < 0)
-+ goto out_destroy;
-+ used += ALIGN(snod->len, 8);
-+ }
-+ }
-+
-+ free = c->leb_size - sleb->endpt;
-+ dirty = sleb->endpt - used;
-+
-+ if (free > c->leb_size || free < 0 || dirty > c->leb_size ||
-+ dirty < 0) {
-+ ubifs_err("bad calculated accounting for LEB %d: "
-+ "free %d, dirty %d", lnum, free, dirty);
-+ goto out_destroy;
-+ }
-+
-+ if (lp->free + lp->dirty == c->leb_size &&
-+ free + dirty == c->leb_size)
-+ if ((is_idx && !(lp->flags & LPROPS_INDEX)) ||
-+ (!is_idx && free == c->leb_size)) {
-+ /*
-+ * Empty or freeable LEBs could contain index
-+ * nodes from an uncompleted commit due to an
-+ * unclean unmount. Or they could be empty for
-+ * the same reason.
-+ */
-+ free = lp->free;
-+ dirty = lp->dirty;
-+ is_idx = 0;
-+ }
-+
-+ if (is_idx && lp->free + lp->dirty == free + dirty &&
-+ lnum != c->ihead_lnum) {
-+ /*
-+ * After an unclean unmount, an index LEB could have a different
-+ * amount of free space than the value recorded by lprops. That
-+ * is because the in-the-gaps method may use free space or
-+ * create free space (as a side-effect of using ubi_leb_change
-+ * and not writing the whole LEB). The incorrect free space
-+ * value is not a problem because the index is only ever
-+ * allocated empty LEBs, so there will never be an attempt to
-+ * write to the free space at the end of an index LEB - except
-+ * by the in-the-gaps method for which it is not a problem.
-+ */
-+ free = lp->free;
-+ dirty = lp->dirty;
-+ }
-+
-+ if (lp->free != free || lp->dirty != dirty)
-+ goto out_print;
-+
-+ if (is_idx && !(lp->flags & LPROPS_INDEX)) {
-+ if (free == c->leb_size)
-+ /* Free but not unmapped LEB, it's fine */
-+ is_idx = 0;
-+ else {
-+ ubifs_err("indexing node without indexing "
-+ "flag");
-+ goto out_print;
-+ }
-+ }
-+
-+ if (!is_idx && (lp->flags & LPROPS_INDEX)) {
-+ ubifs_err("data node with indexing flag");
-+ goto out_print;
-+ }
-+
-+ if (free == c->leb_size)
-+ lst->empty_lebs += 1;
-+
-+ if (is_idx)
-+ lst->idx_lebs += 1;
-+
-+ if (!(lp->flags & LPROPS_INDEX))
-+ lst->total_used += c->leb_size - free - dirty;
-+ lst->total_free += free;
-+ lst->total_dirty += dirty;
-+
-+ if (!(lp->flags & LPROPS_INDEX)) {
-+ int spc = free + dirty;
-+
-+ if (spc < c->dead_wm)
-+ lst->total_dead += spc;
-+ else
-+ lst->total_dark += calc_dark(c, spc);
-+ }
-+
-+ ubifs_scan_destroy(sleb);
-+
-+ return LPT_SCAN_CONTINUE;
-+
-+out_print:
-+ ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, "
-+ "should be free %d, dirty %d",
-+ lnum, lp->free, lp->dirty, lp->flags, free, dirty);
-+ dbg_dump_leb(c, lnum);
-+out_destroy:
-+ ubifs_scan_destroy(sleb);
-+out:
-+ data->err = -EINVAL;
-+ return LPT_SCAN_STOP;
-+}
-+
-+/**
-+ * dbg_check_lprops - check all LEB properties.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function checks all LEB properties and makes sure they are all correct.
-+ * It returns zero if everything is fine, %-EINVAL if there is an inconsistency
-+ * and other negative error codes in case of other errors. This function is
-+ * called while the file system is locked (because of commit start), so no
-+ * additional locking is required. Note that locking the LPT mutex would cause
-+ * a circular lock dependency with the TNC mutex.
-+ */
-+int dbg_check_lprops(struct ubifs_info *c)
-+{
-+ int i, err;
-+ struct scan_check_data data;
-+ struct ubifs_lp_stats *lst = &data.lst;
-+
-+ if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
-+ return 0;
-+
-+ /*
-+ * As we are going to scan the media, the write buffers have to be
-+ * synchronized.
-+ */
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
-+ if (err)
-+ return err;
-+ }
-+
-+ memset(lst, 0, sizeof(struct ubifs_lp_stats));
-+
-+ data.err = 0;
-+ err = ubifs_lpt_scan_nolock(c, c->main_first, c->leb_cnt - 1,
-+ (ubifs_lpt_scan_callback)scan_check_cb,
-+ &data);
-+ if (err && err != -ENOSPC)
-+ goto out;
-+ if (data.err) {
-+ err = data.err;
-+ goto out;
-+ }
-+
-+ if (lst->empty_lebs != c->lst.empty_lebs ||
-+ lst->idx_lebs != c->lst.idx_lebs ||
-+ lst->total_free != c->lst.total_free ||
-+ lst->total_dirty != c->lst.total_dirty ||
-+ lst->total_used != c->lst.total_used) {
-+ ubifs_err("bad overall accounting");
-+ ubifs_err("calculated: empty_lebs %d, idx_lebs %d, "
-+ "total_free %lld, total_dirty %lld, total_used %lld",
-+ lst->empty_lebs, lst->idx_lebs, lst->total_free,
-+ lst->total_dirty, lst->total_used);
-+ ubifs_err("read from lprops: empty_lebs %d, idx_lebs %d, "
-+ "total_free %lld, total_dirty %lld, total_used %lld",
-+ c->lst.empty_lebs, c->lst.idx_lebs, c->lst.total_free,
-+ c->lst.total_dirty, c->lst.total_used);
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (lst->total_dead != c->lst.total_dead ||
-+ lst->total_dark != c->lst.total_dark) {
-+ ubifs_err("bad dead/dark space accounting");
-+ ubifs_err("calculated: total_dead %lld, total_dark %lld",
-+ lst->total_dead, lst->total_dark);
-+ ubifs_err("read from lprops: total_dead %lld, total_dark %lld",
-+ c->lst.total_dead, c->lst.total_dark);
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ err = dbg_check_cats(c);
-+out:
-+ return err;
-+}
-+
-+#endif /* CONFIG_UBIFS_FS_DEBUG */
---- linux-2.6.24.7.old/fs/ubifs/lpt.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/lpt.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,2279 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file implements the LEB properties tree (LPT) area. The LPT area
-+ * contains the LEB properties tree, a table of LPT area eraseblocks (ltab), and
-+ * (for the "big" model) a table of saved LEB numbers (lsave). The LPT area sits
-+ * between the log and the orphan area.
-+ *
-+ * The LPT area is like a miniature self-contained file system. It is required
-+ * that it never runs out of space, is fast to access and update, and scales
-+ * logarithmically. The LEB properties tree is implemented as a wandering tree
-+ * much like the TNC, and the LPT area has its own garbage collection.
-+ *
-+ * The LPT has two slightly different forms called the "small model" and the
-+ * "big model". The small model is used when the entire LEB properties table
-+ * can be written into a single eraseblock. In that case, garbage collection
-+ * consists of just writing the whole table, which therefore makes all other
-+ * eraseblocks reusable. In the case of the big model, dirty eraseblocks are
-+ * selected for garbage collection, which consists are marking the nodes in
-+ * that LEB as dirty, and then only the dirty nodes are written out. Also, in
-+ * the case of the big model, a table of LEB numbers is saved so that the entire
-+ * LPT does not to be scanned looking for empty eraseblocks when UBIFS is first
-+ * mounted.
-+ */
-+
-+#include
-+#include "ubifs.h"
-+
-+/**
-+ * do_calc_lpt_geom - calculate sizes for the LPT area.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * Calculate the sizes of LPT bit fields, nodes, and tree, based on the
-+ * properties of the flash and whether LPT is "big" (c->big_lpt).
-+ */
-+static void do_calc_lpt_geom(struct ubifs_info *c)
-+{
-+ int i, n, bits, per_leb_wastage, max_pnode_cnt;
-+ long long sz, tot_wastage;
-+
-+ n = c->main_lebs + c->max_leb_cnt - c->leb_cnt;
-+ max_pnode_cnt = DIV_ROUND_UP(n, UBIFS_LPT_FANOUT);
-+
-+ c->lpt_hght = 1;
-+ n = UBIFS_LPT_FANOUT;
-+ while (n < max_pnode_cnt) {
-+ c->lpt_hght += 1;
-+ n <<= UBIFS_LPT_FANOUT_SHIFT;
-+ }
-+
-+ c->pnode_cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
-+
-+ n = DIV_ROUND_UP(c->pnode_cnt, UBIFS_LPT_FANOUT);
-+ c->nnode_cnt = n;
-+ for (i = 1; i < c->lpt_hght; i++) {
-+ n = DIV_ROUND_UP(n, UBIFS_LPT_FANOUT);
-+ c->nnode_cnt += n;
-+ }
-+
-+ c->space_bits = fls(c->leb_size) - 3;
-+ c->lpt_lnum_bits = fls(c->lpt_lebs);
-+ c->lpt_offs_bits = fls(c->leb_size - 1);
-+ c->lpt_spc_bits = fls(c->leb_size);
-+
-+ n = DIV_ROUND_UP(c->max_leb_cnt, UBIFS_LPT_FANOUT);
-+ c->pcnt_bits = fls(n - 1);
-+
-+ c->lnum_bits = fls(c->max_leb_cnt - 1);
-+
-+ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-+ (c->big_lpt ? c->pcnt_bits : 0) +
-+ (c->space_bits * 2 + 1) * UBIFS_LPT_FANOUT;
-+ c->pnode_sz = (bits + 7) / 8;
-+
-+ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-+ (c->big_lpt ? c->pcnt_bits : 0) +
-+ (c->lpt_lnum_bits + c->lpt_offs_bits) * UBIFS_LPT_FANOUT;
-+ c->nnode_sz = (bits + 7) / 8;
-+
-+ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-+ c->lpt_lebs * c->lpt_spc_bits * 2;
-+ c->ltab_sz = (bits + 7) / 8;
-+
-+ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-+ c->lnum_bits * c->lsave_cnt;
-+ c->lsave_sz = (bits + 7) / 8;
-+
-+ /* Calculate the minimum LPT size */
-+ c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
-+ c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
-+ c->lpt_sz += c->ltab_sz;
-+ c->lpt_sz += c->lsave_sz;
-+
-+ /* Add wastage */
-+ sz = c->lpt_sz;
-+ per_leb_wastage = max_t(int, c->pnode_sz, c->nnode_sz);
-+ sz += per_leb_wastage;
-+ tot_wastage = per_leb_wastage;
-+ while (sz > c->leb_size) {
-+ sz += per_leb_wastage;
-+ sz -= c->leb_size;
-+ tot_wastage += per_leb_wastage;
-+ }
-+ tot_wastage += ALIGN(sz, c->min_io_size) - sz;
-+ c->lpt_sz += tot_wastage;
-+}
-+
-+/**
-+ * ubifs_calc_lpt_geom - calculate and check sizes for the LPT area.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_calc_lpt_geom(struct ubifs_info *c)
-+{
-+ int lebs_needed;
-+ uint64_t sz;
-+
-+ do_calc_lpt_geom(c);
-+
-+ /* Verify that lpt_lebs is big enough */
-+ sz = c->lpt_sz * 2; /* Must have at least 2 times the size */
-+ sz += c->leb_size - 1;
-+ do_div(sz, c->leb_size);
-+ lebs_needed = sz;
-+ if (lebs_needed > c->lpt_lebs) {
-+ ubifs_err("too few LPT LEBs");
-+ return -EINVAL;
-+ }
-+
-+ /* Verify that ltab fits in a single LEB (since ltab is a single node */
-+ if (c->ltab_sz > c->leb_size) {
-+ ubifs_err("LPT ltab too big");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * calc_dflt_lpt_geom - calculate default LPT geometry.
-+ * @c: the UBIFS file-system description object
-+ * @main_lebs: number of main area LEBs is passed and returned here
-+ * @big_lpt: whether the LPT area is "big" is returned here
-+ *
-+ * The size of the LPT area depends on parameters that themselves are dependent
-+ * on the size of the LPT area. This function, successively recalculates the LPT
-+ * area geometry until the parameters and resultant geometry are consistent.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs,
-+ int *big_lpt)
-+{
-+ int i, lebs_needed;
-+ uint64_t sz;
-+
-+ /* Start by assuming the minimum number of LPT LEBs */
-+ c->lpt_lebs = UBIFS_MIN_LPT_LEBS;
-+ c->main_lebs = *main_lebs - c->lpt_lebs;
-+ if (c->main_lebs <= 0)
-+ return -EINVAL;
-+
-+ /* And assume we will use the small LPT model */
-+ c->big_lpt = 0;
-+
-+ /*
-+ * Calculate the geometry based on assumptions above and then see if it
-+ * makes sense
-+ */
-+ do_calc_lpt_geom(c);
-+
-+ /* Small LPT model must have lpt_sz < leb_size */
-+ if (c->lpt_sz > c->leb_size) {
-+ /* Nope, so try again using big LPT model */
-+ c->big_lpt = 1;
-+ do_calc_lpt_geom(c);
-+ }
-+
-+ /* Now check there are enough LPT LEBs */
-+ for (i = 0; i < 64 ; i++) {
-+ sz = c->lpt_sz * 4; /* Allow 4 times the size */
-+ sz += c->leb_size - 1;
-+ do_div(sz, c->leb_size);
-+ lebs_needed = sz;
-+ if (lebs_needed > c->lpt_lebs) {
-+ /* Not enough LPT LEBs so try again with more */
-+ c->lpt_lebs = lebs_needed;
-+ c->main_lebs = *main_lebs - c->lpt_lebs;
-+ if (c->main_lebs <= 0)
-+ return -EINVAL;
-+ do_calc_lpt_geom(c);
-+ continue;
-+ }
-+ if (c->ltab_sz > c->leb_size) {
-+ ubifs_err("LPT ltab too big");
-+ return -EINVAL;
-+ }
-+ *main_lebs = c->main_lebs;
-+ *big_lpt = c->big_lpt;
-+ return 0;
-+ }
-+ return -EINVAL;
-+}
-+
-+/**
-+ * pack_bits - pack bit fields end-to-end.
-+ * @addr: address at which to pack (passed and next address returned)
-+ * @pos: bit position at which to pack (passed and next position returned)
-+ * @val: value to pack
-+ * @nrbits: number of bits of value to pack (1-32)
-+ */
-+static void pack_bits(uint8_t **addr, int *pos, uint32_t val, int nrbits)
-+{
-+ uint8_t *p = *addr;
-+ int b = *pos;
-+
-+ ubifs_assert(nrbits > 0);
-+ ubifs_assert(nrbits <= 32);
-+ ubifs_assert(*pos >= 0);
-+ ubifs_assert(*pos < 8);
-+ ubifs_assert((val >> nrbits) == 0 || nrbits == 32);
-+ if (b) {
-+ *p |= ((uint8_t)val) << b;
-+ nrbits += b;
-+ if (nrbits > 8) {
-+ *++p = (uint8_t)(val >>= (8 - b));
-+ if (nrbits > 16) {
-+ *++p = (uint8_t)(val >>= 8);
-+ if (nrbits > 24) {
-+ *++p = (uint8_t)(val >>= 8);
-+ if (nrbits > 32)
-+ *++p = (uint8_t)(val >>= 8);
-+ }
-+ }
-+ }
-+ } else {
-+ *p = (uint8_t)val;
-+ if (nrbits > 8) {
-+ *++p = (uint8_t)(val >>= 8);
-+ if (nrbits > 16) {
-+ *++p = (uint8_t)(val >>= 8);
-+ if (nrbits > 24)
-+ *++p = (uint8_t)(val >>= 8);
-+ }
-+ }
-+ }
-+ b = nrbits & 7;
-+ if (b == 0)
-+ p++;
-+ *addr = p;
-+ *pos = b;
-+}
-+
-+/**
-+ * ubifs_unpack_bits - unpack bit fields.
-+ * @addr: address at which to unpack (passed and next address returned)
-+ * @pos: bit position at which to unpack (passed and next position returned)
-+ * @nrbits: number of bits of value to unpack (1-32)
-+ *
-+ * This functions returns the value unpacked.
-+ */
-+uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits)
-+{
-+ const int k = 32 - nrbits;
-+ uint8_t *p = *addr;
-+ int b = *pos;
-+ uint32_t val;
-+
-+ ubifs_assert(nrbits > 0);
-+ ubifs_assert(nrbits <= 32);
-+ ubifs_assert(*pos >= 0);
-+ ubifs_assert(*pos < 8);
-+ if (b) {
-+ val = p[1] | ((uint32_t)p[2] << 8) | ((uint32_t)p[3] << 16) |
-+ ((uint32_t)p[4] << 24);
-+ val <<= (8 - b);
-+ val |= *p >> b;
-+ nrbits += b;
-+ } else
-+ val = p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) |
-+ ((uint32_t)p[3] << 24);
-+ val <<= k;
-+ val >>= k;
-+ b = nrbits & 7;
-+ p += nrbits / 8;
-+ *addr = p;
-+ *pos = b;
-+ ubifs_assert((val >> nrbits) == 0 || nrbits - b == 32);
-+ return val;
-+}
-+
-+/**
-+ * ubifs_pack_pnode - pack all the bit fields of a pnode.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer into which to pack
-+ * @pnode: pnode to pack
-+ */
-+void ubifs_pack_pnode(struct ubifs_info *c, void *buf,
-+ struct ubifs_pnode *pnode)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0;
-+ uint16_t crc;
-+
-+ pack_bits(&addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS);
-+ if (c->big_lpt)
-+ pack_bits(&addr, &pos, pnode->num, c->pcnt_bits);
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ pack_bits(&addr, &pos, pnode->lprops[i].free >> 3,
-+ c->space_bits);
-+ pack_bits(&addr, &pos, pnode->lprops[i].dirty >> 3,
-+ c->space_bits);
-+ if (pnode->lprops[i].flags & LPROPS_INDEX)
-+ pack_bits(&addr, &pos, 1, 1);
-+ else
-+ pack_bits(&addr, &pos, 0, 1);
-+ }
-+ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ c->pnode_sz - UBIFS_LPT_CRC_BYTES);
-+ addr = buf;
-+ pos = 0;
-+ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-+}
-+
-+/**
-+ * ubifs_pack_nnode - pack all the bit fields of a nnode.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer into which to pack
-+ * @nnode: nnode to pack
-+ */
-+void ubifs_pack_nnode(struct ubifs_info *c, void *buf,
-+ struct ubifs_nnode *nnode)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0;
-+ uint16_t crc;
-+
-+ pack_bits(&addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS);
-+ if (c->big_lpt)
-+ pack_bits(&addr, &pos, nnode->num, c->pcnt_bits);
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ int lnum = nnode->nbranch[i].lnum;
-+
-+ if (lnum == 0)
-+ lnum = c->lpt_last + 1;
-+ pack_bits(&addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits);
-+ pack_bits(&addr, &pos, nnode->nbranch[i].offs,
-+ c->lpt_offs_bits);
-+ }
-+ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ c->nnode_sz - UBIFS_LPT_CRC_BYTES);
-+ addr = buf;
-+ pos = 0;
-+ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-+}
-+
-+/**
-+ * ubifs_pack_ltab - pack the LPT's own lprops table.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer into which to pack
-+ * @ltab: LPT's own lprops table to pack
-+ */
-+void ubifs_pack_ltab(struct ubifs_info *c, void *buf,
-+ struct ubifs_lpt_lprops *ltab)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0;
-+ uint16_t crc;
-+
-+ pack_bits(&addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS);
-+ for (i = 0; i < c->lpt_lebs; i++) {
-+ pack_bits(&addr, &pos, ltab[i].free, c->lpt_spc_bits);
-+ pack_bits(&addr, &pos, ltab[i].dirty, c->lpt_spc_bits);
-+ }
-+ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ c->ltab_sz - UBIFS_LPT_CRC_BYTES);
-+ addr = buf;
-+ pos = 0;
-+ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-+}
-+
-+/**
-+ * ubifs_pack_lsave - pack the LPT's save table.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer into which to pack
-+ * @lsave: LPT's save table to pack
-+ */
-+void ubifs_pack_lsave(struct ubifs_info *c, void *buf, int *lsave)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0;
-+ uint16_t crc;
-+
-+ pack_bits(&addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS);
-+ for (i = 0; i < c->lsave_cnt; i++)
-+ pack_bits(&addr, &pos, lsave[i], c->lnum_bits);
-+ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ c->lsave_sz - UBIFS_LPT_CRC_BYTES);
-+ addr = buf;
-+ pos = 0;
-+ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-+}
-+
-+/**
-+ * ubifs_add_lpt_dirt - add dirty space to LPT LEB properties.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number to which to add dirty space
-+ * @dirty: amount of dirty space to add
-+ */
-+void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty)
-+{
-+ if (!dirty || !lnum)
-+ return;
-+ dbg_lp("LEB %d add %d to %d",
-+ lnum, dirty, c->ltab[lnum - c->lpt_first].dirty);
-+ ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
-+ c->ltab[lnum - c->lpt_first].dirty += dirty;
-+}
-+
-+/**
-+ * set_ltab - set LPT LEB properties.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number
-+ * @free: amount of free space
-+ * @dirty: amount of dirty space
-+ */
-+static void set_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
-+{
-+ dbg_lp("LEB %d free %d dirty %d to %d %d",
-+ lnum, c->ltab[lnum - c->lpt_first].free,
-+ c->ltab[lnum - c->lpt_first].dirty, free, dirty);
-+ ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
-+ c->ltab[lnum - c->lpt_first].free = free;
-+ c->ltab[lnum - c->lpt_first].dirty = dirty;
-+}
-+
-+/**
-+ * ubifs_add_nnode_dirt - add dirty space to LPT LEB properties.
-+ * @c: UBIFS file-system description object
-+ * @nnode: nnode for which to add dirt
-+ */
-+void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode)
-+{
-+ struct ubifs_nnode *np = nnode->parent;
-+
-+ if (np)
-+ ubifs_add_lpt_dirt(c, np->nbranch[nnode->iip].lnum,
-+ c->nnode_sz);
-+ else {
-+ ubifs_add_lpt_dirt(c, c->lpt_lnum, c->nnode_sz);
-+ if (!(c->lpt_drty_flgs & LTAB_DIRTY)) {
-+ c->lpt_drty_flgs |= LTAB_DIRTY;
-+ ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz);
-+ }
-+ }
-+}
-+
-+/**
-+ * add_pnode_dirt - add dirty space to LPT LEB properties.
-+ * @c: UBIFS file-system description object
-+ * @pnode: pnode for which to add dirt
-+ */
-+static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode)
-+{
-+ ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum,
-+ c->pnode_sz);
-+}
-+
-+/**
-+ * calc_nnode_num - calculate nnode number.
-+ * @row: the row in the tree (root is zero)
-+ * @col: the column in the row (leftmost is zero)
-+ *
-+ * The nnode number is a number that uniquely identifies a nnode and can be used
-+ * easily to traverse the tree from the root to that nnode.
-+ *
-+ * This function calculates and returns the nnode number for the nnode at @row
-+ * and @col.
-+ */
-+static int calc_nnode_num(int row, int col)
-+{
-+ int num, bits;
-+
-+ num = 1;
-+ while (row--) {
-+ bits = (col & (UBIFS_LPT_FANOUT - 1));
-+ col >>= UBIFS_LPT_FANOUT_SHIFT;
-+ num <<= UBIFS_LPT_FANOUT_SHIFT;
-+ num |= bits;
-+ }
-+ return num;
-+}
-+
-+/**
-+ * calc_nnode_num_from_parent - calculate nnode number.
-+ * @c: UBIFS file-system description object
-+ * @parent: parent nnode
-+ * @iip: index in parent
-+ *
-+ * The nnode number is a number that uniquely identifies a nnode and can be used
-+ * easily to traverse the tree from the root to that nnode.
-+ *
-+ * This function calculates and returns the nnode number based on the parent's
-+ * nnode number and the index in parent.
-+ */
-+static int calc_nnode_num_from_parent(struct ubifs_info *c,
-+ struct ubifs_nnode *parent, int iip)
-+{
-+ int num, shft;
-+
-+ if (!parent)
-+ return 1;
-+ shft = (c->lpt_hght - parent->level) * UBIFS_LPT_FANOUT_SHIFT;
-+ num = parent->num ^ (1 << shft);
-+ num |= (UBIFS_LPT_FANOUT + iip) << shft;
-+ return num;
-+}
-+
-+/**
-+ * calc_pnode_num_from_parent - calculate pnode number.
-+ * @c: UBIFS file-system description object
-+ * @parent: parent nnode
-+ * @iip: index in parent
-+ *
-+ * The pnode number is a number that uniquely identifies a pnode and can be used
-+ * easily to traverse the tree from the root to that pnode.
-+ *
-+ * This function calculates and returns the pnode number based on the parent's
-+ * nnode number and the index in parent.
-+ */
-+static int calc_pnode_num_from_parent(struct ubifs_info *c,
-+ struct ubifs_nnode *parent, int iip)
-+{
-+ int i, n = c->lpt_hght - 1, pnum = parent->num, num = 0;
-+
-+ for (i = 0; i < n; i++) {
-+ num <<= UBIFS_LPT_FANOUT_SHIFT;
-+ num |= pnum & (UBIFS_LPT_FANOUT - 1);
-+ pnum >>= UBIFS_LPT_FANOUT_SHIFT;
-+ }
-+ num <<= UBIFS_LPT_FANOUT_SHIFT;
-+ num |= iip;
-+ return num;
-+}
-+
-+/**
-+ * ubifs_create_dflt_lpt - create default LPT.
-+ * @c: UBIFS file-system description object
-+ * @main_lebs: number of main area LEBs is passed and returned here
-+ * @lpt_first: LEB number of first LPT LEB
-+ * @lpt_lebs: number of LEBs for LPT is passed and returned here
-+ * @big_lpt: use big LPT model is passed and returned here
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
-+ int *lpt_lebs, int *big_lpt)
-+{
-+ int lnum, err = 0, node_sz, iopos, i, j, cnt, len, alen, row;
-+ int blnum, boffs, bsz, bcnt;
-+ struct ubifs_pnode *pnode = NULL;
-+ struct ubifs_nnode *nnode = NULL;
-+ void *buf = NULL, *p;
-+ struct ubifs_lpt_lprops *ltab = NULL;
-+ int *lsave = NULL;
-+
-+ err = calc_dflt_lpt_geom(c, main_lebs, big_lpt);
-+ if (err)
-+ return err;
-+ *lpt_lebs = c->lpt_lebs;
-+
-+ /* Needed by 'ubifs_pack_nnode()' and 'set_ltab()' */
-+ c->lpt_first = lpt_first;
-+ /* Needed by 'set_ltab()' */
-+ c->lpt_last = lpt_first + c->lpt_lebs - 1;
-+ /* Needed by 'ubifs_pack_lsave()' */
-+ c->main_first = c->leb_cnt - *main_lebs;
-+
-+ lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_KERNEL);
-+ pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL);
-+ nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ buf = kmalloc(c->leb_size, GFP_KERNEL);
-+ ltab = kmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs, GFP_KERNEL);
-+#else
-+ buf = vmalloc(c->leb_size);
-+ ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
-+#endif
-+ if (!pnode || !nnode || !buf || !ltab || !lsave) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ ubifs_assert(!c->ltab);
-+ c->ltab = ltab; /* Needed by set_ltab */
-+
-+ /* Initialize LPT's own lprops */
-+ for (i = 0; i < c->lpt_lebs; i++) {
-+ ltab[i].free = c->leb_size;
-+ ltab[i].dirty = 0;
-+ ltab[i].tgc = 0;
-+ ltab[i].cmt = 0;
-+ }
-+
-+ lnum = lpt_first;
-+ p = buf;
-+ /* Number of leaf nodes (pnodes) */
-+ cnt = c->pnode_cnt;
-+
-+ /*
-+ * The first pnode contains the LEB properties for the LEBs that contain
-+ * the root inode node and the root index node of the index tree.
-+ */
-+ node_sz = ALIGN(ubifs_idx_node_sz(c, 1), 8);
-+ iopos = ALIGN(node_sz, c->min_io_size);
-+ pnode->lprops[0].free = c->leb_size - iopos;
-+ pnode->lprops[0].dirty = iopos - node_sz;
-+ pnode->lprops[0].flags = LPROPS_INDEX;
-+
-+ node_sz = UBIFS_INO_NODE_SZ;
-+ iopos = ALIGN(node_sz, c->min_io_size);
-+ pnode->lprops[1].free = c->leb_size - iopos;
-+ pnode->lprops[1].dirty = iopos - node_sz;
-+
-+ for (i = 2; i < UBIFS_LPT_FANOUT; i++)
-+ pnode->lprops[i].free = c->leb_size;
-+
-+ /* Add first pnode */
-+ ubifs_pack_pnode(c, p, pnode);
-+ p += c->pnode_sz;
-+ len = c->pnode_sz;
-+ pnode->num += 1;
-+
-+ /* Reset pnode values for remaining pnodes */
-+ pnode->lprops[0].free = c->leb_size;
-+ pnode->lprops[0].dirty = 0;
-+ pnode->lprops[0].flags = 0;
-+
-+ pnode->lprops[1].free = c->leb_size;
-+ pnode->lprops[1].dirty = 0;
-+
-+ /*
-+ * To calculate the internal node branches, we keep information about
-+ * the level below.
-+ */
-+ blnum = lnum; /* LEB number of level below */
-+ boffs = 0; /* Offset of level below */
-+ bcnt = cnt; /* Number of nodes in level below */
-+ bsz = c->pnode_sz; /* Size of nodes in level below */
-+
-+ /* Add all remaining pnodes */
-+ for (i = 1; i < cnt; i++) {
-+ if (len + c->pnode_sz > c->leb_size) {
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen, alen - len);
-+ memset(p, 0xff, alen - len);
-+ err = ubi_leb_change(c->ubi, lnum++, buf, alen,
-+ UBI_SHORTTERM);
-+ if (err)
-+ goto out;
-+ p = buf;
-+ len = 0;
-+ }
-+ ubifs_pack_pnode(c, p, pnode);
-+ p += c->pnode_sz;
-+ len += c->pnode_sz;
-+ /*
-+ * pnodes are simply numbered left to right starting at zero,
-+ * which means the pnode number can be used easily to traverse
-+ * down the tree to the corresponding pnode.
-+ */
-+ pnode->num += 1;
-+ }
-+
-+ row = 0;
-+ for (i = UBIFS_LPT_FANOUT; cnt > i; i <<= UBIFS_LPT_FANOUT_SHIFT)
-+ row += 1;
-+ /* Add all nnodes, one level at a time */
-+ while (1) {
-+ /* Number of internal nodes (nnodes) at next level */
-+ cnt = DIV_ROUND_UP(cnt, UBIFS_LPT_FANOUT);
-+ for (i = 0; i < cnt; i++) {
-+ if (len + c->nnode_sz > c->leb_size) {
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen,
-+ alen - len);
-+ memset(p, 0xff, alen - len);
-+ err = ubi_leb_change(c->ubi, lnum++, buf, alen,
-+ UBI_SHORTTERM);
-+ if (err)
-+ goto out;
-+ p = buf;
-+ len = 0;
-+ }
-+ /* Only 1 nnode at this level, so it is the root */
-+ if (cnt == 1) {
-+ c->lpt_lnum = lnum;
-+ c->lpt_offs = len;
-+ }
-+ /* Set branches to the level below */
-+ for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
-+ if (bcnt) {
-+ if (boffs + bsz > c->leb_size) {
-+ blnum += 1;
-+ boffs = 0;
-+ }
-+ nnode->nbranch[j].lnum = blnum;
-+ nnode->nbranch[j].offs = boffs;
-+ boffs += bsz;
-+ bcnt--;
-+ } else {
-+ nnode->nbranch[j].lnum = 0;
-+ nnode->nbranch[j].offs = 0;
-+ }
-+ }
-+ nnode->num = calc_nnode_num(row, i);
-+ ubifs_pack_nnode(c, p, nnode);
-+ p += c->nnode_sz;
-+ len += c->nnode_sz;
-+ }
-+ /* Only 1 nnode at this level, so it is the root */
-+ if (cnt == 1)
-+ break;
-+ /* Update the information about the level below */
-+ bcnt = cnt;
-+ bsz = c->nnode_sz;
-+ row -= 1;
-+ }
-+
-+ if (*big_lpt) {
-+ /* Need to add LPT's save table */
-+ if (len + c->lsave_sz > c->leb_size) {
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen, alen - len);
-+ memset(p, 0xff, alen - len);
-+ err = ubi_leb_change(c->ubi, lnum++, buf, alen,
-+ UBI_SHORTTERM);
-+ if (err)
-+ goto out;
-+ p = buf;
-+ len = 0;
-+ }
-+
-+ c->lsave_lnum = lnum;
-+ c->lsave_offs = len;
-+
-+ for (i = 0; i < c->lsave_cnt && i < *main_lebs; i++)
-+ lsave[i] = c->main_first + i;
-+ for (; i < c->lsave_cnt; i++)
-+ lsave[i] = c->main_first;
-+
-+ ubifs_pack_lsave(c, p, lsave);
-+ p += c->lsave_sz;
-+ len += c->lsave_sz;
-+ }
-+
-+ /* Need to add LPT's own LEB properties table */
-+ if (len + c->ltab_sz > c->leb_size) {
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen, alen - len);
-+ memset(p, 0xff, alen - len);
-+ err = ubi_leb_change(c->ubi, lnum++, buf, alen, UBI_SHORTTERM);
-+ if (err)
-+ goto out;
-+ p = buf;
-+ len = 0;
-+ }
-+
-+ c->ltab_lnum = lnum;
-+ c->ltab_offs = len;
-+
-+ /* Update ltab before packing it */
-+ len += c->ltab_sz;
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen, alen - len);
-+
-+ ubifs_pack_ltab(c, p, ltab);
-+ p += c->ltab_sz;
-+
-+ /* Write remaining buffer */
-+ memset(p, 0xff, alen - len);
-+ err = ubi_leb_change(c->ubi, lnum, buf, alen, UBI_SHORTTERM);
-+ if (err)
-+ goto out;
-+
-+ c->nhead_lnum = lnum;
-+ c->nhead_offs = ALIGN(len, c->min_io_size);
-+
-+ dbg_lp("space_bits %d", c->space_bits);
-+ dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits);
-+ dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits);
-+ dbg_lp("lpt_spc_bits %d", c->lpt_spc_bits);
-+ dbg_lp("pcnt_bits %d", c->pcnt_bits);
-+ dbg_lp("lnum_bits %d", c->lnum_bits);
-+ dbg_lp("pnode_sz %d", c->pnode_sz);
-+ dbg_lp("nnode_sz %d", c->nnode_sz);
-+ dbg_lp("ltab_sz %d", c->ltab_sz);
-+ dbg_lp("lsave_sz %d", c->lsave_sz);
-+ dbg_lp("lsave_cnt %d", c->lsave_cnt);
-+ dbg_lp("lpt_hght %d", c->lpt_hght);
-+ dbg_lp("big_lpt %d", c->big_lpt);
-+ dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
-+ dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
-+ dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
-+ if (c->big_lpt)
-+ dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
-+out:
-+ c->ltab = NULL;
-+ kfree(lsave);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(ltab);
-+ kfree(buf);
-+#else
-+ vfree(ltab);
-+ vfree(buf);
-+#endif
-+ kfree(nnode);
-+ kfree(pnode);
-+ return err;
-+}
-+
-+/**
-+ * update_cats - add LEB properties of a pnode to LEB category lists and heaps.
-+ * @c: UBIFS file-system description object
-+ * @pnode: pnode
-+ *
-+ * When a pnode is loaded into memory, the LEB properties it contains are added,
-+ * by this function, to the LEB category lists and heaps.
-+ */
-+static void update_cats(struct ubifs_info *c, struct ubifs_pnode *pnode)
-+{
-+ int i;
-+
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ int cat = pnode->lprops[i].flags & LPROPS_CAT_MASK;
-+ int lnum = pnode->lprops[i].lnum;
-+
-+ if (!lnum)
-+ return;
-+ ubifs_add_to_cat(c, &pnode->lprops[i], cat);
-+ }
-+}
-+
-+/**
-+ * replace_cats - add LEB properties of a pnode to LEB category lists and heaps.
-+ * @c: UBIFS file-system description object
-+ * @old_pnode: pnode copied
-+ * @new_pnode: pnode copy
-+ *
-+ * During commit it is sometimes necessary to copy a pnode
-+ * (see dirty_cow_pnode). When that happens, references in
-+ * category lists and heaps must be replaced. This function does that.
-+ */
-+static void replace_cats(struct ubifs_info *c, struct ubifs_pnode *old_pnode,
-+ struct ubifs_pnode *new_pnode)
-+{
-+ int i;
-+
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ if (!new_pnode->lprops[i].lnum)
-+ return;
-+ ubifs_replace_cat(c, &old_pnode->lprops[i],
-+ &new_pnode->lprops[i]);
-+ }
-+}
-+
-+/**
-+ * check_lpt_crc - check LPT node crc is correct.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer containing node
-+ * @len: length of node
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int check_lpt_crc(void *buf, int len)
-+{
-+ int pos = 0;
-+ uint8_t *addr = buf;
-+ uint16_t crc, calc_crc;
-+
-+ crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS);
-+ calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ len - UBIFS_LPT_CRC_BYTES);
-+ if (crc != calc_crc) {
-+ ubifs_err("invalid crc in LPT node: crc %hx calc %hx", crc,
-+ calc_crc);
-+ dbg_dump_stack();
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * check_lpt_type - check LPT node type is correct.
-+ * @c: UBIFS file-system description object
-+ * @addr: address of type bit field is passed and returned updated here
-+ * @pos: position of type bit field is passed and returned updated here
-+ * @type: expected type
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int check_lpt_type(uint8_t **addr, int *pos, int type)
-+{
-+ int node_type;
-+
-+ node_type = ubifs_unpack_bits(addr, pos, UBIFS_LPT_TYPE_BITS);
-+ if (node_type != type) {
-+ ubifs_err("invalid type (%d) in LPT node type %d", node_type,
-+ type);
-+ dbg_dump_stack();
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * unpack_pnode - unpack a pnode.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer containing packed pnode to unpack
-+ * @pnode: pnode structure to fill
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int unpack_pnode(struct ubifs_info *c, void *buf,
-+ struct ubifs_pnode *pnode)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0, err;
-+
-+ err = check_lpt_type(&addr, &pos, UBIFS_LPT_PNODE);
-+ if (err)
-+ return err;
-+ if (c->big_lpt)
-+ pnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ struct ubifs_lprops * const lprops = &pnode->lprops[i];
-+
-+ lprops->free = ubifs_unpack_bits(&addr, &pos, c->space_bits);
-+ lprops->free <<= 3;
-+ lprops->dirty = ubifs_unpack_bits(&addr, &pos, c->space_bits);
-+ lprops->dirty <<= 3;
-+
-+ if (ubifs_unpack_bits(&addr, &pos, 1))
-+ lprops->flags = LPROPS_INDEX;
-+ else
-+ lprops->flags = 0;
-+ lprops->flags |= ubifs_categorize_lprops(c, lprops);
-+ }
-+ err = check_lpt_crc(buf, c->pnode_sz);
-+ return err;
-+}
-+
-+/**
-+ * unpack_nnode - unpack a nnode.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer containing packed nnode to unpack
-+ * @nnode: nnode structure to fill
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int unpack_nnode(struct ubifs_info *c, void *buf,
-+ struct ubifs_nnode *nnode)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0, err;
-+
-+ err = check_lpt_type(&addr, &pos, UBIFS_LPT_NNODE);
-+ if (err)
-+ return err;
-+ if (c->big_lpt)
-+ nnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ int lnum;
-+
-+ lnum = ubifs_unpack_bits(&addr, &pos, c->lpt_lnum_bits) +
-+ c->lpt_first;
-+ if (lnum == c->lpt_last + 1)
-+ lnum = 0;
-+ nnode->nbranch[i].lnum = lnum;
-+ nnode->nbranch[i].offs = ubifs_unpack_bits(&addr, &pos,
-+ c->lpt_offs_bits);
-+ }
-+ err = check_lpt_crc(buf, c->nnode_sz);
-+ return err;
-+}
-+
-+/**
-+ * unpack_ltab - unpack the LPT's own lprops table.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer from which to unpack
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int unpack_ltab(struct ubifs_info *c, void *buf)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0, err;
-+
-+ err = check_lpt_type(&addr, &pos, UBIFS_LPT_LTAB);
-+ if (err)
-+ return err;
-+ for (i = 0; i < c->lpt_lebs; i++) {
-+ int free = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits);
-+ int dirty = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits);
-+
-+ if (free < 0 || free > c->leb_size || dirty < 0 ||
-+ dirty > c->leb_size || free + dirty > c->leb_size)
-+ return -EINVAL;
-+
-+ c->ltab[i].free = free;
-+ c->ltab[i].dirty = dirty;
-+ c->ltab[i].tgc = 0;
-+ c->ltab[i].cmt = 0;
-+ }
-+ err = check_lpt_crc(buf, c->ltab_sz);
-+ return err;
-+}
-+
-+/**
-+ * unpack_lsave - unpack the LPT's save table.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer from which to unpack
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int unpack_lsave(struct ubifs_info *c, void *buf)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0, err;
-+
-+ err = check_lpt_type(&addr, &pos, UBIFS_LPT_LSAVE);
-+ if (err)
-+ return err;
-+ for (i = 0; i < c->lsave_cnt; i++) {
-+ int lnum = ubifs_unpack_bits(&addr, &pos, c->lnum_bits);
-+
-+ if (lnum < c->main_first || lnum >= c->leb_cnt)
-+ return -EINVAL;
-+ c->lsave[i] = lnum;
-+ }
-+ err = check_lpt_crc(buf, c->lsave_sz);
-+ return err;
-+}
-+
-+/**
-+ * validate_nnode - validate a nnode.
-+ * @c: UBIFS file-system description object
-+ * @nnode: nnode to validate
-+ * @parent: parent nnode (or NULL for the root nnode)
-+ * @iip: index in parent
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int validate_nnode(struct ubifs_info *c, struct ubifs_nnode *nnode,
-+ struct ubifs_nnode *parent, int iip)
-+{
-+ int i, lvl, max_offs;
-+
-+ if (c->big_lpt) {
-+ int num = calc_nnode_num_from_parent(c, parent, iip);
-+
-+ if (nnode->num != num)
-+ return -EINVAL;
-+ }
-+ lvl = parent ? parent->level - 1 : c->lpt_hght;
-+ if (lvl < 1)
-+ return -EINVAL;
-+ if (lvl == 1)
-+ max_offs = c->leb_size - c->pnode_sz;
-+ else
-+ max_offs = c->leb_size - c->nnode_sz;
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ int lnum = nnode->nbranch[i].lnum;
-+ int offs = nnode->nbranch[i].offs;
-+
-+ if (lnum == 0) {
-+ if (offs != 0)
-+ return -EINVAL;
-+ continue;
-+ }
-+ if (lnum < c->lpt_first || lnum > c->lpt_last)
-+ return -EINVAL;
-+ if (offs < 0 || offs > max_offs)
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * validate_pnode - validate a pnode.
-+ * @c: UBIFS file-system description object
-+ * @pnode: pnode to validate
-+ * @parent: parent nnode
-+ * @iip: index in parent
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int validate_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
-+ struct ubifs_nnode *parent, int iip)
-+{
-+ int i;
-+
-+ if (c->big_lpt) {
-+ int num = calc_pnode_num_from_parent(c, parent, iip);
-+
-+ if (pnode->num != num)
-+ return -EINVAL;
-+ }
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ int free = pnode->lprops[i].free;
-+ int dirty = pnode->lprops[i].dirty;
-+
-+ if (free < 0 || free > c->leb_size || free % c->min_io_size ||
-+ (free & 7))
-+ return -EINVAL;
-+ if (dirty < 0 || dirty > c->leb_size || (dirty & 7))
-+ return -EINVAL;
-+ if (dirty + free > c->leb_size)
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * set_pnode_lnum - set LEB numbers on a pnode.
-+ * @c: UBIFS file-system description object
-+ * @pnode: pnode to update
-+ *
-+ * This function calculates the LEB numbers for the LEB properties it contains
-+ * based on the pnode number.
-+ */
-+static void set_pnode_lnum(struct ubifs_info *c, struct ubifs_pnode *pnode)
-+{
-+ int i, lnum;
-+
-+ lnum = (pnode->num << UBIFS_LPT_FANOUT_SHIFT) + c->main_first;
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ if (lnum >= c->leb_cnt)
-+ return;
-+ pnode->lprops[i].lnum = lnum++;
-+ }
-+}
-+
-+/**
-+ * ubifs_read_nnode - read a nnode from flash and link it to the tree in memory.
-+ * @c: UBIFS file-system description object
-+ * @parent: parent nnode (or NULL for the root)
-+ * @iip: index in parent
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
-+{
-+ struct ubifs_nbranch *branch = NULL;
-+ struct ubifs_nnode *nnode = NULL;
-+ void *buf = c->lpt_nod_buf;
-+ int err, lnum, offs;
-+
-+ if (parent) {
-+ branch = &parent->nbranch[iip];
-+ lnum = branch->lnum;
-+ offs = branch->offs;
-+ } else {
-+ lnum = c->lpt_lnum;
-+ offs = c->lpt_offs;
-+ }
-+ nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_NOFS);
-+ if (!nnode) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+ if (lnum == 0) {
-+ /*
-+ * This nnode was not written which just means that the LEB
-+ * properties in the subtree below it describe empty LEBs. We
-+ * make the nnode as though we had read it, which in fact means
-+ * doing almost nothing.
-+ */
-+ if (c->big_lpt)
-+ nnode->num = calc_nnode_num_from_parent(c, parent, iip);
-+ } else {
-+ err = ubi_read(c->ubi, lnum, buf, offs, c->nnode_sz);
-+ if (err)
-+ goto out;
-+ err = unpack_nnode(c, buf, nnode);
-+ if (err)
-+ goto out;
-+ }
-+ err = validate_nnode(c, nnode, parent, iip);
-+ if (err)
-+ goto out;
-+ if (!c->big_lpt)
-+ nnode->num = calc_nnode_num_from_parent(c, parent, iip);
-+ if (parent) {
-+ branch->nnode = nnode;
-+ nnode->level = parent->level - 1;
-+ } else {
-+ c->nroot = nnode;
-+ nnode->level = c->lpt_hght;
-+ }
-+ nnode->parent = parent;
-+ nnode->iip = iip;
-+ return 0;
-+
-+out:
-+ ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs);
-+ kfree(nnode);
-+ return err;
-+}
-+
-+/**
-+ * read_pnode - read a pnode from flash and link it to the tree in memory.
-+ * @c: UBIFS file-system description object
-+ * @parent: parent nnode
-+ * @iip: index in parent
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
-+{
-+ struct ubifs_nbranch *branch;
-+ struct ubifs_pnode *pnode = NULL;
-+ void *buf = c->lpt_nod_buf;
-+ int err, lnum, offs;
-+
-+ branch = &parent->nbranch[iip];
-+ lnum = branch->lnum;
-+ offs = branch->offs;
-+ pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
-+ if (!pnode) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+ if (lnum == 0) {
-+ /*
-+ * This pnode was not written which just means that the LEB
-+ * properties in it describe empty LEBs. We make the pnode as
-+ * though we had read it.
-+ */
-+ int i;
-+
-+ if (c->big_lpt)
-+ pnode->num = calc_pnode_num_from_parent(c, parent, iip);
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ struct ubifs_lprops * const lprops = &pnode->lprops[i];
-+
-+ lprops->free = c->leb_size;
-+ lprops->flags = ubifs_categorize_lprops(c, lprops);
-+ }
-+ } else {
-+ err = ubi_read(c->ubi, lnum, buf, offs, c->pnode_sz);
-+ if (err)
-+ goto out;
-+ err = unpack_pnode(c, buf, pnode);
-+ if (err)
-+ goto out;
-+ }
-+ err = validate_pnode(c, pnode, parent, iip);
-+ if (err)
-+ goto out;
-+ if (!c->big_lpt)
-+ pnode->num = calc_pnode_num_from_parent(c, parent, iip);
-+ branch->pnode = pnode;
-+ pnode->parent = parent;
-+ pnode->iip = iip;
-+ set_pnode_lnum(c, pnode);
-+ c->pnodes_have += 1;
-+ return 0;
-+
-+out:
-+ ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs);
-+ dbg_dump_pnode(c, pnode, parent, iip);
-+ dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
-+ kfree(pnode);
-+ return err;
-+}
-+
-+/**
-+ * read_ltab - read LPT's own lprops table.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int read_ltab(struct ubifs_info *c)
-+{
-+ int err;
-+ void *buf;
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ buf = kmalloc(c->ltab_sz, GFP_KERNEL);
-+#else
-+ buf = vmalloc(c->ltab_sz);
-+#endif
-+ if (!buf)
-+ return -ENOMEM;
-+ err = ubi_read(c->ubi, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz);
-+ if (err)
-+ goto out;
-+ err = unpack_ltab(c, buf);
-+out:
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(buf);
-+#else
-+ vfree(buf);
-+#endif
-+ return err;
-+}
-+
-+/**
-+ * read_lsave - read LPT's save table.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int read_lsave(struct ubifs_info *c)
-+{
-+ int err, i;
-+ void *buf;
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ buf = kmalloc(c->lsave_sz, GFP_KERNEL);
-+#else
-+ buf = vmalloc(c->lsave_sz);
-+#endif
-+ if (!buf)
-+ return -ENOMEM;
-+ err = ubi_read(c->ubi, c->lsave_lnum, buf, c->lsave_offs, c->lsave_sz);
-+ if (err)
-+ goto out;
-+ err = unpack_lsave(c, buf);
-+ if (err)
-+ goto out;
-+ for (i = 0; i < c->lsave_cnt; i++) {
-+ int lnum = c->lsave[i];
-+
-+ /*
-+ * Due to automatic resizing, the values in the lsave table
-+ * could be beyond the volume size - just ignore them.
-+ */
-+ if (lnum >= c->leb_cnt)
-+ continue;
-+ ubifs_lpt_lookup(c, lnum);
-+ }
-+out:
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(buf);
-+#else
-+ vfree(buf);
-+#endif
-+ return err;
-+}
-+
-+/**
-+ * ubifs_get_nnode - get a nnode.
-+ * @c: UBIFS file-system description object
-+ * @parent: parent nnode (or NULL for the root)
-+ * @iip: index in parent
-+ *
-+ * This function returns a pointer to the nnode on success or a negative error
-+ * code on failure.
-+ */
-+struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c,
-+ struct ubifs_nnode *parent, int iip)
-+{
-+ struct ubifs_nbranch *branch;
-+ struct ubifs_nnode *nnode;
-+ int err;
-+
-+ branch = &parent->nbranch[iip];
-+ nnode = branch->nnode;
-+ if (nnode)
-+ return nnode;
-+ err = ubifs_read_nnode(c, parent, iip);
-+ if (err)
-+ return ERR_PTR(err);
-+ return branch->nnode;
-+}
-+
-+/**
-+ * ubifs_get_pnode - get a pnode.
-+ * @c: UBIFS file-system description object
-+ * @parent: parent nnode
-+ * @iip: index in parent
-+ *
-+ * This function returns a pointer to the pnode on success or a negative error
-+ * code on failure.
-+ */
-+struct ubifs_pnode *ubifs_get_pnode(struct ubifs_info *c,
-+ struct ubifs_nnode *parent, int iip)
-+{
-+ struct ubifs_nbranch *branch;
-+ struct ubifs_pnode *pnode;
-+ int err;
-+
-+ branch = &parent->nbranch[iip];
-+ pnode = branch->pnode;
-+ if (pnode)
-+ return pnode;
-+ err = read_pnode(c, parent, iip);
-+ if (err)
-+ return ERR_PTR(err);
-+ update_cats(c, branch->pnode);
-+ return branch->pnode;
-+}
-+
-+/**
-+ * ubifs_lpt_lookup - lookup LEB properties in the LPT.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number to lookup
-+ *
-+ * This function returns a pointer to the LEB properties on success or a
-+ * negative error code on failure.
-+ */
-+struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum)
-+{
-+ int err, i, h, iip, shft;
-+ struct ubifs_nnode *nnode;
-+ struct ubifs_pnode *pnode;
-+
-+ if (!c->nroot) {
-+ err = ubifs_read_nnode(c, NULL, 0);
-+ if (err)
-+ return ERR_PTR(err);
-+ }
-+ nnode = c->nroot;
-+ i = lnum - c->main_first;
-+ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
-+ for (h = 1; h < c->lpt_hght; h++) {
-+ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-+ shft -= UBIFS_LPT_FANOUT_SHIFT;
-+ nnode = ubifs_get_nnode(c, nnode, iip);
-+ if (IS_ERR(nnode))
-+ return ERR_PTR(PTR_ERR(nnode));
-+ }
-+ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-+ shft -= UBIFS_LPT_FANOUT_SHIFT;
-+ pnode = ubifs_get_pnode(c, nnode, iip);
-+ if (IS_ERR(pnode))
-+ return ERR_PTR(PTR_ERR(pnode));
-+ iip = (i & (UBIFS_LPT_FANOUT - 1));
-+ dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum,
-+ pnode->lprops[iip].free, pnode->lprops[iip].dirty,
-+ pnode->lprops[iip].flags);
-+ return &pnode->lprops[iip];
-+}
-+
-+/**
-+ * dirty_cow_nnode - ensure a nnode is not being committed.
-+ * @c: UBIFS file-system description object
-+ * @nnode: nnode to check
-+ *
-+ * Returns dirtied nnode on success or negative error code on failure.
-+ */
-+static struct ubifs_nnode *dirty_cow_nnode(struct ubifs_info *c,
-+ struct ubifs_nnode *nnode)
-+{
-+ struct ubifs_nnode *n;
-+ int i;
-+
-+ if (!test_bit(COW_CNODE, &nnode->flags)) {
-+ /* nnode is not being committed */
-+ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
-+ c->dirty_nn_cnt += 1;
-+ ubifs_add_nnode_dirt(c, nnode);
-+ }
-+ return nnode;
-+ }
-+
-+ /* nnode is being committed, so copy it */
-+ n = kmalloc(sizeof(struct ubifs_nnode), GFP_NOFS);
-+ if (unlikely(!n))
-+ return ERR_PTR(-ENOMEM);
-+
-+ memcpy(n, nnode, sizeof(struct ubifs_nnode));
-+ n->cnext = NULL;
-+ __set_bit(DIRTY_CNODE, &n->flags);
-+ __clear_bit(COW_CNODE, &n->flags);
-+
-+ /* The children now have new parent */
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ struct ubifs_nbranch *branch = &n->nbranch[i];
-+
-+ if (branch->cnode)
-+ branch->cnode->parent = n;
-+ }
-+
-+ ubifs_assert(!test_bit(OBSOLETE_CNODE, &nnode->flags));
-+ __set_bit(OBSOLETE_CNODE, &nnode->flags);
-+
-+ c->dirty_nn_cnt += 1;
-+ ubifs_add_nnode_dirt(c, nnode);
-+ if (nnode->parent)
-+ nnode->parent->nbranch[n->iip].nnode = n;
-+ else
-+ c->nroot = n;
-+ return n;
-+}
-+
-+/**
-+ * dirty_cow_pnode - ensure a pnode is not being committed.
-+ * @c: UBIFS file-system description object
-+ * @pnode: pnode to check
-+ *
-+ * Returns dirtied pnode on success or negative error code on failure.
-+ */
-+static struct ubifs_pnode *dirty_cow_pnode(struct ubifs_info *c,
-+ struct ubifs_pnode *pnode)
-+{
-+ struct ubifs_pnode *p;
-+
-+ if (!test_bit(COW_CNODE, &pnode->flags)) {
-+ /* pnode is not being committed */
-+ if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) {
-+ c->dirty_pn_cnt += 1;
-+ add_pnode_dirt(c, pnode);
-+ }
-+ return pnode;
-+ }
-+
-+ /* pnode is being committed, so copy it */
-+ p = kmalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
-+ if (unlikely(!p))
-+ return ERR_PTR(-ENOMEM);
-+
-+ memcpy(p, pnode, sizeof(struct ubifs_pnode));
-+ p->cnext = NULL;
-+ __set_bit(DIRTY_CNODE, &p->flags);
-+ __clear_bit(COW_CNODE, &p->flags);
-+ replace_cats(c, pnode, p);
-+
-+ ubifs_assert(!test_bit(OBSOLETE_CNODE, &pnode->flags));
-+ __set_bit(OBSOLETE_CNODE, &pnode->flags);
-+
-+ c->dirty_pn_cnt += 1;
-+ add_pnode_dirt(c, pnode);
-+ pnode->parent->nbranch[p->iip].pnode = p;
-+ return p;
-+}
-+
-+/**
-+ * ubifs_lpt_lookup_dirty - lookup LEB properties in the LPT.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number to lookup
-+ *
-+ * This function returns a pointer to the LEB properties on success or a
-+ * negative error code on failure.
-+ */
-+struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum)
-+{
-+ int err, i, h, iip, shft;
-+ struct ubifs_nnode *nnode;
-+ struct ubifs_pnode *pnode;
-+
-+ if (!c->nroot) {
-+ err = ubifs_read_nnode(c, NULL, 0);
-+ if (err)
-+ return ERR_PTR(err);
-+ }
-+ nnode = c->nroot;
-+ nnode = dirty_cow_nnode(c, nnode);
-+ if (IS_ERR(nnode))
-+ return ERR_PTR(PTR_ERR(nnode));
-+ i = lnum - c->main_first;
-+ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
-+ for (h = 1; h < c->lpt_hght; h++) {
-+ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-+ shft -= UBIFS_LPT_FANOUT_SHIFT;
-+ nnode = ubifs_get_nnode(c, nnode, iip);
-+ if (IS_ERR(nnode))
-+ return ERR_PTR(PTR_ERR(nnode));
-+ nnode = dirty_cow_nnode(c, nnode);
-+ if (IS_ERR(nnode))
-+ return ERR_PTR(PTR_ERR(nnode));
-+ }
-+ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-+ shft -= UBIFS_LPT_FANOUT_SHIFT;
-+ pnode = ubifs_get_pnode(c, nnode, iip);
-+ if (IS_ERR(pnode))
-+ return ERR_PTR(PTR_ERR(pnode));
-+ pnode = dirty_cow_pnode(c, pnode);
-+ if (IS_ERR(pnode))
-+ return ERR_PTR(PTR_ERR(pnode));
-+ iip = (i & (UBIFS_LPT_FANOUT - 1));
-+ dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum,
-+ pnode->lprops[iip].free, pnode->lprops[iip].dirty,
-+ pnode->lprops[iip].flags);
-+ ubifs_assert(test_bit(DIRTY_CNODE, &pnode->flags));
-+ return &pnode->lprops[iip];
-+}
-+
-+/**
-+ * lpt_init_rd - initialize the LPT for reading.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int lpt_init_rd(struct ubifs_info *c)
-+{
-+ int err, i;
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->ltab = kmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs, GFP_KERNEL);
-+#else
-+ c->ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
-+#endif
-+ if (!c->ltab)
-+ return -ENOMEM;
-+
-+ i = max_t(int, c->nnode_sz, c->pnode_sz);
-+ c->lpt_nod_buf = kmalloc(i, GFP_KERNEL);
-+ if (!c->lpt_nod_buf)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < LPROPS_HEAP_CNT; i++) {
-+ c->lpt_heap[i].arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ,
-+ GFP_KERNEL);
-+ if (!c->lpt_heap[i].arr)
-+ return -ENOMEM;
-+ c->lpt_heap[i].cnt = 0;
-+ c->lpt_heap[i].max_cnt = LPT_HEAP_SZ;
-+ }
-+
-+ c->dirty_idx.arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ, GFP_KERNEL);
-+ if (!c->dirty_idx.arr)
-+ return -ENOMEM;
-+ c->dirty_idx.cnt = 0;
-+ c->dirty_idx.max_cnt = LPT_HEAP_SZ;
-+
-+ err = read_ltab(c);
-+ if (err)
-+ return err;
-+
-+ dbg_lp("space_bits %d", c->space_bits);
-+ dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits);
-+ dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits);
-+ dbg_lp("lpt_spc_bits %d", c->lpt_spc_bits);
-+ dbg_lp("pcnt_bits %d", c->pcnt_bits);
-+ dbg_lp("lnum_bits %d", c->lnum_bits);
-+ dbg_lp("pnode_sz %d", c->pnode_sz);
-+ dbg_lp("nnode_sz %d", c->nnode_sz);
-+ dbg_lp("ltab_sz %d", c->ltab_sz);
-+ dbg_lp("lsave_sz %d", c->lsave_sz);
-+ dbg_lp("lsave_cnt %d", c->lsave_cnt);
-+ dbg_lp("lpt_hght %d", c->lpt_hght);
-+ dbg_lp("big_lpt %d", c->big_lpt);
-+ dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
-+ dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
-+ dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
-+ if (c->big_lpt)
-+ dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
-+
-+ return 0;
-+}
-+
-+/**
-+ * lpt_init_wr - initialize the LPT for writing.
-+ * @c: UBIFS file-system description object
-+ *
-+ * 'lpt_init_rd()' must have been called already.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int lpt_init_wr(struct ubifs_info *c)
-+{
-+ int err, i;
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->ltab_cmt = kmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs, GFP_KERNEL);
-+ if (!c->ltab_cmt)
-+ return -ENOMEM;
-+ c->lpt_buf = kmalloc(c->leb_size, GFP_KERNEL);
-+ if (!c->lpt_buf)
-+ return -ENOMEM;
-+#else
-+ c->ltab_cmt = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
-+ if (!c->ltab_cmt)
-+ return -ENOMEM;
-+ c->lpt_buf = vmalloc(c->leb_size);
-+ if (!c->lpt_buf)
-+ return -ENOMEM;
-+#endif
-+
-+ if (c->big_lpt) {
-+ c->lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_NOFS);
-+ if (!c->lsave)
-+ return -ENOMEM;
-+ err = read_lsave(c);
-+ if (err)
-+ return err;
-+ }
-+
-+ for (i = 0; i < c->lpt_lebs; i++)
-+ if (c->ltab[i].free == c->leb_size) {
-+ err = ubifs_leb_unmap(c, i + c->lpt_first);
-+ if (err)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_lpt_init - initialize the LPT.
-+ * @c: UBIFS file-system description object
-+ * @rd: whether to initialize lpt for reading
-+ * @wr: whether to initialize lpt for writing
-+ *
-+ * For mounting 'rw', @rd and @wr are both true. For mounting 'ro', @rd is true
-+ * and @wr is false. For mounting from 'ro' to 'rw', @rd is false and @wr is
-+ * true.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr)
-+{
-+ int err;
-+
-+ if (rd) {
-+ err = lpt_init_rd(c);
-+ if (err)
-+ return err;
-+ }
-+
-+ if (wr) {
-+ err = lpt_init_wr(c);
-+ if (err)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * struct lpt_scan_node - somewhere to put nodes while we scan LPT.
-+ * @nnode: where to keep a nnode
-+ * @pnode: where to keep a pnode
-+ * @cnode: where to keep a cnode
-+ * @in_tree: is the node in the tree in memory
-+ * @ptr.nnode: pointer to the nnode (if it is an nnode) which may be here or in
-+ * the tree
-+ * @ptr.pnode: ditto for pnode
-+ * @ptr.cnode: ditto for cnode
-+ */
-+struct lpt_scan_node {
-+ union {
-+ struct ubifs_nnode nnode;
-+ struct ubifs_pnode pnode;
-+ struct ubifs_cnode cnode;
-+ };
-+ int in_tree;
-+ union {
-+ struct ubifs_nnode *nnode;
-+ struct ubifs_pnode *pnode;
-+ struct ubifs_cnode *cnode;
-+ } ptr;
-+};
-+
-+/**
-+ * scan_get_nnode - for the scan, get a nnode from either the tree or flash.
-+ * @c: the UBIFS file-system description object
-+ * @path: where to put the nnode
-+ * @parent: parent of the nnode
-+ * @iip: index in parent of the nnode
-+ *
-+ * This function returns a pointer to the nnode on success or a negative error
-+ * code on failure.
-+ */
-+static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c,
-+ struct lpt_scan_node *path,
-+ struct ubifs_nnode *parent, int iip)
-+{
-+ struct ubifs_nbranch *branch;
-+ struct ubifs_nnode *nnode;
-+ void *buf = c->lpt_nod_buf;
-+ int err;
-+
-+ branch = &parent->nbranch[iip];
-+ nnode = branch->nnode;
-+ if (nnode) {
-+ path->in_tree = 1;
-+ path->ptr.nnode = nnode;
-+ return nnode;
-+ }
-+ nnode = &path->nnode;
-+ path->in_tree = 0;
-+ path->ptr.nnode = nnode;
-+ memset(nnode, 0, sizeof(struct ubifs_nnode));
-+ if (branch->lnum == 0) {
-+ /*
-+ * This nnode was not written which just means that the LEB
-+ * properties in the subtree below it describe empty LEBs. We
-+ * make the nnode as though we had read it, which in fact means
-+ * doing almost nothing.
-+ */
-+ if (c->big_lpt)
-+ nnode->num = calc_nnode_num_from_parent(c, parent, iip);
-+ } else {
-+ err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
-+ c->nnode_sz);
-+ if (err)
-+ return ERR_PTR(err);
-+ err = unpack_nnode(c, buf, nnode);
-+ if (err)
-+ return ERR_PTR(err);
-+ }
-+ err = validate_nnode(c, nnode, parent, iip);
-+ if (err)
-+ return ERR_PTR(err);
-+ if (!c->big_lpt)
-+ nnode->num = calc_nnode_num_from_parent(c, parent, iip);
-+ nnode->level = parent->level - 1;
-+ nnode->parent = parent;
-+ nnode->iip = iip;
-+ return nnode;
-+}
-+
-+/**
-+ * scan_get_pnode - for the scan, get a pnode from either the tree or flash.
-+ * @c: the UBIFS file-system description object
-+ * @path: where to put the pnode
-+ * @parent: parent of the pnode
-+ * @iip: index in parent of the pnode
-+ *
-+ * This function returns a pointer to the pnode on success or a negative error
-+ * code on failure.
-+ */
-+static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c,
-+ struct lpt_scan_node *path,
-+ struct ubifs_nnode *parent, int iip)
-+{
-+ struct ubifs_nbranch *branch;
-+ struct ubifs_pnode *pnode;
-+ void *buf = c->lpt_nod_buf;
-+ int err;
-+
-+ branch = &parent->nbranch[iip];
-+ pnode = branch->pnode;
-+ if (pnode) {
-+ path->in_tree = 1;
-+ path->ptr.pnode = pnode;
-+ return pnode;
-+ }
-+ pnode = &path->pnode;
-+ path->in_tree = 0;
-+ path->ptr.pnode = pnode;
-+ memset(pnode, 0, sizeof(struct ubifs_pnode));
-+ if (branch->lnum == 0) {
-+ /*
-+ * This pnode was not written which just means that the LEB
-+ * properties in it describe empty LEBs. We make the pnode as
-+ * though we had read it.
-+ */
-+ int i;
-+
-+ if (c->big_lpt)
-+ pnode->num = calc_pnode_num_from_parent(c, parent, iip);
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ struct ubifs_lprops * const lprops = &pnode->lprops[i];
-+
-+ lprops->free = c->leb_size;
-+ lprops->flags = ubifs_categorize_lprops(c, lprops);
-+ }
-+ } else {
-+ ubifs_assert(branch->lnum >= c->lpt_first &&
-+ branch->lnum <= c->lpt_last);
-+ ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size);
-+ err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
-+ c->pnode_sz);
-+ if (err)
-+ return ERR_PTR(err);
-+ err = unpack_pnode(c, buf, pnode);
-+ if (err)
-+ return ERR_PTR(err);
-+ }
-+ err = validate_pnode(c, pnode, parent, iip);
-+ if (err)
-+ return ERR_PTR(err);
-+ if (!c->big_lpt)
-+ pnode->num = calc_pnode_num_from_parent(c, parent, iip);
-+ pnode->parent = parent;
-+ pnode->iip = iip;
-+ set_pnode_lnum(c, pnode);
-+ return pnode;
-+}
-+
-+/**
-+ * ubifs_lpt_scan_nolock - scan the LPT.
-+ * @c: the UBIFS file-system description object
-+ * @start_lnum: LEB number from which to start scanning
-+ * @end_lnum: LEB number at which to stop scanning
-+ * @scan_cb: callback function called for each lprops
-+ * @data: data to be passed to the callback function
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
-+ ubifs_lpt_scan_callback scan_cb, void *data)
-+{
-+ int err = 0, i, h, iip, shft;
-+ struct ubifs_nnode *nnode;
-+ struct ubifs_pnode *pnode;
-+ struct lpt_scan_node *path;
-+
-+ if (start_lnum == -1) {
-+ start_lnum = end_lnum + 1;
-+ if (start_lnum >= c->leb_cnt)
-+ start_lnum = c->main_first;
-+ }
-+
-+ ubifs_assert(start_lnum >= c->main_first && start_lnum < c->leb_cnt);
-+ ubifs_assert(end_lnum >= c->main_first && end_lnum < c->leb_cnt);
-+
-+ if (!c->nroot) {
-+ err = ubifs_read_nnode(c, NULL, 0);
-+ if (err)
-+ return err;
-+ }
-+
-+ path = kmalloc(sizeof(struct lpt_scan_node) * (c->lpt_hght + 1),
-+ GFP_NOFS);
-+ if (!path)
-+ return -ENOMEM;
-+
-+ path[0].ptr.nnode = c->nroot;
-+ path[0].in_tree = 1;
-+again:
-+ /* Descend to the pnode containing start_lnum */
-+ nnode = c->nroot;
-+ i = start_lnum - c->main_first;
-+ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
-+ for (h = 1; h < c->lpt_hght; h++) {
-+ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-+ shft -= UBIFS_LPT_FANOUT_SHIFT;
-+ nnode = scan_get_nnode(c, path + h, nnode, iip);
-+ if (IS_ERR(nnode)) {
-+ err = PTR_ERR(nnode);
-+ goto out;
-+ }
-+ }
-+ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-+ shft -= UBIFS_LPT_FANOUT_SHIFT;
-+ pnode = scan_get_pnode(c, path + h, nnode, iip);
-+ if (IS_ERR(pnode)) {
-+ err = PTR_ERR(pnode);
-+ goto out;
-+ }
-+ iip = (i & (UBIFS_LPT_FANOUT - 1));
-+
-+ /* Loop for each lprops */
-+ while (1) {
-+ struct ubifs_lprops *lprops = &pnode->lprops[iip];
-+ int ret, lnum = lprops->lnum;
-+
-+ ret = scan_cb(c, lprops, path[h].in_tree, data);
-+ if (ret < 0) {
-+ err = ret;
-+ goto out;
-+ }
-+ if (ret & LPT_SCAN_ADD) {
-+ /* Add all the nodes in path to the tree in memory */
-+ for (h = 1; h < c->lpt_hght; h++) {
-+ const size_t sz = sizeof(struct ubifs_nnode);
-+ struct ubifs_nnode *parent;
-+
-+ if (path[h].in_tree)
-+ continue;
-+ nnode = kmalloc(sz, GFP_NOFS);
-+ if (!nnode) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+ memcpy(nnode, &path[h].nnode, sz);
-+ parent = nnode->parent;
-+ parent->nbranch[nnode->iip].nnode = nnode;
-+ path[h].ptr.nnode = nnode;
-+ path[h].in_tree = 1;
-+ path[h + 1].cnode.parent = nnode;
-+ }
-+ if (path[h].in_tree)
-+ ubifs_ensure_cat(c, lprops);
-+ else {
-+ const size_t sz = sizeof(struct ubifs_pnode);
-+ struct ubifs_nnode *parent;
-+
-+ pnode = kmalloc(sz, GFP_NOFS);
-+ if (!pnode) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+ memcpy(pnode, &path[h].pnode, sz);
-+ parent = pnode->parent;
-+ parent->nbranch[pnode->iip].pnode = pnode;
-+ path[h].ptr.pnode = pnode;
-+ path[h].in_tree = 1;
-+ update_cats(c, pnode);
-+ c->pnodes_have += 1;
-+ }
-+ err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *)
-+ c->nroot, 0, 0);
-+ if (err)
-+ goto out;
-+ err = dbg_check_cats(c);
-+ if (err)
-+ goto out;
-+ }
-+ if (ret & LPT_SCAN_STOP) {
-+ err = 0;
-+ break;
-+ }
-+ /* Get the next lprops */
-+ if (lnum == end_lnum) {
-+ /*
-+ * We got to the end without finding what we were
-+ * looking for
-+ */
-+ err = -ENOSPC;
-+ goto out;
-+ }
-+ if (lnum + 1 >= c->leb_cnt) {
-+ /* Wrap-around to the beginning */
-+ start_lnum = c->main_first;
-+ goto again;
-+ }
-+ if (iip + 1 < UBIFS_LPT_FANOUT) {
-+ /* Next lprops is in the same pnode */
-+ iip += 1;
-+ continue;
-+ }
-+ /* We need to get the next pnode. Go up until we can go right */
-+ iip = pnode->iip;
-+ while (1) {
-+ h -= 1;
-+ ubifs_assert(h >= 0);
-+ nnode = path[h].ptr.nnode;
-+ if (iip + 1 < UBIFS_LPT_FANOUT)
-+ break;
-+ iip = nnode->iip;
-+ }
-+ /* Go right */
-+ iip += 1;
-+ /* Descend to the pnode */
-+ h += 1;
-+ for (; h < c->lpt_hght; h++) {
-+ nnode = scan_get_nnode(c, path + h, nnode, iip);
-+ if (IS_ERR(nnode)) {
-+ err = PTR_ERR(nnode);
-+ goto out;
-+ }
-+ iip = 0;
-+ }
-+ pnode = scan_get_pnode(c, path + h, nnode, iip);
-+ if (IS_ERR(pnode)) {
-+ err = PTR_ERR(pnode);
-+ goto out;
-+ }
-+ iip = 0;
-+ }
-+out:
-+ kfree(path);
-+ return err;
-+}
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+/**
-+ * dbg_chk_pnode - check a pnode.
-+ * @c: the UBIFS file-system description object
-+ * @pnode: pnode to check
-+ * @col: pnode column
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
-+ int col)
-+{
-+ int i;
-+
-+ if (pnode->num != col) {
-+ dbg_err("pnode num %d expected %d parent num %d iip %d",
-+ pnode->num, col, pnode->parent->num, pnode->iip);
-+ return -EINVAL;
-+ }
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ struct ubifs_lprops *lp, *lprops = &pnode->lprops[i];
-+ int lnum = (pnode->num << UBIFS_LPT_FANOUT_SHIFT) + i +
-+ c->main_first;
-+ int found, cat = lprops->flags & LPROPS_CAT_MASK;
-+ struct ubifs_lpt_heap *heap;
-+ struct list_head *list = NULL;
-+
-+ if (lnum >= c->leb_cnt)
-+ continue;
-+ if (lprops->lnum != lnum) {
-+ dbg_err("bad LEB number %d expected %d",
-+ lprops->lnum, lnum);
-+ return -EINVAL;
-+ }
-+ if (lprops->flags & LPROPS_TAKEN) {
-+ if (cat != LPROPS_UNCAT) {
-+ dbg_err("LEB %d taken but not uncat %d",
-+ lprops->lnum, cat);
-+ return -EINVAL;
-+ }
-+ continue;
-+ }
-+ if (lprops->flags & LPROPS_INDEX) {
-+ switch (cat) {
-+ case LPROPS_UNCAT:
-+ case LPROPS_DIRTY_IDX:
-+ case LPROPS_FRDI_IDX:
-+ break;
-+ default:
-+ dbg_err("LEB %d index but cat %d",
-+ lprops->lnum, cat);
-+ return -EINVAL;
-+ }
-+ } else {
-+ switch (cat) {
-+ case LPROPS_UNCAT:
-+ case LPROPS_DIRTY:
-+ case LPROPS_FREE:
-+ case LPROPS_EMPTY:
-+ case LPROPS_FREEABLE:
-+ break;
-+ default:
-+ dbg_err("LEB %d not index but cat %d",
-+ lprops->lnum, cat);
-+ return -EINVAL;
-+ }
-+ }
-+ switch (cat) {
-+ case LPROPS_UNCAT:
-+ list = &c->uncat_list;
-+ break;
-+ case LPROPS_EMPTY:
-+ list = &c->empty_list;
-+ break;
-+ case LPROPS_FREEABLE:
-+ list = &c->freeable_list;
-+ break;
-+ case LPROPS_FRDI_IDX:
-+ list = &c->frdi_idx_list;
-+ break;
-+ }
-+ found = 0;
-+ switch (cat) {
-+ case LPROPS_DIRTY:
-+ case LPROPS_DIRTY_IDX:
-+ case LPROPS_FREE:
-+ heap = &c->lpt_heap[cat - 1];
-+ if (lprops->hpos < heap->cnt &&
-+ heap->arr[lprops->hpos] == lprops)
-+ found = 1;
-+ break;
-+ case LPROPS_UNCAT:
-+ case LPROPS_EMPTY:
-+ case LPROPS_FREEABLE:
-+ case LPROPS_FRDI_IDX:
-+ list_for_each_entry(lp, list, list)
-+ if (lprops == lp) {
-+ found = 1;
-+ break;
-+ }
-+ break;
-+ }
-+ if (!found) {
-+ dbg_err("LEB %d cat %d not found in cat heap/list",
-+ lprops->lnum, cat);
-+ return -EINVAL;
-+ }
-+ switch (cat) {
-+ case LPROPS_EMPTY:
-+ if (lprops->free != c->leb_size) {
-+ dbg_err("LEB %d cat %d free %d dirty %d",
-+ lprops->lnum, cat, lprops->free,
-+ lprops->dirty);
-+ return -EINVAL;
-+ }
-+ case LPROPS_FREEABLE:
-+ case LPROPS_FRDI_IDX:
-+ if (lprops->free + lprops->dirty != c->leb_size) {
-+ dbg_err("LEB %d cat %d free %d dirty %d",
-+ lprops->lnum, cat, lprops->free,
-+ lprops->dirty);
-+ return -EINVAL;
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * dbg_check_lpt_nodes - check nnodes and pnodes.
-+ * @c: the UBIFS file-system description object
-+ * @cnode: next cnode (nnode or pnode) to check
-+ * @row: row of cnode (root is zero)
-+ * @col: column of cnode (leftmost is zero)
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
-+ int row, int col)
-+{
-+ struct ubifs_nnode *nnode, *nn;
-+ struct ubifs_cnode *cn;
-+ int num, iip = 0, err;
-+
-+ if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
-+ return 0;
-+
-+ while (cnode) {
-+ ubifs_assert(row >= 0);
-+ nnode = cnode->parent;
-+ if (cnode->level) {
-+ /* cnode is a nnode */
-+ num = calc_nnode_num(row, col);
-+ if (cnode->num != num) {
-+ dbg_err("nnode num %d expected %d "
-+ "parent num %d iip %d", cnode->num, num,
-+ (nnode ? nnode->num : 0), cnode->iip);
-+ return -EINVAL;
-+ }
-+ nn = (struct ubifs_nnode *)cnode;
-+ while (iip < UBIFS_LPT_FANOUT) {
-+ cn = nn->nbranch[iip].cnode;
-+ if (cn) {
-+ /* Go down */
-+ row += 1;
-+ col <<= UBIFS_LPT_FANOUT_SHIFT;
-+ col += iip;
-+ iip = 0;
-+ cnode = cn;
-+ break;
-+ }
-+ /* Go right */
-+ iip += 1;
-+ }
-+ if (iip < UBIFS_LPT_FANOUT)
-+ continue;
-+ } else {
-+ struct ubifs_pnode *pnode;
-+
-+ /* cnode is a pnode */
-+ pnode = (struct ubifs_pnode *)cnode;
-+ err = dbg_chk_pnode(c, pnode, col);
-+ if (err)
-+ return err;
-+ }
-+ /* Go up and to the right */
-+ row -= 1;
-+ col >>= UBIFS_LPT_FANOUT_SHIFT;
-+ iip = cnode->iip + 1;
-+ cnode = (struct ubifs_cnode *)nnode;
-+ }
-+ return 0;
-+}
-+
-+#endif /* CONFIG_UBIFS_FS_DEBUG */
---- linux-2.6.24.7.old/fs/ubifs/lpt_commit.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/lpt_commit.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1639 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file implements commit-related functionality of the LEB properties
-+ * subsystem.
-+ */
-+
-+#include
-+#include "ubifs.h"
-+
-+/**
-+ * first_dirty_cnode - find first dirty cnode.
-+ * @c: UBIFS file-system description object
-+ * @nnode: nnode at which to start
-+ *
-+ * This function returns the first dirty cnode or %NULL if there is not one.
-+ */
-+static struct ubifs_cnode *first_dirty_cnode(struct ubifs_nnode *nnode)
-+{
-+ ubifs_assert(nnode);
-+ while (1) {
-+ int i, cont = 0;
-+
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ struct ubifs_cnode *cnode;
-+
-+ cnode = nnode->nbranch[i].cnode;
-+ if (cnode &&
-+ test_bit(DIRTY_CNODE, &cnode->flags)) {
-+ if (cnode->level == 0)
-+ return cnode;
-+ nnode = (struct ubifs_nnode *)cnode;
-+ cont = 1;
-+ break;
-+ }
-+ }
-+ if (!cont)
-+ return (struct ubifs_cnode *)nnode;
-+ }
-+}
-+
-+/**
-+ * next_dirty_cnode - find next dirty cnode.
-+ * @cnode: cnode from which to begin searching
-+ *
-+ * This function returns the next dirty cnode or %NULL if there is not one.
-+ */
-+static struct ubifs_cnode *next_dirty_cnode(struct ubifs_cnode *cnode)
-+{
-+ struct ubifs_nnode *nnode;
-+ int i;
-+
-+ ubifs_assert(cnode);
-+ nnode = cnode->parent;
-+ if (!nnode)
-+ return NULL;
-+ for (i = cnode->iip + 1; i < UBIFS_LPT_FANOUT; i++) {
-+ cnode = nnode->nbranch[i].cnode;
-+ if (cnode && test_bit(DIRTY_CNODE, &cnode->flags)) {
-+ if (cnode->level == 0)
-+ return cnode; /* cnode is a pnode */
-+ /* cnode is a nnode */
-+ return first_dirty_cnode((struct ubifs_nnode *)cnode);
-+ }
-+ }
-+ return (struct ubifs_cnode *)nnode;
-+}
-+
-+/**
-+ * get_cnodes_to_commit - create list of dirty cnodes to commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns the number of cnodes to commit.
-+ */
-+static int get_cnodes_to_commit(struct ubifs_info *c)
-+{
-+ struct ubifs_cnode *cnode, *cnext;
-+ int cnt = 0;
-+
-+ if (!c->nroot)
-+ return 0;
-+
-+ if (!test_bit(DIRTY_CNODE, &c->nroot->flags))
-+ return 0;
-+
-+ c->lpt_cnext = first_dirty_cnode(c->nroot);
-+ cnode = c->lpt_cnext;
-+ if (!cnode)
-+ return 0;
-+ cnt += 1;
-+ while (1) {
-+ ubifs_assert(!test_bit(COW_ZNODE, &cnode->flags));
-+ __set_bit(COW_ZNODE, &cnode->flags);
-+ cnext = next_dirty_cnode(cnode);
-+ if (!cnext) {
-+ cnode->cnext = c->lpt_cnext;
-+ break;
-+ }
-+ cnode->cnext = cnext;
-+ cnode = cnext;
-+ cnt += 1;
-+ }
-+ dbg_cmt("committing %d cnodes", cnt);
-+ dbg_lp("committing %d cnodes", cnt);
-+ ubifs_assert(cnt == c->dirty_nn_cnt + c->dirty_pn_cnt);
-+ return cnt;
-+}
-+
-+/**
-+ * upd_ltab - update LPT LEB properties.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number
-+ * @free: amount of free space
-+ * @dirty: amount of dirty space to add
-+ */
-+static void upd_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
-+{
-+ dbg_lp("LEB %d free %d dirty %d to %d +%d",
-+ lnum, c->ltab[lnum - c->lpt_first].free,
-+ c->ltab[lnum - c->lpt_first].dirty, free, dirty);
-+ ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
-+ c->ltab[lnum - c->lpt_first].free = free;
-+ c->ltab[lnum - c->lpt_first].dirty += dirty;
-+}
-+
-+/**
-+ * alloc_lpt_leb - allocate an LPT LEB that is empty.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number is passed and returned here
-+ *
-+ * This function finds the next empty LEB in the ltab starting from @lnum. If a
-+ * an empty LEB is found it is returned in @lnum and the function returns %0.
-+ * Otherwise the function returns -ENOSPC. Note however, that LPT is designed
-+ * never to run out of space.
-+ */
-+static int alloc_lpt_leb(struct ubifs_info *c, int *lnum)
-+{
-+ int i, n;
-+
-+ n = *lnum - c->lpt_first + 1;
-+ for (i = n; i < c->lpt_lebs; i++) {
-+ if (c->ltab[i].tgc || c->ltab[i].cmt)
-+ continue;
-+ if (c->ltab[i].free == c->leb_size) {
-+ c->ltab[i].cmt = 1;
-+ *lnum = i + c->lpt_first;
-+ return 0;
-+ }
-+ }
-+
-+ for (i = 0; i < n; i++) {
-+ if (c->ltab[i].tgc || c->ltab[i].cmt)
-+ continue;
-+ if (c->ltab[i].free == c->leb_size) {
-+ c->ltab[i].cmt = 1;
-+ *lnum = i + c->lpt_first;
-+ return 0;
-+ }
-+ }
-+ dbg_err("last LEB %d", *lnum);
-+ dump_stack();
-+ return -ENOSPC;
-+}
-+
-+/**
-+ * layout_cnodes - layout cnodes for commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int layout_cnodes(struct ubifs_info *c)
-+{
-+ int lnum, offs, len, alen, done_lsave, done_ltab, err;
-+ struct ubifs_cnode *cnode;
-+
-+ cnode = c->lpt_cnext;
-+ if (!cnode)
-+ return 0;
-+ lnum = c->nhead_lnum;
-+ offs = c->nhead_offs;
-+ /* Try to place lsave and ltab nicely */
-+ done_lsave = !c->big_lpt;
-+ done_ltab = 0;
-+ if (!done_lsave && offs + c->lsave_sz <= c->leb_size) {
-+ done_lsave = 1;
-+ c->lsave_lnum = lnum;
-+ c->lsave_offs = offs;
-+ offs += c->lsave_sz;
-+ }
-+
-+ if (offs + c->ltab_sz <= c->leb_size) {
-+ done_ltab = 1;
-+ c->ltab_lnum = lnum;
-+ c->ltab_offs = offs;
-+ offs += c->ltab_sz;
-+ }
-+
-+ do {
-+ if (cnode->level) {
-+ len = c->nnode_sz;
-+ c->dirty_nn_cnt -= 1;
-+ } else {
-+ len = c->pnode_sz;
-+ c->dirty_pn_cnt -= 1;
-+ }
-+ while (offs + len > c->leb_size) {
-+ alen = ALIGN(offs, c->min_io_size);
-+ upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
-+ err = alloc_lpt_leb(c, &lnum);
-+ if (err)
-+ return err;
-+ offs = 0;
-+ ubifs_assert(lnum >= c->lpt_first &&
-+ lnum <= c->lpt_last);
-+ /* Try to place lsave and ltab nicely */
-+ if (!done_lsave) {
-+ done_lsave = 1;
-+ c->lsave_lnum = lnum;
-+ c->lsave_offs = offs;
-+ offs += c->lsave_sz;
-+ continue;
-+ }
-+ if (!done_ltab) {
-+ done_ltab = 1;
-+ c->ltab_lnum = lnum;
-+ c->ltab_offs = offs;
-+ offs += c->ltab_sz;
-+ continue;
-+ }
-+ break;
-+ }
-+ if (cnode->parent) {
-+ cnode->parent->nbranch[cnode->iip].lnum = lnum;
-+ cnode->parent->nbranch[cnode->iip].offs = offs;
-+ } else {
-+ c->lpt_lnum = lnum;
-+ c->lpt_offs = offs;
-+ }
-+ offs += len;
-+ cnode = cnode->cnext;
-+ } while (cnode && cnode != c->lpt_cnext);
-+
-+ /* Make sure to place LPT's save table */
-+ if (!done_lsave) {
-+ if (offs + c->lsave_sz > c->leb_size) {
-+ alen = ALIGN(offs, c->min_io_size);
-+ upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
-+ err = alloc_lpt_leb(c, &lnum);
-+ if (err)
-+ return err;
-+ offs = 0;
-+ ubifs_assert(lnum >= c->lpt_first &&
-+ lnum <= c->lpt_last);
-+ }
-+ done_lsave = 1;
-+ c->lsave_lnum = lnum;
-+ c->lsave_offs = offs;
-+ offs += c->lsave_sz;
-+ }
-+
-+ /* Make sure to place LPT's own lprops table */
-+ if (!done_ltab) {
-+ if (offs + c->ltab_sz > c->leb_size) {
-+ alen = ALIGN(offs, c->min_io_size);
-+ upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
-+ err = alloc_lpt_leb(c, &lnum);
-+ if (err)
-+ return err;
-+ offs = 0;
-+ ubifs_assert(lnum >= c->lpt_first &&
-+ lnum <= c->lpt_last);
-+ }
-+ done_ltab = 1;
-+ c->ltab_lnum = lnum;
-+ c->ltab_offs = offs;
-+ offs += c->ltab_sz;
-+ }
-+
-+ alen = ALIGN(offs, c->min_io_size);
-+ upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
-+ return 0;
-+}
-+
-+/**
-+ * realloc_lpt_leb - allocate an LPT LEB that is empty.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number is passed and returned here
-+ *
-+ * This function duplicates exactly the results of the function alloc_lpt_leb.
-+ * It is used during end commit to reallocate the same LEB numbers that were
-+ * allocated by alloc_lpt_leb during start commit.
-+ *
-+ * This function finds the next LEB that was allocated by the alloc_lpt_leb
-+ * function starting from @lnum. If a LEB is found it is returned in @lnum and
-+ * the function returns %0. Otherwise the function returns -ENOSPC.
-+ * Note however, that LPT is designed never to run out of space.
-+ */
-+static int realloc_lpt_leb(struct ubifs_info *c, int *lnum)
-+{
-+ int i, n;
-+
-+ n = *lnum - c->lpt_first + 1;
-+ for (i = n; i < c->lpt_lebs; i++)
-+ if (c->ltab[i].cmt) {
-+ c->ltab[i].cmt = 0;
-+ *lnum = i + c->lpt_first;
-+ return 0;
-+ }
-+
-+ for (i = 0; i < n; i++)
-+ if (c->ltab[i].cmt) {
-+ c->ltab[i].cmt = 0;
-+ *lnum = i + c->lpt_first;
-+ return 0;
-+ }
-+ dbg_err("last LEB %d", *lnum);
-+ dump_stack();
-+ return -ENOSPC;
-+}
-+
-+/**
-+ * write_cnodes - write cnodes for commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int write_cnodes(struct ubifs_info *c)
-+{
-+ int lnum, offs, len, from, err, wlen, alen, done_ltab, done_lsave;
-+ struct ubifs_cnode *cnode;
-+ void *buf = c->lpt_buf;
-+
-+ cnode = c->lpt_cnext;
-+ if (!cnode)
-+ return 0;
-+ lnum = c->nhead_lnum;
-+ offs = c->nhead_offs;
-+ from = offs;
-+ /* Ensure empty LEB is unmapped */
-+ if (offs == 0) {
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ }
-+ /* Try to place lsave and ltab nicely */
-+ done_lsave = !c->big_lpt;
-+ done_ltab = 0;
-+ if (!done_lsave && offs + c->lsave_sz <= c->leb_size) {
-+ done_lsave = 1;
-+ ubifs_pack_lsave(c, buf + offs, c->lsave);
-+ offs += c->lsave_sz;
-+ }
-+
-+ if (offs + c->ltab_sz <= c->leb_size) {
-+ done_ltab = 1;
-+ ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
-+ offs += c->ltab_sz;
-+ }
-+
-+ /* Loop for each cnode */
-+ do {
-+ if (cnode->level)
-+ len = c->nnode_sz;
-+ else
-+ len = c->pnode_sz;
-+ while (offs + len > c->leb_size) {
-+ wlen = offs - from;
-+ if (wlen) {
-+ alen = ALIGN(wlen, c->min_io_size);
-+ memset(buf + offs, 0xff, alen - wlen);
-+ err = ubifs_leb_write(c, lnum, buf + from, from,
-+ alen, UBI_SHORTTERM);
-+ if (err)
-+ return err;
-+ }
-+ err = realloc_lpt_leb(c, &lnum);
-+ if (err)
-+ return err;
-+ offs = 0;
-+ from = 0;
-+ ubifs_assert(lnum >= c->lpt_first &&
-+ lnum <= c->lpt_last);
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ /* Try to place lsave and ltab nicely */
-+ if (!done_lsave) {
-+ done_lsave = 1;
-+ ubifs_pack_lsave(c, buf + offs, c->lsave);
-+ offs += c->lsave_sz;
-+ continue;
-+ }
-+ if (!done_ltab) {
-+ done_ltab = 1;
-+ ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
-+ offs += c->ltab_sz;
-+ continue;
-+ }
-+ break;
-+ }
-+ if (cnode->level)
-+ ubifs_pack_nnode(c, buf + offs,
-+ (struct ubifs_nnode *)cnode);
-+ else
-+ ubifs_pack_pnode(c, buf + offs,
-+ (struct ubifs_pnode *)cnode);
-+ /*
-+ * The reason for the barriers is the same as in case of TNC.
-+ * See comment in 'write_index()'. 'dirty_cow_nnode()' and
-+ * 'dirty_cow_pnode()' are the functions for which this is
-+ * important.
-+ */
-+ clear_bit(DIRTY_CNODE, &cnode->flags);
-+ smp_mb__before_clear_bit();
-+ clear_bit(COW_ZNODE, &cnode->flags);
-+ smp_mb__after_clear_bit();
-+ offs += len;
-+ cnode = cnode->cnext;
-+ } while (cnode && cnode != c->lpt_cnext);
-+
-+ /* Make sure to place LPT's save table */
-+ if (!done_lsave) {
-+ if (offs + c->lsave_sz > c->leb_size) {
-+ wlen = offs - from;
-+ alen = ALIGN(wlen, c->min_io_size);
-+ memset(buf + offs, 0xff, alen - wlen);
-+ err = ubifs_leb_write(c, lnum, buf + from, from, alen,
-+ UBI_SHORTTERM);
-+ if (err)
-+ return err;
-+ err = realloc_lpt_leb(c, &lnum);
-+ if (err)
-+ return err;
-+ offs = 0;
-+ ubifs_assert(lnum >= c->lpt_first &&
-+ lnum <= c->lpt_last);
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ }
-+ done_lsave = 1;
-+ ubifs_pack_lsave(c, buf + offs, c->lsave);
-+ offs += c->lsave_sz;
-+ }
-+
-+ /* Make sure to place LPT's own lprops table */
-+ if (!done_ltab) {
-+ if (offs + c->ltab_sz > c->leb_size) {
-+ wlen = offs - from;
-+ alen = ALIGN(wlen, c->min_io_size);
-+ memset(buf + offs, 0xff, alen - wlen);
-+ err = ubifs_leb_write(c, lnum, buf + from, from, alen,
-+ UBI_SHORTTERM);
-+ if (err)
-+ return err;
-+ err = realloc_lpt_leb(c, &lnum);
-+ if (err)
-+ return err;
-+ offs = 0;
-+ ubifs_assert(lnum >= c->lpt_first &&
-+ lnum <= c->lpt_last);
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ }
-+ done_ltab = 1;
-+ ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
-+ offs += c->ltab_sz;
-+ }
-+
-+ /* Write remaining data in buffer */
-+ wlen = offs - from;
-+ alen = ALIGN(wlen, c->min_io_size);
-+ memset(buf + offs, 0xff, alen - wlen);
-+ err = ubifs_leb_write(c, lnum, buf + from, from, alen, UBI_SHORTTERM);
-+ if (err)
-+ return err;
-+ c->nhead_lnum = lnum;
-+ c->nhead_offs = ALIGN(offs, c->min_io_size);
-+
-+ dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
-+ dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
-+ dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
-+ if (c->big_lpt)
-+ dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
-+ return 0;
-+}
-+
-+/**
-+ * next_pnode - find next pnode.
-+ * @c: UBIFS file-system description object
-+ * @pnode: pnode
-+ *
-+ * This function returns the next pnode or %NULL if there are no more pnodes.
-+ */
-+static struct ubifs_pnode *next_pnode(struct ubifs_info *c,
-+ struct ubifs_pnode *pnode)
-+{
-+ struct ubifs_nnode *nnode;
-+ int iip;
-+
-+ /* Try to go right */
-+ nnode = pnode->parent;
-+ iip = pnode->iip + 1;
-+ if (iip < UBIFS_LPT_FANOUT) {
-+ /* We assume here that LEB zero is never an LPT LEB */
-+ if (nnode->nbranch[iip].lnum)
-+ return ubifs_get_pnode(c, nnode, iip);
-+ else
-+ return NULL;
-+ }
-+
-+ /* Go up while can't go right */
-+ do {
-+ iip = nnode->iip + 1;
-+ nnode = nnode->parent;
-+ if (!nnode)
-+ return NULL;
-+ /* We assume here that LEB zero is never an LPT LEB */
-+ } while (iip >= UBIFS_LPT_FANOUT || !nnode->nbranch[iip].lnum);
-+
-+ /* Go right */
-+ nnode = ubifs_get_nnode(c, nnode, iip);
-+ if (IS_ERR(nnode))
-+ return (void *)nnode;
-+
-+ /* Go down to level 1 */
-+ while (nnode->level > 1) {
-+ nnode = ubifs_get_nnode(c, nnode, 0);
-+ if (IS_ERR(nnode))
-+ return (void *)nnode;
-+ }
-+
-+ return ubifs_get_pnode(c, nnode, 0);
-+}
-+
-+/**
-+ * pnode_lookup - lookup a pnode in the LPT.
-+ * @c: UBIFS file-system description object
-+ * @i: pnode number (0 to main_lebs - 1)
-+ *
-+ * This function returns a pointer to the pnode on success or a negative
-+ * error code on failure.
-+ */
-+static struct ubifs_pnode *pnode_lookup(struct ubifs_info *c, int i)
-+{
-+ int err, h, iip, shft;
-+ struct ubifs_nnode *nnode;
-+
-+ if (!c->nroot) {
-+ err = ubifs_read_nnode(c, NULL, 0);
-+ if (err)
-+ return ERR_PTR(err);
-+ }
-+ i <<= UBIFS_LPT_FANOUT_SHIFT;
-+ nnode = c->nroot;
-+ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
-+ for (h = 1; h < c->lpt_hght; h++) {
-+ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-+ shft -= UBIFS_LPT_FANOUT_SHIFT;
-+ nnode = ubifs_get_nnode(c, nnode, iip);
-+ if (IS_ERR(nnode))
-+ return ERR_PTR(PTR_ERR(nnode));
-+ }
-+ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-+ return ubifs_get_pnode(c, nnode, iip);
-+}
-+
-+/**
-+ * add_pnode_dirt - add dirty space to LPT LEB properties.
-+ * @c: UBIFS file-system description object
-+ * @pnode: pnode for which to add dirt
-+ */
-+static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode)
-+{
-+ ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum,
-+ c->pnode_sz);
-+}
-+
-+/**
-+ * do_make_pnode_dirty - mark a pnode dirty.
-+ * @c: UBIFS file-system description object
-+ * @pnode: pnode to mark dirty
-+ */
-+static void do_make_pnode_dirty(struct ubifs_info *c, struct ubifs_pnode *pnode)
-+{
-+ /* Assumes cnext list is empty i.e. not called during commit */
-+ if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) {
-+ struct ubifs_nnode *nnode;
-+
-+ c->dirty_pn_cnt += 1;
-+ add_pnode_dirt(c, pnode);
-+ /* Mark parent and ancestors dirty too */
-+ nnode = pnode->parent;
-+ while (nnode) {
-+ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
-+ c->dirty_nn_cnt += 1;
-+ ubifs_add_nnode_dirt(c, nnode);
-+ nnode = nnode->parent;
-+ } else
-+ break;
-+ }
-+ }
-+}
-+
-+/**
-+ * make_tree_dirty - mark the entire LEB properties tree dirty.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function is used by the "small" LPT model to cause the entire LEB
-+ * properties tree to be written. The "small" LPT model does not use LPT
-+ * garbage collection because it is more efficient to write the entire tree
-+ * (because it is small).
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int make_tree_dirty(struct ubifs_info *c)
-+{
-+ struct ubifs_pnode *pnode;
-+
-+ pnode = pnode_lookup(c, 0);
-+ while (pnode) {
-+ do_make_pnode_dirty(c, pnode);
-+ pnode = next_pnode(c, pnode);
-+ if (IS_ERR(pnode))
-+ return PTR_ERR(pnode);
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * need_write_all - determine if the LPT area is running out of free space.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns %1 if the LPT area is running out of free space and %0
-+ * if it is not.
-+ */
-+static int need_write_all(struct ubifs_info *c)
-+{
-+ long long free = 0;
-+ int i;
-+
-+ for (i = 0; i < c->lpt_lebs; i++) {
-+ if (i + c->lpt_first == c->nhead_lnum)
-+ free += c->leb_size - c->nhead_offs;
-+ else if (c->ltab[i].free == c->leb_size)
-+ free += c->leb_size;
-+ else if (c->ltab[i].free + c->ltab[i].dirty == c->leb_size)
-+ free += c->leb_size;
-+ }
-+ /* Less than twice the size left */
-+ if (free <= c->lpt_sz * 2)
-+ return 1;
-+ return 0;
-+}
-+
-+/**
-+ * lpt_tgc_start - start trivial garbage collection of LPT LEBs.
-+ * @c: UBIFS file-system description object
-+ *
-+ * LPT trivial garbage collection is where a LPT LEB contains only dirty and
-+ * free space and so may be reused as soon as the next commit is completed.
-+ * This function is called during start commit to mark LPT LEBs for trivial GC.
-+ */
-+static void lpt_tgc_start(struct ubifs_info *c)
-+{
-+ int i;
-+
-+ for (i = 0; i < c->lpt_lebs; i++) {
-+ if (i + c->lpt_first == c->nhead_lnum)
-+ continue;
-+ if (c->ltab[i].dirty > 0 &&
-+ c->ltab[i].free + c->ltab[i].dirty == c->leb_size) {
-+ c->ltab[i].tgc = 1;
-+ c->ltab[i].free = c->leb_size;
-+ c->ltab[i].dirty = 0;
-+ dbg_lp("LEB %d", i + c->lpt_first);
-+ }
-+ }
-+}
-+
-+/**
-+ * lpt_tgc_end - end trivial garbage collection of LPT LEBs.
-+ * @c: UBIFS file-system description object
-+ *
-+ * LPT trivial garbage collection is where a LPT LEB contains only dirty and
-+ * free space and so may be reused as soon as the next commit is completed.
-+ * This function is called after the commit is completed (master node has been
-+ * written) and unmaps LPT LEBs that were marked for trivial GC.
-+ */
-+static int lpt_tgc_end(struct ubifs_info *c)
-+{
-+ int i, err;
-+
-+ for (i = 0; i < c->lpt_lebs; i++)
-+ if (c->ltab[i].tgc) {
-+ err = ubifs_leb_unmap(c, i + c->lpt_first);
-+ if (err)
-+ return err;
-+ c->ltab[i].tgc = 0;
-+ dbg_lp("LEB %d", i + c->lpt_first);
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * populate_lsave - fill the lsave array with important LEB numbers.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function is only called for the "big" model. It records a small number
-+ * of LEB numbers of important LEBs. Important LEBs are ones that are (from
-+ * most important to least important): empty, freeable, freeable index, dirty
-+ * index, dirty or free. Upon mount, we read this list of LEB numbers and bring
-+ * their pnodes into memory. That will stop us from having to scan the LPT
-+ * straight away. For the "small" model we assume that scanning the LPT is no
-+ * big deal.
-+ */
-+static void populate_lsave(struct ubifs_info *c)
-+{
-+ struct ubifs_lprops *lprops;
-+ struct ubifs_lpt_heap *heap;
-+ int i, cnt = 0;
-+
-+ ubifs_assert(c->big_lpt);
-+ if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) {
-+ c->lpt_drty_flgs |= LSAVE_DIRTY;
-+ ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz);
-+ }
-+ list_for_each_entry(lprops, &c->empty_list, list) {
-+ c->lsave[cnt++] = lprops->lnum;
-+ if (cnt >= c->lsave_cnt)
-+ return;
-+ }
-+ list_for_each_entry(lprops, &c->freeable_list, list) {
-+ c->lsave[cnt++] = lprops->lnum;
-+ if (cnt >= c->lsave_cnt)
-+ return;
-+ }
-+ list_for_each_entry(lprops, &c->frdi_idx_list, list) {
-+ c->lsave[cnt++] = lprops->lnum;
-+ if (cnt >= c->lsave_cnt)
-+ return;
-+ }
-+ heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
-+ for (i = 0; i < heap->cnt; i++) {
-+ c->lsave[cnt++] = heap->arr[i]->lnum;
-+ if (cnt >= c->lsave_cnt)
-+ return;
-+ }
-+ heap = &c->lpt_heap[LPROPS_DIRTY - 1];
-+ for (i = 0; i < heap->cnt; i++) {
-+ c->lsave[cnt++] = heap->arr[i]->lnum;
-+ if (cnt >= c->lsave_cnt)
-+ return;
-+ }
-+ heap = &c->lpt_heap[LPROPS_FREE - 1];
-+ for (i = 0; i < heap->cnt; i++) {
-+ c->lsave[cnt++] = heap->arr[i]->lnum;
-+ if (cnt >= c->lsave_cnt)
-+ return;
-+ }
-+ /* Fill it up completely */
-+ while (cnt < c->lsave_cnt)
-+ c->lsave[cnt++] = c->main_first;
-+}
-+
-+/**
-+ * ubifs_lpt_start_commit - UBIFS commit starts.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function has to be called when UBIFS starts the commit operation.
-+ * This function "freezes" all currently dirty LEB properties and does not
-+ * change them anymore. Further changes are saved and tracked separately
-+ * because they are not part of this commit. This function returns zero in case
-+ * of success and a negative error code in case of failure.
-+ */
-+int ubifs_lpt_start_commit(struct ubifs_info *c)
-+{
-+ int err, cnt;
-+
-+ dbg_lp("");
-+
-+ mutex_lock(&c->lp_mutex);
-+ err = dbg_check_ltab(c);
-+ if (err)
-+ goto out;
-+
-+ lpt_tgc_start(c);
-+
-+ if (!c->dirty_pn_cnt) {
-+ dbg_cmt("no cnodes to commit");
-+ err = 0;
-+ goto out;
-+ }
-+
-+ if (!c->big_lpt && need_write_all(c)) {
-+ /* If needed, write everything */
-+ err = make_tree_dirty(c);
-+ if (err)
-+ goto out;
-+ lpt_tgc_start(c);
-+ }
-+
-+ if (c->big_lpt)
-+ populate_lsave(c);
-+
-+ cnt = get_cnodes_to_commit(c);
-+ ubifs_assert(cnt != 0);
-+
-+ err = layout_cnodes(c);
-+ if (err)
-+ goto out;
-+
-+ /* Copy the LPT's own lprops for end commit to write */
-+ memcpy(c->ltab_cmt, c->ltab,
-+ sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
-+ c->lpt_drty_flgs &= ~(LTAB_DIRTY | LSAVE_DIRTY);
-+
-+out:
-+ mutex_unlock(&c->lp_mutex);
-+ return err;
-+}
-+
-+/**
-+ * free_obsolete_cnodes - free obsolete cnodes for commit end.
-+ * @c: UBIFS file-system description object
-+ */
-+static void free_obsolete_cnodes(struct ubifs_info *c)
-+{
-+ struct ubifs_cnode *cnode, *cnext;
-+
-+ cnext = c->lpt_cnext;
-+ if (!cnext)
-+ return;
-+ do {
-+ cnode = cnext;
-+ cnext = cnode->cnext;
-+ if (test_bit(OBSOLETE_CNODE, &cnode->flags))
-+ kfree(cnode);
-+ else
-+ cnode->cnext = NULL;
-+ } while (cnext != c->lpt_cnext);
-+ c->lpt_cnext = NULL;
-+}
-+
-+/**
-+ * ubifs_lpt_end_commit - finish the commit operation.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function has to be called when the commit operation finishes. It
-+ * flushes the changes which were "frozen" by 'ubifs_lprops_start_commit()' to
-+ * the media. Returns zero in case of success and a negative error code in case
-+ * of failure.
-+ */
-+int ubifs_lpt_end_commit(struct ubifs_info *c)
-+{
-+ int err;
-+
-+ dbg_lp("");
-+
-+ if (!c->lpt_cnext)
-+ return 0;
-+
-+ err = write_cnodes(c);
-+ if (err)
-+ return err;
-+
-+ mutex_lock(&c->lp_mutex);
-+ free_obsolete_cnodes(c);
-+ mutex_unlock(&c->lp_mutex);
-+
-+ return 0;
-+}
-+
-+/**
-+ * nnode_lookup - lookup a nnode in the LPT.
-+ * @c: UBIFS file-system description object
-+ * @i: nnode number
-+ *
-+ * This function returns a pointer to the nnode on success or a negative
-+ * error code on failure.
-+ */
-+static struct ubifs_nnode *nnode_lookup(struct ubifs_info *c, int i)
-+{
-+ int err, iip;
-+ struct ubifs_nnode *nnode;
-+
-+ if (!c->nroot) {
-+ err = ubifs_read_nnode(c, NULL, 0);
-+ if (err)
-+ return ERR_PTR(err);
-+ }
-+ nnode = c->nroot;
-+ while (1) {
-+ iip = i & (UBIFS_LPT_FANOUT - 1);
-+ i >>= UBIFS_LPT_FANOUT_SHIFT;
-+ if (!i)
-+ break;
-+ nnode = ubifs_get_nnode(c, nnode, iip);
-+ if (IS_ERR(nnode))
-+ return nnode;
-+ }
-+ return nnode;
-+}
-+
-+/**
-+ * make_nnode_dirty - find a nnode and, if found, make it dirty.
-+ * @c: UBIFS file-system description object
-+ * @node_num: nnode number of nnode to make dirty
-+ * @lnum: LEB number where nnode was written
-+ * @offs: offset where nnode was written
-+ *
-+ * This function is used by LPT garbage collection. LPT garbage collection is
-+ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
-+ * simply involves marking all the nodes in the LEB being garbage-collected as
-+ * dirty. The dirty nodes are written next commit, after which the LEB is free
-+ * to be reused.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int make_nnode_dirty(struct ubifs_info *c, int node_num, int lnum,
-+ int offs)
-+{
-+ struct ubifs_nnode *nnode;
-+
-+ nnode = nnode_lookup(c, node_num);
-+ if (IS_ERR(nnode))
-+ return PTR_ERR(nnode);
-+ if (nnode->parent) {
-+ struct ubifs_nbranch *branch;
-+
-+ branch = &nnode->parent->nbranch[nnode->iip];
-+ if (branch->lnum != lnum || branch->offs != offs)
-+ return 0; /* nnode is obsolete */
-+ } else if (c->lpt_lnum != lnum || c->lpt_offs != offs)
-+ return 0; /* nnode is obsolete */
-+ /* Assumes cnext list is empty i.e. not called during commit */
-+ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
-+ c->dirty_nn_cnt += 1;
-+ ubifs_add_nnode_dirt(c, nnode);
-+ /* Mark parent and ancestors dirty too */
-+ nnode = nnode->parent;
-+ while (nnode) {
-+ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
-+ c->dirty_nn_cnt += 1;
-+ ubifs_add_nnode_dirt(c, nnode);
-+ nnode = nnode->parent;
-+ } else
-+ break;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * make_pnode_dirty - find a pnode and, if found, make it dirty.
-+ * @c: UBIFS file-system description object
-+ * @node_num: pnode number of pnode to make dirty
-+ * @lnum: LEB number where pnode was written
-+ * @offs: offset where pnode was written
-+ *
-+ * This function is used by LPT garbage collection. LPT garbage collection is
-+ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
-+ * simply involves marking all the nodes in the LEB being garbage-collected as
-+ * dirty. The dirty nodes are written next commit, after which the LEB is free
-+ * to be reused.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int make_pnode_dirty(struct ubifs_info *c, int node_num, int lnum,
-+ int offs)
-+{
-+ struct ubifs_pnode *pnode;
-+ struct ubifs_nbranch *branch;
-+
-+ pnode = pnode_lookup(c, node_num);
-+ if (IS_ERR(pnode))
-+ return PTR_ERR(pnode);
-+ branch = &pnode->parent->nbranch[pnode->iip];
-+ if (branch->lnum != lnum || branch->offs != offs)
-+ return 0;
-+ do_make_pnode_dirty(c, pnode);
-+ return 0;
-+}
-+
-+/**
-+ * make_ltab_dirty - make ltab node dirty.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number where ltab was written
-+ * @offs: offset where ltab was written
-+ *
-+ * This function is used by LPT garbage collection. LPT garbage collection is
-+ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
-+ * simply involves marking all the nodes in the LEB being garbage-collected as
-+ * dirty. The dirty nodes are written next commit, after which the LEB is free
-+ * to be reused.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int make_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
-+{
-+ if (lnum != c->ltab_lnum || offs != c->ltab_offs)
-+ return 0; /* This ltab node is obsolete */
-+ if (!(c->lpt_drty_flgs & LTAB_DIRTY)) {
-+ c->lpt_drty_flgs |= LTAB_DIRTY;
-+ ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz);
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * make_lsave_dirty - make lsave node dirty.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number where lsave was written
-+ * @offs: offset where lsave was written
-+ *
-+ * This function is used by LPT garbage collection. LPT garbage collection is
-+ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
-+ * simply involves marking all the nodes in the LEB being garbage-collected as
-+ * dirty. The dirty nodes are written next commit, after which the LEB is free
-+ * to be reused.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int make_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
-+{
-+ if (lnum != c->lsave_lnum || offs != c->lsave_offs)
-+ return 0; /* This lsave node is obsolete */
-+ if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) {
-+ c->lpt_drty_flgs |= LSAVE_DIRTY;
-+ ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz);
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * make_node_dirty - make node dirty.
-+ * @c: UBIFS file-system description object
-+ * @node_type: LPT node type
-+ * @node_num: node number
-+ * @lnum: LEB number where node was written
-+ * @offs: offset where node was written
-+ *
-+ * This function is used by LPT garbage collection. LPT garbage collection is
-+ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection
-+ * simply involves marking all the nodes in the LEB being garbage-collected as
-+ * dirty. The dirty nodes are written next commit, after which the LEB is free
-+ * to be reused.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int make_node_dirty(struct ubifs_info *c, int node_type, int node_num,
-+ int lnum, int offs)
-+{
-+ switch (node_type) {
-+ case UBIFS_LPT_NNODE:
-+ return make_nnode_dirty(c, node_num, lnum, offs);
-+ case UBIFS_LPT_PNODE:
-+ return make_pnode_dirty(c, node_num, lnum, offs);
-+ case UBIFS_LPT_LTAB:
-+ return make_ltab_dirty(c, lnum, offs);
-+ case UBIFS_LPT_LSAVE:
-+ return make_lsave_dirty(c, lnum, offs);
-+ }
-+ return -EINVAL;
-+}
-+
-+/**
-+ * get_lpt_node_len - return the length of a node based on its type.
-+ * @c: UBIFS file-system description object
-+ * @node_type: LPT node type
-+ */
-+static int get_lpt_node_len(struct ubifs_info *c, int node_type)
-+{
-+ switch (node_type) {
-+ case UBIFS_LPT_NNODE:
-+ return c->nnode_sz;
-+ case UBIFS_LPT_PNODE:
-+ return c->pnode_sz;
-+ case UBIFS_LPT_LTAB:
-+ return c->ltab_sz;
-+ case UBIFS_LPT_LSAVE:
-+ return c->lsave_sz;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * get_pad_len - return the length of padding in a buffer.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer
-+ * @len: length of buffer
-+ */
-+static int get_pad_len(struct ubifs_info *c, uint8_t *buf, int len)
-+{
-+ int offs, pad_len;
-+
-+ if (c->min_io_size == 1)
-+ return 0;
-+ offs = c->leb_size - len;
-+ pad_len = ALIGN(offs, c->min_io_size) - offs;
-+ return pad_len;
-+}
-+
-+/**
-+ * get_lpt_node_type - return type (and node number) of a node in a buffer.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer
-+ * @node_num: node number is returned here
-+ */
-+static int get_lpt_node_type(struct ubifs_info *c, uint8_t *buf, int *node_num)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int pos = 0, node_type;
-+
-+ node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
-+ *node_num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
-+ return node_type;
-+}
-+
-+/**
-+ * is_a_node - determine if a buffer contains a node.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer
-+ * @len: length of buffer
-+ *
-+ * This function returns %1 if the buffer contains a node or %0 if it does not.
-+ */
-+static int is_a_node(struct ubifs_info *c, uint8_t *buf, int len)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int pos = 0, node_type, node_len;
-+ uint16_t crc, calc_crc;
-+
-+ node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
-+ if (node_type == UBIFS_LPT_NOT_A_NODE)
-+ return 0;
-+ node_len = get_lpt_node_len(c, node_type);
-+ if (!node_len || node_len > len)
-+ return 0;
-+ pos = 0;
-+ addr = buf;
-+ crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS);
-+ calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ node_len - UBIFS_LPT_CRC_BYTES);
-+ if (crc != calc_crc)
-+ return 0;
-+ return 1;
-+}
-+
-+
-+/**
-+ * lpt_gc_lnum - garbage collect a LPT LEB.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number to garbage collect
-+ *
-+ * LPT garbage collection is used only for the "big" LPT model
-+ * (c->big_lpt == 1). Garbage collection simply involves marking all the nodes
-+ * in the LEB being garbage-collected as dirty. The dirty nodes are written
-+ * next commit, after which the LEB is free to be reused.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int lpt_gc_lnum(struct ubifs_info *c, int lnum)
-+{
-+ int err, len = c->leb_size, node_type, node_num, node_len, offs;
-+ void *buf = c->lpt_buf;
-+
-+ dbg_lp("LEB %d", lnum);
-+ err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
-+ if (err) {
-+ ubifs_err("cannot read LEB %d, error %d", lnum, err);
-+ return err;
-+ }
-+ while (1) {
-+ if (!is_a_node(c, buf, len)) {
-+ int pad_len;
-+
-+ pad_len = get_pad_len(c, buf, len);
-+ if (pad_len) {
-+ buf += pad_len;
-+ len -= pad_len;
-+ continue;
-+ }
-+ return 0;
-+ }
-+ node_type = get_lpt_node_type(c, buf, &node_num);
-+ node_len = get_lpt_node_len(c, node_type);
-+ offs = c->leb_size - len;
-+ ubifs_assert(node_len != 0);
-+ mutex_lock(&c->lp_mutex);
-+ err = make_node_dirty(c, node_type, node_num, lnum, offs);
-+ mutex_unlock(&c->lp_mutex);
-+ if (err)
-+ return err;
-+ buf += node_len;
-+ len -= node_len;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * lpt_gc - LPT garbage collection.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Select a LPT LEB for LPT garbage collection and call 'lpt_gc_lnum()'.
-+ * Returns %0 on success and a negative error code on failure.
-+ */
-+static int lpt_gc(struct ubifs_info *c)
-+{
-+ int i, lnum = -1, dirty = 0;
-+
-+ mutex_lock(&c->lp_mutex);
-+ for (i = 0; i < c->lpt_lebs; i++) {
-+ ubifs_assert(!c->ltab[i].tgc);
-+ if (i + c->lpt_first == c->nhead_lnum ||
-+ c->ltab[i].free + c->ltab[i].dirty == c->leb_size)
-+ continue;
-+ if (c->ltab[i].dirty > dirty) {
-+ dirty = c->ltab[i].dirty;
-+ lnum = i + c->lpt_first;
-+ }
-+ }
-+ mutex_unlock(&c->lp_mutex);
-+ if (lnum == -1)
-+ return -ENOSPC;
-+ return lpt_gc_lnum(c, lnum);
-+}
-+
-+/**
-+ * ubifs_lpt_post_commit - post commit LPT trivial GC and LPT GC.
-+ * @c: UBIFS file-system description object
-+ *
-+ * LPT trivial GC is completed after a commit. Also LPT GC is done after a
-+ * commit for the "big" LPT model.
-+ */
-+int ubifs_lpt_post_commit(struct ubifs_info *c)
-+{
-+ int err;
-+
-+ mutex_lock(&c->lp_mutex);
-+ err = lpt_tgc_end(c);
-+ if (err)
-+ goto out;
-+ if (c->big_lpt)
-+ while (need_write_all(c)) {
-+ mutex_unlock(&c->lp_mutex);
-+ err = lpt_gc(c);
-+ if (err)
-+ return err;
-+ mutex_lock(&c->lp_mutex);
-+ }
-+out:
-+ mutex_unlock(&c->lp_mutex);
-+ return err;
-+}
-+
-+/**
-+ * first_nnode - find the first nnode in memory.
-+ * @c: UBIFS file-system description object
-+ * @hght: height of tree where nnode found is returned here
-+ *
-+ * This function returns a pointer to the nnode found or %NULL if no nnode is
-+ * found. This function is a helper to 'ubifs_lpt_free()'.
-+ */
-+static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght)
-+{
-+ struct ubifs_nnode *nnode;
-+ int h, i, found;
-+
-+ nnode = c->nroot;
-+ *hght = 0;
-+ if (!nnode)
-+ return NULL;
-+ for (h = 1; h < c->lpt_hght; h++) {
-+ found = 0;
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ if (nnode->nbranch[i].nnode) {
-+ found = 1;
-+ nnode = nnode->nbranch[i].nnode;
-+ *hght = h;
-+ break;
-+ }
-+ }
-+ if (!found)
-+ break;
-+ }
-+ return nnode;
-+}
-+
-+/**
-+ * next_nnode - find the next nnode in memory.
-+ * @c: UBIFS file-system description object
-+ * @nnode: nnode from which to start.
-+ * @hght: height of tree where nnode is, is passed and returned here
-+ *
-+ * This function returns a pointer to the nnode found or %NULL if no nnode is
-+ * found. This function is a helper to 'ubifs_lpt_free()'.
-+ */
-+static struct ubifs_nnode *next_nnode(struct ubifs_info *c,
-+ struct ubifs_nnode *nnode, int *hght)
-+{
-+ struct ubifs_nnode *parent;
-+ int iip, h, i, found;
-+
-+ parent = nnode->parent;
-+ if (!parent)
-+ return NULL;
-+ if (nnode->iip == UBIFS_LPT_FANOUT - 1) {
-+ *hght -= 1;
-+ return parent;
-+ }
-+ for (iip = nnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
-+ nnode = parent->nbranch[iip].nnode;
-+ if (nnode)
-+ break;
-+ }
-+ if (!nnode) {
-+ *hght -= 1;
-+ return parent;
-+ }
-+ for (h = *hght + 1; h < c->lpt_hght; h++) {
-+ found = 0;
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ if (nnode->nbranch[i].nnode) {
-+ found = 1;
-+ nnode = nnode->nbranch[i].nnode;
-+ *hght = h;
-+ break;
-+ }
-+ }
-+ if (!found)
-+ break;
-+ }
-+ return nnode;
-+}
-+
-+/**
-+ * ubifs_lpt_free - free resources owned by the LPT.
-+ * @c: UBIFS file-system description object
-+ * @wr_only: free only resources used for writing
-+ */
-+void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
-+{
-+ struct ubifs_nnode *nnode;
-+ int i, hght;
-+
-+ /* Free write-only things first */
-+
-+ free_obsolete_cnodes(c); /* Leftover from a failed commit */
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->ltab_cmt);
-+ kfree(c->lpt_buf);
-+#else
-+ vfree(c->ltab_cmt);
-+ vfree(c->lpt_buf);
-+#endif
-+ c->ltab_cmt = NULL;
-+ c->lpt_buf = NULL;
-+ kfree(c->lsave);
-+ c->lsave = NULL;
-+
-+ if (wr_only)
-+ return;
-+
-+ /* Now free the rest */
-+
-+ nnode = first_nnode(c, &hght);
-+ while (nnode) {
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++)
-+ kfree(nnode->nbranch[i].nnode);
-+ nnode = next_nnode(c, nnode, &hght);
-+ }
-+ for (i = 0; i < LPROPS_HEAP_CNT; i++)
-+ kfree(c->lpt_heap[i].arr);
-+ kfree(c->dirty_idx.arr);
-+ kfree(c->nroot);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->ltab);
-+#else
-+ vfree(c->ltab);
-+#endif
-+ kfree(c->lpt_nod_buf);
-+}
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+/**
-+ * dbg_is_all_ff - determine if a buffer contains only 0xff bytes.
-+ * @buf: buffer
-+ * @len: buffer length
-+ */
-+static int dbg_is_all_ff(uint8_t *buf, int len)
-+{
-+ int i;
-+
-+ for (i = 0; i < len; i++)
-+ if (buf[i] != 0xff)
-+ return 0;
-+ return 1;
-+}
-+
-+/**
-+ * dbg_is_nnode_dirty - determine if a nnode is dirty.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB number where nnode was written
-+ * @offs: offset where nnode was written
-+ */
-+static int dbg_is_nnode_dirty(struct ubifs_info *c, int lnum, int offs)
-+{
-+ struct ubifs_nnode *nnode;
-+ int hght;
-+
-+ /* Entire tree is in memory so first_nnode / next_nnode are ok */
-+ nnode = first_nnode(c, &hght);
-+ for (; nnode; nnode = next_nnode(c, nnode, &hght)) {
-+ struct ubifs_nbranch *branch;
-+
-+ cond_resched();
-+ if (nnode->parent) {
-+ branch = &nnode->parent->nbranch[nnode->iip];
-+ if (branch->lnum != lnum || branch->offs != offs)
-+ continue;
-+ if (test_bit(DIRTY_CNODE, &nnode->flags))
-+ return 1;
-+ return 0;
-+ } else {
-+ if (c->lpt_lnum != lnum || c->lpt_offs != offs)
-+ continue;
-+ if (test_bit(DIRTY_CNODE, &nnode->flags))
-+ return 1;
-+ return 0;
-+ }
-+ }
-+ return 1;
-+}
-+
-+/**
-+ * dbg_is_pnode_dirty - determine if a pnode is dirty.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB number where pnode was written
-+ * @offs: offset where pnode was written
-+ */
-+static int dbg_is_pnode_dirty(struct ubifs_info *c, int lnum, int offs)
-+{
-+ int i, cnt;
-+
-+ cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
-+ for (i = 0; i < cnt; i++) {
-+ struct ubifs_pnode *pnode;
-+ struct ubifs_nbranch *branch;
-+
-+ cond_resched();
-+ pnode = pnode_lookup(c, i);
-+ if (IS_ERR(pnode))
-+ return PTR_ERR(pnode);
-+ branch = &pnode->parent->nbranch[pnode->iip];
-+ if (branch->lnum != lnum || branch->offs != offs)
-+ continue;
-+ if (test_bit(DIRTY_CNODE, &pnode->flags))
-+ return 1;
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+/**
-+ * dbg_is_ltab_dirty - determine if a ltab node is dirty.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB number where ltab node was written
-+ * @offs: offset where ltab node was written
-+ */
-+static int dbg_is_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
-+{
-+ if (lnum != c->ltab_lnum || offs != c->ltab_offs)
-+ return 1;
-+ return (c->lpt_drty_flgs & LTAB_DIRTY) != 0;
-+}
-+
-+/**
-+ * dbg_is_lsave_dirty - determine if a lsave node is dirty.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB number where lsave node was written
-+ * @offs: offset where lsave node was written
-+ */
-+static int dbg_is_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
-+{
-+ if (lnum != c->lsave_lnum || offs != c->lsave_offs)
-+ return 1;
-+ return (c->lpt_drty_flgs & LSAVE_DIRTY) != 0;
-+}
-+
-+/**
-+ * dbg_is_node_dirty - determine if a node is dirty.
-+ * @c: the UBIFS file-system description object
-+ * @node_type: node type
-+ * @lnum: LEB number where node was written
-+ * @offs: offset where node was written
-+ */
-+static int dbg_is_node_dirty(struct ubifs_info *c, int node_type, int lnum,
-+ int offs)
-+{
-+ switch (node_type) {
-+ case UBIFS_LPT_NNODE:
-+ return dbg_is_nnode_dirty(c, lnum, offs);
-+ case UBIFS_LPT_PNODE:
-+ return dbg_is_pnode_dirty(c, lnum, offs);
-+ case UBIFS_LPT_LTAB:
-+ return dbg_is_ltab_dirty(c, lnum, offs);
-+ case UBIFS_LPT_LSAVE:
-+ return dbg_is_lsave_dirty(c, lnum, offs);
-+ }
-+ return 1;
-+}
-+
-+/**
-+ * dbg_check_ltab_lnum - check the ltab for a LPT LEB number.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB number where node was written
-+ * @offs: offset where node was written
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
-+{
-+ int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len;
-+ int ret;
-+ void *buf = c->dbg_buf;
-+
-+ dbg_lp("LEB %d", lnum);
-+ err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
-+ if (err) {
-+ dbg_msg("ubi_read failed, LEB %d, error %d", lnum, err);
-+ return err;
-+ }
-+ while (1) {
-+ if (!is_a_node(c, buf, len)) {
-+ int i, pad_len;
-+
-+ pad_len = get_pad_len(c, buf, len);
-+ if (pad_len) {
-+ buf += pad_len;
-+ len -= pad_len;
-+ dirty += pad_len;
-+ continue;
-+ }
-+ if (!dbg_is_all_ff(buf, len)) {
-+ dbg_msg("invalid empty space in LEB %d at %d",
-+ lnum, c->leb_size - len);
-+ err = -EINVAL;
-+ }
-+ i = lnum - c->lpt_first;
-+ if (len != c->ltab[i].free) {
-+ dbg_msg("invalid free space in LEB %d "
-+ "(free %d, expected %d)",
-+ lnum, len, c->ltab[i].free);
-+ err = -EINVAL;
-+ }
-+ if (dirty != c->ltab[i].dirty) {
-+ dbg_msg("invalid dirty space in LEB %d "
-+ "(dirty %d, expected %d)",
-+ lnum, dirty, c->ltab[i].dirty);
-+ err = -EINVAL;
-+ }
-+ return err;
-+ }
-+ node_type = get_lpt_node_type(c, buf, &node_num);
-+ node_len = get_lpt_node_len(c, node_type);
-+ ret = dbg_is_node_dirty(c, node_type, lnum, c->leb_size - len);
-+ if (ret == 1)
-+ dirty += node_len;
-+ buf += node_len;
-+ len -= node_len;
-+ }
-+}
-+
-+/**
-+ * dbg_check_ltab - check the free and dirty space in the ltab.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int dbg_check_ltab(struct ubifs_info *c)
-+{
-+ int lnum, err, i, cnt;
-+
-+ if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
-+ return 0;
-+
-+ /* Bring the entire tree into memory */
-+ cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
-+ for (i = 0; i < cnt; i++) {
-+ struct ubifs_pnode *pnode;
-+
-+ pnode = pnode_lookup(c, i);
-+ if (IS_ERR(pnode))
-+ return PTR_ERR(pnode);
-+ cond_resched();
-+ }
-+
-+ /* Check nodes */
-+ err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *)c->nroot, 0, 0);
-+ if (err)
-+ return err;
-+
-+ /* Check each LEB */
-+ for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) {
-+ err = dbg_check_ltab_lnum(c, lnum);
-+ if (err) {
-+ dbg_err("failed at LEB %d", lnum);
-+ return err;
-+ }
-+ }
-+
-+ dbg_lp("succeeded");
-+ return 0;
-+}
-+
-+#endif /* CONFIG_UBIFS_FS_DEBUG */
---- linux-2.6.24.7.old/fs/ubifs/master.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/master.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,387 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/* This file implements reading and writing the master node */
-+
-+#include "ubifs.h"
-+
-+/**
-+ * scan_for_master - search the valid master node.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function scans the master node LEBs and search for the latest master
-+ * node. Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+static int scan_for_master(struct ubifs_info *c)
-+{
-+ struct ubifs_scan_leb *sleb;
-+ struct ubifs_scan_node *snod;
-+ int lnum, offs = 0, nodes_cnt;
-+
-+ lnum = UBIFS_MST_LNUM;
-+
-+ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
-+ if (IS_ERR(sleb))
-+ return PTR_ERR(sleb);
-+ nodes_cnt = sleb->nodes_cnt;
-+ if (nodes_cnt > 0) {
-+ snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
-+ list);
-+ if (snod->type != UBIFS_MST_NODE)
-+ goto out;
-+ memcpy(c->mst_node, snod->node, snod->len);
-+ offs = snod->offs;
-+ }
-+ ubifs_scan_destroy(sleb);
-+
-+ lnum += 1;
-+
-+ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
-+ if (IS_ERR(sleb))
-+ return PTR_ERR(sleb);
-+ if (sleb->nodes_cnt != nodes_cnt)
-+ goto out;
-+ if (!sleb->nodes_cnt)
-+ goto out;
-+ snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
-+ if (snod->type != UBIFS_MST_NODE)
-+ goto out;
-+ if (snod->offs != offs)
-+ goto out;
-+ if (memcmp((void *)c->mst_node + UBIFS_CH_SZ,
-+ (void *)snod->node + UBIFS_CH_SZ,
-+ UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
-+ goto out;
-+ c->mst_offs = offs;
-+ ubifs_scan_destroy(sleb);
-+ return 0;
-+
-+out:
-+ ubifs_scan_destroy(sleb);
-+ return -EINVAL;
-+}
-+
-+/**
-+ * validate_master - validate master node.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function validates data which was read from master node. Returns zero
-+ * if the data is all right and %-EINVAL if not.
-+ */
-+static int validate_master(const struct ubifs_info *c)
-+{
-+ unsigned long long main_sz;
-+ int err;
-+
-+ if (c->max_sqnum >= SQNUM_WATERMARK) {
-+ err = 1;
-+ goto out;
-+ }
-+
-+ if (c->cmt_no >= c->max_sqnum) {
-+ err = 2;
-+ goto out;
-+ }
-+
-+ if (c->highest_inum >= INUM_WATERMARK) {
-+ err = 3;
-+ goto out;
-+ }
-+
-+ if (c->lhead_lnum < UBIFS_LOG_LNUM ||
-+ c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs ||
-+ c->lhead_offs < 0 || c->lhead_offs >= c->leb_size ||
-+ c->lhead_offs & (c->min_io_size - 1)) {
-+ err = 4;
-+ goto out;
-+ }
-+
-+ if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first ||
-+ c->zroot.offs >= c->leb_size || c->zroot.offs & 7) {
-+ err = 5;
-+ goto out;
-+ }
-+
-+ if (c->zroot.len < c->ranges[UBIFS_IDX_NODE].min_len ||
-+ c->zroot.len > c->ranges[UBIFS_IDX_NODE].max_len) {
-+ err = 6;
-+ goto out;
-+ }
-+
-+ if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) {
-+ err = 7;
-+ goto out;
-+ }
-+
-+ if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first ||
-+ c->ihead_offs % c->min_io_size || c->ihead_offs < 0 ||
-+ c->ihead_offs > c->leb_size || c->ihead_offs & 7) {
-+ err = 8;
-+ goto out;
-+ }
-+
-+ main_sz = c->main_lebs * (unsigned long long)c->leb_size;
-+ if (c->old_idx_sz & 7 || c->old_idx_sz >= main_sz) {
-+ err = 9;
-+ goto out;
-+ }
-+
-+ if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last ||
-+ c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) {
-+ err = 10;
-+ goto out;
-+ }
-+
-+ if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last ||
-+ c->nhead_offs < 0 || c->nhead_offs % c->min_io_size ||
-+ c->nhead_offs > c->leb_size) {
-+ err = 11;
-+ goto out;
-+ }
-+
-+ if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last ||
-+ c->ltab_offs < 0 ||
-+ c->ltab_offs + c->ltab_sz > c->leb_size) {
-+ err = 12;
-+ goto out;
-+ }
-+
-+ if (c->big_lpt && (c->lsave_lnum < c->lpt_first ||
-+ c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 ||
-+ c->lsave_offs + c->lsave_sz > c->leb_size)) {
-+ err = 13;
-+ goto out;
-+ }
-+
-+ if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) {
-+ err = 14;
-+ goto out;
-+ }
-+
-+ if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) {
-+ err = 15;
-+ goto out;
-+ }
-+
-+ if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) {
-+ err = 16;
-+ goto out;
-+ }
-+
-+ if (c->lst.total_free < 0 || c->lst.total_free > main_sz ||
-+ c->lst.total_free & 7) {
-+ err = 17;
-+ goto out;
-+ }
-+
-+ if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) {
-+ err = 18;
-+ goto out;
-+ }
-+
-+ if (c->lst.total_used < 0 || (c->lst.total_used & 7)) {
-+ err = 19;
-+ goto out;
-+ }
-+
-+ if (c->lst.total_free + c->lst.total_dirty +
-+ c->lst.total_used > main_sz) {
-+ err = 20;
-+ goto out;
-+ }
-+
-+ if (c->lst.total_dead + c->lst.total_dark +
-+ c->lst.total_used + c->old_idx_sz > main_sz) {
-+ err = 21;
-+ goto out;
-+ }
-+
-+ if (c->lst.total_dead < 0 ||
-+ c->lst.total_dead > c->lst.total_free + c->lst.total_dirty ||
-+ c->lst.total_dead & 7) {
-+ err = 22;
-+ goto out;
-+ }
-+
-+ if (c->lst.total_dark < 0 ||
-+ c->lst.total_dark > c->lst.total_free + c->lst.total_dirty ||
-+ c->lst.total_dark & 7) {
-+ err = 23;
-+ goto out;
-+ }
-+
-+ return 0;
-+
-+out:
-+ ubifs_err("bad master node at offset %d error %d", c->mst_offs, err);
-+ dbg_dump_node(c, c->mst_node);
-+ return -EINVAL;
-+}
-+
-+/**
-+ * ubifs_read_master - read master node.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function finds and reads the master node during file-system mount. If
-+ * the flash is empty, it creates default master node as well. Returns zero in
-+ * case of success and a negative error code in case of failure.
-+ */
-+int ubifs_read_master(struct ubifs_info *c)
-+{
-+ int err, old_leb_cnt;
-+
-+ c->mst_node = kzalloc(c->mst_node_alsz, GFP_KERNEL);
-+ if (!c->mst_node)
-+ return -ENOMEM;
-+
-+ err = scan_for_master(c);
-+ if (err) {
-+ err = ubifs_recover_master_node(c);
-+ if (err)
-+ /*
-+ * Note, we do not free 'c->mst_node' here because the
-+ * unmount routine will take care of this.
-+ */
-+ return err;
-+ }
-+
-+ /* Make sure that the recovery flag is clear */
-+ c->mst_node->flags &= cpu_to_le32(~UBIFS_MST_RCVRY);
-+
-+ c->max_sqnum = le64_to_cpu(c->mst_node->ch.sqnum);
-+ c->highest_inum = le64_to_cpu(c->mst_node->highest_inum);
-+ c->cmt_no = le64_to_cpu(c->mst_node->cmt_no);
-+ c->zroot.lnum = le32_to_cpu(c->mst_node->root_lnum);
-+ c->zroot.offs = le32_to_cpu(c->mst_node->root_offs);
-+ c->zroot.len = le32_to_cpu(c->mst_node->root_len);
-+ c->lhead_lnum = le32_to_cpu(c->mst_node->log_lnum);
-+ c->gc_lnum = le32_to_cpu(c->mst_node->gc_lnum);
-+ c->ihead_lnum = le32_to_cpu(c->mst_node->ihead_lnum);
-+ c->ihead_offs = le32_to_cpu(c->mst_node->ihead_offs);
-+ c->old_idx_sz = le64_to_cpu(c->mst_node->index_size);
-+ c->lpt_lnum = le32_to_cpu(c->mst_node->lpt_lnum);
-+ c->lpt_offs = le32_to_cpu(c->mst_node->lpt_offs);
-+ c->nhead_lnum = le32_to_cpu(c->mst_node->nhead_lnum);
-+ c->nhead_offs = le32_to_cpu(c->mst_node->nhead_offs);
-+ c->ltab_lnum = le32_to_cpu(c->mst_node->ltab_lnum);
-+ c->ltab_offs = le32_to_cpu(c->mst_node->ltab_offs);
-+ c->lsave_lnum = le32_to_cpu(c->mst_node->lsave_lnum);
-+ c->lsave_offs = le32_to_cpu(c->mst_node->lsave_offs);
-+ c->lscan_lnum = le32_to_cpu(c->mst_node->lscan_lnum);
-+ c->lst.empty_lebs = le32_to_cpu(c->mst_node->empty_lebs);
-+ c->lst.idx_lebs = le32_to_cpu(c->mst_node->idx_lebs);
-+ old_leb_cnt = le32_to_cpu(c->mst_node->leb_cnt);
-+ c->lst.total_free = le64_to_cpu(c->mst_node->total_free);
-+ c->lst.total_dirty = le64_to_cpu(c->mst_node->total_dirty);
-+ c->lst.total_used = le64_to_cpu(c->mst_node->total_used);
-+ c->lst.total_dead = le64_to_cpu(c->mst_node->total_dead);
-+ c->lst.total_dark = le64_to_cpu(c->mst_node->total_dark);
-+
-+ c->calc_idx_sz = c->old_idx_sz;
-+
-+ if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS))
-+ c->no_orphs = 1;
-+
-+ if (old_leb_cnt != c->leb_cnt) {
-+ /* The file system has been resized */
-+ int growth = c->leb_cnt - old_leb_cnt;
-+
-+ if (c->leb_cnt < old_leb_cnt ||
-+ c->leb_cnt < UBIFS_MIN_LEB_CNT) {
-+ ubifs_err("bad leb_cnt on master node");
-+ dbg_dump_node(c, c->mst_node);
-+ return -EINVAL;
-+ }
-+
-+ dbg_mnt("Auto resizing (master) from %d LEBs to %d LEBs",
-+ old_leb_cnt, c->leb_cnt);
-+ c->lst.empty_lebs += growth;
-+ c->lst.total_free += growth * (long long)c->leb_size;
-+ c->lst.total_dark += growth * (long long)c->dark_wm;
-+
-+ /*
-+ * Reflect changes back onto the master node. N.B. the master
-+ * node gets written immediately whenever mounting (or
-+ * remounting) in read-write mode, so we do not need to write it
-+ * here.
-+ */
-+ c->mst_node->leb_cnt = cpu_to_le32(c->leb_cnt);
-+ c->mst_node->empty_lebs = cpu_to_le32(c->lst.empty_lebs);
-+ c->mst_node->total_free = cpu_to_le64(c->lst.total_free);
-+ c->mst_node->total_dark = cpu_to_le64(c->lst.total_dark);
-+ }
-+
-+ err = validate_master(c);
-+ if (err)
-+ return err;
-+
-+ err = dbg_old_index_check_init(c, &c->zroot);
-+
-+ return err;
-+}
-+
-+/**
-+ * ubifs_write_master - write master node.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function writes the master node. The caller has to take the
-+ * @c->mst_mutex lock before calling this function. Returns zero in case of
-+ * success and a negative error code in case of failure. The master node is
-+ * written twice to enable recovery.
-+ */
-+int ubifs_write_master(struct ubifs_info *c)
-+{
-+ int err, lnum, offs, len;
-+
-+ if (c->ro_media)
-+ return -EINVAL;
-+
-+ lnum = UBIFS_MST_LNUM;
-+ offs = c->mst_offs + c->mst_node_alsz;
-+ len = UBIFS_MST_NODE_SZ;
-+
-+ if (offs + UBIFS_MST_NODE_SZ > c->leb_size) {
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ offs = 0;
-+ }
-+
-+ c->mst_offs = offs;
-+ c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
-+
-+ err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
-+ if (err)
-+ return err;
-+
-+ lnum += 1;
-+
-+ if (offs == 0) {
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ }
-+ err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
-+
-+ return err;
-+}
---- linux-2.6.24.7.old/fs/ubifs/misc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/misc.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,310 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file contains miscellaneous helper functions.
-+ */
-+
-+#ifndef __UBIFS_MISC_H__
-+#define __UBIFS_MISC_H__
-+
-+/**
-+ * ubifs_zn_dirty - check if znode is dirty.
-+ * @znode: znode to check
-+ *
-+ * This helper function returns %1 if @znode is dirty and %0 otherwise.
-+ */
-+static inline int ubifs_zn_dirty(const struct ubifs_znode *znode)
-+{
-+ return !!test_bit(DIRTY_ZNODE, &znode->flags);
-+}
-+
-+/**
-+ * ubifs_wake_up_bgt - wake up background thread.
-+ * @c: UBIFS file-system description object
-+ */
-+static inline void ubifs_wake_up_bgt(struct ubifs_info *c)
-+{
-+ if (c->bgt && !c->need_bgt) {
-+ c->need_bgt = 1;
-+ wake_up_process(c->bgt);
-+ }
-+}
-+
-+/**
-+ * ubifs_tnc_find_child - find next child in znode.
-+ * @znode: znode to search at
-+ * @start: the zbranch index to start at
-+ *
-+ * This helper function looks for znode child starting at index @start. Returns
-+ * the child or %NULL if no children were found.
-+ */
-+static inline struct ubifs_znode *
-+ubifs_tnc_find_child(struct ubifs_znode *znode, int start)
-+{
-+ while (start < znode->child_cnt) {
-+ if (znode->zbranch[start].znode)
-+ return znode->zbranch[start].znode;
-+ start += 1;
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * ubifs_inode - get UBIFS inode information by VFS 'struct inode' object.
-+ * @inode: the VFS 'struct inode' pointer
-+ */
-+static inline struct ubifs_inode *ubifs_inode(const struct inode *inode)
-+{
-+ return container_of(inode, struct ubifs_inode, vfs_inode);
-+}
-+
-+/**
-+ * ubifs_ro_mode - switch UBIFS to read read-only mode.
-+ * @c: UBIFS file-system description object
-+ * @err: error code which is the reason of switching to R/O mode
-+ */
-+static inline void ubifs_ro_mode(struct ubifs_info *c, int err)
-+{
-+ if (!c->ro_media) {
-+ c->ro_media = 1;
-+ ubifs_warn("switched to read-only mode, error %d", err);
-+ dbg_dump_stack();
-+ }
-+}
-+
-+/**
-+ * ubifs_compr_present - check if compressor was compiled in.
-+ * @compr_type: compressor type to check
-+ *
-+ * This function returns %1 of compressor of type @compr_type is present, and
-+ * %0 if not.
-+ */
-+static inline int ubifs_compr_present(int compr_type)
-+{
-+ ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
-+ return !!ubifs_compressors[compr_type]->capi_name;
-+}
-+
-+/**
-+ * ubifs_compr_name - get compressor name string by its type.
-+ * @compr_type: compressor type
-+ *
-+ * This function returns compressor type string.
-+ */
-+static inline const char *ubifs_compr_name(int compr_type)
-+{
-+ ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
-+ return ubifs_compressors[compr_type]->name;
-+}
-+
-+/**
-+ * ubifs_wbuf_sync - synchronize write-buffer.
-+ * @wbuf: write-buffer to synchronize
-+ *
-+ * This is the same as as 'ubifs_wbuf_sync_nolock()' but it does not assume
-+ * that the write-buffer is already locked.
-+ */
-+static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf)
-+{
-+ int err;
-+
-+ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
-+ err = ubifs_wbuf_sync_nolock(wbuf);
-+ mutex_unlock(&wbuf->io_mutex);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_leb_unmap - unmap an LEB.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number to unmap
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
-+{
-+ int err;
-+
-+ err = ubi_leb_unmap(c->ubi, lnum);
-+ if (err) {
-+ ubifs_err("unmap LEB %d failed, error %d", lnum, err);
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_leb_write - write to a LEB.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number to write
-+ * @buf: buffer to write from
-+ * @offs: offset within LEB to write to
-+ * @len: length to write
-+ * @dtype: data type
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
-+ const void *buf, int offs, int len, int dtype)
-+{
-+ int err;
-+
-+ err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
-+ if (err) {
-+ ubifs_err("writing %d bytes at %d:%d, error %d",
-+ len, lnum, offs, err);
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_encode_dev - encode device node IDs.
-+ * @dev: UBIFS device node information
-+ * @rdev: device IDs to encode
-+ *
-+ * This is a helper function which encodes major/minor numbers of a device node
-+ * into UBIFS device node description. We use standard Linux "new" and "huge"
-+ * encodings.
-+ */
-+static inline int ubifs_encode_dev(union ubifs_dev_desc *dev, dev_t rdev)
-+{
-+ if (new_valid_dev(rdev)) {
-+ dev->new = cpu_to_le32(new_encode_dev(rdev));
-+ return sizeof(dev->new);
-+ } else {
-+ dev->huge = cpu_to_le64(huge_encode_dev(rdev));
-+ return sizeof(dev->huge);
-+ }
-+}
-+
-+/**
-+ * ubifs_add_dirt - add dirty space to LEB properties.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB to add dirty space for
-+ * @dirty: dirty space to add
-+ *
-+ * This is a helper function which increased amount of dirty LEB space. Returns
-+ * zero in case of success and a negative error code in case of failure.
-+ */
-+static inline int ubifs_add_dirt(struct ubifs_info *c, int lnum, int dirty)
-+{
-+ return ubifs_update_one_lp(c, lnum, -1, dirty, 0, 0);
-+}
-+
-+/**
-+ * ubifs_return_leb - return LEB to lprops.
-+ * @c: the UBIFS file-system description object
-+ * @lnum: LEB to return
-+ *
-+ * This helper function cleans the "taken" flag of a logical eraseblock in the
-+ * lprops. Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+static inline int ubifs_return_leb(struct ubifs_info *c, int lnum)
-+{
-+ return ubifs_change_one_lp(c, lnum, -1, -1, 0, LPROPS_TAKEN, 0);
-+}
-+
-+/**
-+ * ubifs_idx_node_sz - return index node size.
-+ * @c: the UBIFS file-system description object
-+ * @child_cnt: number of children of this index node
-+ */
-+static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt)
-+{
-+ return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt;
-+}
-+
-+/**
-+ * ubifs_idx_branch - return pointer to an index branch.
-+ * @c: the UBIFS file-system description object
-+ * @idx: index node
-+ * @bnum: branch number
-+ */
-+static inline
-+struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c,
-+ const struct ubifs_idx_node *idx,
-+ int bnum)
-+{
-+ return (struct ubifs_branch *)((void *)idx->branches +
-+ (UBIFS_BRANCH_SZ + c->key_len) * bnum);
-+}
-+
-+/**
-+ * ubifs_idx_key - return pointer to an index key.
-+ * @c: the UBIFS file-system description object
-+ * @idx: index node
-+ */
-+static inline void *ubifs_idx_key(const struct ubifs_info *c,
-+ const struct ubifs_idx_node *idx)
-+{
-+ return (void *)((struct ubifs_branch *)idx->branches)->key;
-+}
-+
-+/**
-+ * ubifs_reported_space - calculate reported free space.
-+ * @c: the UBIFS file-system description object
-+ * @free: amount of free space
-+ *
-+ * This function calculates amount of free space which will be reported to
-+ * user-space. User-space application tend to expect that if the file-system
-+ * (e.g., via the 'statfs()' call) reports that it has N bytes available, they
-+ * are able to write a file of size N. UBIFS attaches node headers to each data
-+ * node and it has to write indexind nodes as well. This introduces additional
-+ * overhead, and UBIFS it has to report sligtly less free space to meet the
-+ * above expectetion.
-+ *
-+ * This function assumes free space is made up of uncompressed data nodes and
-+ * full index nodes (one per data node, doubled because we always allow enough
-+ * space to write the index twice).
-+ *
-+ * Note, the calculation is pessimistic, which means that most of the time
-+ * UBIFS reports less space than it actually has.
-+ */
-+static inline long long ubifs_reported_space(const struct ubifs_info *c,
-+ uint64_t free)
-+{
-+ int divisor, factor;
-+
-+ divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz << 1);
-+ factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ;
-+ do_div(free, divisor);
-+
-+ return free * factor;
-+}
-+
-+/**
-+ * ubifs_current_time - round current time to time granularity.
-+ * @inode: inode
-+ */
-+static inline struct timespec ubifs_current_time(struct inode *inode)
-+{
-+ return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ?
-+ current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
-+}
-+
-+#endif /* __UBIFS_MISC_H__ */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/config 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/config 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,11 @@
-+[core]
-+ repositoryformatversion = 0
-+ filemode = true
-+ bare = false
-+ logallrefupdates = true
-+[remote "origin"]
-+ url = git://git.infradead.org/~dedekind/mkfs.ubifs.git
-+ fetch = +refs/heads/*:refs/remotes/origin/*
-+[branch "master"]
-+ remote = origin
-+ merge = refs/heads/master
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/description 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/description 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1 @@
-+Unnamed repository; edit this file to name it for gitweb.
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/head 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/head 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1 @@
-+ref: refs/heads/master
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/applypatch-msg 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/applypatch-msg 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,15 @@
-+#!/bin/sh
-+#
-+# An example hook script to check the commit log message taken by
-+# applypatch from an e-mail message.
-+#
-+# The hook should exit with non-zero status after issuing an
-+# appropriate message if it wants to stop the commit. The hook is
-+# allowed to edit the commit message file.
-+#
-+# To enable this hook, make this file executable.
-+
-+. git-sh-setup
-+test -x "$GIT_DIR/hooks/commit-msg" &&
-+ exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
-+:
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/commit-msg 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/commit-msg 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,24 @@
-+#!/bin/sh
-+#
-+# An example hook script to check the commit log message.
-+# Called by git-commit with one argument, the name of the file
-+# that has the commit message. The hook should exit with non-zero
-+# status after issuing an appropriate message if it wants to stop the
-+# commit. The hook is allowed to edit the commit message file.
-+#
-+# To enable this hook, make this file executable.
-+
-+# Uncomment the below to add a Signed-off-by line to the message.
-+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
-+# hook is more suited to it.
-+#
-+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
-+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
-+
-+# This example catches duplicate Signed-off-by lines.
-+
-+test "" = "$(grep '^Signed-off-by: ' "$1" |
-+ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
-+ echo >&2 Duplicate Signed-off-by lines.
-+ exit 1
-+}
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/post-commit 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/post-commit 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,8 @@
-+#!/bin/sh
-+#
-+# An example hook script that is called after a successful
-+# commit is made.
-+#
-+# To enable this hook, make this file executable.
-+
-+: Nothing
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/post-receive 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/post-receive 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,16 @@
-+#!/bin/sh
-+#
-+# An example hook script for the post-receive event
-+#
-+# This script is run after receive-pack has accepted a pack and the
-+# repository has been updated. It is passed arguments in through stdin
-+# in the form
-+#
-+# For example:
-+# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
-+#
-+# see contrib/hooks/ for an sample, or uncomment the next line (on debian)
-+#
-+
-+
-+#. /usr/share/doc/git-core/contrib/hooks/post-receive-email
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/post-update 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/post-update 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,8 @@
-+#!/bin/sh
-+#
-+# An example hook script to prepare a packed repository for use over
-+# dumb transports.
-+#
-+# To enable this hook, make this file executable by "chmod +x post-update".
-+
-+exec git-update-server-info
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/pre-applypatch 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/pre-applypatch 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,14 @@
-+#!/bin/sh
-+#
-+# An example hook script to verify what is about to be committed
-+# by applypatch from an e-mail message.
-+#
-+# The hook should exit with non-zero status after issuing an
-+# appropriate message if it wants to stop the commit.
-+#
-+# To enable this hook, make this file executable.
-+
-+. git-sh-setup
-+test -x "$GIT_DIR/hooks/pre-commit" &&
-+ exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
-+:
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/pre-commit 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/pre-commit 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,70 @@
-+#!/bin/sh
-+#
-+# An example hook script to verify what is about to be committed.
-+# Called by git-commit with no arguments. The hook should
-+# exit with non-zero status after issuing an appropriate message if
-+# it wants to stop the commit.
-+#
-+# To enable this hook, make this file executable.
-+
-+# This is slightly modified from Andrew Morton's Perfect Patch.
-+# Lines you introduce should not have trailing whitespace.
-+# Also check for an indentation that has SP before a TAB.
-+
-+if git-rev-parse --verify HEAD 2>/dev/null
-+then
-+ git-diff-index -p -M --cached HEAD --
-+else
-+ # NEEDSWORK: we should produce a diff with an empty tree here
-+ # if we want to do the same verification for the initial import.
-+ :
-+fi |
-+perl -e '
-+ my $found_bad = 0;
-+ my $filename;
-+ my $reported_filename = "";
-+ my $lineno;
-+ sub bad_line {
-+ my ($why, $line) = @_;
-+ if (!$found_bad) {
-+ print STDERR "*\n";
-+ print STDERR "* You have some suspicious patch lines:\n";
-+ print STDERR "*\n";
-+ $found_bad = 1;
-+ }
-+ if ($reported_filename ne $filename) {
-+ print STDERR "* In $filename\n";
-+ $reported_filename = $filename;
-+ }
-+ print STDERR "* $why (line $lineno)\n";
-+ print STDERR "$filename:$lineno:$line\n";
-+ }
-+ while (<>) {
-+ if (m|^diff --git a/(.*) b/\1$|) {
-+ $filename = $1;
-+ next;
-+ }
-+ if (/^@@ -\S+ \+(\d+)/) {
-+ $lineno = $1 - 1;
-+ next;
-+ }
-+ if (/^ /) {
-+ $lineno++;
-+ next;
-+ }
-+ if (s/^\+//) {
-+ $lineno++;
-+ chomp;
-+ if (/\s$/) {
-+ bad_line("trailing whitespace", $_);
-+ }
-+ if (/^\s* \t/) {
-+ bad_line("indent SP followed by a TAB", $_);
-+ }
-+ if (/^([<>])\1{6} |^={7}$/) {
-+ bad_line("unresolved merge conflict", $_);
-+ }
-+ }
-+ }
-+ exit($found_bad);
-+'
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/pre-rebase 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/pre-rebase 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,150 @@
-+#!/bin/sh
-+#
-+# Copyright (c) 2006 Junio C Hamano
-+#
-+
-+publish=next
-+basebranch="$1"
-+if test "$#" = 2
-+then
-+ topic="refs/heads/$2"
-+else
-+ topic=`git symbolic-ref HEAD`
-+fi
-+
-+case "$basebranch,$topic" in
-+master,refs/heads/??/*)
-+ ;;
-+*)
-+ exit 0 ;# we do not interrupt others.
-+ ;;
-+esac
-+
-+# Now we are dealing with a topic branch being rebased
-+# on top of master. Is it OK to rebase it?
-+
-+# Is topic fully merged to master?
-+not_in_master=`git-rev-list --pretty=oneline ^master "$topic"`
-+if test -z "$not_in_master"
-+then
-+ echo >&2 "$topic is fully merged to master; better remove it."
-+ exit 1 ;# we could allow it, but there is no point.
-+fi
-+
-+# Is topic ever merged to next? If so you should not be rebasing it.
-+only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort`
-+only_next_2=`git-rev-list ^master ${publish} | sort`
-+if test "$only_next_1" = "$only_next_2"
-+then
-+ not_in_topic=`git-rev-list "^$topic" master`
-+ if test -z "$not_in_topic"
-+ then
-+ echo >&2 "$topic is already up-to-date with master"
-+ exit 1 ;# we could allow it, but there is no point.
-+ else
-+ exit 0
-+ fi
-+else
-+ not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"`
-+ perl -e '
-+ my $topic = $ARGV[0];
-+ my $msg = "* $topic has commits already merged to public branch:\n";
-+ my (%not_in_next) = map {
-+ /^([0-9a-f]+) /;
-+ ($1 => 1);
-+ } split(/\n/, $ARGV[1]);
-+ for my $elem (map {
-+ /^([0-9a-f]+) (.*)$/;
-+ [$1 => $2];
-+ } split(/\n/, $ARGV[2])) {
-+ if (!exists $not_in_next{$elem->[0]}) {
-+ if ($msg) {
-+ print STDERR $msg;
-+ undef $msg;
-+ }
-+ print STDERR " $elem->[1]\n";
-+ }
-+ }
-+ ' "$topic" "$not_in_next" "$not_in_master"
-+ exit 1
-+fi
-+
-+exit 0
-+
-+################################################################
-+
-+This sample hook safeguards topic branches that have been
-+published from being rewound.
-+
-+The workflow assumed here is:
-+
-+ * Once a topic branch forks from "master", "master" is never
-+ merged into it again (either directly or indirectly).
-+
-+ * Once a topic branch is fully cooked and merged into "master",
-+ it is deleted. If you need to build on top of it to correct
-+ earlier mistakes, a new topic branch is created by forking at
-+ the tip of the "master". This is not strictly necessary, but
-+ it makes it easier to keep your history simple.
-+
-+ * Whenever you need to test or publish your changes to topic
-+ branches, merge them into "next" branch.
-+
-+The script, being an example, hardcodes the publish branch name
-+to be "next", but it is trivial to make it configurable via
-+$GIT_DIR/config mechanism.
-+
-+With this workflow, you would want to know:
-+
-+(1) ... if a topic branch has ever been merged to "next". Young
-+ topic branches can have stupid mistakes you would rather
-+ clean up before publishing, and things that have not been
-+ merged into other branches can be easily rebased without
-+ affecting other people. But once it is published, you would
-+ not want to rewind it.
-+
-+(2) ... if a topic branch has been fully merged to "master".
-+ Then you can delete it. More importantly, you should not
-+ build on top of it -- other people may already want to
-+ change things related to the topic as patches against your
-+ "master", so if you need further changes, it is better to
-+ fork the topic (perhaps with the same name) afresh from the
-+ tip of "master".
-+
-+Let's look at this example:
-+
-+ o---o---o---o---o---o---o---o---o---o "next"
-+ / / / /
-+ / a---a---b A / /
-+ / / / /
-+ / / c---c---c---c B /
-+ / / / \ /
-+ / / / b---b C \ /
-+ / / / / \ /
-+ ---o---o---o---o---o---o---o---o---o---o---o "master"
-+
-+
-+A, B and C are topic branches.
-+
-+ * A has one fix since it was merged up to "next".
-+
-+ * B has finished. It has been fully merged up to "master" and "next",
-+ and is ready to be deleted.
-+
-+ * C has not merged to "next" at all.
-+
-+We would want to allow C to be rebased, refuse A, and encourage
-+B to be deleted.
-+
-+To compute (1):
-+
-+ git-rev-list ^master ^topic next
-+ git-rev-list ^master next
-+
-+ if these match, topic has not merged in next at all.
-+
-+To compute (2):
-+
-+ git-rev-list master..topic
-+
-+ if this is empty, it is fully merged to "master".
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/prepare-commit-msg 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/prepare-commit-msg 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,36 @@
-+#!/bin/sh
-+#
-+# An example hook script to prepare the commit log message.
-+# Called by git-commit with the name of the file that has the
-+# commit message, followed by the description of the commit
-+# message's source. The hook's purpose is to edit the commit
-+# message file. If the hook fails with a non-zero status,
-+# the commit is aborted.
-+#
-+# To enable this hook, make this file executable.
-+
-+# This hook includes three examples. The first comments out the
-+# "Conflicts:" part of a merge commit.
-+#
-+# The second includes the output of "git diff --name-status -r"
-+# into the message, just before the "git status" output. It is
-+# commented because it doesn't cope with --amend or with squashed
-+# commits.
-+#
-+# The third example adds a Signed-off-by line to the message, that can
-+# still be edited. This is rarely a good idea.
-+
-+case "$2 $3" in
-+ merge)
-+ sed -i '/^Conflicts:/,/#/!b;s/^/# &/;s/^# #/#/' "$1" ;;
-+
-+# ""|template)
-+# perl -i -pe '
-+# print "\n" . `git diff --cached --name-status -r`
-+# if /^#/ && $first++ == 0' "$1" ;;
-+
-+ *) ;;
-+esac
-+
-+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
-+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/update 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/update 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,107 @@
-+#!/bin/sh
-+#
-+# An example hook script to blocks unannotated tags from entering.
-+# Called by git-receive-pack with arguments: refname sha1-old sha1-new
-+#
-+# To enable this hook, make this file executable by "chmod +x update".
-+#
-+# Config
-+# ------
-+# hooks.allowunannotated
-+# This boolean sets whether unannotated tags will be allowed into the
-+# repository. By default they won't be.
-+# hooks.allowdeletetag
-+# This boolean sets whether deleting tags will be allowed in the
-+# repository. By default they won't be.
-+# hooks.allowdeletebranch
-+# This boolean sets whether deleting branches will be allowed in the
-+# repository. By default they won't be.
-+#
-+
-+# --- Command line
-+refname="$1"
-+oldrev="$2"
-+newrev="$3"
-+
-+# --- Safety check
-+if [ -z "$GIT_DIR" ]; then
-+ echo "Don't run this script from the command line." >&2
-+ echo " (if you want, you could supply GIT_DIR then run" >&2
-+ echo " $0 [ )" >&2
-+ exit 1
-+fi
-+
-+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
-+ echo "Usage: $0 ][ " >&2
-+ exit 1
-+fi
-+
-+# --- Config
-+allowunannotated=$(git config --bool hooks.allowunannotated)
-+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
-+allowdeletetag=$(git config --bool hooks.allowdeletetag)
-+
-+# check for no description
-+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
-+if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb." ]; then
-+ echo "*** Project description file hasn't been set" >&2
-+ exit 1
-+fi
-+
-+# --- Check types
-+# if $newrev is 0000...0000, it's a commit to delete a ref.
-+if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then
-+ newrev_type=delete
-+else
-+ newrev_type=$(git-cat-file -t $newrev)
-+fi
-+
-+case "$refname","$newrev_type" in
-+ refs/tags/*,commit)
-+ # un-annotated tag
-+ short_refname=${refname##refs/tags/}
-+ if [ "$allowunannotated" != "true" ]; then
-+ echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
-+ echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
-+ exit 1
-+ fi
-+ ;;
-+ refs/tags/*,delete)
-+ # delete tag
-+ if [ "$allowdeletetag" != "true" ]; then
-+ echo "*** Deleting a tag is not allowed in this repository" >&2
-+ exit 1
-+ fi
-+ ;;
-+ refs/tags/*,tag)
-+ # annotated tag
-+ ;;
-+ refs/heads/*,commit)
-+ # branch
-+ ;;
-+ refs/heads/*,delete)
-+ # delete branch
-+ if [ "$allowdeletebranch" != "true" ]; then
-+ echo "*** Deleting a branch is not allowed in this repository" >&2
-+ exit 1
-+ fi
-+ ;;
-+ refs/remotes/*,commit)
-+ # tracking branch
-+ ;;
-+ refs/remotes/*,delete)
-+ # delete tracking branch
-+ if [ "$allowdeletebranch" != "true" ]; then
-+ echo "*** Deleting a tracking branch is not allowed in this repository" >&2
-+ exit 1
-+ fi
-+ ;;
-+ *)
-+ # Anything else (is there anything else?)
-+ echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
-+ exit 1
-+ ;;
-+esac
-+
-+# --- Finished
-+exit 0
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/info/exclude 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/info/exclude 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,6 @@
-+# git-ls-files --others --exclude-from=.git/info/exclude
-+# Lines that start with '#' are comments.
-+# For a project mostly in C, the following would be a good set of
-+# exclude patterns (uncomment them if you want to use them):
-+# *.[oa]
-+# *~
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/logs/head 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/logs/head 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1 @@
-+0000000000000000000000000000000000000000 549a9c94e7919c86fc260dd534fd908343348228 root 1208919344 -0400
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/logs/refs/heads/master 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/logs/refs/heads/master 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1 @@
-+0000000000000000000000000000000000000000 549a9c94e7919c86fc260dd534fd908343348228 root 1208919344 -0400
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/logs/refs/remotes/origin/master 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/logs/refs/remotes/origin/master 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1 @@
-+0000000000000000000000000000000000000000 549a9c94e7919c86fc260dd534fd908343348228 root 1208919344 -0400 clone: from git://git.infradead.org/~dedekind/mkfs.ubifs.git
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/objects/pack/pack-b57e0a817d6303b8f24187e61200a9f06e6974ce.keep 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/objects/pack/pack-b57e0a817d6303b8f24187e61200a9f06e6974ce.keep 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1 @@
-+fetch-pack 29608 on localhost.localdomain
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/refs/heads/master 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/refs/heads/master 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1 @@
-+549a9c94e7919c86fc260dd534fd908343348228
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/head 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/head 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1 @@
-+ref: refs/remotes/origin/master
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/master 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/master 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1 @@
-+549a9c94e7919c86fc260dd534fd908343348228
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.gitignore 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.gitignore 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,5 @@
-+*.o
-+mkfs.ubifs
-+patches
-+cscope.out
-+.pc
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/Makefile 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,24 @@
-+ifeq ($(origin CC),default)
-+CC = gcc
-+endif
-+
-+ALL_SOURCES=*.[ch] hashtable/*.[ch]
-+
-+CFLAGS := $(CFLAGS) -Wall -O2 -I./lzo/include -I../../../include
-+
-+LDFLAGS := $(LDFLAGS) -lz -llzo2 -lm -L./lzo/lib
-+
-+TARGETS = mkfs.ubifs
-+
-+all: $(TARGETS)
-+
-+mkfs.ubifs: crc16.o crc32.o lpt.o compr.o hashtable/hashtable.o \
-+ hashtable/hashtable_itr.o devtable.o
-+
-+clean:
-+ rm -f *.o $(TARGETS) cscope.*
-+
-+cscope:
-+ @echo $(ALL_SOURCES) > cscope.files
-+ @cscope -bR
-+ @rm cscope.files
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/compr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/compr.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,154 @@
-+/*
-+ * Copyright (C) 2008 Nokia Corporation.
-+ * Copyright (C) 2008 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy
-+ * Adrian Hunter
-+ * Zoltan Sogor
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "compr.h"
-+#include "ubifs-media.h"
-+
-+static void *lzo_mem;
-+static unsigned long long errcnt = 0;
-+
-+#define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
-+#define DEFLATE_DEF_WINBITS 11
-+#define DEFLATE_DEF_MEMLEVEL 8
-+
-+static int zlib_deflate(void *in_buf, size_t in_len, void *out_buf,
-+ size_t *out_len)
-+{
-+ z_stream strm;
-+
-+ strm.zalloc = NULL;
-+ strm.zfree = NULL;
-+
-+ /*
-+ * Match exactly the zlib parameters used by the linux kernel crypto
-+ * API.
-+ */
-+ if (deflateInit2(&strm, DEFLATE_DEF_LEVEL, Z_DEFLATED,
-+ -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
-+ Z_DEFAULT_STRATEGY)) {
-+ errcnt += 1;
-+ return -1;
-+ }
-+
-+ strm.next_in = in_buf;
-+ strm.avail_in = in_len;
-+ strm.total_in = 0;
-+
-+ strm.next_out = out_buf;
-+ strm.avail_out = *out_len;
-+ strm.total_out = 0;
-+
-+ if (deflate(&strm, Z_FINISH) != Z_STREAM_END) {
-+ deflateEnd(&strm);
-+ errcnt += 1;
-+ return -1;
-+ }
-+
-+ if (deflateEnd(&strm) != Z_OK) {
-+ errcnt += 1;
-+ return -1;
-+ }
-+
-+ *out_len = strm.total_out;
-+
-+ return 0;
-+}
-+
-+static int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
-+ size_t *out_len)
-+{
-+ lzo_uint len;
-+ int ret;
-+
-+ len = *out_len;
-+ ret = lzo1x_999_compress(in_buf, in_len, out_buf, &len, lzo_mem);
-+ *out_len = len;
-+
-+ if (ret != LZO_E_OK) {
-+ errcnt += 1;
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int no_compress(void *in_buf, size_t in_len, void *out_buf,
-+ size_t *out_len)
-+{
-+ memcpy(out_buf, in_buf, in_len);
-+ *out_len = in_len;
-+ return 0;
-+}
-+
-+int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
-+ int type)
-+{
-+ int ret = 1;
-+
-+ if (in_len < UBIFS_MIN_COMPR_LEN) {
-+ no_compress(in_buf, in_len, out_buf, out_len);
-+ return MKFS_UBIFS_COMPR_NONE;
-+ }
-+
-+ switch (type) {
-+ case MKFS_UBIFS_COMPR_LZO:
-+ ret = lzo_compress(in_buf, in_len, out_buf, out_len);
-+ break;
-+ case MKFS_UBIFS_COMPR_ZLIB:
-+ ret = zlib_deflate(in_buf, in_len, out_buf, out_len);
-+ break;
-+ case MKFS_UBIFS_COMPR_NONE:
-+ ret = 1;
-+ break;
-+ default:
-+ errcnt += 1;
-+ break;
-+ }
-+ if (ret || *out_len >= in_len) {
-+ no_compress(in_buf, in_len, out_buf, out_len);
-+ return MKFS_UBIFS_COMPR_NONE;
-+ }
-+ return type;
-+}
-+
-+int init_compression(void)
-+{
-+ lzo_mem = malloc(LZO1X_999_MEM_COMPRESS);
-+ if (!lzo_mem)
-+ return -1;
-+ return 0;
-+}
-+
-+void destroy_compression(void)
-+{
-+ free(lzo_mem);
-+ if (errcnt)
-+ fprintf(stderr, "%llu compression errors occurred\n", errcnt);
-+}
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/compr.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/compr.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,38 @@
-+/*
-+ * Copyright (C) 2008 Nokia Corporation.
-+ * Copyright (C) 2008 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy
-+ * Adrian Hunter
-+ * Zoltan Sogor
-+ */
-+
-+#ifndef __UBIFS_COMPRESS_H__
-+#define __UBIFS_COMPRESS_H__
-+
-+enum compression_type
-+{
-+ MKFS_UBIFS_COMPR_NONE,
-+ MKFS_UBIFS_COMPR_LZO,
-+ MKFS_UBIFS_COMPR_ZLIB,
-+};
-+
-+int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
-+ int type);
-+int init_compression(void);
-+void destroy_compression(void);
-+
-+#endif
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/copying 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/copying 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,340 @@
-+ GNU GENERAL PUBLIC LICENSE
-+ Version 2, June 1991
-+
-+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ Everyone is permitted to copy and distribute verbatim copies
-+ of this license document, but changing it is not allowed.
-+
-+ Preamble
-+
-+ The licenses for most software are designed to take away your
-+freedom to share and change it. By contrast, the GNU General Public
-+License is intended to guarantee your freedom to share and change free
-+software--to make sure the software is free for all its users. This
-+General Public License applies to most of the Free Software
-+Foundation's software and to any other program whose authors commit to
-+using it. (Some other Free Software Foundation software is covered by
-+the GNU Library General Public License instead.) You can apply it to
-+your programs, too.
-+
-+ When we speak of free software, we are referring to freedom, not
-+price. Our General Public Licenses are designed to make sure that you
-+have the freedom to distribute copies of free software (and charge for
-+this service if you wish), that you receive source code or can get it
-+if you want it, that you can change the software or use pieces of it
-+in new free programs; and that you know you can do these things.
-+
-+ To protect your rights, we need to make restrictions that forbid
-+anyone to deny you these rights or to ask you to surrender the rights.
-+These restrictions translate to certain responsibilities for you if you
-+distribute copies of the software, or if you modify it.
-+
-+ For example, if you distribute copies of such a program, whether
-+gratis or for a fee, you must give the recipients all the rights that
-+you have. You must make sure that they, too, receive or can get the
-+source code. And you must show them these terms so they know their
-+rights.
-+
-+ We protect your rights with two steps: (1) copyright the software, and
-+(2) offer you this license which gives you legal permission to copy,
-+distribute and/or modify the software.
-+
-+ Also, for each author's protection and ours, we want to make certain
-+that everyone understands that there is no warranty for this free
-+software. If the software is modified by someone else and passed on, we
-+want its recipients to know that what they have is not the original, so
-+that any problems introduced by others will not reflect on the original
-+authors' reputations.
-+
-+ Finally, any free program is threatened constantly by software
-+patents. We wish to avoid the danger that redistributors of a free
-+program will individually obtain patent licenses, in effect making the
-+program proprietary. To prevent this, we have made it clear that any
-+patent must be licensed for everyone's free use or not licensed at all.
-+
-+ The precise terms and conditions for copying, distribution and
-+modification follow.
-+
-+ GNU GENERAL PUBLIC LICENSE
-+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-+
-+ 0. This License applies to any program or other work which contains
-+a notice placed by the copyright holder saying it may be distributed
-+under the terms of this General Public License. The "Program", below,
-+refers to any such program or work, and a "work based on the Program"
-+means either the Program or any derivative work under copyright law:
-+that is to say, a work containing the Program or a portion of it,
-+either verbatim or with modifications and/or translated into another
-+language. (Hereinafter, translation is included without limitation in
-+the term "modification".) Each licensee is addressed as "you".
-+
-+Activities other than copying, distribution and modification are not
-+covered by this License; they are outside its scope. The act of
-+running the Program is not restricted, and the output from the Program
-+is covered only if its contents constitute a work based on the
-+Program (independent of having been made by running the Program).
-+Whether that is true depends on what the Program does.
-+
-+ 1. You may copy and distribute verbatim copies of the Program's
-+source code as you receive it, in any medium, provided that you
-+conspicuously and appropriately publish on each copy an appropriate
-+copyright notice and disclaimer of warranty; keep intact all the
-+notices that refer to this License and to the absence of any warranty;
-+and give any other recipients of the Program a copy of this License
-+along with the Program.
-+
-+You may charge a fee for the physical act of transferring a copy, and
-+you may at your option offer warranty protection in exchange for a fee.
-+
-+ 2. You may modify your copy or copies of the Program or any portion
-+of it, thus forming a work based on the Program, and copy and
-+distribute such modifications or work under the terms of Section 1
-+above, provided that you also meet all of these conditions:
-+
-+ a) You must cause the modified files to carry prominent notices
-+ stating that you changed the files and the date of any change.
-+
-+ b) You must cause any work that you distribute or publish, that in
-+ whole or in part contains or is derived from the Program or any
-+ part thereof, to be licensed as a whole at no charge to all third
-+ parties under the terms of this License.
-+
-+ c) If the modified program normally reads commands interactively
-+ when run, you must cause it, when started running for such
-+ interactive use in the most ordinary way, to print or display an
-+ announcement including an appropriate copyright notice and a
-+ notice that there is no warranty (or else, saying that you provide
-+ a warranty) and that users may redistribute the program under
-+ these conditions, and telling the user how to view a copy of this
-+ License. (Exception: if the Program itself is interactive but
-+ does not normally print such an announcement, your work based on
-+ the Program is not required to print an announcement.)
-+
-+These requirements apply to the modified work as a whole. If
-+identifiable sections of that work are not derived from the Program,
-+and can be reasonably considered independent and separate works in
-+themselves, then this License, and its terms, do not apply to those
-+sections when you distribute them as separate works. But when you
-+distribute the same sections as part of a whole which is a work based
-+on the Program, the distribution of the whole must be on the terms of
-+this License, whose permissions for other licensees extend to the
-+entire whole, and thus to each and every part regardless of who wrote it.
-+
-+Thus, it is not the intent of this section to claim rights or contest
-+your rights to work written entirely by you; rather, the intent is to
-+exercise the right to control the distribution of derivative or
-+collective works based on the Program.
-+
-+In addition, mere aggregation of another work not based on the Program
-+with the Program (or with a work based on the Program) on a volume of
-+a storage or distribution medium does not bring the other work under
-+the scope of this License.
-+
-+ 3. You may copy and distribute the Program (or a work based on it,
-+under Section 2) in object code or executable form under the terms of
-+Sections 1 and 2 above provided that you also do one of the following:
-+
-+ a) Accompany it with the complete corresponding machine-readable
-+ source code, which must be distributed under the terms of Sections
-+ 1 and 2 above on a medium customarily used for software interchange; or,
-+
-+ b) Accompany it with a written offer, valid for at least three
-+ years, to give any third party, for a charge no more than your
-+ cost of physically performing source distribution, a complete
-+ machine-readable copy of the corresponding source code, to be
-+ distributed under the terms of Sections 1 and 2 above on a medium
-+ customarily used for software interchange; or,
-+
-+ c) Accompany it with the information you received as to the offer
-+ to distribute corresponding source code. (This alternative is
-+ allowed only for noncommercial distribution and only if you
-+ received the program in object code or executable form with such
-+ an offer, in accord with Subsection b above.)
-+
-+The source code for a work means the preferred form of the work for
-+making modifications to it. For an executable work, complete source
-+code means all the source code for all modules it contains, plus any
-+associated interface definition files, plus the scripts used to
-+control compilation and installation of the executable. However, as a
-+special exception, the source code distributed need not include
-+anything that is normally distributed (in either source or binary
-+form) with the major components (compiler, kernel, and so on) of the
-+operating system on which the executable runs, unless that component
-+itself accompanies the executable.
-+
-+If distribution of executable or object code is made by offering
-+access to copy from a designated place, then offering equivalent
-+access to copy the source code from the same place counts as
-+distribution of the source code, even though third parties are not
-+compelled to copy the source along with the object code.
-+
-+ 4. You may not copy, modify, sublicense, or distribute the Program
-+except as expressly provided under this License. Any attempt
-+otherwise to copy, modify, sublicense or distribute the Program is
-+void, and will automatically terminate your rights under this License.
-+However, parties who have received copies, or rights, from you under
-+this License will not have their licenses terminated so long as such
-+parties remain in full compliance.
-+
-+ 5. You are not required to accept this License, since you have not
-+signed it. However, nothing else grants you permission to modify or
-+distribute the Program or its derivative works. These actions are
-+prohibited by law if you do not accept this License. Therefore, by
-+modifying or distributing the Program (or any work based on the
-+Program), you indicate your acceptance of this License to do so, and
-+all its terms and conditions for copying, distributing or modifying
-+the Program or works based on it.
-+
-+ 6. Each time you redistribute the Program (or any work based on the
-+Program), the recipient automatically receives a license from the
-+original licensor to copy, distribute or modify the Program subject to
-+these terms and conditions. You may not impose any further
-+restrictions on the recipients' exercise of the rights granted herein.
-+You are not responsible for enforcing compliance by third parties to
-+this License.
-+
-+ 7. If, as a consequence of a court judgment or allegation of patent
-+infringement or for any other reason (not limited to patent issues),
-+conditions are imposed on you (whether by court order, agreement or
-+otherwise) that contradict the conditions of this License, they do not
-+excuse you from the conditions of this License. If you cannot
-+distribute so as to satisfy simultaneously your obligations under this
-+License and any other pertinent obligations, then as a consequence you
-+may not distribute the Program at all. For example, if a patent
-+license would not permit royalty-free redistribution of the Program by
-+all those who receive copies directly or indirectly through you, then
-+the only way you could satisfy both it and this License would be to
-+refrain entirely from distribution of the Program.
-+
-+If any portion of this section is held invalid or unenforceable under
-+any particular circumstance, the balance of the section is intended to
-+apply and the section as a whole is intended to apply in other
-+circumstances.
-+
-+It is not the purpose of this section to induce you to infringe any
-+patents or other property right claims or to contest validity of any
-+such claims; this section has the sole purpose of protecting the
-+integrity of the free software distribution system, which is
-+implemented by public license practices. Many people have made
-+generous contributions to the wide range of software distributed
-+through that system in reliance on consistent application of that
-+system; it is up to the author/donor to decide if he or she is willing
-+to distribute software through any other system and a licensee cannot
-+impose that choice.
-+
-+This section is intended to make thoroughly clear what is believed to
-+be a consequence of the rest of this License.
-+
-+ 8. If the distribution and/or use of the Program is restricted in
-+certain countries either by patents or by copyrighted interfaces, the
-+original copyright holder who places the Program under this License
-+may add an explicit geographical distribution limitation excluding
-+those countries, so that distribution is permitted only in or among
-+countries not thus excluded. In such case, this License incorporates
-+the limitation as if written in the body of this License.
-+
-+ 9. The Free Software Foundation may publish revised and/or new versions
-+of the General Public License from time to time. Such new versions will
-+be similar in spirit to the present version, but may differ in detail to
-+address new problems or concerns.
-+
-+Each version is given a distinguishing version number. If the Program
-+specifies a version number of this License which applies to it and "any
-+later version", you have the option of following the terms and conditions
-+either of that version or of any later version published by the Free
-+Software Foundation. If the Program does not specify a version number of
-+this License, you may choose any version ever published by the Free Software
-+Foundation.
-+
-+ 10. If you wish to incorporate parts of the Program into other free
-+programs whose distribution conditions are different, write to the author
-+to ask for permission. For software which is copyrighted by the Free
-+Software Foundation, write to the Free Software Foundation; we sometimes
-+make exceptions for this. Our decision will be guided by the two goals
-+of preserving the free status of all derivatives of our free software and
-+of promoting the sharing and reuse of software generally.
-+
-+ NO WARRANTY
-+
-+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-+REPAIR OR CORRECTION.
-+
-+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-+POSSIBILITY OF SUCH DAMAGES.
-+
-+ END OF TERMS AND CONDITIONS
-+
-+ How to Apply These Terms to Your New Programs
-+
-+ If you develop a new program, and you want it to be of the greatest
-+possible use to the public, the best way to achieve this is to make it
-+free software which everyone can redistribute and change under these terms.
-+
-+ To do so, attach the following notices to the program. It is safest
-+to attach them to the start of each source file to most effectively
-+convey the exclusion of warranty; and each file should have at least
-+the "copyright" line and a pointer to where the full notice is found.
-+
-+
-+ Copyright (C) 19yy
-+
-+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+
-+
-+Also add information on how to contact you by electronic and paper mail.
-+
-+If the program is interactive, make it output a short notice like this
-+when it starts in an interactive mode:
-+
-+ Gnomovision version 69, Copyright (C) 19yy name of author
-+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-+ This is free software, and you are welcome to redistribute it
-+ under certain conditions; type `show c' for details.
-+
-+The hypothetical commands `show w' and `show c' should show the appropriate
-+parts of the General Public License. Of course, the commands you use may
-+be called something other than `show w' and `show c'; they could even be
-+mouse-clicks or menu items--whatever suits your program.
-+
-+You should also get your employer (if you work as a programmer) or your
-+school, if any, to sign a "copyright disclaimer" for the program, if
-+necessary. Here is a sample; alter the names:
-+
-+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
-+
-+ , 1 April 1989
-+ Ty Coon, President of Vice
-+
-+This General Public License does not permit incorporating your program into
-+proprietary programs. If your program is a subroutine library, you may
-+consider it more useful to permit linking proprietary applications with the
-+library. If this is what you want to do, use the GNU Library General
-+Public License instead of this License.
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc16.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc16.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,56 @@
-+/*
-+ * This code was taken from the linux kernel. The license is GPL Version 2.
-+ */
-+
-+#include "crc16.h"
-+
-+/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
-+uint16_t const crc16_table[256] = {
-+ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
-+ 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
-+ 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
-+ 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
-+ 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
-+ 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
-+ 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
-+ 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
-+ 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
-+ 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
-+ 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
-+ 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
-+ 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
-+ 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
-+ 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
-+ 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
-+ 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
-+ 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
-+ 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
-+ 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
-+ 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
-+ 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
-+ 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
-+ 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
-+ 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
-+ 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
-+ 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
-+ 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
-+ 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
-+ 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
-+ 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
-+ 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
-+};
-+
-+/**
-+ * crc16 - compute the CRC-16 for the data buffer
-+ * @crc: previous CRC value
-+ * @buffer: data pointer
-+ * @len: number of bytes in the buffer
-+ *
-+ * Returns the updated CRC value.
-+ */
-+uint16_t crc16(uint16_t crc, uint8_t const *buffer, size_t len)
-+{
-+ while (len--)
-+ crc = crc16_byte(crc, *buffer++);
-+ return crc;
-+}
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc16.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc16.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,27 @@
-+/*
-+ * Implements the standard CRC-16:
-+ * Width 16
-+ * Poly 0x8005 (x^16 + x^15 + x^2 + 1)
-+ * Init 0
-+ *
-+ * Copyright (c) 2005 Ben Gardner
-+ *
-+ * This code was taken from the linux kernel. The license is GPL Version 2.
-+ */
-+
-+#ifndef __CRC16_H__
-+#define __CRC16_H__
-+
-+#include
-+#include
-+
-+extern uint16_t const crc16_table[256];
-+
-+extern uint16_t crc16(uint16_t crc, const uint8_t *buffer, size_t len);
-+
-+static inline uint16_t crc16_byte(uint16_t crc, const uint8_t data)
-+{
-+ return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
-+}
-+
-+#endif /* __CRC16_H__ */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc32.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc32.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,95 @@
-+/*
-+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
-+ * code or tables extracted from it, as desired without restriction.
-+ *
-+ * First, the polynomial itself and its table of feedback terms. The
-+ * polynomial is
-+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
-+ *
-+ * Note that we take it "backwards" and put the highest-order term in
-+ * the lowest-order bit. The X^32 term is "implied"; the LSB is the
-+ * X^31 term, etc. The X^0 term (usually shown as "+1") results in
-+ * the MSB being 1
-+ *
-+ * Note that the usual hardware shift register implementation, which
-+ * is what we're using (we're merely optimizing it by doing eight-bit
-+ * chunks at a time) shifts bits into the lowest-order term. In our
-+ * implementation, that means shifting towards the right. Why do we
-+ * do it this way? Because the calculated CRC must be transmitted in
-+ * order from highest-order term to lowest-order term. UARTs transmit
-+ * characters in order from LSB to MSB. By storing the CRC this way
-+ * we hand it to the UART in the order low-byte to high-byte; the UART
-+ * sends each low-bit to hight-bit; and the result is transmission bit
-+ * by bit from highest- to lowest-order term without requiring any bit
-+ * shuffling on our part. Reception works similarly
-+ *
-+ * The feedback terms table consists of 256, 32-bit entries. Notes
-+ *
-+ * The table can be generated at runtime if desired; code to do so
-+ * is shown later. It might not be obvious, but the feedback
-+ * terms simply represent the results of eight shift/xor opera
-+ * tions for all combinations of data and CRC register values
-+ *
-+ * The values must be right-shifted by eight bits by the "updcrc
-+ * logic; the shift must be unsigned (bring in zeroes). On some
-+ * hardware you could probably optimize the shift in assembler by
-+ * using byte-swap instructions
-+ * polynomial $edb88320
-+ */
-+
-+#include
-+
-+const uint32_t crc32_table[256] = {
-+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
-+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
-+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
-+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
-+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
-+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
-+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
-+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
-+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
-+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
-+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
-+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
-+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
-+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
-+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
-+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
-+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
-+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
-+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
-+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
-+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
-+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
-+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
-+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
-+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
-+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
-+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
-+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
-+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
-+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
-+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
-+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
-+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
-+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
-+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
-+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
-+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
-+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
-+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
-+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
-+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
-+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
-+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
-+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
-+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
-+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
-+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
-+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
-+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
-+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
-+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
-+ 0x2d02ef8dL
-+};
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc32.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc32.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,22 @@
-+/*
-+ * This code was taken from the linux kernel. The license is GPL Version 2.
-+ */
-+
-+#ifndef __CRC32_H__
-+#define __CRC32_H__
-+
-+#include
-+
-+extern const uint32_t crc32_table[256];
-+
-+/* Return a 32-bit CRC of the contents of the buffer. */
-+static inline uint32_t crc32(uint32_t val, const void *ss, int len)
-+{
-+ const unsigned char *s = ss;
-+
-+ while (--len >= 0)
-+ val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
-+ return val;
-+}
-+
-+#endif /* __CRC32_H__ */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/defs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/defs.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,105 @@
-+/*
-+ * Greate deal of the code was taken from the kernel UBIFS implementation, and
-+ * this file contains some "glue" definitions.
-+ */
-+
-+#ifndef __UBIFS_DEFS_H__
-+#define __UBIFS_DEFS_H__
-+
-+#define t16(x) ({ \
-+ uint16_t __b = (x); \
-+ (__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_16(__b); \
-+})
-+
-+#define t32(x) ({ \
-+ uint32_t __b = (x); \
-+ (__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_32(__b); \
-+})
-+
-+#define t64(x) ({ \
-+ uint64_t __b = (x); \
-+ (__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_64(__b); \
-+})
-+
-+#define cpu_to_le16(x) ((__le16){t16(x)})
-+#define cpu_to_le32(x) ((__le32){t32(x)})
-+#define cpu_to_le64(x) ((__le64){t64(x)})
-+
-+#define le16_to_cpu(x) (t16((x)))
-+#define le32_to_cpu(x) (t32((x)))
-+#define le64_to_cpu(x) (t64((x)))
-+
-+#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
-+#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
-+
-+#define min_t(t,x,y) ({ \
-+ typeof((x)) _x = (x); \
-+ typeof((y)) _y = (y); \
-+ (_x < _y) ? _x : _y; \
-+})
-+
-+#define max_t(t,x,y) ({ \
-+ typeof((x)) _x = (x); \
-+ typeof((y)) _y = (y); \
-+ (_x > _y) ? _x : _y; \
-+})
-+
-+#define unlikely(x) (x)
-+
-+struct qstr
-+{
-+ char *name;
-+ size_t len;
-+};
-+
-+/**
-+ * fls - find last (most-significant) bit set
-+ * @x: the word to search
-+ *
-+ * This is defined the same way as ffs.
-+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
-+ */
-+static inline int fls(int x)
-+{
-+ int r = 32;
-+
-+ if (!x)
-+ return 0;
-+ if (!(x & 0xffff0000u)) {
-+ x <<= 16;
-+ r -= 16;
-+ }
-+ if (!(x & 0xff000000u)) {
-+ x <<= 8;
-+ r -= 8;
-+ }
-+ if (!(x & 0xf0000000u)) {
-+ x <<= 4;
-+ r -= 4;
-+ }
-+ if (!(x & 0xc0000000u)) {
-+ x <<= 2;
-+ r -= 2;
-+ }
-+ if (!(x & 0x80000000u)) {
-+ x <<= 1;
-+ r -= 1;
-+ }
-+ return r;
-+}
-+
-+#define do_div(n,base) ({ \
-+int __res; \
-+__res = ((unsigned long) n) % (unsigned) base; \
-+n = ((unsigned long) n) / (unsigned) base; \
-+__res; })
-+
-+#if INT_MAX != 0x7fffffff
-+#error : sizeof(int) must be 4 for this program
-+#endif
-+
-+#if (~0ULL) != 0xffffffffffffffffULL
-+#error : sizeof(long long) must be 8 for this program
-+#endif
-+
-+#endif
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/devtable.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/devtable.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,524 @@
-+/*
-+ * Copyright (C) 2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Author: Artem Bityutskiy
-+ *
-+ * Part of the device table parsing code was taken from the mkfs.jffs2 utility.
-+ * The original author of that code is Erik Andersen, hence:
-+ * Copyright (C) 2001, 2002 Erik Andersen
-+ */
-+
-+/*
-+ * This file implemented device table support. Device table entries take the
-+ * form of:
-+ *
-+ * /dev/mem c 640 0 0 1 1 0 0 -
-+ *
-+ * Type can be one of:
-+ * f A regular file
-+ * d Directory
-+ * c Character special device file
-+ * b Block special device file
-+ * p Fifo (named pipe)
-+ *
-+ * Don't bother with symlinks (permissions are irrelevant), hard links (special
-+ * cases of regular files), or sockets (why bother).
-+ *
-+ * Regular files must exist in the target root directory. If a char, block,
-+ * fifo, or directory does not exist, it will be created.
-+ *
-+ * Please, refer the device_table.txt file which can be found at MTD utilities
-+ * for more information about what the device table is.
-+ */
-+
-+#include "mkfs.ubifs.h"
-+#include "hashtable/hashtable.h"
-+#include "hashtable/hashtable_itr.h"
-+
-+/*
-+ * The hash table which contains paths to files/directories/device nodes
-+ * referred to in the device table. For example, if the device table refers
-+ * "/dev/loop0", the @path_htbl will contain "/dev" element.
-+ */
-+static struct hashtable *path_htbl;
-+
-+/* Hash function used for hash tables */
-+static unsigned int r5_hash(void *s)
-+{
-+ unsigned int a = 0;
-+ const signed char *str = s;
-+
-+ while (*str) {
-+ a += *str << 4;
-+ a += *str >> 4;
-+ a *= 11;
-+ str++;
-+ }
-+
-+ return a;
-+}
-+
-+/*
-+ * Check whether 2 keys of a hash table are equivalent. The keys are path/file
-+ * names, so we simply use 'strcmp()'.
-+ */
-+static int is_equivalent(void *k1, void *k2)
-+{
-+ return !strcmp(k1, k2);
-+}
-+
-+/**
-+ * separate_last - separate out the last path component
-+ * @buf: the path to split
-+ * @len: length of the @buf string
-+ * @path: the beginning of path is returned here
-+ * @name: the last path component is returned here
-+ *
-+ * This helper function separates out the the last component of the full path
-+ * string. For example, "/dev/loop" would be split on "/dev" and "loop". This
-+ * function allocates memory for @path and @name and return the result there.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+static int separate_last(const char *buf, int len, char **path, char **name)
-+{
-+ int path_len = len, name_len;
-+ const char *p = buf + len, *n;
-+
-+ while (*--p != '/')
-+ path_len -= 1;
-+
-+ /* Drop the final '/' unless this is the root directory */
-+ name_len = len - path_len;
-+ n = buf + path_len;
-+ if (path_len > 1)
-+ path_len -= 1;
-+
-+ *path = malloc(path_len + 1);
-+ if (!*path)
-+ return err_msg("cannot allocate %d bytes of memory",
-+ path_len + 1);
-+ memcpy(*path, buf, path_len);
-+ (*path)[path_len] = '\0';
-+
-+ *name = malloc(name_len + 1);
-+ if (!*name) {
-+ free(*path);
-+ return err_msg("cannot allocate %d bytes of memory",
-+ name_len + 1);
-+ }
-+ memcpy(*name, n, name_len + 1);
-+
-+ return 0;
-+}
-+
-+static int interpret_table_entry(const char *root, const char *line)
-+{
-+ char buf[1024], type, *path = NULL, *name = NULL;
-+ int len;
-+ struct path_htbl_element *ph_elt = NULL;
-+ struct name_htbl_element *nh_elt = NULL;
-+ unsigned int mode = 0755, uid = 0, gid = 0, major = 0, minor = 0;
-+ unsigned int start = 0, increment = 0, count = 0;
-+
-+ if (sscanf(line, "%1023s %c %o %u %u %u %u %u %u %u",
-+ buf, &type, &mode, &uid, &gid, &major, &minor,
-+ &start, &increment, &count) < 0)
-+ return sys_err_msg("sscanf failed");
-+
-+ dbg_msg(3, "name %s, type %c, mode %o, uid %u, gid %u, major %u, "
-+ "minor %u, start %u, inc %u, cnt %u",
-+ buf, type, mode, uid, gid, major, minor, start,
-+ increment, count);
-+
-+ len = strnlen(buf, 1024);
-+ if (len == 1024)
-+ return err_msg("too long path");
-+
-+ if (!strcmp(buf, "/"))
-+ return err_msg("device table entries require absolute paths");
-+ if (buf[1] == '\0')
-+ return err_msg("root directory cannot be created");
-+ if (strstr(buf, "//"))
-+ return err_msg("'//' cannot be used in the path");
-+ if (buf[len - 1] == '/')
-+ return err_msg("do not put '/' at the end");
-+
-+ if (strstr(buf, "/./") || strstr(buf, "/../") ||
-+ !strcmp(buf + len - 2, "/.") || !strcmp(buf + len - 3, "/.."))
-+ return err_msg("'.' and '..' cannot be used in the path");
-+
-+ switch (type) {
-+ case 'd':
-+ mode |= S_IFDIR;
-+ break;
-+ case 'f':
-+ mode |= S_IFREG;
-+ break;
-+ case 'p':
-+ mode |= S_IFIFO;
-+ break;
-+ case 'c':
-+ mode |= S_IFCHR;
-+ break;
-+ case 'b':
-+ mode |= S_IFBLK;
-+ break;
-+ default:
-+ return err_msg("unsupported file type '%c'", type);
-+ }
-+
-+ if (separate_last(buf, len, &path, &name))
-+ return -1;
-+
-+ /*
-+ * Check if this path already exist in the path hash table and add it
-+ * if it is not.
-+ */
-+ ph_elt = hashtable_search(path_htbl, path);
-+ if (!ph_elt) {
-+ dbg_msg(3, "inserting '%s' into path hash table", path);
-+ ph_elt = malloc(sizeof(struct path_htbl_element));
-+ if (!ph_elt) {
-+ err_msg("cannot allocate %d bytes of memory",
-+ sizeof(struct path_htbl_element));
-+ goto out_free;
-+ }
-+
-+ if (!hashtable_insert(path_htbl, path, ph_elt)) {
-+ err_msg("cannot insert into path hash table");
-+ goto out_free;
-+ }
-+
-+ ph_elt->path = path;
-+ path = NULL;
-+ ph_elt->name_htbl = create_hashtable(128, &r5_hash,
-+ &is_equivalent);
-+ if (!ph_elt->name_htbl) {
-+ err_msg("cannot create name hash table");
-+ goto out_free;
-+ }
-+ }
-+
-+ if (increment != 0 && count == 0)
-+ return err_msg("count cannot be zero if increment is non-zero");
-+
-+ /*
-+ * Add the file/directory/device node (last component of the path) to
-+ * the name hashtable. The name hashtable resides in the corresponding
-+ * path hashtable element.
-+ */
-+
-+ if (count == 0) {
-+ /* This entry does not require any iterating */
-+ nh_elt = malloc(sizeof(struct name_htbl_element));
-+ if (!nh_elt) {
-+ err_msg("cannot allocate %d bytes of memory",
-+ sizeof(struct name_htbl_element));
-+ goto out_free;
-+ }
-+
-+ nh_elt->mode = mode;
-+ nh_elt->uid = uid;
-+ nh_elt->gid = gid;
-+ nh_elt->dev = makedev(major, minor);
-+
-+ dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)",
-+ name, major(nh_elt->dev), minor(nh_elt->dev));
-+
-+ if (hashtable_search(ph_elt->name_htbl, name))
-+ return err_msg("'%s' is referred twice", buf);
-+
-+ nh_elt->name = name;
-+ if (!hashtable_insert(ph_elt->name_htbl, name, nh_elt)) {
-+ err_msg("cannot insert into name hash table");
-+ goto out_free;
-+ }
-+ } else {
-+ int i, num = start + increment * count, len = strlen(name) + 20;
-+ char *nm;
-+
-+ for (i = start; i < num; i++) {
-+ nh_elt = malloc(sizeof(struct name_htbl_element));
-+ if (!nh_elt) {
-+ err_msg("cannot allocate %d bytes of memory",
-+ sizeof(struct name_htbl_element));
-+ goto out_free;
-+ }
-+
-+ nh_elt->mode = mode;
-+ nh_elt->uid = uid;
-+ nh_elt->gid = gid;
-+ nh_elt->dev = makedev(major, minor + i - start);
-+
-+ nm = malloc(len);
-+ if (!nm) {
-+ err_msg("cannot allocate %d bytes of memory", len);
-+ goto out_free;
-+ }
-+
-+ sprintf(nm, "%s%d", name, i);
-+ nh_elt->name = nm;
-+
-+ dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)",
-+ nm, major(nh_elt->dev), minor(nh_elt->dev));
-+
-+ if (hashtable_search(ph_elt->name_htbl, nm)) {
-+ err_msg("'%s' is referred twice", buf);
-+ free (nm);
-+ goto out_free;
-+ }
-+
-+ if (!hashtable_insert(ph_elt->name_htbl, nm, nh_elt)) {
-+ err_msg("cannot insert into name hash table");
-+ free (nm);
-+ goto out_free;
-+ }
-+ }
-+ free(name);
-+ name = NULL;
-+ }
-+
-+ return 0;
-+
-+out_free:
-+ free(ph_elt);
-+ free(nh_elt);
-+ free(path);
-+ free(name);
-+ return -1;
-+}
-+
-+/**
-+ * parse_devtable - parse the device table.
-+ * @tbl_file: device table file name
-+ *
-+ * This function parses the device table and prepare the hash table which will
-+ * later be used by mkfs.ubifs to create the specified files/device nodes.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+int parse_devtable(const char *root, const char *tbl_file)
-+{
-+ FILE *f;
-+ char *line = NULL;
-+ struct stat st;
-+ size_t len;
-+
-+ dbg_msg(1, "parsing device table file '%s'", tbl_file);
-+
-+ path_htbl = create_hashtable(128, &r5_hash, &is_equivalent);
-+ if (!path_htbl)
-+ return err_msg("cannot create path hash table");
-+
-+ f = fopen(tbl_file, "r");
-+ if (!f)
-+ return sys_err_msg("cannot open '%s'", tbl_file);
-+
-+ if (fstat(fileno(f), &st) < 0) {
-+ sys_err_msg("cannot stat '%s'", tbl_file);
-+ goto out_close;
-+ }
-+
-+ if (st.st_size < 10) {
-+ sys_err_msg("'%s' is too short", tbl_file);
-+ goto out_close;
-+ }
-+
-+ /*
-+ * The general plan now is to read in one line at a time, check for
-+ * leading comment delimiters ('#'), then try and parse the line as a
-+ * device table
-+ */
-+ while (getline(&line, &len, f) != -1) {
-+ /* First trim off any white-space */
-+ len = strlen(line);
-+
-+ /* Trim trailing white-space */
-+ while (len > 0 && isspace(line[len - 1]))
-+ line[--len] = '\0';
-+ /* Trim leading white-space */
-+ memmove(line, &line[strspn(line, " \n\r\t\v")], len);
-+
-+ /* How long are we after trimming? */
-+ len = strlen(line);
-+
-+ /* If this is not a comment line, try to interpret it */
-+ if (len && *line != '#') {
-+ if (interpret_table_entry(root, line)) {
-+ err_msg("cannot parse '%s'", line);
-+ goto out_close;
-+ }
-+ }
-+
-+ free(line);
-+ line = NULL;
-+ }
-+
-+ dbg_msg(1, "finished parsing");
-+ fclose(f);
-+ return 0;
-+
-+out_close:
-+ fclose(f);
-+ free_devtable_info();
-+ return -1;
-+}
-+
-+/**
-+ * devtbl_find_path - find a path in the path hash table.
-+ * @path: UBIFS path to find.
-+ *
-+ * This looks up the path hash table. Returns the path hash table element
-+ * reference if @path was found and %NULL if not.
-+ */
-+struct path_htbl_element *devtbl_find_path(const char *path)
-+{
-+ if (!path_htbl)
-+ return NULL;
-+
-+ return hashtable_search(path_htbl, (void *)path);
-+}
-+
-+/**
-+ * devtbl_find_name - find a name in the name hash table.
-+ * @ph_etl: path hash table element to find at
-+ * @name: name to find
-+ *
-+ * This looks up the name hash table. Returns the name hash table element
-+ * reference if @name found and %NULL if not.
-+ */
-+struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt,
-+ const char *name)
-+{
-+ if (!path_htbl)
-+ return NULL;
-+
-+ return hashtable_search(ph_elt->name_htbl, (void *)name);
-+}
-+
-+/**
-+ * override_attributes - override inode attributes.
-+ * @st: struct stat object to containing the attributes to override
-+ * @ph_elt: path hash table element object
-+ * @nh_elt: name hash table element object containing the new values
-+ *
-+ * The device table file may override attributes like UID of files. For
-+ * example, the device table may contain a "/dev" entry, and the UBIFS FS on
-+ * the host may contain "/dev" directory. In this case the attributes of the
-+ * "/dev" directory inode has to be as the device table specifies.
-+ *
-+ * Note, the hash element is removed by this function as well.
-+ */
-+int override_attributes(struct stat *st, struct path_htbl_element *ph_elt,
-+ struct name_htbl_element *nh_elt)
-+{
-+ if (!path_htbl)
-+ return 0;
-+
-+ if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode) ||
-+ S_ISFIFO(st->st_mode))
-+ return err_msg("%s/%s both exists at UBIFS root at host, "
-+ "and is referred from the device table",
-+ strcmp(ph_elt->path, "/") ? ph_elt->path : "",
-+ nh_elt->name);
-+
-+ if ((st->st_mode & S_IFMT) != (nh_elt->mode & S_IFMT))
-+ return err_msg("%s/%s is referred from the device table also exists in "
-+ "the UBIFS root directory at host, but the file type is "
-+ "different", strcmp(ph_elt->path, "/") ? ph_elt->path : "",
-+ nh_elt->name);
-+
-+ dbg_msg(3, "set UID %d, GID %d, mode %o for %s/%s as device table says",
-+ nh_elt->uid, nh_elt->gid, nh_elt->mode, ph_elt->path, nh_elt->name);
-+
-+ st->st_uid = nh_elt->uid;
-+ st->st_gid = nh_elt->gid;
-+ st->st_mode = nh_elt->mode;
-+
-+ hashtable_remove(ph_elt->name_htbl, (void *)nh_elt->name);
-+ return 0;
-+}
-+
-+/**
-+ * first_name_htbl_element - return first element of the name hash table.
-+ * @ph_elt: the path hash table the name hash table belongs to
-+ * @itr: double pointer to a 'struct hashtable_itr' object where the
-+ * information about further iterations is stored
-+ *
-+ * This function implements name hash table iteration together with
-+ * 'next_name_htbl_element()'. Returns the first name hash table element or
-+ * %NULL if the hash table is empty.
-+ */
-+struct name_htbl_element *
-+first_name_htbl_element(struct path_htbl_element *ph_elt,
-+ struct hashtable_itr **itr)
-+{
-+ if (!path_htbl || !ph_elt || hashtable_count(ph_elt->name_htbl) == 0)
-+ return NULL;
-+
-+ *itr = hashtable_iterator(ph_elt->name_htbl);
-+ return hashtable_iterator_value(*itr);
-+}
-+
-+/**
-+ * first_name_htbl_element - return next element of the name hash table.
-+ * @ph_elt: the path hash table the name hash table belongs to
-+ * @itr: double pointer to a 'struct hashtable_itr' object where the
-+ * information about further iterations is stored
-+ *
-+ * This function implements name hash table iteration together with
-+ * 'first_name_htbl_element()'. Returns the next name hash table element or
-+ * %NULL if there are no more elements.
-+ */
-+struct name_htbl_element *
-+next_name_htbl_element(struct path_htbl_element *ph_elt,
-+ struct hashtable_itr **itr)
-+{
-+ if (!path_htbl || !ph_elt || !hashtable_iterator_advance(*itr))
-+ return NULL;
-+
-+ return hashtable_iterator_value(*itr);
-+}
-+
-+/**
-+ * free_devtable_info - free device table information.
-+ *
-+ * This function frees the path hash table and the name hash tables.
-+ */
-+void free_devtable_info(void)
-+{
-+ struct hashtable_itr *ph_itr;
-+ struct path_htbl_element *ph_elt;
-+
-+ if (!path_htbl)
-+ return;
-+
-+ if (hashtable_count(path_htbl) > 0) {
-+ ph_itr = hashtable_iterator(path_htbl);
-+ do {
-+ ph_elt = hashtable_iterator_value(ph_itr);
-+ /*
-+ * Note, since we use the same string for the key and
-+ * @name in the name hash table elements, we do not
-+ * have to iterate name hash table because @name memory
-+ * will be freed when freeing the key.
-+ */
-+ hashtable_destroy(ph_elt->name_htbl, 1);
-+ } while (hashtable_iterator_advance(ph_itr));
-+ }
-+ hashtable_destroy(path_htbl, 1);
-+}
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,274 @@
-+/* Copyright (C) 2004 Christopher Clark */
-+
-+#include "hashtable.h"
-+#include "hashtable_private.h"
-+#include
-+#include
-+#include
-+#include
-+
-+/*
-+Credit for primes table: Aaron Krowne
-+ http://br.endernet.org/~akrowne/
-+ http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
-+*/
-+static const unsigned int primes[] = {
-+53, 97, 193, 389,
-+769, 1543, 3079, 6151,
-+12289, 24593, 49157, 98317,
-+196613, 393241, 786433, 1572869,
-+3145739, 6291469, 12582917, 25165843,
-+50331653, 100663319, 201326611, 402653189,
-+805306457, 1610612741
-+};
-+const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
-+const float max_load_factor = 0.65;
-+
-+/*****************************************************************************/
-+struct hashtable *
-+create_hashtable(unsigned int minsize,
-+ unsigned int (*hashf) (void*),
-+ int (*eqf) (void*,void*))
-+{
-+ struct hashtable *h;
-+ unsigned int pindex, size = primes[0];
-+ /* Check requested hashtable isn't too large */
-+ if (minsize > (1u << 30)) return NULL;
-+ /* Enforce size as prime */
-+ for (pindex=0; pindex < prime_table_length; pindex++) {
-+ if (primes[pindex] > minsize) { size = primes[pindex]; break; }
-+ }
-+ h = (struct hashtable *)malloc(sizeof(struct hashtable));
-+ if (NULL == h) return NULL; /*oom*/
-+ h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
-+ if (NULL == h->table) { free(h); return NULL; } /*oom*/
-+ memset(h->table, 0, size * sizeof(struct entry *));
-+ h->tablelength = size;
-+ h->primeindex = pindex;
-+ h->entrycount = 0;
-+ h->hashfn = hashf;
-+ h->eqfn = eqf;
-+ h->loadlimit = (unsigned int) ceil(size * max_load_factor);
-+ return h;
-+}
-+
-+/*****************************************************************************/
-+unsigned int
-+hash(struct hashtable *h, void *k)
-+{
-+ /* Aim to protect against poor hash functions by adding logic here
-+ * - logic taken from java 1.4 hashtable source */
-+ unsigned int i = h->hashfn(k);
-+ i += ~(i << 9);
-+ i ^= ((i >> 14) | (i << 18)); /* >>> */
-+ i += (i << 4);
-+ i ^= ((i >> 10) | (i << 22)); /* >>> */
-+ return i;
-+}
-+
-+/*****************************************************************************/
-+static int
-+hashtable_expand(struct hashtable *h)
-+{
-+ /* Double the size of the table to accomodate more entries */
-+ struct entry **newtable;
-+ struct entry *e;
-+ struct entry **pE;
-+ unsigned int newsize, i, index;
-+ /* Check we're not hitting max capacity */
-+ if (h->primeindex == (prime_table_length - 1)) return 0;
-+ newsize = primes[++(h->primeindex)];
-+
-+ newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
-+ if (NULL != newtable)
-+ {
-+ memset(newtable, 0, newsize * sizeof(struct entry *));
-+ /* This algorithm is not 'stable'. ie. it reverses the list
-+ * when it transfers entries between the tables */
-+ for (i = 0; i < h->tablelength; i++) {
-+ while (NULL != (e = h->table[i])) {
-+ h->table[i] = e->next;
-+ index = indexFor(newsize,e->h);
-+ e->next = newtable[index];
-+ newtable[index] = e;
-+ }
-+ }
-+ free(h->table);
-+ h->table = newtable;
-+ }
-+ /* Plan B: realloc instead */
-+ else
-+ {
-+ newtable = (struct entry **)
-+ realloc(h->table, newsize * sizeof(struct entry *));
-+ if (NULL == newtable) { (h->primeindex)--; return 0; }
-+ h->table = newtable;
-+ memset(newtable[h->tablelength], 0, newsize - h->tablelength);
-+ for (i = 0; i < h->tablelength; i++) {
-+ for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
-+ index = indexFor(newsize,e->h);
-+ if (index == i)
-+ {
-+ pE = &(e->next);
-+ }
-+ else
-+ {
-+ *pE = e->next;
-+ e->next = newtable[index];
-+ newtable[index] = e;
-+ }
-+ }
-+ }
-+ }
-+ h->tablelength = newsize;
-+ h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
-+ return -1;
-+}
-+
-+/*****************************************************************************/
-+unsigned int
-+hashtable_count(struct hashtable *h)
-+{
-+ return h->entrycount;
-+}
-+
-+/*****************************************************************************/
-+int
-+hashtable_insert(struct hashtable *h, void *k, void *v)
-+{
-+ /* This method allows duplicate keys - but they shouldn't be used */
-+ unsigned int index;
-+ struct entry *e;
-+ if (++(h->entrycount) > h->loadlimit)
-+ {
-+ /* Ignore the return value. If expand fails, we should
-+ * still try cramming just this value into the existing table
-+ * -- we may not have memory for a larger table, but one more
-+ * element may be ok. Next time we insert, we'll try expanding again.*/
-+ hashtable_expand(h);
-+ }
-+ e = (struct entry *)malloc(sizeof(struct entry));
-+ if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
-+ e->h = hash(h,k);
-+ index = indexFor(h->tablelength,e->h);
-+ e->k = k;
-+ e->v = v;
-+ e->next = h->table[index];
-+ h->table[index] = e;
-+ return -1;
-+}
-+
-+/*****************************************************************************/
-+void * /* returns value associated with key */
-+hashtable_search(struct hashtable *h, void *k)
-+{
-+ struct entry *e;
-+ unsigned int hashvalue, index;
-+ hashvalue = hash(h,k);
-+ index = indexFor(h->tablelength,hashvalue);
-+ e = h->table[index];
-+ while (NULL != e)
-+ {
-+ /* Check hash value to short circuit heavier comparison */
-+ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
-+ e = e->next;
-+ }
-+ return NULL;
-+}
-+
-+/*****************************************************************************/
-+void * /* returns value associated with key */
-+hashtable_remove(struct hashtable *h, void *k)
-+{
-+ /* TODO: consider compacting the table when the load factor drops enough,
-+ * or provide a 'compact' method. */
-+
-+ struct entry *e;
-+ struct entry **pE;
-+ void *v;
-+ unsigned int hashvalue, index;
-+
-+ hashvalue = hash(h,k);
-+ index = indexFor(h->tablelength,hash(h,k));
-+ pE = &(h->table[index]);
-+ e = *pE;
-+ while (NULL != e)
-+ {
-+ /* Check hash value to short circuit heavier comparison */
-+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
-+ {
-+ *pE = e->next;
-+ h->entrycount--;
-+ v = e->v;
-+ freekey(e->k);
-+ free(e);
-+ return v;
-+ }
-+ pE = &(e->next);
-+ e = e->next;
-+ }
-+ return NULL;
-+}
-+
-+/*****************************************************************************/
-+/* destroy */
-+void
-+hashtable_destroy(struct hashtable *h, int free_values)
-+{
-+ unsigned int i;
-+ struct entry *e, *f;
-+ struct entry **table = h->table;
-+ if (free_values)
-+ {
-+ for (i = 0; i < h->tablelength; i++)
-+ {
-+ e = table[i];
-+ while (NULL != e)
-+ { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
-+ }
-+ }
-+ else
-+ {
-+ for (i = 0; i < h->tablelength; i++)
-+ {
-+ e = table[i];
-+ while (NULL != e)
-+ { f = e; e = e->next; freekey(f->k); free(f); }
-+ }
-+ }
-+ free(h->table);
-+ free(h);
-+}
-+
-+/*
-+ * Copyright (c) 2002, Christopher Clark
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ *
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ *
-+ * * Neither the name of the original author; nor the names of any contributors
-+ * may be used to endorse or promote products derived from this software
-+ * without specific prior written permission.
-+ *
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+*/
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,199 @@
-+/* Copyright (C) 2002 Christopher Clark */
-+
-+#ifndef __HASHTABLE_CWC22_H__
-+#define __HASHTABLE_CWC22_H__
-+
-+struct hashtable;
-+
-+/* Example of use:
-+ *
-+ * struct hashtable *h;
-+ * struct some_key *k;
-+ * struct some_value *v;
-+ *
-+ * static unsigned int hash_from_key_fn( void *k );
-+ * static int keys_equal_fn ( void *key1, void *key2 );
-+ *
-+ * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
-+ * k = (struct some_key *) malloc(sizeof(struct some_key));
-+ * v = (struct some_value *) malloc(sizeof(struct some_value));
-+ *
-+ * (initialise k and v to suitable values)
-+ *
-+ * if (! hashtable_insert(h,k,v) )
-+ * { exit(-1); }
-+ *
-+ * if (NULL == (found = hashtable_search(h,k) ))
-+ * { printf("not found!"); }
-+ *
-+ * if (NULL == (found = hashtable_remove(h,k) ))
-+ * { printf("Not found\n"); }
-+ *
-+ */
-+
-+/* Macros may be used to define type-safe(r) hashtable access functions, with
-+ * methods specialized to take known key and value types as parameters.
-+ *
-+ * Example:
-+ *
-+ * Insert this at the start of your file:
-+ *
-+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
-+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
-+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
-+ *
-+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
-+ * These operate just like hashtable_insert etc., with the same parameters,
-+ * but their function signatures have 'struct some_key *' rather than
-+ * 'void *', and hence can generate compile time errors if your program is
-+ * supplying incorrect data as a key (and similarly for value).
-+ *
-+ * Note that the hash and key equality functions passed to create_hashtable
-+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
-+ * a difficult issue as they're only defined and passed once, and the other
-+ * functions will ensure that only valid keys are supplied to them.
-+ *
-+ * The cost for this checking is increased code size and runtime overhead
-+ * - if performance is important, it may be worth switching back to the
-+ * unsafe methods once your program has been debugged with the safe methods.
-+ * This just requires switching to some simple alternative defines - eg:
-+ * #define insert_some hashtable_insert
-+ *
-+ */
-+
-+/*****************************************************************************
-+ * create_hashtable
-+
-+ * @name create_hashtable
-+ * @param minsize minimum initial size of hashtable
-+ * @param hashfunction function for hashing keys
-+ * @param key_eq_fn function for determining key equality
-+ * @return newly created hashtable or NULL on failure
-+ */
-+
-+struct hashtable *
-+create_hashtable(unsigned int minsize,
-+ unsigned int (*hashfunction) (void*),
-+ int (*key_eq_fn) (void*,void*));
-+
-+/*****************************************************************************
-+ * hashtable_insert
-+
-+ * @name hashtable_insert
-+ * @param h the hashtable to insert into
-+ * @param k the key - hashtable claims ownership and will free on removal
-+ * @param v the value - does not claim ownership
-+ * @return non-zero for successful insertion
-+ *
-+ * This function will cause the table to expand if the insertion would take
-+ * the ratio of entries to table size over the maximum load factor.
-+ *
-+ * This function does not check for repeated insertions with a duplicate key.
-+ * The value returned when using a duplicate key is undefined -- when
-+ * the hashtable changes size, the order of retrieval of duplicate key
-+ * entries is reversed.
-+ * If in doubt, remove before insert.
-+ */
-+
-+int
-+hashtable_insert(struct hashtable *h, void *k, void *v);
-+
-+#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
-+int fnname (struct hashtable *h, keytype *k, valuetype *v) \
-+{ \
-+ return hashtable_insert(h,k,v); \
-+}
-+
-+/*****************************************************************************
-+ * hashtable_search
-+
-+ * @name hashtable_search
-+ * @param h the hashtable to search
-+ * @param k the key to search for - does not claim ownership
-+ * @return the value associated with the key, or NULL if none found
-+ */
-+
-+void *
-+hashtable_search(struct hashtable *h, void *k);
-+
-+#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
-+valuetype * fnname (struct hashtable *h, keytype *k) \
-+{ \
-+ return (valuetype *) (hashtable_search(h,k)); \
-+}
-+
-+/*****************************************************************************
-+ * hashtable_remove
-+
-+ * @name hashtable_remove
-+ * @param h the hashtable to remove the item from
-+ * @param k the key to search for - does not claim ownership
-+ * @return the value associated with the key, or NULL if none found
-+ */
-+
-+void * /* returns value */
-+hashtable_remove(struct hashtable *h, void *k);
-+
-+#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
-+valuetype * fnname (struct hashtable *h, keytype *k) \
-+{ \
-+ return (valuetype *) (hashtable_remove(h,k)); \
-+}
-+
-+
-+/*****************************************************************************
-+ * hashtable_count
-+
-+ * @name hashtable_count
-+ * @param h the hashtable
-+ * @return the number of items stored in the hashtable
-+ */
-+unsigned int
-+hashtable_count(struct hashtable *h);
-+
-+
-+/*****************************************************************************
-+ * hashtable_destroy
-+
-+ * @name hashtable_destroy
-+ * @param h the hashtable
-+ * @param free_values whether to call 'free' on the remaining values
-+ */
-+
-+void
-+hashtable_destroy(struct hashtable *h, int free_values);
-+
-+#endif /* __HASHTABLE_CWC22_H__ */
-+
-+/*
-+ * Copyright (c) 2002, Christopher Clark
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ *
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ *
-+ * * Neither the name of the original author; nor the names of any contributors
-+ * may be used to endorse or promote products derived from this software
-+ * without specific prior written permission.
-+ *
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+*/
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,188 @@
-+/* Copyright (C) 2002, 2004 Christopher Clark */
-+
-+#include "hashtable.h"
-+#include "hashtable_private.h"
-+#include "hashtable_itr.h"
-+#include /* defines NULL */
-+
-+/*****************************************************************************/
-+/* hashtable_iterator - iterator constructor */
-+
-+struct hashtable_itr *
-+hashtable_iterator(struct hashtable *h)
-+{
-+ unsigned int i, tablelength;
-+ struct hashtable_itr *itr = (struct hashtable_itr *)
-+ malloc(sizeof(struct hashtable_itr));
-+ if (NULL == itr) return NULL;
-+ itr->h = h;
-+ itr->e = NULL;
-+ itr->parent = NULL;
-+ tablelength = h->tablelength;
-+ itr->index = tablelength;
-+ if (0 == h->entrycount) return itr;
-+
-+ for (i = 0; i < tablelength; i++)
-+ {
-+ if (NULL != h->table[i])
-+ {
-+ itr->e = h->table[i];
-+ itr->index = i;
-+ break;
-+ }
-+ }
-+ return itr;
-+}
-+
-+/*****************************************************************************/
-+/* key - return the key of the (key,value) pair at the current position */
-+/* value - return the value of the (key,value) pair at the current position */
-+
-+void *
-+hashtable_iterator_key(struct hashtable_itr *i)
-+{ return i->e->k; }
-+
-+void *
-+hashtable_iterator_value(struct hashtable_itr *i)
-+{ return i->e->v; }
-+
-+/*****************************************************************************/
-+/* advance - advance the iterator to the next element
-+ * returns zero if advanced to end of table */
-+
-+int
-+hashtable_iterator_advance(struct hashtable_itr *itr)
-+{
-+ unsigned int j,tablelength;
-+ struct entry **table;
-+ struct entry *next;
-+ if (NULL == itr->e) return 0; /* stupidity check */
-+
-+ next = itr->e->next;
-+ if (NULL != next)
-+ {
-+ itr->parent = itr->e;
-+ itr->e = next;
-+ return -1;
-+ }
-+ tablelength = itr->h->tablelength;
-+ itr->parent = NULL;
-+ if (tablelength <= (j = ++(itr->index)))
-+ {
-+ itr->e = NULL;
-+ return 0;
-+ }
-+ table = itr->h->table;
-+ while (NULL == (next = table[j]))
-+ {
-+ if (++j >= tablelength)
-+ {
-+ itr->index = tablelength;
-+ itr->e = NULL;
-+ return 0;
-+ }
-+ }
-+ itr->index = j;
-+ itr->e = next;
-+ return -1;
-+}
-+
-+/*****************************************************************************/
-+/* remove - remove the entry at the current iterator position
-+ * and advance the iterator, if there is a successive
-+ * element.
-+ * If you want the value, read it before you remove:
-+ * beware memory leaks if you don't.
-+ * Returns zero if end of iteration. */
-+
-+int
-+hashtable_iterator_remove(struct hashtable_itr *itr)
-+{
-+ struct entry *remember_e, *remember_parent;
-+ int ret;
-+
-+ /* Do the removal */
-+ if (NULL == (itr->parent))
-+ {
-+ /* element is head of a chain */
-+ itr->h->table[itr->index] = itr->e->next;
-+ } else {
-+ /* element is mid-chain */
-+ itr->parent->next = itr->e->next;
-+ }
-+ /* itr->e is now outside the hashtable */
-+ remember_e = itr->e;
-+ itr->h->entrycount--;
-+ freekey(remember_e->k);
-+
-+ /* Advance the iterator, correcting the parent */
-+ remember_parent = itr->parent;
-+ ret = hashtable_iterator_advance(itr);
-+ if (itr->parent == remember_e) { itr->parent = remember_parent; }
-+ free(remember_e);
-+ return ret;
-+}
-+
-+/*****************************************************************************/
-+int /* returns zero if not found */
-+hashtable_iterator_search(struct hashtable_itr *itr,
-+ struct hashtable *h, void *k)
-+{
-+ struct entry *e, *parent;
-+ unsigned int hashvalue, index;
-+
-+ hashvalue = hash(h,k);
-+ index = indexFor(h->tablelength,hashvalue);
-+
-+ e = h->table[index];
-+ parent = NULL;
-+ while (NULL != e)
-+ {
-+ /* Check hash value to short circuit heavier comparison */
-+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
-+ {
-+ itr->index = index;
-+ itr->e = e;
-+ itr->parent = parent;
-+ itr->h = h;
-+ return -1;
-+ }
-+ parent = e;
-+ e = e->next;
-+ }
-+ return 0;
-+}
-+
-+
-+/*
-+ * Copyright (c) 2002, 2004, Christopher Clark
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ *
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ *
-+ * * Neither the name of the original author; nor the names of any contributors
-+ * may be used to endorse or promote products derived from this software
-+ * without specific prior written permission.
-+ *
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+*/
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,112 @@
-+/* Copyright (C) 2002, 2004 Christopher Clark */
-+
-+#ifndef __HASHTABLE_ITR_CWC22__
-+#define __HASHTABLE_ITR_CWC22__
-+#include "hashtable.h"
-+#include "hashtable_private.h" /* needed to enable inlining */
-+
-+/*****************************************************************************/
-+/* This struct is only concrete here to allow the inlining of two of the
-+ * accessor functions. */
-+struct hashtable_itr
-+{
-+ struct hashtable *h;
-+ struct entry *e;
-+ struct entry *parent;
-+ unsigned int index;
-+};
-+
-+
-+/*****************************************************************************/
-+/* hashtable_iterator
-+ */
-+
-+struct hashtable_itr *
-+hashtable_iterator(struct hashtable *h);
-+
-+/*****************************************************************************/
-+/* hashtable_iterator_key
-+ * - return the value of the (key,value) pair at the current position */
-+
-+extern inline void *
-+hashtable_iterator_key(struct hashtable_itr *i)
-+{
-+ return i->e->k;
-+}
-+
-+/*****************************************************************************/
-+/* value - return the value of the (key,value) pair at the current position */
-+
-+extern inline void *
-+hashtable_iterator_value(struct hashtable_itr *i)
-+{
-+ return i->e->v;
-+}
-+
-+/*****************************************************************************/
-+/* advance - advance the iterator to the next element
-+ * returns zero if advanced to end of table */
-+
-+int
-+hashtable_iterator_advance(struct hashtable_itr *itr);
-+
-+/*****************************************************************************/
-+/* remove - remove current element and advance the iterator to the next element
-+ * NB: if you need the value to free it, read it before
-+ * removing. ie: beware memory leaks!
-+ * returns zero if advanced to end of table */
-+
-+int
-+hashtable_iterator_remove(struct hashtable_itr *itr);
-+
-+/*****************************************************************************/
-+/* search - overwrite the supplied iterator, to point to the entry
-+ * matching the supplied key.
-+ h points to the hashtable to be searched.
-+ * returns zero if not found. */
-+int
-+hashtable_iterator_search(struct hashtable_itr *itr,
-+ struct hashtable *h, void *k);
-+
-+#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
-+int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
-+{ \
-+ return (hashtable_iterator_search(i,h,k)); \
-+}
-+
-+
-+
-+#endif /* __HASHTABLE_ITR_CWC22__*/
-+
-+/*
-+ * Copyright (c) 2002, 2004, Christopher Clark
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ *
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ *
-+ * * Neither the name of the original author; nor the names of any contributors
-+ * may be used to endorse or promote products derived from this software
-+ * without specific prior written permission.
-+ *
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+*/
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable_private.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable_private.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,85 @@
-+/* Copyright (C) 2002, 2004 Christopher Clark */
-+
-+#ifndef __HASHTABLE_PRIVATE_CWC22_H__
-+#define __HASHTABLE_PRIVATE_CWC22_H__
-+
-+#include "hashtable.h"
-+
-+/*****************************************************************************/
-+struct entry
-+{
-+ void *k, *v;
-+ unsigned int h;
-+ struct entry *next;
-+};
-+
-+struct hashtable {
-+ unsigned int tablelength;
-+ struct entry **table;
-+ unsigned int entrycount;
-+ unsigned int loadlimit;
-+ unsigned int primeindex;
-+ unsigned int (*hashfn) (void *k);
-+ int (*eqfn) (void *k1, void *k2);
-+};
-+
-+/*****************************************************************************/
-+unsigned int
-+hash(struct hashtable *h, void *k);
-+
-+/*****************************************************************************/
-+/* indexFor */
-+static inline unsigned int
-+indexFor(unsigned int tablelength, unsigned int hashvalue) {
-+ return (hashvalue % tablelength);
-+};
-+
-+/* Only works if tablelength == 2^N */
-+/*static inline unsigned int
-+indexFor(unsigned int tablelength, unsigned int hashvalue)
-+{
-+ return (hashvalue & (tablelength - 1u));
-+}
-+*/
-+
-+/*****************************************************************************/
-+#define freekey(X) free(X)
-+/*define freekey(X) ; */
-+
-+
-+/*****************************************************************************/
-+
-+#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
-+
-+/*
-+ * Copyright (c) 2002, Christopher Clark
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ *
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ *
-+ * * Neither the name of the original author; nor the names of any contributors
-+ * may be used to endorse or promote products derived from this software
-+ * without specific prior written permission.
-+ *
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+*/
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/key.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/key.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,511 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This header contains various key-related definitions and helper function.
-+ * UBIFS allows several key schemes, so we access key fields only via these
-+ * helpers. At the moment only one key scheme is supported.
-+ *
-+ * Simple key scheme
-+ * ~~~~~~~~~~~~~~~~~
-+ *
-+ * Keys are 64-bits long. First 32-bits are inode number (parent inode number
-+ * in case of direntry key). Next 3 bits are node type. The last 29 bits are
-+ * 4KiB offset in case of inode node, and direntry hash in case of a direntry
-+ * node. We use "r5" hash borrowed from reiserfs.
-+ */
-+
-+#ifndef __UBIFS_KEY_H__
-+#define __UBIFS_KEY_H__
-+
-+/**
-+ * key_r5_hash - R5 hash function (borrowed from reiserfs).
-+ * @s: direntry name
-+ * @len: name length
-+ */
-+static inline uint32_t key_r5_hash(const char *s, int len)
-+{
-+ uint32_t a = 0;
-+ const signed char *str = (const signed char *)s;
-+
-+ while (*str) {
-+ a += *str << 4;
-+ a += *str >> 4;
-+ a *= 11;
-+ str++;
-+ }
-+
-+ a &= UBIFS_S_KEY_HASH_MASK;
-+
-+ /*
-+ * We use hash values as offset in directories, so values %0 and %1 are
-+ * reserved for "." and "..". %2 is reserved for possible future use.
-+ */
-+ if (unlikely(a >= 0 && a <= 2))
-+ a += 3;
-+ return a;
-+}
-+
-+/**
-+ * key_test_hash - testing hash function.
-+ * @str: direntry name
-+ * @len: name length
-+ */
-+static inline uint32_t key_test_hash(const char *str, int len)
-+{
-+ uint32_t a = 0;
-+
-+ len = min_t(uint32_t, len, 4);
-+ memcpy(&a, str, len);
-+ a &= UBIFS_S_KEY_HASH_MASK;
-+ if (unlikely(a >= 0 && a <= 2))
-+ a += 3;
-+ return a;
-+}
-+
-+/**
-+ * ino_key_init - initialize inode key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void ino_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS;
-+}
-+
-+/**
-+ * ino_key_init_flash - initialize on-flash inode key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void ino_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum)
-+{
-+ union ubifs_key *key = k;
-+
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS);
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * lowest_ino_key - get the lowest possible inode key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void lowest_ino_key(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = 0;
-+}
-+
-+/**
-+ * highest_ino_key - get the highest possible inode key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void highest_ino_key(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = 0xffffffff;
-+}
-+
-+/**
-+ * dent_key_init - initialize directory entry key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: parent inode number
-+ * @nm: direntry name and length
-+ */
-+static inline void dent_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ const struct qstr *nm)
-+{
-+ uint32_t hash = c->key_hash(nm->name, nm->len);
-+
-+ key->u32[0] = inum;
-+ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
-+}
-+
-+/**
-+ * dent_key_init_hash - initialize directory entry key without re-calculating
-+ * hash function.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: parent inode number
-+ * @hash: direntry name hash
-+ */
-+static inline void dent_key_init_hash(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ uint32_t hash)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
-+}
-+
-+/**
-+ * dent_key_init_flash - initialize on-flash directory entry key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: parent inode number
-+ * @nm: direntry name and length
-+ */
-+static inline void dent_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum, const struct qstr *nm)
-+{
-+ union ubifs_key *key = k;
-+ uint32_t hash = c->key_hash(nm->name, nm->len);
-+
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(hash |
-+ (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS));
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * lowest_dent_key - get the lowest possible directory entry key.
-+ * @c: UBIFS file-system description object
-+ * @key: where to store the lowest key
-+ * @inum: parent inode number
-+ */
-+static inline void lowest_dent_key(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS;
-+}
-+
-+/**
-+ * xent_key_init - initialize extended attribute entry key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: host inode number
-+ * @nm: extended attribute entry name and length
-+ */
-+static inline void xent_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ const struct qstr *nm)
-+{
-+ uint32_t hash = c->key_hash(nm->name, nm->len);
-+
-+ key->u32[0] = inum;
-+ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
-+}
-+
-+/**
-+ * xent_key_init_hash - initialize extended attribute entry key without
-+ * re-calculating hash function.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: host inode number
-+ * @hash: extended attribute entry name hash
-+ */
-+static inline void xent_key_init_hash(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ uint32_t hash)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
-+}
-+
-+/**
-+ * xent_key_init_flash - initialize on-flash extended attribute entry key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: host inode number
-+ * @nm: extended attribute entry name and length
-+ */
-+static inline void xent_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum, const struct qstr *nm)
-+{
-+ union ubifs_key *key = k;
-+ uint32_t hash = c->key_hash(nm->name, nm->len);
-+
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(hash |
-+ (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS));
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * lowest_xent_key - get the lowest possible extended attribute entry key.
-+ * @c: UBIFS file-system description object
-+ * @key: where to store the lowest key
-+ * @inum: host inode number
-+ */
-+static inline void lowest_xent_key(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS;
-+}
-+
-+/**
-+ * data_key_init - initialize data key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ * @block: block number
-+ */
-+static inline void data_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum,
-+ unsigned int block)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = block | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS);
-+}
-+
-+/**
-+ * data_key_init_flash - initialize on-flash data key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: inode number
-+ * @block: block number
-+ */
-+static inline void data_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum, unsigned int block)
-+{
-+ union ubifs_key *key = k;
-+
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(block |
-+ (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS));
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * trun_key_init - initialize truncation node key.
-+ * @c: UBIFS file-system description object
-+ * @key: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void trun_key_init(const struct ubifs_info *c,
-+ union ubifs_key *key, ino_t inum)
-+{
-+ key->u32[0] = inum;
-+ key->u32[1] = UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS;
-+}
-+
-+/**
-+ * trun_key_init_flash - initialize on-flash truncation node key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to initialize
-+ * @inum: inode number
-+ */
-+static inline void trun_key_init_flash(const struct ubifs_info *c, void *k,
-+ ino_t inum)
-+{
-+ union ubifs_key *key = k;
-+
-+ key->j32[0] = cpu_to_le32(inum);
-+ key->j32[1] = cpu_to_le32(UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS);
-+ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * key_type - get key type.
-+ * @c: UBIFS file-system description object
-+ * @key: key to get type of
-+ */
-+static inline int key_type(const struct ubifs_info *c,
-+ const union ubifs_key *key)
-+{
-+ return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS;
-+}
-+
-+/**
-+ * key_type_flash - get type of a on-flash formatted key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to get type of
-+ */
-+static inline int key_type_flash(const struct ubifs_info *c, const void *k)
-+{
-+ const union ubifs_key *key = k;
-+
-+ return le32_to_cpu(key->u32[1]) >> UBIFS_S_KEY_BLOCK_BITS;
-+}
-+
-+/**
-+ * key_ino - fetch inode number from key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to fetch inode number from
-+ */
-+static inline ino_t key_ino(const struct ubifs_info *c, const void *k)
-+{
-+ const union ubifs_key *key = k;
-+
-+ return key->u32[0];
-+}
-+
-+/**
-+ * key_ino_flash - fetch inode number from an on-flash formatted key.
-+ * @c: UBIFS file-system description object
-+ * @k: key to fetch inode number from
-+ */
-+static inline ino_t key_ino_flash(const struct ubifs_info *c, const void *k)
-+{
-+ const union ubifs_key *key = k;
-+
-+ return le32_to_cpu(key->j32[0]);
-+}
-+
-+/**
-+ * key_hash - get directory entry hash.
-+ * @c: UBIFS file-system description object
-+ * @key: the key to get hash from
-+ */
-+static inline int key_hash(const struct ubifs_info *c,
-+ const union ubifs_key *key)
-+{
-+ return key->u32[1] & UBIFS_S_KEY_HASH_MASK;
-+}
-+
-+/**
-+ * key_hash_flash - get directory entry hash from an on-flash formatted key.
-+ * @c: UBIFS file-system description object
-+ * @k: the key to get hash from
-+ */
-+static inline int key_hash_flash(const struct ubifs_info *c, const void *k)
-+{
-+ const union ubifs_key *key = k;
-+
-+ return le32_to_cpu(key->j32[1]) & UBIFS_S_KEY_HASH_MASK;
-+}
-+
-+/**
-+ * key_block - get data block number.
-+ * @c: UBIFS file-system description object
-+ * @key: the key to get the block number from
-+ */
-+static inline unsigned int key_block(const struct ubifs_info *c,
-+ const union ubifs_key *key)
-+{
-+ return key->u32[1] & UBIFS_S_KEY_BLOCK_MASK;
-+}
-+
-+/**
-+ * key_read - transform a key to in-memory format.
-+ * @c: UBIFS file-system description object
-+ * @from: the key to transform
-+ * @to: the key to store the result
-+ */
-+static inline void key_read(const struct ubifs_info *c, const void *from,
-+ union ubifs_key *to)
-+{
-+ const union ubifs_key *f = from;
-+
-+ to->u32[0] = le32_to_cpu(f->j32[0]);
-+ to->u32[1] = le32_to_cpu(f->j32[1]);
-+}
-+
-+/**
-+ * key_write - transform a key from in-memory format.
-+ * @c: UBIFS file-system description object
-+ * @from: the key to transform
-+ * @to: the key to store the result
-+ */
-+static inline void key_write(const struct ubifs_info *c,
-+ const union ubifs_key *from, void *to)
-+{
-+ union ubifs_key *t = to;
-+
-+ t->j32[0] = cpu_to_le32(from->u32[0]);
-+ t->j32[1] = cpu_to_le32(from->u32[1]);
-+ memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-+}
-+
-+/**
-+ * key_write_idx - transform a key from in-memory format for the index.
-+ * @c: UBIFS file-system description object
-+ * @from: the key to transform
-+ * @to: the key to store the result
-+ */
-+static inline void key_write_idx(const struct ubifs_info *c,
-+ const union ubifs_key *from, void *to)
-+{
-+ union ubifs_key *t = to;
-+
-+ t->j32[0] = cpu_to_le32(from->u32[0]);
-+ t->j32[1] = cpu_to_le32(from->u32[1]);
-+}
-+
-+/**
-+ * key_copy - copy a key.
-+ * @c: UBIFS file-system description object
-+ * @from: the key to copy from
-+ * @to: the key to copy to
-+ */
-+static inline void key_copy(const struct ubifs_info *c,
-+ const union ubifs_key *from, union ubifs_key *to)
-+{
-+ to->u64[0] = from->u64[0];
-+}
-+
-+/**
-+ * keys_cmp - compare keys.
-+ * @c: UBIFS file-system description object
-+ * @key1: the first key to compare
-+ * @key2: the second key to compare
-+ *
-+ * This function compares 2 keys and returns %-1 if @key1 is less than
-+ * @key2, 0 if the keys are equivalent and %1 if @key1 is greater than @key2.
-+ */
-+static inline int keys_cmp(const struct ubifs_info *c,
-+ const union ubifs_key *key1,
-+ const union ubifs_key *key2)
-+{
-+ if (key1->u32[0] < key2->u32[0])
-+ return -1;
-+ if (key1->u32[0] > key2->u32[0])
-+ return 1;
-+ if (key1->u32[1] < key2->u32[1])
-+ return -1;
-+ if (key1->u32[1] > key2->u32[1])
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/**
-+ * is_hash_key - is a key vulnerable to hash collisions.
-+ * @c: UBIFS file-system description object
-+ * @key: key
-+ *
-+ * This function returns %1 if @key is a hashed key or %0 otherwise.
-+ */
-+static inline int is_hash_key(const struct ubifs_info *c,
-+ const union ubifs_key *key)
-+{
-+ int type = key_type(c, key);
-+
-+ return type == UBIFS_DENT_KEY || type == UBIFS_XENT_KEY;
-+}
-+
-+#endif /* !__UBIFS_KEY_H__ */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lpt.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lpt.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,577 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006, 2007 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy
-+ */
-+
-+#include "mkfs.ubifs.h"
-+
-+/**
-+ * do_calc_lpt_geom - calculate sizes for the LPT area.
-+ * @c: the UBIFS file-system description object
-+ *
-+ * Calculate the sizes of LPT bit fields, nodes, and tree, based on the
-+ * properties of the flash and whether LPT is "big" (c->big_lpt).
-+ */
-+static void do_calc_lpt_geom(struct ubifs_info *c)
-+{
-+ int n, bits, per_leb_wastage;
-+ long long sz, tot_wastage;
-+
-+ c->pnode_cnt = (c->main_lebs + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-+
-+ n = (c->pnode_cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-+ c->nnode_cnt = n;
-+ while (n > 1) {
-+ n = (n + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-+ c->nnode_cnt += n;
-+ }
-+
-+ c->lpt_hght = 1;
-+ n = UBIFS_LPT_FANOUT;
-+ while (n < c->pnode_cnt) {
-+ c->lpt_hght += 1;
-+ n <<= UBIFS_LPT_FANOUT_SHIFT;
-+ }
-+
-+ c->space_bits = fls(c->leb_size) - 3;
-+ c->lpt_lnum_bits = fls(c->lpt_lebs);
-+ c->lpt_offs_bits = fls(c->leb_size - 1);
-+ c->lpt_spc_bits = fls(c->leb_size);
-+
-+ n = (c->max_leb_cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-+ c->pcnt_bits = fls(n - 1);
-+
-+ c->lnum_bits = fls(c->max_leb_cnt - 1);
-+
-+ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-+ (c->big_lpt ? c->pcnt_bits : 0) +
-+ (c->space_bits * 2 + 1) * UBIFS_LPT_FANOUT;
-+ c->pnode_sz = (bits + 7) / 8;
-+
-+ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-+ (c->big_lpt ? c->pcnt_bits : 0) +
-+ (c->lpt_lnum_bits + c->lpt_offs_bits) * UBIFS_LPT_FANOUT;
-+ c->nnode_sz = (bits + 7) / 8;
-+
-+ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-+ c->lpt_lebs * c->lpt_spc_bits * 2;
-+ c->ltab_sz = (bits + 7) / 8;
-+
-+ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-+ c->lnum_bits * c->lsave_cnt;
-+ c->lsave_sz = (bits + 7) / 8;
-+
-+ /* Calculate the minimum LPT size */
-+ c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
-+ c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
-+ c->lpt_sz += c->ltab_sz;
-+ c->lpt_sz += c->lsave_sz;
-+
-+ /* Add wastage */
-+ sz = c->lpt_sz;
-+ per_leb_wastage = max_t(int, c->pnode_sz, c->nnode_sz);
-+ sz += per_leb_wastage;
-+ tot_wastage = per_leb_wastage;
-+ while (sz > c->leb_size) {
-+ sz += per_leb_wastage;
-+ sz -= c->leb_size;
-+ tot_wastage += per_leb_wastage;
-+ }
-+ tot_wastage += ALIGN(sz, c->min_io_size) - sz;
-+ c->lpt_sz += tot_wastage;
-+}
-+
-+/**
-+ * calc_dflt_lpt_geom - calculate default LPT geometry.
-+ * @c: the UBIFS file-system description object
-+ * @main_lebs: number of main area LEBs is passed and returned here
-+ * @big_lpt: whether the LPT area is "big" is returned here
-+ *
-+ * The size of the LPT area depends on parameters that themselves are dependent
-+ * on the size of the LPT area. This function, successively recalculates the LPT
-+ * area geometry until the parameters and resultant geometry are consistent.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt)
-+{
-+ int i, lebs_needed;
-+ long long sz;
-+
-+ /* Start by assuming the minimum number of LPT LEBs */
-+ c->lpt_lebs = UBIFS_MIN_LPT_LEBS;
-+ c->main_lebs = *main_lebs - c->lpt_lebs;
-+ if (c->main_lebs <= 0)
-+ return -EINVAL;
-+
-+ /* And assume we will use the small LPT model */
-+ c->big_lpt = 0;
-+
-+ /*
-+ * Calculate the geometry based on assumptions above and then see if it
-+ * makes sense
-+ */
-+ do_calc_lpt_geom(c);
-+
-+ /* Small LPT model must have lpt_sz < leb_size */
-+ if (c->lpt_sz > c->leb_size) {
-+ /* Nope, so try again using big LPT model */
-+ c->big_lpt = 1;
-+ do_calc_lpt_geom(c);
-+ }
-+
-+ /* Now check there are enough LPT LEBs */
-+ for (i = 0; i < 64 ; i++) {
-+ sz = c->lpt_sz * 4; /* Allow 4 times the size */
-+ sz += c->leb_size - 1;
-+ do_div(sz, c->leb_size);
-+ lebs_needed = sz;
-+ if (lebs_needed > c->lpt_lebs) {
-+ /* Not enough LPT LEBs so try again with more */
-+ c->lpt_lebs = lebs_needed;
-+ c->main_lebs = *main_lebs - c->lpt_lebs;
-+ if (c->main_lebs <= 0)
-+ return -EINVAL;
-+ do_calc_lpt_geom(c);
-+ continue;
-+ }
-+ if (c->ltab_sz > c->leb_size) {
-+ err_msg("LPT ltab too big");
-+ return -EINVAL;
-+ }
-+ *main_lebs = c->main_lebs;
-+ *big_lpt = c->big_lpt;
-+ return 0;
-+ }
-+ return -EINVAL;
-+}
-+
-+/**
-+ * pack_bits - pack bit fields end-to-end.
-+ * @addr: address at which to pack (passed and next address returned)
-+ * @pos: bit position at which to pack (passed and next position returned)
-+ * @val: value to pack
-+ * @nrbits: number of bits of value to pack (1-32)
-+ */
-+static void pack_bits(uint8_t **addr, int *pos, uint32_t val, int nrbits)
-+{
-+ uint8_t *p = *addr;
-+ int b = *pos;
-+
-+ if (b) {
-+ *p |= ((uint8_t)val) << b;
-+ nrbits += b;
-+ if (nrbits > 8) {
-+ *++p = (uint8_t)(val >>= (8 - b));
-+ if (nrbits > 16) {
-+ *++p = (uint8_t)(val >>= 8);
-+ if (nrbits > 24) {
-+ *++p = (uint8_t)(val >>= 8);
-+ if (nrbits > 32)
-+ *++p = (uint8_t)(val >>= 8);
-+ }
-+ }
-+ }
-+ } else {
-+ *p = (uint8_t)val;
-+ if (nrbits > 8) {
-+ *++p = (uint8_t)(val >>= 8);
-+ if (nrbits > 16) {
-+ *++p = (uint8_t)(val >>= 8);
-+ if (nrbits > 24)
-+ *++p = (uint8_t)(val >>= 8);
-+ }
-+ }
-+ }
-+ b = nrbits & 7;
-+ if (b == 0)
-+ p++;
-+ *addr = p;
-+ *pos = b;
-+}
-+
-+/**
-+ * pack_pnode - pack all the bit fields of a pnode.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer into which to pack
-+ * @pnode: pnode to pack
-+ */
-+static void pack_pnode(struct ubifs_info *c, void *buf,
-+ struct ubifs_pnode *pnode)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0;
-+ uint16_t crc;
-+
-+ pack_bits(&addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS);
-+ if (c->big_lpt)
-+ pack_bits(&addr, &pos, pnode->num, c->pcnt_bits);
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ pack_bits(&addr, &pos, pnode->lprops[i].free >> 3,
-+ c->space_bits);
-+ pack_bits(&addr, &pos, pnode->lprops[i].dirty >> 3,
-+ c->space_bits);
-+ if (pnode->lprops[i].flags & LPROPS_INDEX)
-+ pack_bits(&addr, &pos, 1, 1);
-+ else
-+ pack_bits(&addr, &pos, 0, 1);
-+ }
-+ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ c->pnode_sz - UBIFS_LPT_CRC_BYTES);
-+ addr = buf;
-+ pos = 0;
-+ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-+}
-+
-+/**
-+ * pack_nnode - pack all the bit fields of a nnode.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer into which to pack
-+ * @nnode: nnode to pack
-+ */
-+static void pack_nnode(struct ubifs_info *c, void *buf,
-+ struct ubifs_nnode *nnode)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0;
-+ uint16_t crc;
-+
-+ pack_bits(&addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS);
-+ if (c->big_lpt)
-+ pack_bits(&addr, &pos, nnode->num, c->pcnt_bits);
-+ for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-+ int lnum = nnode->nbranch[i].lnum;
-+
-+ if (lnum == 0)
-+ lnum = c->lpt_last + 1;
-+ pack_bits(&addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits);
-+ pack_bits(&addr, &pos, nnode->nbranch[i].offs,
-+ c->lpt_offs_bits);
-+ }
-+ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ c->nnode_sz - UBIFS_LPT_CRC_BYTES);
-+ addr = buf;
-+ pos = 0;
-+ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-+}
-+
-+/**
-+ * pack_ltab - pack the LPT's own lprops table.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer into which to pack
-+ * @ltab: LPT's own lprops table to pack
-+ */
-+static void pack_ltab(struct ubifs_info *c, void *buf,
-+ struct ubifs_lpt_lprops *ltab)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0;
-+ uint16_t crc;
-+
-+ pack_bits(&addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS);
-+ for (i = 0; i < c->lpt_lebs; i++) {
-+ pack_bits(&addr, &pos, ltab[i].free, c->lpt_spc_bits);
-+ pack_bits(&addr, &pos, ltab[i].dirty, c->lpt_spc_bits);
-+ }
-+ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ c->ltab_sz - UBIFS_LPT_CRC_BYTES);
-+ addr = buf;
-+ pos = 0;
-+ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-+}
-+
-+/**
-+ * pack_lsave - pack the LPT's save table.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer into which to pack
-+ * @lsave: LPT's save table to pack
-+ */
-+static void pack_lsave(struct ubifs_info *c, void *buf, int *lsave)
-+{
-+ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-+ int i, pos = 0;
-+ uint16_t crc;
-+
-+ pack_bits(&addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS);
-+ for (i = 0; i < c->lsave_cnt; i++)
-+ pack_bits(&addr, &pos, lsave[i], c->lnum_bits);
-+ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-+ c->lsave_sz - UBIFS_LPT_CRC_BYTES);
-+ addr = buf;
-+ pos = 0;
-+ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-+}
-+
-+/**
-+ * set_ltab - set LPT LEB properties.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number
-+ * @free: amount of free space
-+ * @dirty: amount of dirty space
-+ */
-+static void set_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
-+{
-+ dbg_msg(3, "LEB %d free %d dirty %d to %d %d",
-+ lnum, c->ltab[lnum - c->lpt_first].free,
-+ c->ltab[lnum - c->lpt_first].dirty, free, dirty);
-+ c->ltab[lnum - c->lpt_first].free = free;
-+ c->ltab[lnum - c->lpt_first].dirty = dirty;
-+}
-+
-+/**
-+ * calc_nnode_num - calculate nnode number.
-+ * @row: the row in the tree (root is zero)
-+ * @col: the column in the row (leftmost is zero)
-+ *
-+ * The nnode number is a number that uniquely identifies a nnode and can be used
-+ * easily to traverse the tree from the root to that nnode.
-+ *
-+ * This function calculates and returns the nnode number for the nnode at @row
-+ * and @col.
-+ */
-+static int calc_nnode_num(int row, int col)
-+{
-+ int num, bits;
-+
-+ num = 1;
-+ while (row--) {
-+ bits = (col & (UBIFS_LPT_FANOUT - 1));
-+ col >>= UBIFS_LPT_FANOUT_SHIFT;
-+ num <<= UBIFS_LPT_FANOUT_SHIFT;
-+ num |= bits;
-+ }
-+ return num;
-+}
-+
-+/**
-+ * create_lpt - create LPT.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int create_lpt(struct ubifs_info *c)
-+{
-+ int lnum, err = 0, i, j, cnt, len, alen, row;
-+ int blnum, boffs, bsz, bcnt;
-+ struct ubifs_pnode *pnode = NULL;
-+ struct ubifs_nnode *nnode = NULL;
-+ void *buf = NULL, *p;
-+ int *lsave = NULL;
-+
-+ pnode = malloc(sizeof(struct ubifs_pnode));
-+ nnode = malloc(sizeof(struct ubifs_nnode));
-+ buf = malloc(c->leb_size);
-+ lsave = malloc(sizeof(int) * c->lsave_cnt);
-+ if (!pnode || !nnode || !buf || !lsave) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+ memset(pnode, 0 , sizeof(struct ubifs_pnode));
-+ memset(nnode, 0 , sizeof(struct ubifs_pnode));
-+
-+ c->lscan_lnum = c->main_first;
-+
-+ lnum = c->lpt_first;
-+ p = buf;
-+ len = 0;
-+ /* Number of leaf nodes (pnodes) */
-+ cnt = (c->main_lebs + UBIFS_LPT_FANOUT - 1) >> UBIFS_LPT_FANOUT_SHIFT;
-+ //printf("pnode_cnt=%d\n",cnt);
-+
-+ /*
-+ * To calculate the internal node branches, we keep information about
-+ * the level below.
-+ */
-+ blnum = lnum; /* LEB number of level below */
-+ boffs = 0; /* Offset of level below */
-+ bcnt = cnt; /* Number of nodes in level below */
-+ bsz = c->pnode_sz; /* Size of nodes in level below */
-+
-+ /* Add pnodes */
-+ for (i = 0; i < cnt; i++) {
-+ if (len + c->pnode_sz > c->leb_size) {
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen, alen - len);
-+ memset(p, 0xff, alen - len);
-+ err = write_leb(lnum++, alen, buf);
-+ if (err)
-+ goto out;
-+ p = buf;
-+ len = 0;
-+ }
-+ /* Fill in the pnode */
-+ for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
-+ int k = (i << UBIFS_LPT_FANOUT_SHIFT) + j;
-+
-+ if (k < c->main_lebs)
-+ pnode->lprops[j] = c->lpt[k];
-+ else {
-+ pnode->lprops[j].free = c->leb_size;
-+ pnode->lprops[j].dirty = 0;
-+ pnode->lprops[j].flags = 0;
-+ }
-+ }
-+ pack_pnode(c, p, pnode);
-+ p += c->pnode_sz;
-+ len += c->pnode_sz;
-+ /*
-+ * pnodes are simply numbered left to right starting at zero,
-+ * which means the pnode number can be used easily to traverse
-+ * down the tree to the corresponding pnode.
-+ */
-+ pnode->num += 1;
-+ }
-+
-+ row = c->lpt_hght - 1;
-+ /* Add all nnodes, one level at a time */
-+ while (1) {
-+ /* Number of internal nodes (nnodes) at next level */
-+ cnt = (cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-+ if (cnt == 0)
-+ cnt = 1;
-+ for (i = 0; i < cnt; i++) {
-+ if (len + c->nnode_sz > c->leb_size) {
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen,
-+ alen - len);
-+ memset(p, 0xff, alen - len);
-+ err = write_leb(lnum++, alen, buf);
-+ if (err)
-+ goto out;
-+ p = buf;
-+ len = 0;
-+ }
-+ /* The root is on row zero */
-+ if (row == 0) {
-+ c->lpt_lnum = lnum;
-+ c->lpt_offs = len;
-+ }
-+ /* Set branches to the level below */
-+ for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
-+ if (bcnt) {
-+ if (boffs + bsz > c->leb_size) {
-+ blnum += 1;
-+ boffs = 0;
-+ }
-+ nnode->nbranch[j].lnum = blnum;
-+ nnode->nbranch[j].offs = boffs;
-+ boffs += bsz;
-+ bcnt--;
-+ } else {
-+ nnode->nbranch[j].lnum = 0;
-+ nnode->nbranch[j].offs = 0;
-+ }
-+ }
-+ nnode->num = calc_nnode_num(row, i);
-+ pack_nnode(c, p, nnode);
-+ p += c->nnode_sz;
-+ len += c->nnode_sz;
-+ }
-+ /* Row zero is the top row */
-+ if (row == 0)
-+ break;
-+ /* Update the information about the level below */
-+ bcnt = cnt;
-+ bsz = c->nnode_sz;
-+ row -= 1;
-+ }
-+
-+ if (c->big_lpt) {
-+ /* Need to add LPT's save table */
-+ if (len + c->lsave_sz > c->leb_size) {
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen, alen - len);
-+ memset(p, 0xff, alen - len);
-+ err = write_leb(lnum++, alen, buf);
-+ if (err)
-+ goto out;
-+ p = buf;
-+ len = 0;
-+ }
-+
-+ c->lsave_lnum = lnum;
-+ c->lsave_offs = len;
-+
-+ for (i = 0; i < c->lsave_cnt; i++)
-+ lsave[i] = c->main_first + i;
-+
-+ pack_lsave(c, p, lsave);
-+ p += c->lsave_sz;
-+ len += c->lsave_sz;
-+ }
-+
-+ /* Need to add LPT's own LEB properties table */
-+ if (len + c->ltab_sz > c->leb_size) {
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen, alen - len);
-+ memset(p, 0xff, alen - len);
-+ err = write_leb(lnum++, alen, buf);
-+ if (err)
-+ goto out;
-+ p = buf;
-+ len = 0;
-+ }
-+
-+ c->ltab_lnum = lnum;
-+ c->ltab_offs = len;
-+
-+ /* Update ltab before packing it */
-+ len += c->ltab_sz;
-+ alen = ALIGN(len, c->min_io_size);
-+ set_ltab(c, lnum, c->leb_size - alen, alen - len);
-+
-+ pack_ltab(c, p, c->ltab);
-+ p += c->ltab_sz;
-+
-+ /* Write remaining buffer */
-+ memset(p, 0xff, alen - len);
-+ err = write_leb(lnum, alen, buf);
-+ if (err)
-+ goto out;
-+
-+ c->nhead_lnum = lnum;
-+ c->nhead_offs = ALIGN(len, c->min_io_size);
-+
-+ dbg_msg(1, "space_bits: %d", c->space_bits);
-+ dbg_msg(1, "lpt_lnum_bits: %d", c->lpt_lnum_bits);
-+ dbg_msg(1, "lpt_offs_bits: %d", c->lpt_offs_bits);
-+ dbg_msg(1, "lpt_spc_bits: %d", c->lpt_spc_bits);
-+ dbg_msg(1, "pcnt_bits: %d", c->pcnt_bits);
-+ dbg_msg(1, "lnum_bits: %d", c->lnum_bits);
-+ dbg_msg(1, "pnode_sz: %d", c->pnode_sz);
-+ dbg_msg(1, "nnode_sz: %d", c->nnode_sz);
-+ dbg_msg(1, "ltab_sz: %d", c->ltab_sz);
-+ dbg_msg(1, "lsave_sz: %d", c->lsave_sz);
-+ dbg_msg(1, "lsave_cnt: %d", c->lsave_cnt);
-+ dbg_msg(1, "lpt_hght: %d", c->lpt_hght);
-+ dbg_msg(1, "big_lpt: %d", c->big_lpt);
-+ dbg_msg(1, "LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
-+ dbg_msg(1, "LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
-+ dbg_msg(1, "LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
-+ if (c->big_lpt)
-+ dbg_msg(1, "LPT lsave is at %d:%d",
-+ c->lsave_lnum, c->lsave_offs);
-+out:
-+ free(lsave);
-+ free(buf);
-+ free(nnode);
-+ free(pnode);
-+ return err;
-+}
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lpt.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lpt.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,28 @@
-+/*
-+ * Copyright (C) 2008 Nokia Corporation.
-+ * Copyright (C) 2008 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy
-+ * Adrian Hunter
-+ */
-+
-+#ifndef __UBIFS_LPT_H__
-+#define __UBIFS_LPT_H__
-+
-+int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt);
-+int create_lpt(struct ubifs_info *c);
-+
-+#endif
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,92 @@
-+/* lzo1.h -- public interface of the LZO1 compression algorithm
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO1_H_INCLUDED
-+#define __LZO1_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+/* Memory required for the wrkmem parameter.
-+ * When the required size is 0, you can also pass a NULL pointer.
-+ */
-+
-+#define LZO1_MEM_COMPRESS ((lzo_uint32) (8192L * lzo_sizeof_dict_t))
-+#define LZO1_MEM_DECOMPRESS (0)
-+
-+
-+LZO_EXTERN(int)
-+lzo1_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+LZO_EXTERN(int)
-+lzo1_decompress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+/***********************************************************************
-+// better compression ratio at the cost of more memory and time
-+************************************************************************/
-+
-+#define LZO1_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t))
-+
-+LZO_EXTERN(int)
-+lzo1_99_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1a.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1a.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,92 @@
-+/* lzo1a.h -- public interface of the LZO1A compression algorithm
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO1A_H_INCLUDED
-+#define __LZO1A_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+/* Memory required for the wrkmem parameter.
-+ * When the required size is 0, you can also pass a NULL pointer.
-+ */
-+
-+#define LZO1A_MEM_COMPRESS ((lzo_uint32) (8192L * lzo_sizeof_dict_t))
-+#define LZO1A_MEM_DECOMPRESS (0)
-+
-+
-+LZO_EXTERN(int)
-+lzo1a_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+LZO_EXTERN(int)
-+lzo1a_decompress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+/***********************************************************************
-+// better compression ratio at the cost of more memory and time
-+************************************************************************/
-+
-+#define LZO1A_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t))
-+
-+LZO_EXTERN(int)
-+lzo1a_99_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1b.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1b.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,156 @@
-+/* lzo1b.h -- public interface of the LZO1B compression algorithm
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO1B_H_INCLUDED
-+#define __LZO1B_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+/* Memory required for the wrkmem parameter.
-+ * When the required size is 0, you can also pass a NULL pointer.
-+ */
-+
-+#define LZO1B_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
-+#define LZO1B_MEM_DECOMPRESS (0)
-+
-+
-+/* compression levels */
-+#define LZO1B_BEST_SPEED 1
-+#define LZO1B_BEST_COMPRESSION 9
-+#define LZO1B_DEFAULT_COMPRESSION (-1) /* fastest by default */
-+
-+
-+LZO_EXTERN(int)
-+lzo1b_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem,
-+ int compression_level );
-+
-+/* decompression */
-+LZO_EXTERN(int)
-+lzo1b_decompress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+/* safe decompression with overrun testing */
-+LZO_EXTERN(int)
-+lzo1b_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+LZO_EXTERN(int)
-+lzo1b_1_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1b_2_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1b_3_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1b_4_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1b_5_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1b_6_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1b_7_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1b_8_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1b_9_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/***********************************************************************
-+// better compression ratio at the cost of more memory and time
-+************************************************************************/
-+
-+#define LZO1B_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t))
-+
-+LZO_EXTERN(int)
-+lzo1b_99_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+#define LZO1B_999_MEM_COMPRESS ((lzo_uint32) (3 * 65536L * sizeof(lzo_xint)))
-+
-+LZO_EXTERN(int)
-+lzo1b_999_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1c.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1c.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,156 @@
-+/* lzo1c.h -- public interface of the LZO1C compression algorithm
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO1C_H_INCLUDED
-+#define __LZO1C_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+/* Memory required for the wrkmem parameter.
-+ * When the required size is 0, you can also pass a NULL pointer.
-+ */
-+
-+#define LZO1C_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
-+#define LZO1C_MEM_DECOMPRESS (0)
-+
-+
-+/* compression levels */
-+#define LZO1C_BEST_SPEED 1
-+#define LZO1C_BEST_COMPRESSION 9
-+#define LZO1C_DEFAULT_COMPRESSION (-1) /* fastest by default */
-+
-+
-+LZO_EXTERN(int)
-+lzo1c_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem,
-+ int compression_level );
-+
-+/* decompression */
-+LZO_EXTERN(int)
-+lzo1c_decompress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+/* safe decompression with overrun testing */
-+LZO_EXTERN(int)
-+lzo1c_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+LZO_EXTERN(int)
-+lzo1c_1_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1c_2_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1c_3_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1c_4_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1c_5_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1c_6_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1c_7_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1c_8_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+LZO_EXTERN(int)
-+lzo1c_9_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/***********************************************************************
-+// better compression ratio at the cost of more memory and time
-+************************************************************************/
-+
-+#define LZO1C_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t))
-+
-+LZO_EXTERN(int)
-+lzo1c_99_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+#define LZO1C_999_MEM_COMPRESS ((lzo_uint32) (5 * 16384L * sizeof(short)))
-+
-+LZO_EXTERN(int)
-+lzo1c_999_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1f.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1f.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,104 @@
-+/* lzo1f.h -- public interface of the LZO1F compression algorithm
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO1F_H_INCLUDED
-+#define __LZO1F_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+/* Memory required for the wrkmem parameter.
-+ * When the required size is 0, you can also pass a NULL pointer.
-+ */
-+
-+#define LZO1F_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
-+#define LZO1F_MEM_DECOMPRESS (0)
-+
-+
-+/* decompression */
-+LZO_EXTERN(int)
-+lzo1f_decompress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+/* safe decompression with overrun testing */
-+LZO_EXTERN(int)
-+lzo1f_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+LZO_EXTERN(int)
-+lzo1f_1_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/***********************************************************************
-+// better compression ratio at the cost of more memory and time
-+************************************************************************/
-+
-+#define LZO1F_999_MEM_COMPRESS ((lzo_uint32) (5 * 16384L * sizeof(short)))
-+
-+LZO_EXTERN(int)
-+lzo1f_999_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1x.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1x.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,173 @@
-+/* lzo1x.h -- public interface of the LZO1X compression algorithm
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO1X_H_INCLUDED
-+#define __LZO1X_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+/* Memory required for the wrkmem parameter.
-+ * When the required size is 0, you can also pass a NULL pointer.
-+ */
-+
-+#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
-+#define LZO1X_MEM_DECOMPRESS (0)
-+#define LZO1X_MEM_OPTIMIZE (0)
-+
-+
-+/* decompression */
-+LZO_EXTERN(int)
-+lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+/* safe decompression with overrun testing */
-+LZO_EXTERN(int)
-+lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
-+
-+LZO_EXTERN(int)
-+lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/***********************************************************************
-+// special compressor versions
-+************************************************************************/
-+
-+/* this version needs only 8 kB work memory */
-+#define LZO1X_1_11_MEM_COMPRESS ((lzo_uint32) (2048L * lzo_sizeof_dict_t))
-+
-+LZO_EXTERN(int)
-+lzo1x_1_11_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/* this version needs 16 kB work memory */
-+#define LZO1X_1_12_MEM_COMPRESS ((lzo_uint32) (4096L * lzo_sizeof_dict_t))
-+
-+LZO_EXTERN(int)
-+lzo1x_1_12_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/* use this version if you need a little more compression speed */
-+#define LZO1X_1_15_MEM_COMPRESS ((lzo_uint32) (32768L * lzo_sizeof_dict_t))
-+
-+LZO_EXTERN(int)
-+lzo1x_1_15_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/***********************************************************************
-+// better compression ratio at the cost of more memory and time
-+************************************************************************/
-+
-+#define LZO1X_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
-+
-+LZO_EXTERN(int)
-+lzo1x_999_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+LZO_EXTERN(int)
-+lzo1x_999_compress_dict ( const lzo_bytep in , lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem,
-+ const lzo_bytep dict, lzo_uint dict_len );
-+
-+LZO_EXTERN(int)
-+lzo1x_999_compress_level ( const lzo_bytep in , lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem,
-+ const lzo_bytep dict, lzo_uint dict_len,
-+ lzo_callback_p cb,
-+ int compression_level );
-+
-+LZO_EXTERN(int)
-+lzo1x_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem /* NOT USED */,
-+ const lzo_bytep dict, lzo_uint dict_len );
-+
-+
-+/***********************************************************************
-+// optimize a compressed data block
-+************************************************************************/
-+
-+LZO_EXTERN(int)
-+lzo1x_optimize ( lzo_bytep in , lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1y.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1y.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,141 @@
-+/* lzo1y.h -- public interface of the LZO1Y compression algorithm
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO1Y_H_INCLUDED
-+#define __LZO1Y_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+/* Memory required for the wrkmem parameter.
-+ * When the required size is 0, you can also pass a NULL pointer.
-+ */
-+
-+#define LZO1Y_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
-+#define LZO1Y_MEM_DECOMPRESS (0)
-+#define LZO1Y_MEM_OPTIMIZE (0)
-+
-+
-+/* decompression */
-+LZO_EXTERN(int)
-+lzo1y_decompress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+/* safe decompression with overrun testing */
-+LZO_EXTERN(int)
-+lzo1y_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+LZO_EXTERN(int)
-+lzo1y_1_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/***********************************************************************
-+// better compression ratio at the cost of more memory and time
-+************************************************************************/
-+
-+#define LZO1Y_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
-+
-+LZO_EXTERN(int)
-+lzo1y_999_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+LZO_EXTERN(int)
-+lzo1y_999_compress_dict ( const lzo_bytep in , lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem,
-+ const lzo_bytep dict, lzo_uint dict_len );
-+
-+LZO_EXTERN(int)
-+lzo1y_999_compress_level ( const lzo_bytep in , lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem,
-+ const lzo_bytep dict, lzo_uint dict_len,
-+ lzo_callback_p cb,
-+ int compression_level );
-+
-+LZO_EXTERN(int)
-+lzo1y_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem /* NOT USED */,
-+ const lzo_bytep dict, lzo_uint dict_len );
-+
-+
-+/***********************************************************************
-+// optimize a compressed data block
-+************************************************************************/
-+
-+LZO_EXTERN(int)
-+lzo1y_optimize ( lzo_bytep in , lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1z.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1z.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,146 @@
-+/* lzo1z.h -- public interface of the LZO1Z compression algorithm
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO1Z_H_INCLUDED
-+#define __LZO1Z_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+/* Memory required for the wrkmem parameter.
-+ * When the required size is 0, you can also pass a NULL pointer.
-+ */
-+
-+#define LZO1Z_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
-+#define LZO1Z_MEM_DECOMPRESS (0)
-+#define LZO1Z_MEM_OPTIMIZE (0)
-+
-+
-+/* decompression */
-+LZO_EXTERN(int)
-+lzo1z_decompress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+/* safe decompression with overrun testing */
-+LZO_EXTERN(int)
-+lzo1z_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+#if 0
-+/* not yet implemented */
-+LZO_EXTERN(int)
-+lzo1z_1_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+#endif
-+
-+
-+/***********************************************************************
-+// better compression ratio at the cost of more memory and time
-+************************************************************************/
-+
-+#define LZO1Z_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
-+
-+LZO_EXTERN(int)
-+lzo1z_999_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+LZO_EXTERN(int)
-+lzo1z_999_compress_dict ( const lzo_bytep in , lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem,
-+ const lzo_bytep dict, lzo_uint dict_len );
-+
-+LZO_EXTERN(int)
-+lzo1z_999_compress_level ( const lzo_bytep in , lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem,
-+ const lzo_bytep dict, lzo_uint dict_len,
-+ lzo_callback_p cb,
-+ int compression_level );
-+
-+LZO_EXTERN(int)
-+lzo1z_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem /* NOT USED */,
-+ const lzo_bytep dict, lzo_uint dict_len );
-+
-+
-+/***********************************************************************
-+// optimize a compressed data block
-+************************************************************************/
-+
-+#if 0
-+/* not yet implemented */
-+LZO_EXTERN(int)
-+lzo1z_optimize ( lzo_bytep in , lzo_uint in_len,
-+ lzo_bytep out, lzo_uintp out_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+#endif
-+
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo2a.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo2a.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,88 @@
-+/* lzo2a.h -- public interface of the LZO2A compression algorithm
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO2A_H_INCLUDED
-+#define __LZO2A_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+//
-+************************************************************************/
-+
-+#define LZO2A_MEM_DECOMPRESS (0)
-+
-+/* decompression */
-+LZO_EXTERN(int)
-+lzo2a_decompress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+/* safe decompression with overrun testing */
-+LZO_EXTERN(int)
-+lzo2a_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem /* NOT USED */ );
-+
-+
-+/***********************************************************************
-+// better compression ratio at the cost of more memory and time
-+************************************************************************/
-+
-+#define LZO2A_999_MEM_COMPRESS ((lzo_uint32) (8 * 16384L * sizeof(short)))
-+
-+LZO_EXTERN(int)
-+lzo2a_999_compress ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo_asm.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo_asm.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,135 @@
-+/* lzo_asm.h -- assembler prototypes for the LZO data compression library
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZO_ASM_H_INCLUDED
-+#define __LZO_ASM_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+// assembly decompressors
-+************************************************************************/
-+
-+LZO_EXTERN(int) lzo1c_decompress_asm
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+LZO_EXTERN(int) lzo1c_decompress_asm_safe
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+
-+LZO_EXTERN(int) lzo1f_decompress_asm_fast
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+LZO_EXTERN(int) lzo1f_decompress_asm_fast_safe
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+
-+LZO_EXTERN(int) lzo1x_decompress_asm
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+LZO_EXTERN(int) lzo1x_decompress_asm_safe
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+LZO_EXTERN(int) lzo1x_decompress_asm_fast
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+LZO_EXTERN(int) lzo1x_decompress_asm_fast_safe
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+
-+LZO_EXTERN(int) lzo1y_decompress_asm
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+LZO_EXTERN(int) lzo1y_decompress_asm_safe
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+LZO_EXTERN(int) lzo1y_decompress_asm_fast
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+LZO_EXTERN(int) lzo1y_decompress_asm_fast_safe
-+ (const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem);
-+
-+
-+/***********************************************************************
-+// checksum and misc functions
-+************************************************************************/
-+
-+#if 0
-+
-+LZO_EXTERN(lzo_uint32)
-+lzo_crc32_asm(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len,
-+ const lzo_uint32p _crc_table);
-+
-+LZO_EXTERN(lzo_uint32)
-+lzo_crc32_asm_small(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len);
-+
-+LZO_EXTERN(int)
-+lzo_cpuid_asm(lzo_uint32p /* lzo_uint32 info[16] */ );
-+
-+LZO_EXTERN(lzo_uint32)
-+lzo_rdtsc_asm(lzo_uint32p /* lzo_uint32 ticks[2] */ );
-+
-+#endif
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoconf.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoconf.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,413 @@
-+/* lzoconf.h -- configuration for the LZO real-time data compression library
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#define __LZOCONF_H_INCLUDED
-+
-+#define LZO_VERSION 0x2020
-+#define LZO_VERSION_STRING "2.02"
-+#define LZO_VERSION_DATE "Oct 17 2005"
-+
-+/* internal Autoconf configuration file - only used when building LZO */
-+#if defined(LZO_HAVE_CONFIG_H)
-+# include
-+#endif
-+#include
-+#include
-+
-+
-+/***********************************************************************
-+// LZO requires a conforming
-+************************************************************************/
-+
-+#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
-+# error "invalid CHAR_BIT"
-+#endif
-+#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
-+# error "check your compiler installation"
-+#endif
-+#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
-+# error "your limits.h macros are broken"
-+#endif
-+
-+/* get OS and architecture defines */
-+#ifndef __LZODEFS_H_INCLUDED
-+#include "lzodefs.h"
-+#endif
-+
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+// some core defines
-+************************************************************************/
-+
-+#if !defined(LZO_UINT32_C)
-+# if (UINT_MAX < LZO_0xffffffffL)
-+# define LZO_UINT32_C(c) c ## UL
-+# else
-+# define LZO_UINT32_C(c) ((c) + 0U)
-+# endif
-+#endif
-+
-+/* memory checkers */
-+#if !defined(__LZO_CHECKER)
-+# if defined(__BOUNDS_CHECKING_ON)
-+# define __LZO_CHECKER 1
-+# elif defined(__CHECKER__)
-+# define __LZO_CHECKER 1
-+# elif defined(__INSURE__)
-+# define __LZO_CHECKER 1
-+# elif defined(__PURIFY__)
-+# define __LZO_CHECKER 1
-+# endif
-+#endif
-+
-+
-+/***********************************************************************
-+// integral and pointer types
-+************************************************************************/
-+
-+/* lzo_uint should match size_t */
-+#if !defined(LZO_UINT_MAX)
-+# if defined(LZO_ABI_LLP64) /* WIN64 */
-+# if defined(LZO_OS_WIN64)
-+ typedef unsigned __int64 lzo_uint;
-+ typedef __int64 lzo_int;
-+# else
-+ typedef unsigned long long lzo_uint;
-+ typedef long long lzo_int;
-+# endif
-+# define LZO_UINT_MAX 0xffffffffffffffffull
-+# define LZO_INT_MAX 9223372036854775807LL
-+# define LZO_INT_MIN (-1LL - LZO_INT_MAX)
-+# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */
-+ typedef unsigned int lzo_uint;
-+ typedef int lzo_int;
-+# define LZO_UINT_MAX UINT_MAX
-+# define LZO_INT_MAX INT_MAX
-+# define LZO_INT_MIN INT_MIN
-+# elif (ULONG_MAX >= LZO_0xffffffffL)
-+ typedef unsigned long lzo_uint;
-+ typedef long lzo_int;
-+# define LZO_UINT_MAX ULONG_MAX
-+# define LZO_INT_MAX LONG_MAX
-+# define LZO_INT_MIN LONG_MIN
-+# else
-+# error "lzo_uint"
-+# endif
-+#endif
-+
-+/* Integral types with 32 bits or more. */
-+#if !defined(LZO_UINT32_MAX)
-+# if (UINT_MAX >= LZO_0xffffffffL)
-+ typedef unsigned int lzo_uint32;
-+ typedef int lzo_int32;
-+# define LZO_UINT32_MAX UINT_MAX
-+# define LZO_INT32_MAX INT_MAX
-+# define LZO_INT32_MIN INT_MIN
-+# elif (ULONG_MAX >= LZO_0xffffffffL)
-+ typedef unsigned long lzo_uint32;
-+ typedef long lzo_int32;
-+# define LZO_UINT32_MAX ULONG_MAX
-+# define LZO_INT32_MAX LONG_MAX
-+# define LZO_INT32_MIN LONG_MIN
-+# else
-+# error "lzo_uint32"
-+# endif
-+#endif
-+
-+/* The larger type of lzo_uint and lzo_uint32. */
-+#if (LZO_UINT_MAX >= LZO_UINT32_MAX)
-+# define lzo_xint lzo_uint
-+#else
-+# define lzo_xint lzo_uint32
-+#endif
-+
-+/* Memory model that allows to access memory at offsets of lzo_uint. */
-+#if !defined(__LZO_MMODEL)
-+# if (LZO_UINT_MAX <= UINT_MAX)
-+# define __LZO_MMODEL
-+# elif defined(LZO_HAVE_MM_HUGE_PTR)
-+# define __LZO_MMODEL_HUGE 1
-+# define __LZO_MMODEL __huge
-+# else
-+# define __LZO_MMODEL
-+# endif
-+#endif
-+
-+/* no typedef here because of const-pointer issues */
-+#define lzo_bytep unsigned char __LZO_MMODEL *
-+#define lzo_charp char __LZO_MMODEL *
-+#define lzo_voidp void __LZO_MMODEL *
-+#define lzo_shortp short __LZO_MMODEL *
-+#define lzo_ushortp unsigned short __LZO_MMODEL *
-+#define lzo_uint32p lzo_uint32 __LZO_MMODEL *
-+#define lzo_int32p lzo_int32 __LZO_MMODEL *
-+#define lzo_uintp lzo_uint __LZO_MMODEL *
-+#define lzo_intp lzo_int __LZO_MMODEL *
-+#define lzo_xintp lzo_xint __LZO_MMODEL *
-+#define lzo_voidpp lzo_voidp __LZO_MMODEL *
-+#define lzo_bytepp lzo_bytep __LZO_MMODEL *
-+/* deprecated - use `lzo_bytep' instead of `lzo_byte *' */
-+#define lzo_byte unsigned char __LZO_MMODEL
-+
-+typedef int lzo_bool;
-+
-+
-+/***********************************************************************
-+// function types
-+************************************************************************/
-+
-+/* name mangling */
-+#if !defined(__LZO_EXTERN_C)
-+# ifdef __cplusplus
-+# define __LZO_EXTERN_C extern "C"
-+# else
-+# define __LZO_EXTERN_C extern
-+# endif
-+#endif
-+
-+/* calling convention */
-+#if !defined(__LZO_CDECL)
-+# define __LZO_CDECL __lzo_cdecl
-+#endif
-+
-+/* DLL export information */
-+#if !defined(__LZO_EXPORT1)
-+# define __LZO_EXPORT1
-+#endif
-+#if !defined(__LZO_EXPORT2)
-+# define __LZO_EXPORT2
-+#endif
-+
-+/* __cdecl calling convention for public C and assembly functions */
-+#if !defined(LZO_PUBLIC)
-+# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
-+#endif
-+#if !defined(LZO_EXTERN)
-+# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
-+#endif
-+#if !defined(LZO_PRIVATE)
-+# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL
-+#endif
-+
-+/* function types */
-+typedef int
-+(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+typedef int
-+(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+typedef int
-+(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem );
-+
-+typedef int
-+(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem,
-+ const lzo_bytep dict, lzo_uint dict_len );
-+
-+typedef int
-+(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len,
-+ lzo_bytep dst, lzo_uintp dst_len,
-+ lzo_voidp wrkmem,
-+ const lzo_bytep dict, lzo_uint dict_len );
-+
-+
-+/* Callback interface. Currently only the progress indicator ("nprogress")
-+ * is used, but this may change in a future release. */
-+
-+struct lzo_callback_t;
-+typedef struct lzo_callback_t lzo_callback_t;
-+#define lzo_callback_p lzo_callback_t __LZO_MMODEL *
-+
-+/* malloc & free function types */
-+typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t)
-+ (lzo_callback_p self, lzo_uint items, lzo_uint size);
-+typedef void (__LZO_CDECL *lzo_free_func_t)
-+ (lzo_callback_p self, lzo_voidp ptr);
-+
-+/* a progress indicator callback function */
-+typedef void (__LZO_CDECL *lzo_progress_func_t)
-+ (lzo_callback_p, lzo_uint, lzo_uint, int);
-+
-+struct lzo_callback_t
-+{
-+ /* custom allocators (set to 0 to disable) */
-+ lzo_alloc_func_t nalloc; /* [not used right now] */
-+ lzo_free_func_t nfree; /* [not used right now] */
-+
-+ /* a progress indicator callback function (set to 0 to disable) */
-+ lzo_progress_func_t nprogress;
-+
-+ /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress
-+ * callbacks points back to this struct, so you are free to store
-+ * some extra info in the following variables. */
-+ lzo_voidp user1;
-+ lzo_xint user2;
-+ lzo_xint user3;
-+};
-+
-+
-+/***********************************************************************
-+// error codes and prototypes
-+************************************************************************/
-+
-+/* Error codes for the compression/decompression functions. Negative
-+ * values are errors, positive values will be used for special but
-+ * normal events.
-+ */
-+#define LZO_E_OK 0
-+#define LZO_E_ERROR (-1)
-+#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */
-+#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
-+#define LZO_E_INPUT_OVERRUN (-4)
-+#define LZO_E_OUTPUT_OVERRUN (-5)
-+#define LZO_E_LOOKBEHIND_OVERRUN (-6)
-+#define LZO_E_EOF_NOT_FOUND (-7)
-+#define LZO_E_INPUT_NOT_CONSUMED (-8)
-+#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
-+
-+
-+#ifndef lzo_sizeof_dict_t
-+# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep))
-+#endif
-+
-+/* lzo_init() should be the first function you call.
-+ * Check the return code !
-+ *
-+ * lzo_init() is a macro to allow checking that the library and the
-+ * compiler's view of various types are consistent.
-+ */
-+#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
-+ (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
-+ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
-+ (int)sizeof(lzo_callback_t))
-+LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
-+
-+/* version functions (useful for shared libraries) */
-+LZO_EXTERN(unsigned) lzo_version(void);
-+LZO_EXTERN(const char *) lzo_version_string(void);
-+LZO_EXTERN(const char *) lzo_version_date(void);
-+LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
-+LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
-+
-+/* string functions */
-+LZO_EXTERN(int)
-+lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len);
-+LZO_EXTERN(lzo_voidp)
-+lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
-+LZO_EXTERN(lzo_voidp)
-+lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
-+LZO_EXTERN(lzo_voidp)
-+lzo_memset(lzo_voidp _s, int _c, lzo_uint _len);
-+
-+/* checksum functions */
-+LZO_EXTERN(lzo_uint32)
-+lzo_adler32(lzo_uint32 _adler, const lzo_bytep _buf, lzo_uint _len);
-+LZO_EXTERN(lzo_uint32)
-+lzo_crc32(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len);
-+LZO_EXTERN(const lzo_uint32p)
-+lzo_get_crc32_table(void);
-+
-+/* misc. */
-+LZO_EXTERN(int) _lzo_config_check(void);
-+typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
-+typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
-+typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t;
-+
-+/* align a char pointer on a boundary that is a multiple of `size' */
-+LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size);
-+#define LZO_PTR_ALIGN_UP(_ptr,_size) \
-+ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size)))
-+
-+
-+/***********************************************************************
-+// deprecated macros - only for backward compatibility with LZO v1.xx
-+************************************************************************/
-+
-+#if defined(LZO_CFG_COMPAT)
-+
-+#define __LZOCONF_H 1
-+
-+#if defined(LZO_ARCH_I086)
-+# define __LZO_i386 1
-+#elif defined(LZO_ARCH_I386)
-+# define __LZO_i386 1
-+#endif
-+
-+#if defined(LZO_OS_DOS16)
-+# define __LZO_DOS 1
-+# define __LZO_DOS16 1
-+#elif defined(LZO_OS_DOS32)
-+# define __LZO_DOS 1
-+#elif defined(LZO_OS_WIN16)
-+# define __LZO_WIN 1
-+# define __LZO_WIN16 1
-+#elif defined(LZO_OS_WIN32)
-+# define __LZO_WIN 1
-+#endif
-+
-+#define __LZO_CMODEL
-+#define __LZO_DMODEL
-+#define __LZO_ENTRY __LZO_CDECL
-+#define LZO_EXTERN_CDECL LZO_EXTERN
-+#define LZO_ALIGN LZO_PTR_ALIGN_UP
-+
-+#define lzo_compress_asm_t lzo_compress_t
-+#define lzo_decompress_asm_t lzo_decompress_t
-+
-+#endif /* LZO_CFG_COMPAT */
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzodefs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzodefs.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1545 @@
-+/* lzodefs.h -- architecture, OS and compiler specific defines
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZODEFS_H_INCLUDED
-+#define __LZODEFS_H_INCLUDED 1
-+
-+#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
-+# define __CYGWIN__ __CYGWIN32__
-+#endif
-+#if defined(__IBMCPP__) && !defined(__IBMC__)
-+# define __IBMC__ __IBMCPP__
-+#endif
-+#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)
-+# define __INTEL_COMPILER __ICL
-+#endif
-+#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)
-+# define _ALL_SOURCE 1
-+#endif
-+#if defined(__mips__) && defined(__R5900__)
-+# if !defined(__LONG_MAX__)
-+# define __LONG_MAX__ 9223372036854775807L
-+# endif
-+#endif
-+#if defined(__INTEL_COMPILER) && defined(__linux__)
-+# pragma warning(disable: 193)
-+#endif
-+#if defined(__KEIL__) && defined(__C166__)
-+# pragma warning disable = 322
-+#elif 0 && defined(__C251__)
-+# pragma warning disable = 322
-+#endif
-+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
-+# if (_MSC_VER >= 1300)
-+# pragma warning(disable: 4668)
-+# endif
-+#endif
-+#if 0 && defined(__WATCOMC__)
-+# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)
-+# pragma warning 203 9
-+# endif
-+#endif
-+#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)
-+# pragma option -h
-+#endif
-+#if 0
-+#define LZO_0xffffL 0xfffful
-+#define LZO_0xffffffffL 0xfffffffful
-+#else
-+#define LZO_0xffffL 65535ul
-+#define LZO_0xffffffffL 4294967295ul
-+#endif
-+#if (LZO_0xffffL == LZO_0xffffffffL)
-+# error "your preprocessor is broken 1"
-+#endif
-+#if (16ul * 16384ul != 262144ul)
-+# error "your preprocessor is broken 2"
-+#endif
-+#if 0
-+#if (32767 >= 4294967295ul)
-+# error "your preprocessor is broken 3"
-+#endif
-+#if (65535u >= 4294967295ul)
-+# error "your preprocessor is broken 4"
-+#endif
-+#endif
-+#if (UINT_MAX == LZO_0xffffL)
-+#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)
-+# if !defined(MSDOS)
-+# define MSDOS 1
-+# endif
-+# if !defined(_MSDOS)
-+# define _MSDOS 1
-+# endif
-+#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX)
-+# if (__VERSION == 520) && (MB_LEN_MAX == 1)
-+# if !defined(__AZTEC_C__)
-+# define __AZTEC_C__ __VERSION
-+# endif
-+# if !defined(__DOS__)
-+# define __DOS__ 1
-+# endif
-+# endif
-+#endif
-+#endif
-+#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
-+# define ptrdiff_t long
-+# define _PTRDIFF_T_DEFINED
-+#endif
-+#if (UINT_MAX == LZO_0xffffL)
-+# undef __LZO_RENAME_A
-+# undef __LZO_RENAME_B
-+# if defined(__AZTEC_C__) && defined(__DOS__)
-+# define __LZO_RENAME_A 1
-+# elif defined(_MSC_VER) && defined(MSDOS)
-+# if (_MSC_VER < 600)
-+# define __LZO_RENAME_A 1
-+# elif (_MSC_VER < 700)
-+# define __LZO_RENAME_B 1
-+# endif
-+# elif defined(__TSC__) && defined(__OS2__)
-+# define __LZO_RENAME_A 1
-+# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410)
-+# define __LZO_RENAME_A 1
-+# elif defined(__PACIFIC__) && defined(DOS)
-+# if !defined(__far)
-+# define __far far
-+# endif
-+# if !defined(__near)
-+# define __near near
-+# endif
-+# endif
-+# if defined(__LZO_RENAME_A)
-+# if !defined(__cdecl)
-+# define __cdecl cdecl
-+# endif
-+# if !defined(__far)
-+# define __far far
-+# endif
-+# if !defined(__huge)
-+# define __huge huge
-+# endif
-+# if !defined(__near)
-+# define __near near
-+# endif
-+# if !defined(__pascal)
-+# define __pascal pascal
-+# endif
-+# if !defined(__huge)
-+# define __huge huge
-+# endif
-+# elif defined(__LZO_RENAME_B)
-+# if !defined(__cdecl)
-+# define __cdecl _cdecl
-+# endif
-+# if !defined(__far)
-+# define __far _far
-+# endif
-+# if !defined(__huge)
-+# define __huge _huge
-+# endif
-+# if !defined(__near)
-+# define __near _near
-+# endif
-+# if !defined(__pascal)
-+# define __pascal _pascal
-+# endif
-+# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
-+# if !defined(__cdecl)
-+# define __cdecl cdecl
-+# endif
-+# if !defined(__pascal)
-+# define __pascal pascal
-+# endif
-+# endif
-+# undef __LZO_RENAME_A
-+# undef __LZO_RENAME_B
-+#endif
-+#if (UINT_MAX == LZO_0xffffL)
-+#if defined(__AZTEC_C__) && defined(__DOS__)
-+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
-+#elif defined(_MSC_VER) && defined(MSDOS)
-+# if (_MSC_VER < 600)
-+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
-+# endif
-+# if (_MSC_VER < 700)
-+# define LZO_BROKEN_INTEGRAL_PROMOTION 1
-+# define LZO_BROKEN_SIZEOF 1
-+# endif
-+#elif defined(__PACIFIC__) && defined(DOS)
-+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
-+#elif defined(__TURBOC__) && defined(__MSDOS__)
-+# if (__TURBOC__ < 0x0150)
-+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
-+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
-+# define LZO_BROKEN_INTEGRAL_PROMOTION 1
-+# endif
-+# if (__TURBOC__ < 0x0200)
-+# define LZO_BROKEN_SIZEOF 1
-+# endif
-+# if (__TURBOC__ < 0x0400) && defined(__cplusplus)
-+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
-+# endif
-+#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
-+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
-+# define LZO_BROKEN_SIZEOF 1
-+#endif
-+#endif
-+#if defined(__WATCOMC__) && (__WATCOMC__ < 900)
-+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
-+#endif
-+#define LZO_CPP_STRINGIZE(x) #x
-+#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x)
-+#define LZO_CPP_CONCAT2(a,b) a ## b
-+#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c
-+#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d
-+#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
-+#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b)
-+#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c)
-+#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d)
-+#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e)
-+#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o))
-+#if 1 && defined(__cplusplus)
-+# if !defined(__STDC_CONSTANT_MACROS)
-+# define __STDC_CONSTANT_MACROS 1
-+# endif
-+# if !defined(__STDC_LIMIT_MACROS)
-+# define __STDC_LIMIT_MACROS 1
-+# endif
-+#endif
-+#if defined(__cplusplus)
-+# define LZO_EXTERN_C extern "C"
-+#else
-+# define LZO_EXTERN_C extern
-+#endif
-+#if !defined(__LZO_OS_OVERRIDE)
-+#if defined(LZO_OS_FREESTANDING)
-+# define LZO_INFO_OS "freestanding"
-+#elif defined(LZO_OS_EMBEDDED)
-+# define LZO_INFO_OS "embedded"
-+#elif defined(__CYGWIN__) && defined(__GNUC__)
-+# define LZO_OS_CYGWIN 1
-+# define LZO_INFO_OS "cygwin"
-+#elif defined(__EMX__) && defined(__GNUC__)
-+# define LZO_OS_EMX 1
-+# define LZO_INFO_OS "emx"
-+#elif defined(__BEOS__)
-+# define LZO_OS_BEOS 1
-+# define LZO_INFO_OS "beos"
-+#elif defined(__Lynx__)
-+# define LZO_OS_LYNXOS 1
-+# define LZO_INFO_OS "lynxos"
-+#elif defined(__OS400__)
-+# define LZO_OS_OS400 1
-+# define LZO_INFO_OS "os400"
-+#elif defined(__QNX__)
-+# define LZO_OS_QNX 1
-+# define LZO_INFO_OS "qnx"
-+#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460)
-+# define LZO_OS_DOS32 1
-+# define LZO_INFO_OS "dos32"
-+#elif defined(__BORLANDC__) && defined(__DPMI16__)
-+# define LZO_OS_DOS16 1
-+# define LZO_INFO_OS "dos16"
-+#elif defined(__ZTC__) && defined(DOS386)
-+# define LZO_OS_DOS32 1
-+# define LZO_INFO_OS "dos32"
-+#elif defined(__OS2__) || defined(__OS2V2__)
-+# if (UINT_MAX == LZO_0xffffL)
-+# define LZO_OS_OS216 1
-+# define LZO_INFO_OS "os216"
-+# elif (UINT_MAX == LZO_0xffffffffL)
-+# define LZO_OS_OS2 1
-+# define LZO_INFO_OS "os2"
-+# else
-+# error "check your limits.h header"
-+# endif
-+#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64)
-+# define LZO_OS_WIN64 1
-+# define LZO_INFO_OS "win64"
-+#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__)
-+# define LZO_OS_WIN32 1
-+# define LZO_INFO_OS "win32"
-+#elif defined(__MWERKS__) && defined(__INTEL__)
-+# define LZO_OS_WIN32 1
-+# define LZO_INFO_OS "win32"
-+#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
-+# if (UINT_MAX == LZO_0xffffL)
-+# define LZO_OS_WIN16 1
-+# define LZO_INFO_OS "win16"
-+# elif (UINT_MAX == LZO_0xffffffffL)
-+# define LZO_OS_WIN32 1
-+# define LZO_INFO_OS "win32"
-+# else
-+# error "check your limits.h header"
-+# endif
-+#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS))
-+# if (UINT_MAX == LZO_0xffffL)
-+# define LZO_OS_DOS16 1
-+# define LZO_INFO_OS "dos16"
-+# elif (UINT_MAX == LZO_0xffffffffL)
-+# define LZO_OS_DOS32 1
-+# define LZO_INFO_OS "dos32"
-+# else
-+# error "check your limits.h header"
-+# endif
-+#elif defined(__WATCOMC__)
-+# if defined(__NT__) && (UINT_MAX == LZO_0xffffL)
-+# define LZO_OS_DOS16 1
-+# define LZO_INFO_OS "dos16"
-+# elif defined(__NT__) && (__WATCOMC__ < 1100)
-+# define LZO_OS_WIN32 1
-+# define LZO_INFO_OS "win32"
-+# else
-+# error "please specify a target using the -bt compiler option"
-+# endif
-+#elif defined(__palmos__)
-+# define LZO_OS_PALMOS 1
-+# define LZO_INFO_OS "palmos"
-+#elif defined(__TOS__) || defined(__atarist__)
-+# define LZO_OS_TOS 1
-+# define LZO_INFO_OS "tos"
-+#elif defined(macintosh) && !defined(__ppc__)
-+# define LZO_OS_MACCLASSIC 1
-+# define LZO_INFO_OS "macclassic"
-+#elif defined(__VMS)
-+# define LZO_OS_VMS 1
-+# define LZO_INFO_OS "vms"
-+#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
-+# define LZO_OS_CONSOLE 1
-+# define LZO_OS_CONSOLE_PS2 1
-+# define LZO_INFO_OS "console"
-+# define LZO_INFO_OS_CONSOLE "ps2"
-+#elif (defined(__mips__) && defined(__psp__))
-+# define LZO_OS_CONSOLE 1
-+# define LZO_OS_CONSOLE_PSP 1
-+# define LZO_INFO_OS "console"
-+# define LZO_INFO_OS_CONSOLE "psp"
-+#else
-+# define LZO_OS_POSIX 1
-+# define LZO_INFO_OS "posix"
-+#endif
-+#if (LZO_OS_POSIX)
-+# if defined(_AIX) || defined(__AIX__) || defined(__aix__)
-+# define LZO_OS_POSIX_AIX 1
-+# define LZO_INFO_OS_POSIX "aix"
-+# elif defined(__FreeBSD__)
-+# define LZO_OS_POSIX_FREEBSD 1
-+# define LZO_INFO_OS_POSIX "freebsd"
-+# elif defined(__hpux__) || defined(__hpux)
-+# define LZO_OS_POSIX_HPUX 1
-+# define LZO_INFO_OS_POSIX "hpux"
-+# elif defined(__INTERIX)
-+# define LZO_OS_POSIX_INTERIX 1
-+# define LZO_INFO_OS_POSIX "interix"
-+# elif defined(__IRIX__) || defined(__irix__)
-+# define LZO_OS_POSIX_IRIX 1
-+# define LZO_INFO_OS_POSIX "irix"
-+# elif defined(__linux__) || defined(__linux)
-+# define LZO_OS_POSIX_LINUX 1
-+# define LZO_INFO_OS_POSIX "linux"
-+# elif defined(__APPLE__) || defined(__MACOS__)
-+# define LZO_OS_POSIX_MACOSX 1
-+# define LZO_INFO_OS_POSIX "macosx"
-+# elif defined(__NetBSD__)
-+# define LZO_OS_POSIX_NETBSD 1
-+# define LZO_INFO_OS_POSIX "netbsd"
-+# elif defined(__OpenBSD__)
-+# define LZO_OS_POSIX_OPENBSD 1
-+# define LZO_INFO_OS_POSIX "openbsd"
-+# elif defined(__osf__)
-+# define LZO_OS_POSIX_OSF 1
-+# define LZO_INFO_OS_POSIX "osf"
-+# elif defined(__solaris__) || defined(__sun)
-+# if defined(__SVR4) || defined(__svr4__)
-+# define LZO_OS_POSIX_SOLARIS 1
-+# define LZO_INFO_OS_POSIX "solaris"
-+# else
-+# define LZO_OS_POSIX_SUNOS 1
-+# define LZO_INFO_OS_POSIX "sunos"
-+# endif
-+# elif defined(__ultrix__) || defined(__ultrix)
-+# define LZO_OS_POSIX_ULTRIX 1
-+# define LZO_INFO_OS_POSIX "ultrix"
-+# else
-+# define LZO_OS_POSIX_UNKNOWN 1
-+# define LZO_INFO_OS_POSIX "unknown"
-+# endif
-+#endif
-+#endif
-+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
-+# if (UINT_MAX != LZO_0xffffL)
-+# error "this should not happen"
-+# endif
-+# if (ULONG_MAX != LZO_0xffffffffL)
-+# error "this should not happen"
-+# endif
-+#endif
-+#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64)
-+# if (UINT_MAX != LZO_0xffffffffL)
-+# error "this should not happen"
-+# endif
-+# if (ULONG_MAX != LZO_0xffffffffL)
-+# error "this should not happen"
-+# endif
-+#endif
-+#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)
-+# define LZO_CC_CILLY 1
-+# define LZO_INFO_CC "Cilly"
-+# if defined(__CILLY__)
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__CILLY__)
-+# else
-+# define LZO_INFO_CCVER "unknown"
-+# endif
-+#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__)
-+# define LZO_CC_SDCC 1
-+# define LZO_INFO_CC "sdcc"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(SDCC)
-+#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)
-+# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)
-+# define LZO_INFO_CC "Pathscale C"
-+# define LZO_INFO_CCVER __PATHSCALE__
-+#elif defined(__INTEL_COMPILER)
-+# define LZO_CC_INTELC 1
-+# define LZO_INFO_CC "Intel C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__INTEL_COMPILER)
-+#elif defined(__POCC__) && defined(_WIN32)
-+# define LZO_CC_PELLESC 1
-+# define LZO_INFO_CC "Pelles C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__POCC__)
-+#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__)
-+# define LZO_CC_LLVM 1
-+# define LZO_INFO_CC "llvm-gcc"
-+# define LZO_INFO_CCVER __VERSION__
-+#elif defined(__GNUC__) && defined(__VERSION__)
-+# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
-+# elif defined(__GNUC_MINOR__)
-+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
-+# else
-+# define LZO_CC_GNUC (__GNUC__ * 0x10000L)
-+# endif
-+# define LZO_INFO_CC "gcc"
-+# define LZO_INFO_CCVER __VERSION__
-+#elif defined(__AZTEC_C__)
-+# define LZO_CC_AZTECC 1
-+# define LZO_INFO_CC "Aztec C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__AZTEC_C__)
-+#elif defined(__BORLANDC__)
-+# define LZO_CC_BORLANDC 1
-+# define LZO_INFO_CC "Borland C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__BORLANDC__)
-+#elif defined(__DMC__) && defined(__SC__)
-+# define LZO_CC_DMC 1
-+# define LZO_INFO_CC "Digital Mars C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__DMC__)
-+#elif defined(__DECC)
-+# define LZO_CC_DECC 1
-+# define LZO_INFO_CC "DEC C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__DECC)
-+#elif defined(__HIGHC__)
-+# define LZO_CC_HIGHC 1
-+# define LZO_INFO_CC "MetaWare High C"
-+# define LZO_INFO_CCVER "unknown"
-+#elif defined(__IBMC__)
-+# define LZO_CC_IBMC 1
-+# define LZO_INFO_CC "IBM C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__IBMC__)
-+#elif defined(__KEIL__) && defined(__C166__)
-+# define LZO_CC_KEILC 1
-+# define LZO_INFO_CC "Keil C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__C166__)
-+#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL)
-+# define LZO_CC_LCCWIN32 1
-+# define LZO_INFO_CC "lcc-win32"
-+# define LZO_INFO_CCVER "unknown"
-+#elif defined(__LCC__)
-+# define LZO_CC_LCC 1
-+# define LZO_INFO_CC "lcc"
-+# if defined(__LCC_VERSION__)
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__LCC_VERSION__)
-+# else
-+# define LZO_INFO_CCVER "unknown"
-+# endif
-+#elif defined(_MSC_VER)
-+# define LZO_CC_MSC 1
-+# define LZO_INFO_CC "Microsoft C"
-+# if defined(_MSC_FULL_VER)
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(_MSC_VER) "." LZO_CPP_MACRO_EXPAND(_MSC_FULL_VER)
-+# else
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(_MSC_VER)
-+# endif
-+#elif defined(__MWERKS__)
-+# define LZO_CC_MWERKS 1
-+# define LZO_INFO_CC "Metrowerks C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__MWERKS__)
-+#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)
-+# define LZO_CC_NDPC 1
-+# define LZO_INFO_CC "Microway NDP C"
-+# define LZO_INFO_CCVER "unknown"
-+#elif defined(__PACIFIC__)
-+# define LZO_CC_PACIFICC 1
-+# define LZO_INFO_CC "Pacific C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__PACIFIC__)
-+#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))
-+# define LZO_CC_PGI 1
-+# define LZO_INFO_CC "Portland Group PGI C"
-+# define LZO_INFO_CCVER "unknown"
-+#elif defined(__PUREC__) && defined(__TOS__)
-+# define LZO_CC_PUREC 1
-+# define LZO_INFO_CC "Pure C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__PUREC__)
-+#elif defined(__SC__) && defined(__ZTC__)
-+# define LZO_CC_SYMANTECC 1
-+# define LZO_INFO_CC "Symantec C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__SC__)
-+#elif defined(__SUNPRO_C)
-+# define LZO_CC_SUNPROC 1
-+# define LZO_INFO_CC "Sun C"
-+# define LZO_INFO_CCVER "unknown"
-+#elif defined(__TINYC__)
-+# define LZO_CC_TINYC 1
-+# define LZO_INFO_CC "Tiny C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__TINYC__)
-+#elif defined(__TSC__)
-+# define LZO_CC_TOPSPEEDC 1
-+# define LZO_INFO_CC "TopSpeed C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__TSC__)
-+#elif defined(__WATCOMC__)
-+# define LZO_CC_WATCOMC 1
-+# define LZO_INFO_CC "Watcom C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__WATCOMC__)
-+#elif defined(__TURBOC__)
-+# define LZO_CC_TURBOC 1
-+# define LZO_INFO_CC "Turbo C"
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__TURBOC__)
-+#elif defined(__ZTC__)
-+# define LZO_CC_ZORTECHC 1
-+# define LZO_INFO_CC "Zortech C"
-+# if (__ZTC__ == 0x310)
-+# define LZO_INFO_CCVER "0x310"
-+# else
-+# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__ZTC__)
-+# endif
-+#else
-+# define LZO_CC_UNKNOWN 1
-+# define LZO_INFO_CC "unknown"
-+# define LZO_INFO_CCVER "unknown"
-+#endif
-+#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
-+# error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
-+#endif
-+#if !defined(__LZO_ARCH_OVERRIDE)
-+#if defined(LZO_ARCH_GENERIC)
-+# define LZO_INFO_ARCH "generic"
-+#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
-+# define LZO_ARCH_I086 1
-+# define LZO_ARCH_IA16 1
-+# define LZO_INFO_ARCH "i086"
-+#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
-+# define LZO_ARCH_ALPHA 1
-+# define LZO_INFO_ARCH "alpha"
-+#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
-+# define LZO_ARCH_AMD64 1
-+# define LZO_INFO_ARCH "amd64"
-+#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))
-+# define LZO_ARCH_ARM 1
-+# define LZO_ARCH_ARM_THUMB 1
-+# define LZO_INFO_ARCH "arm_thumb"
-+#elif defined(__arm__) || defined(_M_ARM)
-+# define LZO_ARCH_ARM 1
-+# define LZO_INFO_ARCH "arm"
-+#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
-+# define LZO_ARCH_AVR 1
-+# define LZO_INFO_ARCH "avr"
-+#elif defined(__bfin__)
-+# define LZO_ARCH_BLACKFIN 1
-+# define LZO_INFO_ARCH "blackfin"
-+#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__)
-+# define LZO_ARCH_C166 1
-+# define LZO_INFO_ARCH "c166"
-+#elif defined(__cris__)
-+# define LZO_ARCH_CRIS 1
-+# define LZO_INFO_ARCH "cris"
-+#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
-+# define LZO_ARCH_H8300 1
-+# define LZO_INFO_ARCH "h8300"
-+#elif defined(__hppa__) || defined(__hppa)
-+# define LZO_ARCH_HPPA 1
-+# define LZO_INFO_ARCH "hppa"
-+#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
-+# define LZO_ARCH_I386 1
-+# define LZO_ARCH_IA32 1
-+# define LZO_INFO_ARCH "i386"
-+#elif (LZO_CC_ZORTECHC && defined(__I86__))
-+# define LZO_ARCH_I386 1
-+# define LZO_ARCH_IA32 1
-+# define LZO_INFO_ARCH "i386"
-+#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386)
-+# define LZO_ARCH_I386 1
-+# define LZO_ARCH_IA32 1
-+# define LZO_INFO_ARCH "i386"
-+#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
-+# define LZO_ARCH_IA64 1
-+# define LZO_INFO_ARCH "ia64"
-+#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__)
-+# define LZO_ARCH_M16C 1
-+# define LZO_INFO_ARCH "m16c"
-+#elif defined(__m32r__)
-+# define LZO_ARCH_M32R 1
-+# define LZO_INFO_ARCH "m32r"
-+#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(_M_M68K)
-+# define LZO_ARCH_M68K 1
-+# define LZO_INFO_ARCH "m68k"
-+#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__)
-+# define LZO_ARCH_MCS251 1
-+# define LZO_INFO_ARCH "mcs251"
-+#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__)
-+# define LZO_ARCH_MCS51 1
-+# define LZO_INFO_ARCH "mcs51"
-+#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
-+# define LZO_ARCH_MIPS 1
-+# define LZO_INFO_ARCH "mips"
-+#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__)
-+# define LZO_ARCH_MSP430 1
-+# define LZO_INFO_ARCH "msp430"
-+#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC)
-+# define LZO_ARCH_POWERPC 1
-+# define LZO_INFO_ARCH "powerpc"
-+#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
-+# define LZO_ARCH_S390 1
-+# define LZO_INFO_ARCH "s390"
-+#elif defined(__sh__) || defined(_M_SH)
-+# define LZO_ARCH_SH 1
-+# define LZO_INFO_ARCH "sh"
-+#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
-+# define LZO_ARCH_SPARC 1
-+# define LZO_INFO_ARCH "sparc"
-+#elif (UINT_MAX == LZO_0xffffL) && defined(__z80)
-+# define LZO_ARCH_Z80 1
-+# define LZO_INFO_ARCH "z80"
-+#else
-+# define LZO_ARCH_UNKNOWN 1
-+# define LZO_INFO_ARCH "unknown"
-+#endif
-+#endif
-+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2)
-+# error "FIXME - missing define for CPU architecture"
-+#endif
-+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32)
-+# error "FIXME - missing WIN32 define for CPU architecture"
-+#endif
-+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64)
-+# error "FIXME - missing WIN64 define for CPU architecture"
-+#endif
-+#if (LZO_OS_OS216 || LZO_OS_WIN16)
-+# define LZO_ARCH_I086PM 1
-+# define LZO_ARCH_IA16PM 1
-+#elif 1 && (LZO_OS_DOS16 && defined(BLX286))
-+# define LZO_ARCH_I086PM 1
-+# define LZO_ARCH_IA16PM 1
-+#elif 1 && (LZO_OS_DOS16 && defined(DOSX286))
-+# define LZO_ARCH_I086PM 1
-+# define LZO_ARCH_IA16PM 1
-+#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__))
-+# define LZO_ARCH_I086PM 1
-+# define LZO_ARCH_IA16PM 1
-+#endif
-+#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM)
-+# error "this should not happen"
-+#endif
-+#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086)
-+# error "this should not happen"
-+#endif
-+#if (LZO_ARCH_I086)
-+# if (UINT_MAX != LZO_0xffffL)
-+# error "this should not happen"
-+# endif
-+# if (ULONG_MAX != LZO_0xffffffffL)
-+# error "this should not happen"
-+# endif
-+#endif
-+#if (LZO_ARCH_I386)
-+# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__)
-+# error "this should not happen"
-+# endif
-+# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__)
-+# error "this should not happen"
-+# endif
-+# if (ULONG_MAX != LZO_0xffffffffL)
-+# error "this should not happen"
-+# endif
-+#endif
-+#if !defined(__LZO_MM_OVERRIDE)
-+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
-+#if (UINT_MAX != LZO_0xffffL)
-+# error "this should not happen"
-+#endif
-+#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)
-+# define LZO_MM_TINY 1
-+#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM)
-+# define LZO_MM_HUGE 1
-+#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL)
-+# define LZO_MM_SMALL 1
-+#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM)
-+# define LZO_MM_MEDIUM 1
-+#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM)
-+# define LZO_MM_COMPACT 1
-+#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL)
-+# define LZO_MM_LARGE 1
-+#elif (LZO_CC_AZTECC)
-+# if defined(_LARGE_CODE) && defined(_LARGE_DATA)
-+# define LZO_MM_LARGE 1
-+# elif defined(_LARGE_CODE)
-+# define LZO_MM_MEDIUM 1
-+# elif defined(_LARGE_DATA)
-+# define LZO_MM_COMPACT 1
-+# else
-+# define LZO_MM_SMALL 1
-+# endif
-+#elif (LZO_CC_ZORTECHC && defined(__VCM__))
-+# define LZO_MM_LARGE 1
-+#else
-+# error "unknown memory model"
-+#endif
-+#define LZO_HAVE_MM_HUGE_PTR 1
-+#define LZO_HAVE_MM_HUGE_ARRAY 1
-+#if (LZO_MM_TINY)
-+# undef LZO_HAVE_MM_HUGE_ARRAY
-+#endif
-+#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC)
-+# undef LZO_HAVE_MM_HUGE_PTR
-+# undef LZO_HAVE_MM_HUGE_ARRAY
-+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
-+# undef LZO_HAVE_MM_HUGE_ARRAY
-+#elif (LZO_CC_MSC && defined(_QC))
-+# undef LZO_HAVE_MM_HUGE_ARRAY
-+# if (_MSC_VER < 600)
-+# undef LZO_HAVE_MM_HUGE_PTR
-+# endif
-+#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295))
-+# undef LZO_HAVE_MM_HUGE_ARRAY
-+#endif
-+#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR)
-+# if (LZO_OS_DOS16)
-+# error "this should not happen"
-+# elif (LZO_CC_ZORTECHC)
-+# else
-+# error "this should not happen"
-+# endif
-+#endif
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200))
-+ extern void __near __cdecl _AHSHIFT(void);
-+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
-+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
-+ extern void __near __cdecl _AHSHIFT(void);
-+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
-+#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC)
-+ extern void __near __cdecl _AHSHIFT(void);
-+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
-+#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295))
-+ extern void __near __cdecl _AHSHIFT(void);
-+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
-+#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16)
-+# define LZO_MM_AHSHIFT 12
-+#elif (LZO_CC_WATCOMC)
-+ extern unsigned char _HShift;
-+# define LZO_MM_AHSHIFT ((unsigned) _HShift)
-+#else
-+# error "FIXME - implement LZO_MM_AHSHIFT"
-+#endif
-+#ifdef __cplusplus
-+}
-+#endif
-+#elif (LZO_ARCH_C166)
-+#if !defined(__MODEL__)
-+# error "FIXME - C166 __MODEL__"
-+#elif ((__MODEL__) == 0)
-+# define LZO_MM_SMALL 1
-+#elif ((__MODEL__) == 1)
-+# define LZO_MM_SMALL 1
-+#elif ((__MODEL__) == 2)
-+# define LZO_MM_LARGE 1
-+#elif ((__MODEL__) == 3)
-+# define LZO_MM_TINY 1
-+#elif ((__MODEL__) == 4)
-+# define LZO_MM_XTINY 1
-+#elif ((__MODEL__) == 5)
-+# define LZO_MM_XSMALL 1
-+#else
-+# error "FIXME - C166 __MODEL__"
-+#endif
-+#elif (LZO_ARCH_MCS251)
-+#if !defined(__MODEL__)
-+# error "FIXME - MCS251 __MODEL__"
-+#elif ((__MODEL__) == 0)
-+# define LZO_MM_SMALL 1
-+#elif ((__MODEL__) == 2)
-+# define LZO_MM_LARGE 1
-+#elif ((__MODEL__) == 3)
-+# define LZO_MM_TINY 1
-+#elif ((__MODEL__) == 4)
-+# define LZO_MM_XTINY 1
-+#elif ((__MODEL__) == 5)
-+# define LZO_MM_XSMALL 1
-+#else
-+# error "FIXME - MCS251 __MODEL__"
-+#endif
-+#elif (LZO_ARCH_MCS51)
-+#if !defined(__MODEL__)
-+# error "FIXME - MCS51 __MODEL__"
-+#elif ((__MODEL__) == 1)
-+# define LZO_MM_SMALL 1
-+#elif ((__MODEL__) == 2)
-+# define LZO_MM_LARGE 1
-+#elif ((__MODEL__) == 3)
-+# define LZO_MM_TINY 1
-+#elif ((__MODEL__) == 4)
-+# define LZO_MM_XTINY 1
-+#elif ((__MODEL__) == 5)
-+# define LZO_MM_XSMALL 1
-+#else
-+# error "FIXME - MCS51 __MODEL__"
-+#endif
-+#else
-+# define LZO_MM_FLAT 1
-+#endif
-+#if (LZO_MM_FLAT)
-+# define LZO_INFO_MM "flat"
-+#elif (LZO_MM_TINY)
-+# define LZO_INFO_MM "tiny"
-+#elif (LZO_MM_SMALL)
-+# define LZO_INFO_MM "small"
-+#elif (LZO_MM_MEDIUM)
-+# define LZO_INFO_MM "medium"
-+#elif (LZO_MM_COMPACT)
-+# define LZO_INFO_MM "compact"
-+#elif (LZO_MM_LARGE)
-+# define LZO_INFO_MM "large"
-+#elif (LZO_MM_HUGE)
-+# define LZO_INFO_MM "huge"
-+#else
-+# error "unknown memory model"
-+#endif
-+#endif
-+#if defined(SIZEOF_SHORT)
-+# define LZO_SIZEOF_SHORT (SIZEOF_SHORT)
-+#endif
-+#if defined(SIZEOF_INT)
-+# define LZO_SIZEOF_INT (SIZEOF_INT)
-+#endif
-+#if defined(SIZEOF_LONG)
-+# define LZO_SIZEOF_LONG (SIZEOF_LONG)
-+#endif
-+#if defined(SIZEOF_LONG_LONG)
-+# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG)
-+#endif
-+#if defined(SIZEOF___INT16)
-+# define LZO_SIZEOF___INT16 (SIZEOF___INT16)
-+#endif
-+#if defined(SIZEOF___INT32)
-+# define LZO_SIZEOF___INT32 (SIZEOF___INT32)
-+#endif
-+#if defined(SIZEOF___INT64)
-+# define LZO_SIZEOF___INT64 (SIZEOF___INT64)
-+#endif
-+#if defined(SIZEOF_VOID_P)
-+# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P)
-+#endif
-+#if defined(SIZEOF_SIZE_T)
-+# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T)
-+#endif
-+#if defined(SIZEOF_PTRDIFF_T)
-+# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T)
-+#endif
-+#define __LZO_LSR(x,b) (((x)+0ul) >> (b))
-+#if !defined(LZO_SIZEOF_SHORT)
-+# if (USHRT_MAX == LZO_0xffffL)
-+# define LZO_SIZEOF_SHORT 2
-+# elif (__LZO_LSR(USHRT_MAX,7) == 1)
-+# define LZO_SIZEOF_SHORT 1
-+# elif (__LZO_LSR(USHRT_MAX,15) == 1)
-+# define LZO_SIZEOF_SHORT 2
-+# elif (__LZO_LSR(USHRT_MAX,31) == 1)
-+# define LZO_SIZEOF_SHORT 4
-+# elif (__LZO_LSR(USHRT_MAX,63) == 1)
-+# define LZO_SIZEOF_SHORT 8
-+# elif (__LZO_LSR(USHRT_MAX,127) == 1)
-+# define LZO_SIZEOF_SHORT 16
-+# else
-+# error "LZO_SIZEOF_SHORT"
-+# endif
-+#endif
-+#if !defined(LZO_SIZEOF_INT)
-+# if (UINT_MAX == LZO_0xffffL)
-+# define LZO_SIZEOF_INT 2
-+# elif (UINT_MAX == LZO_0xffffffffL)
-+# define LZO_SIZEOF_INT 4
-+# elif (__LZO_LSR(UINT_MAX,7) == 1)
-+# define LZO_SIZEOF_INT 1
-+# elif (__LZO_LSR(UINT_MAX,15) == 1)
-+# define LZO_SIZEOF_INT 2
-+# elif (__LZO_LSR(UINT_MAX,31) == 1)
-+# define LZO_SIZEOF_INT 4
-+# elif (__LZO_LSR(UINT_MAX,63) == 1)
-+# define LZO_SIZEOF_INT 8
-+# elif (__LZO_LSR(UINT_MAX,127) == 1)
-+# define LZO_SIZEOF_INT 16
-+# else
-+# error "LZO_SIZEOF_INT"
-+# endif
-+#endif
-+#if !defined(LZO_SIZEOF_LONG)
-+# if (ULONG_MAX == LZO_0xffffffffL)
-+# define LZO_SIZEOF_LONG 4
-+# elif (__LZO_LSR(ULONG_MAX,7) == 1)
-+# define LZO_SIZEOF_LONG 1
-+# elif (__LZO_LSR(ULONG_MAX,15) == 1)
-+# define LZO_SIZEOF_LONG 2
-+# elif (__LZO_LSR(ULONG_MAX,31) == 1)
-+# define LZO_SIZEOF_LONG 4
-+# elif (__LZO_LSR(ULONG_MAX,63) == 1)
-+# define LZO_SIZEOF_LONG 8
-+# elif (__LZO_LSR(ULONG_MAX,127) == 1)
-+# define LZO_SIZEOF_LONG 16
-+# else
-+# error "LZO_SIZEOF_LONG"
-+# endif
-+#endif
-+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
-+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
-+# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)
-+# if (LZO_CC_GNUC >= 0x030300ul)
-+# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)
-+# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG
-+# endif
-+# endif
-+# endif
-+#endif
-+#endif
-+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
-+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
-+#if (LZO_ARCH_I086 && LZO_CC_DMC)
-+#elif (LZO_CC_CILLY) && defined(__GNUC__)
-+# define LZO_SIZEOF_LONG_LONG 8
-+#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-+# define LZO_SIZEOF_LONG_LONG 8
-+#elif ((LZO_OS_WIN32 || LZO_OS_WIN64) && LZO_CC_MSC && (_MSC_VER >= 1400))
-+# define LZO_SIZEOF_LONG_LONG 8
-+#elif (LZO_OS_WIN64)
-+# define LZO_SIZEOF___INT64 8
-+#elif (LZO_ARCH_I386 && (LZO_CC_DMC))
-+# define LZO_SIZEOF_LONG_LONG 8
-+#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700)))
-+# define LZO_SIZEOF_LONG_LONG 8
-+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__)))
-+# define LZO_SIZEOF_LONG_LONG 8
-+#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI))
-+# define LZO_SIZEOF_LONG_LONG 8
-+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC))
-+# define LZO_SIZEOF___INT64 8
-+#elif (LZO_OS_WIN32 && (LZO_CC_MSC))
-+# define LZO_SIZEOF___INT64 8
-+#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520)))
-+# define LZO_SIZEOF___INT64 8
-+#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100)))
-+# define LZO_SIZEOF___INT64 8
-+#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))
-+# define LZO_SIZEOF___INT64 8
-+#elif (LZO_OS_OS400) && defined(__LLP64_IFC__)
-+# define LZO_SIZEOF_LONG_LONG 8
-+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
-+# define LZO_SIZEOF_LONG_LONG 8
-+#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2)
-+#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-+# define LZO_SIZEOF_LONG_LONG 8
-+#endif
-+#endif
-+#endif
-+#if defined(__cplusplus) && defined(LZO_CC_GNUC)
-+# if (LZO_CC_GNUC < 0x020800ul)
-+# undef LZO_SIZEOF_LONG_LONG
-+# endif
-+#endif
-+#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
-+# undef LZO_SIZEOF_LONG_LONG
-+#endif
-+#if !defined(LZO_SIZEOF_VOID_P)
-+#if (LZO_ARCH_I086)
-+# define __LZO_WORDSIZE 2
-+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
-+# define LZO_SIZEOF_VOID_P 2
-+# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
-+# define LZO_SIZEOF_VOID_P 4
-+# else
-+# error "LZO_MM"
-+# endif
-+#elif (LZO_ARCH_AVR || LZO_ARCH_Z80)
-+# define __LZO_WORDSIZE 1
-+# define LZO_SIZEOF_VOID_P 2
-+#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
-+# define LZO_SIZEOF_VOID_P 2
-+#elif (LZO_ARCH_H8300)
-+# if defined(__NORMAL_MODE__)
-+# define __LZO_WORDSIZE 4
-+# define LZO_SIZEOF_VOID_P 2
-+# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
-+# define __LZO_WORDSIZE 4
-+# define LZO_SIZEOF_VOID_P 4
-+# else
-+# define __LZO_WORDSIZE 2
-+# define LZO_SIZEOF_VOID_P 2
-+# endif
-+# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
-+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT
-+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT
-+# endif
-+#elif (LZO_ARCH_M16C)
-+# define __LZO_WORDSIZE 2
-+# if defined(__m32c_cpu__) || defined(__m32cm_cpu__)
-+# define LZO_SIZEOF_VOID_P 4
-+# else
-+# define LZO_SIZEOF_VOID_P 2
-+# endif
-+#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
-+# define __LZO_WORDSIZE 8
-+# define LZO_SIZEOF_VOID_P 4
-+#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
-+# define __LZO_WORDSIZE 8
-+# define LZO_SIZEOF_VOID_P 8
-+#elif (LZO_OS_OS400) && defined(__LLP64_IFC__)
-+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
-+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
-+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
-+#elif (LZO_OS_OS400)
-+# define __LZO_WORDSIZE LZO_SIZEOF_LONG
-+# define LZO_SIZEOF_VOID_P 16
-+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
-+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
-+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
-+# define LZO_SIZEOF_VOID_P 8
-+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
-+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
-+#else
-+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
-+#endif
-+#endif
-+#if !defined(LZO_WORDSIZE)
-+# if defined(__LZO_WORDSIZE)
-+# define LZO_WORDSIZE __LZO_WORDSIZE
-+# else
-+# define LZO_WORDSIZE LZO_SIZEOF_VOID_P
-+# endif
-+#endif
-+#if !defined(LZO_SIZEOF_SIZE_T)
-+#if (LZO_ARCH_I086 || LZO_ARCH_M16C)
-+# define LZO_SIZEOF_SIZE_T 2
-+#else
-+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P
-+#endif
-+#endif
-+#if !defined(LZO_SIZEOF_PTRDIFF_T)
-+#if (LZO_ARCH_I086)
-+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE)
-+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P
-+# elif (LZO_MM_COMPACT || LZO_MM_LARGE)
-+# if (LZO_CC_BORLANDC || LZO_CC_TURBOC)
-+# define LZO_SIZEOF_PTRDIFF_T 4
-+# else
-+# define LZO_SIZEOF_PTRDIFF_T 2
-+# endif
-+# else
-+# error "LZO_MM"
-+# endif
-+#else
-+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T
-+#endif
-+#endif
-+#if !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN) && !defined(LZO_ABI_NEUTRAL_ENDIAN)
-+#if (LZO_ARCH_AMD64 || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
-+# define LZO_ABI_LITTLE_ENDIAN 1
-+#elif (LZO_ARCH_M68K || LZO_ARCH_S390)
-+# define LZO_ABI_BIG_ENDIAN 1
-+#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
-+# define LZO_ABI_BIG_ENDIAN 1
-+#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
-+# define LZO_ABI_LITTLE_ENDIAN 1
-+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
-+# define LZO_ABI_BIG_ENDIAN 1
-+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
-+# define LZO_ABI_LITTLE_ENDIAN 1
-+#endif
-+#endif
-+#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN)
-+# error "this should not happen"
-+#endif
-+#if defined(LZO_ABI_BIG_ENDIAN)
-+# define LZO_INFO_ABI_ENDIAN "be"
-+#elif defined(LZO_ABI_LITTLE_ENDIAN)
-+# define LZO_INFO_ABI_ENDIAN "le"
-+#elif defined(LZO_ABI_NEUTRAL_ENDIAN)
-+# define LZO_INFO_ABI_ENDIAN "neutral"
-+#endif
-+#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
-+# define LZO_ABI_I8LP16 1
-+# define LZO_INFO_ABI_PM "i8lp16"
-+#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
-+# define LZO_ABI_ILP16 1
-+# define LZO_INFO_ABI_PM "ilp16"
-+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
-+# define LZO_ABI_ILP32 1
-+# define LZO_INFO_ABI_PM "ilp32"
-+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8)
-+# define LZO_ABI_LLP64 1
-+# define LZO_INFO_ABI_PM "llp64"
-+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
-+# define LZO_ABI_LP64 1
-+# define LZO_INFO_ABI_PM "lp64"
-+#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
-+# define LZO_ABI_ILP64 1
-+# define LZO_INFO_ABI_PM "ilp64"
-+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4)
-+# define LZO_ABI_IP32L64 1
-+# define LZO_INFO_ABI_PM "ip32l64"
-+#endif
-+#if !defined(__LZO_LIBC_OVERRIDE)
-+#if defined(LZO_LIBC_NAKED)
-+# define LZO_INFO_LIBC "naked"
-+#elif defined(LZO_LIBC_FREESTANDING)
-+# define LZO_INFO_LIBC "freestanding"
-+#elif defined(LZO_LIBC_MOSTLY_FREESTANDING)
-+# define LZO_INFO_LIBC "mfreestanding"
-+#elif defined(LZO_LIBC_ISOC90)
-+# define LZO_INFO_LIBC "isoc90"
-+#elif defined(LZO_LIBC_ISOC99)
-+# define LZO_INFO_LIBC "isoc99"
-+#elif defined(__dietlibc__)
-+# define LZO_LIBC_DIETLIBC 1
-+# define LZO_INFO_LIBC "dietlibc"
-+#elif defined(_NEWLIB_VERSION)
-+# define LZO_LIBC_NEWLIB 1
-+# define LZO_INFO_LIBC "newlib"
-+#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)
-+# if defined(__UCLIBC_SUBLEVEL__)
-+# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)
-+# else
-+# define LZO_LIBC_UCLIBC 0x00090bL
-+# endif
-+# define LZO_INFO_LIBC "uclibc"
-+#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
-+# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)
-+# define LZO_INFO_LIBC "glibc"
-+#elif (LZO_CC_MWERKS) && defined(__MSL__)
-+# define LZO_LIBC_MSL __MSL__
-+# define LZO_INFO_LIBC "msl"
-+#else
-+# define LZO_LIBC_DEFAULT 1
-+# define LZO_INFO_LIBC "default"
-+#endif
-+#endif
-+#if (LZO_CC_GNUC >= 0x020800ul)
-+# define __lzo_gnuc_extension__ __extension__
-+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
-+# define __lzo_gnuc_extension__ __extension__
-+#else
-+# define __lzo_gnuc_extension__
-+#endif
-+#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
-+# define lzo_alignof(e) __alignof__(e)
-+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
-+# define lzo_alignof(e) __alignof__(e)
-+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
-+# define lzo_alignof(e) __alignof(e)
-+#endif
-+#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
-+#elif defined(__cplusplus)
-+# define __lzo_inline inline
-+#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
-+# define __lzo_inline __inline
-+#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
-+# define __lzo_inline __inline__
-+#elif (LZO_CC_DMC)
-+# define __lzo_inline __inline
-+#elif (LZO_CC_INTELC)
-+# define __lzo_inline __inline
-+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
-+# define __lzo_inline __inline
-+#elif (LZO_CC_MSC && (_MSC_VER >= 900))
-+# define __lzo_inline __inline
-+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-+# define __lzo_inline inline
-+#endif
-+#if (LZO_CC_GNUC >= 0x030200ul)
-+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
-+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && (LZO_OS_WIN32 || LZO_OS_WIN64))
-+# define __lzo_forceinline __forceinline
-+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
-+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
-+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
-+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
-+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
-+# define __lzo_forceinline __forceinline
-+#endif
-+#if (LZO_CC_GNUC >= 0x030200ul)
-+# define __lzo_noinline __attribute__((__noinline__))
-+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && (LZO_OS_WIN32 || LZO_OS_WIN64))
-+# define __lzo_noinline __declspec(noinline)
-+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
-+# define __lzo_noinline __attribute__((__noinline__))
-+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
-+# define __lzo_noinline __attribute__((__noinline__))
-+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
-+# define __lzo_noinline __declspec(noinline)
-+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
-+# if defined(__cplusplus)
-+# else
-+# define __lzo_noinline __declspec(noinline)
-+# endif
-+#endif
-+#if (defined(__lzo_forceinline) || defined(__lzo_noinline)) && !defined(__lzo_inline)
-+# error "this should not happen"
-+#endif
-+#if (LZO_CC_GNUC >= 0x020700ul)
-+# define __lzo_noreturn __attribute__((__noreturn__))
-+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && (LZO_OS_WIN32 || LZO_OS_WIN64))
-+# define __lzo_noreturn __declspec(noreturn)
-+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && (LZO_OS_POSIX))
-+# define __lzo_noreturn __attribute__((__noreturn__))
-+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
-+# define __lzo_noreturn __attribute__((__noreturn__))
-+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
-+# define __lzo_noreturn __declspec(noreturn)
-+#endif
-+#if (LZO_CC_GNUC >= 0x030400ul)
-+# define __lzo_constructor __attribute__((__constructor__,__used__))
-+#elif (LZO_CC_GNUC >= 0x020700ul)
-+# define __lzo_constructor __attribute__((__constructor__))
-+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
-+# define __lzo_constructor __attribute__((__constructor__))
-+#endif
-+#if (LZO_CC_GNUC >= 0x030400ul)
-+# define __lzo_destructor __attribute__((__destructor__,__used__))
-+#elif (LZO_CC_GNUC >= 0x020700ul)
-+# define __lzo_destructor __attribute__((__destructor__))
-+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
-+# define __lzo_destructor __attribute__((__destructor__))
-+#endif
-+#if defined(__lzo_destructor) && !defined(__lzo_constructor)
-+# error "this should not happen"
-+#endif
-+#if (LZO_CC_GNUC >= 0x030200ul)
-+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
-+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
-+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
-+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
-+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
-+#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
-+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
-+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
-+#else
-+# define __lzo_likely(e) (e)
-+# define __lzo_unlikely(e) (e)
-+#endif
-+#if !defined(LZO_UNUSED)
-+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
-+# define LZO_UNUSED(var) ((void) &var)
-+# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
-+# define LZO_UNUSED(var) if (&var) ; else
-+# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
-+# define LZO_UNUSED(var) ((void) var)
-+# elif (LZO_CC_MSC && (_MSC_VER < 900))
-+# define LZO_UNUSED(var) if (&var) ; else
-+# elif (LZO_CC_KEILC)
-+# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];}
-+# elif (LZO_CC_PACIFICC)
-+# define LZO_UNUSED(var) ((void) sizeof(var))
-+# elif (LZO_CC_WATCOMC) && defined(__cplusplus)
-+# define LZO_UNUSED(var) ((void) var)
-+# else
-+# define LZO_UNUSED(var) ((void) &var)
-+# endif
-+#endif
-+#if !defined(LZO_UNUSED_FUNC)
-+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
-+# define LZO_UNUSED_FUNC(func) ((void) func)
-+# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
-+# define LZO_UNUSED_FUNC(func) if (func) ; else
-+# elif (LZO_CC_LLVM)
-+# define LZO_UNUSED_FUNC(func) ((void) &func)
-+# elif (LZO_CC_MSC && (_MSC_VER < 900))
-+# define LZO_UNUSED_FUNC(func) if (func) ; else
-+# elif (LZO_CC_MSC)
-+# define LZO_UNUSED_FUNC(func) ((void) &func)
-+# elif (LZO_CC_KEILC || LZO_CC_PELLESC)
-+# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];}
-+# else
-+# define LZO_UNUSED_FUNC(func) ((void) func)
-+# endif
-+#endif
-+#if !defined(LZO_UNUSED_LABEL)
-+# if (LZO_CC_WATCOMC) && defined(__cplusplus)
-+# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
-+# elif (LZO_CC_INTELC || LZO_CC_WATCOMC)
-+# define LZO_UNUSED_LABEL(l) if (0) goto l
-+# else
-+# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
-+# endif
-+#endif
-+#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
-+# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
-+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
-+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
-+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)];
-+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
-+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
-+# else
-+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)];
-+# endif
-+#endif
-+#if !defined(LZO_COMPILE_TIME_ASSERT)
-+# if (LZO_CC_AZTECC)
-+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];}
-+# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
-+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
-+# elif (LZO_CC_MSC && (_MSC_VER < 900))
-+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
-+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
-+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
-+# else
-+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];}
-+# endif
-+#endif
-+#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
-+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
-+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
-+# define __lzo_cdecl __cdecl
-+# define __lzo_cdecl_atexit
-+# define __lzo_cdecl_main __cdecl
-+# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
-+# define __lzo_cdecl_qsort __pascal
-+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
-+# define __lzo_cdecl_qsort _stdcall
-+# else
-+# define __lzo_cdecl_qsort __cdecl
-+# endif
-+# elif (LZO_CC_WATCOMC)
-+# define __lzo_cdecl __cdecl
-+# else
-+# define __lzo_cdecl __cdecl
-+# define __lzo_cdecl_atexit __cdecl
-+# define __lzo_cdecl_main __cdecl
-+# define __lzo_cdecl_qsort __cdecl
-+# endif
-+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
-+# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
-+# define __lzo_cdecl_sighandler __pascal
-+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
-+# define __lzo_cdecl_sighandler _stdcall
-+# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
-+# define __lzo_cdecl_sighandler __clrcall
-+# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
-+# if defined(_DLL)
-+# define __lzo_cdecl_sighandler _far _cdecl _loadds
-+# elif defined(_MT)
-+# define __lzo_cdecl_sighandler _far _cdecl
-+# else
-+# define __lzo_cdecl_sighandler _cdecl
-+# endif
-+# else
-+# define __lzo_cdecl_sighandler __cdecl
-+# endif
-+#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
-+# define __lzo_cdecl cdecl
-+#endif
-+#if !defined(__lzo_cdecl)
-+# define __lzo_cdecl
-+#endif
-+#if !defined(__lzo_cdecl_atexit)
-+# define __lzo_cdecl_atexit
-+#endif
-+#if !defined(__lzo_cdecl_main)
-+# define __lzo_cdecl_main
-+#endif
-+#if !defined(__lzo_cdecl_qsort)
-+# define __lzo_cdecl_qsort
-+#endif
-+#if !defined(__lzo_cdecl_sighandler)
-+# define __lzo_cdecl_sighandler
-+#endif
-+#if !defined(__lzo_cdecl_va)
-+# define __lzo_cdecl_va __lzo_cdecl
-+#endif
-+#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
-+# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
-+# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
-+# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
-+# else
-+# define LZO_HAVE_WINDOWS_H 1
-+# endif
-+#endif
-+#if (LZO_ARCH_ALPHA)
-+# define LZO_OPT_AVOID_UINT_INDEX 1
-+# define LZO_OPT_AVOID_SHORT 1
-+# define LZO_OPT_AVOID_USHORT 1
-+#elif (LZO_ARCH_AMD64)
-+# define LZO_OPT_AVOID_INT_INDEX 1
-+# define LZO_OPT_AVOID_UINT_INDEX 1
-+# define LZO_OPT_UNALIGNED16 1
-+# define LZO_OPT_UNALIGNED32 1
-+# define LZO_OPT_UNALIGNED64 1
-+#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB)
-+#elif (LZO_ARCH_ARM)
-+# define LZO_OPT_AVOID_SHORT 1
-+# define LZO_OPT_AVOID_USHORT 1
-+#elif (LZO_ARCH_CRIS)
-+# define LZO_OPT_UNALIGNED16 1
-+# define LZO_OPT_UNALIGNED32 1
-+#elif (LZO_ARCH_I386)
-+# define LZO_OPT_UNALIGNED16 1
-+# define LZO_OPT_UNALIGNED32 1
-+#elif (LZO_ARCH_IA64)
-+# define LZO_OPT_AVOID_INT_INDEX 1
-+# define LZO_OPT_AVOID_UINT_INDEX 1
-+# define LZO_OPT_PREFER_POSTINC 1
-+#elif (LZO_ARCH_M68K)
-+# define LZO_OPT_PREFER_POSTINC 1
-+# define LZO_OPT_PREFER_PREDEC 1
-+# if defined(__mc68020__) && !defined(__mcoldfire__)
-+# define LZO_OPT_UNALIGNED16 1
-+# define LZO_OPT_UNALIGNED32 1
-+# endif
-+#elif (LZO_ARCH_MIPS)
-+# define LZO_OPT_AVOID_UINT_INDEX 1
-+#elif (LZO_ARCH_POWERPC)
-+# define LZO_OPT_PREFER_PREINC 1
-+# define LZO_OPT_PREFER_PREDEC 1
-+# if defined(LZO_ABI_BIG_ENDIAN)
-+# define LZO_OPT_UNALIGNED16 1
-+# define LZO_OPT_UNALIGNED32 1
-+# endif
-+#elif (LZO_ARCH_S390)
-+# define LZO_OPT_UNALIGNED16 1
-+# define LZO_OPT_UNALIGNED32 1
-+# if (LZO_SIZEOF_SIZE_T == 8)
-+# define LZO_OPT_UNALIGNED64 1
-+# endif
-+#elif (LZO_ARCH_SH)
-+# define LZO_OPT_PREFER_POSTINC 1
-+# define LZO_OPT_PREFER_PREDEC 1
-+#endif
-+#if !defined(LZO_CFG_NO_INLINE_ASM)
-+#if defined(LZO_CC_LLVM)
-+# define LZO_CFG_NO_INLINE_ASM 1
-+#endif
-+#endif
-+#if !defined(LZO_CFG_NO_UNALIGNED)
-+#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC)
-+# define LZO_CFG_NO_UNALIGNED 1
-+#endif
-+#endif
-+#if defined(LZO_CFG_NO_UNALIGNED)
-+# undef LZO_OPT_UNALIGNED16
-+# undef LZO_OPT_UNALIGNED32
-+# undef LZO_OPT_UNALIGNED64
-+#endif
-+#if defined(LZO_CFG_NO_INLINE_ASM)
-+#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
-+# define LZO_ASM_SYNTAX_MSC 1
-+#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
-+#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
-+# define LZO_ASM_SYNTAX_GNUC 1
-+#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
-+# define LZO_ASM_SYNTAX_GNUC 1
-+#endif
-+#if (LZO_ASM_SYNTAX_GNUC)
-+#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
-+# define __LZO_ASM_CLOBBER "ax"
-+#elif (LZO_CC_INTELC)
-+# define __LZO_ASM_CLOBBER "memory"
-+#else
-+# define __LZO_ASM_CLOBBER "cc", "memory"
-+#endif
-+#endif
-+#if defined(__LZO_INFOSTR_MM)
-+#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM))
-+# define __LZO_INFOSTR_MM ""
-+#elif defined(LZO_INFO_MM)
-+# define __LZO_INFOSTR_MM "." LZO_INFO_MM
-+#else
-+# define __LZO_INFOSTR_MM ""
-+#endif
-+#if defined(__LZO_INFOSTR_PM)
-+#elif defined(LZO_INFO_ABI_PM)
-+# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM
-+#else
-+# define __LZO_INFOSTR_PM ""
-+#endif
-+#if defined(__LZO_INFOSTR_ENDIAN)
-+#elif defined(LZO_INFO_ABI_ENDIAN)
-+# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN
-+#else
-+# define __LZO_INFOSTR_ENDIAN ""
-+#endif
-+#if defined(__LZO_INFOSTR_OSNAME)
-+#elif defined(LZO_INFO_OS_CONSOLE)
-+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE
-+#elif defined(LZO_INFO_OS_POSIX)
-+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX
-+#else
-+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS
-+#endif
-+#if defined(__LZO_INFOSTR_LIBC)
-+#elif defined(LZO_INFO_LIBC)
-+# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC
-+#else
-+# define __LZO_INFOSTR_LIBC ""
-+#endif
-+#if defined(__LZO_INFOSTR_CCVER)
-+#elif defined(LZO_INFO_CCVER)
-+# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER
-+#else
-+# define __LZO_INFOSTR_CCVER ""
-+#endif
-+#define LZO_INFO_STRING \
-+ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \
-+ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER
-+
-+#endif /* already included */
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoutil.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoutil.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,69 @@
-+/* lzoutil.h -- utilitiy functions for use by applications [DEPRECATED]
-+
-+ This file is part of the LZO real-time data compression library.
-+
-+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
-+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
-+ All Rights Reserved.
-+
-+ The LZO library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ The LZO library 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 the LZO library; see the file COPYING.
-+ If not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+
-+ Markus F.X.J. Oberhumer
-+
-+ http://www.oberhumer.com/opensource/lzo/
-+ */
-+
-+
-+#ifndef __LZOUTIL_H_INCLUDED
-+#define __LZOUTIL_H_INCLUDED
-+
-+#ifndef __LZOCONF_H_INCLUDED
-+#include "lzoconf.h"
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/***********************************************************************
-+// LZO-v1 deprecated macros (which were used in the old example programs)
-+// DO NOT USE
-+************************************************************************/
-+
-+#define lzo_alloc(a,b) (malloc((a)*(b)))
-+#define lzo_malloc(a) (malloc(a))
-+#define lzo_free(a) (free(a))
-+
-+#define lzo_fread(f,b,s) (fread(b,1,s,f))
-+#define lzo_fwrite(f,b,s) (fwrite(b,1,s,f))
-+
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* already included */
-+
-+
-+/* vim:set ts=4 et: */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/lib/liblzo2.la 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/lib/liblzo2.la 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,35 @@
-+# liblzo2.la - a libtool library file
-+# Generated by ltmain.sh - GNU libtool 1.5.6 (1.1220.2.95 2004/04/11 05:50:42) Debian: 220 $
-+#
-+# Please DO NOT delete this file!
-+# It is necessary for linking the library.
-+
-+# The name that we can dlopen(3).
-+dlname='liblzo2.so.2'
-+
-+# Names of this library.
-+library_names='liblzo2.so.2.0.0 liblzo2.so.2 liblzo2.so'
-+
-+# The name of the static archive.
-+old_library='liblzo2.a'
-+
-+# Libraries that this one depends upon.
-+dependency_libs=''
-+
-+# Version information for liblzo2.
-+current=2
-+age=0
-+revision=0
-+
-+# Is this an already installed library?
-+installed=yes
-+
-+# Should we warn about portability when linking against -modules?
-+shouldnotlink=no
-+
-+# Files to dlopen/dlpreopen
-+dlopen=''
-+dlpreopen=''
-+
-+# Directory that this library needs to be installed in:
-+libdir='/home/yrtan/lzo/lib'
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/mkfs.ubifs.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/mkfs.ubifs.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,2163 @@
-+/*
-+ * Copyright (C) 2008 Nokia Corporation.
-+ * Copyright (C) 2008 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy
-+ * Zoltan Sogor
-+ */
-+
-+#include "mkfs.ubifs.h"
-+
-+#define PROGRAM_VERSION "0.6"
-+
-+/* Size (prime number) of hash table for link counting */
-+#define HASH_TABLE_SIZE 10099
-+
-+/* The node buffer must allow for worst case compression */
-+#define NODE_BUFFER_SIZE (UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * 4)
-+
-+/* Default time granularity in nanoseconds */
-+#define DEFAULT_TIME_GRAN 1000000000
-+
-+/* UBI EC and VID header sizes - used when calculating LEB size from PRB size */
-+#define UBI_EC_HDR_SIZE 64
-+#define UBI_VID_HDR_SIZE 64
-+
-+/**
-+ * struct idx_entry - index entry.
-+ * @next: next index entry (NULL at end of list)
-+ * @prev: previous index entry (NULL at beginning of list)
-+ * @key: key
-+ * @name: directory entry name used for sorting colliding keys by name
-+ * @lnum: LEB number
-+ * @offs: offset
-+ * @len: length
-+ *
-+ * The index is recorded as a linked list which is sorted and used to create
-+ * the bottom level of the on-flash index tree. The remaining levels of the
-+ * index tree are each built from the level below.
-+ */
-+struct idx_entry {
-+ struct idx_entry *next;
-+ struct idx_entry *prev;
-+ union ubifs_key key;
-+ char *name;
-+ int lnum;
-+ int offs;
-+ int len;
-+};
-+
-+/**
-+ * struct inum_mapping - inode number mapping for link counting.
-+ * @next: next inum_mapping (NULL at end of list)
-+ * @prev: previous inum_mapping (NULL at beginning of list)
-+ * @dev: source device on which the source inode number resides
-+ * @inum: source inode number of the file
-+ * @use_inum: target inode number of the file
-+ * @use_nlink: number of links
-+ * @path_name: a path name of the file
-+ * @st: struct stat object containing inode attributes which have to be used
-+ * when the inode is being created (actually only UID, GID, access
-+ * mode, major and minor device numbers)
-+ *
-+ * If a file has more than one hard link, then the number of hard links that
-+ * exist in the source directory hierarchy must be counted to exclude the
-+ * possibility that the file is linked from outside the source directory
-+ * hierarchy.
-+ *
-+ * The inum_mappings are stored in a hash_table of linked lists.
-+ */
-+struct inum_mapping {
-+ struct inum_mapping *next;
-+ struct inum_mapping *prev;
-+ dev_t dev;
-+ ino_t inum;
-+ ino_t use_inum;
-+ unsigned int use_nlink;
-+ char *path_name;
-+ struct stat st;
-+};
-+
-+/*
-+ * Because we copy functions from the kernel, we use a subset of the UBIFS
-+ * file-system description object struct ubifs_info.
-+ */
-+static struct ubifs_info info_, *c = &info_;
-+
-+/* Debug levels are: 0 (none), 1 (statistics), 2 (files) ,3 (more details) */
-+int debug_level;
-+int verbose;
-+
-+static char *root;
-+static int root_len;
-+static struct stat root_st;
-+static char *output;
-+static int out_fd;
-+static int squash_owner;
-+
-+/* The 'head' (position) which nodes are written */
-+static int head_lnum;
-+static int head_offs;
-+static int head_flags;
-+
-+/* The index list */
-+static struct idx_entry *idx_list_first;
-+static struct idx_entry *idx_list_last;
-+static size_t idx_cnt;
-+
-+/* Global buffers */
-+static void *leb_buf;
-+static void *node_buf;
-+static void *block_buf;
-+
-+/* Hash table for inode link counting */
-+static struct inum_mapping **hash_table;
-+
-+/* Inode creation sequence number */
-+static unsigned long long creat_sqnum;
-+
-+static const char *optstring = "d:r:m:o:D:h?vVe:c:g:f:P:k:x:j:l:j:U";
-+
-+static const struct option longopts[] = {
-+ {"root", 1, NULL, 'r'},
-+ {"min-io-size", 1, NULL, 'm'},
-+ {"leb-size", 1, NULL, 'e'},
-+ {"max-leb-cnt", 1, NULL, 'c'},
-+ {"output", 1, NULL, 'o'},
-+ {"devtable", 1, NULL, 'D'},
-+ {"help", 0, NULL, 'h'},
-+ {"verbose", 0, NULL, 'v'},
-+ {"version", 0, NULL, 'V'},
-+ {"debug-level", 1, NULL, 'g'},
-+ {"jrn-size", 1, NULL, 'j'},
-+ {"compr", 1, NULL, 'x'},
-+ {"fanout", 1, NULL, 'f'},
-+ {"keyhash", 1, NULL, 'k'},
-+ {"log-lebs", 1, NULL, 'l'},
-+ {"orph-lebs", 1, NULL, 'p'},
-+ {"squash-uids" , 0, NULL, 'U'},
-+ {NULL, 0, NULL, 0}
-+};
-+
-+static const char *helptext =
-+"Usage: mkfs.ubifs [OPTIONS]\n"
-+"Make a UBIFS file system image from an existing directory tree\n\n"
-+"Options:\n"
-+"-r, -d, --root=DIR build file system from directory DIR\n"
-+"-m, --min-io-size=SIZE minimum I/O unit size\n"
-+"-e, --leb-size=SIZE logical erase block size\n"
-+"-c, --max-leb-cnt=COUNT maximum logical erase block count\n"
-+"-o, --output=FILE output to FILE\n"
-+"-j, --jrn-size=SIZE journal size\n"
-+"-x, --compr=TYPE compression type - \"lzo\", \"zlib\" or \"none\"\n"
-+" (default: \"lzo\")\n"
-+"-f, --fanout=NUM fanout NUM (default: 8)\n"
-+"-k, --keyhash=TYPE key hash type - \"r5\" or \"test\" (default: \"r5\")\n"
-+"-l, --log-lebs=COUNT count of erase blocks for the log\n"
-+"-p, --orph-lebs=COUNT count of erase blocks for orphans (default: 1)\n"
-+"-D, --devtable=FILE use device table FILE\n"
-+"-U, --squash-uids squash owners making all files owned by root\n"
-+"-v, --verbose verbose operation\n"
-+"-V, --version display version information\n"
-+"-g, --debug=LEVEL display debug information (0 - none, 1 - statistics,\n"
-+" 2 - files, 3 - more details)\n"
-+"-h, --help display this help text\n\n"
-+"Note, SIZE is specified in bytes, but it may also be specified in Kilobytes,\n"
-+"Megabytes, and Gigabytes if a KiB, MiB, or GiB suffix is used.\n";
-+
-+/**
-+ * make_path - make a path name from a directory and a name.
-+ * @dir: directory path name
-+ * @name: name
-+ */
-+static char *make_path(const char *dir, const char *name)
-+{
-+ char *s;
-+
-+ s = malloc(strlen(dir) + strlen(name) + 2);
-+ if (!s)
-+ return NULL;
-+ strcpy(s, dir);
-+ if (dir[strlen(dir) - 1] != '/')
-+ strcat(s, "/");
-+ strcat(s, name);
-+ return s;
-+}
-+
-+/**
-+ * same_dir - determine if two file descriptors refer to the same directory.
-+ * @fd1: file descriptor 1
-+ * @fd2: file descriptor 2
-+ */
-+static int same_dir(int fd1, int fd2)
-+{
-+ struct stat stat1, stat2;
-+
-+ if (fstat(fd1, &stat1) == -1)
-+ return -1;
-+ if (fstat(fd2, &stat2) == -1)
-+ return -1;
-+ return stat1.st_dev == stat2.st_dev && stat1.st_ino == stat2.st_ino;
-+}
-+
-+/**
-+ * do_openat - open a file in a directory.
-+ * @fd: file descriptor of open directory
-+ * @path: path relative to directory
-+ * @flags: open flags
-+ *
-+ * This function is provided because the library function openat is sometimes
-+ * not available.
-+ */
-+static int do_openat(int fd, const char *path, int flags)
-+{
-+ int ret;
-+ char *cwd;
-+
-+ cwd = getcwd(NULL, 0);
-+ if (!cwd)
-+ return -1;
-+ ret = fchdir(fd);
-+ if (ret != -1)
-+ ret = open(path, flags);
-+ chdir(cwd);
-+ free(cwd);
-+ return ret;
-+}
-+
-+/**
-+ * in_path - determine if a file is beneath a directory.
-+ * @dir_name: directory path name
-+ * @file_name: file path name
-+ */
-+static int in_path(const char *dir_name, const char *file_name)
-+{
-+ char *fn = strdup(file_name);
-+ char *dn;
-+ int fd1, fd2, fd3, ret = -1, top_fd;
-+
-+ if (!fn)
-+ return -1;
-+ top_fd = open("/", O_RDONLY);
-+ if (top_fd != -1) {
-+ dn = dirname(fn);
-+ fd1 = open(dir_name, O_RDONLY);
-+ if (fd1 != -1) {
-+ fd2 = open(dn, O_RDONLY);
-+ if (fd2 != -1) {
-+ while (1) {
-+ int same;
-+
-+ same = same_dir(fd1, fd2);
-+ if (same) {
-+ ret = same;
-+ break;
-+ }
-+ if (same_dir(fd2, top_fd)) {
-+ ret = 0;
-+ break;
-+ }
-+ fd3 = do_openat(fd2, "..", O_RDONLY);
-+ if (fd3 == -1)
-+ break;
-+ close(fd2);
-+ fd2 = fd3;
-+ }
-+ close(fd2);
-+ }
-+ close(fd1);
-+ }
-+ close(top_fd);
-+ }
-+ free(fn);
-+ return ret;
-+}
-+
-+/**
-+ * calc_min_log_lebs - calculate the minimum number of log LEBs needed.
-+ * @max_bud_bytes: journal size (buds only)
-+ */
-+static int calc_min_log_lebs(unsigned long long max_bud_bytes)
-+{
-+ int buds, log_lebs;
-+ unsigned long long log_size;
-+
-+ buds = (max_bud_bytes + c->leb_size - 1) / c->leb_size;
-+ log_size = ALIGN(UBIFS_REF_NODE_SZ, c->min_io_size);
-+ log_size *= buds;
-+ log_size += ALIGN(UBIFS_CS_NODE_SZ +
-+ UBIFS_REF_NODE_SZ * (c->jhead_cnt + 2),
-+ c->min_io_size);
-+ log_lebs = (log_size + c->leb_size - 1) / c->leb_size;
-+ log_lebs += 1;
-+ return log_lebs;
-+}
-+
-+static inline int is_power_of_2(unsigned long long n)
-+{
-+ return (n != 0 && ((n & (n - 1)) == 0));
-+}
-+
-+static int validate_options(void)
-+{
-+ int tmp;
-+
-+ if (!root)
-+ return err_msg("root directory was not specified");
-+ if (!output)
-+ return err_msg("no output file specified");
-+ if (in_path(root, output))
-+ return err_msg("output file cannot be in the UBIFS root "
-+ "directory");
-+ if (!is_power_of_2(c->min_io_size))
-+ return err_msg("min. I/O unit size should be power of 2");
-+ if (c->leb_size < c->min_io_size)
-+ return err_msg("min. I/O unit cannot be larger than LEB size");
-+ if (c->leb_size < UBIFS_MIN_LEB_SZ)
-+ return err_msg("too smal LEB size %d, minimum is %d",
-+ c->min_io_size, UBIFS_MIN_LEB_SZ);
-+ if (c->leb_size % c->min_io_size)
-+ return err_msg("LEB should be multiple of min. I/O units");
-+ if (c->leb_size % 8)
-+ return err_msg("LEB size has to be multiple of 8");
-+ if (c->leb_size > 1024*1024)
-+ return err_msg("too large LEB size %d", c->leb_size);
-+ if (c->max_leb_cnt < UBIFS_MIN_LEB_CNT)
-+ return err_msg("too low max. count of LEBs, minimum is %d",
-+ UBIFS_MIN_LEB_CNT);
-+ if (c->fanout < UBIFS_MIN_FANOUT)
-+ return err_msg("too low fanout, minimum is %d",
-+ UBIFS_MIN_FANOUT);
-+ tmp = c->leb_size - UBIFS_IDX_NODE_SZ;
-+ tmp /= UBIFS_BRANCH_SZ + UBIFS_MAX_KEY_LEN;
-+ if (c->fanout > tmp)
-+ return err_msg("too high fanout, maximum is %d", tmp);
-+ if (c->log_lebs < UBIFS_MIN_LOG_LEBS)
-+ return err_msg("too few log LEBs, minimum is %d",
-+ UBIFS_MIN_LOG_LEBS);
-+ if (c->log_lebs >= c->max_leb_cnt - UBIFS_MIN_LEB_CNT)
-+ return err_msg("too many log LEBs, maximum is %d",
-+ c->max_leb_cnt - UBIFS_MIN_LEB_CNT);
-+ if (c->orph_lebs < UBIFS_MIN_ORPH_LEBS)
-+ return err_msg("too few orphan LEBs, minimum is %d",
-+ UBIFS_MIN_ORPH_LEBS);
-+ if (c->orph_lebs >= c->max_leb_cnt - UBIFS_MIN_LEB_CNT)
-+ return err_msg("too many orphan LEBs, maximum is %d",
-+ c->max_leb_cnt - UBIFS_MIN_LEB_CNT);
-+ tmp = UBIFS_SB_LEBS + UBIFS_MST_LEBS + c->log_lebs + c->lpt_lebs;
-+ tmp += c->orph_lebs + 4;
-+ if (tmp > c->max_leb_cnt)
-+ return err_msg("too low max. count of LEBs, expected at "
-+ "least %d", tmp);
-+ tmp = calc_min_log_lebs(c->max_bud_bytes);
-+ if (c->log_lebs < calc_min_log_lebs(c->max_bud_bytes))
-+ return err_msg("too few log LEBs, expected at least %d",
-+ tmp);
-+ return 0;
-+}
-+
-+/**
-+ * get_multiplier - convert size specifier to an integer multiplier.
-+ * @str: the size specifier string
-+ *
-+ * This function parses the @str size specifier, which may be one of
-+ * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
-+ * size multiplier in case of success and %-1 in case of failure.
-+ */
-+static int get_multiplier(const char *str)
-+{
-+ if (!str)
-+ return 1;
-+
-+ /* Remove spaces before the specifier */
-+ while (*str == ' ' || *str == '\t')
-+ str += 1;
-+
-+ if (!strcmp(str, "KiB"))
-+ return 1024;
-+ if (!strcmp(str, "MiB"))
-+ return 1024 * 1024;
-+ if (!strcmp(str, "GiB"))
-+ return 1024 * 1024 * 1024;
-+
-+ return -1;
-+}
-+
-+/**
-+ * get_bytes - convert a string containing amount of bytes into an
-+ * integer.
-+ * @str: string to convert
-+ *
-+ * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB' size
-+ * specifiers. Returns positive amount of bytes in case of success and %-1 in
-+ * case of failure.
-+ */
-+static long long get_bytes(const char *str)
-+{
-+ char *endp;
-+ long long bytes = strtoull(str, &endp, 0);
-+
-+ if (endp == str || bytes < 0)
-+ return err_msg("incorrect amount of bytes: \"%s\"", str);
-+
-+ if (*endp != '\0') {
-+ int mult = get_multiplier(endp);
-+
-+ if (mult == -1)
-+ return err_msg("bad size specifier: \"%s\" - "
-+ "should be 'KiB', 'MiB' or 'GiB'", endp);
-+ bytes *= mult;
-+ }
-+
-+ return bytes;
-+}
-+
-+static int get_options(int argc, char**argv)
-+{
-+ int opt, i;
-+ const char *tbl_file = NULL;
-+ struct stat st;
-+ char *endp;
-+
-+ c->fanout = 8;
-+ c->orph_lebs = 1;
-+ c->key_hash = key_r5_hash;
-+ c->key_len = UBIFS_SK_LEN;
-+ c->default_compr = UBIFS_COMPR_LZO;
-+ c->lsave_cnt = 256;
-+ c->leb_size = -1;
-+ c->min_io_size = -1;
-+ c->max_bud_bytes = -1;
-+ c->log_lebs = -1;
-+
-+ while (1) {
-+ opt = getopt_long(argc, argv, optstring, longopts, &i);
-+ if (opt == -1)
-+ break;
-+ switch (opt) {
-+ case 'r':
-+ case 'd':
-+ root_len = strlen(optarg);
-+ root = malloc(root_len + 2);
-+ if (!root)
-+ return err_msg("cannot allocate memory");
-+
-+ /*
-+ * The further code expects '/' at the end of the root
-+ * UBIFS directory on the host.
-+ */
-+ memcpy(root, optarg, root_len);
-+ if (root[root_len - 1] != '/')
-+ root[root_len++] = '/';
-+ root[root_len] = 0;
-+
-+ /* Make sure the root directory exists */
-+ if (stat(root, &st))
-+ return sys_err_msg("bad root directory '%s'",
-+ root);
-+ break;
-+ case 'm':
-+ c->min_io_size = get_bytes(optarg);
-+ if (c->min_io_size <= 0)
-+ return err_msg("bad min. I/O size");
-+ break;
-+ case 'e':
-+ c->leb_size = get_bytes(optarg);
-+ if (c->leb_size <= 0)
-+ return err_msg("bad LEB size");
-+ break;
-+ case 'c':
-+ c->max_leb_cnt = get_bytes(optarg);
-+ if (c->max_leb_cnt <= 0)
-+ return err_msg("bad maximum LEB count");
-+ break;
-+ case 'o':
-+ output = strdup(optarg);
-+ break;
-+ case 'D':
-+ tbl_file = optarg;
-+ if (stat(tbl_file, &st) < 0)
-+ return sys_err_msg("bad device table file '%s'",
-+ tbl_file);
-+ break;
-+ case 'h':
-+ case '?':
-+ printf(helptext);
-+ exit(0);
-+ case 'v':
-+ verbose = 1;
-+ break;
-+ case 'V':
-+ printf("Version " PROGRAM_VERSION "\n");
-+ exit(0);
-+ case 'g':
-+ debug_level = strtol(optarg, &endp, 0);
-+ if (*endp != '\0' || endp == optarg ||
-+ debug_level < 0 || debug_level > 3)
-+ return err_msg("bad debugging level '%s'",
-+ optarg);
-+ break;
-+ case 'f':
-+ c->fanout = strtol(optarg, &endp, 0);
-+ if (*endp != '\0' || endp == optarg || c->fanout <= 0)
-+ return err_msg("bad fanout %s", optarg);
-+ break;
-+ case 'l':
-+ c->log_lebs = strtol(optarg, &endp, 0);
-+ if (*endp != '\0' || endp == optarg || c->log_lebs <= 0)
-+ return err_msg("bad count of log LEBs '%s'",
-+ optarg);
-+ break;
-+ case 'p':
-+ c->orph_lebs = strtol(optarg, &endp, 0);
-+ if (*endp != '\0' || endp == optarg ||
-+ c->orph_lebs <= 0)
-+ return err_msg("bad orphan LEB count '%s'",
-+ optarg);
-+ break;
-+ case 'k':
-+ if (strcmp(optarg, "r5") == 0) {
-+ c->key_hash = key_r5_hash;
-+ c->key_hash_type = UBIFS_KEY_HASH_R5;
-+ } else if (strcmp(optarg, "test") == 0) {
-+ c->key_hash = key_test_hash;
-+ c->key_hash_type = UBIFS_KEY_HASH_TEST;
-+ } else
-+ return err_msg("bad key hash");
-+ break;
-+ case 'x':
-+ if (strcmp(optarg, "lzo") == 0)
-+ c->default_compr = UBIFS_COMPR_LZO;
-+ else if (strcmp(optarg, "zlib") == 0)
-+ c->default_compr = UBIFS_COMPR_ZLIB;
-+ else if (strcmp(optarg, "none") == 0)
-+ c->default_compr = UBIFS_COMPR_NONE;
-+ else
-+ return err_msg("bad compressor name");
-+ break;
-+ case 'j':
-+ c->max_bud_bytes = get_bytes(optarg);
-+ if (c->max_bud_bytes <= 0)
-+ return err_msg("bad maximum amount of buds");
-+ break;
-+ case 'U':
-+ squash_owner = 1;
-+ break;
-+ }
-+ }
-+
-+ if (c->min_io_size == -1)
-+ return err_msg("min. I/O unit was not specified "
-+ "(use -h for help)");
-+
-+ if (c->leb_size == -1)
-+ return err_msg("LEB size was not specified (use -h for help)");
-+
-+ if (c->max_bud_bytes == -1) {
-+ int lebs;
-+
-+ lebs = c->max_leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS;
-+ lebs -= c->orph_lebs;
-+ if (c->log_lebs)
-+ lebs -= c->log_lebs;
-+ else
-+ lebs -= UBIFS_MIN_LOG_LEBS;
-+ if (c->lpt_lebs)
-+ lebs -= c->lpt_lebs;
-+ else
-+ lebs -= UBIFS_MIN_LPT_LEBS;
-+ /* Make the journal about 12.5% of main area lebs */
-+ c->max_bud_bytes = (lebs / 8) * (long long)c->leb_size;
-+ /* Make the max journal size 8MiB */
-+ if (c->max_bud_bytes > 8 * 1024 * 1024)
-+ c->max_bud_bytes = 8 * 1024 * 1024;
-+ if (c->max_bud_bytes < 4 * c->leb_size)
-+ c->max_bud_bytes = 4 * c->leb_size;
-+ }
-+
-+ if (c->log_lebs == -1) {
-+ c->log_lebs = calc_min_log_lebs(c->max_bud_bytes);
-+ c->log_lebs += 2;
-+ }
-+
-+ if (verbose) {
-+ printf("mkfs.ubifs\n");
-+ printf("\troot: %s\n", root);
-+ printf("\tmin_io_size: %d\n", c->min_io_size);
-+ printf("\tleb_size: %d\n", c->leb_size);
-+ printf("\tmax_leb_cnt: %d\n", c->max_leb_cnt);
-+ printf("\toutput: %s\n", output);
-+ printf("\tjrn_size: %llu\n", c->max_bud_bytes);
-+ switch (c->default_compr) {
-+ case UBIFS_COMPR_LZO:
-+ printf("\tcompr: lzo\n");
-+ break;
-+ case UBIFS_COMPR_ZLIB:
-+ printf("\tcompr: zlib\n");
-+ break;
-+ case UBIFS_COMPR_NONE:
-+ printf("\tcompr: none\n");
-+ break;
-+ }
-+ printf("\tkeyhash: %s\n", (c->key_hash == key_r5_hash) ?
-+ "r5" : "test");
-+ printf("\tfanout: %d\n", c->fanout);
-+ printf("\torph_lebs: %d\n", c->orph_lebs);
-+ }
-+
-+ if (c->min_io_size < 8)
-+ c->min_io_size = 8;
-+
-+ if (validate_options())
-+ return -1;
-+
-+ if (tbl_file && parse_devtable(root, tbl_file))
-+ return err_msg("cannot parse device table file '%s'", tbl_file);
-+
-+ return 0;
-+}
-+
-+/**
-+ * prepare_node - fill in the common header.
-+ * @node: node
-+ * @len: node length
-+ */
-+static void prepare_node(void *node, int len)
-+{
-+ uint32_t crc;
-+ struct ubifs_ch *ch = node;
-+
-+ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
-+ ch->len = cpu_to_le32(len);
-+ ch->group_type = UBIFS_NO_NODE_GROUP;
-+ ch->sqnum = cpu_to_le64(++c->max_sqnum);
-+ ch->padding[0] = ch->padding[1] = 0;
-+ crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8);
-+ ch->crc = cpu_to_le32(crc);
-+}
-+
-+/**
-+ * write_leb - copy the image of a LEB to the output file.
-+ * @lnum: LEB number
-+ * @len: length of data in the buffer
-+ * @buf: buffer (must be at least c->leb_size bytes)
-+ */
-+int write_leb(int lnum, int len, void *buf)
-+{
-+ off64_t pos = (off64_t)lnum * c->leb_size;
-+
-+ dbg_msg(3, "LEB %d len %d", lnum, len);
-+ if (lseek64(out_fd, pos, SEEK_SET) != pos)
-+ return sys_err_msg("lseek64 failed seeking %lld", pos);
-+
-+ memset(buf + len, 0xff, c->leb_size - len);
-+
-+ if (write(out_fd, buf, c->leb_size) != c->leb_size)
-+ return sys_err_msg("write failed writing %d bytes at pos %lld",
-+ c->leb_size, pos);
-+
-+ return 0;
-+}
-+
-+/**
-+ * write_empty_leb - copy the image of an empty LEB to the output file.
-+ * @lnum: LEB number
-+ */
-+static int write_empty_leb(int lnum)
-+{
-+ return write_leb(lnum, 0, leb_buf);
-+}
-+
-+/**
-+ * do_pad - pad a buffer to the minimum I/O size.
-+ * @buf: buffer
-+ * @len: buffer length
-+ */
-+static int do_pad(void *buf, int len)
-+{
-+ int pad_len, alen = ALIGN(len, 8), wlen = ALIGN(alen, c->min_io_size);
-+ uint32_t crc;
-+
-+ memset(buf + len, 0xff, alen - len);
-+ pad_len = wlen - alen;
-+ dbg_msg(3, "len %d pad_len %d", len, pad_len);
-+ buf += alen;
-+ if (pad_len >= UBIFS_PAD_NODE_SZ) {
-+ struct ubifs_ch *ch = buf;
-+ struct ubifs_pad_node *pad_node = buf;
-+
-+ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
-+ ch->node_type = UBIFS_PAD_NODE;
-+ ch->group_type = UBIFS_NO_NODE_GROUP;
-+ ch->padding[0] = ch->padding[1] = 0;
-+ ch->sqnum = cpu_to_le64(0);
-+ ch->len = cpu_to_le32(UBIFS_PAD_NODE_SZ);
-+
-+ pad_len -= UBIFS_PAD_NODE_SZ;
-+ pad_node->pad_len = cpu_to_le32(pad_len);
-+
-+ crc = crc32(UBIFS_CRC32_INIT, buf + 8, UBIFS_PAD_NODE_SZ - 8);
-+ ch->crc = cpu_to_le32(crc);
-+
-+ memset(buf + UBIFS_PAD_NODE_SZ, 0, pad_len);
-+ } else if (pad_len > 0)
-+ memset(buf, UBIFS_PADDING_BYTE, pad_len);
-+
-+ return wlen;
-+}
-+
-+/**
-+ * write_node - write a node to a LEB.
-+ * @node: node
-+ * @len: node length
-+ * @lnum: LEB number
-+ */
-+static int write_node(void *node, int len, int lnum)
-+{
-+ prepare_node(node, len);
-+
-+ memcpy(leb_buf, node, len);
-+
-+ len = do_pad(leb_buf, len);
-+
-+ return write_leb(lnum, len, leb_buf);
-+}
-+
-+/**
-+ * calc_dark - calculate LEB dark space size.
-+ * @c: the UBIFS file-system description object
-+ * @spc: amount of free and dirty space in the LEB
-+ *
-+ * This function calculates amount of dark space in an LEB which has @spc bytes
-+ * of free and dirty space. Returns the calculations result.
-+ *
-+ * Dark space is the space which is not always usable - it depends on which
-+ * nodes are written in which order. E.g., if an LEB has only 512 free bytes,
-+ * it is dark space, because it cannot fit a large data node. So UBIFS cannot
-+ * count on this LEB and treat these 512 bytes as usable because it is not true
-+ * if, for example, only big chunks of uncompressible data will be written to
-+ * the FS.
-+ */
-+static int calc_dark(struct ubifs_info *c, int spc)
-+{
-+ if (spc < c->dark_wm)
-+ return spc;
-+
-+ /*
-+ * If we have slightly more space then the dark space watermark, we can
-+ * anyway safely assume it we'll be able to write a node of the
-+ * smallest size there.
-+ */
-+ if (spc - c->dark_wm < MIN_WRITE_SZ)
-+ return spc - MIN_WRITE_SZ;
-+
-+ return c->dark_wm;
-+}
-+
-+/**
-+ * set_lprops - set the LEB property values for a LEB.
-+ * @lnum: LEB number
-+ * @offs: end offset of data in the LEB
-+ * @flags: LEB property flags
-+ */
-+static void set_lprops(int lnum, int offs, int flags)
-+{
-+ int i = lnum - c->main_first, free, dirty;
-+ int a = max_t(int, c->min_io_size, 8);
-+
-+ free = c->leb_size - ALIGN(offs, a);
-+ dirty = c->leb_size - free - ALIGN(offs, 8);
-+ dbg_msg(3, "LEB %d free %d dirty %d flags %d", lnum, free, dirty,
-+ flags);
-+ c->lpt[i].free = free;
-+ c->lpt[i].dirty = dirty;
-+ c->lpt[i].flags = flags;
-+ c->lst.total_free += free;
-+ c->lst.total_dirty += dirty;
-+ if (flags & LPROPS_INDEX)
-+ c->lst.idx_lebs += 1;
-+ else {
-+ int spc;
-+
-+ spc = free + dirty;
-+ if (spc < c->dead_wm)
-+ c->lst.total_dead += spc;
-+ else
-+ c->lst.total_dark += calc_dark(c, spc);
-+ c->lst.total_used += c->leb_size - spc;
-+ }
-+}
-+
-+/**
-+ * add_to_index - add a node key and position to the index.
-+ * @key: node key
-+ * @lnum: node LEB number
-+ * @offs: node offset
-+ * @len: node length
-+ */
-+static int add_to_index(union ubifs_key *key, char *name, int lnum, int offs,
-+ int len)
-+{
-+ struct idx_entry *e;
-+
-+ dbg_msg(3, "LEB %d offs %d len %d", lnum, offs, len);
-+ e = malloc(sizeof(struct idx_entry));
-+ if (!e)
-+ return err_msg("out of memory");
-+ e->next = NULL;
-+ e->prev = idx_list_last;
-+ e->key = *key;
-+ e->name = name;
-+ e->lnum = lnum;
-+ e->offs = offs;
-+ e->len = len;
-+ if (!idx_list_first)
-+ idx_list_first = e;
-+ if (idx_list_last)
-+ idx_list_last->next = e;
-+ idx_list_last = e;
-+ idx_cnt += 1;
-+ return 0;
-+}
-+
-+/**
-+ * flush_nodes - write the current head and move the head to the next LEB.
-+ */
-+static int flush_nodes(void)
-+{
-+ int len, err;
-+
-+ if (!head_offs)
-+ return 0;
-+ len = do_pad(leb_buf, head_offs);
-+ err = write_leb(head_lnum, len, leb_buf);
-+ if (err)
-+ return err;
-+ set_lprops(head_lnum, head_offs, head_flags);
-+ head_lnum += 1;
-+ head_offs = 0;
-+ return 0;
-+}
-+
-+/**
-+ * reserve_space - reserve space for a node on the head.
-+ * @len: node length
-+ * @lnum: LEB number is returned here
-+ * @offs: offset is returned here
-+ */
-+static int reserve_space(int len, int *lnum, int *offs)
-+{
-+ int err;
-+
-+ if (len > c->leb_size - head_offs) {
-+ err = flush_nodes();
-+ if (err)
-+ return err;
-+ }
-+ *lnum = head_lnum;
-+ *offs = head_offs;
-+ head_offs += ALIGN(len, 8);
-+ return 0;
-+}
-+
-+/**
-+ * add_node - write a node to the head.
-+ * @key: node key
-+ * @node: node
-+ * @len: node length
-+ */
-+static int add_node(union ubifs_key *key, char *name, void *node, int len)
-+{
-+ int err, lnum, offs;
-+
-+ prepare_node(node, len);
-+
-+ err = reserve_space(len, &lnum, &offs);
-+ if (err)
-+ return err;
-+
-+ memcpy(leb_buf + offs, node, len);
-+ memset(leb_buf + offs + len, 0xff, ALIGN(len, 8) - len);
-+
-+ add_to_index(key, name, lnum, offs, len);
-+
-+ return 0;
-+}
-+
-+/**
-+ * add_inode_with_data - write an inode.
-+ * @st: stat information of source inode
-+ * @inum: target inode number
-+ * @data: inode data (for special inodes e.g. symlink path etc)
-+ * @data_len: inode data length
-+ * @flags: source inode flags
-+ */
-+static int add_inode_with_data(struct stat *st, ino_t inum, void *data,
-+ unsigned int data_len, int flags)
-+{
-+ struct ubifs_ino_node *ino = node_buf;
-+ union ubifs_key key;
-+ int len, use_flags = 0;
-+
-+ if (c->default_compr != UBIFS_COMPR_NONE)
-+ use_flags |= UBIFS_COMPR_FL;
-+ if (flags & FS_COMPR_FL)
-+ use_flags |= UBIFS_COMPR_FL;
-+ if (flags & FS_SYNC_FL)
-+ use_flags |= UBIFS_SYNC_FL;
-+ if (flags & FS_IMMUTABLE_FL)
-+ use_flags |= UBIFS_IMMUTABLE_FL;
-+ if (flags & FS_APPEND_FL)
-+ use_flags |= UBIFS_APPEND_FL;
-+ if (flags & FS_DIRSYNC_FL && S_ISDIR(st->st_mode))
-+ use_flags |= UBIFS_DIRSYNC_FL;
-+
-+ memset(ino, 0, UBIFS_INO_NODE_SZ);
-+
-+ ino_key_init(c, &key, inum);
-+ ino->ch.node_type = UBIFS_INO_NODE;
-+ key_write(c, &key, &ino->key);
-+ ino->creat_sqnum = cpu_to_le64(creat_sqnum);
-+ ino->size = cpu_to_le64(st->st_size);
-+ ino->nlink = cpu_to_le32(st->st_nlink);
-+ /*
-+ * The time fields are updated assuming the default time granularity
-+ * of 1 second. To support finer granularities, utime() would be needed.
-+ */
-+ ino->atime_sec = cpu_to_le64(st->st_atime);
-+ ino->ctime_sec = cpu_to_le64(st->st_ctime);
-+ ino->mtime_sec = cpu_to_le64(st->st_mtime);
-+ ino->atime_nsec = 0;
-+ ino->ctime_nsec = 0;
-+ ino->mtime_nsec = 0;
-+ ino->uid = cpu_to_le32(st->st_uid);
-+ ino->gid = cpu_to_le32(st->st_gid);
-+ ino->uid = cpu_to_le32(st->st_uid);
-+ ino->gid = cpu_to_le32(st->st_gid);
-+ ino->mode = cpu_to_le32(st->st_mode);
-+ ino->flags = cpu_to_le32(use_flags);
-+ ino->data_len = cpu_to_le32(data_len);
-+ ino->compr_type = cpu_to_le16(c->default_compr);
-+ if (data_len)
-+ memcpy(&ino->data, data, data_len);
-+
-+ len = UBIFS_INO_NODE_SZ + data_len;
-+
-+ return add_node(&key, NULL, ino, len);
-+}
-+
-+/**
-+ * add_inode - write an inode.
-+ * @st: stat information of source inode
-+ * @inum: target inode number
-+ * @flags: source inode flags
-+ */
-+static int add_inode(struct stat *st, ino_t inum, int flags)
-+{
-+ return add_inode_with_data(st, inum, NULL, 0, flags);
-+}
-+
-+/**
-+ * add_dir_inode - write an inode for a directory.
-+ * @dir: source directory
-+ * @inum: target inode number
-+ * @size: target directory size
-+ * @nlink: target directory link count
-+ * @st: struct stat object describing attributes (except size and nlink) of the
-+ * target inode to create
-+ *
-+ * Note, this function may be called with %NULL @dir, when the directory which
-+ * is being created does not exist at the host file system, but is defined by
-+ * the device table.
-+ */
-+static int add_dir_inode(DIR *dir, ino_t inum, loff_t size, unsigned int nlink,
-+ struct stat *st)
-+{
-+ int fd, flags = 0;
-+
-+ st->st_size = size;
-+ st->st_nlink = nlink;
-+
-+ if (dir) {
-+ fd = dirfd(dir);
-+ if (fd == -1)
-+ return sys_err_msg("dirfd failed");
-+ if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1)
-+ flags = 0;
-+ }
-+
-+ return add_inode(st, inum, flags);
-+}
-+
-+/**
-+ * add_dev_inode - write an inode for a character or block device.
-+ * @st: stat information of source inode
-+ * @inum: target inode number
-+ * @flags: source inode flags
-+ */
-+static int add_dev_inode(struct stat *st, ino_t inum, int flags)
-+{
-+ union ubifs_dev_desc dev;
-+
-+ dev.huge = cpu_to_le64(makedev(major(st->st_rdev), minor(st->st_rdev)));
-+ return add_inode_with_data(st, inum, &dev, 8, flags);
-+}
-+
-+/**
-+ * add_symlink_inode - write an inode for a symbolic link.
-+ * @path_name: path name of symbolic link inode itself (not the link target)
-+ * @st: stat information of source inode
-+ * @inum: target inode number
-+ * @flags: source inode flags
-+ */
-+static int add_symlink_inode(const char *path_name, struct stat *st, ino_t inum,
-+ int flags)
-+{
-+ char buf[UBIFS_MAX_INO_DATA + 2];
-+ ssize_t len;
-+
-+ /* Take the symlink as is */
-+ len = readlink(path_name, buf, UBIFS_MAX_INO_DATA + 1);
-+ if (len <= 0)
-+ return sys_err_msg("readlink failed for %s", path_name);
-+ if (len > UBIFS_MAX_INO_DATA)
-+ return err_msg("symlink too long for %s", path_name);
-+
-+ return add_inode_with_data(st, inum, buf, len, flags);
-+}
-+
-+/**
-+ * add_dent_node - write a directory entry node.
-+ * @dir_inum: target inode number of directory
-+ * @name: directory entry name
-+ * @inum: target inode number of the directory entry
-+ * @type: type of the target inode
-+ */
-+static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
-+ unsigned char type)
-+{
-+ struct ubifs_dent_node *dent = node_buf;
-+ union ubifs_key key;
-+ struct qstr dname;
-+ char *kname;
-+ int len;
-+
-+ dbg_msg(3, "%s ino %lu type %u dir ino %lu", name, inum,
-+ (unsigned)type, dir_inum);
-+ memset(dent, 0, UBIFS_DENT_NODE_SZ);
-+
-+ dname.name = (void *)name;
-+ dname.len = strlen(name);
-+
-+ dent->ch.node_type = UBIFS_DENT_NODE;
-+
-+ dent_key_init(c, &key, dir_inum, &dname);
-+ key_write(c, &key, dent->key);
-+ dent->inum = cpu_to_le64(inum);
-+ dent->padding1 = 0;
-+ dent->type = type;
-+ dent->nlen = cpu_to_le16(dname.len);
-+ memcpy(dent->name, dname.name, dname.len);
-+ dent->name[dname.len] = '\0';
-+
-+ len = UBIFS_DENT_NODE_SZ + dname.len + 1;
-+
-+ kname = strdup(name);
-+ if (!kname)
-+ return err_msg("cannot allocate memory");
-+
-+ return add_node(&key, kname, dent, len);
-+}
-+
-+/**
-+ * lookup_inum_mapping - add an inode mapping for link counting.
-+ * @dev: source device on which source inode number resides
-+ * @inum: source inode number
-+ */
-+static struct inum_mapping *lookup_inum_mapping(dev_t dev, ino_t inum)
-+{
-+ struct inum_mapping *im;
-+ unsigned int k;
-+
-+ k = inum % HASH_TABLE_SIZE;
-+ im = hash_table[k];
-+ while (im) {
-+ if (im->dev == dev && im->inum == inum)
-+ return im;
-+ im = im->next;
-+ }
-+ im = malloc(sizeof(struct inum_mapping));
-+ if (!im)
-+ return NULL;
-+ im->next = hash_table[k];
-+ im->prev = NULL;
-+ im->dev = dev;
-+ im->inum = inum;
-+ im->use_inum = 0;
-+ im->use_nlink = 0;
-+ if (hash_table[k])
-+ hash_table[k]->prev = im;
-+ hash_table[k] = im;
-+ return im;
-+}
-+
-+/**
-+ * all_zero - does a buffer contain only zero bytes.
-+ * @buf: buffer
-+ * @len: buffer length
-+ */
-+static int all_zero(void *buf, int len)
-+{
-+ unsigned char *p = buf;
-+
-+ while (len--)
-+ if (*p++ != 0)
-+ return 0;
-+ return 1;
-+}
-+
-+/**
-+ * add_file - write the data of a file and its inode to the output file.
-+ * @path_name: source path name
-+ * @st: source inode stat information
-+ * @inum: target inode number
-+ * @flags: source inode flags
-+ */
-+static int add_file(const char *path_name, struct stat *st, ino_t inum,
-+ int flags)
-+{
-+ struct ubifs_data_node *dn = node_buf;
-+ void *buf = block_buf;
-+ loff_t file_size = 0;
-+ ssize_t ret, bytes_read;
-+ union ubifs_key key;
-+ int fd, dn_len, err, compr_type, use_compr;
-+ unsigned int block_no = 0;
-+ size_t out_len;
-+
-+ fd = open(path_name, O_RDONLY | O_LARGEFILE);
-+ if (fd == -1)
-+ return sys_err_msg("failed to open file '%s'", path_name);
-+ do {
-+ /* Read next block */
-+ bytes_read = 0;
-+ do {
-+ ret = read(fd, buf + bytes_read,
-+ UBIFS_BLOCK_SIZE - bytes_read);
-+ if (ret == -1) {
-+ sys_err_msg("failed to read file '%s'",
-+ path_name);
-+ close(fd);
-+ return 1;
-+ }
-+ bytes_read += ret;
-+ } while (ret != 0 && bytes_read != UBIFS_BLOCK_SIZE);
-+ if (bytes_read == 0)
-+ break;
-+ file_size += bytes_read;
-+ /* Skip holes */
-+ if (all_zero(buf, bytes_read)) {
-+ block_no += 1;
-+ continue;
-+ }
-+ /* Make data node */
-+ memset(dn, 0, UBIFS_DATA_NODE_SZ);
-+ data_key_init(c, &key, inum, block_no++);
-+ dn->ch.node_type = UBIFS_DATA_NODE;
-+ key_write(c, &key, &dn->key);
-+ dn->size = cpu_to_le32(bytes_read);
-+ out_len = NODE_BUFFER_SIZE - UBIFS_DATA_NODE_SZ;
-+ if (c->default_compr == UBIFS_COMPR_NONE &&
-+ (flags & FS_COMPR_FL))
-+ use_compr = UBIFS_COMPR_LZO;
-+ else
-+ use_compr = c->default_compr;
-+ compr_type = compress_data(buf, bytes_read, &dn->data,
-+ &out_len, use_compr);
-+ dn->compr_type = cpu_to_le16(compr_type);
-+ dn_len = UBIFS_DATA_NODE_SZ + out_len;
-+ /* Add data node to file system */
-+ err = add_node(&key, NULL, dn, dn_len);
-+ if (err) {
-+ close(fd);
-+ return err;
-+ }
-+ } while (ret != 0);
-+ if (close(fd) == -1)
-+ return sys_err_msg("failed to close file '%s'", path_name);
-+ if (file_size != st->st_size)
-+ return err_msg("file size changed during writing file '%s'",
-+ path_name);
-+ return add_inode(st, inum, flags);
-+}
-+
-+/**
-+ * add_non_dir - write a non-directory to the output file.
-+ * @path_name: source path name
-+ * @inum: target inode number is passed and returned here (due to link counting)
-+ * @nlink: number of links if known otherwise zero
-+ * @type: UBIFS inode type is returned here
-+ * @st: struct stat object containing inode attributes which should be use when
-+ * creating the UBIFS inode
-+ */
-+static int add_non_dir(const char *path_name, ino_t *inum, unsigned int nlink,
-+ unsigned char *type, struct stat *st)
-+{
-+ int fd, flags = 0;
-+
-+ dbg_msg(2, "%s", path_name);
-+
-+ if (S_ISREG(st->st_mode)) {
-+ fd = open(path_name, O_RDONLY);
-+ if (fd == -1)
-+ return sys_err_msg("failed to open file '%s'",
-+ path_name);
-+ if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1)
-+ flags = 0;
-+ if (close(fd) == -1)
-+ return sys_err_msg("failed to close file '%s'",
-+ path_name);
-+ *type = UBIFS_ITYPE_REG;
-+ } else if (S_ISCHR(st->st_mode))
-+ *type = UBIFS_ITYPE_CHR;
-+ else if (S_ISBLK(st->st_mode))
-+ *type = UBIFS_ITYPE_BLK;
-+ else if (S_ISLNK(st->st_mode))
-+ *type = UBIFS_ITYPE_LNK;
-+ else if (S_ISSOCK(st->st_mode))
-+ *type = UBIFS_ITYPE_SOCK;
-+ else if (S_ISFIFO(st->st_mode))
-+ *type = UBIFS_ITYPE_FIFO;
-+ else
-+ return err_msg("file '%s' has unknown inode type", path_name);
-+
-+ if (nlink)
-+ st->st_nlink = nlink;
-+ else if (st->st_nlink > 1) {
-+ /*
-+ * If the number of links is greater than 1, then add this file
-+ * later when we know the number of links that we actually have.
-+ * For now, we just put the inode mapping in the hash table.
-+ */
-+ struct inum_mapping *im;
-+
-+ im = lookup_inum_mapping(st->st_dev, st->st_ino);
-+ if (!im)
-+ return err_msg("out of memory");
-+ if (im->use_nlink == 0) {
-+ /* New entry */
-+ im->use_inum = *inum;
-+ im->use_nlink = 1;
-+ im->path_name = malloc(strlen(path_name) + 1);
-+ if (!im->path_name)
-+ return err_msg("out of memory");
-+ strcpy(im->path_name, path_name);
-+ } else {
-+ /* Existing entry */
-+ *inum = im->use_inum;
-+ im->use_nlink += 1;
-+ /* Return unused inode number */
-+ c->highest_inum -= 1;
-+ }
-+
-+ memcpy(&im->st, st, sizeof(struct stat));
-+ return 0;
-+ } else
-+ st->st_nlink = 1;
-+
-+ creat_sqnum = ++c->max_sqnum;
-+
-+ if (S_ISREG(st->st_mode))
-+ return add_file(path_name, st, *inum, flags);
-+ if (S_ISCHR(st->st_mode))
-+ return add_dev_inode(st, *inum, flags);
-+ if (S_ISBLK(st->st_mode))
-+ return add_dev_inode(st, *inum, flags);
-+ if (S_ISLNK(st->st_mode))
-+ return add_symlink_inode(path_name, st, *inum, flags);
-+ if (S_ISSOCK(st->st_mode))
-+ return add_inode(st, *inum, flags);
-+ if (S_ISFIFO(st->st_mode))
-+ return add_inode(st, *inum, flags);
-+
-+ return err_msg("file '%s' has unknown inode type", path_name);
-+}
-+
-+/**
-+ * add_directory - write a directory tree to the output file.
-+ * @dir_name: directory path name
-+ * @dir_inum: UBIFS inode number of directory
-+ * @st: directory inode statistics
-+ * @non_existing: non-zero if this function is called for a directory which
-+ * does not exist on the host file-system and it is being
-+ * created because it is defined in the device table file.
-+ */
-+static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
-+ int non_existing)
-+{
-+ struct dirent *entry;
-+ DIR *dir = NULL;
-+ int err = 0;
-+ loff_t size = UBIFS_INO_NODE_SZ;
-+ char *name = NULL;
-+ unsigned int nlink = 2;
-+ struct path_htbl_element *ph_elt;
-+ struct name_htbl_element *nh_elt = NULL;
-+ struct hashtable_itr *itr;
-+ ino_t inum;
-+ unsigned char type;
-+ unsigned long long dir_creat_sqnum = ++c->max_sqnum;
-+
-+ dbg_msg(2, "%s", dir_name);
-+ if (!non_existing) {
-+ dir = opendir(dir_name);
-+ if (dir == NULL)
-+ return sys_err_msg("cannot open directory '%s'",
-+ dir_name);
-+ }
-+
-+ /*
-+ * Check whether this directory contains files which should be
-+ * added/changed because they were specified in the device table.
-+ * @ph_elt will be non-zero if yes.
-+ */
-+ ph_elt = devtbl_find_path(dir_name + root_len - 1);
-+
-+ /*
-+ * Before adding the directory itself, we have to iterate over all the
-+ * entries the device table adds to this directory and create them.
-+ */
-+ for (; !non_existing;) {
-+ struct stat dent_st;
-+
-+ errno = 0;
-+ entry = readdir(dir);
-+ if (!entry) {
-+ if (errno == 0)
-+ break;
-+ sys_err_msg("error reading directory '%s'", dir_name);
-+ err = -1;
-+ break;
-+ }
-+
-+ if (strcmp(".", entry->d_name) == 0)
-+ continue;
-+ if (strcmp("..", entry->d_name) == 0)
-+ continue;
-+
-+ if (ph_elt)
-+ /*
-+ * This directory was referred to at the device table
-+ * file. Check if this directory entry is referred at
-+ * too.
-+ */
-+ nh_elt = devtbl_find_name(ph_elt, entry->d_name);
-+
-+ /*
-+ * We are going to create the file corresponding to this
-+ * directory entry (@entry->d_name). We use 'struct stat'
-+ * object to pass information about file attributes (actually
-+ * only about UID, GID, mode, major, and minor). Get attributes
-+ * for this file from the UBIFS rootfs on the host.
-+ */
-+ free(name);
-+ name = make_path(dir_name, entry->d_name);
-+ if (lstat(name, &dent_st) == -1) {
-+ sys_err_msg("lstat failed for file '%s'", name);
-+ goto out_free;
-+ }
-+
-+ if (squash_owner)
-+ /*
-+ * Squash UID/GID. But the device table may override
-+ * this.
-+ */
-+ dent_st.st_uid = dent_st.st_gid = 0;
-+
-+ /*
-+ * And if the device table describes the same file, override
-+ * the attributes. However, this is not allowed for device node
-+ * files.
-+ */
-+ if (nh_elt && override_attributes(&dent_st, ph_elt, nh_elt))
-+ goto out_free;
-+
-+ inum = ++c->highest_inum;
-+
-+ if (S_ISDIR(dent_st.st_mode)) {
-+ err = add_directory(name, inum, &dent_st, 0);
-+ if (err)
-+ goto out_free;
-+ nlink += 1;
-+ type = UBIFS_ITYPE_DIR;
-+ } else {
-+ err = add_non_dir(name, &inum, 0, &type, &dent_st);
-+ if (err)
-+ goto out_free;
-+ }
-+
-+ err = add_dent_node(dir_inum, entry->d_name, inum, type);
-+ if (err)
-+ goto out_free;
-+ size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(entry->d_name) + 1,
-+ 8);
-+ }
-+
-+ /*
-+ * OK, we have created all files in this directory (recursively), let's
-+ * also create all files described in the device table. All t
-+ */
-+ nh_elt = first_name_htbl_element(ph_elt, &itr);
-+ while (nh_elt) {
-+ struct stat fake_st;
-+
-+ /*
-+ * We prohibit creating regular files using the device table,
-+ * the device table may only re-define attributes of regular
-+ * files.
-+ */
-+ if (S_ISREG(nh_elt->mode)) {
-+ err_msg("Bad device table entry %s/%s - it is "
-+ "prohibited to create regular files "
-+ "via device table",
-+ strcmp(ph_elt->path, "/") ? ph_elt->path : "",
-+ nh_elt->name);
-+ goto out_free;
-+ }
-+
-+ memcpy(&fake_st, &root_st, sizeof(struct stat));
-+ fake_st.st_uid = nh_elt->uid;
-+ fake_st.st_uid = nh_elt->uid;
-+ fake_st.st_mode = nh_elt->mode;
-+ fake_st.st_rdev = nh_elt->dev;
-+ fake_st.st_nlink = 1;
-+
-+ free(name);
-+ name = make_path(dir_name, nh_elt->name);
-+ inum = ++c->highest_inum;
-+
-+ if (S_ISDIR(nh_elt->mode)) {
-+ err = add_directory(name, inum, &fake_st, 1);
-+ if (err)
-+ goto out_free;
-+ nlink += 1;
-+ type = UBIFS_ITYPE_DIR;
-+ } else {
-+ err = add_non_dir(name, &inum, 0, &type, &fake_st);
-+ if (err)
-+ goto out_free;
-+ }
-+
-+ err = add_dent_node(dir_inum, nh_elt->name, inum, type);
-+ if (err)
-+ goto out_free;
-+ size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(nh_elt->name) + 1, 8);
-+
-+ nh_elt = next_name_htbl_element(ph_elt, &itr);
-+ }
-+
-+ creat_sqnum = dir_creat_sqnum;
-+
-+ err = add_dir_inode(dir, dir_inum, size, nlink, st);
-+ if (err)
-+ goto out_free;
-+
-+ free(name);
-+ if (!non_existing && closedir(dir) == -1)
-+ return sys_err_msg("error closing directory '%s'", dir_name);
-+
-+ return 0;
-+
-+out_free:
-+ free(name);
-+ if (!non_existing)
-+ closedir(dir);
-+ return -1;
-+}
-+
-+/**
-+ * add_multi_linked_files - write all the files for which we counted links.
-+ */
-+static int add_multi_linked_files(void)
-+{
-+ int i, err;
-+
-+ for (i = 0; i < HASH_TABLE_SIZE; i++) {
-+ struct inum_mapping *im;
-+ unsigned char type = 0;
-+
-+ for (im = hash_table[i]; im; im = im->next) {
-+ dbg_msg(2, "%s", im->path_name);
-+ err = add_non_dir(im->path_name, &im->use_inum,
-+ im->use_nlink, &type, &im->st);
-+ if (err)
-+ return err;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * write_data - write the files and directories.
-+ */
-+static int write_data(void)
-+{
-+ int err;
-+
-+ err = stat(root, &root_st);
-+ if (err)
-+ return sys_err_msg("bad root file-system directory '%s'", root);
-+ root_st.st_uid = root_st.st_gid = 0;
-+ root_st.st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
-+
-+ head_flags = 0;
-+ err = add_directory(root, UBIFS_ROOT_INO, &root_st, 0);
-+ if (err)
-+ return err;
-+ err = add_multi_linked_files();
-+ if (err)
-+ return err;
-+ return flush_nodes();
-+}
-+
-+static int namecmp(const char *name1, const char *name2)
-+{
-+ size_t len1 = strlen(name1), len2 = strlen(name2);
-+ size_t clen = (len1 < len2) ? len1 : len2;
-+ int cmp;
-+
-+ cmp = memcmp(name1, name2, clen);
-+ if (cmp)
-+ return cmp;
-+ return (len1 < len2) ? -1 : 1;
-+}
-+
-+static int cmp_idx(const void *a, const void *b)
-+{
-+ const struct idx_entry *e1 = *(const struct idx_entry **)a;
-+ const struct idx_entry *e2 = *(const struct idx_entry **)b;
-+ int cmp;
-+
-+ cmp = keys_cmp(c, &e1->key, &e2->key);
-+ if (cmp)
-+ return cmp;
-+ return namecmp(e1->name, e2->name);
-+}
-+
-+/**
-+ * add_idx_node - write an index node to the head.
-+ * @node: index node
-+ * @child_cnt: number of children of this index node
-+ */
-+static int add_idx_node(void *node, int child_cnt)
-+{
-+ int err, lnum, offs, len;
-+
-+ len = ubifs_idx_node_sz(c, child_cnt);
-+
-+ prepare_node(node, len);
-+
-+ err = reserve_space(len, &lnum, &offs);
-+ if (err)
-+ return err;
-+
-+ memcpy(leb_buf + offs, node, len);
-+ memset(leb_buf + offs + len, 0xff, ALIGN(len, 8) - len);
-+
-+ c->old_idx_sz += ALIGN(len, 8);
-+
-+ dbg_msg(3, "at %d:%d len %d index size %llu", lnum, offs, len,
-+ c->old_idx_sz);
-+
-+ /* The last index node written will be the root */
-+ c->zroot.lnum = lnum;
-+ c->zroot.offs = offs;
-+ c->zroot.len = len;
-+
-+ return 0;
-+}
-+
-+/**
-+ * write_index - write out the index.
-+ */
-+static int write_index(void)
-+{
-+ size_t sz, i, cnt, idx_sz, pstep, bcnt;
-+ struct idx_entry **idx_ptr, **p;
-+ struct ubifs_idx_node *idx;
-+ struct ubifs_branch *br;
-+ int child_cnt, j, level, blnum, boffs, blen, blast_len, err;
-+
-+ dbg_msg(1, "leaf node count: %d", idx_cnt);
-+
-+ /* Reset the head for the index */
-+ head_flags = LPROPS_INDEX;
-+ /* Allocate index node */
-+ idx_sz = ubifs_idx_node_sz(c, c->fanout);
-+ idx = malloc(idx_sz);
-+ if (!idx)
-+ return err_msg("out of memory");
-+ /* Make an array of pointers to sort the index list */
-+ sz = idx_cnt * sizeof(struct idx_entry *);
-+ if (sz / sizeof(struct idx_entry *) != idx_cnt) {
-+ free(idx);
-+ return err_msg("index is too big (%zu entries)", idx_cnt);
-+ }
-+ idx_ptr = malloc(sz);
-+ if (!idx_ptr) {
-+ free(idx);
-+ return err_msg("out of memory - needed %zu bytes for index",
-+ sz);
-+ }
-+ idx_ptr[0] = idx_list_first;
-+ for (i = 1; i < idx_cnt; i++)
-+ idx_ptr[i] = idx_ptr[i - 1]->next;
-+ qsort(idx_ptr, idx_cnt, sizeof(struct idx_entry *), cmp_idx);
-+ /* Write level 0 index nodes */
-+ cnt = idx_cnt / c->fanout;
-+ if (idx_cnt % c->fanout)
-+ cnt += 1;
-+ p = idx_ptr;
-+ blnum = head_lnum;
-+ boffs = head_offs;
-+ for (i = 0; i < cnt; i++) {
-+ /*
-+ * Calculate the child count. All index nodes are created full
-+ * except for the last index node on each row.
-+ */
-+ if (i == cnt - 1) {
-+ child_cnt = idx_cnt % c->fanout;
-+ if (child_cnt == 0)
-+ child_cnt = c->fanout;
-+ } else
-+ child_cnt = c->fanout;
-+ memset(idx, 0, idx_sz);
-+ idx->ch.node_type = UBIFS_IDX_NODE;
-+ idx->child_cnt = cpu_to_le16(child_cnt);
-+ idx->level = cpu_to_le16(0);
-+ for (j = 0; j < child_cnt; j++, p++) {
-+ br = ubifs_idx_branch(c, idx, j);
-+ key_write_idx(c, &(*p)->key, &br->key);
-+ br->lnum = cpu_to_le32((*p)->lnum);
-+ br->offs = cpu_to_le32((*p)->offs);
-+ br->len = cpu_to_le32((*p)->len);
-+ }
-+ add_idx_node(idx, child_cnt);
-+ }
-+ /* Write level 1 index nodes and above */
-+ level = 0;
-+ pstep = 1;
-+ while (cnt > 1) {
-+ /*
-+ * 'blast_len' is the length of the last index node in the level
-+ * below.
-+ */
-+ blast_len = ubifs_idx_node_sz(c, child_cnt);
-+ /* 'bcnt' is the number of index nodes in the level below */
-+ bcnt = cnt;
-+ /* 'cnt' is the number of index nodes in this level */
-+ cnt = (cnt + c->fanout - 1) / c->fanout;
-+ if (cnt == 0)
-+ cnt = 1;
-+ level += 1;
-+ /*
-+ * The key of an index node is the same as the key of its first
-+ * child. Thus we can get the key by stepping along the bottom
-+ * level 'p' with an increasing large step 'pstep'.
-+ */
-+ p = idx_ptr;
-+ pstep *= c->fanout;
-+ for (i = 0; i < cnt; i++) {
-+ /*
-+ * Calculate the child count. All index nodes are
-+ * created full except for the last index node on each
-+ * row.
-+ */
-+ if (i == cnt - 1) {
-+ child_cnt = bcnt % c->fanout;
-+ if (child_cnt == 0)
-+ child_cnt = c->fanout;
-+ } else
-+ child_cnt = c->fanout;
-+ memset(idx, 0, idx_sz);
-+ idx->ch.node_type = UBIFS_IDX_NODE;
-+ idx->child_cnt = cpu_to_le16(child_cnt);
-+ idx->level = cpu_to_le16(level);
-+ for (j = 0; j < child_cnt; j++) {
-+ size_t bn = i * c->fanout + j;
-+
-+ /*
-+ * The length of the index node in the level
-+ * below is 'idx_sz' except when it is the last
-+ * node on the row. i.e. all the others on the
-+ * row are full.
-+ */
-+ if (bn == bcnt - 1)
-+ blen = blast_len;
-+ else
-+ blen = idx_sz;
-+ /*
-+ * 'blnum' and 'boffs' hold the position of the
-+ * index node on the level below.
-+ */
-+ if (boffs + blen > c->leb_size) {
-+ blnum += 1;
-+ boffs = 0;
-+ }
-+ /*
-+ * Fill in the branch with the key and position
-+ * of the index node from the level below.
-+ */
-+ br = ubifs_idx_branch(c, idx, j);
-+ key_write_idx(c, &(*p)->key, &br->key);
-+ br->lnum = cpu_to_le32(blnum);
-+ br->offs = cpu_to_le32(boffs);
-+ br->len = cpu_to_le32(blen);
-+ /*
-+ * Step to the next index node on the level
-+ * below.
-+ */
-+ boffs += ALIGN(blen, 8);
-+ p += pstep;
-+ }
-+ add_idx_node(idx, child_cnt);
-+ }
-+ }
-+
-+ /* Free stuff */
-+ for (i = 0; i < idx_cnt; i++)
-+ free(idx_ptr[i]);
-+ free(idx_ptr);
-+ free(idx);
-+
-+ dbg_msg(1, "zroot is at %d:%d len %d", c->zroot.lnum, c->zroot.offs,
-+ c->zroot.len);
-+
-+ /* Set the index head */
-+ c->ihead_lnum = head_lnum;
-+ c->ihead_offs = ALIGN(head_offs, c->min_io_size);
-+ dbg_msg(1, "ihead is at %d:%d", c->ihead_lnum, c->ihead_offs);
-+
-+ /* Flush the last index LEB */
-+ err = flush_nodes();
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+/**
-+ * set_gc_lnum - set the LEB number reserved for the garbage collector.
-+ */
-+static int set_gc_lnum(void)
-+{
-+ int err;
-+
-+ c->gc_lnum = head_lnum++;
-+ err = write_empty_leb(c->gc_lnum);
-+ if (err)
-+ return err;
-+ set_lprops(c->gc_lnum, 0, 0);
-+ c->lst.empty_lebs += 1;
-+ return 0;
-+}
-+
-+/**
-+ * finalize_leb_cnt - now that we know how many LEBs we used.
-+ */
-+static int finalize_leb_cnt(void)
-+{
-+ c->leb_cnt = head_lnum;
-+ if (c->leb_cnt > c->max_leb_cnt)
-+ /* TODO: in this case it segfaults because buffer overruns - we
-+ * somewhere allocate smaller buffers - fix */
-+ return err_msg("max_leb_cnt too low (%d needed)", c->leb_cnt);
-+ c->main_lebs = c->leb_cnt - c->main_first;
-+ if (verbose) {
-+ printf("\tsuper lebs: %d\n", UBIFS_SB_LEBS);
-+ printf("\tmaster lebs: %d\n", UBIFS_MST_LEBS);
-+ printf("\tlog_lebs: %d\n", c->log_lebs);
-+ printf("\tlpt_lebs: %d\n", c->lpt_lebs);
-+ printf("\torph_lebs: %d\n", c->orph_lebs);
-+ printf("\tmain_lebs: %d\n", c->main_lebs);
-+ printf("\tgc lebs: %d\n", 1);
-+ printf("\tindex lebs: %d\n", c->lst.idx_lebs);
-+ printf("\tleb_cnt: %d\n", c->leb_cnt);
-+ }
-+ dbg_msg(1, "total_free: %llu", c->lst.total_free);
-+ dbg_msg(1, "total_dirty: %llu", c->lst.total_dirty);
-+ dbg_msg(1, "total_used: %llu", c->lst.total_used);
-+ dbg_msg(1, "total_dead: %llu", c->lst.total_dead);
-+ dbg_msg(1, "total_dark: %llu", c->lst.total_dark);
-+ dbg_msg(1, "index size: %llu", c->old_idx_sz);
-+ dbg_msg(1, "empty_lebs: %d", c->lst.empty_lebs);
-+ return 0;
-+}
-+
-+/**
-+ * write_super - write the super block.
-+ */
-+static int write_super(void)
-+{
-+ struct ubifs_sb_node sup;
-+
-+ memset(&sup, 0, UBIFS_SB_NODE_SZ);
-+
-+ sup.ch.node_type = UBIFS_SB_NODE;
-+ sup.key_hash = c->key_hash_type;
-+ sup.min_io_size = cpu_to_le32(c->min_io_size);
-+ sup.leb_size = cpu_to_le32(c->leb_size);
-+ sup.leb_cnt = cpu_to_le32(c->leb_cnt);
-+ sup.max_leb_cnt = cpu_to_le32(c->max_leb_cnt);
-+ sup.max_bud_bytes = cpu_to_le64(c->max_bud_bytes);
-+ sup.log_lebs = cpu_to_le32(c->log_lebs);
-+ sup.lpt_lebs = cpu_to_le32(c->lpt_lebs);
-+ sup.orph_lebs = cpu_to_le32(c->orph_lebs);
-+ sup.jhead_cnt = cpu_to_le32(c->jhead_cnt);
-+ sup.fanout = cpu_to_le32(c->fanout);
-+ sup.lsave_cnt = cpu_to_le32(c->lsave_cnt);
-+ sup.fmt_version = cpu_to_le32(UBIFS_FORMAT_VERSION);
-+ sup.default_compr = cpu_to_le16(c->default_compr);
-+ sup.time_gran = cpu_to_le32(DEFAULT_TIME_GRAN);
-+ if (c->big_lpt)
-+ sup.flags |= UBIFS_FLG_BIGLPT;
-+
-+ return write_node(&sup, UBIFS_SB_NODE_SZ, UBIFS_SB_LNUM);
-+}
-+
-+/**
-+ * write_master - write the master node.
-+ */
-+static int write_master(void)
-+{
-+ struct ubifs_mst_node mst;
-+ int err;
-+
-+ memset(&mst, 0, UBIFS_MST_NODE_SZ);
-+
-+ mst.ch.node_type = UBIFS_MST_NODE;
-+ mst.log_lnum = cpu_to_le32(UBIFS_LOG_LNUM);
-+ mst.highest_inum = cpu_to_le64(c->highest_inum);
-+ mst.cmt_no = cpu_to_le64(0);
-+ mst.flags = cpu_to_le32(UBIFS_MST_NO_ORPHS);
-+ mst.root_lnum = cpu_to_le32(c->zroot.lnum);
-+ mst.root_offs = cpu_to_le32(c->zroot.offs);
-+ mst.root_len = cpu_to_le32(c->zroot.len);
-+ mst.gc_lnum = cpu_to_le32(c->gc_lnum);
-+ mst.ihead_lnum = cpu_to_le32(c->ihead_lnum);
-+ mst.ihead_offs = cpu_to_le32(c->ihead_offs);
-+ mst.index_size = cpu_to_le64(c->old_idx_sz);
-+ mst.lpt_lnum = cpu_to_le32(c->lpt_lnum);
-+ mst.lpt_offs = cpu_to_le32(c->lpt_offs);
-+ mst.nhead_lnum = cpu_to_le32(c->nhead_lnum);
-+ mst.nhead_offs = cpu_to_le32(c->nhead_offs);
-+ mst.ltab_lnum = cpu_to_le32(c->ltab_lnum);
-+ mst.ltab_offs = cpu_to_le32(c->ltab_offs);
-+ mst.lsave_lnum = cpu_to_le32(c->lsave_lnum);
-+ mst.lsave_offs = cpu_to_le32(c->lsave_offs);
-+ mst.lscan_lnum = cpu_to_le32(c->lscan_lnum);
-+ mst.empty_lebs = cpu_to_le32(c->lst.empty_lebs);
-+ mst.idx_lebs = cpu_to_le32(c->lst.idx_lebs);
-+ mst.total_free = cpu_to_le64(c->lst.total_free);
-+ mst.total_dirty = cpu_to_le64(c->lst.total_dirty);
-+ mst.total_used = cpu_to_le64(c->lst.total_used);
-+ mst.total_dead = cpu_to_le64(c->lst.total_dead);
-+ mst.total_dark = cpu_to_le64(c->lst.total_dark);
-+ mst.leb_cnt = cpu_to_le32(c->leb_cnt);
-+
-+ err = write_node(&mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM);
-+ if (err)
-+ return err;
-+
-+ err = write_node(&mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1);
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+/**
-+ * write_log - write an empty log.
-+ */
-+static int write_log(void)
-+{
-+ struct ubifs_cs_node cs;
-+ int err, i, lnum;
-+
-+ lnum = UBIFS_LOG_LNUM;
-+
-+ cs.ch.node_type = UBIFS_CS_NODE;
-+ cs.cmt_no = cpu_to_le64(0);
-+
-+ err = write_node(&cs, UBIFS_CS_NODE_SZ, lnum);
-+ if (err)
-+ return err;
-+
-+ lnum += 1;
-+
-+ for (i = 1; i < c->log_lebs; i++, lnum++) {
-+ err = write_empty_leb(lnum);
-+ if (err)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * write_lpt - write the LEB properties tree.
-+ */
-+static int write_lpt(void)
-+{
-+ int err, lnum;
-+
-+ err = create_lpt(c);
-+ if (err)
-+ return err;
-+
-+ lnum = c->nhead_lnum + 1;
-+ while (lnum <= c->lpt_last) {
-+ err = write_empty_leb(lnum++);
-+ if (err)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * write_orphan_area - write an empty orphan area.
-+ */
-+static int write_orphan_area(void)
-+{
-+ int err, i, lnum;
-+
-+ lnum = UBIFS_LOG_LNUM + c->log_lebs + c->lpt_lebs;
-+ for (i = 0; i < c->orph_lebs; i++, lnum++) {
-+ err = write_empty_leb(lnum);
-+ if (err)
-+ return err;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * open_target - open the output file.
-+ */
-+static int open_target(void)
-+{
-+ out_fd = open(output, O_CREAT | O_RDWR | O_TRUNC,
-+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
-+ if (out_fd == -1)
-+ return sys_err_msg("cannot create output file '%s'", output);
-+ return 0;
-+}
-+
-+/**
-+ * close_target - close the output file.
-+ */
-+static int close_target(void)
-+{
-+ if (close(out_fd) == -1)
-+ return sys_err_msg("cannot close output file '%s'", output);
-+ return 0;
-+}
-+
-+/**
-+ * init - initialize things.
-+ */
-+static int init(void)
-+{
-+ int err, i, main_lebs, big_lpt = 0, sz;
-+
-+ c->highest_inum = UBIFS_FIRST_INO;
-+
-+ c->jhead_cnt = 1;
-+
-+ main_lebs = c->max_leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS;
-+ main_lebs -= c->log_lebs + c->orph_lebs;
-+
-+ err = calc_dflt_lpt_geom(c, &main_lebs, &big_lpt);
-+ if (err)
-+ return err;
-+
-+ c->main_first = UBIFS_LOG_LNUM + c->log_lebs + c->lpt_lebs +
-+ c->orph_lebs;
-+ head_lnum = c->main_first;
-+ head_offs = 0;
-+
-+ c->lpt_first = UBIFS_LOG_LNUM + c->log_lebs;
-+ c->lpt_last = c->lpt_first + c->lpt_lebs - 1;
-+
-+ c->lpt = malloc(c->main_lebs * sizeof(struct ubifs_lprops));
-+ if (!c->lpt)
-+ return err_msg("unable to allocate LPT");
-+
-+ c->ltab = malloc(c->lpt_lebs * sizeof(struct ubifs_lprops));
-+ if (!c->ltab)
-+ return err_msg("unable to allocate LPT ltab");
-+
-+ /* Initialize LPT's own lprops */
-+ for (i = 0; i < c->lpt_lebs; i++) {
-+ c->ltab[i].free = c->leb_size;
-+ c->ltab[i].dirty = 0;
-+ }
-+
-+ c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size);
-+ c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size);
-+ dbg_msg(1, "dead_wm %d dark_wm %d", c->dead_wm, c->dark_wm);
-+
-+ leb_buf = malloc(c->leb_size);
-+ if (!leb_buf)
-+ return err_msg("out of memory");
-+
-+ node_buf = malloc(NODE_BUFFER_SIZE);
-+ if (!node_buf)
-+ return err_msg("out of memory");
-+
-+ block_buf = malloc(UBIFS_BLOCK_SIZE);
-+ if (!block_buf)
-+ return err_msg("out of memory");
-+
-+ sz = sizeof(struct inum_mapping *) * HASH_TABLE_SIZE;
-+ hash_table = malloc(sz);
-+ if (!hash_table)
-+ return err_msg("out of memory");
-+ memset(hash_table, 0, sz);
-+
-+ err = init_compression();
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+static void destroy_hash_table(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < HASH_TABLE_SIZE; i++) {
-+ struct inum_mapping *im, *q;
-+
-+ for (im = hash_table[i]; im; ) {
-+ q = im;
-+ im = im->next;
-+ free(q->path_name);
-+ free(q);
-+ }
-+ }
-+}
-+
-+/**
-+ * deinit - deinitialize things.
-+ */
-+static void deinit(void)
-+{
-+ free(c->lpt);
-+ free(c->ltab);
-+ free(leb_buf);
-+ free(node_buf);
-+ free(block_buf);
-+ destroy_hash_table();
-+ free(hash_table);
-+ destroy_compression();
-+ free_devtable_info();
-+}
-+
-+/**
-+ * mkfs - make the file system.
-+ *
-+ * Each on-flash area has a corresponding function to create it. The order of
-+ * the functions reflects what information must be known to complete each stage.
-+ * As a consequence the output file is not written sequentially. No effort has
-+ * been made to make efficient use of memory or to allow for the possibility of
-+ * incremental updates to the output file.
-+ */
-+static int mkfs(void)
-+{
-+ int err = 0;
-+
-+ err = init();
-+ if (err)
-+ goto out;
-+
-+ err = write_data();
-+ if (err)
-+ goto out;
-+
-+ err = set_gc_lnum();
-+ if (err)
-+ goto out;
-+
-+ err = write_index();
-+ if (err)
-+ goto out;
-+
-+ err = finalize_leb_cnt();
-+ if (err)
-+ goto out;
-+
-+ err = write_lpt();
-+ if (err)
-+ goto out;
-+
-+ err = write_super();
-+ if (err)
-+ goto out;
-+
-+ err = write_master();
-+ if (err)
-+ goto out;
-+
-+ err = write_log();
-+ if (err)
-+ goto out;
-+
-+ err = write_orphan_area();
-+
-+out:
-+ deinit();
-+ return err;
-+}
-+
-+int main(int argc, char *argv[])
-+{
-+ int err;
-+
-+ err = get_options(argc, argv);
-+ if (err)
-+ return err;
-+
-+ err = open_target();
-+ if (err)
-+ return err;
-+
-+ err = mkfs();
-+ if (err) {
-+ close_target();
-+ return err;
-+ }
-+
-+ err = close_target();
-+ if (err)
-+ return err;
-+
-+ if (verbose)
-+ printf("Success!\n");
-+
-+ return 0;
-+}
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/mkfs.ubifs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/mkfs.ubifs.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,143 @@
-+/*
-+ * Copyright (C) 2008 Nokia Corporation.
-+ * Copyright (C) 2008 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy
-+ * Adrian Hunter
-+ * Zoltan Sogor
-+ */
-+
-+#ifndef __MKFS_UBIFS_H__
-+#define __MKFS_UBIFS_H__
-+
-+#define _GNU_SOURCE
-+#define _LARGEFILE64_SOURCE
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "crc32.h"
-+#include "defs.h"
-+#include "crc16.h"
-+#include "ubifs-media.h"
-+#include "ubifs.h"
-+#include "key.h"
-+#include "lpt.h"
-+#include "compr.h"
-+
-+/*
-+ * Compression flags are duplicated so that compr.c can compile without ubifs.h.
-+ * Here we make sure they are the same.
-+ */
-+#if MKFS_UBIFS_COMPR_NONE != UBIFS_COMPR_NONE
-+#error MKFS_UBIFS_COMPR_NONE != UBIFS_COMPR_NONE
-+#endif
-+#if MKFS_UBIFS_COMPR_LZO != UBIFS_COMPR_LZO
-+#error MKFS_UBIFS_COMPR_LZO != UBIFS_COMPR_LZO
-+#endif
-+#if MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
-+#error MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
-+#endif
-+
-+extern int verbose;
-+extern int debug_level;
-+
-+#define dbg_msg(lvl, fmt, ...) do {if (debug_level >= lvl) \
-+ printf("mkfs.ubifs: %s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \
-+} while(0)
-+
-+#define err_msg(fmt, ...) ({ \
-+ fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__); \
-+ -1; \
-+})
-+
-+#define sys_err_msg(fmt, ...) ({ \
-+ int err_ = errno; \
-+ fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__); \
-+ fprintf(stderr, " %s (error %d)\n", strerror(err_), err_); \
-+ -1; \
-+})
-+
-+/**
-+ * struct path_htbl_element - an element of the path hash table.
-+ * @path: the UBIFS path the element describes (the key of the element)
-+ * @name_htbl: one more (nested) hash table containing names of all
-+ * files/directories/device nodes which should be created at this
-+ * path
-+ *
-+ * See device table handling for more information.
-+ */
-+struct path_htbl_element {
-+ const char *path;
-+ struct hashtable *name_htbl;
-+};
-+
-+/**
-+ * struct name_htbl_element - an element in the name hash table
-+ * @name: name of the file/directory/device node (the key of the element)
-+ * @mode: accsess rights and file type
-+ * @uid: user ID
-+ * @gid: group ID
-+ * @major: device node major number
-+ * @minor: device node minor number
-+ *
-+ * This is an element of the name hash table. Name hash table sits in the path
-+ * hash table elements and describes file names which should be created/changed
-+ * at this path.
-+ */
-+struct name_htbl_element {
-+ const char *name;
-+ unsigned int mode;
-+ unsigned int uid;
-+ unsigned int gid;
-+ dev_t dev;
-+};
-+
-+struct hashtable_itr;
-+
-+int write_leb(int lnum, int len, void *buf);
-+int parse_devtable(const char *root, const char *tbl_file);
-+struct path_htbl_element *devtbl_find_path(const char *path);
-+struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt,
-+ const char *name);
-+int override_attributes(struct stat *st, struct path_htbl_element *ph_elt,
-+ struct name_htbl_element *nh_elt);
-+struct name_htbl_element *
-+first_name_htbl_element(struct path_htbl_element *ph_elt,
-+ struct hashtable_itr **itr);
-+struct name_htbl_element *
-+next_name_htbl_element(struct path_htbl_element *ph_elt,
-+ struct hashtable_itr **itr);
-+void free_devtable_info(void);
-+
-+#endif
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/readme 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/readme 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,28 @@
-+UBIFS File System - Make File System program
-+
-+* crc16.h and crc16.c were copied from the linux kernel.
-+* crc32.h and crc32.c were copied from mtd-utils and amended.
-+* ubifs-media.h is fs/ubifs/ubifs-media.h from the linux kernel
-+* ubifs.h is a selection of definitions from fs/ubifs/ubifs.h from the linux kernel.
-+* key.h is copied from fs/ubifs/key.h from the linux kernel.
-+* defs.h is a bunch of definitions to smooth things over.
-+* lpt.c is a selection of functions copied from fs/ubifs/lpt.c from the linux kernel, and amended.
-+* hashtable/* was downloaded from http://www.cl.cam.ac.uk/~cwc22/hashtable/
-+
-+***************************************************************************
-+
-+To build the mkfs.ubifs:
-+
-+$ cd fs/ubifs/mkfs.ubifs
-+$ make
-+
-+To run mkfs.ubifs:
-+
-+$ export LD_LIBRARY_PATH=`pwd`/lzo/lib:$LD_LIBRARY_PATH
-+$ ./mkfs.ubifs -h
-+
-+To build an ubifs image:
-+
-+$ ./mkfs.ubifs -r /nfsroot/root26 -m 2048 -e 258048 -c 813 -o ubifs.img
-+
-+***************************************************************************
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/ubifs-media.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/ubifs-media.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,725 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file describes UBIFS on-flash format and contains definitions of all the
-+ * relevant data structures and constants.
-+ *
-+ * All UBIFS on-flash objects are stored in the form of nodes. All nodes start
-+ * with the UBIFS node magic number and have the same common header. Nodes
-+ * always sit at 8-byte aligned positions on the media and node header sizes are
-+ * also 8-byte aligned (except for the indexing node and the padding node).
-+ */
-+
-+#ifndef __UBIFS_MEDIA_H__
-+#define __UBIFS_MEDIA_H__
-+
-+/* UBIFS node magic number (must not have the padding byte first or last) */
-+#define UBIFS_NODE_MAGIC 0x06101831
-+
-+/* UBIFS on-flash format version */
-+#define UBIFS_FORMAT_VERSION 3
-+
-+/* Minimum logical eraseblock size in bytes */
-+#define UBIFS_MIN_LEB_SZ (15*1024)
-+
-+/* Initial CRC32 value used when calculating CRC checksums */
-+#define UBIFS_CRC32_INIT 0xFFFFFFFFU
-+
-+/*
-+ * UBIFS does not try to compress data if its length is less than the below
-+ * constant.
-+ */
-+#define UBIFS_MIN_COMPR_LEN 128
-+
-+/* Root inode number */
-+#define UBIFS_ROOT_INO 1
-+
-+/* Lowest inode number used for regular inodes (not UBIFS-only internal ones) */
-+#define UBIFS_FIRST_INO 64
-+
-+/*
-+ * Maximum file name and extended attribute length (must be a multiple of 8,
-+ * minus 1).
-+ */
-+#define UBIFS_MAX_NLEN 255
-+
-+/* Maximum number of data journal heads */
-+#define UBIFS_MAX_JHEADS 1
-+
-+/*
-+ * Size of UBIFS data block. Note, UBIFS is not a block oriented file-system,
-+ * which means that it does not treat the underlying media as consisting of
-+ * blocks like in case of hard drives. Do not be confused. UBIFS block is just
-+ * the maximum amount of data which one data node can have or which can be
-+ * attached to an inode node.
-+ */
-+#define UBIFS_BLOCK_SIZE 4096
-+#define UBIFS_BLOCK_SHIFT 12
-+#define UBIFS_BLOCK_MASK 0x00000FFF
-+
-+/* UBIFS padding byte pattern (must not be first or last byte of node magic) */
-+#define UBIFS_PADDING_BYTE 0xCE
-+
-+/* Maximum possible key length */
-+#define UBIFS_MAX_KEY_LEN 16
-+
-+/* Key length ("simple" format) */
-+#define UBIFS_SK_LEN 8
-+
-+/* Minimum index tree fanout */
-+#define UBIFS_MIN_FANOUT 2
-+
-+/* Maximum number of levels in UBIFS indexing B-tree */
-+#define UBIFS_MAX_LEVELS 512
-+
-+/* Maximum amount of data attached to an inode in bytes */
-+#define UBIFS_MAX_INO_DATA UBIFS_BLOCK_SIZE
-+
-+/* LEB Properties Tree fanout (must be power of 2) and fanout shift */
-+#define UBIFS_LPT_FANOUT 4
-+#define UBIFS_LPT_FANOUT_SHIFT 2
-+
-+/* LEB Properties Tree bit field sizes */
-+#define UBIFS_LPT_CRC_BITS 16
-+#define UBIFS_LPT_CRC_BYTES 2
-+#define UBIFS_LPT_TYPE_BITS 4
-+
-+/* The key is always at the same position in all keyed nodes */
-+#define UBIFS_KEY_OFFSET offsetof(struct ubifs_ino_node, key)
-+
-+/*
-+ * LEB Properties Tree node types.
-+ *
-+ * UBIFS_LPT_PNODE: LPT leaf node (contains LEB properties)
-+ * UBIFS_LPT_NNODE: LPT internal node
-+ * UBIFS_LPT_LTAB: LPT's own lprops table
-+ * UBIFS_LPT_LSAVE: LPT's save table (big model only)
-+ * UBIFS_LPT_NODE_CNT: count of LPT node types
-+ * UBIFS_LPT_NOT_A_NODE: all ones (15 for 4 bits) is never a valid node type
-+ */
-+enum {
-+ UBIFS_LPT_PNODE,
-+ UBIFS_LPT_NNODE,
-+ UBIFS_LPT_LTAB,
-+ UBIFS_LPT_LSAVE,
-+ UBIFS_LPT_NODE_CNT,
-+ UBIFS_LPT_NOT_A_NODE = (1 << UBIFS_LPT_TYPE_BITS) - 1,
-+};
-+
-+/*
-+ * UBIFS inode types.
-+ *
-+ * UBIFS_ITYPE_REG: regular file
-+ * UBIFS_ITYPE_DIR: directory
-+ * UBIFS_ITYPE_LNK: soft link
-+ * UBIFS_ITYPE_BLK: block device node
-+ * UBIFS_ITYPE_CHR: character device node
-+ * UBIFS_ITYPE_FIFO: fifo
-+ * UBIFS_ITYPE_SOCK: socket
-+ * UBIFS_ITYPES_CNT: count of supported file types
-+ */
-+enum {
-+ UBIFS_ITYPE_REG,
-+ UBIFS_ITYPE_DIR,
-+ UBIFS_ITYPE_LNK,
-+ UBIFS_ITYPE_BLK,
-+ UBIFS_ITYPE_CHR,
-+ UBIFS_ITYPE_FIFO,
-+ UBIFS_ITYPE_SOCK,
-+ UBIFS_ITYPES_CNT,
-+};
-+
-+/*
-+ * Supported key hash functions.
-+ *
-+ * UBIFS_KEY_HASH_R5: R5 hash
-+ * UBIFS_KEY_HASH_TEST: test hash which just returns first 4 bytes of the name
-+ */
-+enum {
-+ UBIFS_KEY_HASH_R5,
-+ UBIFS_KEY_HASH_TEST,
-+};
-+
-+/*
-+ * Supported key formats.
-+ *
-+ * UBIFS_SIMPLE_KEY_FMT: simple key format
-+ */
-+enum {
-+ UBIFS_SIMPLE_KEY_FMT,
-+};
-+
-+/*
-+ * The simple key format uses 29 bits for storing UBIFS block number and hash
-+ * value.
-+ */
-+#define UBIFS_S_KEY_BLOCK_BITS 29
-+#define UBIFS_S_KEY_BLOCK_MASK 0x1FFFFFFF
-+#define UBIFS_S_KEY_HASH_BITS UBIFS_S_KEY_BLOCK_BITS
-+#define UBIFS_S_KEY_HASH_MASK UBIFS_S_KEY_BLOCK_MASK
-+
-+/*
-+ * Key types.
-+ *
-+ * UBIFS_INO_KEY: inode node key
-+ * UBIFS_DATA_KEY: data node key
-+ * UBIFS_DENT_KEY: directory entry node key
-+ * UBIFS_XENT_KEY: extended attribute entry key
-+ * UBIFS_TRUN_KEY: truncation node key
-+ * UBIFS_KEY_TYPES_CNT: number of supported key types
-+ */
-+enum {
-+ UBIFS_INO_KEY,
-+ UBIFS_DATA_KEY,
-+ UBIFS_DENT_KEY,
-+ UBIFS_XENT_KEY,
-+ UBIFS_TRUN_KEY,
-+ UBIFS_KEY_TYPES_CNT,
-+};
-+
-+/* Count of LEBs reserved for the superblock area */
-+#define UBIFS_SB_LEBS 1
-+/* Count of LEBs reserved for the master area */
-+#define UBIFS_MST_LEBS 2
-+
-+/* First LEB of the superblock area */
-+#define UBIFS_SB_LNUM 0
-+/* First LEB of the master area */
-+#define UBIFS_MST_LNUM (UBIFS_SB_LNUM + UBIFS_SB_LEBS)
-+/* First LEB of the log area */
-+#define UBIFS_LOG_LNUM (UBIFS_MST_LNUM + UBIFS_MST_LEBS)
-+
-+/* Minimum number of logical eraseblocks in the log */
-+#define UBIFS_MIN_LOG_LEBS 2
-+/* Minimum number of bud logical eraseblocks */
-+#define UBIFS_MIN_BUD_LEBS 2
-+/* Minimum number of journal logical eraseblocks */
-+#define UBIFS_MIN_JNL_LEBS (UBIFS_MIN_LOG_LEBS + UBIFS_MIN_BUD_LEBS)
-+/* Minimum number of LPT area logical eraseblocks */
-+#define UBIFS_MIN_LPT_LEBS 2
-+/* Minimum number of orphan area logical eraseblocks */
-+#define UBIFS_MIN_ORPH_LEBS 1
-+/* Minimum number of main area logical eraseblocks */
-+#define UBIFS_MIN_MAIN_LEBS 8
-+
-+/* Minimum number of logical eraseblocks */
-+#define UBIFS_MIN_LEB_CNT (UBIFS_SB_LEBS + UBIFS_MST_LEBS + \
-+ UBIFS_MIN_LOG_LEBS + UBIFS_MIN_BUD_LEBS + \
-+ UBIFS_MIN_LPT_LEBS + UBIFS_MIN_ORPH_LEBS + \
-+ UBIFS_MIN_MAIN_LEBS)
-+
-+/* Node sizes (N.B. these are guaranteed to be multiples of 8) */
-+#define UBIFS_CH_SZ sizeof(struct ubifs_ch)
-+#define UBIFS_INO_NODE_SZ sizeof(struct ubifs_ino_node)
-+#define UBIFS_DATA_NODE_SZ sizeof(struct ubifs_data_node)
-+#define UBIFS_DENT_NODE_SZ sizeof(struct ubifs_dent_node)
-+#define UBIFS_TRUN_NODE_SZ sizeof(struct ubifs_trun_node)
-+#define UBIFS_PAD_NODE_SZ sizeof(struct ubifs_pad_node)
-+#define UBIFS_SB_NODE_SZ sizeof(struct ubifs_sb_node)
-+#define UBIFS_MST_NODE_SZ sizeof(struct ubifs_mst_node)
-+#define UBIFS_REF_NODE_SZ sizeof(struct ubifs_ref_node)
-+#define UBIFS_IDX_NODE_SZ sizeof(struct ubifs_idx_node)
-+#define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node)
-+#define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node)
-+/* Extended attribute entry nodes are identical to directory entry nodes */
-+#define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ
-+/* Only this does not have to be multiple of 8 bytes */
-+#define UBIFS_BRANCH_SZ sizeof(struct ubifs_branch)
-+
-+/* Maximum node sizes (N.B. these are guaranteed to be multiples of 8) */
-+#define UBIFS_MAX_DATA_NODE_SZ (UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE)
-+#define UBIFS_MAX_INO_NODE_SZ (UBIFS_INO_NODE_SZ + UBIFS_MAX_INO_DATA)
-+#define UBIFS_MAX_DENT_NODE_SZ (UBIFS_DENT_NODE_SZ + UBIFS_MAX_NLEN + 1)
-+#define UBIFS_MAX_XENT_NODE_SZ UBIFS_MAX_DENT_NODE_SZ
-+
-+/* The largest UBIFS node */
-+#define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ
-+
-+/*
-+ * On-flash inode flags.
-+ *
-+ * UBIFS_COMPR_FL: use compression for this inode
-+ * UBIFS_SYNC_FL: I/O on this inode has to be synchronous
-+ * UBIFS_IMMUTABLE_FL: inode is immutable
-+ * UBIFS_APPEND_FL: writes to the inode may only append data
-+ * UBIFS_DIRSYNC_FL: I/O on this directory inode has to be synchronous
-+ *
-+ * Note, these are on-flash flags which correspond to ioctl flags
-+ * (@FS_COMPR_FL, etc). They have the same values now, but generally, do not
-+ * have to be the same.
-+ */
-+enum {
-+ UBIFS_COMPR_FL = 0x01,
-+ UBIFS_SYNC_FL = 0x02,
-+ UBIFS_IMMUTABLE_FL = 0x04,
-+ UBIFS_APPEND_FL = 0x08,
-+ UBIFS_DIRSYNC_FL = 0x10,
-+};
-+
-+/* Inode flag bits used by UBIFS */
-+#define UBIFS_FL_MASK 0x0000001F
-+
-+/*
-+ * UBIFS compression algorithms.
-+ *
-+ * UBIFS_COMPR_NONE: no compression
-+ * UBIFS_COMPR_LZO: LZO compression
-+ * UBIFS_COMPR_ZLIB: ZLIB compression
-+ * UBIFS_COMPR_TYPES_CNT: count of supported compression types
-+ */
-+enum {
-+ UBIFS_COMPR_NONE,
-+ UBIFS_COMPR_LZO,
-+ UBIFS_COMPR_ZLIB,
-+ UBIFS_COMPR_TYPES_CNT,
-+};
-+
-+/*
-+ * UBIFS node types.
-+ *
-+ * UBIFS_INO_NODE: inode node
-+ * UBIFS_DATA_NODE: data node
-+ * UBIFS_DENT_NODE: directory entry node
-+ * UBIFS_XENT_NODE: extended attribute node
-+ * UBIFS_TRUN_NODE: truncation node
-+ * UBIFS_PAD_NODE: padding node
-+ * UBIFS_SB_NODE: superblock node
-+ * UBIFS_MST_NODE: master node
-+ * UBIFS_REF_NODE: LEB reference node
-+ * UBIFS_IDX_NODE: index node
-+ * UBIFS_CS_NODE: commit start node
-+ * UBIFS_ORPH_NODE: orphan node
-+ * UBIFS_NODE_TYPES_CNT: count of supported node types
-+ *
-+ * Note, we index arrays by these numbers, so keep them low and contiguous.
-+ * Node type constants for inodes, direntries and so on have to be the same as
-+ * corresponding key type constants.
-+ */
-+enum {
-+ UBIFS_INO_NODE,
-+ UBIFS_DATA_NODE,
-+ UBIFS_DENT_NODE,
-+ UBIFS_XENT_NODE,
-+ UBIFS_TRUN_NODE,
-+ UBIFS_PAD_NODE,
-+ UBIFS_SB_NODE,
-+ UBIFS_MST_NODE,
-+ UBIFS_REF_NODE,
-+ UBIFS_IDX_NODE,
-+ UBIFS_CS_NODE,
-+ UBIFS_ORPH_NODE,
-+ UBIFS_NODE_TYPES_CNT,
-+};
-+
-+/*
-+ * Master node flags.
-+ *
-+ * UBIFS_MST_DIRTY: rebooted uncleanly - master node is dirty
-+ * UBIFS_MST_NO_ORPHS: no orphan inodes present
-+ * UBIFS_MST_RCVRY: written by recovery
-+ */
-+enum {
-+ UBIFS_MST_DIRTY = 1,
-+ UBIFS_MST_NO_ORPHS = 2,
-+ UBIFS_MST_RCVRY = 4,
-+};
-+
-+/*
-+ * Node group type (used by recovery to recover whole group or none).
-+ *
-+ * UBIFS_NO_NODE_GROUP: this node is not part of a group
-+ * UBIFS_IN_NODE_GROUP: this node is a part of a group
-+ * UBIFS_LAST_OF_NODE_GROUP: this node is the last in a group
-+ */
-+enum {
-+ UBIFS_NO_NODE_GROUP = 0,
-+ UBIFS_IN_NODE_GROUP,
-+ UBIFS_LAST_OF_NODE_GROUP,
-+};
-+
-+/*
-+ * Superblock flags.
-+ *
-+ * UBIFS_FLG_BIGLPT: if "big" LPT model is used if set
-+ */
-+enum {
-+ UBIFS_FLG_BIGLPT = 0x02,
-+};
-+
-+/**
-+ * struct ubifs_ch - common header node.
-+ * @magic: UBIFS node magic number (%UBIFS_NODE_MAGIC)
-+ * @crc: CRC-32 checksum of the node header
-+ * @sqnum: sequence number
-+ * @len: full node length
-+ * @node_type: node type
-+ * @group_type: node group type
-+ * @padding: reserved for future, zeroes
-+ *
-+ * Every UBIFS node starts with this common part. If the node has a key, the
-+ * key always goes next.
-+ */
-+struct ubifs_ch {
-+ __le32 magic;
-+ __le32 crc;
-+ __le64 sqnum;
-+ __le32 len;
-+ __u8 node_type;
-+ __u8 group_type;
-+ __u8 padding[2];
-+} __attribute__ ((packed));
-+
-+/**
-+ * union ubifs_dev_desc - device node descriptor.
-+ * @new: new type device descriptor
-+ * @huge: huge type device descriptor
-+ *
-+ * This data structure describes major/minor numbers of a device node. In an
-+ * inode is a device node then its data contains an object of this type. UBIFS
-+ * uses standard Linux "new" and "huge" device node encodings.
-+ */
-+union ubifs_dev_desc {
-+ __le32 new;
-+ __le64 huge;
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_ino_node - inode node.
-+ * @ch: common header
-+ * @key: node key
-+ * @creat_sqnum: sequence number at time of creation
-+ * @size: inode size in bytes (amount of uncompressed data)
-+ * @atime_sec: access time seconds
-+ * @ctime_sec: creation time seconds
-+ * @mtime_sec: modification time seconds
-+ * @atime_nsec: access time nanoseconds
-+ * @ctime_nsec: creation time nanoseconds
-+ * @mtime_nsec: modification time nanoseconds
-+ * @nlink: number of hard links
-+ * @uid: owner ID
-+ * @gid: group ID
-+ * @mode: access flags
-+ * @flags: per-inode flags (%UBIFS_COMPR_FL, %UBIFS_SYNC_FL, etc)
-+ * @data_len: inode data length
-+ * @xattr_cnt: count of extended attributes this inode has
-+ * @xattr_size: summarized size of all extended attributes in bytes
-+ * @xattr_names: sum of lengths of all extended attribute names belonging to
-+ * this inode
-+ * @compr_type: compression type used for this inode
-+ * @padding: reserved for future, zeroes
-+ * @data: data attached to the inode
-+ *
-+ * Note, even though inode compression type is defined by @compr_type, some
-+ * nodes of this inode may be compressed with different compressor - this
-+ * happens if compression type is changed while the inode already has data
-+ * nodes. But @compr_type will be use for further writes to the inode.
-+ *
-+ * Note, do not forget to amend 'zero_ino_node_unused()' function when changing
-+ * the padding fields.
-+ */
-+struct ubifs_ino_node {
-+ struct ubifs_ch ch;
-+ __u8 key[UBIFS_MAX_KEY_LEN];
-+ __le64 creat_sqnum;
-+ __le64 size;
-+ __le64 atime_sec;
-+ __le64 ctime_sec;
-+ __le64 mtime_sec;
-+ __le32 atime_nsec;
-+ __le32 ctime_nsec;
-+ __le32 mtime_nsec;
-+ __le32 nlink;
-+ __le32 uid;
-+ __le32 gid;
-+ __le32 mode;
-+ __le32 flags;
-+ __le32 data_len;
-+ __le32 xattr_cnt;
-+ __le64 xattr_size;
-+ __le32 xattr_names;
-+ __le16 compr_type;
-+ __u8 padding[26]; /* Watch 'zero_ino_node_unused()' if changing! */
-+ __u8 data[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_dent_node - directory entry node.
-+ * @ch: common header
-+ * @key: node key
-+ * @inum: target inode number
-+ * @padding1: reserved for future, zeroes
-+ * @type: type of the target inode (%UBIFS_ITYPE_REG, %UBIFS_ITYPE_DIR, etc)
-+ * @nlen: name length
-+ * @padding2: reserved for future, zeroes
-+ * @name: zero-terminated name
-+ *
-+ * Note, do not forget to amend 'zero_dent_node_unused()' function when
-+ * changing the padding fields.
-+ */
-+struct ubifs_dent_node {
-+ struct ubifs_ch ch;
-+ __u8 key[UBIFS_MAX_KEY_LEN];
-+ __le64 inum;
-+ __u8 padding1;
-+ __u8 type;
-+ __le16 nlen;
-+ __u8 padding2[4]; /* Watch 'zero_dent_node_unused()' if changing! */
-+ __u8 name[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_data_node - data node.
-+ * @ch: common header
-+ * @key: node key
-+ * @size: uncompressed data size in bytes
-+ * @compr_type: compression type (%UBIFS_COMPR_NONE, %UBIFS_COMPR_LZO, etc)
-+ * @padding: reserved for future, zeroes
-+ * @data: data
-+ *
-+ * Note, do not forget to amend 'zero_data_node_unused()' function when
-+ * changing the padding fields.
-+ */
-+struct ubifs_data_node {
-+ struct ubifs_ch ch;
-+ __u8 key[UBIFS_MAX_KEY_LEN];
-+ __le32 size;
-+ __le16 compr_type;
-+ __u8 padding[2]; /* Watch 'zero_data_node_unused()' if changing! */
-+ __u8 data[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_trun_node - truncation node.
-+ * @ch: common header
-+ * @key: truncation node key
-+ * @old_size: size before truncation
-+ * @new_size: size after truncation
-+ *
-+ * This node exists only in the journal and never goes to the main area.
-+ */
-+struct ubifs_trun_node {
-+ struct ubifs_ch ch;
-+ __u8 key[UBIFS_MAX_KEY_LEN];
-+ __le64 old_size;
-+ __le64 new_size;
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_pad_node - padding node.
-+ * @ch: common header
-+ * @pad_len: how many bytes after this node are unused (because padded)
-+ * @padding: reserved for future, zeroes
-+ */
-+struct ubifs_pad_node {
-+ struct ubifs_ch ch;
-+ __le32 pad_len;
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_sb_node - superblock node.
-+ * @ch: common header
-+ * @padding: reserved for future, zeroes
-+ * @key_hash: type of hash function used in keys
-+ * @key_fmt: format of the key
-+ * @flags: file-system flags (%UBIFS_FLG_BIGLPT, etc)
-+ * @min_io_size: minimal input/output unit size
-+ * @leb_size: logical eraseblock size in bytes
-+ * @leb_cnt: count of LEBs used by filesystem
-+ * @max_leb_cnt: maximum count of LEBs used by filesystem
-+ * @max_bud_bytes: maximum amount of data stored in buds
-+ * @log_lebs: log size in logical eraseblocks
-+ * @lpt_lebs: number of LEBs used for lprops table
-+ * @orph_lebs: number of LEBs used for recording orphans
-+ * @jhead_cnt: count of journal heads
-+ * @fanout: tree fanout (max. number of links per indexing node)
-+ * @lsave_cnt: number of LEB numbers in LPT's save table
-+ * @fmt_version: UBIFS on-flash format version
-+ * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc)
-+ * @padding1: reserved for future, zeroes
-+ * @rp_uid: reserve pool UID
-+ * @rp_gid: reserve pool GID
-+ * @rp_size: size of the reserved pool in bytes
-+ * @padding2: reserved for future, zeroes
-+ * @time_gran: time granularity in nanoseconds
-+ */
-+struct ubifs_sb_node {
-+ struct ubifs_ch ch;
-+ __u8 padding[2];
-+ __u8 key_hash;
-+ __u8 key_fmt;
-+ __le32 flags;
-+ __le32 min_io_size;
-+ __le32 leb_size;
-+ __le32 leb_cnt;
-+ __le32 max_leb_cnt;
-+ __le64 max_bud_bytes;
-+ __le32 log_lebs;
-+ __le32 lpt_lebs;
-+ __le32 orph_lebs;
-+ __le32 jhead_cnt;
-+ __le32 fanout;
-+ __le32 lsave_cnt;
-+ __le32 fmt_version;
-+ __le16 default_compr;
-+ __u8 padding1[2];
-+ __le32 rp_uid;
-+ __le32 rp_gid;
-+ __le64 rp_size;
-+ __le32 time_gran;
-+ __u8 padding2[3988];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_mst_node - master node.
-+ * @ch: common header
-+ * @highest_inum: highest inode number in the committed index
-+ * @cmt_no: commit number
-+ * @flags: various flags (%UBIFS_MST_DIRTY, etc)
-+ * @log_lnum: start of the log
-+ * @root_lnum: LEB number of the root indexing node
-+ * @root_offs: offset within @root_lnum
-+ * @root_len: root indexing node length
-+ * @gc_lnum: LEB reserved for garbage collection (%-1 value means the LEB was
-+ * not reserved and should be reserved on mount)
-+ * @ihead_lnum: LEB number of index head
-+ * @ihead_offs: offset of index head
-+ * @index_size: size of index on flash
-+ * @total_free: total free space in bytes
-+ * @total_dirty: total dirty space in bytes
-+ * @total_used: total used space in bytes (includes only data LEBs)
-+ * @total_dead: total dead space in bytes (includes only data LEBs)
-+ * @total_dark: total dark space in bytes (includes only data LEBs)
-+ * @lpt_lnum: LEB number of LPT root nnode
-+ * @lpt_offs: offset of LPT root nnode
-+ * @nhead_lnum: LEB number of LPT head
-+ * @nhead_offs: offset of LPT head
-+ * @ltab_lnum: LEB number of LPT's own lprops table
-+ * @ltab_offs: offset of LPT's own lprops table
-+ * @lsave_lnum: LEB number of LPT's save table (big model only)
-+ * @lsave_offs: offset of LPT's save table (big model only)
-+ * @lscan_lnum: LEB number of last LPT scan
-+ * @empty_lebs: number of empty logical eraseblocks
-+ * @idx_lebs: number of indexing logical eraseblocks
-+ * @leb_cnt: count of LEBs used by filesystem
-+ * @padding: reserved for future, zeroes
-+ */
-+struct ubifs_mst_node {
-+ struct ubifs_ch ch;
-+ __le64 highest_inum;
-+ __le64 cmt_no;
-+ __le32 flags;
-+ __le32 log_lnum;
-+ __le32 root_lnum;
-+ __le32 root_offs;
-+ __le32 root_len;
-+ __le32 gc_lnum;
-+ __le32 ihead_lnum;
-+ __le32 ihead_offs;
-+ __le64 index_size;
-+ __le64 total_free;
-+ __le64 total_dirty;
-+ __le64 total_used;
-+ __le64 total_dead;
-+ __le64 total_dark;
-+ __le32 lpt_lnum;
-+ __le32 lpt_offs;
-+ __le32 nhead_lnum;
-+ __le32 nhead_offs;
-+ __le32 ltab_lnum;
-+ __le32 ltab_offs;
-+ __le32 lsave_lnum;
-+ __le32 lsave_offs;
-+ __le32 lscan_lnum;
-+ __le32 empty_lebs;
-+ __le32 idx_lebs;
-+ __le32 leb_cnt;
-+ __u8 padding[344];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_ref_node - logical eraseblock reference node.
-+ * @ch: common header
-+ * @lnum: the referred logical eraseblock number
-+ * @offs: start offset in the referred LEB
-+ * @jhead: journal head number
-+ * @padding: reserved for future, zeroes
-+ */
-+struct ubifs_ref_node {
-+ struct ubifs_ch ch;
-+ __le32 lnum;
-+ __le32 offs;
-+ __le32 jhead;
-+ __u8 padding[28];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_branch - key/reference/length branch
-+ * @lnum: LEB number of the target node
-+ * @offs: offset within @lnum
-+ * @len: target node length
-+ * @key: key
-+ */
-+struct ubifs_branch {
-+ __le32 lnum;
-+ __le32 offs;
-+ __le32 len;
-+ __u8 key[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_idx_node - indexing node.
-+ * @ch: common header
-+ * @child_cnt: number of child index nodes
-+ * @level: tree level
-+ * @branches: LEB number / offset / length / key branches
-+ */
-+struct ubifs_idx_node {
-+ struct ubifs_ch ch;
-+ __le16 child_cnt;
-+ __le16 level;
-+ __u8 branches[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_cs_node - commit start node.
-+ * @ch: common header
-+ * @cmt_no: commit number
-+ */
-+struct ubifs_cs_node {
-+ struct ubifs_ch ch;
-+ __le64 cmt_no;
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_orph_node - orphan node.
-+ * @ch: common header
-+ * @cmt_no: commit number (also top bit is set on the last node of the commit)
-+ * @inos: inode numbers of orphans
-+ */
-+struct ubifs_orph_node {
-+ struct ubifs_ch ch;
-+ __le64 cmt_no;
-+ __le64 inos[];
-+} __attribute__ ((packed));
-+
-+#endif /* __UBIFS_MEDIA_H__ */
---- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/ubifs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/ubifs.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,424 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2008 Nokia Corporation.
-+ * Copyright (C) 2008 University of Szeged, Hungary
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy
-+ * Adrian Hunter
-+ * Zoltan Sogor
-+ */
-+
-+#ifndef __UBIFS_H__
-+#define __UBIFS_H__
-+
-+/* Minimum amount of data UBIFS writes to the flash */
-+#define MIN_WRITE_SZ (UBIFS_DATA_NODE_SZ + 8)
-+
-+/* Largest key size supported in this implementation */
-+#define CUR_MAX_KEY_LEN UBIFS_SK_LEN
-+
-+/* The below union makes it easier to deal with keys */
-+union ubifs_key
-+{
-+ uint8_t u8[CUR_MAX_KEY_LEN];
-+ uint32_t u32[CUR_MAX_KEY_LEN/4];
-+ uint64_t u64[CUR_MAX_KEY_LEN/8];
-+ __le32 j32[CUR_MAX_KEY_LEN/4];
-+};
-+
-+/*
-+ * LEB properties flags.
-+ *
-+ * LPROPS_UNCAT: not categorized
-+ * LPROPS_DIRTY: dirty > 0, not index
-+ * LPROPS_DIRTY_IDX: dirty + free > UBIFS_CH_SZ and index
-+ * LPROPS_FREE: free > 0, not empty, not index
-+ * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs
-+ * LPROPS_EMPTY: LEB is empty, not taken
-+ * LPROPS_FREEABLE: free + dirty == leb_size, not index, not taken
-+ * LPROPS_FRDI_IDX: free + dirty == leb_size and index, may be taken
-+ * LPROPS_CAT_MASK: mask for the LEB categories above
-+ * LPROPS_TAKEN: LEB was taken (this flag is not saved on the media)
-+ * LPROPS_INDEX: LEB contains indexing nodes (this flag also exists on flash)
-+ */
-+enum {
-+ LPROPS_UNCAT = 0,
-+ LPROPS_DIRTY = 1,
-+ LPROPS_DIRTY_IDX = 2,
-+ LPROPS_FREE = 3,
-+ LPROPS_HEAP_CNT = 3,
-+ LPROPS_EMPTY = 4,
-+ LPROPS_FREEABLE = 5,
-+ LPROPS_FRDI_IDX = 6,
-+ LPROPS_CAT_MASK = 15,
-+ LPROPS_TAKEN = 16,
-+ LPROPS_INDEX = 32,
-+};
-+
-+/**
-+ * struct ubifs_lprops - logical eraseblock properties.
-+ * @free: amount of free space in bytes
-+ * @dirty: amount of dirty space in bytes
-+ * @flags: LEB properties flags (see above)
-+ */
-+struct ubifs_lprops
-+{
-+ int free;
-+ int dirty;
-+ int flags;
-+};
-+
-+/**
-+ * struct ubifs_lpt_lprops - LPT logical eraseblock properties.
-+ * @free: amount of free space in bytes
-+ * @dirty: amount of dirty space in bytes
-+ */
-+struct ubifs_lpt_lprops
-+{
-+ int free;
-+ int dirty;
-+};
-+
-+struct ubifs_nnode;
-+
-+/**
-+ * struct ubifs_cnode - LEB Properties Tree common node.
-+ * @parent: parent nnode
-+ * @cnext: next cnode to commit
-+ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
-+ * @iip: index in parent
-+ * @level: level in the tree (zero for pnodes, greater than zero for nnodes)
-+ * @num: node number
-+ */
-+struct ubifs_cnode
-+{
-+ struct ubifs_nnode *parent;
-+ struct ubifs_cnode *cnext;
-+ unsigned long flags;
-+ int iip;
-+ int level;
-+ int num;
-+};
-+
-+/**
-+ * struct ubifs_pnode - LEB Properties Tree leaf node.
-+ * @parent: parent nnode
-+ * @cnext: next cnode to commit
-+ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
-+ * @iip: index in parent
-+ * @level: level in the tree (always zero for pnodes)
-+ * @num: node number
-+ * @lprops: LEB properties array
-+ */
-+struct ubifs_pnode
-+{
-+ struct ubifs_nnode *parent;
-+ struct ubifs_cnode *cnext;
-+ unsigned long flags;
-+ int iip;
-+ int level;
-+ int num;
-+ struct ubifs_lprops lprops[UBIFS_LPT_FANOUT];
-+};
-+
-+/**
-+ * struct ubifs_nbranch - LEB Properties Tree internal node branch.
-+ * @lnum: LEB number of child
-+ * @offs: offset of child
-+ * @nnode: nnode child
-+ * @pnode: pnode child
-+ * @cnode: cnode child
-+ */
-+struct ubifs_nbranch
-+{
-+ int lnum;
-+ int offs;
-+ union
-+ {
-+ struct ubifs_nnode *nnode;
-+ struct ubifs_pnode *pnode;
-+ struct ubifs_cnode *cnode;
-+ };
-+};
-+
-+/**
-+ * struct ubifs_nnode - LEB Properties Tree internal node.
-+ * @parent: parent nnode
-+ * @cnext: next cnode to commit
-+ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
-+ * @iip: index in parent
-+ * @level: level in the tree (always greater than zero for nnodes)
-+ * @num: node number
-+ * @nbranch: branches to child nodes
-+ */
-+struct ubifs_nnode
-+{
-+ struct ubifs_nnode *parent;
-+ struct ubifs_cnode *cnext;
-+ unsigned long flags;
-+ int iip;
-+ int level;
-+ int num;
-+ struct ubifs_nbranch nbranch[UBIFS_LPT_FANOUT];
-+};
-+
-+/**
-+ * struct ubifs_lp_stats - statistics of eraseblocks in the main area.
-+ * @empty_lebs: number of empty LEBs
-+ * @taken_empty_lebs: number of taken LEBs
-+ * @idx_lebs: number of indexing LEBs
-+ * @total_free: total free space in bytes
-+ * @total_dirty: total dirty space in bytes
-+ * @total_used: total used space in bytes (includes only data LEBs)
-+ * @total_dead: total dead space in bytes (includes only data LEBs)
-+ * @total_dark: total dark space in bytes (includes only data LEBs)
-+ */
-+struct ubifs_lp_stats {
-+ int empty_lebs;
-+ int taken_empty_lebs;
-+ int idx_lebs;
-+ long long total_free;
-+ long long total_dirty;
-+ long long total_used;
-+ long long total_dead;
-+ long long total_dark;
-+};
-+
-+/**
-+ * struct ubifs_zbranch - key/coordinate/length branch stored in znodes.
-+ * @key: key
-+ * @znode: znode address in memory
-+ * @lnum: LEB number of the indexing node
-+ * @offs: offset of the indexing node within @lnum
-+ * @len: target node length
-+ */
-+struct ubifs_zbranch
-+{
-+ union ubifs_key key;
-+ struct ubifs_znode *znode;
-+ int lnum;
-+ int offs;
-+ int len;
-+};
-+
-+/**
-+ * struct ubifs_znode - in-memory representation of an indexing node.
-+ * @parent: parent znode or NULL if it is the root
-+ * @cnext: next znode to commit
-+ * @flags: flags
-+ * @time: last access time (seconds)
-+ * @level: level of the entry in the TNC tree
-+ * @child_cnt: count of child znodes
-+ * @iip: index in parent's zbranch array
-+ * @alt: lower bound of key range has altered i.e. child inserted at slot 0
-+ * @zbranch: array of znode branches (@c->fanout elements)
-+ */
-+struct ubifs_znode
-+{
-+ struct ubifs_znode *parent;
-+ struct ubifs_znode *cnext;
-+ unsigned long flags;
-+ unsigned long time;
-+ int level;
-+ int child_cnt;
-+ int iip;
-+ int alt;
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ int lnum, offs, len;
-+#endif
-+ struct ubifs_zbranch zbranch[];
-+};
-+
-+/**
-+ * struct ubifs_info - UBIFS file-system description data structure
-+ * (per-superblock).
-+ *
-+ * @highest_inum: highest used inode number
-+ * @max_sqnum: current global sequence number
-+ *
-+ * @jhead_cnt: count of journal heads
-+ * @max_bud_bytes: maximum number of bytes allowed in buds
-+ *
-+ * @zroot: zbranch which points to the root index node and znode
-+ * @ihead_lnum: LEB number of index head
-+ * @ihead_offs: offset of index head
-+ *
-+ * @log_lebs: number of logical eraseblocks in the log
-+ * @lpt_lebs: number of LEBs used for lprops table
-+ * @lpt_first: first LEB of the lprops table area
-+ * @lpt_last: last LEB of the lprops table area
-+ * @main_lebs: count of LEBs in the main area
-+ * @main_first: first LEB of the main area
-+ * @default_compr: default compression type
-+ *
-+ * @key_hash_type: type of the key hash
-+ * @key_hash: direntry key hash function
-+ * @key_len: key length
-+ * @fanout: fanout of the index tree (number of links per indexing node)
-+ *
-+ * @min_io_size: minimal input/output unit size
-+ * @leb_size: logical eraseblock size in bytes
-+ * @leb_cnt: count of logical eraseblocks
-+ * @max_leb_cnt: maximum count of logical eraseblocks
-+ *
-+ * @old_idx_sz: size of index on flash
-+ * @lst: lprops statistics
-+ *
-+ * @dead_wm: LEB dead space watermark
-+ * @dark_wm: LEB dark space watermark
-+ *
-+ * @gc_lnum: LEB number used for garbage collection
-+ * @space_bits: number of bits needed to record free or dirty space
-+ * @lpt_lnum_bits: number of bits needed to record a LEB number in the LPT
-+ * @lpt_offs_bits: number of bits needed to record an offset in the LPT
-+ * @lpt_spc_bits: number of bits needed to space in the LPT
-+ * @pcnt_bits: number of bits needed to record pnode or nnode number
-+ * @lnum_bits: number of bits needed to record LEB number
-+ * @nnode_sz: size of on-flash nnode
-+ * @pnode_sz: size of on-flash pnode
-+ * @ltab_sz: size of on-flash LPT lprops table
-+ * @lsave_sz: size of on-flash LPT save table
-+ * @pnode_cnt: number of pnodes
-+ * @nnode_cnt: number of nnodes
-+ * @lpt_hght: height of the LPT
-+ *
-+ * @lpt_lnum: LEB number of the root nnode of the LPT
-+ * @lpt_offs: offset of the root nnode of the LPT
-+ * @nhead_lnum: LEB number of LPT head
-+ * @nhead_offs: offset of LPT head
-+ * @big_lpt: flag that LPT is too big to write whole during commit
-+ * @lpt_sz: LPT size
-+ *
-+ * @ltab_lnum: LEB number of LPT's own lprops table
-+ * @ltab_offs: offset of LPT's own lprops table
-+ * @lpt: lprops table
-+ * @ltab: LPT's own lprops table
-+ * @lsave_cnt: number of LEB numbers in LPT's save table
-+ * @lsave_lnum: LEB number of LPT's save table
-+ * @lsave_offs: offset of LPT's save table
-+ * @lsave: LPT's save table
-+ * @lscan_lnum: LEB number of last LPT scan
-+ */
-+struct ubifs_info
-+{
-+ ino_t highest_inum;
-+ unsigned long long max_sqnum;
-+
-+ int jhead_cnt;
-+ long long max_bud_bytes;
-+
-+ struct ubifs_zbranch zroot;
-+ int ihead_lnum;
-+ int ihead_offs;
-+
-+ int log_lebs;
-+ int lpt_lebs;
-+ int lpt_first;
-+ int lpt_last;
-+ int orph_lebs;
-+ int main_lebs;
-+ int main_first;
-+ int default_compr;
-+
-+ uint8_t key_hash_type;
-+ uint32_t (*key_hash)(const char *str, int len);
-+ int key_len;
-+ int fanout;
-+
-+ int min_io_size;
-+ int leb_size;
-+ int leb_cnt;
-+ int max_leb_cnt;
-+
-+ unsigned long long old_idx_sz;
-+ struct ubifs_lp_stats lst;
-+
-+ int dead_wm;
-+ int dark_wm;
-+
-+ int gc_lnum;
-+
-+ int space_bits;
-+ int lpt_lnum_bits;
-+ int lpt_offs_bits;
-+ int lpt_spc_bits;
-+ int pcnt_bits;
-+ int lnum_bits;
-+ int nnode_sz;
-+ int pnode_sz;
-+ int ltab_sz;
-+ int lsave_sz;
-+ int pnode_cnt;
-+ int nnode_cnt;
-+ int lpt_hght;
-+
-+ int lpt_lnum;
-+ int lpt_offs;
-+ int nhead_lnum;
-+ int nhead_offs;
-+ int big_lpt;
-+ long long lpt_sz;
-+
-+ int ltab_lnum;
-+ int ltab_offs;
-+ struct ubifs_lprops *lpt;
-+ struct ubifs_lpt_lprops *ltab;
-+ int lsave_cnt;
-+ int lsave_lnum;
-+ int lsave_offs;
-+ int *lsave;
-+ int lscan_lnum;
-+
-+};
-+
-+/**
-+ * ubifs_idx_node_sz - return index node size.
-+ * @c: the UBIFS file-system description object
-+ * @child_cnt: number of children of this index node
-+ */
-+static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt)
-+{
-+ return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt;
-+}
-+
-+/**
-+ * ubifs_idx_branch - return pointer to an index branch.
-+ * @c: the UBIFS file-system description object
-+ * @idx: index node
-+ * @bnum: branch number
-+ */
-+static inline
-+struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c,
-+ const struct ubifs_idx_node *idx,
-+ int bnum)
-+{
-+ return (struct ubifs_branch *)((void *)idx->branches +
-+ (UBIFS_BRANCH_SZ + c->key_len) * bnum);
-+}
-+
-+/**
-+ * ubifs_idx_key - return pointer to an index key.
-+ * @c: the UBIFS file-system description object
-+ * @idx: index node
-+ */
-+static inline void *ubifs_idx_key(const struct ubifs_info *c,
-+ const struct ubifs_idx_node *idx)
-+{
-+ return (void *)((struct ubifs_branch *)idx->branches)->key;
-+}
-+
-+#endif /* __UBIFS_H__ */
---- linux-2.6.24.7.old/fs/ubifs/orphan.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/orphan.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,959 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Author: Adrian Hunter
-+ */
-+
-+#include "ubifs.h"
-+
-+/*
-+ * An orphan is an inode number whose inode node has been committed to the index
-+ * with a link count of zero. That happens when an open file is deleted
-+ * (unlinked) and then a commit is run. In the normal course of events the inode
-+ * would be deleted when the file is closed. However in the case of an unclean
-+ * unmount, orphans need to be accounted for. After an unclean unmount, the
-+ * orphans' inodes must be deleted which means either scanning the entire index
-+ * looking for them, or keeping a list on flash somewhere. This unit implements
-+ * the latter approach.
-+ *
-+ * The orphan area is a fixed number of LEBs situated between the LPT area and
-+ * the main area. The number of orphan area LEBs is specified when the file
-+ * system is created. The minimum number is 1. The size of the orphan area
-+ * should be so that it can hold the maximum number of orphans that are expected
-+ * to ever exist at one time.
-+ *
-+ * The number of orphans that can fit in a LEB is:
-+ *
-+ * (c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64)
-+ *
-+ * For example: a 15872 byte LEB can fit 1980 orphans so 1 LEB may be enough.
-+ *
-+ * Orphans are accumulated in a rb-tree. When an inode's link count drops to
-+ * zero, the inode number is added to the rb-tree. It is removed from the tree
-+ * when the inode is deleted. Any new orphans that are in the orphan tree when
-+ * the commit is run, are written to the orphan area in 1 or more orph nodes.
-+ * If the orphan area is full, it is consolidated to make space. There is
-+ * always enough space because validation prevents the user from creating more
-+ * than the maximum number of orphans allowed.
-+ */
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+static int dbg_check_orphans(struct ubifs_info *c);
-+#else
-+#define dbg_check_orphans(c) 0
-+#endif
-+
-+/**
-+ * ubifs_add_orphan - add an orphan.
-+ * @c: UBIFS file-system description object
-+ * @inum: orphan inode number
-+ *
-+ * Add an orphan. This function is called when an inodes link count drops to
-+ * zero.
-+ */
-+int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
-+{
-+ struct ubifs_orphan *orphan, *o;
-+ struct rb_node **p, *parent = NULL;
-+
-+ orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_NOFS);
-+ if (!orphan)
-+ return -ENOMEM;
-+ orphan->inum = inum;
-+ orphan->new = 1;
-+
-+ spin_lock(&c->orphan_lock);
-+ if (c->tot_orphans >= c->max_orphans) {
-+ spin_unlock(&c->orphan_lock);
-+ kfree(orphan);
-+ return -ENFILE;
-+ }
-+ p = &c->orph_tree.rb_node;
-+ while (*p) {
-+ parent = *p;
-+ o = rb_entry(parent, struct ubifs_orphan, rb);
-+ if (inum < o->inum)
-+ p = &(*p)->rb_left;
-+ else if (inum > o->inum)
-+ p = &(*p)->rb_right;
-+ else {
-+ dbg_err("orphaned twice");
-+ spin_unlock(&c->orphan_lock);
-+ kfree(orphan);
-+ return 0;
-+ }
-+ }
-+ c->tot_orphans += 1;
-+ c->new_orphans += 1;
-+ rb_link_node(&orphan->rb, parent, p);
-+ rb_insert_color(&orphan->rb, &c->orph_tree);
-+ list_add_tail(&orphan->list, &c->orph_list);
-+ list_add_tail(&orphan->new_list, &c->orph_new);
-+ spin_unlock(&c->orphan_lock);
-+ dbg_gen("ino %lu", inum);
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_delete_orphan - delete an orphan.
-+ * @c: UBIFS file-system description object
-+ * @inum: orphan inode number
-+ *
-+ * Delete an orphan. This function is called when an inode is deleted.
-+ */
-+void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
-+{
-+ struct ubifs_orphan *o;
-+ struct rb_node *p;
-+
-+ spin_lock(&c->orphan_lock);
-+ p = c->orph_tree.rb_node;
-+ while (p) {
-+ o = rb_entry(p, struct ubifs_orphan, rb);
-+ if (inum < o->inum)
-+ p = p->rb_left;
-+ else if (inum > o->inum)
-+ p = p->rb_right;
-+ else {
-+ if (o->dnext) {
-+ spin_unlock(&c->orphan_lock);
-+ dbg_gen("deleted twice ino %lu", inum);
-+ return;
-+ }
-+ if (o->cnext) {
-+ o->dnext = c->orph_dnext;
-+ c->orph_dnext = o;
-+ spin_unlock(&c->orphan_lock);
-+ dbg_gen("delete later ino %lu", inum);
-+ return;
-+ }
-+ rb_erase(p, &c->orph_tree);
-+ list_del(&o->list);
-+ c->tot_orphans -= 1;
-+ if (o->new) {
-+ list_del(&o->new_list);
-+ c->new_orphans -= 1;
-+ }
-+ spin_unlock(&c->orphan_lock);
-+ kfree(o);
-+ dbg_gen("inum %lu", inum);
-+ return;
-+ }
-+ }
-+ spin_unlock(&c->orphan_lock);
-+ dbg_err("missing orphan ino %lu", inum);
-+ dbg_dump_stack();
-+}
-+
-+/**
-+ * ubifs_orphan_start_commit - start commit of orphans.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Start commit of orphans.
-+ */
-+int ubifs_orphan_start_commit(struct ubifs_info *c)
-+{
-+ struct ubifs_orphan *orphan, **last;
-+
-+ spin_lock(&c->orphan_lock);
-+ last = &c->orph_cnext;
-+ list_for_each_entry(orphan, &c->orph_new, new_list) {
-+ ubifs_assert(orphan->new);
-+ orphan->new = 0;
-+ *last = orphan;
-+ last = &orphan->cnext;
-+ }
-+ *last = orphan->cnext;
-+ c->cmt_orphans = c->new_orphans;
-+ c->new_orphans = 0;
-+ dbg_cmt("%d orphans to commit", c->cmt_orphans);
-+ INIT_LIST_HEAD(&c->orph_new);
-+ if (c->tot_orphans == 0)
-+ c->no_orphs = 1;
-+ else
-+ c->no_orphs = 0;
-+ spin_unlock(&c->orphan_lock);
-+ return 0;
-+}
-+
-+/**
-+ * avail_orphs - calculate available space.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns the number of orphans that can be written in the
-+ * available space.
-+ */
-+static int avail_orphs(struct ubifs_info *c)
-+{
-+ int avail_lebs, avail, gap;
-+
-+ avail_lebs = c->orph_lebs - (c->ohead_lnum - c->orph_first) - 1;
-+ avail = avail_lebs *
-+ ((c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64));
-+ gap = c->leb_size - c->ohead_offs;
-+ if (gap >= UBIFS_ORPH_NODE_SZ + sizeof(__le64))
-+ avail += (gap - UBIFS_ORPH_NODE_SZ) / sizeof(__le64);
-+ return avail;
-+}
-+
-+/**
-+ * tot_avail_orphs - calculate total space.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns the number of orphans that can be written in half
-+ * the total space. That leaves half the space for adding new orphans.
-+ */
-+static int tot_avail_orphs(struct ubifs_info *c)
-+{
-+ int avail_lebs, avail;
-+
-+ avail_lebs = c->orph_lebs;
-+ avail = avail_lebs *
-+ ((c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64));
-+ return avail / 2;
-+}
-+
-+/**
-+ * do_write_orph_node - write a node
-+ * @c: UBIFS file-system description object
-+ * @len: length of node
-+ * @atomic: write atomically
-+ *
-+ * This function writes a node to the orphan head from the orphan buffer. If
-+ * %atomic is not zero, then the write is done atomically. On success, %0 is
-+ * returned, otherwise a negative error code is returned.
-+ */
-+static int do_write_orph_node(struct ubifs_info *c, int len, int atomic)
-+{
-+ int err = 0;
-+
-+ if (atomic) {
-+ ubifs_assert(c->ohead_offs == 0);
-+ ubifs_prepare_node(c, c->orph_buf, len, 1);
-+ len = ALIGN(len, c->min_io_size);
-+ err = ubi_leb_change(c->ubi, c->ohead_lnum, c->orph_buf, len,
-+ UBI_SHORTTERM);
-+ } else {
-+ if (c->ohead_offs == 0) {
-+ /* Ensure LEB has been unmapped */
-+ err = ubifs_leb_unmap(c, c->ohead_lnum);
-+ if (err)
-+ return err;
-+ }
-+ err = ubifs_write_node(c, c->orph_buf, len, c->ohead_lnum,
-+ c->ohead_offs, UBI_SHORTTERM);
-+ }
-+ return err;
-+}
-+
-+/**
-+ * write_orph_node - write an orph node
-+ * @c: UBIFS file-system description object
-+ * @atomic: write atomically
-+ *
-+ * This function builds an orph node from the cnext list and writes it to the
-+ * orphan head. On success, %0 is returned, otherwise a negative error code
-+ * is returned.
-+ */
-+static int write_orph_node(struct ubifs_info *c, int atomic)
-+{
-+ struct ubifs_orphan *orphan, *cnext;
-+ struct ubifs_orph_node *orph;
-+ int gap, err, len, cnt, i;
-+
-+ ubifs_assert(c->cmt_orphans > 0);
-+ gap = c->leb_size - c->ohead_offs;
-+ if (gap < UBIFS_ORPH_NODE_SZ + sizeof(__le64)) {
-+ c->ohead_lnum += 1;
-+ c->ohead_offs = 0;
-+ gap = c->leb_size;
-+ if (c->ohead_lnum > c->orph_last) {
-+ /*
-+ * We limit the number of orphans so that this should
-+ * never happen.
-+ */
-+ ubifs_err("out of space in orphan area");
-+ return -EINVAL;
-+ }
-+ }
-+ cnt = (gap - UBIFS_ORPH_NODE_SZ) / sizeof(__le64);
-+ if (cnt > c->cmt_orphans)
-+ cnt = c->cmt_orphans;
-+ len = UBIFS_ORPH_NODE_SZ + cnt * sizeof(__le64);
-+ ubifs_assert(c->orph_buf);
-+ orph = c->orph_buf;
-+ orph->ch.node_type = UBIFS_ORPH_NODE;
-+ spin_lock(&c->orphan_lock);
-+ cnext = c->orph_cnext;
-+ for (i = 0; i < cnt; i++) {
-+ orphan = cnext;
-+ orph->inos[i] = cpu_to_le64(orphan->inum);
-+ cnext = orphan->cnext;
-+ orphan->cnext = NULL;
-+ }
-+ c->orph_cnext = cnext;
-+ c->cmt_orphans -= cnt;
-+ spin_unlock(&c->orphan_lock);
-+ if (c->cmt_orphans)
-+ orph->cmt_no = cpu_to_le64(c->cmt_no + 1);
-+ else
-+ /* Mark the last node of the commit */
-+ orph->cmt_no = cpu_to_le64((c->cmt_no + 1) | (1ULL << 63));
-+ ubifs_assert(c->ohead_offs + len <= c->leb_size);
-+ ubifs_assert(c->ohead_lnum >= c->orph_first);
-+ ubifs_assert(c->ohead_lnum <= c->orph_last);
-+ err = do_write_orph_node(c, len, atomic);
-+ c->ohead_offs += ALIGN(len, c->min_io_size);
-+ c->ohead_offs = ALIGN(c->ohead_offs, 8);
-+ return err;
-+}
-+
-+/**
-+ * write_orph_nodes - write orph nodes until there are no more to commit
-+ * @c: UBIFS file-system description object
-+ * @atomic: write atomically
-+ *
-+ * This function writes orph nodes for all the orphans to commit. On success,
-+ * %0 is returned, otherwise a negative error code is returned.
-+ */
-+static int write_orph_nodes(struct ubifs_info *c, int atomic)
-+{
-+ int err;
-+
-+ while (c->cmt_orphans > 0) {
-+ err = write_orph_node(c, atomic);
-+ if (err)
-+ return err;
-+ }
-+ if (atomic) {
-+ int lnum;
-+
-+ /* Unmap any unused LEBs after consolidation */
-+ lnum = c->ohead_lnum + 1;
-+ for (lnum = c->ohead_lnum + 1; lnum <= c->orph_last; lnum++) {
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * consolidate - consolidate the orphan area.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function enables consolidation by putting all the orphans into the list
-+ * to commit. The list is in the order that the orphans were added, and the
-+ * LEBs are written atomically in order, so at no time can orphans be lost by
-+ * an unclean unmount.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int consolidate(struct ubifs_info *c)
-+{
-+ int tot_avail = tot_avail_orphs(c), err = 0;
-+
-+ spin_lock(&c->orphan_lock);
-+ dbg_cmt("there is space for %d orphans and there are %d",
-+ tot_avail, c->tot_orphans);
-+ if (c->tot_orphans - c->new_orphans <= tot_avail) {
-+ struct ubifs_orphan *orphan, **last;
-+ int cnt = 0;
-+
-+ /* Change the cnext list to include all non-new orphans */
-+ last = &c->orph_cnext;
-+ list_for_each_entry(orphan, &c->orph_list, list) {
-+ if (orphan->new)
-+ continue;
-+ *last = orphan;
-+ last = &orphan->cnext;
-+ cnt += 1;
-+ }
-+ *last = orphan->cnext;
-+ ubifs_assert(cnt == c->tot_orphans - c->new_orphans);
-+ c->cmt_orphans = cnt;
-+ c->ohead_lnum = c->orph_first;
-+ c->ohead_offs = 0;
-+ } else {
-+ /*
-+ * We limit the number of orphans so that this should
-+ * never happen.
-+ */
-+ ubifs_err("out of space in orphan area");
-+ err = -EINVAL;
-+ }
-+ spin_unlock(&c->orphan_lock);
-+ return err;
-+}
-+
-+/**
-+ * commit_orphans - commit orphans.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function commits orphans to flash. On success, %0 is returned,
-+ * otherwise a negative error code is returned.
-+ */
-+static int commit_orphans(struct ubifs_info *c)
-+{
-+ int avail, atomic = 0, err;
-+
-+ ubifs_assert(c->cmt_orphans > 0);
-+ avail = avail_orphs(c);
-+ if (avail < c->cmt_orphans) {
-+ /* Not enough space to write new orphans, so consolidate */
-+ err = consolidate(c);
-+ if (err)
-+ return err;
-+ atomic = 1;
-+ }
-+ err = write_orph_nodes(c, atomic);
-+ return err;
-+}
-+
-+/**
-+ * erase_deleted - erase the orphans marked for deletion.
-+ * @c: UBIFS file-system description object
-+ *
-+ * During commit, the orphans being committed cannot be deleted, so they are
-+ * marked for deletion and deleted by this function. Also, the recovery
-+ * adds killed orphans to the deletion list, and therefore they are deleted
-+ * here too.
-+ */
-+static void erase_deleted(struct ubifs_info *c)
-+{
-+ struct ubifs_orphan *orphan, *dnext;
-+
-+ spin_lock(&c->orphan_lock);
-+ dnext = c->orph_dnext;
-+ while (dnext) {
-+ orphan = dnext;
-+ dnext = orphan->dnext;
-+ ubifs_assert(!orphan->new);
-+ rb_erase(&orphan->rb, &c->orph_tree);
-+ list_del(&orphan->list);
-+ c->tot_orphans -= 1;
-+ dbg_gen("deleting orphan ino %lu", orphan->inum);
-+ kfree(orphan);
-+ }
-+ c->orph_dnext = NULL;
-+ spin_unlock(&c->orphan_lock);
-+}
-+
-+/**
-+ * ubifs_orphan_end_commit - end commit of orphans.
-+ * @c: UBIFS file-system description object
-+ *
-+ * End commit of orphans.
-+ */
-+int ubifs_orphan_end_commit(struct ubifs_info *c)
-+{
-+ int err;
-+
-+ if (c->cmt_orphans != 0) {
-+ err = commit_orphans(c);
-+ if (err)
-+ return err;
-+ }
-+ erase_deleted(c);
-+ err = dbg_check_orphans(c);
-+ return err;
-+}
-+
-+/**
-+ * clear_orphans - erase all LEBs used for orphans.
-+ * @c: UBIFS file-system description object
-+ *
-+ * If recovery is not required, then the orphans from the previous session
-+ * are not needed. This function locates the LEBs used to record
-+ * orphans, and un-maps them.
-+ */
-+static int clear_orphans(struct ubifs_info *c)
-+{
-+ int lnum, err;
-+
-+ for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ }
-+ c->ohead_lnum = c->orph_first;
-+ c->ohead_offs = 0;
-+ return 0;
-+}
-+
-+/**
-+ * insert_dead_orphan - insert an orphan.
-+ * @c: UBIFS file-system description object
-+ * @inum: orphan inode number
-+ *
-+ * This function is a helper to the 'do_kill_orphans()' function. The orphan
-+ * must be kept until the next commit, so it is added to the rb-tree and the
-+ * deletion list.
-+ */
-+static int insert_dead_orphan(struct ubifs_info *c, ino_t inum)
-+{
-+ struct ubifs_orphan *orphan, *o;
-+ struct rb_node **p, *parent = NULL;
-+
-+ orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_KERNEL);
-+ if (!orphan)
-+ return -ENOMEM;
-+ orphan->inum = inum;
-+
-+ p = &c->orph_tree.rb_node;
-+ while (*p) {
-+ parent = *p;
-+ o = rb_entry(parent, struct ubifs_orphan, rb);
-+ if (inum < o->inum)
-+ p = &(*p)->rb_left;
-+ else if (inum > o->inum)
-+ p = &(*p)->rb_right;
-+ else {
-+ /* Already added - no problem */
-+ kfree(orphan);
-+ return 0;
-+ }
-+ }
-+ c->tot_orphans += 1;
-+ rb_link_node(&orphan->rb, parent, p);
-+ rb_insert_color(&orphan->rb, &c->orph_tree);
-+ list_add_tail(&orphan->list, &c->orph_list);
-+ orphan->dnext = c->orph_dnext;
-+ c->orph_dnext = orphan;
-+ dbg_mnt("ino %lu, new %d, tot %d",
-+ inum, c->new_orphans, c->tot_orphans);
-+ return 0;
-+}
-+
-+/**
-+ * do_kill_orphans - remove orphan inodes from the index.
-+ * @c: UBIFS file-system description object
-+ * @sleb: scanned LEB
-+ * @last_cmt_no: cmt_no of last orph node read is passed and returned here
-+ * @outofdate: whether the LEB is out of date is returned here
-+ * @last_flagged: whether the end orph node is encountered
-+ *
-+ * This function is a helper to the 'kill_orphans()' function. It goes through
-+ * every orphan node in a LEB and for every inode number recorded, removes
-+ * all keys for that inode from the TNC.
-+ */
-+static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
-+ unsigned long long *last_cmt_no, int *outofdate,
-+ int *last_flagged)
-+{
-+ struct ubifs_scan_node *snod;
-+ struct ubifs_orph_node *orph;
-+ unsigned long long cmt_no;
-+ ino_t inum;
-+ int i, n, err, first = 1;
-+
-+ list_for_each_entry(snod, &sleb->nodes, list) {
-+ if (snod->type != UBIFS_ORPH_NODE) {
-+ ubifs_err("invalid node type %d in orphan area at "
-+ "%d:%d", snod->type, sleb->lnum, snod->offs);
-+ dbg_dump_node(c, snod->node);
-+ return -EINVAL;
-+ }
-+
-+ orph = snod->node;
-+
-+ /* Check commit number */
-+ cmt_no = le64_to_cpu(orph->cmt_no) & LLONG_MAX;
-+ /*
-+ * The commit number on the master node may be less, because
-+ * of a failed commit. If there are several failed commits in a
-+ * row, the commit number written on orph nodes will continue to
-+ * increase (because the commit number is adjusted here) even
-+ * though the commit number on the master node stays the same
-+ * because the master node has not been re-written.
-+ */
-+ if (cmt_no > c->cmt_no)
-+ c->cmt_no = cmt_no;
-+ if (cmt_no < *last_cmt_no && *last_flagged) {
-+ /*
-+ * The last orph node had a higher commit number and was
-+ * flagged as the last written for that commit number.
-+ * That makes this orph node, out of date.
-+ */
-+ if (!first) {
-+ ubifs_err("out of order commit number %llu in "
-+ "orphan node at %d:%d",
-+ cmt_no, sleb->lnum, snod->offs);
-+ dbg_dump_node(c, snod->node);
-+ return -EINVAL;
-+ }
-+ dbg_rcvry("out of date LEB %d", sleb->lnum);
-+ *outofdate = 1;
-+ return 0;
-+ }
-+
-+ if (first)
-+ first = 0;
-+
-+ n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
-+ for (i = 0; i < n; i++) {
-+ inum = le64_to_cpu(orph->inos[i]);
-+ dbg_rcvry("deleting orphaned inode %lu", inum);
-+ err = ubifs_tnc_remove_ino(c, inum);
-+ if (err)
-+ return err;
-+ err = insert_dead_orphan(c, inum);
-+ if (err)
-+ return err;
-+ }
-+
-+ *last_cmt_no = cmt_no;
-+ if (le64_to_cpu(orph->cmt_no) & (1ULL << 63)) {
-+ dbg_rcvry("last orph node for commit %llu at %d:%d",
-+ cmt_no, sleb->lnum, snod->offs);
-+ *last_flagged = 1;
-+ } else
-+ *last_flagged = 0;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * kill_orphans - remove all orphan inodes from the index.
-+ * @c: UBIFS file-system description object
-+ *
-+ * If recovery is required, then orphan inodes recorded during the previous
-+ * session (which ended with an unclean unmount) must be deleted from the index.
-+ * This is done by updating the TNC, but since the index is not updated until
-+ * the next commit, the LEBs where the orphan information is recorded are not
-+ * erased until the next commit.
-+ */
-+static int kill_orphans(struct ubifs_info *c)
-+{
-+ unsigned long long last_cmt_no = 0;
-+ int lnum, err = 0, outofdate = 0, last_flagged = 0;
-+
-+ c->ohead_lnum = c->orph_first;
-+ c->ohead_offs = 0;
-+ /* Check no-orphans flag and skip this if no orphans */
-+ if (c->no_orphs) {
-+ dbg_rcvry("no orphans");
-+ return 0;
-+ }
-+ /*
-+ * Orph nodes always start at c->orph_first and are written to each
-+ * successive LEB in turn. Generally unused LEBs will have been unmapped
-+ * but may contain out of date orph nodes if the unmap didn't go
-+ * through. In addition, the last orph node written for each commit is
-+ * marked (top bit of orph->cmt_no is set to 1). It is possible that
-+ * there are orph nodes from the next commit (i.e. the commit did not
-+ * complete successfully). In that case, no orphans will have been lost
-+ * due to the way that orphans are written, and any orphans added will
-+ * be valid orphans anyway and so can be deleted.
-+ */
-+ for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
-+ struct ubifs_scan_leb *sleb;
-+
-+ dbg_rcvry("LEB %d", lnum);
-+ sleb = ubifs_scan(c, lnum, 0, c->sbuf);
-+ if (IS_ERR(sleb)) {
-+ sleb = ubifs_recover_leb(c, lnum, 0, c->sbuf, 0);
-+ if (IS_ERR(sleb)) {
-+ err = PTR_ERR(sleb);
-+ break;
-+ }
-+ }
-+ err = do_kill_orphans(c, sleb, &last_cmt_no, &outofdate,
-+ &last_flagged);
-+ if (err || outofdate) {
-+ ubifs_scan_destroy(sleb);
-+ break;
-+ }
-+ if (sleb->endpt) {
-+ c->ohead_lnum = lnum;
-+ c->ohead_offs = sleb->endpt;
-+ }
-+ ubifs_scan_destroy(sleb);
-+ }
-+ return err;
-+}
-+
-+/**
-+ * ubifs_mount_orphans - delete orphan inodes and erase LEBs that recorded them.
-+ * @c: UBIFS file-system description object
-+ * @unclean: %1 => recover from unclean unmount
-+ *
-+ * This function is called when mounting to erase orphans from the previous
-+ * session. If UBIFS was not unmounted cleanly, then the inodes recorded as
-+ * orphans are deleted.
-+ */
-+int ubifs_mount_orphans(struct ubifs_info *c, int unclean)
-+{
-+ int err = 0;
-+
-+ c->max_orphans = tot_avail_orphs(c);
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->orph_buf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ c->orph_buf = vmalloc(c->leb_size);
-+#endif
-+ if (!c->orph_buf)
-+ return -ENOMEM;
-+
-+ if (unclean)
-+ err = kill_orphans(c);
-+ else
-+ err = clear_orphans(c);
-+
-+ return err;
-+}
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+struct check_orphan {
-+ struct rb_node rb;
-+ ino_t inum;
-+};
-+
-+struct check_info {
-+ unsigned long last_ino;
-+ unsigned long tot_inos;
-+ unsigned long missing;
-+ unsigned long long leaf_cnt;
-+ struct ubifs_ino_node *node;
-+ struct rb_root root;
-+};
-+
-+static int dbg_find_orphan(struct ubifs_info *c, ino_t inum)
-+{
-+ struct ubifs_orphan *o;
-+ struct rb_node *p;
-+
-+ spin_lock(&c->orphan_lock);
-+ p = c->orph_tree.rb_node;
-+ while (p) {
-+ o = rb_entry(p, struct ubifs_orphan, rb);
-+ if (inum < o->inum)
-+ p = p->rb_left;
-+ else if (inum > o->inum)
-+ p = p->rb_right;
-+ else {
-+ spin_unlock(&c->orphan_lock);
-+ return 1;
-+ }
-+ }
-+ spin_unlock(&c->orphan_lock);
-+ return 0;
-+}
-+
-+static int dbg_ins_check_orphan(struct rb_root *root, ino_t inum)
-+{
-+ struct check_orphan *orphan, *o;
-+ struct rb_node **p, *parent = NULL;
-+
-+ orphan = kzalloc(sizeof(struct check_orphan), GFP_NOFS);
-+ if (!orphan)
-+ return -ENOMEM;
-+ orphan->inum = inum;
-+
-+ p = &root->rb_node;
-+ while (*p) {
-+ parent = *p;
-+ o = rb_entry(parent, struct check_orphan, rb);
-+ if (inum < o->inum)
-+ p = &(*p)->rb_left;
-+ else if (inum > o->inum)
-+ p = &(*p)->rb_right;
-+ else {
-+ kfree(orphan);
-+ return 0;
-+ }
-+ }
-+ rb_link_node(&orphan->rb, parent, p);
-+ rb_insert_color(&orphan->rb, root);
-+ return 0;
-+}
-+
-+static int dbg_find_check_orphan(struct rb_root *root, ino_t inum)
-+{
-+ struct check_orphan *o;
-+ struct rb_node *p;
-+
-+ p = root->rb_node;
-+ while (p) {
-+ o = rb_entry(p, struct check_orphan, rb);
-+ if (inum < o->inum)
-+ p = p->rb_left;
-+ else if (inum > o->inum)
-+ p = p->rb_right;
-+ else
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static void dbg_free_check_tree(struct rb_root *root)
-+{
-+ struct rb_node *this = root->rb_node;
-+ struct check_orphan *o;
-+
-+ while (this) {
-+ if (this->rb_left) {
-+ this = this->rb_left;
-+ continue;
-+ } else if (this->rb_right) {
-+ this = this->rb_right;
-+ continue;
-+ }
-+ o = rb_entry(this, struct check_orphan, rb);
-+ this = rb_parent(this);
-+ if (this) {
-+ if (this->rb_left == &o->rb)
-+ this->rb_left = NULL;
-+ else
-+ this->rb_right = NULL;
-+ }
-+ kfree(o);
-+ }
-+}
-+
-+static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr,
-+ void *priv)
-+{
-+ struct check_info *ci = priv;
-+ ino_t inum;
-+ int err;
-+
-+ inum = key_ino(c, &zbr->key);
-+ if (inum != ci->last_ino) {
-+ /* Lowest node type is the inode node, so it comes first */
-+ if (key_type(c, &zbr->key) != UBIFS_INO_KEY)
-+ ubifs_err("found orphan node ino %lu, type %d", inum,
-+ key_type(c, &zbr->key));
-+ ci->last_ino = inum;
-+ ci->tot_inos += 1;
-+ err = dbg_read_leaf_nolock(c, zbr, ci->node);
-+ if (err) {
-+ ubifs_err("node read failed, error %d", err);
-+ return err;
-+ }
-+ if (ci->node->nlink == 0)
-+ /* Must be recorded as an orphan */
-+ if (!dbg_find_check_orphan(&ci->root, inum) &&
-+ !dbg_find_orphan(c, inum)) {
-+ ubifs_err("missing orphan, ino %lu", inum);
-+ ci->missing += 1;
-+ }
-+ }
-+ ci->leaf_cnt += 1;
-+ return 0;
-+}
-+
-+static int dbg_read_orphans(struct check_info *ci, struct ubifs_scan_leb *sleb)
-+{
-+ struct ubifs_scan_node *snod;
-+ struct ubifs_orph_node *orph;
-+ ino_t inum;
-+ int i, n, err;
-+
-+ list_for_each_entry(snod, &sleb->nodes, list) {
-+ cond_resched();
-+ if (snod->type != UBIFS_ORPH_NODE)
-+ continue;
-+ orph = snod->node;
-+ n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
-+ for (i = 0; i < n; i++) {
-+ inum = le64_to_cpu(orph->inos[i]);
-+ err = dbg_ins_check_orphan(&ci->root, inum);
-+ if (err)
-+ return err;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci)
-+{
-+ int lnum, err = 0;
-+
-+ /* Check no-orphans flag and skip this if no orphans */
-+ if (c->no_orphs)
-+ return 0;
-+
-+ for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
-+ struct ubifs_scan_leb *sleb;
-+
-+ sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
-+ if (IS_ERR(sleb)) {
-+ err = PTR_ERR(sleb);
-+ break;
-+ }
-+
-+ err = dbg_read_orphans(ci, sleb);
-+ ubifs_scan_destroy(sleb);
-+ if (err)
-+ break;
-+ }
-+
-+ return err;
-+}
-+
-+static int dbg_check_orphans(struct ubifs_info *c)
-+{
-+ struct check_info ci;
-+ int err;
-+
-+ if (!(ubifs_chk_flags & UBIFS_CHK_ORPH))
-+ return 0;
-+
-+ ci.last_ino = 0;
-+ ci.tot_inos = 0;
-+ ci.missing = 0;
-+ ci.leaf_cnt = 0;
-+ ci.root = RB_ROOT;
-+ ci.node = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
-+ if (!ci.node) {
-+ ubifs_err("out of memory");
-+ return -ENOMEM;
-+ }
-+
-+ err = dbg_scan_orphans(c, &ci);
-+ if (err)
-+ goto out;
-+
-+ err = dbg_walk_index(c, &dbg_orphan_check, NULL, &ci);
-+ if (err) {
-+ ubifs_err("cannot scan TNC, error %d", err);
-+ goto out;
-+ }
-+
-+ if (ci.missing) {
-+ ubifs_err("%lu missing orphan(s)", ci.missing);
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ dbg_cmt("last inode number is %lu", ci.last_ino);
-+ dbg_cmt("total number of inodes is %lu", ci.tot_inos);
-+ dbg_cmt("total number of leaf nodes is %llu", ci.leaf_cnt);
-+
-+out:
-+ dbg_free_check_tree(&ci.root);
-+ kfree(ci.node);
-+ return err;
-+}
-+
-+#endif /* CONFIG_UBIFS_FS_DEBUG */
---- linux-2.6.24.7.old/fs/ubifs/recovery.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/recovery.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1524 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file implements functions needed to recover from unclean un-mounts.
-+ * When UBIFS is mounted, it checks a flag on the master node to determine if
-+ * an un-mount was completed sucessfully. If not, the process of mounting
-+ * incorparates additional checking and fixing of on-flash data structures.
-+ * UBIFS always cleans away all remnants of an unclean un-mount, so that
-+ * errors do not accumulate. However UBIFS defers recovery if it is mounted
-+ * read-only, and the flash is not modified in that case.
-+ */
-+
-+#include
-+#include "ubifs.h"
-+
-+/**
-+ * is_empty - determine whether a buffer is empty (contains all 0xff).
-+ * @buf: buffer to clean
-+ * @len: length of buffer
-+ *
-+ * This function returns %1 if the buffer is empty (contains all 0xff) otherwise
-+ * %0 is returned.
-+ */
-+static int is_empty(void *buf, int len)
-+{
-+ uint8_t *p = buf;
-+ int i;
-+
-+ for (i = 0; i < len; i++)
-+ if (*p++ != 0xff)
-+ return 0;
-+ return 1;
-+}
-+
-+/**
-+ * get_master_node - get the last valid master node allowing for corruption.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number
-+ * @pbuf: buffer containing the LEB read, is returned here
-+ * @mst: master node, if found, is returned here
-+ * @cor: corruption, if found, is returned here
-+ *
-+ * This function allocates a buffer, reads the LEB into it, and finds and
-+ * returns the last valid master node allowing for one area of corruption.
-+ * The corrupt area, if there is one, must be consistent with the assumption
-+ * that it is the result of an unclean unmount while the master node was being
-+ * written. Under those circumstances, it is valid to use the previously written
-+ * master node.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf,
-+ struct ubifs_mst_node **mst, void **cor)
-+{
-+ const int sz = c->mst_node_alsz;
-+ int err, offs, len;
-+ void *sbuf, *buf;
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ sbuf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ sbuf = vmalloc(c->leb_size);
-+#endif
-+ if (!sbuf)
-+ return -ENOMEM;
-+
-+ err = ubi_read(c->ubi, lnum, sbuf, 0, c->leb_size);
-+ if (err && err != -EBADMSG)
-+ goto out_free;
-+
-+ /* Find the first position that is definitely not a node */
-+ offs = 0;
-+ buf = sbuf;
-+ len = c->leb_size;
-+ while (offs + UBIFS_MST_NODE_SZ <= c->leb_size) {
-+ struct ubifs_ch *ch = buf;
-+
-+ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC)
-+ break;
-+ offs += sz;
-+ buf += sz;
-+ len -= sz;
-+ }
-+ /* See if there was a valid master node before that */
-+ if (offs) {
-+ int ret;
-+
-+ offs -= sz;
-+ buf -= sz;
-+ len += sz;
-+ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
-+ if (ret != SCANNED_A_NODE && offs) {
-+ /* Could have been corruption so check one place back */
-+ offs -= sz;
-+ buf -= sz;
-+ len += sz;
-+ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
-+ if (ret != SCANNED_A_NODE)
-+ /*
-+ * We accept only one area of corruption because
-+ * we are assuming that it was caused while
-+ * trying to write a master node.
-+ */
-+ goto out_err;
-+ }
-+ if (ret == SCANNED_A_NODE) {
-+ struct ubifs_ch *ch = buf;
-+
-+ if (ch->node_type != UBIFS_MST_NODE)
-+ goto out_err;
-+ dbg_rcvry("found a master node at %d:%d", lnum, offs);
-+ *mst = buf;
-+ offs += sz;
-+ buf += sz;
-+ len -= sz;
-+ }
-+ }
-+ /* Check for corruption */
-+ if (offs < c->leb_size) {
-+ if (!is_empty(buf, min_t(int, len, sz))) {
-+ *cor = buf;
-+ dbg_rcvry("found corruption at %d:%d", lnum, offs);
-+ }
-+ offs += sz;
-+ buf += sz;
-+ len -= sz;
-+ }
-+ /* Check remaining empty space */
-+ if (offs < c->leb_size)
-+ if (!is_empty(buf, len))
-+ goto out_err;
-+ *pbuf = sbuf;
-+ return 0;
-+
-+out_err:
-+ err = -EINVAL;
-+out_free:
-+ vfree(sbuf);
-+ *mst = NULL;
-+ *cor = NULL;
-+ return err;
-+}
-+
-+/**
-+ * write_rcvrd_mst_node - write recovered master node.
-+ * @c: UBIFS file-system description object
-+ * @mst: master node
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int write_rcvrd_mst_node(struct ubifs_info *c,
-+ struct ubifs_mst_node *mst)
-+{
-+ int err = 0, lnum = UBIFS_MST_LNUM, sz = c->mst_node_alsz;
-+ uint32_t save_flags;
-+
-+ dbg_rcvry("recovery");
-+
-+ save_flags = mst->flags;
-+ mst->flags = cpu_to_le32(le32_to_cpu(mst->flags) | UBIFS_MST_RCVRY);
-+
-+ ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
-+ err = ubi_leb_change(c->ubi, lnum, mst, sz, UBI_SHORTTERM);
-+ if (err)
-+ goto out;
-+ err = ubi_leb_change(c->ubi, lnum + 1, mst, sz, UBI_SHORTTERM);
-+ if (err)
-+ goto out;
-+out:
-+ mst->flags = save_flags;
-+ return err;
-+}
-+
-+/**
-+ * ubifs_recover_master_node - recover the master node.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function recovers the master node from corruption that may occur due to
-+ * an unclean unmount.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_recover_master_node(struct ubifs_info *c)
-+{
-+ void *buf1 = NULL, *buf2 = NULL, *cor1 = NULL, *cor2 = NULL;
-+ struct ubifs_mst_node *mst1 = NULL, *mst2 = NULL, *mst;
-+ const int sz = c->mst_node_alsz;
-+ int err, offs1, offs2;
-+
-+ dbg_rcvry("recovery");
-+
-+ err = get_master_node(c, UBIFS_MST_LNUM, &buf1, &mst1, &cor1);
-+ if (err)
-+ goto out_free;
-+
-+ err = get_master_node(c, UBIFS_MST_LNUM + 1, &buf2, &mst2, &cor2);
-+ if (err)
-+ goto out_free;
-+
-+ if (mst1) {
-+ offs1 = (void *)mst1 - buf1;
-+ if ((le32_to_cpu(mst1->flags) & UBIFS_MST_RCVRY) &&
-+ (offs1 == 0 && !cor1)) {
-+ /*
-+ * mst1 was written by recovery at offset 0 with no
-+ * corruption.
-+ */
-+ dbg_rcvry("recovery recovery");
-+ mst = mst1;
-+ } else if (mst2) {
-+ offs2 = (void *)mst2 - buf2;
-+ if (offs1 == offs2) {
-+ /* Same offset, so must be the same */
-+ if (memcmp((void *)mst1 + UBIFS_CH_SZ,
-+ (void *)mst2 + UBIFS_CH_SZ,
-+ UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
-+ goto out_err;
-+ mst = mst1;
-+ } else if (offs2 + sz == offs1) {
-+ /* 1st LEB was written, 2nd was not */
-+ if (cor1)
-+ goto out_err;
-+ mst = mst1;
-+ } else if (offs1 == 0 && offs2 + sz >= c->leb_size) {
-+ /* 1st LEB was unmapped and written, 2nd not */
-+ if (cor1)
-+ goto out_err;
-+ mst = mst1;
-+ } else
-+ goto out_err;
-+ } else {
-+ /*
-+ * 2nd LEB was unmapped and about to be written, so
-+ * there must be only one master node in the first LEB
-+ * and no corruption.
-+ */
-+ if (offs1 != 0 || cor1)
-+ goto out_err;
-+ mst = mst1;
-+ }
-+ } else {
-+ if (!mst2)
-+ goto out_err;
-+ /*
-+ * 1st LEB was unmapped and about to be written, so there must
-+ * be no room left in 2nd LEB.
-+ */
-+ offs2 = (void *)mst2 - buf2;
-+ if (offs2 + sz + sz <= c->leb_size)
-+ goto out_err;
-+ mst = mst2;
-+ }
-+
-+ dbg_rcvry("recovered master node from LEB %d",
-+ (mst == mst1 ? UBIFS_MST_LNUM : UBIFS_MST_LNUM + 1));
-+
-+ memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);
-+
-+ if ((c->vfs_sb->s_flags & MS_RDONLY)) {
-+ /* Read-only mode. Keep a copy for switching to rw mode */
-+ c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
-+ if (!c->rcvrd_mst_node) {
-+ err = -ENOMEM;
-+ goto out_free;
-+ }
-+ memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ);
-+ } else {
-+ /* Write the recovered master node */
-+ c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1;
-+ err = write_rcvrd_mst_node(c, c->mst_node);
-+ if (err)
-+ goto out_free;
-+ }
-+
-+ vfree(buf2);
-+ vfree(buf1);
-+
-+ return 0;
-+
-+out_err:
-+ err = -EINVAL;
-+out_free:
-+ ubifs_err("failed to recover master node");
-+ if (mst1) {
-+ dbg_err("dumping first master node");
-+ dbg_dump_node(c, mst1);
-+ }
-+ if (mst2) {
-+ dbg_err("dumping second master node");
-+ dbg_dump_node(c, mst2);
-+ }
-+ vfree(buf2);
-+ vfree(buf1);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_write_rcvrd_mst_node - write the recovered master node.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function writes the master node that was recovered during mounting in
-+ * read-only mode and must now be written because we are remounting rw.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_write_rcvrd_mst_node(struct ubifs_info *c)
-+{
-+ int err;
-+
-+ if (!c->rcvrd_mst_node)
-+ return 0;
-+ c->rcvrd_mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
-+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
-+ err = write_rcvrd_mst_node(c, c->rcvrd_mst_node);
-+ if (err)
-+ return err;
-+ kfree(c->rcvrd_mst_node);
-+ c->rcvrd_mst_node = NULL;
-+ return 0;
-+}
-+
-+/**
-+ * is_last_write - determine if an offset was in the last write to a LEB.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer to check
-+ * @offs: offset to check
-+ *
-+ * This function returns %1 if @offs was in the last write to the LEB whose data
-+ * is in @buf, otherwise %0 is returned. The determination is made by checking
-+ * for subsequent empty space starting from the next min_io_size boundary (or a
-+ * bit less than the common header size if min_io_size is one).
-+ */
-+static int is_last_write(const struct ubifs_info *c, void *buf, int offs)
-+{
-+ int empty_offs;
-+ int check_len;
-+ uint8_t *p;
-+
-+ if (c->min_io_size == 1) {
-+ check_len = c->leb_size - offs;
-+ p = buf + check_len;
-+ for (; check_len > 0; check_len--)
-+ if (*--p != 0xff)
-+ break;
-+ /*
-+ * 'check_len' is the size of the corruption which cannot be
-+ * more than the size of 1 node if it was caused by an unclean
-+ * unmount.
-+ */
-+ if (check_len > UBIFS_MAX_NODE_SZ)
-+ return 0;
-+ return 1;
-+ }
-+
-+ /*
-+ * Round up to the next c->min_io_size boundary i.e. 'offs' is in the
-+ * last wbuf written. After that should be empty space.
-+ */
-+ empty_offs = ALIGN(offs + 1, c->min_io_size);
-+ check_len = c->leb_size - empty_offs;
-+ p = buf + empty_offs - offs;
-+
-+ for (; check_len > 0; check_len--)
-+ if (*p++ != 0xff)
-+ return 0;
-+ return 1;
-+}
-+
-+/**
-+ * clean_buf - clean the data from an LEB sitting in a buffer.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer to clean
-+ * @lnum: LEB number to clean
-+ * @offs: offset from which to clean
-+ * @len: length of buffer
-+ *
-+ * This function pads up to the next min_io_size boundary (if there is one) and
-+ * sets empty space to all 0xff. @buf, @offs and @len are updated to the next
-+ * min_io_size boundary (if there is one).
-+ */
-+static void clean_buf(const struct ubifs_info *c, void **buf, int lnum,
-+ int *offs, int *len)
-+{
-+ int empty_offs, pad_len;
-+
-+ lnum = lnum;
-+ dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs);
-+
-+ if (c->min_io_size == 1) {
-+ memset(*buf, 0xff, c->leb_size - *offs);
-+ return;
-+ }
-+
-+ ubifs_assert(!(*offs & 7));
-+ empty_offs = ALIGN(*offs, c->min_io_size);
-+ pad_len = empty_offs - *offs;
-+ ubifs_pad(c, *buf, pad_len);
-+ *offs += pad_len;
-+ *buf += pad_len;
-+ *len -= pad_len;
-+ memset(*buf, 0xff, c->leb_size - empty_offs);
-+}
-+
-+/**
-+ * no_more_nodes - determine if there are no more nodes in a buffer.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer to check
-+ * @len: length of buffer
-+ * @lnum: LEB number of the LEB from which @buf was read
-+ * @offs: offset from which @buf was read
-+ *
-+ * This function scans @buf for more nodes and returns %0 is a node is found and
-+ * %1 if no more nodes are found.
-+ */
-+static int no_more_nodes(const struct ubifs_info *c, void *buf, int len,
-+ int lnum, int offs)
-+{
-+ int skip, next_offs = 0;
-+
-+ if (len > UBIFS_DATA_NODE_SZ) {
-+ struct ubifs_ch *ch = buf;
-+ int dlen = le32_to_cpu(ch->len);
-+
-+ if (ch->node_type == UBIFS_DATA_NODE && dlen >= UBIFS_CH_SZ &&
-+ dlen <= UBIFS_MAX_DATA_NODE_SZ)
-+ /* The corrupt node looks like a data node */
-+ next_offs = ALIGN(offs + dlen, 8);
-+ }
-+
-+ if (c->min_io_size == 1)
-+ skip = 8;
-+ else
-+ skip = ALIGN(offs + 1, c->min_io_size) - offs;
-+
-+ offs += skip;
-+ buf += skip;
-+ len -= skip;
-+ while (len > 8) {
-+ struct ubifs_ch *ch = buf;
-+ uint32_t magic = le32_to_cpu(ch->magic);
-+ int ret;
-+
-+ if (magic == UBIFS_NODE_MAGIC) {
-+ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
-+ if (ret == SCANNED_A_NODE || ret > 0) {
-+ /*
-+ * There is a small chance this is just data in
-+ * a data node, so check that possibility. e.g.
-+ * this is part of a file that itself contains
-+ * a UBIFS image.
-+ */
-+ if (next_offs && offs + le32_to_cpu(ch->len) <=
-+ next_offs)
-+ continue;
-+ dbg_rcvry("unexpected node at %d:%d", lnum,
-+ offs);
-+ return 0;
-+ }
-+ }
-+ offs += 8;
-+ buf += 8;
-+ len -= 8;
-+ }
-+ return 1;
-+}
-+
-+/**
-+ * fix_unclean_leb - fix an unclean LEB.
-+ * @c: UBIFS file-system description object
-+ * @sleb: scanned LEB information
-+ * @start: offset where scan started
-+ */
-+static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
-+ int start)
-+{
-+ int lnum = sleb->lnum, endpt = start;
-+
-+ /* Get the end offset of the last node we are keeping */
-+ if (!list_empty(&sleb->nodes)) {
-+ struct ubifs_scan_node *snod;
-+
-+ snod = list_entry(sleb->nodes.prev,
-+ struct ubifs_scan_node, list);
-+ endpt = snod->offs + snod->len;
-+ }
-+
-+ if ((c->vfs_sb->s_flags & MS_RDONLY) && !c->remounting_rw) {
-+ /* Add to recovery list */
-+ struct ubifs_unclean_leb *ucleb;
-+
-+ dbg_rcvry("need to fix LEB %d start %d endpt %d",
-+ lnum, start, sleb->endpt);
-+ ucleb = kzalloc(sizeof(struct ubifs_unclean_leb), GFP_NOFS);
-+ if (!ucleb)
-+ return -ENOMEM;
-+ ucleb->lnum = lnum;
-+ ucleb->endpt = endpt;
-+ list_add_tail(&ucleb->list, &c->unclean_leb_list);
-+ } else {
-+ /* Write the fixed LEB back to flash */
-+ int err;
-+
-+ dbg_rcvry("fixing LEB %d start %d endpt %d",
-+ lnum, start, sleb->endpt);
-+ if (endpt == 0) {
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ } else {
-+ int len = ALIGN(endpt, c->min_io_size);
-+
-+ if (start) {
-+ err = ubi_read(c->ubi, lnum, sleb->buf, 0,
-+ start);
-+ if (err)
-+ return err;
-+ }
-+ /* Pad to min_io_size */
-+ if (len > endpt) {
-+ int pad_len = len - ALIGN(endpt, 8);
-+
-+ if (pad_len > 0) {
-+ void *buf = sleb->buf + len - pad_len;
-+
-+ ubifs_pad(c, buf, pad_len);
-+ }
-+ }
-+ err = ubi_leb_change(c->ubi, lnum, sleb->buf, len,
-+ UBI_UNKNOWN);
-+ if (err)
-+ return err;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * drop_incomplete_group - drop nodes from an incomplete group.
-+ * @sleb: scanned LEB information
-+ * @offs: offset of dropped nodes is returned here
-+ *
-+ * This function returns %1 if nodes are dropped and %0 otherwise.
-+ */
-+static int drop_incomplete_group(struct ubifs_scan_leb *sleb, int *offs)
-+{
-+ int dropped = 0;
-+
-+ while (!list_empty(&sleb->nodes)) {
-+ struct ubifs_scan_node *snod;
-+ struct ubifs_ch *ch;
-+
-+ snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
-+ list);
-+ ch = snod->node;
-+ if (ch->group_type != UBIFS_IN_NODE_GROUP)
-+ return dropped;
-+ dbg_rcvry("dropping node at %d:%d", sleb->lnum, snod->offs);
-+ *offs = snod->offs;
-+ list_del(&snod->list);
-+ kfree(snod);
-+ sleb->nodes_cnt -= 1;
-+ dropped = 1;
-+ }
-+ return dropped;
-+}
-+
-+/**
-+ * ubifs_recover_leb - scan and recover a LEB.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number
-+ * @offs: offset
-+ * @sbuf: LEB-sized buffer to use
-+ * @grouped: nodes may be grouped for recovery
-+ *
-+ * This function does a scan of a LEB, but caters for errors that might have
-+ * been caused by the unclean unmount from which we are attempting to recover.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
-+ int offs, void *sbuf, int grouped)
-+{
-+ int err, len = c->leb_size - offs, need_clean = 0, quiet = 1;
-+ int empty_chkd = 0, start = offs;
-+ struct ubifs_scan_leb *sleb;
-+ void *buf = sbuf + offs;
-+
-+ dbg_rcvry("%d:%d", lnum, offs);
-+
-+ sleb = ubifs_start_scan(c, lnum, offs, sbuf);
-+ if (IS_ERR(sleb))
-+ return sleb;
-+
-+ if (sleb->ecc)
-+ need_clean = 1;
-+
-+ while (len >= 8) {
-+ int ret;
-+
-+ dbg_scan("look at LEB %d:%d (%d bytes left)",
-+ lnum, offs, len);
-+
-+ cond_resched();
-+
-+ /*
-+ * Scan quietly until there is an error from which we cannot
-+ * recover
-+ */
-+ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet);
-+
-+ if (ret == SCANNED_A_NODE) {
-+ /* A valid node, and not a padding node */
-+ struct ubifs_ch *ch = buf;
-+ int node_len;
-+
-+ err = ubifs_add_snod(c, sleb, buf, offs);
-+ if (err)
-+ goto error;
-+ node_len = ALIGN(le32_to_cpu(ch->len), 8);
-+ offs += node_len;
-+ buf += node_len;
-+ len -= node_len;
-+ continue;
-+ }
-+
-+ if (ret > 0) {
-+ /* Padding bytes or a valid padding node */
-+ offs += ret;
-+ buf += ret;
-+ len -= ret;
-+ continue;
-+ }
-+
-+ if (ret == SCANNED_EMPTY_SPACE) {
-+ if (!is_empty(buf, len)) {
-+ if (!is_last_write(c, buf, offs))
-+ break;
-+ clean_buf(c, &buf, lnum, &offs, &len);
-+ need_clean = 1;
-+ }
-+ empty_chkd = 1;
-+ break;
-+ }
-+
-+ if (ret == SCANNED_GARBAGE || ret == SCANNED_A_BAD_PAD_NODE)
-+ if (is_last_write(c, buf, offs)) {
-+ clean_buf(c, &buf, lnum, &offs, &len);
-+ need_clean = 1;
-+ empty_chkd = 1;
-+ break;
-+ }
-+
-+ if (ret == SCANNED_A_CORRUPT_NODE)
-+ if (no_more_nodes(c, buf, len, lnum, offs)) {
-+ clean_buf(c, &buf, lnum, &offs, &len);
-+ need_clean = 1;
-+ empty_chkd = 1;
-+ break;
-+ }
-+
-+ if (quiet) {
-+ /* Redo the last scan but noisily */
-+ quiet = 0;
-+ continue;
-+ }
-+
-+ switch (ret) {
-+ case SCANNED_GARBAGE:
-+ dbg_err("garbage");
-+ goto corrupted;
-+ case SCANNED_A_CORRUPT_NODE:
-+ case SCANNED_A_BAD_PAD_NODE:
-+ dbg_err("bad node");
-+ goto corrupted;
-+ default:
-+ dbg_err("unknown");
-+ goto corrupted;
-+ }
-+ }
-+
-+ if (!empty_chkd && !is_empty(buf, len)) {
-+ if (is_last_write(c, buf, offs)) {
-+ clean_buf(c, &buf, lnum, &offs, &len);
-+ need_clean = 1;
-+ } else {
-+ ubifs_err("corrupt empty space at LEB %d:%d",
-+ lnum, offs);
-+ goto corrupted;
-+ }
-+ }
-+
-+ /* Drop nodes from incomplete group */
-+ if (grouped && drop_incomplete_group(sleb, &offs)) {
-+ buf = sbuf + offs;
-+ len = c->leb_size - offs;
-+ clean_buf(c, &buf, lnum, &offs, &len);
-+ need_clean = 1;
-+ }
-+
-+ if (offs % c->min_io_size) {
-+ clean_buf(c, &buf, lnum, &offs, &len);
-+ need_clean = 1;
-+ }
-+
-+ ubifs_end_scan(c, sleb, lnum, offs);
-+
-+ if (need_clean) {
-+ err = fix_unclean_leb(c, sleb, start);
-+ if (err)
-+ goto error;
-+ }
-+
-+ return sleb;
-+
-+corrupted:
-+ ubifs_scanned_corruption(c, lnum, offs, buf);
-+ err = -EUCLEAN;
-+error:
-+ ubifs_err("LEB %d scanning failed", lnum);
-+ ubifs_scan_destroy(sleb);
-+ return ERR_PTR(err);
-+}
-+
-+/**
-+ * get_cs_sqnum - get commit start sequence number.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number of commit start node
-+ * @offs: offset of commit start node
-+ * @cs_sqnum: commit start sequence number is returned here
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs,
-+ unsigned long long *cs_sqnum)
-+{
-+ struct ubifs_cs_node *cs_node = NULL;
-+ int err, ret;
-+
-+ dbg_rcvry("at %d:%d", lnum, offs);
-+ cs_node = kmalloc(UBIFS_CS_NODE_SZ, GFP_KERNEL);
-+ if (!cs_node)
-+ return -ENOMEM;
-+ if (c->leb_size - offs < UBIFS_CS_NODE_SZ)
-+ goto out_err;
-+ err = ubi_read(c->ubi, lnum, (void *)cs_node, offs, UBIFS_CS_NODE_SZ);
-+ if (err && err != -EBADMSG)
-+ goto out_free;
-+ ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
-+ if (ret != SCANNED_A_NODE) {
-+ dbg_err("Not a valid node");
-+ goto out_err;
-+ }
-+ if (cs_node->ch.node_type != UBIFS_CS_NODE) {
-+ dbg_err("Node a CS node, type is %d", cs_node->ch.node_type);
-+ goto out_err;
-+ }
-+ if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) {
-+ dbg_err("CS node cmt_no %llu != current cmt_no %llu",
-+ (unsigned long long)le64_to_cpu(cs_node->cmt_no),
-+ c->cmt_no);
-+ goto out_err;
-+ }
-+ *cs_sqnum = le64_to_cpu(cs_node->ch.sqnum);
-+ dbg_rcvry("commit start sqnum %llu", *cs_sqnum);
-+ kfree(cs_node);
-+ return 0;
-+
-+out_err:
-+ err = -EINVAL;
-+out_free:
-+ ubifs_err("failed to get CS sqnum");
-+ kfree(cs_node);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_recover_log_leb - scan and recover a log LEB.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number
-+ * @offs: offset
-+ * @sbuf: LEB-sized buffer to use
-+ *
-+ * This function does a scan of a LEB, but caters for errors that might have
-+ * been caused by the unclean unmount from which we are attempting to recover.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
-+ int offs, void *sbuf)
-+{
-+ struct ubifs_scan_leb *sleb;
-+ int next_lnum;
-+
-+ dbg_rcvry("LEB %d", lnum);
-+ next_lnum = lnum + 1;
-+ if (next_lnum >= UBIFS_LOG_LNUM + c->log_lebs)
-+ next_lnum = UBIFS_LOG_LNUM;
-+ if (next_lnum != c->ltail_lnum) {
-+ /*
-+ * We can only recover at the end of the log, so check that the
-+ * next log LEB is empty or out of date.
-+ */
-+ sleb = ubifs_scan(c, next_lnum, 0, sbuf);
-+ if (IS_ERR(sleb))
-+ return sleb;
-+ if (sleb->nodes_cnt) {
-+ struct ubifs_scan_node *snod;
-+ unsigned long long cs_sqnum = c->cs_sqnum;
-+
-+ snod = list_entry(sleb->nodes.next,
-+ struct ubifs_scan_node, list);
-+ if (cs_sqnum == 0) {
-+ int err;
-+
-+ err = get_cs_sqnum(c, lnum, offs, &cs_sqnum);
-+ if (err) {
-+ ubifs_scan_destroy(sleb);
-+ return ERR_PTR(err);
-+ }
-+ }
-+ if (snod->sqnum > cs_sqnum) {
-+ ubifs_err("unrecoverable log corruption "
-+ "in LEB %d", lnum);
-+ ubifs_scan_destroy(sleb);
-+ return ERR_PTR(-EUCLEAN);
-+ }
-+ }
-+ ubifs_scan_destroy(sleb);
-+ }
-+ return ubifs_recover_leb(c, lnum, offs, sbuf, 0);
-+}
-+
-+/**
-+ * recover_head - recover a head.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number of head to recover
-+ * @offs: offset of head to recover
-+ * @sbuf: LEB-sized buffer to use
-+ *
-+ * This function ensures that there is no data on the flash at a head location.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int recover_head(const struct ubifs_info *c, int lnum, int offs,
-+ void *sbuf)
-+{
-+ int len, err, need_clean = 0;
-+
-+ if (c->min_io_size > 1)
-+ len = c->min_io_size;
-+ else
-+ len = 512;
-+ if (offs + len > c->leb_size)
-+ len = c->leb_size - offs;
-+
-+ if (!len)
-+ return 0;
-+
-+ /* Read at the head location and check it is empty flash */
-+ err = ubi_read(c->ubi, lnum, sbuf, offs, len);
-+ if (err)
-+ need_clean = 1;
-+ else {
-+ uint8_t *p = sbuf;
-+
-+ while (len--)
-+ if (*p++ != 0xff) {
-+ need_clean = 1;
-+ break;
-+ }
-+ }
-+
-+ if (need_clean) {
-+ dbg_rcvry("cleaning head at %d:%d", lnum, offs);
-+ if (offs == 0)
-+ return ubifs_leb_unmap(c, lnum);
-+ err = ubi_read(c->ubi, lnum, sbuf, 0, offs);
-+ if (err)
-+ return err;
-+ return ubi_leb_change(c->ubi, lnum, sbuf, offs, UBI_UNKNOWN);
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_recover_inl_heads - recover index and LPT heads.
-+ * @c: UBIFS file-system description object
-+ * @sbuf: LEB-sized buffer to use
-+ *
-+ * This function ensures that there is no data on the flash at the index and
-+ * LPT head locations.
-+ *
-+ * This deals with the recovery of a half-completed journal commit. UBIFS is
-+ * careful never to overwrite the last version of the index or the LPT. Because
-+ * the index and LPT are wandering trees, data from a half-completed commit will
-+ * not be referenced anywhere in UBIFS. The data will be either in LEBs that are
-+ * assumed to be empty and will be unmapped anyway before use, or in the index
-+ * and LPT heads.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
-+{
-+ int err;
-+
-+ ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY) || c->remounting_rw);
-+
-+ dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
-+ err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
-+ if (err)
-+ return err;
-+
-+ dbg_rcvry("checking LPT head at %d:%d", c->nhead_lnum, c->nhead_offs);
-+ err = recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf);
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+/**
-+ * clean_an_unclean_leb - read and write a LEB to remove corruption.
-+ * @c: UBIFS file-system description object
-+ * @ucleb: unclean LEB information
-+ * @sbuf: LEB-sized buffer to use
-+ *
-+ * This function reads a LEB up to a point pre-determined by the mount recovery,
-+ * checks the nodes, and writes the result back to the flash, thereby cleaning
-+ * off any following corruption, or non-fatal ECC errors.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int clean_an_unclean_leb(const struct ubifs_info *c,
-+ struct ubifs_unclean_leb *ucleb, void *sbuf)
-+{
-+ int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1;
-+ void *buf = sbuf;
-+
-+ dbg_rcvry("LEB %d len %d", lnum, len);
-+
-+ if (len == 0) {
-+ /* Nothing to read, just unmap it */
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ return 0;
-+ }
-+
-+ err = ubi_read(c->ubi, lnum, buf, offs, len);
-+ if (err && err != -EBADMSG)
-+ return err;
-+
-+ while (len >= 8) {
-+ int ret;
-+
-+ cond_resched();
-+
-+ /* Scan quietly until there is an error */
-+ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet);
-+
-+ if (ret == SCANNED_A_NODE) {
-+ /* A valid node, and not a padding node */
-+ struct ubifs_ch *ch = buf;
-+ int node_len;
-+
-+ node_len = ALIGN(le32_to_cpu(ch->len), 8);
-+ offs += node_len;
-+ buf += node_len;
-+ len -= node_len;
-+ continue;
-+ }
-+
-+ if (ret > 0) {
-+ /* Padding bytes or a valid padding node */
-+ offs += ret;
-+ buf += ret;
-+ len -= ret;
-+ continue;
-+ }
-+
-+ if (ret == SCANNED_EMPTY_SPACE) {
-+ ubifs_err("unexpected empty space at %d:%d",
-+ lnum, offs);
-+ return -EUCLEAN;
-+ }
-+
-+ if (quiet) {
-+ /* Redo the last scan but noisily */
-+ quiet = 0;
-+ continue;
-+ }
-+
-+ ubifs_scanned_corruption(c, lnum, offs, buf);
-+ return -EUCLEAN;
-+ }
-+
-+ /* Pad to min_io_size */
-+ len = ALIGN(ucleb->endpt, c->min_io_size);
-+ if (len > ucleb->endpt) {
-+ int pad_len = len - ALIGN(ucleb->endpt, 8);
-+
-+ if (pad_len > 0) {
-+ buf = c->sbuf + len - pad_len;
-+ ubifs_pad(c, buf, pad_len);
-+ }
-+ }
-+
-+ /* Write back the LEB atomically */
-+ err = ubi_leb_change(c->ubi, lnum, sbuf, len, UBI_UNKNOWN);
-+ if (err)
-+ return err;
-+
-+ dbg_rcvry("cleaned LEB %d", lnum);
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_clean_lebs - clean LEBs recovered during read-only mount.
-+ * @c: UBIFS file-system description object
-+ * @sbuf: LEB-sized buffer to use
-+ *
-+ * This function cleans a LEB identified during recovery that needs to be
-+ * written but was not because UBIFS was mounted read-only. This happens when
-+ * remounting to read-write mode.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf)
-+{
-+ dbg_rcvry("recovery");
-+ while (!list_empty(&c->unclean_leb_list)) {
-+ struct ubifs_unclean_leb *ucleb;
-+ int err;
-+
-+ ucleb = list_entry(c->unclean_leb_list.next,
-+ struct ubifs_unclean_leb, list);
-+ err = clean_an_unclean_leb(c, ucleb, sbuf);
-+ if (err)
-+ return err;
-+ list_del(&ucleb->list);
-+ kfree(ucleb);
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_recover_gc_lnum - recover the GC LEB number.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Out-of-place garbage collection requires always one empty LEB with which to
-+ * start garbage collection. The LEB number is recorded in c->gc_lnum and is
-+ * written to the master node on unmounting. In the case of an unclean unmount
-+ * the value of gc_lnum recorded in the master node is out of date and cannot
-+ * be used. Instead, recovery must allocate an empty LEB for this purpose.
-+ * However, there may not be enough empty space, in which case it must be
-+ * possible to GC the dirtiest LEB into the GC head LEB.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_recover_gc_lnum(struct ubifs_info *c)
-+{
-+ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
-+ struct ubifs_lprops lp;
-+ int lnum, err;
-+
-+ c->gc_lnum = -1;
-+ if (wbuf->lnum == -1) {
-+ dbg_rcvry("no GC head LEB");
-+ goto find_free;
-+ }
-+ /*
-+ * See whether the used space in the dirtiest LEB fits in the GC head
-+ * LEB.
-+ */
-+ err = ubifs_find_dirty_leb(c, &lp, c->dead_wm, 2);
-+ if (err) {
-+ if (err == -ENOSPC)
-+ dbg_err("could not find a dirty LEB");
-+ return err;
-+ }
-+ ubifs_assert(!(lp.flags & LPROPS_INDEX));
-+ lnum = lp.lnum;
-+ if (lp.free + lp.dirty == c->leb_size) {
-+ /* An empty LEB was returned */
-+ if (lp.free != c->leb_size) {
-+ err = ubifs_change_one_lp(c, lnum, c->leb_size,
-+ 0, 0, 0, 0);
-+ if (err)
-+ return err;
-+ }
-+ err = ubifs_leb_unmap(c, lnum);
-+ if (err)
-+ return err;
-+ c->gc_lnum = lnum;
-+ dbg_rcvry("allocated LEB %d for GC", lnum);
-+ return 0;
-+ }
-+ /*
-+ * There was no empty LEB so the used space in the dirtiest LEB must fit
-+ * in the GC head LEB.
-+ */
-+ if (lp.free + lp.dirty < wbuf->offs) {
-+ dbg_rcvry("LEB %d doesn't fit in GC head LEB %d:%d",
-+ lnum, wbuf->lnum, wbuf->offs);
-+ err = ubifs_return_leb(c, lnum);
-+ if (err)
-+ return err;
-+ goto find_free;
-+ }
-+ /* It fits, so GC it - use locking to keep 'ubifs_assert()' happy */
-+ dbg_rcvry("GC'ing LEB %d", lnum);
-+ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
-+ err = ubifs_garbage_collect_leb(c, &lp);
-+ if (err >= 0) {
-+ int err2 = ubifs_wbuf_sync_nolock(wbuf);
-+
-+ if (err2)
-+ err = err2;
-+ }
-+ mutex_unlock(&wbuf->io_mutex);
-+ if (err < 0) {
-+ dbg_err("GC failed, error %d", err);
-+ if (err == -EAGAIN)
-+ err = -EINVAL;
-+ return err;
-+ }
-+ if (err != LEB_RETAINED) {
-+ dbg_err("GC returned %d", err);
-+ return -EINVAL;
-+ }
-+ err = ubifs_leb_unmap(c, c->gc_lnum);
-+ if (err)
-+ return err;
-+ dbg_rcvry("allocated LEB %d for GC", lnum);
-+ return 0;
-+
-+find_free:
-+ /*
-+ * There is no GC head LEB or the free space in the GC head LEB is too
-+ * small. Allocate gc_lnum by calling 'ubifs_find_free_leb_for_idx()' so
-+ * GC is not run.
-+ */
-+ lnum = ubifs_find_free_leb_for_idx(c);
-+ if (lnum < 0) {
-+ dbg_err("could not find an empty LEB");
-+ return lnum;
-+ }
-+ /* And reset the index flag */
-+ err = ubifs_change_one_lp(c, lnum, -1, -1, 0, LPROPS_INDEX, 0);
-+ if (err)
-+ return err;
-+ c->gc_lnum = lnum;
-+ dbg_rcvry("allocated LEB %d for GC", lnum);
-+ return 0;
-+}
-+
-+/**
-+ * struct size_entry - inode size information for recovery.
-+ * @rb: link in the RB-tree of sizes
-+ * @inum: inode number
-+ * @i_size: size on inode
-+ * @d_size: maximum size based on data nodes
-+ * @exists: indicates whether the inode exists
-+ * @inode: inode if pinned in memory awaiting rw mode to fix it
-+ */
-+struct size_entry {
-+ struct rb_node rb;
-+ ino_t inum;
-+ loff_t i_size;
-+ loff_t d_size;
-+ int exists;
-+ struct inode *inode;
-+};
-+
-+/**
-+ * add_ino - add an entry to the size tree.
-+ * @c: UBIFS file-system description object
-+ * @inum: inode number
-+ * @i_size: size on inode
-+ * @d_size: maximum size based on data nodes
-+ * @exists: indicates whether the inode exists
-+ */
-+static int add_ino(struct ubifs_info *c, ino_t inum, loff_t i_size,
-+ loff_t d_size, int exists)
-+{
-+ struct rb_node **p = &c->size_tree.rb_node, *parent = NULL;
-+ struct size_entry *e;
-+
-+ while (*p) {
-+ parent = *p;
-+ e = rb_entry(parent, struct size_entry, rb);
-+ if (inum < e->inum)
-+ p = &(*p)->rb_left;
-+ else
-+ p = &(*p)->rb_right;
-+ }
-+
-+ e = kzalloc(sizeof(struct size_entry), GFP_KERNEL);
-+ if (!e)
-+ return -ENOMEM;
-+
-+ e->inum = inum;
-+ e->i_size = i_size;
-+ e->d_size = d_size;
-+ e->exists = exists;
-+
-+ rb_link_node(&e->rb, parent, p);
-+ rb_insert_color(&e->rb, &c->size_tree);
-+
-+ return 0;
-+}
-+
-+/**
-+ * find_ino - find an entry on the size tree.
-+ * @c: UBIFS file-system description object
-+ * @inum: inode number
-+ */
-+static struct size_entry *find_ino(struct ubifs_info *c, ino_t inum)
-+{
-+ struct rb_node *p = c->size_tree.rb_node;
-+ struct size_entry *e;
-+
-+ while (p) {
-+ e = rb_entry(p, struct size_entry, rb);
-+ if (inum < e->inum)
-+ p = p->rb_left;
-+ else if (inum > e->inum)
-+ p = p->rb_right;
-+ else
-+ return e;
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * remove_ino - remove an entry from the size tree.
-+ * @c: UBIFS file-system description object
-+ * @inum: inode number
-+ */
-+static void remove_ino(struct ubifs_info *c, ino_t inum)
-+{
-+ struct size_entry *e = find_ino(c, inum);
-+
-+ if (!e)
-+ return;
-+ rb_erase(&e->rb, &c->size_tree);
-+ kfree(e);
-+}
-+
-+/**
-+ * ubifs_destroy_size_tree - free resources related to the size tree.
-+ * @c: UBIFS file-system description object
-+ */
-+void ubifs_destroy_size_tree(struct ubifs_info *c)
-+{
-+ struct rb_node *this = c->size_tree.rb_node;
-+ struct size_entry *e;
-+
-+ while (this) {
-+ if (this->rb_left) {
-+ this = this->rb_left;
-+ continue;
-+ } else if (this->rb_right) {
-+ this = this->rb_right;
-+ continue;
-+ }
-+ e = rb_entry(this, struct size_entry, rb);
-+ if (e->inode)
-+ iput(e->inode);
-+ this = rb_parent(this);
-+ if (this) {
-+ if (this->rb_left == &e->rb)
-+ this->rb_left = NULL;
-+ else
-+ this->rb_right = NULL;
-+ }
-+ kfree(e);
-+ }
-+ c->size_tree = RB_ROOT;
-+}
-+
-+/**
-+ * ubifs_recover_size_accum - accumulate inode sizes for recovery.
-+ * @c: UBIFS file-system description object
-+ * @key: node key
-+ * @deletion: node is for a deletion
-+ * @new_size: inode size
-+ *
-+ * This function has two purposes:
-+ * 1) to ensure there are no data nodes that fall outside the inode size
-+ * 2) to ensure there are no data nodes for inodes that do not exist
-+ * To accomplish those purposes, a rb-tree is constructed containing an entry
-+ * for each inode number in the journal that has not been deleted, and recording
-+ * the size from the inode node, the maximum size of any data node (also altered
-+ * by truncations) and a flag indicating a inode number for which no inode node
-+ * was present in the journal.
-+ *
-+ * Note that there is still the possibility that there are data nodes that have
-+ * been committed that are beyond the inode size, however the only way to find
-+ * them would be to scan the entire index. Alternatively, some provision could
-+ * be made to record the size of inodes at the start of commit, which would seem
-+ * very cumbersome for a scenario that is quite unlikely and the only negative
-+ * consequence of which is wasted space.
-+ *
-+ * This functions returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
-+ int deletion, loff_t new_size)
-+{
-+ ino_t inum = key_ino(c, key);
-+ struct size_entry *e;
-+ int err;
-+
-+ switch (key_type(c, key)) {
-+ case UBIFS_INO_KEY:
-+ if (deletion)
-+ remove_ino(c, inum);
-+ else {
-+ e = find_ino(c, inum);
-+ if (e) {
-+ e->i_size = new_size;
-+ e->exists = 1;
-+ } else {
-+ err = add_ino(c, inum, new_size, 0, 1);
-+ if (err)
-+ return err;
-+ }
-+ }
-+ break;
-+ case UBIFS_DATA_KEY:
-+ e = find_ino(c, inum);
-+ if (e) {
-+ if (new_size > e->d_size)
-+ e->d_size = new_size;
-+ } else {
-+ err = add_ino(c, inum, 0, new_size, 0);
-+ if (err)
-+ return err;
-+ }
-+ break;
-+ case UBIFS_TRUN_KEY:
-+ e = find_ino(c, inum);
-+ if (e)
-+ e->d_size = new_size;
-+ break;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * fix_size_in_place - fix inode size in place on flash.
-+ * @c: UBIFS file-system description object
-+ * @e: inode size information for recovery
-+ */
-+static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
-+{
-+ struct ubifs_ino_node *ino = c->sbuf;
-+ unsigned char *p;
-+ union ubifs_key key;
-+ int err, lnum, offs, len;
-+ loff_t i_size;
-+ uint32_t crc;
-+
-+ /* Locate the inode node LEB number and offset */
-+ ino_key_init(c, &key, e->inum);
-+ err = ubifs_tnc_locate(c, &key, ino, &lnum, &offs);
-+ if (err)
-+ goto out;
-+ /*
-+ * If the size recorded on the inode node is greater than the size that
-+ * was calculated from nodes in the journal then don't change the inode.
-+ */
-+ i_size = le64_to_cpu(ino->size);
-+ if (i_size >= e->d_size)
-+ return 0;
-+ /* Read the LEB */
-+ err = ubi_read(c->ubi, lnum, c->sbuf, 0, c->leb_size);
-+ if (err)
-+ goto out;
-+ /* Change the size field and recalculate the CRC */
-+ ino = c->sbuf + offs;
-+ ino->size = cpu_to_le64(e->d_size);
-+ len = le32_to_cpu(ino->ch.len);
-+ crc = crc32(UBIFS_CRC32_INIT, (void *)ino + 8, len - 8);
-+ ino->ch.crc = cpu_to_le32(crc);
-+ /* Work out where data in the LEB ends and free space begins */
-+ p = c->sbuf;
-+ len = c->leb_size - 1;
-+ while (p[len] == 0xff)
-+ len -= 1;
-+ len = ALIGN(len + 1, c->min_io_size);
-+ /* Atomically write the fixed LEB back again */
-+ err = ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN);
-+ if (err)
-+ goto out;
-+ dbg_rcvry("inode %lu at %d:%d size %lld -> %lld ", e->inum, lnum, offs,
-+ i_size, e->d_size);
-+ return 0;
-+
-+out:
-+ ubifs_warn("inode %lu failed to fix size %lld -> %lld error %d",
-+ e->inum, e->i_size, e->d_size, err);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_recover_size - recover inode size.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function attempts to fix inode size discrepancies identified by the
-+ * 'ubifs_recover_size_accum()' function.
-+ *
-+ * This functions returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_recover_size(struct ubifs_info *c)
-+{
-+ struct rb_node *this = rb_first(&c->size_tree);
-+
-+ while (this) {
-+ struct size_entry *e;
-+ int err;
-+
-+ e = rb_entry(this, struct size_entry, rb);
-+ if (!e->exists) {
-+ union ubifs_key key;
-+
-+ ino_key_init(c, &key, e->inum);
-+ err = ubifs_tnc_lookup(c, &key, c->sbuf);
-+ if (err && err != -ENOENT)
-+ return err;
-+ if (err == -ENOENT) {
-+ /* Remove data nodes that have no inode */
-+ dbg_rcvry("removing ino %lu", e->inum);
-+ err = ubifs_tnc_remove_ino(c, e->inum);
-+ if (err)
-+ return err;
-+ /*
-+ * If we later unmount cleanly without
-+ * committing, the TNC changes will be lost,
-+ * hence we set a flag to ensure a commit is
-+ * done.
-+ */
-+ c->recovery_needs_commit = 1;
-+ } else {
-+ struct ubifs_ino_node *ino = c->sbuf;
-+
-+ e->exists = 1;
-+ e->i_size = le64_to_cpu(ino->size);
-+ }
-+ }
-+ if (e->exists && e->i_size < e->d_size) {
-+ if (!e->inode && (c->vfs_sb->s_flags & MS_RDONLY)) {
-+ /* Fix the inode size and pin it in memory */
-+ struct inode *inode;
-+
-+ inode = ubifs_iget(c->vfs_sb, e->inum);
-+ if (IS_ERR(inode))
-+ return PTR_ERR(inode);
-+ if (inode->i_size < e->d_size) {
-+ dbg_rcvry("ino %lu size %lld -> %lld",
-+ e->inum, e->d_size,
-+ inode->i_size);
-+ inode->i_size = e->d_size;
-+ e->inode = inode;
-+ this = rb_next(this);
-+ continue;
-+ }
-+ iput(inode);
-+ } else {
-+ /* Fix the size in place */
-+ err = fix_size_in_place(c, e);
-+ if (err) {
-+ if (e->inode)
-+ /*
-+ * We have changed the inode
-+ * size in memory but failed to
-+ * fix it on flash. Mark it
-+ * dirty without budgeting, and
-+ * hope we don't run out of
-+ * space.
-+ */
-+ mark_inode_dirty_sync(e->inode);
-+ /*
-+ * We consider that failing to recover
-+ * the size is not fatal, because it
-+ * only affects files that were being
-+ * written without synchronization and
-+ * the only down side is that some space
-+ * may be wasted.
-+ */
-+ err = 0;
-+ }
-+ if (e->inode)
-+ iput(e->inode);
-+ }
-+ }
-+ this = rb_next(this);
-+ rb_erase(&e->rb, &c->size_tree);
-+ kfree(e);
-+ }
-+ return 0;
-+}
---- linux-2.6.24.7.old/fs/ubifs/replay.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/replay.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1049 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file contains journal replay code. It runs when the file-system is being
-+ * mounted and requires no locking.
-+ *
-+ * The larger is the journal, the longer it takes to scan it, so the longer it
-+ * takes to mount UBIFS. This is why the journal has limited size which may be
-+ * changed depending on the system requirements. But a larger journal gives
-+ * faster I/O speed because it writes the index less frequently. So this is a
-+ * trade-off. Also, the journal is indexed by the in-memory index (TNC), so the
-+ * larger is the journal, the more memory its index may consume.
-+ */
-+
-+#include "ubifs.h"
-+
-+/*
-+ * Replay flags.
-+ *
-+ * REPLAY_DELETION: node was deleted
-+ * REPLAY_REF: node is a reference node
-+ */
-+enum {
-+ REPLAY_DELETION = 1,
-+ REPLAY_REF = 2,
-+};
-+
-+/**
-+ * struct replay_entry - replay tree entry.
-+ * @lnum: logical eraseblock number of the node
-+ * @offs: node offset
-+ * @len: node length
-+ * @sqnum: node sequence number
-+ * @flags: replay flags
-+ * @rb: links the replay tree
-+ * @key: node key
-+ * @nm: directory entry name
-+ * @old_size: truncation old size
-+ * @new_size: truncation new size
-+ * @free: amount of free space in a bud
-+ * @dirty: amount of dirty space in a bud from padding and deletion nodes
-+ *
-+ * UBIFS journal replay must compare node sequence numbers, which means it must
-+ * build a tree of node information to insert into the TNC.
-+ */
-+struct replay_entry {
-+ int lnum;
-+ int offs;
-+ int len;
-+ unsigned long long sqnum;
-+ int flags;
-+ struct rb_node rb;
-+ union ubifs_key key;
-+ union {
-+ struct qstr nm;
-+ struct {
-+ loff_t old_size;
-+ loff_t new_size;
-+ };
-+ struct {
-+ int free;
-+ int dirty;
-+ };
-+ };
-+};
-+
-+/**
-+ * struct bud_entry - entry in the list of buds to replay.
-+ * @list: next bud in the list
-+ * @bud: bud description object
-+ * @free: free bytes in the bud
-+ * @sqnum: reference node sequence number
-+ */
-+struct bud_entry {
-+ struct list_head list;
-+ struct ubifs_bud *bud;
-+ int free;
-+ unsigned long long sqnum;
-+};
-+
-+/**
-+ * set_bud_lprops - set free and dirty space used by a bud.
-+ * @c: UBIFS file-system description object
-+ * @r: replay entry of bud
-+ */
-+static int set_bud_lprops(struct ubifs_info *c, struct replay_entry *r)
-+{
-+ const struct ubifs_lprops *lp;
-+ int err = 0, dirty;
-+
-+ ubifs_get_lprops(c);
-+
-+ lp = ubifs_lpt_lookup_dirty(c, r->lnum);
-+ if (IS_ERR(lp)) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+
-+ dirty = lp->dirty;
-+ if (r->offs == 0 && (lp->free != c->leb_size || lp->dirty != 0)) {
-+ dbg_mnt("bud LEB %d was GC'd (%d free, %d dirty)", r->lnum,
-+ lp->free, lp->dirty);
-+ dbg_gc("bud LEB %d was GC'd (%d free, %d dirty)", r->lnum,
-+ lp->free, lp->dirty);
-+ dirty -= c->leb_size - lp->free;
-+ if (dirty != 0)
-+ dbg_msg("LEB %d lp: %d free %d dirty "
-+ "replay: %d free %d dirty", r->lnum, lp->free,
-+ lp->dirty, r->free, r->dirty);
-+ }
-+ lp = ubifs_change_lp(c, lp, r->free, dirty + r->dirty,
-+ lp->flags | LPROPS_TAKEN, 0);
-+ if (IS_ERR(lp)) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+out:
-+ ubifs_release_lprops(c);
-+ return err;
-+}
-+
-+/**
-+ * trun_remove_range - apply a replay entry for a truncation to the TNC.
-+ * @c: UBIFS file-system description object
-+ * @r: replay entry of truncation
-+ */
-+static int trun_remove_range(struct ubifs_info *c, struct replay_entry *r)
-+{
-+ unsigned min_blk, max_blk;
-+ union ubifs_key min_key, max_key;
-+ ino_t ino;
-+
-+ min_blk = r->new_size / UBIFS_BLOCK_SIZE;
-+ if (r->new_size & (UBIFS_BLOCK_SIZE - 1))
-+ min_blk += 1;
-+
-+ max_blk = r->old_size / UBIFS_BLOCK_SIZE;
-+ if ((r->old_size & (UBIFS_BLOCK_SIZE - 1)) == 0)
-+ max_blk -= 1;
-+
-+ ino = key_ino(c, &r->key);
-+
-+ data_key_init(c, &min_key, ino, min_blk);
-+ data_key_init(c, &max_key, ino, max_blk);
-+
-+ return ubifs_tnc_remove_range(c, &min_key, &max_key);
-+}
-+
-+/**
-+ * apply_replay_entry - apply a replay entry to the TNC.
-+ * @c: UBIFS file-system description object
-+ * @r: replay entry to apply
-+ *
-+ * Apply a replay entry to the TNC.
-+ */
-+static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r)
-+{
-+ int err, deletion = ((r->flags & REPLAY_DELETION) != 0);
-+
-+ dbg_mnt("LEB %d:%d len %d flgs %d sqnum %llu %s", r->lnum,
-+ r->offs, r->len, r->flags, r->sqnum, DBGKEY(&r->key));
-+
-+ /* Set c->replay_sqnum to help deal with dangling branches. */
-+ c->replay_sqnum = r->sqnum;
-+
-+ if (r->flags & REPLAY_REF)
-+ err = set_bud_lprops(c, r);
-+ else if (is_hash_key(c, &r->key)) {
-+ if (deletion)
-+ err = ubifs_tnc_remove_nm(c, &r->key, &r->nm);
-+ else
-+ err = ubifs_tnc_add_nm(c, &r->key, r->lnum, r->offs,
-+ r->len, &r->nm);
-+ } else {
-+ if (deletion)
-+ switch (key_type(c, &r->key)) {
-+ case UBIFS_INO_KEY:
-+ {
-+ ino_t inum = key_ino(c, &r->key);
-+
-+ err = ubifs_tnc_remove_ino(c, inum);
-+ break;
-+ }
-+ case UBIFS_TRUN_KEY:
-+ err = trun_remove_range(c, r);
-+ break;
-+ default:
-+ err = ubifs_tnc_remove(c, &r->key);
-+ break;
-+ }
-+ else
-+ err = ubifs_tnc_add(c, &r->key, r->lnum, r->offs,
-+ r->len);
-+ if (err)
-+ return err;
-+
-+ if (c->need_recovery)
-+ err = ubifs_recover_size_accum(c, &r->key, deletion,
-+ r->new_size);
-+ }
-+
-+ return err;
-+}
-+
-+/**
-+ * destroy_replay_tree - destroy the replay.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Destroy the replay tree.
-+ */
-+static void destroy_replay_tree(struct ubifs_info *c)
-+{
-+ struct rb_node *this = c->replay_tree.rb_node;
-+ struct replay_entry *r;
-+
-+ while (this) {
-+ if (this->rb_left) {
-+ this = this->rb_left;
-+ continue;
-+ } else if (this->rb_right) {
-+ this = this->rb_right;
-+ continue;
-+ }
-+ r = rb_entry(this, struct replay_entry, rb);
-+ this = rb_parent(this);
-+ if (this) {
-+ if (this->rb_left == &r->rb)
-+ this->rb_left = NULL;
-+ else
-+ this->rb_right = NULL;
-+ }
-+ if (is_hash_key(c, &r->key))
-+ kfree(r->nm.name);
-+ kfree(r);
-+ }
-+ c->replay_tree = RB_ROOT;
-+}
-+
-+/**
-+ * apply_replay_tree - apply the replay tree to the TNC.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Apply the replay tree.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+static int apply_replay_tree(struct ubifs_info *c)
-+{
-+ struct rb_node *this = rb_first(&c->replay_tree);
-+
-+ while (this) {
-+ struct replay_entry *r;
-+ int err;
-+
-+ cond_resched();
-+
-+ r = rb_entry(this, struct replay_entry, rb);
-+ err = apply_replay_entry(c, r);
-+ if (err)
-+ return err;
-+ this = rb_next(this);
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * insert_node - insert a node to the replay tree.
-+ * @c: UBIFS file-system description object
-+ * @lnum: node logical eraseblock number
-+ * @offs: node offset
-+ * @len: node length
-+ * @key: node key
-+ * @sqnum: sequence number
-+ * @deletion: non-zero if this is a deletion
-+ * @used: number of bytes in use in a LEB
-+ * @old_size: truncation old size
-+ * @new_size: truncation new size
-+ *
-+ * This function inserts a scanned non-direntry node to the replay tree. The
-+ * replay tree is an RB-tree containing @struct replay_entry elements which are
-+ * indexed by the sequence number. The replay tree is applied at the very end
-+ * of the replay process. Since the tree is sorted in sequence number order,
-+ * the older modifications are applied first. This function returns zero in
-+ * case of success and a negative error code in case of failure.
-+ */
-+static int insert_node(struct ubifs_info *c, int lnum, int offs, int len,
-+ union ubifs_key *key, unsigned long long sqnum,
-+ int deletion, int *used, loff_t old_size,
-+ loff_t new_size)
-+{
-+ struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL;
-+ struct replay_entry *r;
-+
-+ if (key_ino(c, key) >= c->highest_inum)
-+ c->highest_inum = key_ino(c, key);
-+
-+ dbg_mnt("add LEB %d:%d, key %s", lnum, offs, DBGKEY(key));
-+ while (*p) {
-+ parent = *p;
-+ r = rb_entry(parent, struct replay_entry, rb);
-+ if (sqnum < r->sqnum) {
-+ p = &(*p)->rb_left;
-+ continue;
-+ } else if (sqnum > r->sqnum) {
-+ p = &(*p)->rb_right;
-+ continue;
-+ }
-+ ubifs_err("duplicate sqnum in replay");
-+ return -EINVAL;
-+ }
-+
-+ r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL);
-+ if (!r)
-+ return -ENOMEM;
-+
-+ if (!deletion)
-+ *used += ALIGN(len, 8);
-+ r->lnum = lnum;
-+ r->offs = offs;
-+ r->len = len;
-+ r->sqnum = sqnum;
-+ r->flags = (deletion ? REPLAY_DELETION : 0);
-+ r->old_size = old_size;
-+ r->new_size = new_size;
-+ key_copy(c, key, &r->key);
-+
-+ rb_link_node(&r->rb, parent, p);
-+ rb_insert_color(&r->rb, &c->replay_tree);
-+ return 0;
-+}
-+
-+/**
-+ * insert_dent - insert a directory entry node into the replay tree.
-+ * @c: UBIFS file-system description object
-+ * @lnum: node logical eraseblock number
-+ * @offs: node offset
-+ * @len: node length
-+ * @key: node key
-+ * @name: directory entry name
-+ * @nlen: directory entry name length
-+ * @sqnum: sequence number
-+ * @deletion: non-zero if this is a deletion
-+ * @used: number of bytes in use in a LEB
-+ *
-+ * This function inserts a scanned directory entry node to the replay tree.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ *
-+ * This function is also used for extended attribute entries because they are
-+ * implemented as directory entry nodes.
-+ */
-+static int insert_dent(struct ubifs_info *c, int lnum, int offs, int len,
-+ union ubifs_key *key, const char *name, int nlen,
-+ unsigned long long sqnum, int deletion, int *used)
-+{
-+ struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL;
-+ struct replay_entry *r;
-+ char *nbuf;
-+
-+ if (key_ino(c, key) >= c->highest_inum)
-+ c->highest_inum = key_ino(c, key);
-+
-+ dbg_mnt("add LEB %d:%d, key %s", lnum, offs, DBGKEY(key));
-+ while (*p) {
-+ parent = *p;
-+ r = rb_entry(parent, struct replay_entry, rb);
-+ if (sqnum < r->sqnum) {
-+ p = &(*p)->rb_left;
-+ continue;
-+ }
-+ if (sqnum > r->sqnum) {
-+ p = &(*p)->rb_right;
-+ continue;
-+ }
-+ ubifs_err("duplicate sqnum in replay");
-+ return -EINVAL;
-+ }
-+
-+ r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL);
-+ if (!r)
-+ return -ENOMEM;
-+ nbuf = kmalloc(nlen + 1, GFP_KERNEL);
-+ if (!nbuf) {
-+ kfree(r);
-+ return -ENOMEM;
-+ }
-+
-+ if (!deletion)
-+ *used += ALIGN(len, 8);
-+ r->lnum = lnum;
-+ r->offs = offs;
-+ r->len = len;
-+ r->sqnum = sqnum;
-+ r->nm.len = nlen;
-+ memcpy(nbuf, name, nlen);
-+ nbuf[nlen] = '\0';
-+ r->nm.name = nbuf;
-+ r->flags = (deletion ? REPLAY_DELETION : 0);
-+ key_copy(c, key, &r->key);
-+
-+ ubifs_assert(!*p);
-+ rb_link_node(&r->rb, parent, p);
-+ rb_insert_color(&r->rb, &c->replay_tree);
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_validate_entry - validate directory or extended attribute entry node.
-+ * @c: UBIFS file-system description object
-+ * @dent: the node to validate
-+ *
-+ * This function validates directory or extended attribute entry node @dent.
-+ * Returns zero if the node is all right and a %-EINVAL if not.
-+ */
-+int ubifs_validate_entry(struct ubifs_info *c,
-+ const struct ubifs_dent_node *dent)
-+{
-+ int key_type = key_type_flash(c, dent->key);
-+ int nlen = le16_to_cpu(dent->nlen);
-+
-+ if (le32_to_cpu(dent->ch.len) != nlen + UBIFS_DENT_NODE_SZ + 1 ||
-+ dent->type >= UBIFS_ITYPES_CNT ||
-+ nlen > UBIFS_MAX_NLEN || dent->name[nlen] != 0 ||
-+ strnlen(dent->name, nlen) != nlen ||
-+ le64_to_cpu(dent->inum) > MAX_INUM) {
-+ ubifs_err("bad %s node", key_type == UBIFS_DENT_KEY ?
-+ "directory entry" : "extended attribute entry");
-+ return -EINVAL;
-+ }
-+
-+ if (key_type != UBIFS_DENT_KEY && key_type != UBIFS_XENT_KEY) {
-+ ubifs_err("bad key type %d", key_type);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * replay_bud - replay a bud logical eraseblock.
-+ * @c: UBIFS file-system description object
-+ * @lnum: bud logical eraseblock number to replay
-+ * @offs: bud start offset
-+ * @jhead: journal head to which this bud belongs
-+ * @free: amount of free space in the bud is returned here
-+ * @dirty: amount of dirty space from padding and deletion nodes is returned
-+ * here
-+ *
-+ * This function returns zero in case of success and a negative error code in
-+ * case of failure.
-+ */
-+static int replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
-+ int *free, int *dirty)
-+{
-+ int err = 0, used = 0;
-+ struct ubifs_scan_leb *sleb;
-+ struct ubifs_scan_node *snod;
-+ struct ubifs_bud *bud;
-+
-+ dbg_mnt("replay bud LEB %d, head %d", lnum, jhead);
-+ if (c->need_recovery)
-+ sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf, jhead != GCHD);
-+ else
-+ sleb = ubifs_scan(c, lnum, offs, c->sbuf);
-+ if (IS_ERR(sleb))
-+ return PTR_ERR(sleb);
-+
-+ /*
-+ * The bud does not have to start from offset zero - the beginning of
-+ * the 'lnum' LEB may contain previously committed data. One of the
-+ * things we have to do in replay is to correctly update lprops with
-+ * newer information about this LEB.
-+ *
-+ * At this point lprops thinks that this LEB has 'c->leb_size - offs'
-+ * bytes of free space because it only contain information about
-+ * committed data.
-+ *
-+ * But we know that real amount of free space is 'c->leb_size -
-+ * sleb->endpt', and the space in the 'lnum' LEB between 'offs' and
-+ * 'sleb->endpt' is used by bud data. We have to correctly calculate
-+ * how much of these data are dirty and update lprops with this
-+ * information.
-+ *
-+ * The dirt in that LEB region is comprised of padding nodes, deletion
-+ * nodes, truncation nodes and nodes which are obsoleted by subsequent
-+ * nodes in this LEB. So instead of calculating clean space, we
-+ * calculate used space ('used' variable).
-+ */
-+
-+ list_for_each_entry(snod, &sleb->nodes, list) {
-+ int deletion = 0;
-+
-+ cond_resched();
-+
-+ if (snod->sqnum >= SQNUM_WATERMARK) {
-+ ubifs_err("file system's life ended");
-+ goto out_dump;
-+ }
-+
-+ if (snod->sqnum > c->max_sqnum)
-+ c->max_sqnum = snod->sqnum;
-+
-+ switch (snod->type) {
-+ case UBIFS_INO_NODE:
-+ {
-+ struct ubifs_ino_node *ino = snod->node;
-+ loff_t new_size = le64_to_cpu(ino->size);
-+
-+ if (le32_to_cpu(ino->nlink) == 0)
-+ deletion = 1;
-+ err = insert_node(c, lnum, snod->offs, snod->len,
-+ &snod->key, snod->sqnum, deletion,
-+ &used, 0, new_size);
-+ break;
-+ }
-+ case UBIFS_DATA_NODE:
-+ {
-+ struct ubifs_data_node *dn = snod->node;
-+ loff_t new_size = le32_to_cpu(dn->size) +
-+ key_block(c, &snod->key) *
-+ UBIFS_BLOCK_SIZE;
-+
-+ err = insert_node(c, lnum, snod->offs, snod->len,
-+ &snod->key, snod->sqnum, deletion,
-+ &used, 0, new_size);
-+ break;
-+ }
-+ case UBIFS_DENT_NODE:
-+ case UBIFS_XENT_NODE:
-+ {
-+ struct ubifs_dent_node *dent = snod->node;
-+
-+ err = ubifs_validate_entry(c, dent);
-+ if (err)
-+ goto out_dump;
-+
-+ err = insert_dent(c, lnum, snod->offs, snod->len,
-+ &snod->key, dent->name,
-+ le16_to_cpu(dent->nlen), snod->sqnum,
-+ !le64_to_cpu(dent->inum), &used);
-+ break;
-+ }
-+ case UBIFS_TRUN_NODE:
-+ {
-+ struct ubifs_trun_node *trun = snod->node;
-+ loff_t old_size = le64_to_cpu(trun->old_size);
-+ loff_t new_size = le64_to_cpu(trun->new_size);
-+
-+ /* Validate truncation node */
-+ if (old_size < 0 || old_size > c->max_inode_sz ||
-+ new_size < 0 || new_size > c->max_inode_sz ||
-+ old_size <= new_size) {
-+ ubifs_err("bad truncation node");
-+ goto out_dump;
-+ }
-+
-+ err = insert_node(c, lnum, snod->offs, snod->len,
-+ &snod->key, snod->sqnum, 1, &used,
-+ old_size, new_size);
-+ break;
-+ }
-+ default:
-+ ubifs_err("unexpected node type %d in bud LEB %d:%d",
-+ snod->type, lnum, snod->offs);
-+ err = -EINVAL;
-+ goto out_dump;
-+ }
-+ if (err)
-+ goto out;
-+ }
-+
-+ bud = ubifs_search_bud(c, lnum);
-+ if (!bud)
-+ BUG();
-+
-+ ubifs_assert(sleb->endpt - offs >= used);
-+ ubifs_assert(sleb->endpt % c->min_io_size == 0);
-+
-+ if (sleb->endpt + c->min_io_size <= c->leb_size &&
-+ !(c->vfs_sb->s_flags & MS_RDONLY))
-+ err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
-+ sleb->endpt, UBI_SHORTTERM);
-+
-+ *dirty = sleb->endpt - offs - used;
-+ *free = c->leb_size - sleb->endpt;
-+
-+out:
-+ ubifs_scan_destroy(sleb);
-+ return err;
-+
-+out_dump:
-+ ubifs_err("bad node is at LEB %d:%d", lnum, snod->offs);
-+ dbg_dump_node(c, snod->node);
-+ ubifs_scan_destroy(sleb);
-+ return -EINVAL;
-+}
-+
-+/**
-+ * insert_ref_node - insert a reference node to the replay tree.
-+ * @c: UBIFS file-system description object
-+ * @lnum: node logical eraseblock number
-+ * @offs: node offset
-+ * @sqnum: sequence number
-+ * @free: amount of free space in bud
-+ * @dirty: amount of dirty space from padding and deletion nodes
-+ *
-+ * This function inserts a reference node to the replay tree and returns zero
-+ * in case of success ort a negative error code in case of failure.
-+ */
-+static int insert_ref_node(struct ubifs_info *c, int lnum, int offs,
-+ unsigned long long sqnum, int free, int dirty)
-+{
-+ struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL;
-+ struct replay_entry *r;
-+
-+ dbg_mnt("add ref LEB %d:%d", lnum, offs);
-+ while (*p) {
-+ parent = *p;
-+ r = rb_entry(parent, struct replay_entry, rb);
-+ if (sqnum < r->sqnum) {
-+ p = &(*p)->rb_left;
-+ continue;
-+ } else if (sqnum > r->sqnum) {
-+ p = &(*p)->rb_right;
-+ continue;
-+ }
-+ ubifs_err("duplicate sqnum in replay tree");
-+ return -EINVAL;
-+ }
-+
-+ r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL);
-+ if (!r)
-+ return -ENOMEM;
-+
-+ r->lnum = lnum;
-+ r->offs = offs;
-+ r->sqnum = sqnum;
-+ r->flags = REPLAY_REF;
-+ r->free = free;
-+ r->dirty = dirty;
-+
-+ rb_link_node(&r->rb, parent, p);
-+ rb_insert_color(&r->rb, &c->replay_tree);
-+ return 0;
-+}
-+
-+/**
-+ * replay_buds - replay all buds.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns zero in case of success and a negative error code in
-+ * case of failure.
-+ */
-+static int replay_buds(struct ubifs_info *c)
-+{
-+ struct bud_entry *b;
-+ int err, uninitialized_var(free), uninitialized_var(dirty);
-+
-+ list_for_each_entry(b, &c->replay_buds, list) {
-+ err = replay_bud(c, b->bud->lnum, b->bud->start, b->bud->jhead,
-+ &free, &dirty);
-+ if (err)
-+ return err;
-+ err = insert_ref_node(c, b->bud->lnum, b->bud->start, b->sqnum,
-+ free, dirty);
-+ if (err)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * destroy_bud_list - destroy the list of buds to replay.
-+ * @c: UBIFS file-system description object
-+ */
-+static void destroy_bud_list(struct ubifs_info *c)
-+{
-+ struct bud_entry *b;
-+
-+ while (!list_empty(&c->replay_buds)) {
-+ b = list_entry(c->replay_buds.next, struct bud_entry, list);
-+ list_del(&b->list);
-+ kfree(b);
-+ }
-+}
-+
-+/**
-+ * add_replay_bud - add a bud to the list of buds to replay.
-+ * @c: UBIFS file-system description object
-+ * @lnum: bud logical eraseblock number to replay
-+ * @offs: bud start offset
-+ * @jhead: journal head to which this bud belongs
-+ * @sqnum: reference node sequence number
-+ *
-+ * This function returns zero in case of success and a negative error code in
-+ * case of failure.
-+ */
-+static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
-+ unsigned long long sqnum)
-+{
-+ struct ubifs_bud *bud;
-+ struct bud_entry *b;
-+
-+ dbg_mnt("add replay bud LEB %d:%d, head %d", lnum, offs, jhead);
-+
-+ bud = kmalloc(sizeof(struct ubifs_bud), GFP_KERNEL);
-+ if (!bud)
-+ return -ENOMEM;
-+
-+ b = kmalloc(sizeof(struct bud_entry), GFP_KERNEL);
-+ if (!b) {
-+ kfree(bud);
-+ return -ENOMEM;
-+ }
-+
-+ bud->lnum = lnum;
-+ bud->start = offs;
-+ bud->jhead = jhead;
-+ ubifs_add_bud(c, bud);
-+
-+ b->bud = bud;
-+ b->sqnum = sqnum;
-+ list_add_tail(&b->list, &c->replay_buds);
-+
-+ return 0;
-+}
-+
-+/**
-+ * validate_ref - validate a reference node.
-+ * @c: UBIFS file-system description object
-+ * @ref: the reference node to validate
-+ * @ref_lnum: LEB number of the reference node
-+ * @ref_offs: reference node offset
-+ *
-+ * This function returns %1 if a bud reference already exists for the LEB. %0 is
-+ * returned if the reference node is new, otherwise %-EINVAL is returned if
-+ * validation failed.
-+ */
-+static int validate_ref(struct ubifs_info *c, const struct ubifs_ref_node *ref)
-+{
-+ struct ubifs_bud *bud;
-+ int lnum = le32_to_cpu(ref->lnum);
-+ unsigned int offs = le32_to_cpu(ref->offs);
-+ unsigned int jhead = le32_to_cpu(ref->jhead);
-+
-+ /*
-+ * ref->offs may point to the end of LEB when the journal head points
-+ * to the end of LEB and we write reference node for it during commit.
-+ * So this is why we require 'offs > c->leb_size'.
-+ */
-+ if (jhead >= c->jhead_cnt || lnum >= c->leb_cnt ||
-+ lnum < c->main_first || offs > c->leb_size ||
-+ offs & (c->min_io_size - 1))
-+ return -EINVAL;
-+
-+ /* Make sure we have not already looked at this bud */
-+ bud = ubifs_search_bud(c, lnum);
-+ if (bud) {
-+ if (bud->jhead == jhead && bud->start <= offs)
-+ return 1;
-+ ubifs_err("bud at LEB %d:%d was already referred", lnum, offs);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * replay_log_leb - replay a log logical eraseblock.
-+ * @c: UBIFS file-system description object
-+ * @lnum: log logical eraseblock to replay
-+ * @offs: offset to start replaying from
-+ * @sbuf: scan buffer
-+ *
-+ * This function replays a log LEB and returns zero in case of success, %1 if
-+ * this is the last LEB in the log, and a negative error code in case of
-+ * failure.
-+ */
-+static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
-+{
-+ int err;
-+ struct ubifs_scan_leb *sleb;
-+ struct ubifs_scan_node *snod;
-+ const struct ubifs_cs_node *node;
-+
-+ dbg_mnt("replay log LEB %d:%d", lnum, offs);
-+ sleb = ubifs_scan(c, lnum, offs, sbuf);
-+ if (IS_ERR(sleb)) {
-+ if (c->need_recovery)
-+ sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
-+ if (IS_ERR(sleb))
-+ return PTR_ERR(sleb);
-+ }
-+
-+ if (sleb->nodes_cnt == 0) {
-+ err = 1;
-+ goto out;
-+ }
-+
-+ node = sleb->buf;
-+
-+ snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
-+ if (c->cs_sqnum == 0) {
-+ /*
-+ * This is the first log LEB we are looking at, make sure that
-+ * the first node is a commit start node. Also record its
-+ * sequence number so that UBIFS can determine where the log
-+ * ends, because all nodes which were have higher sequence
-+ * numbers.
-+ */
-+ if (snod->type != UBIFS_CS_NODE) {
-+ dbg_err("first log node at LEB %d:%d is not CS node",
-+ lnum, offs);
-+ goto out_dump;
-+ }
-+ if (le64_to_cpu(node->cmt_no) != c->cmt_no) {
-+ dbg_err("first CS node at LEB %d:%d has wrong "
-+ "commit number %llu expected %llu",
-+ lnum, offs,
-+ (unsigned long long)le64_to_cpu(node->cmt_no),
-+ c->cmt_no);
-+ goto out_dump;
-+ }
-+
-+ c->cs_sqnum = le64_to_cpu(node->ch.sqnum);
-+ dbg_mnt("commit start sqnum %llu", c->cs_sqnum);
-+ }
-+
-+ if (snod->sqnum < c->cs_sqnum) {
-+ /*
-+ * This means that we reached end of log and now
-+ * look to the older log data, which was already
-+ * committed but the eraseblock was not erased (UBIFS
-+ * only unmaps it). So this basically means we have to
-+ * exit with "end of log" code.
-+ */
-+ err = 1;
-+ goto out;
-+ }
-+
-+ /* Make sure the first node sits at offset zero of the LEB */
-+ if (snod->offs != 0) {
-+ dbg_err("first node is not at zero offset");
-+ goto out_dump;
-+ }
-+
-+ list_for_each_entry(snod, &sleb->nodes, list) {
-+
-+ cond_resched();
-+
-+ if (snod->sqnum >= SQNUM_WATERMARK) {
-+ ubifs_err("file system's life ended");
-+ goto out_dump;
-+ }
-+
-+ if (snod->sqnum < c->cs_sqnum) {
-+ dbg_err("bad sqnum %llu, commit sqnum %llu",
-+ snod->sqnum, c->cs_sqnum);
-+ goto out_dump;
-+ }
-+
-+ if (snod->sqnum > c->max_sqnum)
-+ c->max_sqnum = snod->sqnum;
-+
-+ switch (snod->type) {
-+ case UBIFS_REF_NODE: {
-+ const struct ubifs_ref_node *ref = snod->node;
-+
-+ err = validate_ref(c, ref);
-+ if (err == 1)
-+ break; /* Already have this bud */
-+ if (err)
-+ goto out_dump;
-+
-+ err = add_replay_bud(c, le32_to_cpu(ref->lnum),
-+ le32_to_cpu(ref->offs),
-+ le32_to_cpu(ref->jhead),
-+ snod->sqnum);
-+ if (err)
-+ goto out;
-+
-+ break;
-+ }
-+ case UBIFS_CS_NODE:
-+ /* Make sure it sits at the beginning of LEB */
-+ if (snod->offs != 0) {
-+ ubifs_err("unexpected node in log");
-+ goto out_dump;
-+ }
-+ break;
-+ default:
-+ ubifs_err("unexpected node in log");
-+ goto out_dump;
-+ }
-+ }
-+
-+ if (sleb->endpt || c->lhead_offs >= c->leb_size) {
-+ c->lhead_lnum = lnum;
-+ c->lhead_offs = sleb->endpt;
-+ }
-+
-+ err = !sleb->endpt;
-+out:
-+ ubifs_scan_destroy(sleb);
-+ return err;
-+
-+out_dump:
-+ ubifs_err("log error detected while replying the log at LEB %d:%d",
-+ lnum, offs + snod->offs);
-+ dbg_dump_node(c, snod->node);
-+ ubifs_scan_destroy(sleb);
-+ return -EINVAL;
-+}
-+
-+/**
-+ * take_ihead - update the status of the index head in lprops to 'taken'.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns the amount of free space in the index head LEB or a
-+ * negative error code.
-+ */
-+static int take_ihead(struct ubifs_info *c)
-+{
-+ const struct ubifs_lprops *lp;
-+ int err, free;
-+
-+ ubifs_get_lprops(c);
-+
-+ lp = ubifs_lpt_lookup_dirty(c, c->ihead_lnum);
-+ if (IS_ERR(lp)) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+
-+ free = lp->free;
-+
-+ lp = ubifs_change_lp(c, lp, -1, -1, lp->flags | LPROPS_TAKEN, 0);
-+ if (IS_ERR(lp)) {
-+ err = PTR_ERR(lp);
-+ goto out;
-+ }
-+
-+ err = free;
-+out:
-+ ubifs_release_lprops(c);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_replay_journal - replay journal.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function scans the journal, replays and cleans it up. It makes sure all
-+ * memory data structures related to uncommitted journal are built (dirty TNC
-+ * tree, tree of buds, modified lprops, etc).
-+ */
-+int ubifs_replay_journal(struct ubifs_info *c)
-+{
-+ int err, i, lnum, offs, free;
-+ void *sbuf = NULL;
-+
-+ /* Update the status of the index head in lprops to 'taken' */
-+ free = take_ihead(c);
-+ if (free < 0)
-+ return free; /* Error code */
-+
-+ if (c->ihead_offs != c->leb_size - free) {
-+ ubifs_err("bad index head LEB %d:%d", c->ihead_lnum,
-+ c->ihead_offs);
-+ return -EINVAL;
-+ }
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ sbuf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ sbuf = vmalloc(c->leb_size);
-+#endif
-+ if (!sbuf)
-+ return -ENOMEM;
-+
-+ dbg_mnt("start replaying the journal");
-+
-+ c->replaying = 1;
-+
-+ lnum = c->ltail_lnum = c->lhead_lnum;
-+ offs = c->lhead_offs;
-+
-+ for (i = 0; i < c->log_lebs; i++, lnum++) {
-+ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) {
-+ /*
-+ * The log is logically circular, we reached the last
-+ * LEB, switch to the first one.
-+ */
-+ lnum = UBIFS_LOG_LNUM;
-+ offs = 0;
-+ }
-+ err = replay_log_leb(c, lnum, offs, sbuf);
-+ if (err == 1)
-+ /* We hit the end of the log */
-+ break;
-+ if (err)
-+ goto out;
-+ offs = 0;
-+ }
-+
-+ err = replay_buds(c);
-+ if (err)
-+ goto out;
-+
-+ err = apply_replay_tree(c);
-+ if (err)
-+ goto out;
-+
-+ ubifs_assert(c->bud_bytes <= c->max_bud_bytes || c->need_recovery);
-+ dbg_mnt("finished, log head LEB %d:%d, max_sqnum %llu, "
-+ "highest_inum %lu", c->lhead_lnum, c->lhead_offs, c->max_sqnum,
-+ c->highest_inum);
-+out:
-+ destroy_replay_tree(c);
-+ destroy_bud_list(c);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(sbuf);
-+#else
-+ vfree(sbuf);
-+#endif
-+ c->replaying = 0;
-+ return err;
-+}
---- linux-2.6.24.7.old/fs/ubifs/sb.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/sb.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,617 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file implements UBIFS superblock. The superblock is stored at the first
-+ * LEB of the volume and is never changed by UBIFS. Only user-space tools may
-+ * change it. The superblock node mostly contains geometry information.
-+ */
-+
-+#include "ubifs.h"
-+
-+/*
-+ * Default journal size in logical eraseblocks as a percent of total
-+ * flash size.
-+ */
-+#define DEFAULT_JNL_PERCENT 5
-+
-+/* Default maximum journal size in bytes */
-+#define DEFAULT_MAX_JNL (32*1024*1024)
-+
-+/* Default indexing tree fanout */
-+#define DEFAULT_FANOUT 8
-+
-+/* Default number of LEBs for orphan information */
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+#define DEFAULT_ORPHAN_LEBS 2 /* 2 is better for testing */
-+#else
-+#define DEFAULT_ORPHAN_LEBS 1
-+#endif
-+
-+/* Default number of journal heads */
-+#define DEFAULT_JHEADS_CNT 1
-+
-+/* Default positions of different LEBs in the main area */
-+#define DEFAULT_IDX_LEB 0
-+#define DEFAULT_DATA_LEB 1
-+#define DEFAULT_GC_LEB 2
-+
-+/* Default number of LEB numbers in LPT's save table */
-+#define DEFAULT_LSAVE_CNT 256
-+
-+/* Default reserved pool size as a percent of maximum free space */
-+#define DEFAULT_RP_PERCENT 5
-+
-+/* The default maximum size of reserved pool in bytes */
-+#define DEFAULT_MAX_RP_SIZE (5*1024*1024)
-+
-+/* Default UBIFS compressor */
-+#define DEFAULT_COMPRESSOR UBIFS_COMPR_LZO
-+
-+/* Default time granularity in nanoseconds */
-+#define DEFAULT_TIME_GRAN 1000000000
-+
-+/**
-+ * create_default_filesystem - format empty UBI volume.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function creates default empty file-system. Returns zero in case of
-+ * success and a negative error code in case of failure.
-+ */
-+static int create_default_filesystem(struct ubifs_info *c)
-+{
-+ struct ubifs_sb_node *sup;
-+ struct ubifs_mst_node *mst;
-+ struct ubifs_idx_node *idx;
-+ struct ubifs_branch *br;
-+ struct ubifs_ino_node *ino;
-+ struct ubifs_cs_node *cs;
-+ union ubifs_key key;
-+ int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first;
-+ int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0;
-+ uint64_t tmp64, main_bytes;
-+
-+ /* Some functions called from here depend on the @c->key_len filed */
-+ c->key_len = UBIFS_SK_LEN;
-+
-+ /*
-+ * First of all, we have to calculate default file-system geometry -
-+ * log size, journal size, etc.
-+ */
-+ c->max_leb_cnt = c->leb_cnt;
-+ if (c->leb_cnt < 0x7FFFFFFF / DEFAULT_JNL_PERCENT)
-+ /* We can first multiply then divide and have no overflow */
-+ jnl_lebs = c->leb_cnt * DEFAULT_JNL_PERCENT / 100;
-+ else
-+ jnl_lebs = (c->leb_cnt / 100) * DEFAULT_JNL_PERCENT;
-+
-+ if (jnl_lebs < UBIFS_MIN_JNL_LEBS)
-+ jnl_lebs = UBIFS_MIN_JNL_LEBS;
-+ if (jnl_lebs * c->leb_size > DEFAULT_MAX_JNL)
-+ jnl_lebs = DEFAULT_MAX_JNL / c->leb_size;
-+
-+ /*
-+ * The log should be large enough to fit reference nodes for all bud
-+ * LEBs. Because buds do not have to start from the beginning of LEBs
-+ * (half of the LEB may contain committed data), the log should
-+ * generally be larger, make it twice as large.
-+ */
-+ tmp = 2 * (c->ref_node_alsz * jnl_lebs) + c->leb_size - 1;
-+ log_lebs = tmp / c->leb_size;
-+ /* Plus one LEB reserved for commit */
-+ log_lebs += 1;
-+ /* And some extra space to allow writes while committing */
-+ log_lebs += 1;
-+
-+ max_buds = jnl_lebs - log_lebs;
-+ if (max_buds < UBIFS_MIN_BUD_LEBS)
-+ max_buds = UBIFS_MIN_BUD_LEBS;
-+
-+ /*
-+ * Orphan nodes are stored in a separate area. One node can store a lot
-+ * of orphan inode numbers, but when new orphan comes we just add a new
-+ * orphan node. At some point the nodes are consolidated into one
-+ * orphan node.
-+ */
-+ orph_lebs = DEFAULT_ORPHAN_LEBS;
-+
-+ main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS - log_lebs;
-+ main_lebs -= orph_lebs;
-+
-+ lpt_first = UBIFS_LOG_LNUM + log_lebs;
-+ c->lsave_cnt = DEFAULT_LSAVE_CNT;
-+ err = ubifs_create_dflt_lpt(c, &main_lebs, lpt_first, &lpt_lebs,
-+ &big_lpt);
-+ if (err)
-+ return err;
-+
-+ dbg_gen("LEB Properties Tree created (LEBs %d-%d)", lpt_first,
-+ lpt_first + lpt_lebs - 1);
-+
-+ main_first = c->leb_cnt - main_lebs;
-+
-+ /* Create default superblock */
-+ tmp = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
-+ sup = kzalloc(tmp, GFP_KERNEL);
-+ if (!sup)
-+ return -ENOMEM;
-+
-+ tmp64 = (uint64_t)max_buds * c->leb_size;
-+ if (big_lpt)
-+ sup_flags |= UBIFS_FLG_BIGLPT;
-+
-+ sup->ch.node_type = UBIFS_SB_NODE;
-+ sup->key_hash = UBIFS_KEY_HASH_R5;
-+ sup->flags = cpu_to_le32(sup_flags);
-+ sup->min_io_size = cpu_to_le32(c->min_io_size);
-+ sup->leb_size = cpu_to_le32(c->leb_size);
-+ sup->leb_cnt = cpu_to_le32(c->leb_cnt);
-+ sup->max_leb_cnt = cpu_to_le32(c->max_leb_cnt);
-+ sup->max_bud_bytes = cpu_to_le64(tmp64);
-+ sup->log_lebs = cpu_to_le32(log_lebs);
-+ sup->lpt_lebs = cpu_to_le32(lpt_lebs);
-+ sup->orph_lebs = cpu_to_le32(orph_lebs);
-+ sup->jhead_cnt = cpu_to_le32(DEFAULT_JHEADS_CNT);
-+ sup->fanout = cpu_to_le32(DEFAULT_FANOUT);
-+ sup->lsave_cnt = cpu_to_le32(c->lsave_cnt);
-+ sup->fmt_version = cpu_to_le32(UBIFS_FORMAT_VERSION);
-+ sup->default_compr = cpu_to_le16(DEFAULT_COMPRESSOR);
-+ sup->time_gran = cpu_to_le32(DEFAULT_TIME_GRAN);
-+
-+ main_bytes = (uint64_t)main_lebs * c->leb_size;
-+ tmp64 = main_bytes * DEFAULT_RP_PERCENT;
-+ do_div(tmp64, 100);
-+ if (tmp64 > DEFAULT_MAX_RP_SIZE)
-+ tmp64 = DEFAULT_MAX_RP_SIZE;
-+ sup->rp_size = cpu_to_le64(tmp64);
-+
-+ err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0, UBI_LONGTERM);
-+ kfree(sup);
-+ if (err)
-+ return err;
-+
-+ dbg_gen("default superblock created at LEB 0:0");
-+
-+ /* Create default master node */
-+ mst = kzalloc(c->mst_node_alsz, GFP_KERNEL);
-+ if (!mst)
-+ return -ENOMEM;
-+
-+ mst->ch.node_type = UBIFS_MST_NODE;
-+ mst->log_lnum = cpu_to_le32(UBIFS_LOG_LNUM);
-+ mst->highest_inum = cpu_to_le64(UBIFS_FIRST_INO);
-+ mst->cmt_no = 0;
-+ mst->root_lnum = cpu_to_le32(main_first + DEFAULT_IDX_LEB);
-+ mst->root_offs = 0;
-+ tmp = ubifs_idx_node_sz(c, 1);
-+ mst->root_len = cpu_to_le32(tmp);
-+ mst->gc_lnum = cpu_to_le32(main_first + DEFAULT_GC_LEB);
-+ mst->ihead_lnum = cpu_to_le32(main_first + DEFAULT_IDX_LEB);
-+ mst->ihead_offs = cpu_to_le32(ALIGN(tmp, c->min_io_size));
-+ mst->index_size = cpu_to_le64(ALIGN(tmp, 8));
-+ mst->lpt_lnum = cpu_to_le32(c->lpt_lnum);
-+ mst->lpt_offs = cpu_to_le32(c->lpt_offs);
-+ mst->nhead_lnum = cpu_to_le32(c->nhead_lnum);
-+ mst->nhead_offs = cpu_to_le32(c->nhead_offs);
-+ mst->ltab_lnum = cpu_to_le32(c->ltab_lnum);
-+ mst->ltab_offs = cpu_to_le32(c->ltab_offs);
-+ mst->lsave_lnum = cpu_to_le32(c->lsave_lnum);
-+ mst->lsave_offs = cpu_to_le32(c->lsave_offs);
-+ mst->lscan_lnum = cpu_to_le32(main_first);
-+ mst->empty_lebs = cpu_to_le32(main_lebs - 2);
-+ mst->idx_lebs = cpu_to_le32(1);
-+ mst->leb_cnt = cpu_to_le32(c->leb_cnt);
-+
-+ /* Calculate lprops statistics */
-+ tmp64 = main_bytes;
-+ tmp64 -= ALIGN(ubifs_idx_node_sz(c, 1), c->min_io_size);
-+ tmp64 -= ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size);
-+ mst->total_free = cpu_to_le64(tmp64);
-+
-+ tmp64 = ALIGN(ubifs_idx_node_sz(c, 1), c->min_io_size);
-+ ino_waste = ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size) -
-+ UBIFS_INO_NODE_SZ;
-+ tmp64 += ino_waste;
-+ tmp64 -= ALIGN(ubifs_idx_node_sz(c, 1), 8);
-+ mst->total_dirty = cpu_to_le64(tmp64);
-+
-+ /* The indexing LEB does not contribute to dark space */
-+ tmp64 = (c->main_lebs - 1) * c->dark_wm;
-+ mst->total_dark = cpu_to_le64(tmp64);
-+
-+ mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ);
-+
-+ err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0,
-+ UBI_UNKNOWN);
-+ if (err) {
-+ kfree(mst);
-+ return err;
-+ }
-+ err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1, 0,
-+ UBI_UNKNOWN);
-+ kfree(mst);
-+ if (err)
-+ return err;
-+
-+ dbg_gen("default master node created at LEB %d:0", UBIFS_MST_LNUM);
-+
-+ /* Create the root indexing node */
-+ tmp = ubifs_idx_node_sz(c, 1);
-+ idx = kzalloc(ALIGN(tmp, c->min_io_size), GFP_KERNEL);
-+ if (!idx)
-+ return -ENOMEM;
-+
-+ c->key_fmt = UBIFS_SIMPLE_KEY_FMT;
-+ c->key_hash = key_r5_hash;
-+
-+ idx->ch.node_type = UBIFS_IDX_NODE;
-+ idx->child_cnt = cpu_to_le16(1);
-+ ino_key_init(c, &key, UBIFS_ROOT_INO);
-+ br = ubifs_idx_branch(c, idx, 0);
-+ key_write_idx(c, &key, &br->key);
-+ br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB);
-+ br->len = cpu_to_le32(UBIFS_INO_NODE_SZ);
-+ err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0,
-+ UBI_UNKNOWN);
-+ kfree(idx);
-+ if (err)
-+ return err;
-+
-+ dbg_gen("default root indexing node created LEB %d:0",
-+ main_first + DEFAULT_IDX_LEB);
-+
-+ /* Create default root inode */
-+ tmp = ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size);
-+ ino = kzalloc(tmp, GFP_KERNEL);
-+ if (!ino)
-+ return -ENOMEM;
-+
-+ ino_key_init_flash(c, &ino->key, UBIFS_ROOT_INO);
-+ ino->ch.node_type = UBIFS_INO_NODE;
-+ ino->creat_sqnum = cpu_to_le64(++c->max_sqnum);
-+ ino->nlink = cpu_to_le32(2);
-+ tmp = cpu_to_le64(CURRENT_TIME_SEC.tv_sec);
-+ ino->atime_sec = tmp;
-+ ino->ctime_sec = tmp;
-+ ino->mtime_sec = tmp;
-+ ino->atime_nsec = 0;
-+ ino->ctime_nsec = 0;
-+ ino->mtime_nsec = 0;
-+ ino->mode = cpu_to_le32(S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO);
-+ ino->size = cpu_to_le64(UBIFS_INO_NODE_SZ);
-+
-+ /* Set compression enabled by default */
-+ ino->flags = cpu_to_le32(UBIFS_COMPR_FL);
-+
-+ err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ,
-+ main_first + DEFAULT_DATA_LEB, 0,
-+ UBI_UNKNOWN);
-+ kfree(ino);
-+ if (err)
-+ return err;
-+
-+ dbg_gen("root inode created at LEB %d:0",
-+ main_first + DEFAULT_DATA_LEB);
-+
-+ /*
-+ * The first node in the log has to be the commit start node. This is
-+ * always the case during normal file-system operation. Write a fake
-+ * commit start node to the log.
-+ */
-+ tmp = ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size);
-+ cs = kzalloc(tmp, GFP_KERNEL);
-+ if (!cs)
-+ return -ENOMEM;
-+
-+ cs->ch.node_type = UBIFS_CS_NODE;
-+ err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM,
-+ 0, UBI_UNKNOWN);
-+ kfree(cs);
-+
-+ ubifs_msg("default file-system created");
-+ return 0;
-+}
-+
-+/**
-+ * validate_sb - validate superblock node.
-+ * @c: UBIFS file-system description object
-+ * @sup: superblock node
-+ *
-+ * This function validates superblock node @sup. Since most of data was read
-+ * from the superblock and stored in @c, the function validates fields in @c
-+ * instead. Returns zero in case of success and %-EINVAL in case of validation
-+ * failure.
-+ */
-+static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup)
-+{
-+ long long max_bytes;
-+ int err = 1;
-+
-+ if (!c->key_hash) {
-+ err = 2;
-+ goto failed;
-+ }
-+
-+ if (sup->key_fmt != UBIFS_SIMPLE_KEY_FMT) {
-+ err = 3;
-+ goto failed;
-+ }
-+
-+ if (le32_to_cpu(sup->min_io_size) != c->min_io_size) {
-+ ubifs_err("min. I/O unit mismatch: %d in superblock, %d real",
-+ le32_to_cpu(sup->min_io_size), c->min_io_size);
-+ goto failed;
-+ }
-+
-+ if (le32_to_cpu(sup->leb_size) != c->leb_size) {
-+ ubifs_err("LEB size mismatch: %d in superblock, %d real",
-+ le32_to_cpu(sup->leb_size), c->leb_size);
-+ goto failed;
-+ }
-+
-+ if (c->leb_cnt < UBIFS_MIN_LEB_CNT || c->leb_cnt > c->vi.size) {
-+ ubifs_err("bad LEB count: %d in superblock, %d on UBI volume, "
-+ "%d minimum required", c->leb_cnt, c->vi.size,
-+ UBIFS_MIN_LEB_CNT);
-+ goto failed;
-+ }
-+
-+ if (c->max_leb_cnt < c->leb_cnt) {
-+ ubifs_err("max. LEB count %d less than LEB count %d",
-+ c->max_leb_cnt, c->leb_cnt);
-+ goto failed;
-+ }
-+
-+ if (c->log_lebs < UBIFS_MIN_LOG_LEBS ||
-+ c->lpt_lebs < UBIFS_MIN_LPT_LEBS ||
-+ c->orph_lebs < UBIFS_MIN_ORPH_LEBS ||
-+ c->main_lebs < UBIFS_MIN_MAIN_LEBS) {
-+ err = 6;
-+ goto failed;
-+ }
-+
-+ if (c->main_lebs < UBIFS_MIN_MAIN_LEBS) {
-+ err = 7;
-+ goto failed;
-+ }
-+
-+ if (c->max_bud_bytes < (long long)c->leb_size * UBIFS_MIN_BUD_LEBS ||
-+ c->max_bud_bytes > (long long)c->leb_size * c->main_lebs) {
-+ err = 8;
-+ goto failed;
-+ }
-+
-+ if (c->jhead_cnt < NONDATA_JHEADS_CNT + 1 ||
-+ c->jhead_cnt > NONDATA_JHEADS_CNT + UBIFS_MAX_JHEADS) {
-+ err = 9;
-+ goto failed;
-+ }
-+
-+ if (c->fanout < UBIFS_MIN_FANOUT ||
-+ ubifs_idx_node_sz(c, c->fanout) > c->leb_size) {
-+ err = 10;
-+ goto failed;
-+ }
-+
-+ if (c->lsave_cnt < 0 || (c->lsave_cnt > DEFAULT_LSAVE_CNT &&
-+ c->lsave_cnt > c->max_leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS -
-+ c->log_lebs - c->lpt_lebs - c->orph_lebs)) {
-+ err = 11;
-+ goto failed;
-+ }
-+
-+ if (UBIFS_SB_LEBS + UBIFS_MST_LEBS + c->log_lebs + c->lpt_lebs +
-+ c->orph_lebs + c->main_lebs != c->leb_cnt) {
-+ err = 12;
-+ goto failed;
-+ }
-+
-+ if (c->default_compr < 0 || c->default_compr >= UBIFS_COMPR_TYPES_CNT) {
-+ err = 13;
-+ goto failed;
-+ }
-+
-+ max_bytes = c->main_lebs * (long long)c->leb_size;
-+ if (c->rp_size < 0 || max_bytes < c->rp_size) {
-+ err = 14;
-+ goto failed;
-+ }
-+
-+ if (le32_to_cpu(sup->time_gran) > 1000000000 ||
-+ le32_to_cpu(sup->time_gran) < 1) {
-+ err = 15;
-+ goto failed;
-+ }
-+
-+ return 0;
-+
-+failed:
-+ ubifs_err("bad superblock, error %d", err);
-+ dbg_dump_node(c, sup);
-+ return -EINVAL;
-+}
-+
-+/**
-+ * ubifs_read_sb_node - read superblock node.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns a pointer to the superblock node or a negative error
-+ * code.
-+ */
-+struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
-+{
-+ struct ubifs_sb_node *sup;
-+ int err;
-+
-+ sup = kmalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_NOFS);
-+ if (!sup)
-+ return ERR_PTR(-ENOMEM);
-+
-+ err = ubifs_read_node(c, sup, UBIFS_SB_NODE, UBIFS_SB_NODE_SZ,
-+ UBIFS_SB_LNUM, 0);
-+ if (err) {
-+ kfree(sup);
-+ return ERR_PTR(err);
-+ }
-+
-+ return sup;
-+}
-+
-+/**
-+ * ubifs_write_sb_node - write superblock node.
-+ * @c: UBIFS file-system description object
-+ * @sup: superblock node read with 'ubifs_read_sb_node()'
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup)
-+{
-+ int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
-+
-+ ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1);
-+ return ubi_leb_change(c->ubi, UBIFS_SB_LNUM, sup, len, UBI_LONGTERM);
-+}
-+
-+/**
-+ * ubifs_read_superblock - read superblock.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function finds, reads and checks the superblock. If an empty UBI volume
-+ * is being mounted, this function creates default superblock. Returns zero in
-+ * case of success, and a negative error code in case of failure.
-+ */
-+int ubifs_read_superblock(struct ubifs_info *c)
-+{
-+ int err, sup_flags;
-+ struct ubifs_sb_node *sup;
-+
-+ if (c->empty) {
-+ err = create_default_filesystem(c);
-+ if (err)
-+ return err;
-+ }
-+
-+ sup = ubifs_read_sb_node(c);
-+ if (IS_ERR(sup))
-+ return PTR_ERR(sup);
-+
-+ /*
-+ * The software supports all previous versions but not future versions,
-+ * due to the unavailability of time-travelling equipment.
-+ */
-+ c->fmt_version = le32_to_cpu(sup->fmt_version);
-+ if (c->fmt_version > UBIFS_FORMAT_VERSION) {
-+ ubifs_err("on-flash format version is %d, but software only "
-+ "supports up to version %d", c->fmt_version,
-+ UBIFS_FORMAT_VERSION);
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (c->fmt_version == 1) {
-+ ubifs_err("on-flash format version %d is not supported",
-+ c->fmt_version);
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ switch (sup->key_hash) {
-+ case UBIFS_KEY_HASH_R5:
-+ /* TODO: this should die soon */
-+ if (c->fmt_version == 2)
-+ c->key_hash = tmp_key_r5_hash;
-+ else
-+ c->key_hash = key_r5_hash;
-+ c->key_hash_type = UBIFS_KEY_HASH_R5;
-+ break;
-+
-+ case UBIFS_KEY_HASH_TEST:
-+ c->key_hash = key_test_hash;
-+ c->key_hash_type = UBIFS_KEY_HASH_TEST;
-+ break;
-+ };
-+
-+ c->key_fmt = sup->key_fmt;
-+
-+ switch (c->key_fmt) {
-+ case UBIFS_SIMPLE_KEY_FMT:
-+ c->key_len = UBIFS_SK_LEN;
-+ break;
-+ default:
-+ ubifs_err("unsupported key format");
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ c->leb_cnt = le32_to_cpu(sup->leb_cnt);
-+ c->max_leb_cnt = le32_to_cpu(sup->max_leb_cnt);
-+ c->max_bud_bytes = le64_to_cpu(sup->max_bud_bytes);
-+ c->log_lebs = le32_to_cpu(sup->log_lebs);
-+ c->lpt_lebs = le32_to_cpu(sup->lpt_lebs);
-+ c->orph_lebs = le32_to_cpu(sup->orph_lebs);
-+ c->jhead_cnt = le32_to_cpu(sup->jhead_cnt) + NONDATA_JHEADS_CNT;
-+ c->fanout = le32_to_cpu(sup->fanout);
-+ c->lsave_cnt = le32_to_cpu(sup->lsave_cnt);
-+ c->default_compr = le16_to_cpu(sup->default_compr);
-+ c->rp_size = le64_to_cpu(sup->rp_size);
-+ c->rp_uid = le32_to_cpu(sup->rp_uid);
-+ c->rp_gid = le32_to_cpu(sup->rp_gid);
-+ sup_flags = le32_to_cpu(sup->flags);
-+
-+ c->vfs_sb->s_time_gran = le32_to_cpu(sup->time_gran);
-+
-+ c->big_lpt = !!(sup_flags & UBIFS_FLG_BIGLPT);
-+
-+ /* Automatically increase file system size to the maximum size */
-+ c->old_leb_cnt = c->leb_cnt;
-+ if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) {
-+ c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size);
-+ if (c->vfs_sb->s_flags & MS_RDONLY)
-+ dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs",
-+ c->old_leb_cnt, c->leb_cnt);
-+ else {
-+ dbg_mnt("Auto resizing (sb) from %d LEBs to %d LEBs",
-+ c->old_leb_cnt, c->leb_cnt);
-+ sup->leb_cnt = cpu_to_le32(c->leb_cnt);
-+ err = ubifs_write_sb_node(c, sup);
-+ if (err)
-+ goto out;
-+ c->old_leb_cnt = c->leb_cnt;
-+ }
-+ }
-+
-+ c->log_bytes = (long long)c->log_lebs * c->leb_size;
-+ c->log_last = UBIFS_LOG_LNUM + c->log_lebs - 1;
-+ c->lpt_first = UBIFS_LOG_LNUM + c->log_lebs;
-+ c->lpt_last = c->lpt_first + c->lpt_lebs - 1;
-+ c->orph_first = c->lpt_last + 1;
-+ c->orph_last = c->orph_first + c->orph_lebs - 1;
-+ c->main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS;
-+ c->main_lebs -= c->log_lebs + c->lpt_lebs + c->orph_lebs;
-+ c->main_first = c->leb_cnt - c->main_lebs;
-+ c->report_rp_size = ubifs_reported_space(c, c->rp_size);
-+
-+ err = validate_sb(c, sup);
-+out:
-+ kfree(sup);
-+ return err;
-+}
---- linux-2.6.24.7.old/fs/ubifs/scan.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/scan.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,362 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file implements the scan which is a general-purpose function for
-+ * determining what nodes are in an eraseblock. The scan is used to replay the
-+ * journal, to do garbage collection. for the TNC in-the-gaps method, and by
-+ * debugging functions.
-+ */
-+
-+#include "ubifs.h"
-+
-+/**
-+ * scan_padding_bytes - scan for padding bytes.
-+ * @buf: buffer to scan
-+ * @len: length of buffer
-+ *
-+ * This function returns the number of padding bytes on success and
-+ * %SCANNED_GARBAGE on failure.
-+ */
-+static int scan_padding_bytes(void *buf, int len)
-+{
-+ int pad_len = 0, max_pad_len = min_t(int, UBIFS_PAD_NODE_SZ, len);
-+ uint8_t *p = buf;
-+
-+ dbg_scan("not a node");
-+
-+ while (pad_len < max_pad_len && *p++ == UBIFS_PADDING_BYTE)
-+ pad_len += 1;
-+
-+ if (!pad_len || (pad_len & 7))
-+ return SCANNED_GARBAGE;
-+
-+ dbg_scan("%d padding bytes", pad_len);
-+
-+ return pad_len;
-+}
-+
-+/**
-+ * ubifs_scan_a_node - scan for a node or padding.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer to scan
-+ * @len: length of buffer
-+ * @lnum: logical eraseblock number
-+ * @offs: offset within the logical eraseblock
-+ * @quiet: print no messages
-+ *
-+ * This function returns a scanning code to indicate what was scanned.
-+ */
-+int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
-+ int offs, int quiet)
-+{
-+ struct ubifs_ch *ch = buf;
-+ uint32_t magic;
-+
-+ magic = le32_to_cpu(ch->magic);
-+
-+ if (magic == 0xFFFFFFFF) {
-+ dbg_scan("hit empty space");
-+ return SCANNED_EMPTY_SPACE;
-+ }
-+
-+ if (magic != UBIFS_NODE_MAGIC)
-+ return scan_padding_bytes(buf, len);
-+
-+ if (len < UBIFS_CH_SZ)
-+ return SCANNED_GARBAGE;
-+
-+ dbg_scan("scanning %s", dbg_ntype(ch->node_type));
-+
-+ if (ubifs_check_node(c, buf, lnum, offs, quiet))
-+ return SCANNED_A_CORRUPT_NODE;
-+
-+ if (ch->node_type == UBIFS_PAD_NODE) {
-+ struct ubifs_pad_node *pad = buf;
-+ int pad_len = le32_to_cpu(pad->pad_len);
-+ int node_len = le32_to_cpu(ch->len);
-+
-+ /* Validate the padding node */
-+ if (pad_len < 0 ||
-+ offs + node_len + pad_len > c->leb_size) {
-+ if (!quiet) {
-+ ubifs_err("bad pad node at LEB %d:%d",
-+ lnum, offs);
-+ dbg_dump_node(c, pad);
-+ }
-+ return SCANNED_A_BAD_PAD_NODE;
-+ }
-+
-+ /* Make the node pads to 8-byte boundary */
-+ if ((node_len + pad_len) & 7) {
-+ if (!quiet) {
-+ dbg_err("bad padding length %d - %d",
-+ offs, offs + node_len + pad_len);
-+ }
-+ return SCANNED_A_BAD_PAD_NODE;
-+ }
-+
-+ dbg_scan("%d bytes padded, offset now %d",
-+ pad_len, ALIGN(offs + node_len + pad_len, 8));
-+
-+ return node_len + pad_len;
-+ }
-+
-+ return SCANNED_A_NODE;
-+}
-+
-+/**
-+ * ubifs_start_scan - create LEB scanning information at start of scan.
-+ * @c: UBIFS file-system description object
-+ * @lnum: logical eraseblock number
-+ * @offs: offset to start at (usually zero)
-+ * @sbuf: scan buffer (must be c->leb_size)
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
-+ int offs, void *sbuf)
-+{
-+ struct ubifs_scan_leb *sleb;
-+ int err;
-+
-+ dbg_scan("scan LEB %d:%d", lnum, offs);
-+
-+ sleb = kzalloc(sizeof(struct ubifs_scan_leb), GFP_NOFS);
-+ if (!sleb)
-+ return ERR_PTR(-ENOMEM);
-+
-+ sleb->lnum = lnum;
-+ INIT_LIST_HEAD(&sleb->nodes);
-+ sleb->buf = sbuf;
-+
-+ err = ubi_read(c->ubi, lnum, sbuf + offs, offs, c->leb_size - offs);
-+ if (err && err != -EBADMSG) {
-+ ubifs_err("cannot read %d bytes from LEB %d:%d,"
-+ " error %d", c->leb_size - offs, lnum, offs, err);
-+ kfree(sleb);
-+ return ERR_PTR(err);
-+ }
-+
-+ if (err == -EBADMSG)
-+ sleb->ecc = 1;
-+
-+ return sleb;
-+}
-+
-+/**
-+ * ubifs_end_scan - update LEB scanning information at end of scan.
-+ * @c: UBIFS file-system description object
-+ * @sleb: scanning information
-+ * @lnum: logical eraseblock number
-+ * @offs: offset to start at (usually zero)
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+void ubifs_end_scan(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
-+ int lnum, int offs)
-+{
-+ lnum = lnum;
-+ dbg_scan("stop scanning LEB %d at offset %d", lnum, offs);
-+ ubifs_assert(offs % c->min_io_size == 0);
-+
-+ sleb->endpt = ALIGN(offs, c->min_io_size);
-+}
-+
-+/**
-+ * ubifs_add_snod - add a scanned node to LEB scanning information.
-+ * @c: UBIFS file-system description object
-+ * @sleb: scanning information
-+ * @buf: buffer containing node
-+ * @offs: offset of node on flash
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
-+ void *buf, int offs)
-+{
-+ struct ubifs_ch *ch = buf;
-+ struct ubifs_ino_node *ino = buf;
-+ struct ubifs_scan_node *snod;
-+
-+ snod = kzalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
-+ if (!snod)
-+ return -ENOMEM;
-+
-+ snod->sqnum = le64_to_cpu(ch->sqnum);
-+ snod->type = ch->node_type;
-+ snod->offs = offs;
-+ snod->len = le32_to_cpu(ch->len);
-+ snod->node = buf;
-+
-+ switch (ch->node_type) {
-+ case UBIFS_INO_NODE:
-+ case UBIFS_DENT_NODE:
-+ case UBIFS_XENT_NODE:
-+ case UBIFS_DATA_NODE:
-+ case UBIFS_TRUN_NODE:
-+ /*
-+ * The key is in the same place in all keyed
-+ * nodes.
-+ */
-+ key_read(c, &ino->key, &snod->key);
-+ break;
-+ }
-+ list_add_tail(&snod->list, &sleb->nodes);
-+ sleb->nodes_cnt += 1;
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_scanned_corruption - print information after UBIFS scanned corruption.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number of corruption
-+ * @offs: offset of corruption
-+ * @buf: buffer containing corruption
-+ */
-+void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
-+ void *buf)
-+{
-+ int len;
-+
-+ ubifs_err("corrupted data at LEB %d:%d", lnum, offs);
-+ if (dbg_failure_mode)
-+ return;
-+ len = c->leb_size - offs;
-+ if (len > 4096)
-+ len = 4096;
-+ dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs);
-+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
-+}
-+
-+/**
-+ * ubifs_scan - scan a logical eraseblock.
-+ * @c: UBIFS file-system description object
-+ * @lnum: logical eraseblock number
-+ * @offs: offset to start at (usually zero)
-+ * @sbuf: scan buffer (must be c->leb_size)
-+ *
-+ * This function scans LEB number @lnum and returns complete information about
-+ * its contents. Returns an error code in case of failure.
-+ */
-+struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
-+ int offs, void *sbuf)
-+{
-+ void *buf = sbuf + offs;
-+ int err, len = c->leb_size - offs;
-+ struct ubifs_scan_leb *sleb;
-+
-+ sleb = ubifs_start_scan(c, lnum, offs, sbuf);
-+ if (IS_ERR(sleb))
-+ return sleb;
-+
-+ while (len >= 8) {
-+ struct ubifs_ch *ch = buf;
-+ int node_len, ret;
-+
-+ dbg_scan("look at LEB %d:%d (%d bytes left)",
-+ lnum, offs, len);
-+
-+ cond_resched();
-+
-+ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
-+
-+ if (ret > 0) {
-+ /* Padding bytes or a valid padding node */
-+ offs += ret;
-+ buf += ret;
-+ len -= ret;
-+ continue;
-+ }
-+
-+ if (ret == SCANNED_EMPTY_SPACE)
-+ /* Empty space is checked later */
-+ break;
-+
-+ switch (ret) {
-+ case SCANNED_GARBAGE:
-+ dbg_err("garbage");
-+ goto corrupted;
-+ case SCANNED_A_NODE:
-+ break;
-+ case SCANNED_A_CORRUPT_NODE:
-+ case SCANNED_A_BAD_PAD_NODE:
-+ dbg_err("bad node");
-+ goto corrupted;
-+ default:
-+ dbg_err("unknown");
-+ goto corrupted;
-+ }
-+
-+ err = ubifs_add_snod(c, sleb, buf, offs);
-+ if (err)
-+ goto error;
-+
-+ node_len = ALIGN(le32_to_cpu(ch->len), 8);
-+ offs += node_len;
-+ buf += node_len;
-+ len -= node_len;
-+ }
-+
-+ if (offs % c->min_io_size)
-+ goto corrupted;
-+
-+ ubifs_end_scan(c, sleb, lnum, offs);
-+
-+ for (; len > 4; offs += 4, buf = buf + 4, len -= 4)
-+ if (*(uint32_t *)buf != 0xffffffff)
-+ break;
-+ for (; len; offs++, buf++, len--)
-+ if (*(uint8_t *)buf != 0xff) {
-+ ubifs_err("corrupt empty space at LEB %d:%d",
-+ lnum, offs);
-+ goto corrupted;
-+ }
-+
-+ return sleb;
-+
-+corrupted:
-+ ubifs_scanned_corruption(c, lnum, offs, buf);
-+ err = -EUCLEAN;
-+error:
-+ ubifs_err("LEB %d scanning failed", lnum);
-+ ubifs_scan_destroy(sleb);
-+ return ERR_PTR(err);
-+}
-+
-+/**
-+ * ubifs_scan_destroy - destroy LEB scanning information.
-+ * @sleb: scanning information to free
-+ */
-+void ubifs_scan_destroy(struct ubifs_scan_leb *sleb)
-+{
-+ struct ubifs_scan_node *node;
-+ struct list_head *head;
-+
-+ head = &sleb->nodes;
-+ while (!list_empty(head)) {
-+ node = list_entry(head->next, struct ubifs_scan_node, list);
-+ list_del(&node->list);
-+ kfree(node);
-+ }
-+ kfree(sleb);
-+}
---- linux-2.6.24.7.old/fs/ubifs/shrinker.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/shrinker.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,322 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file implements UBIFS shrinker which evicts clean znodes from the TNC
-+ * tree when Linux VM needs more RAM.
-+ *
-+ * We do not implement any LRU lists to find oldest znodes to free because it
-+ * would add additional overhead to the file system fast paths. So the shrinker
-+ * just walks the TNC tree when searching for znodes to free.
-+ *
-+ * If the root of a TNC sub-tree is clean and old enough, then the children are
-+ * also clean and old enough. So the shrinker walks the TNC in level order and
-+ * dumps entire sub-trees.
-+ *
-+ * The age of znodes is just the time-stamp when they were last looked at.
-+ * The current shrinker first tries to evict old znodes, then young ones.
-+ *
-+ * Since the shrinker is global, it has to protect against races with FS
-+ * un-mounts, which is done by the 'ubifs_infos_lock' and 'c->umount_mutex'.
-+ */
-+
-+#include "ubifs.h"
-+
-+/* List of all UBIFS file-system instances */
-+LIST_HEAD(ubifs_infos);
-+
-+/*
-+ * We number each shrinker run and record the number on the ubifs_info structure
-+ * so that we can easily work out which ubifs_info structures have already been
-+ * done by the current run.
-+ */
-+static unsigned int shrinker_run_no;
-+
-+/* Protects 'ubifs_infos' list */
-+DEFINE_SPINLOCK(ubifs_infos_lock);
-+
-+/* Global clean znode counter (for all mounted UBIFS instances) */
-+atomic_long_t ubifs_clean_zn_cnt;
-+
-+/**
-+ * shrink_tnc - shrink TNC tree.
-+ * @c: UBIFS file-system description object
-+ * @nr: number of znodes to free
-+ * @age: the age of znodes to free
-+ * @contention: if any contention, this is set to %1
-+ *
-+ * This function traverses TNC tree and frees clean znodes. It does not free
-+ * clean znodes which younger then @age. Returns number of freed znodes.
-+ */
-+static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention)
-+{
-+ int total_freed = 0;
-+ struct ubifs_znode *znode, *zprev;
-+ int time = get_seconds();
-+
-+ ubifs_assert(mutex_is_locked(&c->umount_mutex));
-+ ubifs_assert(mutex_is_locked(&c->tnc_mutex));
-+
-+ if (!c->zroot.znode || atomic_long_read(&c->clean_zn_cnt) == 0)
-+ return 0;
-+
-+ /*
-+ * Traverse the TNC tree in levelorder manner, so that it is possible
-+ * to destroy large sub-trees. Indeed, if a znode is old, then all its
-+ * children are older or of the same age.
-+ *
-+ * Note, we are holding 'c->tnc_mutex', so we do not have to lock the
-+ * 'c->space_lock' when _reading_ 'c->clean_zn_cnt', because it is
-+ * changed only when the 'c->tnc_mutex' is held.
-+ */
-+ zprev = NULL;
-+ znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL);
-+ while (znode && total_freed < nr &&
-+ atomic_long_read(&c->clean_zn_cnt) > 0) {
-+ int freed;
-+
-+ /*
-+ * If the znode is clean, but it is in the 'c->cnext' list, this
-+ * means that this znode has just been written to flash as a
-+ * part of commit and was marked clean. They will be removed
-+ * from the list at end commit. We cannot change the list,
-+ * because it is not protected by any mutex (design decision to
-+ * make commit really independent and parallel to main I/O). So
-+ * we just skip these znodes.
-+ *
-+ * Note, the 'clean_zn_cnt' counters are not updated until
-+ * after the commit, so the UBIFS shrinker does not report
-+ * the znodes which are in the 'c->cnext' list as freeable.
-+ *
-+ * Also note, if the root of a sub-tree is not in 'c->cnext',
-+ * then the whole sub-tree is not in 'c->cnext' as well, so it
-+ * is safe to dump whole sub-tree.
-+ */
-+
-+ if (znode->cnext) {
-+ /*
-+ * Very soon these znodes will be removed from the list
-+ * and become freeable.
-+ */
-+ *contention = 1;
-+ } else if (!ubifs_zn_dirty(znode) &&
-+ abs(time - znode->time) >= age) {
-+ if (znode->parent)
-+ znode->parent->zbranch[znode->iip].znode = NULL;
-+ else
-+ c->zroot.znode = NULL;
-+
-+ freed = ubifs_destroy_tnc_subtree(znode);
-+ atomic_long_sub(freed, &ubifs_clean_zn_cnt);
-+ atomic_long_sub(freed, &c->clean_zn_cnt);
-+ ubifs_assert(atomic_long_read(&c->clean_zn_cnt) >= 0);
-+ total_freed += freed;
-+ znode = zprev;
-+ }
-+
-+ if (unlikely(!c->zroot.znode))
-+ break;
-+
-+ zprev = znode;
-+ znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode);
-+ cond_resched();
-+ }
-+
-+ return total_freed;
-+}
-+
-+/**
-+ * shrink_tnc_trees - shrink UBIFS TNC trees.
-+ * @nr: number of znodes to free
-+ * @age: the age of znodes to free
-+ * @contention: if any contention, this is set to %1
-+ *
-+ * This function walks the list of mounted UBIFS file-systems and frees clean
-+ * znodes which are older then @age, until at least @nr znodes are freed.
-+ * Returns the number of freed znodes.
-+ */
-+static int shrink_tnc_trees(int nr, int age, int *contention)
-+{
-+ struct ubifs_info *c;
-+ struct list_head *p;
-+ unsigned int run_no;
-+ int freed = 0;
-+
-+ spin_lock(&ubifs_infos_lock);
-+ do
-+ run_no = ++shrinker_run_no;
-+ while (run_no == 0);
-+ /* Iterate over all mounted UBIFS file-systems and try to shrink them */
-+ p = ubifs_infos.next;
-+ while (p != &ubifs_infos) {
-+ c = list_entry(p, struct ubifs_info, infos_list);
-+ /*
-+ * We move the ones we do to the end of the list, so we stop
-+ * when we see one we have already done.
-+ */
-+ if (c->shrinker_run_no == run_no)
-+ break;
-+ if (!mutex_trylock(&c->umount_mutex)) {
-+ /* Some un-mount is in progress, try next FS */
-+ *contention = 1;
-+ p = p->next;
-+ continue;
-+ }
-+ /*
-+ * We're holding 'c->umount_mutex', so the file-system won't go
-+ * away.
-+ */
-+ if (!mutex_trylock(&c->tnc_mutex)) {
-+ mutex_unlock(&c->umount_mutex);
-+ *contention = 1;
-+ p = p->next;
-+ continue;
-+ }
-+ spin_unlock(&ubifs_infos_lock);
-+ /*
-+ * OK, now we have TNC locked, the file-system cannot go away -
-+ * it is safe to reap the cache.
-+ */
-+ c->shrinker_run_no = run_no;
-+ freed += shrink_tnc(c, nr, age, contention);
-+ mutex_unlock(&c->tnc_mutex);
-+ spin_lock(&ubifs_infos_lock);
-+ /* Get the next list element before we move this one */
-+ p = p->next;
-+ /*
-+ * Move this one to the end of the list to provide some
-+ * fairness.
-+ */
-+ list_del(&c->infos_list);
-+ list_add_tail(&c->infos_list, &ubifs_infos);
-+ mutex_unlock(&c->umount_mutex);
-+ if (freed >= nr)
-+ break;
-+ }
-+ spin_unlock(&ubifs_infos_lock);
-+ return freed;
-+}
-+
-+/**
-+ * kick_a_thread - kick a background thread to start commit.
-+ *
-+ * This function kicks a background thread to start background commit. Returns
-+ * %-1 if a thread was kicked or there is another reason to assume the memory
-+ * will soon be freed or become freeable. If there are no dirty znodes, returns
-+ * %0.
-+ */
-+static int kick_a_thread(void)
-+{
-+ int i;
-+ struct ubifs_info *c;
-+
-+ /*
-+ * Iterate over all mounted UBIFS file-systems and find out if there is
-+ * already an ongoing commit operation there. If no, then iterate for
-+ * the second time and initiate background commit.
-+ */
-+ spin_lock(&ubifs_infos_lock);
-+ for (i = 0; i < 2; i++) {
-+ list_for_each_entry(c, &ubifs_infos, infos_list) {
-+ long dirty_zn_cnt;
-+
-+ if (!mutex_trylock(&c->umount_mutex)) {
-+ /*
-+ * Some un-mount is in progress, it will
-+ * certainly free memory, so just return.
-+ */
-+ spin_unlock(&ubifs_infos_lock);
-+ return -1;
-+ }
-+
-+ dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt);
-+
-+ if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN ||
-+ c->ro_media) {
-+ mutex_unlock(&c->umount_mutex);
-+ continue;
-+ }
-+
-+ if (c->cmt_state != COMMIT_RESTING) {
-+ spin_unlock(&ubifs_infos_lock);
-+ mutex_unlock(&c->umount_mutex);
-+ return -1;
-+ }
-+
-+ if (i == 1) {
-+ list_del(&c->infos_list);
-+ list_add_tail(&c->infos_list, &ubifs_infos);
-+ spin_unlock(&ubifs_infos_lock);
-+
-+ ubifs_request_bg_commit(c);
-+ mutex_unlock(&c->umount_mutex);
-+ return -1;
-+ }
-+ mutex_unlock(&c->umount_mutex);
-+ }
-+ }
-+ spin_unlock(&ubifs_infos_lock);
-+
-+ return 0;
-+}
-+
-+int ubifs_shrinker(int nr, gfp_t gfp_mask)
-+{
-+ int freed, contention = 0;
-+ long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);
-+
-+ if (nr == 0)
-+ return clean_zn_cnt;
-+
-+ if (!clean_zn_cnt) {
-+ /*
-+ * No clean znodes, nothing to reap. All we can do in this case
-+ * is to kick background threads to start commit, which will
-+ * probably make clean znodes which, in turn, will be freeable.
-+ * And we return -1 which means will make VM call us again
-+ * later.
-+ */
-+ dbg_tnc("no clean znodes, kick a thread");
-+ return kick_a_thread();
-+ }
-+
-+ freed = shrink_tnc_trees(nr, OLD_ZNODE_AGE, &contention);
-+ if (freed >= nr)
-+ goto out;
-+
-+ dbg_tnc("not enough old znodes, try to free young ones");
-+ freed += shrink_tnc_trees(nr - freed, YOUNG_ZNODE_AGE, &contention);
-+ if (freed >= nr)
-+ goto out;
-+
-+ dbg_tnc("not enough young znodes, free all");
-+ freed += shrink_tnc_trees(nr - freed, 0, &contention);
-+
-+ if (!freed && contention) {
-+ dbg_tnc("freed nothing, but contention");
-+ return -1;
-+ }
-+
-+out:
-+ dbg_tnc("%d znodes were freed, requested %d", freed, nr);
-+ return freed;
-+}
---- linux-2.6.24.7.old/fs/ubifs/super.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/super.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,2016 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file implements UBIFS initialization and VFS superblock operations. Some
-+ * initialization stuff which is rather large and complex is placed at
-+ * corresponding subsystems, but most of it is here.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include "ubifs.h"
-+
-+/* Slab cache for UBIFS inodes */
-+struct kmem_cache *ubifs_inode_slab;
-+
-+#ifndef UBIFS_COMPAT_NO_SHRINKER
-+/* UBIFS TNC shrinker description */
-+static struct shrinker ubifs_shrinker_info = {
-+ .shrink = ubifs_shrinker,
-+ .seeks = DEFAULT_SEEKS,
-+};
-+#endif
-+
-+/**
-+ * validate_inode - validate inode.
-+ * @c: UBIFS file-system description object
-+ * @inode: the inode to validate
-+ *
-+ * This is a helper function for 'ubifs_iget()' which validates various fields
-+ * of a newly built inode to make sure they contain sane values and prevent
-+ * possible vulnerabilities. Returns zero if the inode is all right and
-+ * a non-zero error code if not.
-+ */
-+#ifndef UBIFS_COMPAT_USE_OLD_IGET
-+static int validate_inode(struct ubifs_info *c, const struct inode *inode)
-+#else
-+int validate_inode(struct ubifs_info *c, const struct inode *inode)
-+#endif
-+{
-+ int err;
-+ const struct ubifs_inode *ui = ubifs_inode(inode);
-+
-+ if (inode->i_size > c->max_inode_sz) {
-+ ubifs_err("inode is too large (%lld)",
-+ (long long)inode->i_size);
-+ return 1;
-+ }
-+
-+ if (ui->compr_type < 0 || ui->compr_type >= UBIFS_COMPR_TYPES_CNT) {
-+ ubifs_err("unknown compression type %d", ui->compr_type);
-+ return 2;
-+ }
-+
-+ if (ui->xattr_cnt < 0)
-+ return 3;
-+
-+ if (ui->xattr_size < 0)
-+ return 4;
-+
-+ if (ui->xattr_names < 0 ||
-+ ui->xattr_names + ui->xattr_cnt > XATTR_LIST_MAX)
-+ return 5;
-+
-+ if (ui->data_len < 0 || ui->data_len > UBIFS_MAX_INO_DATA)
-+ return 6;
-+
-+ if (!ubifs_compr_present(ui->compr_type)) {
-+ ubifs_warn("inode %lu uses '%s' compression, but it was not "
-+ "compiled in", inode->i_ino,
-+ ubifs_compr_name(ui->compr_type));
-+ }
-+
-+ err = dbg_check_dir_size(c, inode);
-+ return err;
-+}
-+
-+#ifndef UBIFS_COMPAT_USE_OLD_IGET
-+struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
-+{
-+ int err;
-+ union ubifs_key key;
-+ struct ubifs_ino_node *ino;
-+ struct ubifs_info *c = sb->s_fs_info;
-+ struct inode *inode;
-+ struct ubifs_inode *ui;
-+
-+ dbg_gen("inode %lu", inum);
-+
-+ inode = iget_locked(sb, inum);
-+ if (!inode)
-+ return ERR_PTR(-ENOMEM);
-+ if (!(inode->i_state & I_NEW))
-+ return inode;
-+ ui = ubifs_inode(inode);
-+
-+ ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
-+ if (!ino) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ ino_key_init(c, &key, inode->i_ino);
-+
-+ err = ubifs_tnc_lookup(c, &key, ino);
-+ if (err)
-+ goto out_ino;
-+
-+ inode->i_flags |= (S_NOCMTIME | S_NOATIME);
-+ inode->i_nlink = le32_to_cpu(ino->nlink);
-+ inode->i_uid = le32_to_cpu(ino->uid);
-+ inode->i_gid = le32_to_cpu(ino->gid);
-+ inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec);
-+ inode->i_atime.tv_nsec = le32_to_cpu(ino->atime_nsec);
-+ inode->i_mtime.tv_sec = (int64_t)le64_to_cpu(ino->mtime_sec);
-+ inode->i_mtime.tv_nsec = le32_to_cpu(ino->mtime_nsec);
-+ inode->i_ctime.tv_sec = (int64_t)le64_to_cpu(ino->ctime_sec);
-+ inode->i_ctime.tv_nsec = le32_to_cpu(ino->ctime_nsec);
-+ inode->i_mode = le32_to_cpu(ino->mode);
-+ inode->i_size = le64_to_cpu(ino->size);
-+
-+ ui->data_len = le32_to_cpu(ino->data_len);
-+ ui->flags = le32_to_cpu(ino->flags);
-+ ui->compr_type = le16_to_cpu(ino->compr_type);
-+ ui->creat_sqnum = le64_to_cpu(ino->creat_sqnum);
-+ ui->xattr_cnt = le32_to_cpu(ino->xattr_cnt);
-+ ui->xattr_size = le64_to_cpu(ino->xattr_size);
-+ ui->xattr_names = le32_to_cpu(ino->xattr_names);
-+
-+ err = validate_inode(c, inode);
-+ if (err)
-+ goto out_invalid;
-+
-+ /* Disable readahead */
-+ inode->i_mapping->backing_dev_info = &ubifs_backing_dev_info;
-+
-+ switch (inode->i_mode & S_IFMT) {
-+ case S_IFREG:
-+ inode->i_mapping->a_ops = &ubifs_file_address_operations;
-+ inode->i_op = &ubifs_file_inode_operations;
-+ inode->i_fop = &ubifs_file_operations;
-+ if (ui->data_len != 0) {
-+ err = 10;
-+ goto out_invalid;
-+ }
-+ break;
-+ case S_IFDIR:
-+ inode->i_op = &ubifs_dir_inode_operations;
-+ inode->i_fop = &ubifs_dir_operations;
-+ if (ui->data_len != 0) {
-+ err = 11;
-+ goto out_invalid;
-+ }
-+ break;
-+ case S_IFLNK:
-+ inode->i_op = &ubifs_symlink_inode_operations;
-+ if (ui->data_len <= 0 || ui->data_len > UBIFS_MAX_INO_DATA) {
-+ err = 12;
-+ goto out_invalid;
-+ }
-+ ui->data = kmalloc(ui->data_len + 1, GFP_NOFS);
-+ if (!ui->data) {
-+ err = -ENOMEM;
-+ goto out_ino;
-+ }
-+ memcpy(ui->data, ino->data, ui->data_len);
-+ ((char *)ui->data)[ui->data_len] = '\0';
-+ break;
-+ case S_IFBLK:
-+ case S_IFCHR:
-+ {
-+ dev_t rdev;
-+ union ubifs_dev_desc *dev;
-+
-+ ui->data = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
-+ if (!ui->data) {
-+ err = -ENOMEM;
-+ goto out_ino;
-+ }
-+
-+ dev = (union ubifs_dev_desc *)ino->data;
-+ if (ui->data_len == sizeof(dev->new))
-+ rdev = new_decode_dev(le32_to_cpu(dev->new));
-+ else if (ui->data_len == sizeof(dev->huge))
-+ rdev = huge_decode_dev(le64_to_cpu(dev->huge));
-+ else {
-+ err = 13;
-+ goto out_invalid;
-+ }
-+ memcpy(ui->data, ino->data, ui->data_len);
-+ inode->i_op = &ubifs_file_inode_operations;
-+ init_special_inode(inode, inode->i_mode, rdev);
-+ break;
-+ }
-+ case S_IFSOCK:
-+ case S_IFIFO:
-+ inode->i_op = &ubifs_file_inode_operations;
-+ init_special_inode(inode, inode->i_mode, 0);
-+ if (ui->data_len != 0) {
-+ err = 14;
-+ goto out_invalid;
-+ }
-+ break;
-+ default:
-+ err = 15;
-+ goto out_invalid;
-+ }
-+
-+ kfree(ino);
-+ ubifs_set_inode_flags(inode);
-+ unlock_new_inode(inode);
-+ return inode;
-+
-+out_invalid:
-+ ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err);
-+ dbg_dump_node(c, ino);
-+ dbg_dump_inode(c, inode);
-+ err = -EINVAL;
-+out_ino:
-+ kfree(ino);
-+out:
-+ ubifs_err("failed to read inode %lu, error %d", inode->i_ino, err);
-+ iget_failed(inode);
-+ return ERR_PTR(err);
-+}
-+
-+#endif /* UBIFS_COMPAT_USE_OLD_IGET */
-+
-+static struct inode *ubifs_alloc_inode(struct super_block *sb)
-+{
-+ struct ubifs_inode *ui;
-+
-+ ui = kmem_cache_alloc(ubifs_inode_slab, GFP_NOFS);
-+ if (!ui)
-+ return NULL;
-+
-+ memset((void *)ui + sizeof(struct inode), 0,
-+ sizeof(struct ubifs_inode) - sizeof(struct inode));
-+ mutex_init(&ui->budg_mutex);
-+ return &ui->vfs_inode;
-+};
-+
-+static void ubifs_destroy_inode(struct inode *inode)
-+{
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+
-+ kfree(ui->data);
-+ kmem_cache_free(ubifs_inode_slab, inode);
-+}
-+
-+/*
-+ * Note, Linux write-back code calls this without 'i_mutex'.
-+ */
-+static int ubifs_write_inode(struct inode *inode, int wait)
-+{
-+ int err;
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+ struct ubifs_budget_req req = {.dd_growth = c->inode_budget,
-+ .dirtied_ino_d = ui->data_len};
-+
-+ ubifs_assert(!ui->xattr);
-+ if (is_bad_inode(inode))
-+ return 0;
-+
-+ mutex_lock(&ui->budg_mutex);
-+
-+ /*
-+ * Due to races between write-back forced by budgeting
-+ * (see 'sync_some_inodes()') and pdflush write-back, the inode may
-+ * have already been synchronized, do not do this again.
-+ *
-+ * This might also happen if it was synchronized in e.g. ubifs_link()',
-+ * etc.
-+ */
-+ if (!ui->dirty) {
-+ mutex_unlock(&ui->budg_mutex);
-+ return 0;
-+ }
-+
-+ ubifs_assert(ui->budgeted);
-+ dbg_gen("inode %lu", inode->i_ino);
-+
-+ err = ubifs_jnl_write_inode(c, inode, 0, IS_SYNC(inode));
-+ if (err)
-+ ubifs_err("can't write inode %lu, error %d", inode->i_ino, err);
-+
-+ ui->dirty = 0;
-+ UBIFS_DBG(ui->budgeted = 0);
-+ atomic_long_dec(&c->dirty_ino_cnt);
-+
-+ ubifs_release_budget(c, &req);
-+ mutex_unlock(&ui->budg_mutex);
-+
-+ return err;
-+}
-+
-+static void ubifs_delete_inode(struct inode *inode)
-+{
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+ struct ubifs_budget_req req = {.dd_growth = c->inode_budget,
-+ .dirtied_ino_d = ui->data_len};
-+ int err;
-+
-+ if (ui->xattr) {
-+ /*
-+ * Extended attribute inode deletions are fully handled in
-+ * 'ubifs_removexattr()'. These inodes are special and have
-+ * limited usage, so there is nothing to do here.
-+ */
-+ ubifs_assert(!ui->dirty);
-+ goto out;
-+ }
-+
-+ dbg_gen("inode %lu", inode->i_ino);
-+ ubifs_assert(!atomic_read(&inode->i_count));
-+ ubifs_assert(inode->i_nlink == 0);
-+
-+ truncate_inode_pages(&inode->i_data, 0);
-+ if (is_bad_inode(inode))
-+ goto out;
-+
-+ mutex_lock(&ui->budg_mutex);
-+
-+ inode->i_size = 0;
-+
-+ err = ubifs_jnl_write_inode(c, inode, 1, IS_SYNC(inode));
-+ if (err)
-+ /*
-+ * Worst case we have a lost orphan inode wasting space, so a
-+ * simple error message is ok here.
-+ */
-+ ubifs_err("can't write inode %lu, error %d", inode->i_ino, err);
-+
-+ if (ui->dirty) {
-+ ubifs_assert(ui->budgeted);
-+ atomic_long_dec(&c->dirty_ino_cnt);
-+ ui->dirty = 0;
-+ UBIFS_DBG(ui->budgeted = 0);
-+ ubifs_release_budget(c, &req);
-+ }
-+
-+ mutex_unlock(&ui->budg_mutex);
-+out:
-+ clear_inode(inode);
-+}
-+
-+static void ubifs_dirty_inode(struct inode *inode)
-+{
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+
-+ ubifs_assert(mutex_is_locked(&ui->budg_mutex));
-+ if (!ui->dirty) {
-+ struct ubifs_info *c = inode->i_sb->s_fs_info;
-+
-+ ui->dirty = 1;
-+ atomic_long_inc(&c->dirty_ino_cnt);
-+ dbg_gen("inode %lu", inode->i_ino);
-+ }
-+}
-+
-+static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
-+{
-+ struct ubifs_info *c = dentry->d_sb->s_fs_info;
-+ unsigned long long free;
-+
-+ free = ubifs_budg_get_free_space(c);
-+ dbg_gen("free space %lld bytes (%lld blocks)",
-+ free, free >> UBIFS_BLOCK_SHIFT);
-+
-+ buf->f_type = UBIFS_SUPER_MAGIC;
-+ buf->f_bsize = UBIFS_BLOCK_SIZE;
-+ buf->f_blocks = c->block_cnt;
-+ buf->f_bfree = free >> UBIFS_BLOCK_SHIFT;
-+ if (free > c->report_rp_size)
-+ buf->f_bavail = (free - c->report_rp_size) >> UBIFS_BLOCK_SHIFT;
-+ else
-+ buf->f_bavail = 0;
-+ buf->f_files = 0;
-+ buf->f_ffree = 0;
-+ buf->f_namelen = UBIFS_MAX_NLEN;
-+
-+ return 0;
-+}
-+
-+static int ubifs_show_options(struct seq_file *s, struct vfsmount *mnt)
-+{
-+ struct ubifs_info *c = mnt->mnt_sb->s_fs_info;
-+
-+ if (c->mount_opts.unmount_mode == 2)
-+ seq_printf(s, ",fast_unmount");
-+ else if (c->mount_opts.unmount_mode == 1)
-+ seq_printf(s, ",norm_unmount");
-+
-+ return 0;
-+}
-+
-+static int ubifs_sync_fs(struct super_block *sb, int wait)
-+{
-+ struct ubifs_info *c = sb->s_fs_info;
-+ int i, ret = 0, err;
-+
-+ if (c->jheads)
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
-+ if (err && !ret)
-+ ret = err;
-+ }
-+ /*
-+ * We ought to call sync for c->ubi but it does not have one. If it had
-+ * it would in turn call mtd->sync, however mtd operations are
-+ * synchronous anyway, so we don't lose any sleep here.
-+ */
-+ return ret;
-+}
-+
-+/**
-+ * init_constants_early - initialize UBIFS constants.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function initialize UBIFS constants which do not need the superblock to
-+ * be read. It also checks that the UBI volume satisfies basic UBIFS
-+ * requirements. Returns zero in case of success and a negative error code in
-+ * case of failure.
-+ */
-+static int init_constants_early(struct ubifs_info *c)
-+{
-+ if (c->vi.corrupted) {
-+ ubifs_warn("UBI volume is corrupted - read-only mode");
-+ c->ro_media = 1;
-+ }
-+
-+ if (c->di.ro_mode) {
-+ ubifs_msg("read-only UBI device");
-+ c->ro_media = 1;
-+ }
-+
-+ if (c->vi.vol_type == UBI_STATIC_VOLUME) {
-+ ubifs_msg("static UBI volume - read-only mode");
-+ c->ro_media = 1;
-+ }
-+
-+ c->leb_cnt = c->vi.size;
-+ c->leb_size = c->vi.usable_leb_size;
-+ c->half_leb_size = c->leb_size / 2;
-+ c->min_io_size = c->di.min_io_size;
-+ c->min_io_shift = fls(c->min_io_size) - 1;
-+
-+ if (c->leb_size < UBIFS_MIN_LEB_SZ) {
-+ ubifs_err("too small LEBs (%d bytes), min. is %d bytes",
-+ c->leb_size, UBIFS_MIN_LEB_SZ);
-+ return -EINVAL;
-+ }
-+
-+ if (c->leb_cnt < UBIFS_MIN_LEB_CNT) {
-+ ubifs_err("too few LEBs (%d), min. is %d",
-+ c->leb_cnt, UBIFS_MIN_LEB_CNT);
-+ return -EINVAL;
-+ }
-+
-+ if (!is_power_of_2(c->min_io_size)) {
-+ ubifs_err("bad min. I/O size %d", c->min_io_size);
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * UBIFS aligns all node to 8-byte boundary, so to make function in
-+ * io.c simpler, assume minimum I/O unit size to be 8 bytes if it is
-+ * less than 8.
-+ */
-+ if (c->min_io_size < 8) {
-+ c->min_io_size = 8;
-+ c->min_io_shift = 3;
-+ }
-+
-+ c->ref_node_alsz = ALIGN(UBIFS_REF_NODE_SZ, c->min_io_size);
-+ c->mst_node_alsz = ALIGN(UBIFS_MST_NODE_SZ, c->min_io_size);
-+
-+ /*
-+ * Initialize node length ranges which are mostly needed for node
-+ * length validation.
-+ */
-+ c->ranges[UBIFS_PAD_NODE].len = UBIFS_PAD_NODE_SZ;
-+ c->ranges[UBIFS_SB_NODE].len = UBIFS_SB_NODE_SZ;
-+ c->ranges[UBIFS_MST_NODE].len = UBIFS_MST_NODE_SZ;
-+ c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ;
-+ c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ;
-+ c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ;
-+
-+ c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ;
-+ c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ;
-+ c->ranges[UBIFS_ORPH_NODE].min_len =
-+ UBIFS_ORPH_NODE_SZ + sizeof(__le64);
-+ c->ranges[UBIFS_ORPH_NODE].max_len = c->leb_size;
-+ c->ranges[UBIFS_DENT_NODE].min_len = UBIFS_DENT_NODE_SZ;
-+ c->ranges[UBIFS_DENT_NODE].max_len = UBIFS_MAX_DENT_NODE_SZ;
-+ c->ranges[UBIFS_XENT_NODE].min_len = UBIFS_XENT_NODE_SZ;
-+ c->ranges[UBIFS_XENT_NODE].max_len = UBIFS_MAX_XENT_NODE_SZ;
-+ c->ranges[UBIFS_DATA_NODE].min_len = UBIFS_DATA_NODE_SZ;
-+ c->ranges[UBIFS_DATA_NODE].max_len = UBIFS_MAX_DATA_NODE_SZ;
-+ /*
-+ * Minimum indexing node size is amended later when superblock is
-+ * read and the key length is known.
-+ */
-+ c->ranges[UBIFS_IDX_NODE].min_len = UBIFS_IDX_NODE_SZ + UBIFS_BRANCH_SZ;
-+ /*
-+ * Maximum indexing node size is amended later when superblock is
-+ * read and the fanout is known.
-+ */
-+ c->ranges[UBIFS_IDX_NODE].max_len = INT_MAX;
-+
-+ /*
-+ * Initialize dead and dark LEB space watermarks.
-+ *
-+ * Dead space is the space which cannot be used. Its watermark is
-+ * equivalent to min. I/O unit or minimum node size if it is greater
-+ * then min. I/O unit.
-+ *
-+ * Dark space is the space which might be used, or might not, depending
-+ * on which node should be written to the LEB. Its watermark is
-+ * equivalent to maximum UBIFS node size.
-+ */
-+ c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size);
-+ c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size);
-+
-+ return 0;
-+}
-+
-+/**
-+ * bud_wbuf_callback - bud LEB write-buffer synchronization call-back.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB the write-buffer was synchronized to
-+ * @free: how many free bytes left in this LEB
-+ * @pad: how many bytes were padded
-+ *
-+ * This is a callback function which is called by the I/O unit when the
-+ * write-buffer is synchronized. We need this to correctly maintain space
-+ * accounting in bud logical eraseblocks. This function returns zero in case of
-+ * success and a negative error code in case of failure.
-+ *
-+ * This function actually belongs to the journal, but we keep it here because
-+ * we want to keep it static.
-+ */
-+static int bud_wbuf_callback(struct ubifs_info *c, int lnum, int free, int pad)
-+{
-+ return ubifs_update_one_lp(c, lnum, free, pad, 0, 0);
-+}
-+
-+/*
-+ * init_constants_late - initialize UBIFS constants.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This is a helper function which initializes various UBIFS constants after
-+ * the superblock has been read. It also checks various UBIFS parameters and
-+ * makes sure they are all right. Returns zero in case of success and a
-+ * negative error code in case of failure.
-+ */
-+static int init_constants_late(struct ubifs_info *c)
-+{
-+ int tmp, err;
-+ uint64_t tmp64;
-+
-+ c->main_bytes = c->main_lebs * c->leb_size;
-+
-+ c->max_znode_sz = sizeof(struct ubifs_znode) +
-+ c->fanout * sizeof(struct ubifs_zbranch);
-+
-+ tmp = ubifs_idx_node_sz(c, 1);
-+ c->ranges[UBIFS_IDX_NODE].min_len = tmp;
-+ c->min_idx_node_sz = ALIGN(tmp, 8);
-+
-+ tmp = ubifs_idx_node_sz(c, c->fanout);
-+ c->ranges[UBIFS_IDX_NODE].max_len = tmp;
-+ c->max_idx_node_sz = ALIGN(tmp, 8);
-+
-+ /* Make sure LEB size is large enough to fit full commit */
-+ tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt;
-+ tmp = ALIGN(tmp, c->min_io_size);
-+ if (tmp > c->leb_size) {
-+ dbg_err("too small LEB size %d, at least %d needed",
-+ c->leb_size, tmp);
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * Make sure that the log is large enough to fit reference nodes for
-+ * all buds plus one reserved LEB.
-+ */
-+ tmp64 = c->max_bud_bytes;
-+ tmp = do_div(tmp64, c->leb_size);
-+ c->max_bud_cnt = tmp64 + !!tmp;
-+ tmp = (c->ref_node_alsz * c->max_bud_cnt + c->leb_size - 1);
-+ tmp /= c->leb_size;
-+ tmp += 1;
-+ if (c->log_lebs < tmp) {
-+ dbg_err("too small log %d LEBs, required min. %d LEBs",
-+ c->log_lebs, tmp);
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * When budgeting we assume worst-case scenarios when the pages are not
-+ * be compressed and direntries are of the maximum size.
-+ *
-+ * Note, data, which may be stored in inodes is budgeted separately, so
-+ * it is not included into 'c->inode_budget'.
-+ */
-+ c->page_budget = UBIFS_MAX_DATA_NODE_SZ * UBIFS_BLOCKS_PER_PAGE;
-+ c->inode_budget = UBIFS_INO_NODE_SZ;
-+ c->dent_budget = UBIFS_MAX_DENT_NODE_SZ;
-+
-+ /*
-+ * When the amount of flash space used by buds becomes
-+ * 'c->max_bud_bytes', UBIFS just blocks all writers and starts commit.
-+ * The writers are unblocked when the commit is finished. To avoid
-+ * writers to be blocked UBIFS initiates background commit in advance,
-+ * when number of bud bytes becomes above the limit defined below.
-+ */
-+ c->bg_bud_bytes = (c->max_bud_bytes * 13) >> 4;
-+
-+ /*
-+ * Ensure minimum journal size. All the bytes in the journal heads are
-+ * considered to be used, when calculating the current journal usage.
-+ * Consequently, if the journal is too small, UBIFS will treat it as
-+ * always full.
-+ */
-+ tmp64 = (uint64_t)(c->jhead_cnt + 1) * c->leb_size + 1;
-+ if (c->bg_bud_bytes < tmp64)
-+ c->bg_bud_bytes = tmp64;
-+ if (c->max_bud_bytes < tmp64 + c->leb_size)
-+ c->max_bud_bytes = tmp64 + c->leb_size;
-+
-+ err = ubifs_calc_lpt_geom(c);
-+ if (err)
-+ return err;
-+
-+ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
-+
-+ /*
-+ * Calculate total amount of FS blocks. This number is not used
-+ * internally because it does not make much sense for UBIFS, but it is
-+ * necessary to report something for the 'statfs()' call.
-+ *
-+ * Subtract the LEB reserved for GC and the LEB which is reserved for
-+ * deletions.
-+ *
-+ * Review 'ubifs_calc_available()' if changing this calculation.
-+ */
-+ tmp64 = c->main_lebs - 2;
-+ tmp64 *= c->leb_size - c->dark_wm;
-+ tmp64 = ubifs_reported_space(c, tmp64);
-+ c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
-+
-+ return 0;
-+}
-+
-+/**
-+ * care_about_gc_lnum - take care about reserved GC LEB.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function ensures that the LEB reserved for garbage collection is
-+ * unmapped and is marked as "taken" in lprops. We also have to set free space
-+ * to LEB size and dirty space to zero, because lprops may contain out-of-date
-+ * information if the file-system was un-mounted before it has been committed.
-+ * This function returns zero in case of success and a negative error code in
-+ * case of failure.
-+ */
-+static int care_about_gc_lnum(struct ubifs_info *c)
-+{
-+ int err;
-+
-+ if (c->gc_lnum == -1) {
-+ ubifs_err("no LEB for GC");
-+ return -EINVAL;
-+ }
-+
-+ err = ubifs_leb_unmap(c, c->gc_lnum);
-+ if (err)
-+ return err;
-+
-+ /* And we have to tell lprops that this LEB is taken */
-+ err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0,
-+ LPROPS_TAKEN, 0, 0);
-+ return err;
-+}
-+
-+/**
-+ * alloc_wbufs - allocate write-buffers.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This helper function allocates and initializes UBIFS write-buffers. Returns
-+ * zero in case of success and %-ENOMEM in case of failure.
-+ */
-+static int alloc_wbufs(struct ubifs_info *c)
-+{
-+ int i, err;
-+
-+ c->jheads = kzalloc(c->jhead_cnt * sizeof(struct ubifs_jhead),
-+ GFP_KERNEL);
-+ if (!c->jheads)
-+ return -ENOMEM;
-+
-+ /* Initialize journal heads */
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ INIT_LIST_HEAD(&c->jheads[i].buds_list);
-+ err = ubifs_wbuf_init(c, &c->jheads[i].wbuf);
-+ if (err)
-+ return err;
-+
-+ c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback;
-+ c->jheads[i].wbuf.jhead = i;
-+ }
-+
-+ c->jheads[BASEHD].wbuf.dtype = UBI_SHORTTERM;
-+ /*
-+ * Garbage Collector head likely contains long-term data and
-+ * does not need to be synchronized by timer.
-+ */
-+ c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
-+ c->jheads[GCHD].wbuf.timeout = 0;
-+
-+ return 0;
-+}
-+
-+/**
-+ * free_wbufs - free write-buffers.
-+ * @c: UBIFS file-system description object
-+ */
-+static void free_wbufs(struct ubifs_info *c)
-+{
-+ int i;
-+
-+ if (c->jheads) {
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ kfree(c->jheads[i].wbuf.buf);
-+ kfree(c->jheads[i].wbuf.inodes);
-+ }
-+ kfree(c->jheads);
-+ c->jheads = NULL;
-+ }
-+}
-+
-+/**
-+ * free_orphans - free orphans.
-+ * @c: UBIFS file-system description object
-+ */
-+static void free_orphans(struct ubifs_info *c)
-+{
-+ struct ubifs_orphan *orph;
-+
-+ while (c->orph_dnext) {
-+ orph = c->orph_dnext;
-+ c->orph_dnext = orph->dnext;
-+ list_del(&orph->list);
-+ kfree(orph);
-+ }
-+
-+ while (!list_empty(&c->orph_list)) {
-+ orph = list_entry(c->orph_list.next, struct ubifs_orphan, list);
-+ list_del(&orph->list);
-+ kfree(orph);
-+ dbg_err("orphan list not empty at unmount");
-+ }
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->orph_buf);
-+#else
-+ vfree(c->orph_buf);
-+#endif
-+ c->orph_buf = NULL;
-+}
-+
-+/**
-+ * free_buds - free per-bud objects.
-+ * @c: UBIFS file-system description object
-+ */
-+static void free_buds(struct ubifs_info *c)
-+{
-+ struct rb_node *this = c->buds.rb_node;
-+ struct ubifs_bud *bud;
-+
-+ while (this) {
-+ if (this->rb_left)
-+ this = this->rb_left;
-+ else if (this->rb_right)
-+ this = this->rb_right;
-+ else {
-+ bud = rb_entry(this, struct ubifs_bud, rb);
-+ this = rb_parent(this);
-+ if (this) {
-+ if (this->rb_left == &bud->rb)
-+ this->rb_left = NULL;
-+ else
-+ this->rb_right = NULL;
-+ }
-+ kfree(bud);
-+ }
-+ }
-+}
-+
-+/**
-+ * check_volume_empty - check if the UBI volume is empty.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function checks if the UBIFS volume is empty by looking if its LEBs are
-+ * mapped or not. The result of checking is stored in the @c->empty variable.
-+ * Returns zero in case of success and a negative error code in case of
-+ * failure.
-+ */
-+static int check_volume_empty(struct ubifs_info *c)
-+{
-+ int lnum, err;
-+
-+ c->empty = 1;
-+ for (lnum = 0; lnum < c->leb_cnt; lnum++) {
-+ err = ubi_is_mapped(c->ubi, lnum);
-+ if (unlikely(err < 0))
-+ return err;
-+ if (err == 1) {
-+ c->empty = 0;
-+ break;
-+ }
-+
-+ cond_resched();
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * UBIFS mount options.
-+ *
-+ * Opt_fast_unmount: do not run a journal commit before un-mounting
-+ * Opt_norm_unmount: run a journal commit before un-mounting
-+ * Opt_err: just end of array marker
-+ */
-+enum {
-+ Opt_fast_unmount,
-+ Opt_norm_unmount,
-+ Opt_err,
-+};
-+
-+static match_table_t tokens = {
-+ {Opt_fast_unmount, "fast_unmount"},
-+ {Opt_norm_unmount, "norm_unmount"},
-+ {Opt_err, NULL},
-+};
-+
-+/**
-+ * ubifs_parse_options - parse mount parameters.
-+ * @c: UBIFS file-system description object
-+ * @options: parameters to parse
-+ * @is_remount: non-zero if this is FS re-mount
-+ *
-+ * This function parses UBIFS mount options and returns zero in case success
-+ * and a negative error code in case of failure.
-+ */
-+static int ubifs_parse_options(struct ubifs_info *c, char *options,
-+ int is_remount)
-+{
-+ char *p;
-+ substring_t args[MAX_OPT_ARGS];
-+
-+ if (!options)
-+ return 0;
-+
-+ while ((p = strsep(&options, ","))) {
-+ int token;
-+
-+ if (!*p)
-+ continue;
-+
-+ token = match_token(p, tokens, args);
-+ switch (token) {
-+ case Opt_fast_unmount:
-+ c->mount_opts.unmount_mode = 2;
-+ c->fast_unmount = 1;
-+ break;
-+ case Opt_norm_unmount:
-+ c->mount_opts.unmount_mode = 1;
-+ c->fast_unmount = 0;
-+ break;
-+ default:
-+ ubifs_err("unrecognized mount option \"%s\" "
-+ "or missing value", p);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * destroy_journal - destroy journal data structures.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function destroys journal data structures including those that may have
-+ * been created by recovery functions.
-+ */
-+static void destroy_journal(struct ubifs_info *c)
-+{
-+ while (!list_empty(&c->unclean_leb_list)) {
-+ struct ubifs_unclean_leb *ucleb;
-+
-+ ucleb = list_entry(c->unclean_leb_list.next,
-+ struct ubifs_unclean_leb, list);
-+ list_del(&ucleb->list);
-+ kfree(ucleb);
-+ }
-+ while (!list_empty(&c->old_buds)) {
-+ struct ubifs_bud *bud;
-+
-+ bud = list_entry(c->old_buds.next, struct ubifs_bud, list);
-+ list_del(&bud->list);
-+ kfree(bud);
-+ }
-+ ubifs_destroy_idx_gc(c);
-+ ubifs_destroy_size_tree(c);
-+ ubifs_tnc_close(c);
-+ free_buds(c);
-+}
-+
-+/**
-+ * mount_ubifs - mount UBIFS file-system.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function mounts UBIFS file system. Returns zero in case of success and
-+ * a negative error code in case of failure.
-+ *
-+ * Note, the function does not de-allocate resources it it fails half way
-+ * through, and the caller has to do this instead.
-+ */
-+static int mount_ubifs(struct ubifs_info *c)
-+{
-+ struct super_block *sb = c->vfs_sb;
-+ int err, mounted_read_only = (sb->s_flags & MS_RDONLY);
-+ unsigned long long x;
-+ size_t sz;
-+
-+ err = init_constants_early(c);
-+ if (err)
-+ return err;
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->dbg_buf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ c->dbg_buf = vmalloc(c->leb_size);
-+#endif
-+ if (!c->dbg_buf)
-+ return -ENOMEM;
-+#endif
-+
-+ err = check_volume_empty(c);
-+ if (err)
-+ goto out_free;
-+
-+ if (c->empty && (mounted_read_only || c->ro_media)) {
-+ /*
-+ * This UBI volume is empty, and read-only, or the file system
-+ * is mounted read-only - we cannot format it.
-+ */
-+ ubifs_err("can't format empty UBI volume: read-only %s",
-+ c->ro_media ? "UBI volume" : "mount");
-+ err = -EROFS;
-+ goto out_free;
-+ }
-+
-+ if (c->ro_media && !mounted_read_only) {
-+ ubifs_err("cannot mount read-write - read-only media");
-+ err = -EROFS;
-+ goto out_free;
-+ }
-+
-+ /*
-+ * The requirement for the buffer is that it should fit indexing B-tree
-+ * height amount of integers. We assume the height if the TNC tree will
-+ * never exceed 64.
-+ */
-+ err = -ENOMEM;
-+ c->bottom_up_buf = kmalloc(BOTTOM_UP_HEIGHT * sizeof(int), GFP_KERNEL);
-+ if (!c->bottom_up_buf)
-+ goto out_free;
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->sbuf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ c->sbuf = vmalloc(c->leb_size);
-+#endif
-+ if (!c->sbuf)
-+ goto out_free;
-+
-+ if (!mounted_read_only) {
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->ileb_buf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ c->ileb_buf = vmalloc(c->leb_size);
-+#endif
-+ if (!c->ileb_buf)
-+ goto out_free;
-+ }
-+
-+ err = ubifs_read_superblock(c);
-+ if (err)
-+ goto out_free;
-+
-+ /*
-+ * Make sure the compressor which is set as the default on in the
-+ * superblock was actually compiled in.
-+ */
-+ if (!ubifs_compr_present(c->default_compr)) {
-+ ubifs_warn("'%s' compressor is set by superblock, but not "
-+ "compiled in", ubifs_compr_name(c->default_compr));
-+ c->default_compr = UBIFS_COMPR_NONE;
-+ }
-+
-+ dbg_failure_mode_registration(c);
-+
-+ err = init_constants_late(c);
-+ if (err)
-+ goto out_dereg;
-+
-+ sz = ALIGN(c->max_idx_node_sz, c->min_io_size);
-+ sz = ALIGN(sz + c->max_idx_node_sz, c->min_io_size);
-+ c->cbuf = kmalloc(sz, GFP_NOFS);
-+ if (!c->cbuf) {
-+ err = -ENOMEM;
-+ goto out_dereg;
-+ }
-+
-+ if (!mounted_read_only) {
-+ err = alloc_wbufs(c);
-+ if (err)
-+ goto out_cbuf;
-+
-+ /* Create background thread */
-+ sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num,
-+ c->vi.vol_id);
-+ c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name);
-+ if (!c->bgt)
-+ c->bgt = ERR_PTR(-EINVAL);
-+ if (IS_ERR(c->bgt)) {
-+ err = PTR_ERR(c->bgt);
-+ c->bgt = NULL;
-+ ubifs_err("cannot spawn \"%s\", error %d",
-+ c->bgt_name, err);
-+ goto out_wbufs;
-+ }
-+ wake_up_process(c->bgt);
-+ }
-+
-+ err = ubifs_read_master(c);
-+ if (err)
-+ goto out_stop;
-+
-+ if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
-+ ubifs_msg("recovery needed");
-+ c->need_recovery = 1;
-+ if (!mounted_read_only) {
-+ err = ubifs_recover_inl_heads(c, c->sbuf);
-+ if (err)
-+ goto out_master;
-+ }
-+ } else if (!mounted_read_only) {
-+ /*
-+ * Set the "dirty" flag so that if we reboot uncleanly we
-+ * will notice this immediately on the next mount.
-+ */
-+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
-+ err = ubifs_write_master(c);
-+ if (err)
-+ goto out_master;
-+ }
-+
-+ err = ubifs_lpt_init(c, 1, !mounted_read_only);
-+ if (err)
-+ goto out_master;
-+
-+ err = dbg_check_idx_size(c, c->old_idx_sz);
-+ if (err)
-+ goto out_lpt;
-+
-+ err = ubifs_replay_journal(c);
-+ if (err)
-+ goto out_journal;
-+
-+ if (!mounted_read_only) {
-+ int lnum;
-+
-+ err = ubifs_mount_orphans(c, c->need_recovery);
-+ if (err)
-+ goto out_journal;
-+
-+ if (c->need_recovery)
-+ err = ubifs_recover_gc_lnum(c);
-+ else
-+ err = care_about_gc_lnum(c);
-+ if (err)
-+ goto out_orphans;
-+
-+ /* Check for enough log space */
-+ lnum = c->lhead_lnum + 1;
-+ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs)
-+ lnum = UBIFS_LOG_LNUM;
-+ if (lnum == c->ltail_lnum) {
-+ err = ubifs_consolidate_log(c);
-+ if (err)
-+ goto out_orphans;
-+ }
-+
-+ /* Check for enough free space */
-+ if (ubifs_calc_available(c) <= 0) {
-+ ubifs_err("insufficient available space");
-+ err = -EINVAL;
-+ goto out_orphans;
-+ }
-+
-+ err = dbg_check_lprops(c);
-+ if (err)
-+ goto out_orphans;
-+ }
-+
-+ if (c->need_recovery) {
-+ err = ubifs_recover_size(c);
-+ if (err)
-+ goto out_orphans;
-+ }
-+
-+ spin_lock(&ubifs_infos_lock);
-+ list_add_tail(&c->infos_list, &ubifs_infos);
-+ spin_unlock(&ubifs_infos_lock);
-+
-+ if (c->need_recovery) {
-+ if (mounted_read_only)
-+ ubifs_msg("recovery deferred");
-+ else {
-+ c->need_recovery = 0;
-+ ubifs_msg("recovery completed");
-+ }
-+ }
-+
-+ ubifs_msg("mounted UBI device %d, volume %d", c->vi.ubi_num,
-+ c->vi.vol_id);
-+ if (mounted_read_only)
-+ ubifs_msg("mounted read-only");
-+ ubifs_msg("minimal I/O unit size: %d bytes", c->min_io_size);
-+ ubifs_msg("logical eraseblock size: %d bytes (%d KiB)",
-+ c->leb_size, c->leb_size / 1024);
-+ x = (unsigned long long)c->main_lebs * c->leb_size;
-+ ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, "
-+ "%d LEBs)", x, x >> 10, x >> 20, c->main_lebs);
-+ x = (unsigned long long)c->log_lebs * c->leb_size + c->max_bud_bytes;
-+ ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, "
-+ "%d LEBs)", x, x >> 10, x >> 20,
-+ c->log_lebs + c->max_bud_cnt);
-+ ubifs_msg("data journal heads: %d",
-+ c->jhead_cnt - NONDATA_JHEADS_CNT);
-+ ubifs_msg("default compressor: %s",
-+ ubifs_compr_name(c->default_compr));
-+ ubifs_msg("media format %d, latest format %d",
-+ c->fmt_version, UBIFS_FORMAT_VERSION);
-+
-+ dbg_msg("compiled on: " __DATE__ " at " __TIME__);
-+ dbg_msg("fast unmount: %d", c->fast_unmount);
-+ dbg_msg("big_lpt %d", c->big_lpt);
-+ dbg_msg("log LEBs: %d (%d - %d)",
-+ c->log_lebs, UBIFS_LOG_LNUM, c->log_last);
-+ dbg_msg("LPT area LEBs: %d (%d - %d)",
-+ c->lpt_lebs, c->lpt_first, c->lpt_last);
-+ dbg_msg("orphan area LEBs: %d (%d - %d)",
-+ c->orph_lebs, c->orph_first, c->orph_last);
-+ dbg_msg("main area LEBs: %d (%d - %d)",
-+ c->main_lebs, c->main_first, c->leb_cnt - 1);
-+ dbg_msg("index LEBs: %d", c->lst.idx_lebs);
-+ dbg_msg("total index bytes: %lld (%lld KiB, %lld MiB)",
-+ c->old_idx_sz, c->old_idx_sz >> 10, c->old_idx_sz >> 20);
-+ dbg_msg("key hash type: %d", c->key_hash_type);
-+ dbg_msg("tree fanout: %d", c->fanout);
-+ dbg_msg("reserved GC LEB: %d", c->gc_lnum);
-+ dbg_msg("first main LEB: %d", c->main_first);
-+ dbg_msg("dead watermark: %d", c->dead_wm);
-+ dbg_msg("dark watermark: %d", c->dark_wm);
-+ x = c->main_lebs * c->dark_wm;
-+ dbg_msg("max. dark space: %lld (%lld KiB, %lld MiB)",
-+ x, x >> 10, x >> 20);
-+ dbg_msg("maximum bud bytes: %lld (%lld KiB, %lld MiB)",
-+ c->max_bud_bytes, c->max_bud_bytes >> 10,
-+ c->max_bud_bytes >> 20);
-+ dbg_msg("BG commit bud bytes: %lld (%lld KiB, %lld MiB)",
-+ c->bg_bud_bytes, c->bg_bud_bytes >> 10,
-+ c->bg_bud_bytes >> 20);
-+ dbg_msg("current bud bytes %lld (%lld KiB, %lld MiB)",
-+ c->bud_bytes, c->bud_bytes >> 10, c->bud_bytes >> 20);
-+ dbg_msg("max. seq. number: %llu", c->max_sqnum);
-+ dbg_msg("commit number: %llu", c->cmt_no);
-+
-+ return 0;
-+
-+out_orphans:
-+ free_orphans(c);
-+out_journal:
-+ destroy_journal(c);
-+out_lpt:
-+ ubifs_lpt_free(c, 0);
-+out_master:
-+ kfree(c->mst_node);
-+ kfree(c->rcvrd_mst_node);
-+out_stop:
-+ if (c->bgt)
-+ kthread_stop(c->bgt);
-+out_wbufs:
-+ free_wbufs(c);
-+out_cbuf:
-+ kfree(c->cbuf);
-+out_dereg:
-+ dbg_failure_mode_deregistration(c);
-+out_free:
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->ileb_buf);
-+ kfree(c->sbuf);
-+ UBIFS_DBG(kfree(c->dbg_buf));
-+#else
-+ vfree(c->ileb_buf);
-+ vfree(c->sbuf);
-+ UBIFS_DBG(vfree(c->dbg_buf));
-+#endif
-+ kfree(c->bottom_up_buf);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_umount - un-mount UBIFS file-system.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Note, this function is called to free allocated resourced when un-mounting,
-+ * as well as free resources when an error occurred while we were half way
-+ * through mounting (error path cleanup function). So it has to make sure the
-+ * resource was actually allocated before freeing it.
-+ */
-+static void ubifs_umount(struct ubifs_info *c)
-+{
-+ dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num,
-+ c->vi.vol_id);
-+
-+ if (c->bgt)
-+ kthread_stop(c->bgt);
-+
-+ destroy_journal(c);
-+ free_wbufs(c);
-+ free_orphans(c);
-+ ubifs_lpt_free(c, 0);
-+
-+ kfree(c->cbuf);
-+ kfree(c->rcvrd_mst_node);
-+ kfree(c->mst_node);
-+ kfree(c->bottom_up_buf);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->sbuf);
-+ UBIFS_DBG(kfree(c->dbg_buf));
-+ kfree(c->ileb_buf);
-+#else
-+ vfree(c->sbuf);
-+ UBIFS_DBG(vfree(c->dbg_buf));
-+ vfree(c->ileb_buf);
-+#endif
-+ dbg_failure_mode_deregistration(c);
-+}
-+
-+/**
-+ * ubifs_remount_rw - re-mount in read-write mode.
-+ * @c: UBIFS file-system description object
-+ *
-+ * UBIFS avoids allocating many unnecessary resources when mounted in read-only
-+ * mode. This function allocates the needed resources and re-mounts UBIFS in
-+ * read-write mode.
-+ */
-+static int ubifs_remount_rw(struct ubifs_info *c)
-+{
-+ int err, lnum;
-+
-+ if (c->ro_media)
-+ return -EINVAL;
-+
-+ mutex_lock(&c->umount_mutex);
-+ c->remounting_rw = 1;
-+
-+ /* Check for enough free space */
-+ if (ubifs_calc_available(c) <= 0) {
-+ ubifs_err("insufficient available space");
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (c->old_leb_cnt != c->leb_cnt) {
-+ struct ubifs_sb_node *sup;
-+
-+ sup = ubifs_read_sb_node(c);
-+ if (IS_ERR(sup)) {
-+ err = PTR_ERR(sup);
-+ goto out;
-+ }
-+ sup->leb_cnt = cpu_to_le32(c->leb_cnt);
-+ err = ubifs_write_sb_node(c, sup);
-+ if (err)
-+ goto out;
-+ }
-+
-+ if (c->need_recovery) {
-+ ubifs_msg("completing deferred recovery");
-+ err = ubifs_write_rcvrd_mst_node(c);
-+ if (err)
-+ goto out;
-+ err = ubifs_recover_size(c);
-+ if (err)
-+ goto out;
-+ err = ubifs_clean_lebs(c, c->sbuf);
-+ if (err)
-+ goto out;
-+ err = ubifs_recover_inl_heads(c, c->sbuf);
-+ if (err)
-+ goto out;
-+ }
-+
-+ if (!(c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY))) {
-+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
-+ err = ubifs_write_master(c);
-+ if (err)
-+ goto out;
-+ }
-+
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ c->ileb_buf = kmalloc(c->leb_size, GFP_KERNEL);
-+#else
-+ c->ileb_buf = vmalloc(c->leb_size);
-+#endif
-+ if (!c->ileb_buf) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ err = ubifs_lpt_init(c, 0, 1);
-+ if (err)
-+ goto out;
-+
-+ err = alloc_wbufs(c);
-+ if (err)
-+ goto out;
-+
-+ ubifs_create_buds_lists(c);
-+
-+ /* Create background thread */
-+ c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name);
-+ if (!c->bgt)
-+ c->bgt = ERR_PTR(-EINVAL);
-+ if (IS_ERR(c->bgt)) {
-+ err = PTR_ERR(c->bgt);
-+ c->bgt = NULL;
-+ ubifs_err("cannot spawn \"%s\", error %d",
-+ c->bgt_name, err);
-+ return err;
-+ }
-+ wake_up_process(c->bgt);
-+
-+ err = ubifs_mount_orphans(c, c->need_recovery);
-+ if (err)
-+ goto out;
-+
-+ if (c->need_recovery)
-+ err = ubifs_recover_gc_lnum(c);
-+ else
-+ err = care_about_gc_lnum(c);
-+ if (err)
-+ goto out;
-+
-+ /* Check for enough log space */
-+ lnum = c->lhead_lnum + 1;
-+ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs)
-+ lnum = UBIFS_LOG_LNUM;
-+ if (lnum == c->ltail_lnum) {
-+ err = ubifs_consolidate_log(c);
-+ if (err)
-+ goto out;
-+ }
-+
-+ if (c->need_recovery) {
-+ c->need_recovery = 0;
-+ ubifs_msg("deferred recovery completed");
-+ }
-+
-+ dbg_gen("re-mounted read-write");
-+ c->vfs_sb->s_flags &= ~MS_RDONLY;
-+ c->remounting_rw = 0;
-+ mutex_unlock(&c->umount_mutex);
-+ return 0;
-+
-+out:
-+ free_orphans(c);
-+ if (c->bgt) {
-+ kthread_stop(c->bgt);
-+ c->bgt = NULL;
-+ }
-+ free_wbufs(c);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->ileb_buf);
-+#else
-+ vfree(c->ileb_buf);
-+#endif
-+ c->ileb_buf = NULL;
-+ ubifs_lpt_free(c, 1);
-+ c->remounting_rw = 0;
-+ mutex_unlock(&c->umount_mutex);
-+ return err;
-+}
-+
-+/**
-+ * commit_on_unmount - commit the journal when un-mounting.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function is called during un-mounting and it commits the journal unless
-+ * the "fast unmount" mode is enabled. It also avoids committing the journal if
-+ * it contains too few data.
-+ *
-+ * Sometimes recovery requires the journal to be committed at least once, and
-+ * this function takes care about this.
-+ */
-+static void commit_on_unmount(struct ubifs_info *c)
-+{
-+ if (!c->fast_unmount) {
-+ long long bud_bytes;
-+
-+ spin_lock(&c->buds_lock);
-+ bud_bytes = c->bud_bytes;
-+ spin_unlock(&c->buds_lock);
-+ if (bud_bytes > c->leb_size)
-+ ubifs_run_commit(c);
-+ }
-+
-+ if (c->recovery_needs_commit)
-+ ubifs_recovery_commit(c);
-+}
-+
-+/**
-+ * ubifs_remount_ro - re-mount in read-only mode.
-+ * @c: UBIFS file-system description object
-+ *
-+ * We rely on VFS to have stopped writing. Possibly the background thread could
-+ * be running a commit, however kthread_stop will wait in that case.
-+ */
-+static void ubifs_remount_ro(struct ubifs_info *c)
-+{
-+ int i, err;
-+
-+ ubifs_assert(!c->need_recovery);
-+ commit_on_unmount(c);
-+
-+ mutex_lock(&c->umount_mutex);
-+ if (c->bgt) {
-+ kthread_stop(c->bgt);
-+ c->bgt = NULL;
-+ }
-+
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ ubifs_wbuf_sync(&c->jheads[i].wbuf);
-+ del_timer_sync(&c->jheads[i].wbuf.timer);
-+ }
-+
-+ if (!c->ro_media) {
-+ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
-+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
-+ c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
-+ err = ubifs_write_master(c);
-+ if (err)
-+ ubifs_ro_mode(c, err);
-+ }
-+
-+ ubifs_destroy_idx_gc(c);
-+ free_wbufs(c);
-+ free_orphans(c);
-+#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF)
-+ kfree(c->ileb_buf);
-+#else
-+ vfree(c->ileb_buf);
-+#endif
-+ c->ileb_buf = NULL;
-+ ubifs_lpt_free(c, 1);
-+ mutex_unlock(&c->umount_mutex);
-+}
-+
-+static void ubifs_put_super(struct super_block *sb)
-+{
-+ int i;
-+ struct ubifs_info *c = sb->s_fs_info;
-+
-+ ubifs_msg("un-mount UBI device %d, volume %d", c->vi.ubi_num,
-+ c->vi.vol_id);
-+ /*
-+ * The following asserts are only valid if there has not been a failure
-+ * of the media. For example, there will be dirty inodes if we failed
-+ * to write them back because of I/O errors.
-+ */
-+ ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0);
-+ ubifs_assert(atomic_long_read(&c->dirty_ino_cnt) == 0);
-+ ubifs_assert(c->budg_idx_growth == 0);
-+ ubifs_assert(c->budg_data_growth == 0);
-+
-+ /*
-+ * The 'c->umount_lock' prevents races between UBIFS memory shrinker
-+ * and file system un-mount. Namely, it prevents the shrinker from
-+ * picking this superblock for shrinking - it will be just skipped if
-+ * the mutex is locked.
-+ */
-+ mutex_lock(&c->umount_mutex);
-+
-+ spin_lock(&ubifs_infos_lock);
-+ list_del(&c->infos_list);
-+ spin_unlock(&ubifs_infos_lock);
-+
-+ if (!(c->vfs_sb->s_flags & MS_RDONLY)) {
-+ /*
-+ * First of all kill the background thread to make sure it does
-+ * not interfere with un-mounting and freeing resources.
-+ */
-+ if (c->bgt) {
-+ kthread_stop(c->bgt);
-+ c->bgt = NULL;
-+ }
-+
-+ /* Synchronize write-buffers */
-+ if (c->jheads)
-+ for (i = 0; i < c->jhead_cnt; i++) {
-+ ubifs_wbuf_sync(&c->jheads[i].wbuf);
-+ del_timer_sync(&c->jheads[i].wbuf.timer);
-+ }
-+
-+ /*
-+ * On fatal errors c->ro_media is set to 1, in which case we do
-+ * not write the master node.
-+ */
-+ if (!c->ro_media) {
-+ /*
-+ * We are being cleanly unmounted which means the
-+ * orphans were killed - indicate this in the master
-+ * node. Also save the reserved GC LEB number.
-+ */
-+ int err;
-+
-+ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
-+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
-+ c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
-+ err = ubifs_write_master(c);
-+ if (err)
-+ /*
-+ * Recovery will attempt to fix the master area
-+ * next mount, so we just print a message and
-+ * continue to unmount normally.
-+ */
-+ ubifs_err("failed to write master node, "
-+ "error %d", err);
-+ }
-+ }
-+
-+ ubifs_umount(c);
-+ ubi_close_volume(c->ubi);
-+ mutex_unlock(&c->umount_mutex);
-+ kfree(c);
-+}
-+
-+static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
-+{
-+ int err;
-+ struct ubifs_info *c = sb->s_fs_info;
-+
-+ dbg_gen("old flags %#lx, new flags %#x", sb->s_flags, *flags);
-+
-+ err = ubifs_parse_options(c, data, 1);
-+ if (err) {
-+ ubifs_err("invalid or unknown remount parameter");
-+ return err;
-+ }
-+ if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
-+ err = ubifs_remount_rw(c);
-+ if (err)
-+ return err;
-+ } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY))
-+ ubifs_remount_ro(c);
-+
-+ return 0;
-+}
-+
-+struct super_operations ubifs_super_operations = {
-+#ifdef UBIFS_COMPAT_USE_OLD_IGET
-+ .read_inode = ubifs_read_inode,
-+#endif
-+ .alloc_inode = ubifs_alloc_inode,
-+ .destroy_inode = ubifs_destroy_inode,
-+ .put_super = ubifs_put_super,
-+ .write_inode = ubifs_write_inode,
-+ .delete_inode = ubifs_delete_inode,
-+ .statfs = ubifs_statfs,
-+ .dirty_inode = ubifs_dirty_inode,
-+ .remount_fs = ubifs_remount_fs,
-+ .show_options = ubifs_show_options,
-+ .sync_fs = ubifs_sync_fs,
-+};
-+
-+/**
-+ * open_ubi - parse UBI device name string and open the UBI device.
-+ * @name: UBI volume name
-+ * @mode: UBI volume open mode
-+ *
-+ * There are several ways to specify UBI volumes when mounting UBIFS:
-+ * o ubiX_Y - UBI device number X, volume Y;
-+ * o ubiY - UBI device number 0, volume Y;
-+ * o ubiX:NAME - mount UBI device X, volume with name NAME;
-+ * o ubi:NAME - mount UBI device 0, volume with name NAME.
-+ *
-+ * Alternative '!' separator may be used instead of ':' (because some shells
-+ * like busybox may interpret ':' as an NFS host name separator). This function
-+ * returns ubi volume object in case of success and a negative error code in
-+ * case of failure.
-+ */
-+static struct ubi_volume_desc *open_ubi(const char *name, int mode)
-+{
-+ int dev, vol;
-+ char *endptr;
-+
-+ if (name[0] != 'u' || name[1] != 'b' || name[2] != 'i')
-+ return ERR_PTR(-EINVAL);
-+
-+ /* ubi:NAME method */
-+ if ((name[3] == ':' || name[3] == '!') && name[4] != '\0')
-+ return ubi_open_volume_nm(0, name + 4, mode);
-+
-+ if (!isdigit(name[3]))
-+ return ERR_PTR(-EINVAL);
-+
-+ dev = simple_strtoul(name + 3, &endptr, 0);
-+
-+ /* ubiY method */
-+ if (*endptr == '\0')
-+ return ubi_open_volume(0, dev, mode);
-+
-+ /* ubiX_Y method */
-+ if (*endptr == '_' && isdigit(endptr[1])) {
-+ vol = simple_strtoul(endptr + 1, &endptr, 0);
-+ if (*endptr != '\0')
-+ return ERR_PTR(-EINVAL);
-+ return ubi_open_volume(dev, vol, mode);
-+ }
-+
-+ /* ubiX:NAME method */
-+ if ((*endptr == ':' || *endptr == '!') && endptr[1] != '\0')
-+ return ubi_open_volume_nm(dev, ++endptr, mode);
-+
-+ return ERR_PTR(-EINVAL);
-+}
-+
-+static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
-+{
-+ struct ubi_volume_desc *ubi = sb->s_fs_info;
-+ struct ubifs_info *c;
-+ struct inode *root;
-+ int err;
-+
-+ c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL);
-+ if (!c)
-+ return -ENOMEM;
-+
-+ spin_lock_init(&c->cnt_lock);
-+ spin_lock_init(&c->cs_lock);
-+ spin_lock_init(&c->buds_lock);
-+ spin_lock_init(&c->space_lock);
-+ spin_lock_init(&c->orphan_lock);
-+ init_rwsem(&c->commit_sem);
-+ mutex_init(&c->lp_mutex);
-+ mutex_init(&c->tnc_mutex);
-+ mutex_init(&c->log_mutex);
-+ mutex_init(&c->mst_mutex);
-+ mutex_init(&c->umount_mutex);
-+ init_waitqueue_head(&c->cmt_wq);
-+ c->buds = RB_ROOT;
-+ c->old_idx = RB_ROOT;
-+ c->size_tree = RB_ROOT;
-+ c->orph_tree = RB_ROOT;
-+ INIT_LIST_HEAD(&c->infos_list);
-+ INIT_LIST_HEAD(&c->idx_gc);
-+ INIT_LIST_HEAD(&c->replay_list);
-+ INIT_LIST_HEAD(&c->replay_buds);
-+ INIT_LIST_HEAD(&c->uncat_list);
-+ INIT_LIST_HEAD(&c->empty_list);
-+ INIT_LIST_HEAD(&c->freeable_list);
-+ INIT_LIST_HEAD(&c->frdi_idx_list);
-+ INIT_LIST_HEAD(&c->unclean_leb_list);
-+ INIT_LIST_HEAD(&c->old_buds);
-+ INIT_LIST_HEAD(&c->orph_list);
-+ INIT_LIST_HEAD(&c->orph_new);
-+
-+ c->highest_inum = UBIFS_FIRST_INO;
-+ get_random_bytes(&c->vfs_gen, sizeof(int));
-+ c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM;
-+
-+ ubi_get_volume_info(ubi, &c->vi);
-+ ubi_get_device_info(c->vi.ubi_num, &c->di);
-+
-+ /* Re-open the UBI device in read-write mode */
-+ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE);
-+ if (IS_ERR(c->ubi)) {
-+ err = PTR_ERR(c->ubi);
-+ goto out_free;
-+ }
-+
-+ err = ubifs_parse_options(c, data, 0);
-+ if (err)
-+ goto out_close;
-+
-+ c->vfs_sb = sb;
-+
-+ sb->s_fs_info = c;
-+ sb->s_magic = UBIFS_SUPER_MAGIC;
-+ sb->s_blocksize = UBIFS_BLOCK_SIZE;
-+ sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT;
-+ sb->s_dev = c->vi.cdev;
-+ sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c);
-+ if (c->max_inode_sz > MAX_LFS_FILESIZE)
-+ sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE;
-+ sb->s_op = &ubifs_super_operations;
-+
-+ mutex_lock(&c->umount_mutex);
-+ err = mount_ubifs(c);
-+ if (err) {
-+ ubifs_assert(err < 0);
-+ goto out_unlock;
-+ }
-+
-+ /* Read the root inode */
-+ root = ubifs_iget(sb, UBIFS_ROOT_INO);
-+ if (IS_ERR(root)) {
-+ err = PTR_ERR(root);
-+ goto out_umount;
-+ }
-+
-+ sb->s_root = d_alloc_root(root);
-+ if (!sb->s_root)
-+ goto out_iput;
-+
-+ mutex_unlock(&c->umount_mutex);
-+
-+ return 0;
-+
-+out_iput:
-+ iput(root);
-+out_umount:
-+ spin_lock(&ubifs_infos_lock);
-+ list_del(&c->infos_list);
-+ spin_unlock(&ubifs_infos_lock);
-+ ubifs_umount(c);
-+out_unlock:
-+ mutex_unlock(&c->umount_mutex);
-+out_close:
-+ ubi_close_volume(c->ubi);
-+out_free:
-+ kfree(c);
-+ return err;
-+}
-+
-+static int sb_test(struct super_block *sb, void *data)
-+{
-+ dev_t *dev = data;
-+
-+ return sb->s_dev == *dev;
-+}
-+
-+static int sb_set(struct super_block *sb, void *data)
-+{
-+ dev_t *dev = data;
-+
-+ sb->s_dev = *dev;
-+ return 0;
-+}
-+
-+static int ubifs_get_sb(struct file_system_type *fs_type, int flags,
-+ const char *name, void *data, struct vfsmount *mnt)
-+{
-+ struct ubi_volume_desc *ubi;
-+ struct ubi_volume_info vi;
-+ struct super_block *sb;
-+ int err;
-+
-+ dbg_gen("name %s, flags %#x", name, flags);
-+
-+ /*
-+ * Get UBI device number and volume ID. Mount it read-only so far
-+ * because this might be a new mount point, and UBI allows only one
-+ * read-write user at a time.
-+ */
-+ ubi = open_ubi(name, UBI_READONLY);
-+ if (IS_ERR(ubi)) {
-+ ubifs_err("cannot open \"%s\", error %d",
-+ name, (int)PTR_ERR(ubi));
-+ return PTR_ERR(ubi);
-+ }
-+ ubi_get_volume_info(ubi, &vi);
-+
-+ dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id);
-+
-+ sb = sget(fs_type, &sb_test, &sb_set, &vi.cdev);
-+ if (IS_ERR(sb)) {
-+ err = PTR_ERR(sb);
-+ goto out_close;
-+ }
-+
-+ if (sb->s_root) {
-+ /* A new mount point for already mounted UBIFS */
-+ dbg_gen("this ubi volume is already mounted");
-+ if ((flags ^ sb->s_flags) & MS_RDONLY) {
-+ err = -EBUSY;
-+ goto out_deact;
-+ }
-+ } else {
-+ sb->s_flags = flags;
-+ /*
-+ * Pass 'ubi' to 'fill_super()' in sb->s_fs_info where it is
-+ * replaced by 'c'.
-+ */
-+ sb->s_fs_info = ubi;
-+ err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
-+ if (err)
-+ goto out_deact;
-+ /* We do not support atime */
-+ sb->s_flags |= MS_ACTIVE | MS_NOATIME;
-+ }
-+
-+ /* 'fill_super()' opens ubi again so we must close it here */
-+ ubi_close_volume(ubi);
-+
-+ return simple_set_mnt(mnt, sb);
-+
-+out_deact:
-+ up_write(&sb->s_umount);
-+ deactivate_super(sb);
-+out_close:
-+ ubi_close_volume(ubi);
-+ return err;
-+}
-+
-+static void ubifs_kill_sb(struct super_block *sb)
-+{
-+ struct ubifs_info *c = sb->s_fs_info;
-+
-+ /*
-+ * We do 'commit_on_unmount()' here instead of 'ubifs_put_super()'
-+ * in order to be outside BKL.
-+ */
-+ if (sb->s_root && !(sb->s_flags & MS_RDONLY))
-+ commit_on_unmount(c);
-+ /* The un-mount routine is actually done in put_super() */
-+ generic_shutdown_super(sb);
-+}
-+
-+static struct file_system_type ubifs_fs_type = {
-+ .name = "ubifs",
-+ .owner = THIS_MODULE,
-+ .get_sb = ubifs_get_sb,
-+ .kill_sb = ubifs_kill_sb
-+};
-+
-+/*
-+ * Inode slab cache constructor.
-+ */
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
-+static void inode_slab_ctor(void *obj, struct kmem_cache *cachep,
-+ unsigned long flags)
-+#else
-+static void inode_slab_ctor(struct kmem_cache *cachep, void *obj)
-+#endif
-+{
-+ struct ubifs_inode *inode = obj;
-+ inode_init_once(&inode->vfs_inode);
-+}
-+
-+static int __init ubifs_init(void)
-+{
-+ int err;
-+
-+ BUILD_BUG_ON(sizeof(struct ubifs_ch) != 24);
-+
-+ /* Make sure node sizes are 8-byte aligned */
-+ BUILD_BUG_ON(UBIFS_CH_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_INO_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_DENT_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_XENT_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_DATA_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_SB_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MST_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_REF_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_CS_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_ORPH_NODE_SZ & 7);
-+
-+ BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ & 7);
-+ BUILD_BUG_ON(UBIFS_MAX_NODE_SZ & 7);
-+ BUILD_BUG_ON(MIN_WRITE_SZ & 7);
-+
-+ /* Check min. node size */
-+ BUILD_BUG_ON(UBIFS_INO_NODE_SZ < MIN_WRITE_SZ);
-+ BUILD_BUG_ON(UBIFS_DENT_NODE_SZ < MIN_WRITE_SZ);
-+ BUILD_BUG_ON(UBIFS_XENT_NODE_SZ < MIN_WRITE_SZ);
-+ BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ < MIN_WRITE_SZ);
-+
-+ BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ > UBIFS_MAX_NODE_SZ);
-+ BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ > UBIFS_MAX_NODE_SZ);
-+ BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ > UBIFS_MAX_NODE_SZ);
-+ BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ > UBIFS_MAX_NODE_SZ);
-+
-+ /* Defined node sizes */
-+ BUILD_BUG_ON(UBIFS_SB_NODE_SZ != 4096);
-+ BUILD_BUG_ON(UBIFS_MST_NODE_SZ != 512);
-+ BUILD_BUG_ON(UBIFS_INO_NODE_SZ != 160);
-+ BUILD_BUG_ON(UBIFS_REF_NODE_SZ != 64);
-+
-+ /*
-+ * We require that PAGE_CACHE_SIZE is greater-than-or-equal-to
-+ * UBIFS_BLOCK_SIZE. It is assumed that both are powers of 2.
-+ */
-+ if (PAGE_CACHE_SIZE < UBIFS_BLOCK_SIZE) {
-+ ubifs_err("VFS page cache size is %u bytes, but UBIFS requires"
-+ " at least 4096 bytes",
-+ (unsigned int)PAGE_CACHE_SIZE);
-+ return -EINVAL;
-+ }
-+
-+ err = bdi_init(&ubifs_backing_dev_info);
-+ if (err)
-+ return err;
-+
-+ err = register_filesystem(&ubifs_fs_type);
-+ if (err) {
-+ ubifs_err("cannot register file system, error %d", err);
-+ goto out;
-+ }
-+
-+ err = -ENOMEM;
-+ ubifs_inode_slab = kmem_cache_create("ubifs_inode_slab",
-+ sizeof(struct ubifs_inode), 0,
-+ SLAB_MEM_SPREAD | SLAB_RECLAIM_ACCOUNT,
-+ &inode_slab_ctor UBIFSCOMPATNULL);
-+ if (!ubifs_inode_slab)
-+ goto out_reg;
-+
-+ register_shrinker(&ubifs_shrinker_info);
-+
-+ err = ubifs_compressors_init();
-+ if (err)
-+ goto out_compr;
-+
-+ return 0;
-+
-+out_compr:
-+ unregister_shrinker(&ubifs_shrinker_info);
-+ kmem_cache_destroy(ubifs_inode_slab);
-+out_reg:
-+ unregister_filesystem(&ubifs_fs_type);
-+out:
-+ bdi_destroy(&ubifs_backing_dev_info);
-+ return err;
-+}
-+/* late_initcall to let compressors initialize first */
-+late_initcall(ubifs_init);
-+
-+static void __exit ubifs_exit(void)
-+{
-+ ubifs_assert(list_empty(&ubifs_infos));
-+ ubifs_assert(atomic_long_read(&ubifs_clean_zn_cnt) == 0);
-+
-+ ubifs_compressors_exit();
-+ unregister_shrinker(&ubifs_shrinker_info);
-+ kmem_cache_destroy(ubifs_inode_slab);
-+ unregister_filesystem(&ubifs_fs_type);
-+ bdi_destroy(&ubifs_backing_dev_info);
-+}
-+module_exit(ubifs_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(__stringify(UBIFS_VERSION));
-+MODULE_AUTHOR("Artem Bityutskiy, Adrian Hunter");
-+MODULE_DESCRIPTION("UBIFS - UBI File System");
---- linux-2.6.24.7.old/fs/ubifs/tnc.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/tnc.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,3300 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file implements TNC (Tree Node Cache) which caches indexing nodes of
-+ * the UBIFS B-tree.
-+ *
-+ * At the moment the locking rules of the TNC tree are quite simple and
-+ * straightforward. We just have a mutex and lock it when we traverse the
-+ * tree. If a znode is not in memory, we read it from flash while still having
-+ * the mutex locked.
-+ */
-+
-+#include
-+#include "ubifs.h"
-+
-+/*
-+ * Returned codes of 'matches_name()' and 'fallible_matches_name()' functions.
-+ * @NAME_LESS: name corresponding to the first argument is less than second
-+ * @NAME_MATCHES: names match
-+ * @NAME_GREATER: name corresponding to the second argument is greater than
-+ * first
-+ * @NOT_ON_MEDIA: node referred by zbranch does not exist on the media
-+ *
-+ * These constants were introduce to improve readability.
-+ */
-+enum {
-+ NAME_LESS = 0,
-+ NAME_MATCHES = 1,
-+ NAME_GREATER = 2,
-+ NOT_ON_MEDIA = 3,
-+};
-+
-+/**
-+ * insert_old_idx - record an index node obsoleted since the last commit start.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number of obsoleted index node
-+ * @offs: offset of obsoleted index node
-+ *
-+ * Returns %0 on success, and a negative error code on failure.
-+ *
-+ * For recovery, there must always be a complete intact version of the index on
-+ * flash at all times. That is called the "old index". It is the index as at the
-+ * time of the last successful commit. Many of the index nodes in the old index
-+ * may be dirty, but they must not be erased until the next successful commit
-+ * (at which point that index becomes the old index).
-+ *
-+ * That means that the garbage collection and the in-the-gaps method of
-+ * committing must be able to determine if an index node is in the old index.
-+ * Most of the old index nodes can be found by looking up the TNC using the
-+ * 'lookup_znode()' function. However, some of the old index nodes may have
-+ * been deleted from the current index or may have been changed so much that
-+ * they cannot be easily found. In those cases, an entry is added to an RB-tree.
-+ * That is what this function does. The RB-tree is ordered by LEB number and
-+ * offset because they uniquely identify the old index node.
-+ */
-+static int insert_old_idx(struct ubifs_info *c, int lnum, int offs)
-+{
-+ struct ubifs_old_idx *old_idx, *o;
-+ struct rb_node **p, *parent = NULL;
-+
-+ old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS);
-+ if (unlikely(!old_idx))
-+ return -ENOMEM;
-+ old_idx->lnum = lnum;
-+ old_idx->offs = offs;
-+
-+ p = &c->old_idx.rb_node;
-+ while (*p) {
-+ parent = *p;
-+ o = rb_entry(parent, struct ubifs_old_idx, rb);
-+ if (lnum < o->lnum)
-+ p = &(*p)->rb_left;
-+ else if (lnum > o->lnum)
-+ p = &(*p)->rb_right;
-+ else if (offs < o->offs)
-+ p = &(*p)->rb_left;
-+ else if (offs > o->offs)
-+ p = &(*p)->rb_right;
-+ else {
-+ ubifs_err("old idx added twice!");
-+ kfree(old_idx);
-+ return 0;
-+ }
-+ }
-+ rb_link_node(&old_idx->rb, parent, p);
-+ rb_insert_color(&old_idx->rb, &c->old_idx);
-+ return 0;
-+}
-+
-+/**
-+ * insert_old_idx_znode - record a znode obsoleted since last commit start.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode of obsoleted index node
-+ *
-+ * Returns %0 on success, and a negative error code on failure.
-+ */
-+int insert_old_idx_znode(struct ubifs_info *c, struct ubifs_znode *znode)
-+{
-+ if (znode->parent) {
-+ struct ubifs_zbranch *zbr;
-+
-+ zbr = &znode->parent->zbranch[znode->iip];
-+ if (zbr->len)
-+ return insert_old_idx(c, zbr->lnum, zbr->offs);
-+ } else
-+ if (c->zroot.len)
-+ return insert_old_idx(c, c->zroot.lnum,
-+ c->zroot.offs);
-+ return 0;
-+}
-+
-+/**
-+ * ins_clr_old_idx_znode - record a znode obsoleted since last commit start.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode of obsoleted index node
-+ *
-+ * Returns %0 on success, and a negative error code on failure.
-+ */
-+static int ins_clr_old_idx_znode(struct ubifs_info *c,
-+ struct ubifs_znode *znode)
-+{
-+ int err;
-+
-+ if (znode->parent) {
-+ struct ubifs_zbranch *zbr;
-+
-+ zbr = &znode->parent->zbranch[znode->iip];
-+ if (zbr->len) {
-+ err = insert_old_idx(c, zbr->lnum, zbr->offs);
-+ if (err)
-+ return err;
-+ zbr->lnum = 0;
-+ zbr->offs = 0;
-+ zbr->len = 0;
-+ }
-+ } else
-+ if (c->zroot.len) {
-+ err = insert_old_idx(c, c->zroot.lnum, c->zroot.offs);
-+ if (err)
-+ return err;
-+ c->zroot.lnum = 0;
-+ c->zroot.offs = 0;
-+ c->zroot.len = 0;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * destroy_old_idx - destroy the old_idx RB-tree.
-+ * @c: UBIFS file-system description object
-+ *
-+ * During start commit, the old_idx RB-tree is used to avoid overwriting index
-+ * nodes that were in the index last commit but have since been deleted. This
-+ * is necessary for recovery i.e. the old index must be kept intact until the
-+ * new index is successfully written. The old-idx RB-tree is used for the
-+ * in-the-gaps method of writing index nodes and is destroyed every commit.
-+ */
-+void destroy_old_idx(struct ubifs_info *c)
-+{
-+ struct rb_node *this = c->old_idx.rb_node;
-+ struct ubifs_old_idx *old_idx;
-+
-+ while (this) {
-+ if (this->rb_left) {
-+ this = this->rb_left;
-+ continue;
-+ } else if (this->rb_right) {
-+ this = this->rb_right;
-+ continue;
-+ }
-+ old_idx = rb_entry(this, struct ubifs_old_idx, rb);
-+ this = rb_parent(this);
-+ if (this) {
-+ if (this->rb_left == &old_idx->rb)
-+ this->rb_left = NULL;
-+ else
-+ this->rb_right = NULL;
-+ }
-+ kfree(old_idx);
-+ }
-+ c->old_idx = RB_ROOT;
-+}
-+
-+/**
-+ * read_znode - read an indexing node from flash and fill znode.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB of the indexing node to read
-+ * @offs: node offset
-+ * @len: node length
-+ * @znode: znode to read to
-+ *
-+ * This function reads an indexing node from the flash media and fills znode
-+ * with the read data. Returns zero in case of success and a negative error
-+ * code in case of failure. The read indexing node is validated and if anything
-+ * is wrong with it, this function prints complaint messages and returns
-+ * %-EINVAL.
-+ */
-+static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
-+ struct ubifs_znode *znode)
-+{
-+ int i, err, type, cmp;
-+ struct ubifs_idx_node *idx;
-+
-+ idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
-+ if (!idx)
-+ return -ENOMEM;
-+
-+ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
-+ if (err < 0)
-+ goto out;
-+
-+ znode->child_cnt = le16_to_cpu(idx->child_cnt);
-+ znode->level = le16_to_cpu(idx->level);
-+
-+ dbg_tnc("LEB %d:%d, level %d, %d branch",
-+ lnum, offs, znode->level, znode->child_cnt);
-+
-+ if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) {
-+ dbg_err("current fanout %d, branch count %d",
-+ c->fanout, znode->child_cnt);
-+ dbg_err("max levels %d, znode level %d",
-+ UBIFS_MAX_LEVELS, znode->level);
-+ goto out_dump;
-+ }
-+
-+ for (i = 0; i < znode->child_cnt; i++) {
-+ const struct ubifs_branch *br = ubifs_idx_branch(c, idx, i);
-+ struct ubifs_zbranch *zbr = &znode->zbranch[i];
-+
-+ key_read(c, &br->key, &zbr->key);
-+ zbr->lnum = le32_to_cpu(br->lnum);
-+ zbr->offs = le32_to_cpu(br->offs);
-+ zbr->len = le32_to_cpu(br->len);
-+ zbr->znode = NULL;
-+
-+ /* Validate branch */
-+
-+ if (zbr->lnum < c->main_first ||
-+ zbr->lnum >= c->leb_cnt || zbr->offs < 0 ||
-+ zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) {
-+ dbg_err("bad branch %d", i);
-+ goto out_dump;
-+ }
-+
-+ switch (key_type(c, &zbr->key)) {
-+ case UBIFS_INO_KEY:
-+ case UBIFS_DATA_KEY:
-+ case UBIFS_DENT_KEY:
-+ case UBIFS_XENT_KEY:
-+ break;
-+ default:
-+ dbg_msg("bad key type at slot %d: %s", i,
-+ DBGKEY(&zbr->key));
-+ goto out_dump;
-+ }
-+
-+ if (znode->level)
-+ continue;
-+
-+ type = key_type(c, &zbr->key);
-+ if (c->ranges[type].max_len == 0) {
-+ if (zbr->len != c->ranges[type].len) {
-+ dbg_err("bad target node (type %d) length (%d)",
-+ type, zbr->len);
-+ dbg_err("have to be %d", c->ranges[type].len);
-+ goto out_dump;
-+ }
-+ } else if (zbr->len < c->ranges[type].min_len ||
-+ zbr->len > c->ranges[type].max_len) {
-+ dbg_err("bad target node (type %d) length (%d)",
-+ type, zbr->len);
-+ dbg_err("have to be in range of %d-%d",
-+ c->ranges[type].min_len,
-+ c->ranges[type].max_len);
-+ goto out_dump;
-+ }
-+ }
-+
-+ /*
-+ * Ensure that the next key is greater or equivalent to the
-+ * previous one.
-+ */
-+ for (i = 0; i < znode->child_cnt - 1; i++) {
-+ const union ubifs_key *key1, *key2;
-+
-+ key1 = &znode->zbranch[i].key;
-+ key2 = &znode->zbranch[i + 1].key;
-+
-+ cmp = keys_cmp(c, key1, key2);
-+ if (cmp > 0) {
-+ dbg_err("bad key order (keys %d and %d)", i, i + 1);
-+ goto out_dump;
-+ } else if (cmp == 0 && !is_hash_key(c, key1)) {
-+ /* These can only be keys with colliding hash */
-+ dbg_err("keys %d and %d are not hashed but equivalent",
-+ i, i + 1);
-+ goto out_dump;
-+ }
-+ }
-+
-+ kfree(idx);
-+ return 0;
-+
-+out:
-+ kfree(idx);
-+ return err;
-+
-+out_dump:
-+ ubifs_err("bad indexing node at LEB %d:%d", lnum, offs);
-+ dbg_dump_node(c, idx);
-+ kfree(idx);
-+ return -EINVAL;
-+}
-+
-+/**
-+ * load_znode - load znode to TNC cache.
-+ * @c: UBIFS file-system description object
-+ * @zbr: znode branch
-+ * @parent: znode's parent
-+ * @iip: index in parent
-+ *
-+ * This function loads znode pointed to by @zbr into the TNC cache and
-+ * returns pointer to it in case of success and a negative error code in case
-+ * of failure.
-+ */
-+static struct ubifs_znode *load_znode(struct ubifs_info *c,
-+ struct ubifs_zbranch *zbr,
-+ struct ubifs_znode *parent, int iip)
-+{
-+ int err;
-+ struct ubifs_znode *znode;
-+
-+ ubifs_assert(!zbr->znode);
-+ /*
-+ * A slab cache is not presently used for znodes because the znode size
-+ * depends on the fanout which is stored in the superblock.
-+ */
-+ znode = kzalloc(c->max_znode_sz, GFP_NOFS);
-+ if (!znode)
-+ return ERR_PTR(-ENOMEM);
-+
-+ err = read_znode(c, zbr->lnum, zbr->offs, zbr->len, znode);
-+ if (err)
-+ goto out;
-+
-+ atomic_long_inc(&c->clean_zn_cnt);
-+
-+ /*
-+ * Increment the global clean znode counter as well. It is OK that
-+ * global and per-FS clean znode counters may be inconsistent for some
-+ * short time (because we might be preempted at this point), the global
-+ * one is only used in shrinker.
-+ */
-+ atomic_long_inc(&ubifs_clean_zn_cnt);
-+
-+ zbr->znode = znode;
-+ znode->parent = parent;
-+ znode->time = get_seconds();
-+ znode->iip = iip;
-+
-+ return znode;
-+
-+out:
-+ kfree(znode);
-+ return ERR_PTR(err);
-+}
-+
-+/**
-+ * copy_znode - copy a dirty znode.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode to copy
-+ *
-+ * A dirty znode being committed may not be changed, so it is copied.
-+ */
-+static struct ubifs_znode *copy_znode(struct ubifs_info *c,
-+ struct ubifs_znode *znode)
-+{
-+ struct ubifs_znode *zn;
-+
-+ zn = kmalloc(c->max_znode_sz, GFP_NOFS);
-+ if (unlikely(!zn))
-+ return ERR_PTR(-ENOMEM);
-+
-+ memcpy(zn, znode, c->max_znode_sz);
-+ zn->cnext = NULL;
-+ __set_bit(DIRTY_ZNODE, &zn->flags);
-+ __clear_bit(COW_ZNODE, &zn->flags);
-+
-+ ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
-+ __set_bit(OBSOLETE_ZNODE, &znode->flags);
-+
-+ if (znode->level != 0) {
-+ int i;
-+ const int n = zn->child_cnt;
-+
-+ /* The children now have new parent */
-+ for (i = 0; i < n; i++) {
-+ struct ubifs_zbranch *zbr = &zn->zbranch[i];
-+
-+ if (zbr->znode)
-+ zbr->znode->parent = zn;
-+ }
-+ }
-+
-+ atomic_long_inc(&c->dirty_zn_cnt);
-+ return zn;
-+}
-+
-+/**
-+ * add_idx_dirt - add dirt due to a dirty znode.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number of index node
-+ * @dirt: size of index node
-+ *
-+ * This function updates lprops dirty space and the new size of the index.
-+ */
-+static int add_idx_dirt(struct ubifs_info *c, int lnum, int dirt)
-+{
-+ c->calc_idx_sz -= ALIGN(dirt, 8);
-+ return ubifs_add_dirt(c, lnum, dirt);
-+}
-+
-+/**
-+ * dirty_cow_znode - ensure a znode is not being committed.
-+ * @c: UBIFS file-system description object
-+ * @zbr: branch of znode to check
-+ *
-+ * Returns dirtied znode on success or negative error code on failure.
-+ */
-+static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,
-+ struct ubifs_zbranch *zbr)
-+{
-+ struct ubifs_znode *znode = zbr->znode;
-+ struct ubifs_znode *zn;
-+ int err;
-+
-+ if (!test_bit(COW_ZNODE, &znode->flags)) {
-+ /* znode is not being committed */
-+ if (!test_and_set_bit(DIRTY_ZNODE, &znode->flags)) {
-+ atomic_long_inc(&c->dirty_zn_cnt);
-+ atomic_long_dec(&c->clean_zn_cnt);
-+ atomic_long_dec(&ubifs_clean_zn_cnt);
-+ err = add_idx_dirt(c, zbr->lnum, zbr->len);
-+ if (unlikely(err))
-+ return ERR_PTR(err);
-+ }
-+ return znode;
-+ }
-+
-+ zn = copy_znode(c, znode);
-+ if (unlikely(IS_ERR(zn)))
-+ return zn;
-+
-+ if (zbr->len) {
-+ err = insert_old_idx(c, zbr->lnum, zbr->offs);
-+ if (unlikely(err))
-+ return ERR_PTR(err);
-+ err = add_idx_dirt(c, zbr->lnum, zbr->len);
-+ } else
-+ err = 0;
-+
-+ zbr->znode = zn;
-+ zbr->lnum = 0;
-+ zbr->offs = 0;
-+ zbr->len = 0;
-+
-+ if (unlikely(err))
-+ return ERR_PTR(err);
-+ return zn;
-+}
-+
-+/**
-+ * lnc_add - add a leaf node to the leaf node cache.
-+ * @c: UBIFS file-system description object
-+ * @zbr: zbranch of leaf node
-+ * @node: leaf node
-+ *
-+ * Leaf nodes are non-index nodes directory entry nodes or data nodes. The
-+ * purpose of the leaf node cache is to save re-reading the same leaf node over
-+ * and over again. Most things are cached by VFS, however the file system must
-+ * cache directory entries for readdir and for resolving hash collisions. The
-+ * present implementation of the leaf node cache is extremely simple, and
-+ * allows for error returns that are not used but that may be needed if a more
-+ * complex implementation is created.
-+ *
-+ * Note, this function does not add the @node object to LNC directly, but
-+ * allocates a copy of the object and adds the copy to LNC. The reason for this
-+ * is that @node has been allocated outside of the TNC subsystem and will be
-+ * used with @c->tnc_mutex unlock upon return from the TNC subsystem. But LNC
-+ * may be changed at any time, e.g. freed by the shrinker.
-+ */
-+static int lnc_add(struct ubifs_info *c, struct ubifs_zbranch *zbr,
-+ const void *node)
-+{
-+ int err;
-+ void *lnc_node;
-+ const struct ubifs_dent_node *dent = node;
-+
-+ ubifs_assert(!zbr->leaf);
-+ ubifs_assert(zbr->len != 0);
-+ ubifs_assert(is_hash_key(c, &zbr->key));
-+
-+ err = ubifs_validate_entry(c, dent);
-+ if (err) {
-+ dbg_dump_stack();
-+ dbg_dump_node(c, dent);
-+ return err;
-+ }
-+
-+ lnc_node = kmalloc(zbr->len, GFP_NOFS);
-+ if (!lnc_node)
-+ /* We don't have to have the cache, so no error */
-+ return 0;
-+
-+ memcpy(lnc_node, node, zbr->len);
-+ zbr->leaf = lnc_node;
-+ return 0;
-+}
-+
-+ /**
-+ * lnc_add_directly - add a leaf node to the leaf-node-cache.
-+ * @c: UBIFS file-system description object
-+ * @zbr: zbranch of leaf node
-+ * @node: leaf node
-+ *
-+ * This function is similar to 'lnc_add()', but it does not create a copy of
-+ * @node but inserts @node to TNC directly.
-+ */
-+static int lnc_add_directly(struct ubifs_info *c, struct ubifs_zbranch *zbr,
-+ void *node)
-+{
-+ int err;
-+
-+ ubifs_assert(!zbr->leaf);
-+ ubifs_assert(zbr->len != 0);
-+
-+ err = ubifs_validate_entry(c, node);
-+ if (err) {
-+ dbg_dump_stack();
-+ dbg_dump_node(c, node);
-+ return err;
-+ }
-+
-+ zbr->leaf = node;
-+ return 0;
-+}
-+
-+/**
-+ * lnc_free - remove a leaf node from the leaf node cache.
-+ * @zbr: zbranch of leaf node
-+ * @node: leaf node
-+ */
-+static void lnc_free(struct ubifs_zbranch *zbr)
-+{
-+ if (!zbr->leaf)
-+ return;
-+ kfree(zbr->leaf);
-+ zbr->leaf = NULL;
-+}
-+
-+/**
-+ * tnc_read_node - read a leaf node from the flash media.
-+ * @c: UBIFS file-system description object
-+ * @zbr: key and position of the node
-+ * @node: node is returned here
-+ *
-+ * This function reads a node defined by @zbr from the flash media. Returns
-+ * zero in case of success or a negative negative error code in case of
-+ * failure.
-+ */
-+static int tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
-+ void *node)
-+{
-+ union ubifs_key key1, *key = &zbr->key;
-+ int err, type = key_type(c, key);
-+ struct ubifs_wbuf *wbuf;
-+
-+ ubifs_assert(!zbr->leaf);
-+
-+ /*
-+ * 'zbr' has to point to on-flash node. The node may sit in a bud and
-+ * may even be in a write buffer, so we have to take care about this.
-+ */
-+ wbuf = ubifs_get_wbuf(c, zbr->lnum);
-+ if (wbuf)
-+ err = ubifs_read_node_wbuf(wbuf, node, type, zbr->len,
-+ zbr->lnum, zbr->offs);
-+ else
-+ err = ubifs_read_node(c, node, type, zbr->len, zbr->lnum,
-+ zbr->offs);
-+
-+ if (err) {
-+ dbg_tnc("key %s", DBGKEY(key));
-+ return err;
-+ }
-+
-+ /* Make sure the key of the read node is correct */
-+ key_read(c, key, &key1);
-+ if (memcmp(node + UBIFS_KEY_OFFSET, &key1, c->key_len)) {
-+ ubifs_err("bad key in node at LEB %d:%d",
-+ zbr->lnum, zbr->offs);
-+ dbg_tnc("looked for key %s found node's key %s",
-+ DBGKEY(key), DBGKEY1(&key1));
-+ dbg_dump_node(c, node);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * tnc_read_node_nm - read a "hashed" leaf node.
-+ * @c: UBIFS file-system description object
-+ * @zbr: key and position of the node
-+ * @node: node is returned here
-+ *
-+ * This function reads a "hashed" node defined by @zbr from the leaf node cache
-+ * (in it is there) or from the hash media, in which case the node is also
-+ * added to LNC. Returns zero in case of success or a negative negative error
-+ * code in case of failure.
-+ */
-+static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr,
-+ void *node)
-+{
-+ int err;
-+
-+ ubifs_assert(is_hash_key(c, &zbr->key));
-+
-+ if (zbr->leaf) {
-+ /* Read from the leaf node cache */
-+ ubifs_assert(zbr->len != 0);
-+ memcpy(node, zbr->leaf, zbr->len);
-+ return 0;
-+ }
-+
-+ err = tnc_read_node(c, zbr, node);
-+ if (err)
-+ return err;
-+
-+ /* Add the node to the leaf node cache */
-+ err = lnc_add(c, zbr, node);
-+ return err;
-+}
-+
-+/**
-+ * try_read_node - read a node if it is a node.
-+ * @c: UBIFS file-system description object
-+ * @buf: buffer to read to
-+ * @type: node type
-+ * @len: node length (not aligned)
-+ * @lnum: LEB number of node to read
-+ * @offs: offset of node to read
-+ *
-+ * This function tries to read a node of known type and length, checks it and
-+ * stores it in @buf. This function returns %1 if a node is present and %0 if
-+ * a node is not present. A negative error code is returned for I/O errors.
-+ * This function performs that same function as ubifs_read_node except that
-+ * it does not require that there is actually a node present and instead
-+ * the return code indicates if a node was read.
-+ */
-+static int try_read_node(const struct ubifs_info *c, void *buf, int type,
-+ int len, int lnum, int offs)
-+{
-+ int err, node_len;
-+ struct ubifs_ch *ch = buf;
-+ uint32_t crc, node_crc;
-+
-+ dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
-+
-+ err = ubi_read(c->ubi, lnum, buf, offs, len);
-+ if (err) {
-+ ubifs_err("cannot read node type %d from LEB %d:%d, error %d",
-+ type, lnum, offs, err);
-+ return err;
-+ }
-+
-+ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC)
-+ return 0;
-+
-+ if (ch->node_type != type)
-+ return 0;
-+
-+ node_len = le32_to_cpu(ch->len);
-+ if (node_len != len)
-+ return 0;
-+
-+ crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
-+ node_crc = le32_to_cpu(ch->crc);
-+ if (crc != node_crc)
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/**
-+ * fallible_read_node - try to read a leaf node.
-+ * @c: UBIFS file-system description object
-+ * @key: key of node to read
-+ * @zbr: position of node
-+ * @node: node returned
-+ *
-+ * This function tries to read a node and returns %1 if the node is read, %0
-+ * if the node is not present, and a negative error code in the case of error.
-+ */
-+static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,
-+ struct ubifs_zbranch *zbr, void *node)
-+{
-+ int ret;
-+
-+ dbg_tnc("LEB %d:%d, key %s", zbr->lnum, zbr->offs, DBGKEY(key));
-+
-+ ret = try_read_node(c, node, key_type(c, key), zbr->len, zbr->lnum,
-+ zbr->offs);
-+ if (ret == 1) {
-+ union ubifs_key node_key;
-+ struct ubifs_dent_node *dent = node;
-+
-+ /* All nodes have key in the same place */
-+ key_read(c, &dent->key, &node_key);
-+ if (keys_cmp(c, key, &node_key) != 0)
-+ ret = 0;
-+ }
-+ if (ret == 0)
-+ dbg_mnt("dangling branch LEB %d:%d len %d, key %s",
-+ zbr->lnum, zbr->offs, zbr->len, DBGKEY(key));
-+ return ret;
-+}
-+
-+/**
-+ * matches_name - determine if a directory or extended attribute entry matches
-+ * a given name.
-+ * @c: UBIFS file-system description object
-+ * @zbr: zbranch of dent
-+ * @nm: name to match
-+ *
-+ * This function checks if xentry/direntry referred by zbranch @zbr matches name
-+ * @nm. Returns %NAME_MATCHES if it does, %NAME_LESS if the name referred by
-+ * @zbr is less than @nm, and %NAME_GREATER if it is greater than @nm. In case
-+ * of failure, a negative error code is returned.
-+ */
-+static int matches_name(struct ubifs_info *c, struct ubifs_zbranch *zbr,
-+ const struct qstr *nm)
-+{
-+ struct ubifs_dent_node *dent;
-+ int nlen, err;
-+
-+ /* If possible, match against the dent in the leaf node cache */
-+ if (!zbr->leaf) {
-+ dent = kmalloc(zbr->len, GFP_NOFS);
-+ if (!dent)
-+ return -ENOMEM;
-+
-+ err = tnc_read_node(c, zbr, dent);
-+ if (err)
-+ goto out_free;
-+
-+ /* Add the node to the leaf node cache */
-+ err = lnc_add_directly(c, zbr, dent);
-+ if (err)
-+ goto out_free;
-+ } else
-+ dent = zbr->leaf;
-+
-+ nlen = le16_to_cpu(dent->nlen);
-+ err = memcmp(dent->name, nm->name, min_t(int, nlen, nm->len));
-+ if (err == 0) {
-+ if (nlen == nm->len)
-+ return NAME_MATCHES;
-+ else if (nlen < nm->len)
-+ return NAME_LESS;
-+ else
-+ return NAME_GREATER;
-+ } else if (err < 0)
-+ return NAME_LESS;
-+ else
-+ return NAME_GREATER;
-+
-+out_free:
-+ kfree(dent);
-+ return err;
-+}
-+
-+/**
-+ * get_znode - get a TNC znode that may not be loaded yet.
-+ * @c: UBIFS file-system description object
-+ * @znode: parent znode
-+ * @n: znode branch slot number
-+ *
-+ * This function returns the znode or a negative error code.
-+ */
-+static struct ubifs_znode *get_znode(struct ubifs_info *c,
-+ struct ubifs_znode *znode, int n)
-+{
-+ struct ubifs_zbranch *zbr;
-+
-+ zbr = &znode->zbranch[n];
-+ if (zbr->znode)
-+ znode = zbr->znode;
-+ else
-+ znode = load_znode(c, zbr, znode, n);
-+ return znode;
-+}
-+
-+/**
-+ * tnc_next - find next TNC entry.
-+ * @c: UBIFS file-system description object
-+ * @zn: znode is passed and returned here
-+ * @n: znode branch slot number is passed and returned here
-+ *
-+ * This function returns %0 if the next TNC entry is found, %-ENOENT if there is
-+ * no next entry, or a negative error code otherwise.
-+ */
-+static int tnc_next(struct ubifs_info *c, struct ubifs_znode **zn, int *n)
-+{
-+ struct ubifs_znode *znode = *zn;
-+ int nn = *n;
-+
-+ nn += 1;
-+ if (nn < znode->child_cnt) {
-+ *n = nn;
-+ return 0;
-+ }
-+ while (1) {
-+ struct ubifs_znode *zp;
-+
-+ zp = znode->parent;
-+ if (!zp)
-+ return -ENOENT;
-+ nn = znode->iip + 1;
-+ znode = zp;
-+ if (nn < znode->child_cnt) {
-+ znode = get_znode(c, znode, nn);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ while (znode->level != 0) {
-+ znode = get_znode(c, znode, 0);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ }
-+ nn = 0;
-+ break;
-+ }
-+ }
-+ *zn = znode;
-+ *n = nn;
-+ return 0;
-+}
-+
-+/**
-+ * tnc_prev - find previous TNC entry.
-+ * @c: UBIFS file-system description object
-+ * @zn: znode is returned here
-+ * @n: znode branch slot number is passed and returned here
-+ *
-+ * This function returns %0 if the previous TNC entry is found, %-ENOENT if
-+ * there is no next entry, or a negative error code otherwise.
-+ */
-+static int tnc_prev(struct ubifs_info *c, struct ubifs_znode **zn, int *n)
-+{
-+ struct ubifs_znode *znode = *zn;
-+ int nn = *n;
-+
-+ if (nn > 0) {
-+ *n = nn - 1;
-+ return 0;
-+ }
-+ while (1) {
-+ struct ubifs_znode *zp;
-+
-+ zp = znode->parent;
-+ if (!zp)
-+ return -ENOENT;
-+ nn = znode->iip - 1;
-+ znode = zp;
-+ if (nn >= 0) {
-+ znode = get_znode(c, znode, nn);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ while (znode->level != 0) {
-+ nn = znode->child_cnt - 1;
-+ znode = get_znode(c, znode, nn);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ }
-+ nn = znode->child_cnt - 1;
-+ break;
-+ }
-+ }
-+ *zn = znode;
-+ *n = nn;
-+ return 0;
-+}
-+
-+/**
-+ * resolve_collision - resolve a collision.
-+ * @c: UBIFS file-system description object
-+ * @key: key of a directory or extended attribute entry
-+ * @zn: znode is returned here
-+ * @n: zbranch number is passed and returned here
-+ * @nm: name of the entry
-+ *
-+ * This function is called for "hashed" keys to make sure that the found key
-+ * really corresponds to the looked up node (directory or extended attribute
-+ * entry). It returns %1 and sets @zn and @n if the collision is resolved.
-+ * %0 is returned if @nm is not found and @zn and @n are set to the previous
-+ * entry, i.e. to the entry after which @nm could follow if it were in TNC.
-+ * This means that @n may be set to %-1 if the leftmost key in @zn is the
-+ * previous one. A negative error code is returned on failures.
-+ */
-+static int resolve_collision(struct ubifs_info *c, const union ubifs_key *key,
-+ struct ubifs_znode **zn, int *n,
-+ const struct qstr *nm)
-+{
-+ int err;
-+
-+ err = matches_name(c, &(*zn)->zbranch[*n], nm);
-+ if (unlikely(err < 0))
-+ return err;
-+ if (err == NAME_MATCHES)
-+ return 1;
-+
-+ if (err == NAME_GREATER) {
-+ /* Look left */
-+ while (1) {
-+ err = tnc_prev(c, zn, n);
-+ if (err == -ENOENT) {
-+ ubifs_assert(*n == 0);
-+ *n = -1;
-+ return 0;
-+ }
-+ if (err < 0)
-+ return err;
-+ if (keys_cmp(c, &(*zn)->zbranch[*n].key, key)) {
-+ /*
-+ * We have found the branch after which we would
-+ * like to insert, but inserting in this znode
-+ * may still be wrong. Consider the following 3
-+ * znodes, in the case where we are resolving a
-+ * collision with Key2.
-+ *
-+ * znode zp
-+ * ----------------------
-+ * level 1 | Key0 | Key1 |
-+ * -----------------------
-+ * | |
-+ * znode za | | znode zb
-+ * ------------ ------------
-+ * level 0 | Key0 | | Key2 |
-+ * ------------ ------------
-+ *
-+ * The lookup finds Key2 in znode zb. Lets say
-+ * there is no match and the name is greater so
-+ * we look left. When we find Key0, we end up
-+ * here. If we return now, we will insert into
-+ * znode za at slot n = 1. But that is invalid
-+ * according to the parent's keys. Key2 must
-+ * be inserted into znode zb.
-+ *
-+ * Note, this problem is not relevant for the
-+ * case when we go right, because
-+ * 'tnc_insert()' would correct the parent key.
-+ */
-+ if (*n == (*zn)->child_cnt - 1) {
-+ err = tnc_next(c, zn, n);
-+ if (err) {
-+ /* Should be impossible */
-+ ubifs_assert(0);
-+ if (err == -ENOENT)
-+ err = -EINVAL;
-+ return err;
-+ }
-+ ubifs_assert(*n == 0);
-+ *n = -1;
-+ }
-+ return 0;
-+ }
-+ err = matches_name(c, &(*zn)->zbranch[*n], nm);
-+ if (err < 0)
-+ return err;
-+ if (err == NAME_LESS)
-+ return 0;
-+ if (err == NAME_MATCHES)
-+ return 1;
-+ ubifs_assert(err == NAME_GREATER);
-+ }
-+ } else {
-+ int nn = *n;
-+ struct ubifs_znode *znode = *zn;
-+
-+ /* Look right */
-+ while (1) {
-+ err = tnc_next(c, &znode, &nn);
-+ if (err == -ENOENT)
-+ return 0;
-+ if (err < 0)
-+ return err;
-+ if (keys_cmp(c, &znode->zbranch[nn].key, key))
-+ return 0;
-+ err = matches_name(c, &znode->zbranch[nn], nm);
-+ if (err < 0)
-+ return err;
-+ if (err == NAME_GREATER)
-+ return 0;
-+ *zn = znode;
-+ *n = nn;
-+ if (err == NAME_MATCHES)
-+ return 1;
-+ ubifs_assert(err == NAME_LESS);
-+ }
-+ }
-+}
-+
-+/**
-+ * fallible_matches_name - determine if a dent matches a given name.
-+ * @c: UBIFS file-system description object
-+ * @zbr: zbranch of dent
-+ * @nm: name to match
-+ *
-+ * This is a "fallible" version of 'matches_name()' function which does not
-+ * panic if the direntry/xentry referred by @zbr does not exist on the media.
-+ *
-+ * This function checks if xentry/direntry referred by zbranch @zbr matches name
-+ * @nm. Returns %NAME_MATCHES it does, %NAME_LESS if the name referred by @zbr
-+ * is less than @nm, %NAME_GREATER if it is greater than @nm, and @NOT_ON_MEDIA
-+ * if xentry/direntry referred by @zbr does not exist on the media. A negative
-+ * error code is returned in case of failure.
-+ */
-+static int fallible_matches_name(struct ubifs_info *c,
-+ struct ubifs_zbranch *zbr,
-+ const struct qstr *nm)
-+{
-+ struct ubifs_dent_node *dent;
-+ int nlen, err;
-+
-+ /* If possible, match against the dent in the leaf node cache */
-+ if (!zbr->leaf) {
-+ dent = kmalloc(zbr->len, GFP_NOFS);
-+ if (!dent)
-+ return -ENOMEM;
-+
-+ err = fallible_read_node(c, &zbr->key, zbr, dent);
-+ if (err < 0)
-+ goto out_free;
-+ if (err == 0) {
-+ /* The node was not present */
-+ err = NOT_ON_MEDIA;
-+ goto out_free;
-+ }
-+ ubifs_assert(err == 1);
-+
-+ err = lnc_add_directly(c, zbr, dent);
-+ if (err)
-+ goto out_free;
-+ } else
-+ dent = zbr->leaf;
-+
-+ nlen = le16_to_cpu(dent->nlen);
-+ err = memcmp(dent->name, nm->name, min_t(int, nlen, nm->len));
-+ if (err == 0) {
-+ if (nlen == nm->len)
-+ return NAME_MATCHES;
-+ else if (nlen < nm->len)
-+ return NAME_LESS;
-+ else
-+ return NAME_GREATER;
-+ } else if (err < 0)
-+ return NAME_LESS;
-+ else
-+ return NAME_GREATER;
-+
-+out_free:
-+ kfree(dent);
-+ return err;
-+}
-+
-+/**
-+ * fallible_resolve_collision - resolve a collision even if nodes are missing.
-+ * @c: UBIFS file-system description object
-+ * @key: key
-+ * @zn: znode is returned here
-+ * @n: branch number is passed and returned here
-+ * @nm: name of directory entry
-+ * @adding: indicates caller is adding a key to the TNC
-+ *
-+ * This is a "fallible" version of the 'resolve_collision()' function which
-+ * does not panic if one of the nodes referred to by TNC does not exist on the
-+ * media. This may happen when replaying the journal if a deleted node was
-+ * Garbage-collected and the commit was not done. A branch that refers to a node
-+ * that is not present is called a dangling branch. The following are the return
-+ * codes for this function:
-+ * o if @nm was found, %1 is returned and @zn and @n are set to the found
-+ * branch;
-+ * o if we are @adding and @nm was not found, %0 is returned;
-+ * o if we are not @adding and @nm was not found, but a dangling branch was
-+ * found, then %1 is returned and @zn and @n are set to the dangling branch;
-+ * o a negative error code is returned in case of failure.
-+ */
-+static int fallible_resolve_collision(struct ubifs_info *c,
-+ const union ubifs_key *key,
-+ struct ubifs_znode **zn, int *n,
-+ const struct qstr *nm, int adding)
-+{
-+ struct ubifs_znode *o_znode = NULL, *znode = *zn;
-+ int uninitialized_var(o_n), err, cmp, unsure = 0, nn = *n;
-+
-+ cmp = fallible_matches_name(c, &znode->zbranch[nn], nm);
-+ if (unlikely(cmp < 0))
-+ return cmp;
-+ if (cmp == NAME_MATCHES)
-+ return 1;
-+ if (cmp == NOT_ON_MEDIA) {
-+ o_znode = znode;
-+ o_n = nn;
-+ /*
-+ * We are unlucky and hit a dangling branch straight away.
-+ * Now we do not really know where to go to find the needed
-+ * branch - to the left or to the right. Well, let's try left.
-+ */
-+ unsure = 1;
-+ } else if (!adding)
-+ unsure = 1; /* Remove a dangling branch wherever it is */
-+
-+ if (cmp == NAME_GREATER || unsure) {
-+ /* Look left */
-+ while (1) {
-+ err = tnc_prev(c, zn, n);
-+ if (err == -ENOENT) {
-+ ubifs_assert(*n == 0);
-+ *n = -1;
-+ break;
-+ }
-+ if (err < 0)
-+ return err;
-+ if (keys_cmp(c, &(*zn)->zbranch[*n].key, key)) {
-+ /* See comments in 'resolve_collision()' */
-+ if (*n == (*zn)->child_cnt - 1) {
-+ err = tnc_next(c, zn, n);
-+ if (err) {
-+ /* Should be impossible */
-+ ubifs_assert(0);
-+ if (err == -ENOENT)
-+ err = -EINVAL;
-+ return err;
-+ }
-+ ubifs_assert(*n == 0);
-+ *n = -1;
-+ }
-+ break;
-+ }
-+ err = fallible_matches_name(c, &(*zn)->zbranch[*n], nm);
-+ if (err < 0)
-+ return err;
-+ if (err == NAME_MATCHES)
-+ return 1;
-+ if (err == NOT_ON_MEDIA) {
-+ o_znode = *zn;
-+ o_n = *n;
-+ continue;
-+ }
-+ if (!adding)
-+ continue;
-+ if (err == NAME_LESS)
-+ break;
-+ else
-+ unsure = 0;
-+ }
-+ }
-+
-+ if (cmp == NAME_LESS || unsure) {
-+ /* Look right */
-+ *zn = znode;
-+ *n = nn;
-+ while (1) {
-+ err = tnc_next(c, &znode, &nn);
-+ if (err == -ENOENT)
-+ break;
-+ if (err < 0)
-+ return err;
-+ if (keys_cmp(c, &znode->zbranch[nn].key, key))
-+ break;
-+ err = fallible_matches_name(c, &znode->zbranch[nn], nm);
-+ if (err < 0)
-+ return err;
-+ if (err == NAME_GREATER)
-+ break;
-+ *zn = znode;
-+ *n = nn;
-+ if (err == NAME_MATCHES)
-+ return 1;
-+ if (err == NOT_ON_MEDIA) {
-+ o_znode = znode;
-+ o_n = nn;
-+ }
-+ }
-+ }
-+
-+ /* Never match a dangling branch when adding */
-+ if (adding || !o_znode)
-+ return 0;
-+
-+ dbg_mnt("dangling match LEB %d:%d len %d %s",
-+ o_znode->zbranch[o_n].lnum, o_znode->zbranch[o_n].offs,
-+ o_znode->zbranch[o_n].len, DBGKEY(key));
-+ *zn = o_znode;
-+ *n = o_n;
-+ return 1;
-+}
-+
-+/**
-+ * matches_position - determine if a zbranch matches a given position.
-+ * @zbr: zbranch of dent
-+ * @lnum: LEB number of dent to match
-+ * @offs: offset of dent to match
-+ *
-+ * This function returns %1 if @lnum:@offs matches, and %0 otherwise.
-+ */
-+static int matches_position(struct ubifs_zbranch *zbr, int lnum, int offs)
-+{
-+ if (zbr->lnum == lnum && zbr->offs == offs)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+/**
-+ * resolve_collision_directly - resolve a collision directly.
-+ * @c: UBIFS file-system description object
-+ * @key: key of directory entry
-+ * @zn: znode is passed and returned here
-+ * @n: zbranch number is passed and returned here
-+ * @lnum: LEB number of dent node to match
-+ * @offs: offset of dent node to match
-+ *
-+ * This function is used for "hashed" keys to make sure the found directory or
-+ * extended attribute entry node is what was looked for. It is used when the
-+ * flash address of the right node is known (@lnum:@offs) which makes it much
-+ * easier to resolve collisions (no need to read entries and match full
-+ * names). This function returns %1 and sets @zn and @n if the collision is
-+ * resolved, %0 if @lnum:@offs is not found and @zn and @n are set to the
-+ * previous directory entry. Otherwise a negative error code is returned.
-+ */
-+static int resolve_collision_directly(struct ubifs_info *c,
-+ const union ubifs_key *key,
-+ struct ubifs_znode **zn, int *n,
-+ int lnum, int offs)
-+{
-+ struct ubifs_znode *znode;
-+ int nn, err;
-+
-+ znode = *zn;
-+ nn = *n;
-+ if (matches_position(&znode->zbranch[nn], lnum, offs))
-+ return 1;
-+
-+ /* Look left */
-+ while (1) {
-+ err = tnc_prev(c, &znode, &nn);
-+ if (err == -ENOENT)
-+ break;
-+ if (err < 0)
-+ return err;
-+ if (keys_cmp(c, &znode->zbranch[nn].key, key))
-+ break;
-+ if (matches_position(&znode->zbranch[nn], lnum, offs)) {
-+ *zn = znode;
-+ *n = nn;
-+ return 1;
-+ }
-+ }
-+
-+ /* Look right */
-+ znode = *zn;
-+ nn = *n;
-+ while (1) {
-+ err = tnc_next(c, &znode, &nn);
-+ if (err == -ENOENT)
-+ return 0;
-+ if (err < 0)
-+ return err;
-+ if (keys_cmp(c, &znode->zbranch[nn].key, key))
-+ return 0;
-+ *zn = znode;
-+ *n = nn;
-+ if (matches_position(&znode->zbranch[nn], lnum, offs))
-+ return 1;
-+ }
-+}
-+
-+/**
-+ * dirty_cow_bottom_up - dirty a znode and its ancestors.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode to dirty
-+ *
-+ * If we do not have a unique key that resides in a znode, then we cannot
-+ * dirty that znode from the top down (i.e. by using lookup_level0_dirty)
-+ * This function records the path back to the last dirty ancestor, and then
-+ * dirties the znodes on that path.
-+ */
-+static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c,
-+ struct ubifs_znode *znode)
-+{
-+ struct ubifs_znode *zp;
-+ int *path = c->bottom_up_buf, p = 0;
-+
-+ ubifs_assert(c->zroot.znode);
-+ ubifs_assert(znode);
-+ if (c->zroot.znode->level > BOTTOM_UP_HEIGHT) {
-+ kfree(c->bottom_up_buf);
-+ c->bottom_up_buf = kmalloc(c->zroot.znode->level * sizeof(int),
-+ GFP_NOFS);
-+ if (!c->bottom_up_buf)
-+ return ERR_PTR(-ENOMEM);
-+ path = c->bottom_up_buf;
-+ }
-+ if (c->zroot.znode->level) {
-+ /* Go up until parent is dirty */
-+ while (1) {
-+ int n;
-+
-+ zp = znode->parent;
-+ if (!zp)
-+ break;
-+ n = znode->iip;
-+ ubifs_assert(p < c->zroot.znode->level);
-+ path[p++] = n;
-+ if (!zp->cnext && ubifs_zn_dirty(znode))
-+ break;
-+ znode = zp;
-+ }
-+ }
-+
-+ /* Come back down, dirtying as we go */
-+ while (1) {
-+ struct ubifs_zbranch *zbr;
-+
-+ zp = znode->parent;
-+ if (zp) {
-+ ubifs_assert(path[p - 1] >= 0);
-+ ubifs_assert(path[p - 1] < zp->child_cnt);
-+ zbr = &zp->zbranch[path[--p]];
-+ znode = dirty_cow_znode(c, zbr);
-+ } else {
-+ ubifs_assert(znode == c->zroot.znode);
-+ znode = dirty_cow_znode(c, &c->zroot);
-+ }
-+ if (unlikely(IS_ERR(znode)) || !p)
-+ break;
-+ ubifs_assert(path[p - 1] >= 0);
-+ ubifs_assert(path[p - 1] < znode->child_cnt);
-+ znode = znode->zbranch[path[p - 1]].znode;
-+ }
-+
-+ return znode;
-+}
-+
-+/**
-+ * lookup_level0 - search for zero-level znode.
-+ * @c: UBIFS file-system description object
-+ * @key: key to lookup
-+ * @zn: znode is returned here
-+ * @n: znode branch slot number is returned here
-+ *
-+ * This function looks up the TNC tree and search for zero-level znode which
-+ * refers key @key. The found zero-level znode is returned in @zn. There are 3
-+ * cases:
-+ * o exact match, i.e. the found zero-level znode contains key @key, then %1
-+ * is returned and slot number of the matched branch is stored in @n;
-+ * o not exact match, which means that zero-level znode does not contain
-+ * @key, then %0 is returned and slot number of the closed branch is stored
-+ * in @n;
-+ * o @key is so small that it is even less than the lowest key of the
-+ * leftmost zero-level node, then %0 is returned and %0 is stored in @n.
-+ *
-+ * Note, when the TNC tree is traversed, some znodes may be absent, then this
-+ * function reads corresponding indexing nodes and inserts them to TNC. In
-+ * case of failure, a negative error code is returned.
-+ */
-+static int lookup_level0(struct ubifs_info *c, const union ubifs_key *key,
-+ struct ubifs_znode **zn, int *n)
-+{
-+ int err, exact;
-+ struct ubifs_znode *znode;
-+ unsigned long time = get_seconds();
-+
-+ dbg_tnc("search key %s", DBGKEY(key));
-+
-+ znode = c->zroot.znode;
-+ if (unlikely(!znode)) {
-+ znode = load_znode(c, &c->zroot, NULL, 0);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ }
-+
-+ znode->time = time;
-+
-+ while (1) {
-+ struct ubifs_zbranch *zbr;
-+
-+ exact = ubifs_search_zbranch(c, znode, key, n);
-+
-+ if (znode->level == 0)
-+ break;
-+
-+ if (*n < 0)
-+ *n = 0;
-+ zbr = &znode->zbranch[*n];
-+
-+ if (zbr->znode) {
-+ znode->time = time;
-+ znode = zbr->znode;
-+ continue;
-+ }
-+
-+ /* znode is not in TNC cache, load it from the media */
-+ znode = load_znode(c, zbr, znode, *n);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ }
-+
-+ *zn = znode;
-+ if (exact || !is_hash_key(c, key) || *n != -1) {
-+ dbg_tnc("found %d, lvl %d, n %d", exact, znode->level, *n);
-+ return exact;
-+ }
-+
-+ /*
-+ * Here is a tricky place. We have not found the key and this is a
-+ * "hashed" key, which may collide. The rest of the code deals with
-+ * situations like this:
-+ *
-+ * | 3 | 5 |
-+ * / \
-+ * | 3 | 5 | | 6 | 7 | (x)
-+ *
-+ * Or more a complex example:
-+ *
-+ * | 1 | 5 |
-+ * / \
-+ * | 1 | 3 | | 5 | 8 |
-+ * \ /
-+ * | 5 | 5 | | 6 | 7 | (x)
-+ *
-+ * In the examples, if we are looking for key "5", we may reach nodes
-+ * marked with "(x)". In this case what we have do is to look at the
-+ * left and see if there is "5" key there. If there is, we have to
-+ * return it.
-+ *
-+ * Note, this whole situation is possible because we allow to have
-+ * elements which are equivalent to the next key in the parent in the
-+ * children of current znode. For example, this happens if we split a
-+ * znode like this: | 3 | 5 | 5 | 6 | 7 |, which results in something
-+ * like this:
-+ * | 3 | 5 |
-+ * / \
-+ * | 3 | 5 | | 5 | 6 | 7 |
-+ * ^
-+ * And this becomes what is at the first "picture" after key "5" marked
-+ * with "^" is removed. What could be done is we could prohibit
-+ * splitting in the middle of the colliding sequence. Also, when
-+ * removing the leftmost key, we would have to correct the key of the
-+ * parent node, which would introduce additional complications. Namely,
-+ * if we changed the the leftmost key of the parent znode, the garbage
-+ * collector would be unable to find it (GC is doing this when GC'ing
-+ * indexing LEBs). Although we already have an additional RB-tree where
-+ * we save such changed znodes (see 'ins_clr_old_idx_znode()') until
-+ * after the commit. But anyway, this does not look easy to implement
-+ * so we did not try this.
-+ */
-+ err = tnc_prev(c, &znode, n);
-+ if (err == -ENOENT) {
-+ dbg_tnc("found 0, lvl %d, n -1", znode->level);
-+ *n = -1;
-+ return 0;
-+ }
-+ if (unlikely(err < 0))
-+ return err;
-+ if (keys_cmp(c, key, &znode->zbranch[*n].key)) {
-+ dbg_tnc("found 0, lvl %d, n -1", znode->level);
-+ *n = -1;
-+ return 0;
-+ }
-+
-+ dbg_tnc("found 1, lvl %d, n %d", znode->level, *n);
-+ *zn = znode;
-+ return 1;
-+}
-+
-+/**
-+ * lookup_level0_dirty - search for zero-level znode dirtying.
-+ * @c: UBIFS file-system description object
-+ * @key: key to lookup
-+ * @zn: znode is returned here
-+ * @n: znode branch slot number is returned here
-+ *
-+ * This function looks up the TNC tree and search for zero-level znode which
-+ * refers key @key. The found zero-level znode is returned in @zn. There are 3
-+ * cases:
-+ * o exact match, i.e. the found zero-level znode contains key @key, then %1
-+ * is returned and slot number of the matched branch is stored in @n;
-+ * o not exact match, which means that zero-level znode does not contain @key
-+ * then %0 is returned and slot number of the closed branch is stored in
-+ * @n;
-+ * o @key is so small that it is even less than the lowest key of the
-+ * leftmost zero-level node, then %0 is returned and %-1 is stored in @n.
-+ *
-+ * Additionally all znodes in the path from the root to the located zero-level
-+ * znode are marked as dirty.
-+ *
-+ * Note, when the TNC tree is traversed, some znodes may be absent, then this
-+ * function reads corresponding indexing nodes and inserts them to TNC. In
-+ * case of failure, a negative error code is returned.
-+ */
-+static int lookup_level0_dirty(struct ubifs_info *c, const union ubifs_key *key,
-+ struct ubifs_znode **zn, int *n)
-+{
-+ int err, exact;
-+ struct ubifs_znode *znode;
-+ unsigned long time = get_seconds();
-+
-+ dbg_tnc("search and dirty key %s", DBGKEY(key));
-+
-+ znode = c->zroot.znode;
-+ if (unlikely(!znode)) {
-+ znode = load_znode(c, &c->zroot, NULL, 0);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ }
-+
-+ znode = dirty_cow_znode(c, &c->zroot);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+
-+ znode->time = time;
-+
-+ while (1) {
-+ struct ubifs_zbranch *zbr;
-+
-+ exact = ubifs_search_zbranch(c, znode, key, n);
-+
-+ if (znode->level == 0)
-+ break;
-+
-+ if (*n < 0)
-+ *n = 0;
-+ zbr = &znode->zbranch[*n];
-+
-+ if (zbr->znode) {
-+ znode->time = time;
-+ znode = dirty_cow_znode(c, zbr);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ continue;
-+ }
-+
-+ /* znode is not in TNC cache, load it from the media */
-+ znode = load_znode(c, zbr, znode, *n);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ znode = dirty_cow_znode(c, zbr);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ }
-+
-+ *zn = znode;
-+ if (exact || !is_hash_key(c, key) || *n != -1) {
-+ dbg_tnc("found %d, lvl %d, n %d", exact, znode->level, *n);
-+ return exact;
-+ }
-+
-+ /*
-+ * See huge comment at 'lookup_level0_dirty()' what is the rest of the
-+ * code.
-+ */
-+ err = tnc_prev(c, &znode, n);
-+ if (err == -ENOENT) {
-+ *n = -1;
-+ dbg_tnc("found 0, lvl %d, n -1", znode->level);
-+ return 0;
-+ }
-+ if (unlikely(err < 0))
-+ return err;
-+ if (keys_cmp(c, key, &znode->zbranch[*n].key)) {
-+ *n = -1;
-+ dbg_tnc("found 0, lvl %d, n -1", znode->level);
-+ return 0;
-+ }
-+
-+ if (znode->cnext || !ubifs_zn_dirty(znode)) {
-+ znode = dirty_cow_bottom_up(c, znode);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ }
-+
-+ dbg_tnc("found 1, lvl %d, n %d", znode->level, *n);
-+ *zn = znode;
-+ return 1;
-+}
-+
-+/**
-+ * ubifs_tnc_lookup - look up a file-system node.
-+ * @c: UBIFS file-system description object
-+ * @key: node key to lookup
-+ * @node: the node is returned here
-+ *
-+ * This function look up and reads node with key @key. The caller has to make
-+ * sure the @node buffer is large enough to fit the node. Returns zero in case
-+ * of success, %-ENOENT if the node was not found, and a negative error code in
-+ * case of failure.
-+ */
-+int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key,
-+ void *node)
-+{
-+ int found, n, err;
-+ struct ubifs_znode *znode;
-+ struct ubifs_zbranch zbr, *zt;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ found = lookup_level0(c, key, &znode, &n);
-+ if (!found) {
-+ err = -ENOENT;
-+ goto out;
-+ } else if (found < 0) {
-+ err = found;
-+ goto out;
-+ }
-+ zt = &znode->zbranch[n];
-+ if (is_hash_key(c, key)) {
-+ /*
-+ * In this case the leaf node cache gets used, so we pass the
-+ * address of the zbranch and keep the mutex locked
-+ */
-+ err = tnc_read_node_nm(c, zt, node);
-+ goto out;
-+ }
-+ zbr = znode->zbranch[n];
-+ mutex_unlock(&c->tnc_mutex);
-+
-+ err = tnc_read_node(c, &zbr, node);
-+ return err;
-+
-+out:
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_tnc_locate - look up a file-system node and return it and its location.
-+ * @c: UBIFS file-system description object
-+ * @key: node key to lookup
-+ * @node: the node is returned here
-+ * @lnum: LEB number is returned here
-+ * @offs: offset is returned here
-+ *
-+ * This function is the same as 'ubifs_tnc_lookup()' but it returns the node
-+ * location also. See 'ubifs_tnc_lookup()'.
-+ */
-+int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
-+ void *node, int *lnum, int *offs)
-+{
-+ int found, n, err;
-+ struct ubifs_znode *znode;
-+ struct ubifs_zbranch zbr, *zt;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ found = lookup_level0(c, key, &znode, &n);
-+ if (!found) {
-+ err = -ENOENT;
-+ goto out;
-+ } else if (found < 0) {
-+ err = found;
-+ goto out;
-+ }
-+ zt = &znode->zbranch[n];
-+ if (is_hash_key(c, key)) {
-+ /*
-+ * In this case the leaf node cache gets used, so we pass the
-+ * address of the zbranch and keep the mutex locked
-+ */
-+ *lnum = zt->lnum;
-+ *offs = zt->offs;
-+ err = tnc_read_node_nm(c, zt, node);
-+ goto out;
-+ }
-+ zbr = znode->zbranch[n];
-+ mutex_unlock(&c->tnc_mutex);
-+
-+ *lnum = zbr.lnum;
-+ *offs = zbr.offs;
-+
-+ err = tnc_read_node(c, &zbr, node);
-+ return err;
-+
-+out:
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * do_lookup_nm- look up a "hashed" node.
-+ * directory entry file-system node.
-+ * @c: UBIFS file-system description object
-+ * @key: node key to lookup
-+ * @node: the node is returned here
-+ * @nm: node name
-+ *
-+ * This function look up and reads a node which contains name hash in the key.
-+ * Since the hash may have collisions, there may be many nodes with the same
-+ * key, so we have to sequentially look to all of them until the needed one is
-+ * found. This function returns zero in case of success, %-ENOENT if the node
-+ * was not found, and a negative error code in case of failure.
-+ */
-+static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
-+ void *node, const struct qstr *nm)
-+{
-+ int found, n, err;
-+ struct ubifs_znode *znode;
-+ struct ubifs_zbranch zbr;
-+
-+ dbg_tnc("name '%.*s' key %s", nm->len, nm->name, DBGKEY(key));
-+ mutex_lock(&c->tnc_mutex);
-+ found = lookup_level0(c, key, &znode, &n);
-+ if (!found) {
-+ err = -ENOENT;
-+ goto out_unlock;
-+ } else if (found < 0) {
-+ err = found;
-+ goto out_unlock;
-+ }
-+
-+ ubifs_assert(n >= 0);
-+
-+ err = resolve_collision(c, key, &znode, &n, nm);
-+ dbg_tnc("rc returned %d, znode %p, n %d", err, znode, n);
-+ if (unlikely(err < 0))
-+ goto out_unlock;
-+ if (err == 0) {
-+ err = -ENOENT;
-+ goto out_unlock;
-+ }
-+
-+ zbr = znode->zbranch[n];
-+ mutex_unlock(&c->tnc_mutex);
-+
-+ err = tnc_read_node_nm(c, &zbr, node);
-+ return err;
-+
-+out_unlock:
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_tnc_lookup_nm- look up a "hashed" node.
-+ * directory entry file-system node.
-+ * @c: UBIFS file-system description object
-+ * @key: node key to lookup
-+ * @node: the node is returned here
-+ * @nm: node name
-+ *
-+ * This function look up and reads a node which contains name hash in the key.
-+ * Since the hash may have collisions, there may be many nodes with the same
-+ * key, so we have to sequentially look to all of them until the needed one is
-+ * found. This function returns zero in case of success, %-ENOENT if the node
-+ * was not found, and a negative error code in case of failure.
-+ */
-+int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
-+ void *node, const struct qstr *nm)
-+{
-+ int err, len;
-+ const struct ubifs_dent_node *dent = node;
-+
-+ /*
-+ * We assume that in most of the cases there are no name collisions and
-+ * 'ubifs_tnc_lookup()' returns us the right direntry.
-+ */
-+ err = ubifs_tnc_lookup(c, key, node);
-+ if (err)
-+ return err;
-+
-+ len = le16_to_cpu(dent->nlen);
-+ if (nm->len == len && !memcmp(dent->name, nm->name, len))
-+ return 0;
-+
-+ /*
-+ * Unluckily, there are hash collisions and we have to iterate over
-+ * them look at each direntry with colliding name hash sequentially.
-+ */
-+ return do_lookup_nm(c, key, node, nm);
-+}
-+
-+/**
-+ * correct_parent_keys - correct parent znodes' keys.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode to correct parent znodes for
-+ *
-+ * This is a helper function for 'tnc_insert()'. When the key of the leftmost
-+ * zbranch changes, keys of parent znodes have to be corrected. This helper
-+ * function is called in such situations and corrects the keys if needed.
-+ */
-+static void correct_parent_keys(const struct ubifs_info *c,
-+ struct ubifs_znode *znode)
-+{
-+ union ubifs_key *key, *key1;
-+
-+ ubifs_assert(znode->parent);
-+ ubifs_assert(znode->iip == 0);
-+
-+ key = &znode->zbranch[0].key;
-+ key1 = &znode->parent->zbranch[0].key;
-+
-+ while (keys_cmp(c, key, key1) < 0) {
-+ key_copy(c, key, key1);
-+ znode = znode->parent;
-+ if (!znode->parent || znode->iip)
-+ break;
-+ key1 = &znode->parent->zbranch[0].key;
-+ }
-+}
-+
-+/**
-+ * insert_zbranch - insert a zbranch into a znode.
-+ * @znode: znode into which to insert
-+ * @zbr: zbranch to insert
-+ * @n: slot number to insert to
-+ *
-+ * This is a helper function for 'tnc_insert()'. UBIFS does not allow "gaps" in
-+ * znode's array of zbranches and keeps zbranches consolidated, so when a new
-+ * zbranch has to be inserted to the @znode->zbranches[]' array at the @n-th
-+ * slot, zbranches starting from @n have to be moved right.
-+ */
-+static void insert_zbranch(struct ubifs_znode *znode,
-+ const struct ubifs_zbranch *zbr, int n)
-+{
-+ int i;
-+
-+ ubifs_assert(ubifs_zn_dirty(znode));
-+
-+ if (znode->level) {
-+ for (i = znode->child_cnt; i > n; i--) {
-+ znode->zbranch[i] = znode->zbranch[i - 1];
-+ if (znode->zbranch[i].znode)
-+ znode->zbranch[i].znode->iip = i;
-+ }
-+ if (zbr->znode)
-+ zbr->znode->iip = n;
-+ } else
-+ for (i = znode->child_cnt; i > n; i--)
-+ znode->zbranch[i] = znode->zbranch[i - 1];
-+
-+ znode->zbranch[n] = *zbr;
-+ znode->child_cnt += 1;
-+
-+ /*
-+ * After inserting at slot zero, the lower bound of the key range of
-+ * this znode may have changed. If this znode is subsequently split
-+ * then the upper bound of the key range may change, and furthermore
-+ * it could change to be lower than the original lower bound. If that
-+ * happens, then it will no longer be possible to find this znode in the
-+ * TNC using the key from the index node on flash. That is bad because
-+ * if it is not found, we will assume it is obsolete and may overwrite
-+ * it. Then if there is an unclean unmount, we will start using the
-+ * old index which will be broken.
-+ *
-+ * So we first mark znodes that have insertions at slot zero, and then
-+ * if they are split we add their lnum/offs to the old_idx tree.
-+ */
-+ if (n == 0)
-+ znode->alt = 1;
-+}
-+
-+/**
-+ * tnc_insert - insert a node into TNC.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode to insert into
-+ * @zbr: branch to insert
-+ * @n: slot number to insert new zbranch to
-+ *
-+ * This function inserts a new node described by @zbr into znode @znode. If
-+ * znode does not have a free slot for new zbranch, it is split. Parent znodes
-+ * are splat as well if needed. Returns zero in case of success or a negative
-+ * error code in case of failure.
-+ */
-+static int tnc_insert(struct ubifs_info *c, struct ubifs_znode *znode,
-+ struct ubifs_zbranch *zbr, int n)
-+{
-+ struct ubifs_znode *zn, *zi, *zp;
-+ int i, keep, move, appending = 0;
-+ union ubifs_key *key = &zbr->key;
-+
-+ ubifs_assert(n >= 0 && n <= c->fanout);
-+
-+ /* Implement naive insert for now */
-+again:
-+ zp = znode->parent;
-+ if (znode->child_cnt < c->fanout) {
-+ ubifs_assert(n != c->fanout);
-+ dbg_tnc("inserted at %d level %d, key %s", n, znode->level,
-+ DBGKEY(key));
-+
-+ insert_zbranch(znode, zbr, n);
-+
-+ /* Ensure parent's key is correct */
-+ if (n == 0 && zp && znode->iip == 0)
-+ correct_parent_keys(c, znode);
-+
-+ return 0;
-+ }
-+
-+ /*
-+ * Unfortunately, @znode does not have more empty slots and we have to
-+ * split it.
-+ */
-+ dbg_tnc("splitting level %d, key %s", znode->level, DBGKEY(key));
-+
-+ if (znode->alt)
-+ /*
-+ * We can no longer be sure of finding this znode by key, so we
-+ * record it in the old_idx tree.
-+ */
-+ ins_clr_old_idx_znode(c, znode);
-+
-+ zn = kzalloc(c->max_znode_sz, GFP_NOFS);
-+ if (!zn)
-+ return -ENOMEM;
-+ zn->parent = zp;
-+ zn->level = znode->level;
-+
-+ /* Decide where to split */
-+ if (znode->level == 0 && n == c->fanout &&
-+ key_type(c, key) == UBIFS_DATA_KEY) {
-+ union ubifs_key *key1;
-+
-+ /*
-+ * If this is an inode which is being appended - do not split
-+ * it because no other zbranches can be inserted between
-+ * zbranches of consecutive data nodes anyway.
-+ */
-+ key1 = &znode->zbranch[n - 1].key;
-+ if (key_ino(c, key1) == key_ino(c, key) &&
-+ key_type(c, key1) == UBIFS_DATA_KEY &&
-+ key_block(c, key1) == key_block(c, key) - 1)
-+ appending = 1;
-+ }
-+
-+ if (appending) {
-+ keep = c->fanout;
-+ move = 0;
-+ } else {
-+ keep = (c->fanout + 1) / 2;
-+ move = c->fanout - keep;
-+ }
-+
-+ /*
-+ * Although we don't at present, we could look at the neighbors and see
-+ * if we can move some zbranches there.
-+ */
-+
-+ if (n < keep) {
-+ /* Insert into existing znode */
-+ zi = znode;
-+ move += 1;
-+ keep -= 1;
-+ } else {
-+ /* Insert into new znode */
-+ zi = zn;
-+ n -= keep;
-+ /* Re-parent */
-+ if (zn->level != 0)
-+ zbr->znode->parent = zn;
-+ }
-+
-+ __set_bit(DIRTY_ZNODE, &zn->flags);
-+ atomic_long_inc(&c->dirty_zn_cnt);
-+
-+ zn->child_cnt = move;
-+ znode->child_cnt = keep;
-+
-+ dbg_tnc("moving %d, keeping %d", move, keep);
-+
-+ /* Move zbranch */
-+ for (i = 0; i < move; i++) {
-+ zn->zbranch[i] = znode->zbranch[keep + i];
-+ /* Re-parent */
-+ if (zn->level != 0)
-+ if (zn->zbranch[i].znode) {
-+ zn->zbranch[i].znode->parent = zn;
-+ zn->zbranch[i].znode->iip = i;
-+ }
-+ }
-+
-+ /* Insert new key and branch */
-+ dbg_tnc("inserting at %d level %d, key %s", n, zn->level, DBGKEY(key));
-+
-+ insert_zbranch(zi, zbr, n);
-+
-+ /* Insert new znode (produced by spitting) into the parent */
-+ if (zp) {
-+ i = n;
-+ /* Locate insertion point */
-+ n = znode->iip + 1;
-+ if (appending && n != c->fanout)
-+ appending = 0;
-+
-+ if (i == 0 && zi == znode && znode->iip == 0)
-+ correct_parent_keys(c, znode);
-+
-+ /* Tail recursion */
-+ zbr->key = zn->zbranch[0].key;
-+ zbr->znode = zn;
-+ zbr->lnum = 0;
-+ zbr->offs = 0;
-+ zbr->len = 0;
-+ znode = zp;
-+
-+ goto again;
-+ }
-+
-+ /* We have to split root znode */
-+ dbg_tnc("creating new zroot at level %d", znode->level + 1);
-+
-+ zi = kzalloc(c->max_znode_sz, GFP_NOFS);
-+ if (!zi)
-+ return -ENOMEM;
-+
-+ zi->child_cnt = 2;
-+ zi->level = znode->level + 1;
-+
-+ __set_bit(DIRTY_ZNODE, &zi->flags);
-+ atomic_long_inc(&c->dirty_zn_cnt);
-+
-+ zi->zbranch[0].key = znode->zbranch[0].key;
-+ zi->zbranch[0].znode = znode;
-+ zi->zbranch[0].lnum = c->zroot.lnum;
-+ zi->zbranch[0].offs = c->zroot.offs;
-+ zi->zbranch[0].len = c->zroot.len;
-+ zi->zbranch[1].key = zn->zbranch[0].key;
-+ zi->zbranch[1].znode = zn;
-+
-+ c->zroot.lnum = 0;
-+ c->zroot.offs = 0;
-+ c->zroot.len = 0;
-+ c->zroot.znode = zi;
-+
-+ zn->parent = zi;
-+ zn->iip = 1;
-+ znode->parent = zi;
-+ znode->iip = 0;
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_tnc_add - add a node to TNC.
-+ * @c: UBIFS file-system description object
-+ * @key: key to add
-+ * @lnum: LEB number of node
-+ * @offs: node offset
-+ * @len: node length
-+ *
-+ * This function adds a node with key @key to TNC. The node may be new or it may
-+ * obsolete some existing one. Returns %0 on success or negative error code on
-+ * failure.
-+ */
-+int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum,
-+ int offs, int len)
-+{
-+ int found, n, err = 0;
-+ struct ubifs_znode *znode;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ dbg_tnc("%d:%d, len %d, key %s", lnum, offs, len, DBGKEY(key));
-+ found = lookup_level0_dirty(c, key, &znode, &n);
-+ if (!found) {
-+ struct ubifs_zbranch zbr;
-+
-+ zbr.znode = NULL;
-+ zbr.lnum = lnum;
-+ zbr.offs = offs;
-+ zbr.len = len;
-+ key_copy(c, key, &zbr.key);
-+ err = tnc_insert(c, znode, &zbr, n + 1);
-+ } else if (found == 1) {
-+ struct ubifs_zbranch *zbr = &znode->zbranch[n];
-+
-+ lnc_free(zbr);
-+ err = ubifs_add_dirt(c, zbr->lnum, zbr->len);
-+ zbr->lnum = lnum;
-+ zbr->offs = offs;
-+ zbr->len = len;
-+ } else
-+ err = found;
-+ if (!err)
-+ err = dbg_check_tnc(c, 0);
-+ mutex_unlock(&c->tnc_mutex);
-+
-+ return err;
-+}
-+
-+/**
-+ * ubifs_tnc_replace - replace a node in the TNC only if the old node is found.
-+ * @c: UBIFS file-system description object
-+ * @key: key to add
-+ * @old_lnum: LEB number of old node
-+ * @old_offs: old node offset
-+ * @lnum: LEB number of node
-+ * @offs: node offset
-+ * @len: node length
-+ *
-+ * This function replaces a node with key @key in the TNC only if the old node
-+ * is found. This function is called by garbage collection when node are moved.
-+ * Returns %0 on success or negative error code on failure.
-+ */
-+int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key,
-+ int old_lnum, int old_offs, int lnum, int offs, int len)
-+{
-+ int found, n, err = 0;
-+ struct ubifs_znode *znode;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ dbg_tnc("old LEB %d:%d, new LEB %d:%d, len %d, key %s", old_lnum,
-+ old_offs, lnum, offs, len, DBGKEY(key));
-+ found = lookup_level0_dirty(c, key, &znode, &n);
-+ if (found < 0) {
-+ err = found;
-+ goto out_unlock;
-+ }
-+
-+ if (found == 1) {
-+ struct ubifs_zbranch *zbr = &znode->zbranch[n];
-+
-+ found = 0;
-+ if (zbr->lnum == old_lnum && zbr->offs == old_offs) {
-+ lnc_free(zbr);
-+ err = ubifs_add_dirt(c, zbr->lnum, zbr->len);
-+ if (err)
-+ goto out_unlock;
-+ zbr->lnum = lnum;
-+ zbr->offs = offs;
-+ zbr->len = len;
-+ found = 1;
-+ } else if (is_hash_key(c, key)) {
-+ found = resolve_collision_directly(c, key, &znode, &n,
-+ old_lnum, old_offs);
-+ dbg_tnc("rc returned %d, znode %p, n %d, LEB %d:%d",
-+ found, znode, n, old_lnum, old_offs);
-+ if (found < 0) {
-+ err = found;
-+ goto out_unlock;
-+ }
-+
-+ if (found) {
-+ /* Ensure the znode is dirtied */
-+ if (znode->cnext || !ubifs_zn_dirty(znode)) {
-+ znode = dirty_cow_bottom_up(c,
-+ znode);
-+ if (IS_ERR(znode)) {
-+ err = PTR_ERR(znode);
-+ goto out_unlock;
-+ }
-+ }
-+ zbr = &znode->zbranch[n];
-+ lnc_free(zbr);
-+ err = ubifs_add_dirt(c, zbr->lnum,
-+ zbr->len);
-+ if (err)
-+ goto out_unlock;
-+ zbr->lnum = lnum;
-+ zbr->offs = offs;
-+ zbr->len = len;
-+ }
-+ }
-+ }
-+
-+ if (!found)
-+ err = ubifs_add_dirt(c, lnum, len);
-+
-+ if (!err)
-+ err = dbg_check_tnc(c, 0);
-+
-+out_unlock:
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_tnc_add_nm - add a "hashed" node to TNC.
-+ * @c: UBIFS file-system description object
-+ * @key: key to add
-+ * @lnum: LEB number of node
-+ * @offs: node offset
-+ * @len: node length
-+ * @nm: node name
-+ *
-+ * This is the same as 'ubifs_tnc_add()' but it should be used with keys which
-+ * may have collisions, like directory entry keys.
-+ */
-+int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key,
-+ int lnum, int offs, int len, const struct qstr *nm)
-+{
-+ int found, n, err = 0;
-+ struct ubifs_znode *znode;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ dbg_tnc("LEB %d:%d, name '%.*s', key %s", lnum, offs, nm->len, nm->name,
-+ DBGKEY(key));
-+ found = lookup_level0_dirty(c, key, &znode, &n);
-+ if (found < 0) {
-+ err = found;
-+ goto out_unlock;
-+ }
-+
-+ if (found == 1) {
-+ if (c->replaying)
-+ found = fallible_resolve_collision(c, key, &znode, &n,
-+ nm, 1);
-+ else
-+ found = resolve_collision(c, key, &znode, &n, nm);
-+ dbg_tnc("rc returned %d, znode %p, n %d", found, znode, n);
-+ if (found < 0) {
-+ err = found;
-+ goto out_unlock;
-+ }
-+
-+ /* Ensure the znode is dirtied */
-+ if (znode->cnext || !ubifs_zn_dirty(znode)) {
-+ znode = dirty_cow_bottom_up(c, znode);
-+ if (IS_ERR(znode)) {
-+ err = PTR_ERR(znode);
-+ goto out_unlock;
-+ }
-+ }
-+
-+ if (found == 1) {
-+ struct ubifs_zbranch *zbr = &znode->zbranch[n];
-+
-+ lnc_free(zbr);
-+ err = ubifs_add_dirt(c, zbr->lnum, zbr->len);
-+ zbr->lnum = lnum;
-+ zbr->offs = offs;
-+ zbr->len = len;
-+ goto out_unlock;
-+ }
-+ }
-+
-+ if (!found) {
-+ struct ubifs_zbranch zbr;
-+
-+ zbr.znode = NULL;
-+ zbr.lnum = lnum;
-+ zbr.offs = offs;
-+ zbr.len = len;
-+ key_copy(c, key, &zbr.key);
-+ err = tnc_insert(c, znode, &zbr, n + 1);
-+ if (err)
-+ goto out_unlock;
-+ if (c->replaying && c->replay_sqnum < c->cs_sqnum) {
-+ /*
-+ * This node was moved by garbage collection. We can
-+ * tell because it is in the journal but it has a
-+ * sequence number earlier than the last commit-start.
-+ * We did not find it in the index so there may be a
-+ * dangling branch still in the index. So we remove it
-+ * by passing 'ubifs_tnc_remove_nm()' the same key but
-+ * an unmatchable name.
-+ */
-+ struct qstr noname = { .len = 0, .name = "" };
-+
-+ err = dbg_check_tnc(c, 0);
-+ mutex_unlock(&c->tnc_mutex);
-+ if (err)
-+ return err;
-+ return ubifs_tnc_remove_nm(c, key, &noname);
-+ }
-+ }
-+
-+out_unlock:
-+ if (!err)
-+ err = dbg_check_tnc(c, 0);
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * tnc_delete - delete a znode form TNC.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode to delete from
-+ * @n: zbranch slot number to delete
-+ *
-+ * This function deletes a leaf node from @n-th slot of @znode. Returns zero in
-+ * case of success and a negative error code in case of failure.
-+ */
-+static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
-+{
-+ struct ubifs_zbranch *zbr;
-+ struct ubifs_znode *zp;
-+ int i, err;
-+
-+ /* Delete without merge for now */
-+ ubifs_assert(znode->level == 0);
-+ ubifs_assert(n >= 0 && n < c->fanout);
-+ dbg_tnc("deleting %s", DBGKEY(&znode->zbranch[n].key));
-+
-+ zbr = &znode->zbranch[n];
-+ lnc_free(zbr);
-+
-+ err = ubifs_add_dirt(c, zbr->lnum, zbr->len);
-+ if (err) {
-+ dbg_dump_znode(c, znode);
-+ return err;
-+ }
-+
-+ /* We do not "gap" zbranch slots */
-+ for (i = n; i < znode->child_cnt - 1; i++)
-+ znode->zbranch[i] = znode->zbranch[i + 1];
-+ znode->child_cnt -= 1;
-+
-+ if (znode->child_cnt > 0)
-+ return 0;
-+
-+ /*
-+ * This was the last zbranch, we have to delete this znode from the
-+ * parent.
-+ */
-+
-+ do {
-+ ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
-+ ubifs_assert(ubifs_zn_dirty(znode));
-+
-+ zp = znode->parent;
-+ n = znode->iip;
-+
-+ atomic_long_dec(&c->dirty_zn_cnt);
-+
-+ err = insert_old_idx_znode(c, znode);
-+ if (err)
-+ return err;
-+
-+ if (znode->cnext) {
-+ __set_bit(OBSOLETE_ZNODE, &znode->flags);
-+ atomic_long_inc(&c->clean_zn_cnt);
-+ atomic_long_inc(&ubifs_clean_zn_cnt);
-+ } else
-+ kfree(znode);
-+ znode = zp;
-+ } while (znode->child_cnt == 1); /* while removing last child */
-+
-+ /* Remove from znode, entry n - 1 */
-+ znode->child_cnt -= 1;
-+ ubifs_assert(znode->level != 0);
-+ for (i = n; i < znode->child_cnt; i++) {
-+ znode->zbranch[i] = znode->zbranch[i + 1];
-+ if (znode->zbranch[i].znode)
-+ znode->zbranch[i].znode->iip = i;
-+ }
-+
-+ /*
-+ * If this is the root and it has only 1 child then
-+ * collapse the tree.
-+ */
-+ if (!znode->parent) {
-+ while (znode->child_cnt == 1 && znode->level != 0) {
-+ zp = znode;
-+ zbr = &znode->zbranch[0];
-+ znode = get_znode(c, znode, 0);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ znode = dirty_cow_znode(c, zbr);
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+ znode->parent = NULL;
-+ znode->iip = 0;
-+ if (c->zroot.len) {
-+ err = insert_old_idx(c, c->zroot.lnum,
-+ c->zroot.offs);
-+ if (err)
-+ return err;
-+ }
-+ c->zroot.lnum = zbr->lnum;
-+ c->zroot.offs = zbr->offs;
-+ c->zroot.len = zbr->len;
-+ c->zroot.znode = znode;
-+ ubifs_assert(!test_bit(OBSOLETE_ZNODE,
-+ &zp->flags));
-+ ubifs_assert(test_bit(DIRTY_ZNODE, &zp->flags));
-+ atomic_long_dec(&c->dirty_zn_cnt);
-+
-+ if (zp->cnext) {
-+ __set_bit(OBSOLETE_ZNODE, &zp->flags);
-+ atomic_long_inc(&c->clean_zn_cnt);
-+ atomic_long_inc(&ubifs_clean_zn_cnt);
-+ } else
-+ kfree(zp);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_tnc_remove - remove an index entry of a node.
-+ * @c: UBIFS file-system description object
-+ * @key: key of node
-+ *
-+ * Returns %0 on success or negative error code on failure.
-+ */
-+int ubifs_tnc_remove(struct ubifs_info *c, const union ubifs_key *key)
-+{
-+ int found, n, err = 0;
-+ struct ubifs_znode *znode;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ dbg_tnc("key %s", DBGKEY(key));
-+ found = lookup_level0_dirty(c, key, &znode, &n);
-+ if (found < 0) {
-+ err = found;
-+ goto out_unlock;
-+ }
-+ if (found == 1)
-+ err = tnc_delete(c, znode, n);
-+ if (!err)
-+ err = dbg_check_tnc(c, 0);
-+
-+out_unlock:
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_tnc_remove_nm - remove an index entry for a "hashed" node.
-+ * @c: UBIFS file-system description object
-+ * @key: key of node
-+ * @nm: directory entry name
-+ *
-+ * Returns %0 on success or negative error code on failure.
-+ */
-+int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key,
-+ const struct qstr *nm)
-+{
-+ int n, err;
-+ struct ubifs_znode *znode;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ dbg_tnc("%.*s, key %s", nm->len, nm->name, DBGKEY(key));
-+ err = lookup_level0_dirty(c, key, &znode, &n);
-+ if (err < 0)
-+ goto out_unlock;
-+
-+ if (err) {
-+ if (c->replaying)
-+ err = fallible_resolve_collision(c, key, &znode, &n,
-+ nm, 0);
-+ else
-+ err = resolve_collision(c, key, &znode, &n, nm);
-+ dbg_tnc("rc returned %d, znode %p, n %d", err, znode, n);
-+ if (err < 0)
-+ goto out_unlock;
-+ if (err) {
-+ /* Ensure the znode is dirtied */
-+ if (znode->cnext || !ubifs_zn_dirty(znode)) {
-+ znode = dirty_cow_bottom_up(c, znode);
-+ if (IS_ERR(znode)) {
-+ err = PTR_ERR(znode);
-+ goto out_unlock;
-+ }
-+ }
-+ err = tnc_delete(c, znode, n);
-+ }
-+ }
-+
-+out_unlock:
-+ if (!err)
-+ err = dbg_check_tnc(c, 0);
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * key_in_range - determine if a key falls within a range of keys.
-+ * @c: UBIFS file-system description object
-+ * @key: key to check
-+ * @from_key: lowest key in range
-+ * @to_key: highest key in range
-+ *
-+ * This function returns %1 if the key is in range and %0 otherwise.
-+ */
-+static int key_in_range(struct ubifs_info *c, union ubifs_key *key,
-+ union ubifs_key *from_key, union ubifs_key *to_key)
-+{
-+ if (keys_cmp(c, key, from_key) < 0)
-+ return 0;
-+ if (keys_cmp(c, key, to_key) > 0)
-+ return 0;
-+ return 1;
-+}
-+
-+/**
-+ * ubifs_tnc_remove_range - remove index entries in range.
-+ * @c: UBIFS file-system description object
-+ * @from_key: lowest key to remove
-+ * @to_key: highest key to remove
-+ *
-+ * This function removes index entries starting at @from_key and ending at
-+ * @to_key. This function returns zero in case of success and a negative error
-+ * code in case of failure.
-+ */
-+int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key,
-+ union ubifs_key *to_key)
-+{
-+ int i, n, k, err = 0;
-+ struct ubifs_znode *znode;
-+ union ubifs_key *key;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ while (1) {
-+ /* Find first level 0 znode that contains keys to remove */
-+ err = lookup_level0(c, from_key, &znode, &n);
-+ if (err < 0)
-+ goto out_unlock;
-+
-+ if (err)
-+ key = from_key;
-+ else {
-+ err = tnc_next(c, &znode, &n);
-+ if (err == -ENOENT) {
-+ err = 0;
-+ goto out_unlock;
-+ }
-+ if (err < 0)
-+ goto out_unlock;
-+ key = &znode->zbranch[n].key;
-+ if (!key_in_range(c, key, from_key, to_key)) {
-+ err = 0;
-+ goto out_unlock;
-+ }
-+ }
-+
-+ /* Ensure the znode is dirtied */
-+ if (znode->cnext || !ubifs_zn_dirty(znode)) {
-+ znode = dirty_cow_bottom_up(c, znode);
-+ if (IS_ERR(znode)) {
-+ err = PTR_ERR(znode);
-+ goto out_unlock;
-+ }
-+ }
-+
-+ /* Remove all keys in range except the first */
-+ for (i = n + 1, k = 0; i < znode->child_cnt; i++, k++) {
-+ key = &znode->zbranch[i].key;
-+ if (!key_in_range(c, key, from_key, to_key))
-+ break;
-+ lnc_free(&znode->zbranch[i]);
-+ err = ubifs_add_dirt(c, znode->zbranch[i].lnum,
-+ znode->zbranch[i].len);
-+ if (err) {
-+ dbg_dump_znode(c, znode);
-+ goto out_unlock;
-+ }
-+ dbg_tnc("removing %s", DBGKEY(key));
-+ }
-+ if (k) {
-+ for (i = n + 1 + k; i < znode->child_cnt; i++)
-+ znode->zbranch[i - k] = znode->zbranch[i];
-+ znode->child_cnt -= k;
-+ }
-+
-+ /* Now delete the first */
-+ err = tnc_delete(c, znode, n);
-+ if (err)
-+ goto out_unlock;
-+ }
-+
-+out_unlock:
-+ if (!err)
-+ err = dbg_check_tnc(c, 0);
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_tnc_remove_ino - remove an inode from TNC.
-+ * @c: UBIFS file-system description object
-+ * @inum: inode number to remove
-+ *
-+ * This function remove inode @inum and all the extended attributes associated
-+ * with the anode from TNC and returns zero in case of success or a negative
-+ * error code in case of failure.
-+ */
-+int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum)
-+{
-+ union ubifs_key key1, key2;
-+ struct ubifs_dent_node *xent, *pxent = NULL;
-+ struct qstr nm = { .name = NULL };
-+
-+ dbg_tnc("ino %lu", inum);
-+
-+ /*
-+ * Walk all extended attribute entries and remove them together with
-+ * corresponding extended attribute inodes.
-+ */
-+ lowest_xent_key(c, &key1, inum);
-+ while (1) {
-+ ino_t xattr_inum;
-+ int err;
-+
-+ xent = ubifs_tnc_next_ent(c, &key1, &nm);
-+ if (IS_ERR(xent)) {
-+ err = PTR_ERR(xent);
-+ if (err == -ENOENT)
-+ break;
-+ return err;
-+ }
-+
-+ xattr_inum = le64_to_cpu(xent->inum);
-+ dbg_tnc("xent '%s', ino %lu", xent->name, xattr_inum);
-+
-+ nm.name = xent->name;
-+ nm.len = le16_to_cpu(xent->nlen);
-+ err = ubifs_tnc_remove_nm(c, &key1, &nm);
-+ if (err) {
-+ kfree(xent);
-+ return err;
-+ }
-+
-+ lowest_ino_key(c, &key1, xattr_inum);
-+ highest_ino_key(c, &key2, xattr_inum);
-+ err = ubifs_tnc_remove_range(c, &key1, &key2);
-+ if (err) {
-+ kfree(xent);
-+ return err;
-+ }
-+
-+ kfree(pxent);
-+ pxent = xent;
-+ key_read(c, &xent->key, &key1);
-+ }
-+
-+ kfree(pxent);
-+ lowest_ino_key(c, &key1, inum);
-+ highest_ino_key(c, &key2, inum);
-+
-+ return ubifs_tnc_remove_range(c, &key1, &key2);
-+}
-+
-+/**
-+ * ubifs_tnc_next_ent - walk directory or extended attribute entries.
-+ * @c: UBIFS file-system description object
-+ * @key: key of last entry
-+ * @nm: name of last entry found or %NULL
-+ *
-+ * This function finds and reads the next directory or extended attribute entry
-+ * after the given key (@key) if there is one. @nm is used to resolve
-+ * collisions.
-+ *
-+ * If the name of the current entry is not known and only the key is known,
-+ * @nm->name has to be %NULL. In this case the semantics of this function is a
-+ * little bit different and it returns the entry corresponding to this key, not
-+ * the next one. If the key was not found, the closest "right" entry is
-+ * returned.
-+ *
-+ * If the fist entry has to be found, @key has to contain the lowest possible
-+ * key value for this inode and @name has to be %NULL.
-+ *
-+ * This function returns the found directory or extended attribute entry node
-+ * in case of success, %-ENOENT is returned if no entry was found, and a
-+ * negative error code is returned in case of failure.
-+ */
-+struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c,
-+ union ubifs_key *key,
-+ const struct qstr *nm)
-+{
-+ int n, err, type = key_type(c, key);
-+ struct ubifs_znode *znode;
-+ struct ubifs_dent_node *dent;
-+ struct ubifs_zbranch *zbr;
-+ union ubifs_key *dkey;
-+
-+ dbg_tnc("%s %s", nm->name ? (char *)nm->name : "(lowest)", DBGKEY(key));
-+ ubifs_assert(is_hash_key(c, key));
-+
-+ mutex_lock(&c->tnc_mutex);
-+ err = lookup_level0(c, key, &znode, &n);
-+ if (unlikely(err < 0))
-+ goto out_unlock;
-+
-+ if (nm->name) {
-+ if (err) {
-+ /* Handle collisions */
-+ err = resolve_collision(c, key, &znode, &n, nm);
-+ dbg_tnc("rc returned %d, znode %p, n %d",
-+ err, znode, n);
-+ if (unlikely(err < 0))
-+ goto out_unlock;
-+ }
-+
-+ /* Now find next entry */
-+ err = tnc_next(c, &znode, &n);
-+ if (unlikely(err))
-+ goto out_unlock;
-+ } else {
-+ /*
-+ * The full name of the entry was not given, in which case the
-+ * behavior of this function is a little different and it
-+ * returns current entry, not the next one.
-+ */
-+ if (!err) {
-+ /*
-+ * However, the given key does not exist in the TNC
-+ * tree and @znode/@n variables contain the closest
-+ * "preceding" element. Switch to the next one.
-+ */
-+ err = tnc_next(c, &znode, &n);
-+ if (err)
-+ goto out_unlock;
-+ }
-+ }
-+
-+ zbr = &znode->zbranch[n];
-+ dent = kmalloc(zbr->len, GFP_NOFS);
-+ if (unlikely(!dent)) {
-+ err = -ENOMEM;
-+ goto out_unlock;
-+ }
-+
-+ /*
-+ * The above 'tnc_next()' call could lead us to the next inode, check
-+ * this.
-+ */
-+ dkey = &zbr->key;
-+ if (key_ino(c, dkey) != key_ino(c, key) ||
-+ key_type(c, dkey) != type) {
-+ err = -ENOENT;
-+ goto out_free;
-+ }
-+
-+ err = tnc_read_node_nm(c, zbr, dent);
-+ if (unlikely(err))
-+ goto out_free;
-+
-+ mutex_unlock(&c->tnc_mutex);
-+ return dent;
-+
-+out_free:
-+ kfree(dent);
-+out_unlock:
-+ mutex_unlock(&c->tnc_mutex);
-+ return ERR_PTR(err);
-+}
-+
-+/**
-+ * tnc_destroy_cnext - destroy left-over obsolete znodes from a failed commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Destroy left-over obsolete znodes from a failed commit.
-+ */
-+static void tnc_destroy_cnext(struct ubifs_info *c)
-+{
-+ struct ubifs_znode *cnext;
-+
-+ if (!c->cnext)
-+ return;
-+ ubifs_assert(c->cmt_state == COMMIT_BROKEN);
-+ cnext = c->cnext;
-+ do {
-+ struct ubifs_znode *znode = cnext;
-+
-+ cnext = cnext->cnext;
-+ if (test_bit(OBSOLETE_ZNODE, &znode->flags))
-+ kfree(znode);
-+ } while (cnext && cnext != c->cnext);
-+}
-+
-+/**
-+ * ubifs_tnc_close - close TNC subsystem and free all related resources.
-+ * @c: UBIFS file-system description object
-+ */
-+void ubifs_tnc_close(struct ubifs_info *c)
-+{
-+ long clean_freed;
-+
-+ tnc_destroy_cnext(c);
-+ if (c->zroot.znode) {
-+ clean_freed = ubifs_destroy_tnc_subtree(c->zroot.znode);
-+ atomic_long_sub(clean_freed, &ubifs_clean_zn_cnt);
-+ }
-+ kfree(c->gap_lebs);
-+ kfree(c->ilebs);
-+ destroy_old_idx(c);
-+}
-+
-+/**
-+ * left_znode - get the znode to the left.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode
-+ *
-+ * This function returns a pointer to the znode to the left of @znode or NULL if
-+ * there is not one. A negative error code is returned on failure.
-+ */
-+static struct ubifs_znode *left_znode(struct ubifs_info *c,
-+ struct ubifs_znode *znode)
-+{
-+ int level = znode->level;
-+
-+ while (1) {
-+ int n = znode->iip - 1;
-+
-+ /* Go up until we can go left */
-+ znode = znode->parent;
-+ if (!znode)
-+ return NULL;
-+ if (n >= 0) {
-+ /* Now go down the rightmost branch to 'level' */
-+ znode = get_znode(c, znode, n);
-+ if (IS_ERR(znode))
-+ return znode;
-+ while (znode->level != level) {
-+ n = znode->child_cnt - 1;
-+ znode = get_znode(c, znode, n);
-+ if (IS_ERR(znode))
-+ return znode;
-+ }
-+ break;
-+ }
-+ }
-+ return znode;
-+}
-+
-+/**
-+ * right_znode - get the znode to the right.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode
-+ *
-+ * This function returns a pointer to the znode to the right of @znode or NULL
-+ * if there is not one. A negative error code is returned on failure.
-+ */
-+static struct ubifs_znode *right_znode(struct ubifs_info *c,
-+ struct ubifs_znode *znode)
-+{
-+ int level = znode->level;
-+
-+ while (1) {
-+ int n = znode->iip + 1;
-+
-+ /* Go up until we can go right */
-+ znode = znode->parent;
-+ if (!znode)
-+ return NULL;
-+ if (n < znode->child_cnt) {
-+ /* Now go down the leftmost branch to 'level' */
-+ znode = get_znode(c, znode, n);
-+ if (IS_ERR(znode))
-+ return znode;
-+ while (znode->level != level) {
-+ znode = get_znode(c, znode, 0);
-+ if (IS_ERR(znode))
-+ return znode;
-+ }
-+ break;
-+ }
-+ }
-+ return znode;
-+}
-+
-+/**
-+ * lookup_znode - find a particular indexing node from TNC.
-+ * @c: UBIFS file-system description object
-+ * @key: index node key to lookup
-+ * @level: index node level
-+ * @lnum: index node LEB number
-+ * @offs: index node offset
-+ *
-+ * This function searches an indexing node by its first key @key and its
-+ * address @lnum:@offs. It looks up the indexing tree by pulling all indexing
-+ * nodes it traverses to TNC. This function is called fro indexing nodes which
-+ * were found on the media by scanning, for example when garbage-collecting or
-+ * when doing in-the-gaps commit. This means that the indexing node which is
-+ * looked for does not have to have exactly the same leftmost key @key, because
-+ * the leftmost key may have been changed, in which case TNC will contain a
-+ * dirty znode which still refers the same @lnum:@offs. This function is clever
-+ * enough to recognize such indexing nodes.
-+ *
-+ * Note, if a znode was deleted or changed too much, then this function will
-+ * not find it. For situations like this UBIFS has the old index RB-tree
-+ * (indexed by @lnum:@offs).
-+ *
-+ * This function returns a pointer to the znode found or %NULL if it is not
-+ * found. A negative error code is returned on failure.
-+ */
-+static struct ubifs_znode *lookup_znode(struct ubifs_info *c,
-+ union ubifs_key *key, int level,
-+ int lnum, int offs)
-+{
-+ struct ubifs_znode *znode, *zn;
-+ int n, nn;
-+
-+ /*
-+ * The arguments have probably been read off flash, so don't assume
-+ * they are valid.
-+ */
-+ if (level < 0)
-+ return ERR_PTR(-EINVAL);
-+
-+ /* Get the root znode */
-+ znode = c->zroot.znode;
-+ if (!znode) {
-+ znode = load_znode(c, &c->zroot, NULL, 0);
-+ if (IS_ERR(znode))
-+ return znode;
-+ }
-+ /* Check if it is the one we are looking for */
-+ if (c->zroot.lnum == lnum && c->zroot.offs == offs)
-+ return znode;
-+ /* Descend to the parent level i.e. (level + 1) */
-+ if (level >= znode->level)
-+ return NULL;
-+ while (1) {
-+ ubifs_search_zbranch(c, znode, key, &n);
-+ if (n < 0) {
-+ /*
-+ * We reached a znode where the leftmost key is greater
-+ * than the key we are searching for. This is the same
-+ * situation as the one described in a huge comment at
-+ * the end of the 'lookup_level0()' function. And for
-+ * exactly the same reasons we have to try to look left
-+ * before giving up.
-+ */
-+ znode = left_znode(c, znode);
-+ if (!znode)
-+ return NULL;
-+ if (IS_ERR(znode))
-+ return znode;
-+ ubifs_search_zbranch(c, znode, key, &n);
-+ ubifs_assert(n >= 0);
-+ }
-+ if (znode->level == level + 1)
-+ break;
-+ znode = get_znode(c, znode, n);
-+ if (IS_ERR(znode))
-+ return znode;
-+ }
-+ /* Check if the child is the one we are looking for */
-+ if (znode->zbranch[n].lnum == lnum && znode->zbranch[n].offs == offs)
-+ return get_znode(c, znode, n);
-+ /* If the key is unique, there is nowhere else to look */
-+ if (!is_hash_key(c, key))
-+ return NULL;
-+ /*
-+ * The key is not unique and so may be also in the znodes to either
-+ * side.
-+ */
-+ zn = znode;
-+ nn = n;
-+ /* Look left */
-+ while (1) {
-+ /* Move one branch to the left */
-+ if (n)
-+ n -= 1;
-+ else {
-+ znode = left_znode(c, znode);
-+ if (!znode)
-+ break;
-+ if (IS_ERR(znode))
-+ return znode;
-+ n = znode->child_cnt - 1;
-+ }
-+ /* Check it */
-+ if (znode->zbranch[n].lnum == lnum &&
-+ znode->zbranch[n].offs == offs)
-+ return get_znode(c, znode, n);
-+ /* Stop if the key is less than the one we are looking for */
-+ if (keys_cmp(c, &znode->zbranch[n].key, key) < 0)
-+ break;
-+ }
-+ /* Back to the middle */
-+ znode = zn;
-+ n = nn;
-+ /* Look right */
-+ while (1) {
-+ /* Move one branch to the right */
-+ if (++n >= znode->child_cnt) {
-+ znode = right_znode(c, znode);
-+ if (!znode)
-+ break;
-+ if (IS_ERR(znode))
-+ return znode;
-+ n = 0;
-+ }
-+ /* Check it */
-+ if (znode->zbranch[n].lnum == lnum &&
-+ znode->zbranch[n].offs == offs)
-+ return get_znode(c, znode, n);
-+ /* Stop if the key is greater than the one we are looking for */
-+ if (keys_cmp(c, &znode->zbranch[n].key, key) > 0)
-+ break;
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * is_idx_node_in_tnc - determine if an index node is in the TNC.
-+ * @c: UBIFS file-system description object
-+ * @key: key of index node
-+ * @level: index node level
-+ * @lnum: LEB number of index node
-+ * @offs: offset of index node
-+ *
-+ * This function returns %0 if the index node is not referred to in the TNC, %1
-+ * if the index node is referred to in the TNC and the corresponding znode is
-+ * dirty, %2 if an index node is referred to in the TNC and the corresponding
-+ * znode is clean, and a negative error code in case of failure.
-+ *
-+ * Note, the @key argument has to be the key of the first child. Also note,
-+ * this function relies on the fact that 0:0 is never a valid LEB number and
-+ * offset for a main-area node.
-+ */
-+int is_idx_node_in_tnc(struct ubifs_info *c, union ubifs_key *key, int level,
-+ int lnum, int offs)
-+{
-+ struct ubifs_znode *znode;
-+
-+ znode = lookup_znode(c, key, level, lnum, offs);
-+ if (!znode)
-+ return 0;
-+ if (IS_ERR(znode))
-+ return PTR_ERR(znode);
-+
-+ return ubifs_zn_dirty(znode) ? 1 : 2;
-+}
-+
-+/**
-+ * is_leaf_node_in_tnc - determine if a non-indexing not is in the TNC.
-+ * @c: UBIFS file-system description object
-+ * @key: node key
-+ * @lnum: node LEB number
-+ * @offs: node offset
-+ *
-+ * This function returns %1 if the node is referred to in the TNC, %0 if it is
-+ * not, and a negative error code in case of failure.
-+ *
-+ * Note, this function relies on the fact that 0:0 is never a valid LEB number
-+ * and offset for a main-area node.
-+ */
-+static int is_leaf_node_in_tnc(struct ubifs_info *c, union ubifs_key *key,
-+ int lnum, int offs)
-+{
-+ struct ubifs_zbranch *zbr;
-+ struct ubifs_znode *znode, *zn;
-+ int n, found, err, nn;
-+ const int unique = !is_hash_key(c, key);
-+
-+ found = lookup_level0(c, key, &znode, &n);
-+ if (found < 0)
-+ return found; /* Error code */
-+ if (!found)
-+ return 0;
-+ zbr = &znode->zbranch[n];
-+ if (lnum == zbr->lnum && offs == zbr->offs)
-+ return 1; /* Found it */
-+ if (unique)
-+ return 0;
-+ /*
-+ * Because the key is not unique, we have to look left
-+ * and right as well
-+ */
-+ zn = znode;
-+ nn = n;
-+ /* Look left */
-+ while (1) {
-+ err = tnc_prev(c, &znode, &n);
-+ if (err == -ENOENT)
-+ break;
-+ if (err)
-+ return err;
-+ if (keys_cmp(c, key, &znode->zbranch[n].key))
-+ break;
-+ zbr = &znode->zbranch[n];
-+ if (lnum == zbr->lnum && offs == zbr->offs)
-+ return 1; /* Found it */
-+ }
-+ /* Look right */
-+ znode = zn;
-+ n = nn;
-+ while (1) {
-+ err = tnc_next(c, &znode, &n);
-+ if (err) {
-+ if (err == -ENOENT)
-+ return 0;
-+ return err;
-+ }
-+ if (keys_cmp(c, key, &znode->zbranch[n].key))
-+ break;
-+ zbr = &znode->zbranch[n];
-+ if (lnum == zbr->lnum && offs == zbr->offs)
-+ return 1; /* Found it */
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_tnc_has_node - determine whether a node is in the TNC.
-+ * @c: UBIFS file-system description object
-+ * @key: node key
-+ * @level: index node level (if it is an index node)
-+ * @lnum: node LEB number
-+ * @offs: node offset
-+ * @is_idx: non-zero if the node is an index node
-+ *
-+ * This function returns %1 if the node is in the TNC, %0 if it is not, and a
-+ * negative error code in case of failure. For index nodes, @key has to be the
-+ * key of the first child. An index node is considered to be in the TNC only if
-+ * the corresponding znode is clean or has not been loaded.
-+ */
-+int ubifs_tnc_has_node(struct ubifs_info *c, union ubifs_key *key, int level,
-+ int lnum, int offs, int is_idx)
-+{
-+ int err;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ if (is_idx) {
-+ err = is_idx_node_in_tnc(c, key, level, lnum, offs);
-+ if (err < 0)
-+ goto out_unlock;
-+ if (err == 1)
-+ /* The index node was found but it was dirty */
-+ err = 0;
-+ else if (err == 2)
-+ /* The index node was found and it was clean */
-+ err = 1;
-+ else
-+ BUG_ON(err != 0);
-+ } else
-+ err = is_leaf_node_in_tnc(c, key, lnum, offs);
-+
-+out_unlock:
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * ubifs_dirty_idx_node - dirty an index node.
-+ * @c: UBIFS file-system description object
-+ * @key: index node key
-+ * @level: index node level
-+ * @lnum: index node LEB number
-+ * @offs: index node offset
-+ *
-+ * This function loads and dirties an index node so that it can be garbage
-+ * collected. The @key argument has to be the key of the first child. This
-+ * function relies on the fact that 0:0 is never a valid LEB number and offset
-+ * for a main-area node. Returns %0 on success and a negative error code on
-+ * failure.
-+ */
-+int ubifs_dirty_idx_node(struct ubifs_info *c, union ubifs_key *key, int level,
-+ int lnum, int offs)
-+{
-+ struct ubifs_znode *znode;
-+ int err = 0;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ znode = lookup_znode(c, key, level, lnum, offs);
-+ if (!znode)
-+ goto out_unlock;
-+ if (IS_ERR(znode)) {
-+ err = PTR_ERR(znode);
-+ goto out_unlock;
-+ }
-+ znode = dirty_cow_bottom_up(c, znode);
-+ if (IS_ERR(znode)) {
-+ err = PTR_ERR(znode);
-+ goto out_unlock;
-+ }
-+
-+out_unlock:
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+
-+/**
-+ * dbg_walk_sub_tree - walk index subtree.
-+ * @c: UBIFS file-system description object
-+ * @znode: root znode of the subtree to walk
-+ * @leaf_cb: called for each leaf node
-+ * @znode_cb: called for each indexing node
-+ * @priv: private date which is passed to callbacks
-+ *
-+ * This is a helper function which recursively walks the UBIFS index, reading
-+ * each indexing node from the media if needed. Returns zero in case of success
-+ * and a negative error code in case of failure.
-+ */
-+static int dbg_walk_sub_tree(struct ubifs_info *c, struct ubifs_znode *znode,
-+ dbg_leaf_callback leaf_cb,
-+ dbg_znode_callback znode_cb, void *priv)
-+{
-+ int n, err;
-+
-+ cond_resched();
-+
-+ if (znode_cb) {
-+ err = znode_cb(c, znode, priv);
-+ if (err)
-+ return err;
-+ }
-+
-+ if (znode->level == 0) {
-+ if (!leaf_cb)
-+ return 0;
-+
-+ for (n = 0; n < znode->child_cnt; n++) {
-+ struct ubifs_zbranch *zbr = &znode->zbranch[n];
-+
-+ err = leaf_cb(c, zbr, priv);
-+ if (err)
-+ return err;
-+ }
-+ } else
-+ for (n = 0; n < znode->child_cnt; n++) {
-+ struct ubifs_znode *zn;
-+
-+ zn = get_znode(c, znode, n);
-+ if (IS_ERR(zn))
-+ return PTR_ERR(zn);
-+ err = dbg_walk_sub_tree(c, zn, leaf_cb, znode_cb, priv);
-+ if (err)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * dbg_walk_index - walk the on-flash index.
-+ * @c: UBIFS file-system description object
-+ * @leaf_cb: called for each leaf node
-+ * @znode_cb: called for each indexing node
-+ * @priv: private date which is passed to callbacks
-+ *
-+ * This function walks the UBIFS index and calls the @leaf_cb for each leaf
-+ * node and @znode_cb for each indexing node. Returns zero in case of success
-+ * and a negative error code in case of failure.
-+ *
-+ * Because 'dbg_walk_sub_tree()' is recursive, it runs the risk of exceeding the
-+ * stack space.
-+ *
-+ * It would be better if this function removed every znode it pulled to into
-+ * the TNC, so that the behavior more closely matched the non-debugging
-+ * behavior.
-+ */
-+int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
-+ dbg_znode_callback znode_cb, void *priv)
-+{
-+ int err = 0;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ if (!c->zroot.znode) {
-+ c->zroot.znode = load_znode(c, &c->zroot, NULL, 0);
-+ if (IS_ERR(c->zroot.znode)) {
-+ err = PTR_ERR(c->zroot.znode);
-+ c->zroot.znode = NULL;
-+ goto out_unlock;
-+ }
-+ }
-+
-+ err = dbg_walk_sub_tree(c, c->zroot.znode, leaf_cb, znode_cb, priv);
-+
-+out_unlock:
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+int dbg_read_leaf_nolock(struct ubifs_info *c, struct ubifs_zbranch *zbr,
-+ void *node)
-+{
-+ ubifs_assert(mutex_is_locked(&c->tnc_mutex));
-+ if (is_hash_key(c, &zbr->key))
-+ return tnc_read_node_nm(c, zbr, node);
-+ return tnc_read_node(c, zbr, node);
-+}
-+
-+#endif /* CONFIG_UBIFS_FS_DEBUG */
---- linux-2.6.24.7.old/fs/ubifs/tnc_commit.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/tnc_commit.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1105 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/* This file implements TNC functions for committing */
-+
-+#include "ubifs.h"
-+
-+/**
-+ * make_idx_node - make an index node for fill-the-gaps method of TNC commit.
-+ * @c: UBIFS file-system description object
-+ * @idx: buffer in which to place new index node
-+ * @znode: znode from which to make new index node
-+ * @lnum: LEB number where new index node will be written
-+ * @offs: offset where new index node will be written
-+ * @len: length of new index node
-+ */
-+static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx,
-+ struct ubifs_znode *znode, int lnum, int offs, int len)
-+{
-+ struct ubifs_znode *zp;
-+ int i, err;
-+
-+ /* Make index node */
-+ idx->ch.node_type = UBIFS_IDX_NODE;
-+ idx->child_cnt = cpu_to_le16(znode->child_cnt);
-+ idx->level = cpu_to_le16(znode->level);
-+ for (i = 0; i < znode->child_cnt; i++) {
-+ struct ubifs_branch *br = ubifs_idx_branch(c, idx, i);
-+ struct ubifs_zbranch *zbr = &znode->zbranch[i];
-+
-+ key_write_idx(c, &zbr->key, &br->key);
-+ br->lnum = cpu_to_le32(zbr->lnum);
-+ br->offs = cpu_to_le32(zbr->offs);
-+ br->len = cpu_to_le32(zbr->len);
-+ if (!zbr->lnum || !zbr->len) {
-+ ubifs_err("bad ref in znode");
-+ dbg_dump_znode(c, znode);
-+ if (zbr->znode)
-+ dbg_dump_znode(c, zbr->znode);
-+ }
-+ }
-+ ubifs_prepare_node(c, idx, len, 0);
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ znode->lnum = lnum;
-+ znode->offs = offs;
-+ znode->len = len;
-+#endif
-+
-+ err = insert_old_idx_znode(c, znode);
-+
-+ /* Update the parent */
-+ zp = znode->parent;
-+ if (zp) {
-+ struct ubifs_zbranch *zbr;
-+
-+ zbr = &zp->zbranch[znode->iip];
-+ zbr->lnum = lnum;
-+ zbr->offs = offs;
-+ zbr->len = len;
-+ } else {
-+ c->zroot.lnum = lnum;
-+ c->zroot.offs = offs;
-+ c->zroot.len = len;
-+ }
-+ c->calc_idx_sz += ALIGN(len, 8);
-+
-+ atomic_long_dec(&c->dirty_zn_cnt);
-+
-+ ubifs_assert(ubifs_zn_dirty(znode));
-+ ubifs_assert(test_bit(COW_ZNODE, &znode->flags));
-+
-+ __clear_bit(DIRTY_ZNODE, &znode->flags);
-+ __clear_bit(COW_ZNODE, &znode->flags);
-+
-+ return err;
-+}
-+
-+/**
-+ * fill_gap - make index nodes in gaps in dirty index LEBs.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number that gap appears in
-+ * @gap_start: offset of start of gap
-+ * @gap_end: offset of end of gap
-+ * @dirt: adds dirty space to this
-+ *
-+ * This function returns the number of index nodes written into the gap.
-+ */
-+static int fill_gap(struct ubifs_info *c, int lnum, int gap_start, int gap_end,
-+ int *dirt)
-+{
-+ int len, gap_remains, gap_pos, written, pad_len;
-+
-+ ubifs_assert((gap_start & 7) == 0);
-+ ubifs_assert((gap_end & 7) == 0);
-+ ubifs_assert(gap_end >= gap_start);
-+
-+ gap_remains = gap_end - gap_start;
-+ if (!gap_remains)
-+ return 0;
-+ gap_pos = gap_start;
-+ written = 0;
-+ while (c->enext) {
-+ len = ubifs_idx_node_sz(c, c->enext->child_cnt);
-+ if (len < gap_remains) {
-+ struct ubifs_znode *znode = c->enext;
-+ const int alen = ALIGN(len, 8);
-+ int err;
-+
-+ ubifs_assert(alen <= gap_remains);
-+ err = make_idx_node(c, c->ileb_buf + gap_pos, znode,
-+ lnum, gap_pos, len);
-+ if (err)
-+ return err;
-+ gap_remains -= alen;
-+ gap_pos += alen;
-+ c->enext = znode->cnext;
-+ if (c->enext == c->cnext)
-+ c->enext = NULL;
-+ written += 1;
-+ } else
-+ break;
-+ }
-+ if (gap_end == c->leb_size) {
-+ c->ileb_len = ALIGN(gap_pos, c->min_io_size);
-+ /* Pad to end of min_io_size */
-+ pad_len = c->ileb_len - gap_pos;
-+ } else
-+ /* Pad to end of gap */
-+ pad_len = gap_remains;
-+ dbg_gc("LEB %d:%d to %d len %d nodes written %d wasted bytes %d",
-+ lnum, gap_start, gap_end, gap_end - gap_start, written, pad_len);
-+ ubifs_pad(c, c->ileb_buf + gap_pos, pad_len);
-+ *dirt += pad_len;
-+ return written;
-+}
-+
-+/**
-+ * find_old_idx - find an index node obsoleted since the last commit start.
-+ * @c: UBIFS file-system description object
-+ * @lnum: LEB number of obsoleted index node
-+ * @offs: offset of obsoleted index node
-+ *
-+ * Returns %1 if found and %0 otherwise.
-+ */
-+static int find_old_idx(struct ubifs_info *c, int lnum, int offs)
-+{
-+ struct ubifs_old_idx *o;
-+ struct rb_node *p;
-+
-+ p = c->old_idx.rb_node;
-+ while (p) {
-+ o = rb_entry(p, struct ubifs_old_idx, rb);
-+ if (lnum < o->lnum)
-+ p = p->rb_left;
-+ else if (lnum > o->lnum)
-+ p = p->rb_right;
-+ else if (offs < o->offs)
-+ p = p->rb_left;
-+ else if (offs > o->offs)
-+ p = p->rb_right;
-+ else
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * is_idx_node_in_use - determine if an index node can be overwritten.
-+ * @c: UBIFS file-system description object
-+ * @key: key of index node
-+ * @level: index node level
-+ * @lnum: LEB number of index node
-+ * @offs: offset of index node
-+ *
-+ * If @key / @lnum / @offs identify an index node that was not part of the old
-+ * index, then this function returns %0 (obsolete). Else if the index node was
-+ * part of the old index but is now dirty %1 is returned, else if it is clean %2
-+ * is returned. A negative error code is returned on failure.
-+ */
-+static int is_idx_node_in_use(struct ubifs_info *c, union ubifs_key *key,
-+ int level, int lnum, int offs)
-+{
-+ int ret;
-+
-+ ret = is_idx_node_in_tnc(c, key, level, lnum, offs);
-+ if (ret < 0)
-+ return ret; /* Error code */
-+ if (ret == 0)
-+ if (find_old_idx(c, lnum, offs))
-+ return 1;
-+ return ret;
-+}
-+
-+/**
-+ * layout_leb_in_gaps - layout index nodes using in-the-gaps method.
-+ * @c: UBIFS file-system description object
-+ * @p: return LEB number here
-+ *
-+ * This function lays out new index nodes for dirty znodes using in-the-gaps
-+ * method of TNC commit.
-+ * This function merely puts the next znode into the next gap, making no attempt
-+ * to try to maximise the number of znodes that fit.
-+ * This function returns the number of index nodes written into the gaps, or a
-+ * negative error code on failure.
-+ */
-+static int layout_leb_in_gaps(struct ubifs_info *c, int *p)
-+{
-+ struct ubifs_scan_leb *sleb;
-+ struct ubifs_scan_node *snod;
-+ int lnum, dirt = 0, gap_start, gap_end, err, written, tot_written;
-+
-+ tot_written = 0;
-+ /* Get an index LEB with lots of obsolete index nodes */
-+ lnum = ubifs_find_dirty_idx_leb(c);
-+ if (lnum < 0)
-+ /*
-+ * There also may be dirt in the index head that could be
-+ * filled, however we do not check there at present.
-+ */
-+ return lnum; /* Error code */
-+ *p = lnum;
-+ dbg_gc("LEB %d", lnum);
-+ /*
-+ * Scan the index LEB. We use the generic scan for this even though
-+ * it is more comprehensive and less efficient than is needed for this
-+ * purpose.
-+ */
-+ sleb = ubifs_scan(c, lnum, 0, c->ileb_buf);
-+ c->ileb_len = 0;
-+ if (IS_ERR(sleb))
-+ return PTR_ERR(sleb);
-+ gap_start = 0;
-+ list_for_each_entry(snod, &sleb->nodes, list) {
-+ struct ubifs_idx_node *idx;
-+ int in_use, level;
-+
-+ ubifs_assert(snod->type == UBIFS_IDX_NODE);
-+ idx = snod->node;
-+ key_read(c, ubifs_idx_key(c, idx), &snod->key);
-+ level = le16_to_cpu(idx->level);
-+ /* Determine if the index node is in use (not obsolete) */
-+ in_use = is_idx_node_in_use(c, &snod->key, level, lnum,
-+ snod->offs);
-+ if (in_use < 0) {
-+ ubifs_scan_destroy(sleb);
-+ return in_use; /* Error code */
-+ }
-+ if (in_use) {
-+ if (in_use == 1)
-+ dirt += ALIGN(snod->len, 8);
-+ /*
-+ * The obsolete index nodes form gaps that can be
-+ * overwritten. This gap has ended because we have
-+ * found an index node that is still in use
-+ * i.e. not obsolete
-+ */
-+ gap_end = snod->offs;
-+ /* Try to fill gap */
-+ written = fill_gap(c, lnum, gap_start, gap_end, &dirt);
-+ if (written < 0) {
-+ ubifs_scan_destroy(sleb);
-+ return written; /* Error code */
-+ }
-+ tot_written += written;
-+ gap_start = ALIGN(snod->offs + snod->len, 8);
-+ }
-+ }
-+ ubifs_scan_destroy(sleb);
-+ c->ileb_len = c->leb_size;
-+ gap_end = c->leb_size;
-+ /* Try to fill gap */
-+ written = fill_gap(c, lnum, gap_start, gap_end, &dirt);
-+ if (written < 0)
-+ return written; /* Error code */
-+ tot_written += written;
-+ if (tot_written == 0) {
-+ struct ubifs_lprops lp;
-+
-+ dbg_gc("LEB %d wrote %d index nodes", lnum, tot_written);
-+ err = ubifs_read_one_lp(c, lnum, &lp);
-+ if (err)
-+ return err;
-+ if (lp.free == c->leb_size) {
-+ /*
-+ * We must have snatched this LEB from the idx_gc list
-+ * so we need to correct the free and dirty space.
-+ */
-+ err = ubifs_change_one_lp(c, lnum,
-+ c->leb_size - c->ileb_len,
-+ dirt, 0, 0, 0);
-+ if (err)
-+ return err;
-+ }
-+ return 0;
-+ }
-+ err = ubifs_change_one_lp(c, lnum, c->leb_size - c->ileb_len, dirt,
-+ 0, 0, 0);
-+ if (err)
-+ return err;
-+ err = ubi_leb_change(c->ubi, lnum, c->ileb_buf, c->ileb_len,
-+ UBI_SHORTTERM);
-+ if (err) {
-+ ubifs_err("ubi_leb_change failed, error %d", err);
-+ return err;
-+ }
-+ dbg_gc("LEB %d wrote %d index nodes", lnum, tot_written);
-+ return tot_written;
-+}
-+
-+/**
-+ * get_leb_cnt - calculate the number of empty LEBs needed to commit.
-+ * @c: UBIFS file-system description object
-+ * @cnt: number of znodes to commit
-+ *
-+ * This function returns the number of empty LEBs needed to commit @cnt znodes
-+ * to the current index head. The number is not exact and may be more than
-+ * needed.
-+ */
-+static int get_leb_cnt(struct ubifs_info *c, int cnt)
-+{
-+ int d;
-+
-+ /* Assume maximum index node size (i.e. overestimate space needed) */
-+ cnt -= (c->leb_size - c->ihead_offs) / c->max_idx_node_sz;
-+ if (cnt < 0)
-+ cnt = 0;
-+ d = c->leb_size / c->max_idx_node_sz;
-+ return DIV_ROUND_UP(cnt, d);
-+}
-+
-+/**
-+ * layout_in_gaps - in-the-gaps method of committing TNC.
-+ * @c: UBIFS file-system description object
-+ * @cnt: number of dirty znodes to commit.
-+ *
-+ * This function lays out new index nodes for dirty znodes using in-the-gaps
-+ * method of TNC commit.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int layout_in_gaps(struct ubifs_info *c, int cnt)
-+{
-+ int err, leb_needed_cnt, written, *p;
-+
-+ dbg_gc("%d znodes to write", cnt);
-+
-+ c->gap_lebs = kmalloc(sizeof(int) * (c->lst.idx_lebs + 1), GFP_NOFS);
-+ if (!c->gap_lebs)
-+ return -ENOMEM;
-+
-+ p = c->gap_lebs;
-+ do {
-+ ubifs_assert(p < c->gap_lebs + sizeof(int) * c->lst.idx_lebs);
-+ written = layout_leb_in_gaps(c, p);
-+ if (written < 0) {
-+ err = written;
-+ if (err == -ENOSPC) {
-+ if (!dbg_force_in_the_gaps_enabled) {
-+ /*
-+ * Do not print scary warnings if the
-+ * debugging option which forces
-+ * in-the-gaps is enabled.
-+ */
-+ ubifs_err("out of space");
-+ spin_lock(&c->space_lock);
-+ dbg_dump_budg(c);
-+ spin_unlock(&c->space_lock);
-+ dbg_dump_lprops(c);
-+ }
-+ /* Try to commit anyway */
-+ err = 0;
-+ break;
-+ }
-+ kfree(c->gap_lebs);
-+ c->gap_lebs = NULL;
-+ return err;
-+ }
-+ p++;
-+ cnt -= written;
-+ leb_needed_cnt = get_leb_cnt(c, cnt);
-+ dbg_gc("%d znodes remaining, need %d LEBs, have %d", cnt,
-+ leb_needed_cnt, c->ileb_cnt);
-+ } while (leb_needed_cnt > c->ileb_cnt);
-+
-+ *p = -1;
-+ return 0;
-+}
-+
-+/**
-+ * layout_in_empty_space - layout index nodes in empty space.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function lays out new index nodes for dirty znodes using empty LEBs.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int layout_in_empty_space(struct ubifs_info *c)
-+{
-+ struct ubifs_znode *znode, *cnext, *zp;
-+ int lnum, offs, len, next_len, buf_len, buf_offs, used, avail;
-+ int wlen, blen, err;
-+
-+ cnext = c->enext;
-+ if (!cnext)
-+ return 0;
-+
-+ lnum = c->ihead_lnum;
-+ buf_offs = c->ihead_offs;
-+
-+ buf_len = ubifs_idx_node_sz(c, c->fanout);
-+ buf_len = ALIGN(buf_len, c->min_io_size);
-+ used = 0;
-+ avail = buf_len;
-+
-+ /* Ensure there is enough room for first write */
-+ next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
-+ if (buf_offs + next_len > c->leb_size)
-+ lnum = -1;
-+
-+ while (1) {
-+ znode = cnext;
-+
-+ len = ubifs_idx_node_sz(c, znode->child_cnt);
-+
-+ /* Determine the index node position */
-+ if (lnum == -1) {
-+ if (c->ileb_nxt >= c->ileb_cnt) {
-+ ubifs_err("out of space");
-+ return -ENOSPC;
-+ }
-+ lnum = c->ilebs[c->ileb_nxt++];
-+ buf_offs = 0;
-+ used = 0;
-+ avail = buf_len;
-+ }
-+
-+ offs = buf_offs + used;
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ znode->lnum = lnum;
-+ znode->offs = offs;
-+ znode->len = len;
-+#endif
-+
-+ /* Update the parent */
-+ zp = znode->parent;
-+ if (zp) {
-+ struct ubifs_zbranch *zbr;
-+ int i;
-+
-+ i = znode->iip;
-+ zbr = &zp->zbranch[i];
-+ zbr->lnum = lnum;
-+ zbr->offs = offs;
-+ zbr->len = len;
-+ } else {
-+ c->zroot.lnum = lnum;
-+ c->zroot.offs = offs;
-+ c->zroot.len = len;
-+ }
-+ c->calc_idx_sz += ALIGN(len, 8);
-+
-+ /*
-+ * Once lprops is updated, we can decrease the dirty znode count
-+ * but it is easier to just do it here.
-+ */
-+ atomic_long_dec(&c->dirty_zn_cnt);
-+
-+ /*
-+ * Calculate the next index node length to see if there is
-+ * enough room for it
-+ */
-+ cnext = znode->cnext;
-+ if (cnext == c->cnext)
-+ next_len = 0;
-+ else
-+ next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
-+
-+ if (c->min_io_size == 1) {
-+ buf_offs += ALIGN(len, 8);
-+ if (next_len) {
-+ if (buf_offs + next_len <= c->leb_size)
-+ continue;
-+ err = ubifs_update_one_lp(c, lnum, 0,
-+ c->leb_size - buf_offs, 0, 0);
-+ if (err)
-+ return err;
-+ lnum = -1;
-+ continue;
-+ }
-+ err = ubifs_update_one_lp(c, lnum,
-+ c->leb_size - buf_offs, 0, 0, 0);
-+ if (err)
-+ return err;
-+ break;
-+ }
-+
-+ /* Update buffer positions */
-+ wlen = used + len;
-+ used += ALIGN(len, 8);
-+ avail -= ALIGN(len, 8);
-+
-+ if (next_len != 0 &&
-+ buf_offs + used + next_len <= c->leb_size &&
-+ avail > 0)
-+ continue;
-+
-+ if (avail <= 0 && next_len &&
-+ buf_offs + used + next_len <= c->leb_size)
-+ blen = buf_len;
-+ else
-+ blen = ALIGN(wlen, c->min_io_size);
-+
-+ /* The buffer is full or there are no more znodes to do */
-+ buf_offs += blen;
-+ if (next_len) {
-+ if (buf_offs + next_len > c->leb_size) {
-+ err = ubifs_update_one_lp(c, lnum,
-+ c->leb_size - buf_offs, blen - used,
-+ 0, 0);
-+ if (err)
-+ return err;
-+ lnum = -1;
-+ }
-+ used -= blen;
-+ if (used < 0)
-+ used = 0;
-+ avail = buf_len - used;
-+ continue;
-+ }
-+ err = ubifs_update_one_lp(c, lnum, c->leb_size - buf_offs,
-+ blen - used, 0, 0);
-+ if (err)
-+ return err;
-+ break;
-+ }
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ c->new_ihead_lnum = lnum;
-+ c->new_ihead_offs = buf_offs;
-+#endif
-+
-+ return 0;
-+}
-+
-+/**
-+ * layout_commit - determine positions of index nodes to commit.
-+ * @c: UBIFS file-system description object
-+ * @no_space: indicates that insufficient empty LEBs were allocated
-+ * @cnt: number of znodes to commit
-+ *
-+ * Calculate and update the positions of index nodes to commit. If there were
-+ * an insufficient number of empty LEBs allocated, then index nodes are placed
-+ * into the gaps created by obsolete index nodes in non-empty index LEBs. For
-+ * this purpose, an obsolete index node is one that was not in the index as at
-+ * the end of the last commit. To write "in-the-gaps" requires that those index
-+ * LEBs are updated atomically in-place.
-+ */
-+static int layout_commit(struct ubifs_info *c, int no_space, int cnt)
-+{
-+ int err;
-+
-+ if (no_space) {
-+ err = layout_in_gaps(c, cnt);
-+ if (err)
-+ return err;
-+ }
-+ err = layout_in_empty_space(c);
-+ return err;
-+}
-+
-+/**
-+ * find_first_dirty - find first dirty znode.
-+ * @znode: znode to begin searching from
-+ */
-+static struct ubifs_znode *find_first_dirty(struct ubifs_znode *znode)
-+{
-+ int i, cont;
-+
-+ if (!znode)
-+ return NULL;
-+
-+ while (1) {
-+ if (znode->level == 0) {
-+ if (ubifs_zn_dirty(znode))
-+ return znode;
-+ return NULL;
-+ }
-+ cont = 0;
-+ for (i = 0; i < znode->child_cnt; i++) {
-+ struct ubifs_zbranch *zbr = &znode->zbranch[i];
-+
-+ if (zbr->znode && ubifs_zn_dirty(zbr->znode)) {
-+ znode = zbr->znode;
-+ cont = 1;
-+ break;
-+ }
-+ }
-+ if (!cont) {
-+ if (ubifs_zn_dirty(znode))
-+ return znode;
-+ return NULL;
-+ }
-+ }
-+}
-+
-+/**
-+ * find_next_dirty - find next dirty znode.
-+ * @znode: znode to begin searching from
-+ */
-+static struct ubifs_znode *find_next_dirty(struct ubifs_znode *znode)
-+{
-+ int n = znode->iip + 1;
-+
-+ znode = znode->parent;
-+ if (!znode)
-+ return NULL;
-+ for (; n < znode->child_cnt; n++) {
-+ struct ubifs_zbranch *zbr = &znode->zbranch[n];
-+
-+ if (zbr->znode && ubifs_zn_dirty(zbr->znode))
-+ return find_first_dirty(zbr->znode);
-+ }
-+ return znode;
-+}
-+
-+/**
-+ * get_znodes_to_commit - create list of dirty znodes to commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns the number of znodes to commit.
-+ */
-+static int get_znodes_to_commit(struct ubifs_info *c)
-+{
-+ struct ubifs_znode *znode, *cnext;
-+ int cnt = 0;
-+
-+ c->cnext = find_first_dirty(c->zroot.znode);
-+ znode = c->enext = c->cnext;
-+ if (!znode) {
-+ dbg_cmt("no znodes to commit");
-+ return 0;
-+ }
-+ cnt += 1;
-+ while (1) {
-+ ubifs_assert(!test_bit(COW_ZNODE, &znode->flags));
-+ __set_bit(COW_ZNODE, &znode->flags);
-+ znode->alt = 0;
-+ cnext = find_next_dirty(znode);
-+ if (!cnext) {
-+ znode->cnext = c->cnext;
-+ break;
-+ }
-+ znode->cnext = cnext;
-+ znode = cnext;
-+ cnt += 1;
-+ }
-+ dbg_cmt("committing %d znodes", cnt);
-+ ubifs_assert(cnt == atomic_long_read(&c->dirty_zn_cnt));
-+ return cnt;
-+}
-+
-+/**
-+ * alloc_idx_lebs - allocate empty LEBs to be used to commit.
-+ * @c: UBIFS file-system description object
-+ * @cnt: number of znodes to commit
-+ *
-+ * This function returns %-ENOSPC if it cannot allocate a sufficient number of
-+ * empty LEBs. %0 is returned on success, otherwise a negative error code
-+ * is returned.
-+ */
-+static int alloc_idx_lebs(struct ubifs_info *c, int cnt)
-+{
-+ int i, leb_cnt, lnum;
-+
-+ c->ileb_cnt = 0;
-+ c->ileb_nxt = 0;
-+ leb_cnt = get_leb_cnt(c, cnt);
-+ dbg_cmt("need about %d empty LEBS for TNC commit", leb_cnt);
-+ if (!leb_cnt)
-+ return 0;
-+ c->ilebs = kmalloc(leb_cnt * sizeof(int), GFP_NOFS);
-+ if (!c->ilebs)
-+ return -ENOMEM;
-+ for (i = 0; i < leb_cnt; i++) {
-+ lnum = ubifs_find_free_leb_for_idx(c);
-+ if (lnum < 0)
-+ return lnum;
-+ c->ilebs[c->ileb_cnt++] = lnum;
-+ dbg_cmt("LEB %d", lnum);
-+ }
-+ if (dbg_force_in_the_gaps())
-+ return -ENOSPC;
-+ return 0;
-+}
-+
-+/**
-+ * free_unused_idx_lebs - free unused LEBs that were allocated for the commit.
-+ * @c: UBIFS file-system description object
-+ *
-+ * It is possible that we allocate more empty LEBs for the commit than we need.
-+ * This functions frees the surplus.
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int free_unused_idx_lebs(struct ubifs_info *c)
-+{
-+ int i, err = 0, lnum, er;
-+
-+ for (i = c->ileb_nxt; i < c->ileb_cnt; i++) {
-+ lnum = c->ilebs[i];
-+ dbg_cmt("LEB %d", lnum);
-+ er = ubifs_change_one_lp(c, lnum, -1, -1, 0,
-+ LPROPS_INDEX | LPROPS_TAKEN, 0);
-+ if (!err)
-+ err = er;
-+ }
-+ return err;
-+}
-+
-+/**
-+ * free_idx_lebs - free unused LEBs after commit end.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function returns %0 on success and a negative error code on failure.
-+ */
-+static int free_idx_lebs(struct ubifs_info *c)
-+{
-+ int err;
-+
-+ err = free_unused_idx_lebs(c);
-+ kfree(c->ilebs);
-+ c->ilebs = NULL;
-+ return err;
-+}
-+
-+/**
-+ * ubifs_tnc_start_commit - start TNC commit.
-+ * @c: UBIFS file-system description object
-+ * @zroot: new index root position is returned here
-+ *
-+ * This function prepares the list of indexing nodes to commit and lays out
-+ * their positions on flash. If there is not enough free space it uses the
-+ * in-gap commit method. Returns zero in case of success and a negative error
-+ * code in case of failure.
-+ */
-+int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot)
-+{
-+ int err = 0, cnt;
-+
-+ mutex_lock(&c->tnc_mutex);
-+ err = dbg_check_tnc(c, 1);
-+ if (err)
-+ goto out;
-+ cnt = get_znodes_to_commit(c);
-+ if (cnt != 0) {
-+ int no_space = 0;
-+
-+ err = alloc_idx_lebs(c, cnt);
-+ if (err == -ENOSPC)
-+ no_space = 1;
-+ else if (err)
-+ goto out_free;
-+ err = layout_commit(c, no_space, cnt);
-+ if (err)
-+ goto out_free;
-+ ubifs_assert(atomic_long_read(&c->dirty_zn_cnt) == 0);
-+ err = free_unused_idx_lebs(c);
-+ if (err)
-+ goto out;
-+ }
-+ destroy_old_idx(c);
-+ memcpy(zroot, &c->zroot, sizeof(struct ubifs_zbranch));
-+
-+ err = ubifs_save_dirty_idx_lnums(c);
-+ if (err)
-+ goto out;
-+
-+ spin_lock(&c->space_lock);
-+ /*
-+ * Although we have not finished committing yet, update size of the
-+ * committed index ('c->old_idx_sz') and zero out the index growth
-+ * budget. It is OK to do this now, because we've reserved all the
-+ * space which is needed to commit the index, and it is save for the
-+ * budgeting subsystem to assume the index is already committed,
-+ * even though it is not.
-+ */
-+ c->old_idx_sz = c->calc_idx_sz;
-+ c->budg_uncommitted_idx = 0;
-+ spin_unlock(&c->space_lock);
-+ mutex_unlock(&c->tnc_mutex);
-+
-+ dbg_cmt("number of index LEBs %d", c->lst.idx_lebs);
-+ dbg_cmt("size of index %llu", c->calc_idx_sz);
-+ return err;
-+
-+out_free:
-+ free_idx_lebs(c);
-+out:
-+ mutex_unlock(&c->tnc_mutex);
-+ return err;
-+}
-+
-+/**
-+ * write_index - write index nodes.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function writes the index nodes whose positions were laid out in the
-+ * layout_in_empty_space function.
-+ */
-+static int write_index(struct ubifs_info *c)
-+{
-+ struct ubifs_idx_node *idx;
-+ struct ubifs_znode *znode, *cnext;
-+ int i, lnum, offs, len, next_len, buf_len, buf_offs, used;
-+ int avail, wlen, err, lnum_pos = 0;
-+
-+ cnext = c->enext;
-+ if (!cnext)
-+ return 0;
-+
-+ /*
-+ * Always write index nodes to the index head so that index nodes and
-+ * other types of nodes are never mixed in the same erase block.
-+ */
-+ lnum = c->ihead_lnum;
-+ buf_offs = c->ihead_offs;
-+
-+ /* Allocate commit buffer */
-+ buf_len = ALIGN(c->max_idx_node_sz, c->min_io_size);
-+ used = 0;
-+ avail = buf_len;
-+
-+ /* Ensure there is enough room for first write */
-+ next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
-+ if (buf_offs + next_len > c->leb_size) {
-+ err = ubifs_update_one_lp(c, lnum, -1, -1, 0, LPROPS_TAKEN);
-+ if (err)
-+ return err;
-+ lnum = -1;
-+ }
-+
-+ while (1) {
-+ cond_resched();
-+
-+ znode = cnext;
-+ idx = c->cbuf + used;
-+
-+ /* Make index node */
-+ idx->ch.node_type = UBIFS_IDX_NODE;
-+ idx->child_cnt = cpu_to_le16(znode->child_cnt);
-+ idx->level = cpu_to_le16(znode->level);
-+ for (i = 0; i < znode->child_cnt; i++) {
-+ struct ubifs_branch *br = ubifs_idx_branch(c, idx, i);
-+ struct ubifs_zbranch *zbr = &znode->zbranch[i];
-+
-+ key_write_idx(c, &zbr->key, &br->key);
-+ br->lnum = cpu_to_le32(zbr->lnum);
-+ br->offs = cpu_to_le32(zbr->offs);
-+ br->len = cpu_to_le32(zbr->len);
-+ if (!zbr->lnum || !zbr->len) {
-+ ubifs_err("bad ref in znode");
-+ dbg_dump_znode(c, znode);
-+ if (zbr->znode)
-+ dbg_dump_znode(c, zbr->znode);
-+ }
-+ }
-+ len = ubifs_idx_node_sz(c, znode->child_cnt);
-+ ubifs_prepare_node(c, idx, len, 0);
-+
-+ /* Determine the index node position */
-+ if (lnum == -1) {
-+ lnum = c->ilebs[lnum_pos++];
-+ buf_offs = 0;
-+ used = 0;
-+ avail = buf_len;
-+ }
-+ offs = buf_offs + used;
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ if (lnum != znode->lnum || offs != znode->offs ||
-+ len != znode->len) {
-+ ubifs_err("inconsistent znode posn");
-+ return -EINVAL;
-+ }
-+#endif
-+
-+ /* Grab some stuff from znode while we still can */
-+ cnext = znode->cnext;
-+
-+ ubifs_assert(ubifs_zn_dirty(znode));
-+ ubifs_assert(test_bit(COW_ZNODE, &znode->flags));
-+
-+ /*
-+ * It is important that other threads should see %DIRTY_ZNODE
-+ * flag cleared before %COW_ZNODE. Specifically, it matters in
-+ * the 'dirty_cow_znode()' function. This is the reason for the
-+ * first barrier. Also, we want the bit changes to be seen to
-+ * other threads ASAP, to avoid unnecesarry copying, which is
-+ * the reason for the second barrier.
-+ */
-+ clear_bit(DIRTY_ZNODE, &znode->flags);
-+ smp_mb__before_clear_bit();
-+ clear_bit(COW_ZNODE, &znode->flags);
-+ smp_mb__after_clear_bit();
-+
-+ /* Do not access znode from this point on */
-+
-+ /* Update buffer positions */
-+ wlen = used + len;
-+ used += ALIGN(len, 8);
-+ avail -= ALIGN(len, 8);
-+
-+ /*
-+ * Calculate the next index node length to see if there is
-+ * enough room for it
-+ */
-+ if (cnext == c->cnext)
-+ next_len = 0;
-+ else
-+ next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
-+
-+ if (c->min_io_size == 1) {
-+ /*
-+ * Write the prepared index node immediately if there is
-+ * no minimum IO size
-+ */
-+ err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs,
-+ wlen, UBI_SHORTTERM);
-+ if (err)
-+ return err;
-+ buf_offs += ALIGN(wlen, 8);
-+ if (next_len) {
-+ used = 0;
-+ avail = buf_len;
-+ if (buf_offs + next_len > c->leb_size) {
-+ err = ubifs_update_one_lp(c, lnum, -1,
-+ -1, 0,
-+ LPROPS_TAKEN);
-+ if (err)
-+ return err;
-+ lnum = -1;
-+ }
-+ continue;
-+ }
-+ } else {
-+ int blen, nxt_offs = buf_offs + used + next_len;
-+
-+ if (next_len && nxt_offs <= c->leb_size) {
-+ if (avail > 0)
-+ continue;
-+ else
-+ blen = buf_len;
-+ } else {
-+ wlen = ALIGN(wlen, 8);
-+ blen = ALIGN(wlen, c->min_io_size);
-+ ubifs_pad(c, c->cbuf + wlen, blen - wlen);
-+ }
-+ /*
-+ * The buffer is full or there are no more znodes
-+ * to do
-+ */
-+ err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs,
-+ blen, UBI_SHORTTERM);
-+ if (err)
-+ return err;
-+ buf_offs += blen;
-+ if (next_len) {
-+ if (nxt_offs > c->leb_size) {
-+ err = ubifs_update_one_lp(c, lnum, -1,
-+ -1, 0,
-+ LPROPS_TAKEN);
-+ if (err)
-+ return err;
-+ lnum = -1;
-+ }
-+ used -= blen;
-+ if (used < 0)
-+ used = 0;
-+ avail = buf_len - used;
-+ memmove(c->cbuf, c->cbuf + blen, used);
-+ continue;
-+ }
-+ }
-+ break;
-+ }
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ if (lnum != c->new_ihead_lnum || buf_offs != c->new_ihead_offs) {
-+ ubifs_err("inconsistent ihead");
-+ return -EINVAL;
-+ }
-+#endif
-+
-+ c->ihead_lnum = lnum;
-+ c->ihead_offs = buf_offs;
-+
-+ return 0;
-+}
-+
-+/**
-+ * free_obsolete_znodes - free obsolete znodes.
-+ * @c: UBIFS file-system description object
-+ *
-+ * At the end of commit end, obsolete znodes are freed.
-+ */
-+static void free_obsolete_znodes(struct ubifs_info *c)
-+{
-+ struct ubifs_znode *znode, *cnext;
-+
-+ cnext = c->cnext;
-+ do {
-+ znode = cnext;
-+ cnext = znode->cnext;
-+ if (test_bit(OBSOLETE_ZNODE, &znode->flags))
-+ kfree(znode);
-+ else {
-+ znode->cnext = NULL;
-+ atomic_long_inc(&c->clean_zn_cnt);
-+ atomic_long_inc(&ubifs_clean_zn_cnt);
-+ }
-+ } while (cnext != c->cnext);
-+}
-+
-+/**
-+ * return_gap_lebs - return LEBs used by the in-gap commit method.
-+ * @c: UBIFS file-system description object
-+ *
-+ * This function clears the "taken" flag for the LEBs which were used by the
-+ * "commit in-the-gaps" method.
-+ */
-+static int return_gap_lebs(struct ubifs_info *c)
-+{
-+ int *p, err;
-+
-+ if (!c->gap_lebs)
-+ return 0;
-+
-+ dbg_cmt("");
-+ for (p = c->gap_lebs; *p != -1; p++) {
-+ err = ubifs_change_one_lp(c, *p, -1, -1, 0, LPROPS_TAKEN, 0);
-+ if (err)
-+ return err;
-+ }
-+
-+ kfree(c->gap_lebs);
-+ c->gap_lebs = NULL;
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_tnc_end_commit - update the TNC for commit end.
-+ * @c: UBIFS file-system description object
-+ *
-+ * Write the dirty znodes.
-+ */
-+int ubifs_tnc_end_commit(struct ubifs_info *c)
-+{
-+ int err;
-+
-+ if (!c->cnext)
-+ return 0;
-+
-+ err = return_gap_lebs(c);
-+ if (err)
-+ return err;
-+
-+ err = write_index(c);
-+ if (err)
-+ return err;
-+
-+ mutex_lock(&c->tnc_mutex);
-+
-+ dbg_cmt("TNC height is %d", c->zroot.znode->level + 1);
-+
-+ free_obsolete_znodes(c);
-+
-+ c->cnext = NULL;
-+ kfree(c->ilebs);
-+ c->ilebs = NULL;
-+
-+ mutex_unlock(&c->tnc_mutex);
-+
-+ return 0;
-+}
---- linux-2.6.24.7.old/fs/ubifs/tnc_misc.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/tnc_misc.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,259 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Adrian Hunter
-+ * Artem Bityutskiy (Битюцкий Артём)
-+ */
-+
-+/*
-+ * This file contains miscelanious TNC-related functions shared betweend
-+ * different files. This file does not form any logically separate TNC
-+ * sub-system. The file was created because there is a lot of TNC code and
-+ * putting it all in one file would make that file too big and unreadable.
-+ * Nonetheless, this contains more or less "generic" code which may be used for
-+ * more then one specific task.
-+ */
-+
-+#include "ubifs.h"
-+
-+/**
-+ * ubifs_tnc_levelorder_next - next TNC tree element in levelorder traversal.
-+ * @zr: root of the subtree to traverse
-+ * @znode: previous znode
-+ *
-+ * This function implements levelorder TNC traversal. The LNC is ignored.
-+ * Returns the next element or %NULL if @znode is already the last one.
-+ */
-+struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr,
-+ struct ubifs_znode *znode)
-+{
-+ int level, iip, level_search = 0;
-+ struct ubifs_znode *zn;
-+
-+ ubifs_assert(zr);
-+
-+ if (unlikely(!znode))
-+ return zr;
-+
-+ if (unlikely(znode == zr)) {
-+ if (znode->level == 0)
-+ return NULL;
-+ return ubifs_tnc_find_child(zr, 0);
-+ }
-+
-+ level = znode->level;
-+
-+ iip = znode->iip;
-+ while (1) {
-+ ubifs_assert(znode->level <= zr->level);
-+
-+ /*
-+ * First walk up until there is a znode with next branch to
-+ * look at.
-+ */
-+ while (znode->parent != zr && iip >= znode->parent->child_cnt) {
-+ znode = znode->parent;
-+ iip = znode->iip;
-+ }
-+
-+ if (unlikely(znode->parent == zr &&
-+ iip >= znode->parent->child_cnt)) {
-+ /* This level is done, switch to the lower one */
-+ level -= 1;
-+ if (level_search || level < 0)
-+ /*
-+ * We were already looking for znode at lower
-+ * level ('level_search'). As we are here
-+ * again, it just does not exist. Or all levels
-+ * were finished ('level < 0').
-+ */
-+ return NULL;
-+
-+ level_search = 1;
-+ iip = -1;
-+ znode = ubifs_tnc_find_child(zr, 0);
-+ ubifs_assert(znode);
-+ }
-+
-+ /* Switch to the next index */
-+ zn = ubifs_tnc_find_child(znode->parent, iip + 1);
-+ if (!zn) {
-+ /* No more children to look at, we have walk up */
-+ iip = znode->parent->child_cnt;
-+ continue;
-+ }
-+
-+ /* Walk back down to the level we came from ('level') */
-+ while (zn->level != level) {
-+ znode = zn;
-+ zn = ubifs_tnc_find_child(zn, 0);
-+ if (!zn) {
-+ /*
-+ * This path is not too deep so it does not
-+ * reach 'level'. Try next path.
-+ */
-+ iip = znode->iip;
-+ break;
-+ }
-+ }
-+
-+ if (zn) {
-+ ubifs_assert(zn->level >= 0);
-+ return zn;
-+ }
-+ }
-+}
-+
-+/**
-+ * ubifs_search_zbranch - search znode branch.
-+ * @c: UBIFS file-system description object
-+ * @znode: znode to search in
-+ * @key: key to search for
-+ * @n: znode branch slot number is returned here
-+ *
-+ * This is a helper function which search branch with key @key in @znode using
-+ * binary search. The result of the search may be:
-+ * o exact match, then %1 is returned, and the slot number of the branch is
-+ * stored in @n;
-+ * o no exact match, then %0 is returned and the slot number of the left
-+ * closest branch is returned in @n; the slot if all keys in this znode are
-+ * greater than @key, then %-1 is returned in @n.
-+ */
-+int ubifs_search_zbranch(const struct ubifs_info *c,
-+ const struct ubifs_znode *znode,
-+ const union ubifs_key *key, int *n)
-+{
-+ int beg = 0, end = znode->child_cnt, uninitialized_var(mid);
-+ int uninitialized_var(cmp);
-+ const struct ubifs_zbranch *zbr = &znode->zbranch[0];
-+
-+ ubifs_assert(end > beg);
-+
-+ while (end > beg) {
-+ mid = (beg + end) >> 1;
-+ cmp = keys_cmp(c, key, &zbr[mid].key);
-+ if (cmp > 0)
-+ beg = mid + 1;
-+ else if (cmp < 0)
-+ end = mid;
-+ else {
-+ *n = mid;
-+ return 1;
-+ }
-+ }
-+
-+ *n = end - 1;
-+
-+ /* The insert point is after *n */
-+ ubifs_assert(*n >= -1 && *n < znode->child_cnt);
-+ if (*n == -1)
-+ ubifs_assert(keys_cmp(c, key, &zbr[0].key) < 0);
-+ else
-+ ubifs_assert(keys_cmp(c, key, &zbr[*n].key) > 0);
-+ if (*n + 1 < znode->child_cnt)
-+ ubifs_assert(keys_cmp(c, key, &zbr[*n + 1].key) < 0);
-+
-+ return 0;
-+}
-+
-+/**
-+ * ubifs_tnc_postorder_first - find first znode to do postorder tree traversal.
-+ * @znode: znode to start at (root of the sub-tree to traverse)
-+ *
-+ * Find the lowest leftmost znode in a subtree of the TNC tree. The LNC is
-+ * ignored.
-+ */
-+struct ubifs_znode *ubifs_tnc_postorder_first(struct ubifs_znode *znode)
-+{
-+ if (unlikely(!znode))
-+ return NULL;
-+
-+ while (znode->level > 0) {
-+ struct ubifs_znode *child;
-+
-+ child = ubifs_tnc_find_child(znode, 0);
-+ if (!child)
-+ return znode;
-+ znode = child;
-+ }
-+
-+ return znode;
-+}
-+
-+/**
-+ * ubifs_tnc_postorder_next - next TNC tree element in postorder traversal.
-+ * @znode: previous znode
-+ *
-+ * This function implements postorder TNC traversal. The LNC is ignored.
-+ * Returns the next element or %NULL if @znode is already the last one.
-+ */
-+struct ubifs_znode *ubifs_tnc_postorder_next(struct ubifs_znode *znode)
-+{
-+ struct ubifs_znode *zn;
-+
-+ ubifs_assert(znode);
-+ if (unlikely(!znode->parent))
-+ return NULL;
-+
-+ /* Switch to the next index in the parent */
-+ zn = ubifs_tnc_find_child(znode->parent, znode->iip + 1);
-+ if (!zn)
-+ /* This is in fact the last child, return parent */
-+ return znode->parent;
-+
-+ /* Go to the first znode in this new subtree */
-+ return ubifs_tnc_postorder_first(zn);
-+}
-+
-+/**
-+ * ubifs_destroy_tnc_subtree - destroy all znodes connected to a subtree.
-+ * @znode: znode defining subtree to destroy
-+ *
-+ * This function destroys subtree of the TNC tree. Returns number of clean
-+ * znodes in the subtree.
-+ */
-+long ubifs_destroy_tnc_subtree(struct ubifs_znode *znode)
-+{
-+ struct ubifs_znode *zn = ubifs_tnc_postorder_first(znode);
-+ long clean_freed = 0;
-+ int n;
-+
-+ ubifs_assert(zn);
-+ while (1) {
-+ for (n = 0; n < zn->child_cnt; n++) {
-+ if (!zn->zbranch[n].znode)
-+ continue;
-+
-+ if (zn->level > 0 &&
-+ !ubifs_zn_dirty(zn->zbranch[n].znode))
-+ clean_freed += 1;
-+
-+ cond_resched();
-+ kfree(zn->zbranch[n].znode);
-+ }
-+
-+ if (zn == znode) {
-+ if (!ubifs_zn_dirty(zn))
-+ clean_freed += 1;
-+ kfree(zn);
-+ return clean_freed;
-+ }
-+
-+ zn = ubifs_tnc_postorder_next(zn);
-+ }
-+}
---- linux-2.6.24.7.old/fs/ubifs/ubifs-media.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/ubifs-media.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,731 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file describes UBIFS on-flash format and contains definitions of all the
-+ * relevant data structures and constants.
-+ *
-+ * All UBIFS on-flash objects are stored in the form of nodes. All nodes start
-+ * with the UBIFS node magic number and have the same common header. Nodes
-+ * always sit at 8-byte aligned positions on the media and node header sizes are
-+ * also 8-byte aligned (except for the indexing node and the padding node).
-+ */
-+
-+#ifndef __UBIFS_MEDIA_H__
-+#define __UBIFS_MEDIA_H__
-+
-+/* UBIFS node magic number (must not have the padding byte first or last) */
-+#define UBIFS_NODE_MAGIC 0x06101831
-+
-+/* UBIFS on-flash format version */
-+#define UBIFS_FORMAT_VERSION 3
-+
-+/* Minimum logical eraseblock size in bytes */
-+#define UBIFS_MIN_LEB_SZ (15*1024)
-+
-+/* Initial CRC32 value used when calculating CRC checksums */
-+#define UBIFS_CRC32_INIT 0xFFFFFFFFU
-+
-+/*
-+ * UBIFS does not try to compress data if its length is less than the below
-+ * constant.
-+ */
-+#define UBIFS_MIN_COMPR_LEN 128
-+
-+/* Root inode number */
-+#define UBIFS_ROOT_INO 1
-+
-+/* Lowest inode number used for regular inodes (not UBIFS-only internal ones) */
-+#define UBIFS_FIRST_INO 64
-+
-+/*
-+ * Maximum file name and extended attribute length (must be a multiple of 8,
-+ * minus 1).
-+ */
-+#define UBIFS_MAX_NLEN 255
-+
-+/* Maximum number of data journal heads */
-+#define UBIFS_MAX_JHEADS 1
-+
-+/*
-+ * Size of UBIFS data block. Note, UBIFS is not a block oriented file-system,
-+ * which means that it does not treat the underlying media as consisting of
-+ * blocks like in case of hard drives. Do not be confused. UBIFS block is just
-+ * the maximum amount of data which one data node can have or which can be
-+ * attached to an inode node.
-+ */
-+#define UBIFS_BLOCK_SIZE 4096
-+#define UBIFS_BLOCK_SHIFT 12
-+#define UBIFS_BLOCK_MASK 0x00000FFF
-+
-+/* UBIFS padding byte pattern (must not be first or last byte of node magic) */
-+#define UBIFS_PADDING_BYTE 0xCE
-+
-+/* Maximum possible key length */
-+#define UBIFS_MAX_KEY_LEN 16
-+
-+/* Key length ("simple" format) */
-+#define UBIFS_SK_LEN 8
-+
-+/* Minimum index tree fanout */
-+#define UBIFS_MIN_FANOUT 2
-+
-+/* Maximum number of levels in UBIFS indexing B-tree */
-+#define UBIFS_MAX_LEVELS 512
-+
-+/* Maximum amount of data attached to an inode in bytes */
-+#define UBIFS_MAX_INO_DATA UBIFS_BLOCK_SIZE
-+
-+/* LEB Properties Tree fanout (must be power of 2) and fanout shift */
-+#define UBIFS_LPT_FANOUT 4
-+#define UBIFS_LPT_FANOUT_SHIFT 2
-+
-+/* LEB Properties Tree bit field sizes */
-+#define UBIFS_LPT_CRC_BITS 16
-+#define UBIFS_LPT_CRC_BYTES 2
-+#define UBIFS_LPT_TYPE_BITS 4
-+
-+/* The key is always at the same position in all keyed nodes */
-+#define UBIFS_KEY_OFFSET offsetof(struct ubifs_ino_node, key)
-+
-+/*
-+ * LEB Properties Tree node types.
-+ *
-+ * UBIFS_LPT_PNODE: LPT leaf node (contains LEB properties)
-+ * UBIFS_LPT_NNODE: LPT internal node
-+ * UBIFS_LPT_LTAB: LPT's own lprops table
-+ * UBIFS_LPT_LSAVE: LPT's save table (big model only)
-+ * UBIFS_LPT_NODE_CNT: count of LPT node types
-+ * UBIFS_LPT_NOT_A_NODE: all ones (15 for 4 bits) is never a valid node type
-+ */
-+enum {
-+ UBIFS_LPT_PNODE,
-+ UBIFS_LPT_NNODE,
-+ UBIFS_LPT_LTAB,
-+ UBIFS_LPT_LSAVE,
-+ UBIFS_LPT_NODE_CNT,
-+ UBIFS_LPT_NOT_A_NODE = (1 << UBIFS_LPT_TYPE_BITS) - 1,
-+};
-+
-+/*
-+ * UBIFS inode types.
-+ *
-+ * UBIFS_ITYPE_REG: regular file
-+ * UBIFS_ITYPE_DIR: directory
-+ * UBIFS_ITYPE_LNK: soft link
-+ * UBIFS_ITYPE_BLK: block device node
-+ * UBIFS_ITYPE_CHR: character device node
-+ * UBIFS_ITYPE_FIFO: fifo
-+ * UBIFS_ITYPE_SOCK: socket
-+ * UBIFS_ITYPES_CNT: count of supported file types
-+ */
-+enum {
-+ UBIFS_ITYPE_REG,
-+ UBIFS_ITYPE_DIR,
-+ UBIFS_ITYPE_LNK,
-+ UBIFS_ITYPE_BLK,
-+ UBIFS_ITYPE_CHR,
-+ UBIFS_ITYPE_FIFO,
-+ UBIFS_ITYPE_SOCK,
-+ UBIFS_ITYPES_CNT,
-+};
-+
-+/*
-+ * Supported key hash functions.
-+ *
-+ * UBIFS_KEY_HASH_R5: R5 hash
-+ * UBIFS_KEY_HASH_TEST: test hash which just returns first 4 bytes of the name
-+ */
-+enum {
-+ UBIFS_KEY_HASH_R5,
-+ UBIFS_KEY_HASH_TEST,
-+};
-+
-+/*
-+ * Supported key formats.
-+ *
-+ * UBIFS_SIMPLE_KEY_FMT: simple key format
-+ */
-+enum {
-+ UBIFS_SIMPLE_KEY_FMT,
-+};
-+
-+/*
-+ * The simple key format uses 29 bits for storing UBIFS block number and hash
-+ * value.
-+ */
-+#define UBIFS_S_KEY_BLOCK_BITS 29
-+/*
-+ * TODO: this is a temporary hach which was added to support old format and to
-+ * avoid breaking binary compatibility. It is temporaty and should go. The
-+ * define should be
-+ * #define UBIFS_S_KEY_BLOCK_MASK 0x1FFFFFFF
-+ */
-+#define UBIFS_S_KEY_BLOCK_MASK (c->fmt_version == 2 ? 0x01FFFFFF : 0x1FFFFFFF)
-+#define UBIFS_S_KEY_HASH_BITS UBIFS_S_KEY_BLOCK_BITS
-+#define UBIFS_S_KEY_HASH_MASK UBIFS_S_KEY_BLOCK_MASK
-+
-+/*
-+ * Key types.
-+ *
-+ * UBIFS_INO_KEY: inode node key
-+ * UBIFS_DATA_KEY: data node key
-+ * UBIFS_DENT_KEY: directory entry node key
-+ * UBIFS_XENT_KEY: extended attribute entry key
-+ * UBIFS_TRUN_KEY: truncation node key
-+ * UBIFS_KEY_TYPES_CNT: number of supported key types
-+ */
-+enum {
-+ UBIFS_INO_KEY,
-+ UBIFS_DATA_KEY,
-+ UBIFS_DENT_KEY,
-+ UBIFS_XENT_KEY,
-+ UBIFS_TRUN_KEY,
-+ UBIFS_KEY_TYPES_CNT,
-+};
-+
-+/* Count of LEBs reserved for the superblock area */
-+#define UBIFS_SB_LEBS 1
-+/* Count of LEBs reserved for the master area */
-+#define UBIFS_MST_LEBS 2
-+
-+/* First LEB of the superblock area */
-+#define UBIFS_SB_LNUM 0
-+/* First LEB of the master area */
-+#define UBIFS_MST_LNUM (UBIFS_SB_LNUM + UBIFS_SB_LEBS)
-+/* First LEB of the log area */
-+#define UBIFS_LOG_LNUM (UBIFS_MST_LNUM + UBIFS_MST_LEBS)
-+
-+/* Minimum number of logical eraseblocks in the log */
-+#define UBIFS_MIN_LOG_LEBS 2
-+/* Minimum number of bud logical eraseblocks */
-+#define UBIFS_MIN_BUD_LEBS 2
-+/* Minimum number of journal logical eraseblocks */
-+#define UBIFS_MIN_JNL_LEBS (UBIFS_MIN_LOG_LEBS + UBIFS_MIN_BUD_LEBS)
-+/* Minimum number of LPT area logical eraseblocks */
-+#define UBIFS_MIN_LPT_LEBS 2
-+/* Minimum number of orphan area logical eraseblocks */
-+#define UBIFS_MIN_ORPH_LEBS 1
-+/* Minimum number of main area logical eraseblocks */
-+#define UBIFS_MIN_MAIN_LEBS 8
-+
-+/* Minimum number of logical eraseblocks */
-+#define UBIFS_MIN_LEB_CNT (UBIFS_SB_LEBS + UBIFS_MST_LEBS + \
-+ UBIFS_MIN_LOG_LEBS + UBIFS_MIN_BUD_LEBS + \
-+ UBIFS_MIN_LPT_LEBS + UBIFS_MIN_ORPH_LEBS + \
-+ UBIFS_MIN_MAIN_LEBS)
-+
-+/* Node sizes (N.B. these are guaranteed to be multiples of 8) */
-+#define UBIFS_CH_SZ sizeof(struct ubifs_ch)
-+#define UBIFS_INO_NODE_SZ sizeof(struct ubifs_ino_node)
-+#define UBIFS_DATA_NODE_SZ sizeof(struct ubifs_data_node)
-+#define UBIFS_DENT_NODE_SZ sizeof(struct ubifs_dent_node)
-+#define UBIFS_TRUN_NODE_SZ sizeof(struct ubifs_trun_node)
-+#define UBIFS_PAD_NODE_SZ sizeof(struct ubifs_pad_node)
-+#define UBIFS_SB_NODE_SZ sizeof(struct ubifs_sb_node)
-+#define UBIFS_MST_NODE_SZ sizeof(struct ubifs_mst_node)
-+#define UBIFS_REF_NODE_SZ sizeof(struct ubifs_ref_node)
-+#define UBIFS_IDX_NODE_SZ sizeof(struct ubifs_idx_node)
-+#define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node)
-+#define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node)
-+/* Extended attribute entry nodes are identical to directory entry nodes */
-+#define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ
-+/* Only this does not have to be multiple of 8 bytes */
-+#define UBIFS_BRANCH_SZ sizeof(struct ubifs_branch)
-+
-+/* Maximum node sizes (N.B. these are guaranteed to be multiples of 8) */
-+#define UBIFS_MAX_DATA_NODE_SZ (UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE)
-+#define UBIFS_MAX_INO_NODE_SZ (UBIFS_INO_NODE_SZ + UBIFS_MAX_INO_DATA)
-+#define UBIFS_MAX_DENT_NODE_SZ (UBIFS_DENT_NODE_SZ + UBIFS_MAX_NLEN + 1)
-+#define UBIFS_MAX_XENT_NODE_SZ UBIFS_MAX_DENT_NODE_SZ
-+
-+/* The largest UBIFS node */
-+#define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ
-+
-+/*
-+ * On-flash inode flags.
-+ *
-+ * UBIFS_COMPR_FL: use compression for this inode
-+ * UBIFS_SYNC_FL: I/O on this inode has to be synchronous
-+ * UBIFS_IMMUTABLE_FL: inode is immutable
-+ * UBIFS_APPEND_FL: writes to the inode may only append data
-+ * UBIFS_DIRSYNC_FL: I/O on this directory inode has to be synchronous
-+ *
-+ * Note, these are on-flash flags which correspond to ioctl flags
-+ * (@FS_COMPR_FL, etc). They have the same values now, but generally, do not
-+ * have to be the same.
-+ */
-+enum {
-+ UBIFS_COMPR_FL = 0x01,
-+ UBIFS_SYNC_FL = 0x02,
-+ UBIFS_IMMUTABLE_FL = 0x04,
-+ UBIFS_APPEND_FL = 0x08,
-+ UBIFS_DIRSYNC_FL = 0x10,
-+};
-+
-+/* Inode flag bits used by UBIFS */
-+#define UBIFS_FL_MASK 0x0000001F
-+
-+/*
-+ * UBIFS compression types.
-+ *
-+ * UBIFS_COMPR_NONE: no compression
-+ * UBIFS_COMPR_LZO: LZO compression
-+ * UBIFS_COMPR_ZLIB: ZLIB compression
-+ * UBIFS_COMPR_TYPES_CNT: count of supported compression types
-+ */
-+enum {
-+ UBIFS_COMPR_NONE,
-+ UBIFS_COMPR_LZO,
-+ UBIFS_COMPR_ZLIB,
-+ UBIFS_COMPR_TYPES_CNT,
-+};
-+
-+/*
-+ * UBIFS node types.
-+ *
-+ * UBIFS_INO_NODE: inode node
-+ * UBIFS_DATA_NODE: data node
-+ * UBIFS_DENT_NODE: directory entry node
-+ * UBIFS_XENT_NODE: extended attribute node
-+ * UBIFS_TRUN_NODE: truncation node
-+ * UBIFS_PAD_NODE: padding node
-+ * UBIFS_SB_NODE: superblock node
-+ * UBIFS_MST_NODE: master node
-+ * UBIFS_REF_NODE: LEB reference node
-+ * UBIFS_IDX_NODE: index node
-+ * UBIFS_CS_NODE: commit start node
-+ * UBIFS_ORPH_NODE: orphan node
-+ * UBIFS_NODE_TYPES_CNT: count of supported node types
-+ *
-+ * Note, we index arrays by these numbers, so keep them low and contiguous.
-+ * Node type constants for inodes, direntries and so on have to be the same as
-+ * corresponding key type constants.
-+ */
-+enum {
-+ UBIFS_INO_NODE,
-+ UBIFS_DATA_NODE,
-+ UBIFS_DENT_NODE,
-+ UBIFS_XENT_NODE,
-+ UBIFS_TRUN_NODE,
-+ UBIFS_PAD_NODE,
-+ UBIFS_SB_NODE,
-+ UBIFS_MST_NODE,
-+ UBIFS_REF_NODE,
-+ UBIFS_IDX_NODE,
-+ UBIFS_CS_NODE,
-+ UBIFS_ORPH_NODE,
-+ UBIFS_NODE_TYPES_CNT,
-+};
-+
-+/*
-+ * Master node flags.
-+ *
-+ * UBIFS_MST_DIRTY: rebooted uncleanly - master node is dirty
-+ * UBIFS_MST_NO_ORPHS: no orphan inodes present
-+ * UBIFS_MST_RCVRY: written by recovery
-+ */
-+enum {
-+ UBIFS_MST_DIRTY = 1,
-+ UBIFS_MST_NO_ORPHS = 2,
-+ UBIFS_MST_RCVRY = 4,
-+};
-+
-+/*
-+ * Node group type (used by recovery to recover whole group or none).
-+ *
-+ * UBIFS_NO_NODE_GROUP: this node is not part of a group
-+ * UBIFS_IN_NODE_GROUP: this node is a part of a group
-+ * UBIFS_LAST_OF_NODE_GROUP: this node is the last in a group
-+ */
-+enum {
-+ UBIFS_NO_NODE_GROUP = 0,
-+ UBIFS_IN_NODE_GROUP,
-+ UBIFS_LAST_OF_NODE_GROUP,
-+};
-+
-+/*
-+ * Superblock flags.
-+ *
-+ * UBIFS_FLG_BIGLPT: if "big" LPT model is used if set
-+ */
-+enum {
-+ UBIFS_FLG_BIGLPT = 0x02,
-+};
-+
-+/**
-+ * struct ubifs_ch - common header node.
-+ * @magic: UBIFS node magic number (%UBIFS_NODE_MAGIC)
-+ * @crc: CRC-32 checksum of the node header
-+ * @sqnum: sequence number
-+ * @len: full node length
-+ * @node_type: node type
-+ * @group_type: node group type
-+ * @padding: reserved for future, zeroes
-+ *
-+ * Every UBIFS node starts with this common part. If the node has a key, the
-+ * key always goes next.
-+ */
-+struct ubifs_ch {
-+ __le32 magic;
-+ __le32 crc;
-+ __le64 sqnum;
-+ __le32 len;
-+ __u8 node_type;
-+ __u8 group_type;
-+ __u8 padding[2];
-+} __attribute__ ((packed));
-+
-+/**
-+ * union ubifs_dev_desc - device node descriptor.
-+ * @new: new type device descriptor
-+ * @huge: huge type device descriptor
-+ *
-+ * This data structure describes major/minor numbers of a device node. In an
-+ * inode is a device node then its data contains an object of this type. UBIFS
-+ * uses standard Linux "new" and "huge" device node encodings.
-+ */
-+union ubifs_dev_desc {
-+ __le32 new;
-+ __le64 huge;
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_ino_node - inode node.
-+ * @ch: common header
-+ * @key: node key
-+ * @creat_sqnum: sequence number at time of creation
-+ * @size: inode size in bytes (amount of uncompressed data)
-+ * @atime_sec: access time seconds
-+ * @ctime_sec: creation time seconds
-+ * @mtime_sec: modification time seconds
-+ * @atime_nsec: access time nanoseconds
-+ * @ctime_nsec: creation time nanoseconds
-+ * @mtime_nsec: modification time nanoseconds
-+ * @nlink: number of hard links
-+ * @uid: owner ID
-+ * @gid: group ID
-+ * @mode: access flags
-+ * @flags: per-inode flags (%UBIFS_COMPR_FL, %UBIFS_SYNC_FL, etc)
-+ * @data_len: inode data length
-+ * @xattr_cnt: count of extended attributes this inode has
-+ * @xattr_size: summarized size of all extended attributes in bytes
-+ * @xattr_names: sum of lengths of all extended attribute names belonging to
-+ * this inode
-+ * @compr_type: compression type used for this inode
-+ * @padding: reserved for future, zeroes
-+ * @data: data attached to the inode
-+ *
-+ * Note, even though inode compression type is defined by @compr_type, some
-+ * nodes of this inode may be compressed with different compressor - this
-+ * happens if compression type is changed while the inode already has data
-+ * nodes. But @compr_type will be use for further writes to the inode.
-+ *
-+ * Note, do not forget to amend 'zero_ino_node_unused()' function when changing
-+ * the padding fields.
-+ */
-+struct ubifs_ino_node {
-+ struct ubifs_ch ch;
-+ __u8 key[UBIFS_MAX_KEY_LEN];
-+ __le64 creat_sqnum;
-+ __le64 size;
-+ __le64 atime_sec;
-+ __le64 ctime_sec;
-+ __le64 mtime_sec;
-+ __le32 atime_nsec;
-+ __le32 ctime_nsec;
-+ __le32 mtime_nsec;
-+ __le32 nlink;
-+ __le32 uid;
-+ __le32 gid;
-+ __le32 mode;
-+ __le32 flags;
-+ __le32 data_len;
-+ __le32 xattr_cnt;
-+ __le64 xattr_size;
-+ __le32 xattr_names;
-+ __le16 compr_type;
-+ __u8 padding[26]; /* Watch 'zero_ino_node_unused()' if changing! */
-+ __u8 data[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_dent_node - directory entry node.
-+ * @ch: common header
-+ * @key: node key
-+ * @inum: target inode number
-+ * @padding1: reserved for future, zeroes
-+ * @type: type of the target inode (%UBIFS_ITYPE_REG, %UBIFS_ITYPE_DIR, etc)
-+ * @nlen: name length
-+ * @padding2: reserved for future, zeroes
-+ * @name: zero-terminated name
-+ *
-+ * Note, do not forget to amend 'zero_dent_node_unused()' function when
-+ * changing the padding fields.
-+ */
-+struct ubifs_dent_node {
-+ struct ubifs_ch ch;
-+ __u8 key[UBIFS_MAX_KEY_LEN];
-+ __le64 inum;
-+ __u8 padding1;
-+ __u8 type;
-+ __le16 nlen;
-+ __u8 padding2[4]; /* Watch 'zero_dent_node_unused()' if changing! */
-+ __u8 name[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_data_node - data node.
-+ * @ch: common header
-+ * @key: node key
-+ * @size: uncompressed data size in bytes
-+ * @compr_type: compression type (%UBIFS_COMPR_NONE, %UBIFS_COMPR_LZO, etc)
-+ * @padding: reserved for future, zeroes
-+ * @data: data
-+ *
-+ * Note, do not forget to amend 'zero_data_node_unused()' function when
-+ * changing the padding fields.
-+ */
-+struct ubifs_data_node {
-+ struct ubifs_ch ch;
-+ __u8 key[UBIFS_MAX_KEY_LEN];
-+ __le32 size;
-+ __le16 compr_type;
-+ __u8 padding[2]; /* Watch 'zero_data_node_unused()' if changing! */
-+ __u8 data[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_trun_node - truncation node.
-+ * @ch: common header
-+ * @key: truncation node key
-+ * @old_size: size before truncation
-+ * @new_size: size after truncation
-+ *
-+ * This node exists only in the journal and never goes to the main area.
-+ */
-+struct ubifs_trun_node {
-+ struct ubifs_ch ch;
-+ __u8 key[UBIFS_MAX_KEY_LEN];
-+ __le64 old_size;
-+ __le64 new_size;
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_pad_node - padding node.
-+ * @ch: common header
-+ * @pad_len: how many bytes after this node are unused (because padded)
-+ * @padding: reserved for future, zeroes
-+ */
-+struct ubifs_pad_node {
-+ struct ubifs_ch ch;
-+ __le32 pad_len;
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_sb_node - superblock node.
-+ * @ch: common header
-+ * @padding: reserved for future, zeroes
-+ * @key_hash: type of hash function used in keys
-+ * @key_fmt: format of the key
-+ * @flags: file-system flags (%UBIFS_FLG_BIGLPT, etc)
-+ * @min_io_size: minimal input/output unit size
-+ * @leb_size: logical eraseblock size in bytes
-+ * @leb_cnt: count of LEBs used by filesystem
-+ * @max_leb_cnt: maximum count of LEBs used by filesystem
-+ * @max_bud_bytes: maximum amount of data stored in buds
-+ * @log_lebs: log size in logical eraseblocks
-+ * @lpt_lebs: number of LEBs used for lprops table
-+ * @orph_lebs: number of LEBs used for recording orphans
-+ * @jhead_cnt: count of journal heads
-+ * @fanout: tree fanout (max. number of links per indexing node)
-+ * @lsave_cnt: number of LEB numbers in LPT's save table
-+ * @fmt_version: UBIFS on-flash format version
-+ * @default_compr: default compression
-+ * @padding1: reserved for future, zeroes
-+ * @rp_uid: reserve pool UID
-+ * @rp_gid: reserve pool GID
-+ * @rp_size: size of the reserved pool in bytes
-+ * @padding2: reserved for future, zeroes
-+ * @time_gran: time granularity in nanoseconds
-+ */
-+struct ubifs_sb_node {
-+ struct ubifs_ch ch;
-+ __u8 padding[2];
-+ __u8 key_hash;
-+ __u8 key_fmt;
-+ __le32 flags;
-+ __le32 min_io_size;
-+ __le32 leb_size;
-+ __le32 leb_cnt;
-+ __le32 max_leb_cnt;
-+ __le64 max_bud_bytes;
-+ __le32 log_lebs;
-+ __le32 lpt_lebs;
-+ __le32 orph_lebs;
-+ __le32 jhead_cnt;
-+ __le32 fanout;
-+ __le32 lsave_cnt;
-+ __le32 fmt_version;
-+ __le16 default_compr;
-+ __u8 padding1[2];
-+ __le32 rp_uid;
-+ __le32 rp_gid;
-+ __le64 rp_size;
-+ __le32 time_gran;
-+ __u8 padding2[3988];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_mst_node - master node.
-+ * @ch: common header
-+ * @highest_inum: highest inode number in the committed index
-+ * @cmt_no: commit number
-+ * @flags: various flags (%UBIFS_MST_DIRTY, etc)
-+ * @log_lnum: start of the log
-+ * @root_lnum: LEB number of the root indexing node
-+ * @root_offs: offset within @root_lnum
-+ * @root_len: root indexing node length
-+ * @gc_lnum: LEB reserved for garbage collection (%-1 value means the LEB was
-+ * not reserved and should be reserved on mount)
-+ * @ihead_lnum: LEB number of index head
-+ * @ihead_offs: offset of index head
-+ * @index_size: size of index on flash
-+ * @total_free: total free space in bytes
-+ * @total_dirty: total dirty space in bytes
-+ * @total_used: total used space in bytes (includes only data LEBs)
-+ * @total_dead: total dead space in bytes (includes only data LEBs)
-+ * @total_dark: total dark space in bytes (includes only data LEBs)
-+ * @lpt_lnum: LEB number of LPT root nnode
-+ * @lpt_offs: offset of LPT root nnode
-+ * @nhead_lnum: LEB number of LPT head
-+ * @nhead_offs: offset of LPT head
-+ * @ltab_lnum: LEB number of LPT's own lprops table
-+ * @ltab_offs: offset of LPT's own lprops table
-+ * @lsave_lnum: LEB number of LPT's save table (big model only)
-+ * @lsave_offs: offset of LPT's save table (big model only)
-+ * @lscan_lnum: LEB number of last LPT scan
-+ * @empty_lebs: number of empty logical eraseblocks
-+ * @idx_lebs: number of indexing logical eraseblocks
-+ * @leb_cnt: count of LEBs used by filesystem
-+ * @padding: reserved for future, zeroes
-+ */
-+struct ubifs_mst_node {
-+ struct ubifs_ch ch;
-+ __le64 highest_inum;
-+ __le64 cmt_no;
-+ __le32 flags;
-+ __le32 log_lnum;
-+ __le32 root_lnum;
-+ __le32 root_offs;
-+ __le32 root_len;
-+ __le32 gc_lnum;
-+ __le32 ihead_lnum;
-+ __le32 ihead_offs;
-+ __le64 index_size;
-+ __le64 total_free;
-+ __le64 total_dirty;
-+ __le64 total_used;
-+ __le64 total_dead;
-+ __le64 total_dark;
-+ __le32 lpt_lnum;
-+ __le32 lpt_offs;
-+ __le32 nhead_lnum;
-+ __le32 nhead_offs;
-+ __le32 ltab_lnum;
-+ __le32 ltab_offs;
-+ __le32 lsave_lnum;
-+ __le32 lsave_offs;
-+ __le32 lscan_lnum;
-+ __le32 empty_lebs;
-+ __le32 idx_lebs;
-+ __le32 leb_cnt;
-+ __u8 padding[344];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_ref_node - logical eraseblock reference node.
-+ * @ch: common header
-+ * @lnum: the referred logical eraseblock number
-+ * @offs: start offset in the referred LEB
-+ * @jhead: journal head number
-+ * @padding: reserved for future, zeroes
-+ */
-+struct ubifs_ref_node {
-+ struct ubifs_ch ch;
-+ __le32 lnum;
-+ __le32 offs;
-+ __le32 jhead;
-+ __u8 padding[28];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_branch - key/reference/length branch
-+ * @lnum: LEB number of the target node
-+ * @offs: offset within @lnum
-+ * @len: target node length
-+ * @key: key
-+ */
-+struct ubifs_branch {
-+ __le32 lnum;
-+ __le32 offs;
-+ __le32 len;
-+ __u8 key[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_idx_node - indexing node.
-+ * @ch: common header
-+ * @child_cnt: number of child index nodes
-+ * @level: tree level
-+ * @branches: LEB number / offset / length / key branches
-+ */
-+struct ubifs_idx_node {
-+ struct ubifs_ch ch;
-+ __le16 child_cnt;
-+ __le16 level;
-+ __u8 branches[];
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_cs_node - commit start node.
-+ * @ch: common header
-+ * @cmt_no: commit number
-+ */
-+struct ubifs_cs_node {
-+ struct ubifs_ch ch;
-+ __le64 cmt_no;
-+} __attribute__ ((packed));
-+
-+/**
-+ * struct ubifs_orph_node - orphan node.
-+ * @ch: common header
-+ * @cmt_no: commit number (also top bit is set on the last node of the commit)
-+ * @inos: inode numbers of orphans
-+ */
-+struct ubifs_orph_node {
-+ struct ubifs_ch ch;
-+ __le64 cmt_no;
-+ __le64 inos[];
-+} __attribute__ ((packed));
-+
-+#endif /* __UBIFS_MEDIA_H__ */
---- linux-2.6.24.7.old/fs/ubifs/ubifs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/ubifs.h 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,1589 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/* Implementation version 0.6 */
-+
-+#ifndef __UBIFS_H__
-+#define __UBIFS_H__
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include "ubifs-media.h"
-+#include "compat.h"
-+
-+/* Version of this UBIFS implementation */
-+#define UBIFS_VERSION 1
-+
-+/* Normal UBIFS messages */
-+#define ubifs_msg(fmt, ...) \
-+ printk(KERN_NOTICE "UBIFS: " fmt "\n", ##__VA_ARGS__)
-+/* UBIFS error messages */
-+#define ubifs_err(fmt, ...) \
-+ printk(KERN_ERR "UBIFS error (pid %d): %s: " fmt "\n", current->pid, \
-+ __func__, ##__VA_ARGS__)
-+/* UBIFS warning messages */
-+#define ubifs_warn(fmt, ...) \
-+ printk(KERN_WARNING "UBIFS warning (pid %d): %s: " fmt "\n", \
-+ current->pid, __func__, ##__VA_ARGS__)
-+
-+/* UBIFS file system VFS magic number */
-+#define UBIFS_SUPER_MAGIC 0x24051905
-+
-+/* Number of UBIFS blocks per VFS page */
-+#define UBIFS_BLOCKS_PER_PAGE (PAGE_CACHE_SIZE / UBIFS_BLOCK_SIZE)
-+#define UBIFS_BLOCKS_PER_PAGE_SHIFT (PAGE_CACHE_SHIFT - UBIFS_BLOCK_SHIFT)
-+
-+/* "File system end of life" sequence number watermark */
-+#define SQNUM_WARN_WATERMARK 0xFFFFFFFF00000000ULL
-+#define SQNUM_WATERMARK 0xFFFFFFFFFF000000ULL
-+
-+/* Minimum amount of data UBIFS writes to the flash */
-+#define MIN_WRITE_SZ (UBIFS_DATA_NODE_SZ + 8)
-+
-+/*
-+ * Currently we do not support inode number overlapping and re-using, so this
-+ * watermark defines dangerous inode number level. This should be fixed later,
-+ * although it is difficult to exceed current limit. Another option is to use
-+ * 64-bit inode numbers, but this means more overhead.
-+ */
-+#define INUM_WARN_WATERMARK 0xFFF00000
-+#define INUM_WATERMARK 0xFFFFFF00
-+
-+/* Largest key size supported in this implementation */
-+#define CUR_MAX_KEY_LEN UBIFS_SK_LEN
-+
-+/* Maximum number of entries in each LPT (LEB category) heap */
-+#define LPT_HEAP_SZ 256
-+
-+/*
-+ * Background thread name pattern. The numbers are UBI device and volume
-+ * numbers.
-+ */
-+#define BGT_NAME_PATTERN "ubifs_bgt%d_%d"
-+
-+/* Default write-buffer synchronization timeout (5 secs) */
-+#define DEFAULT_WBUF_TIMEOUT (5 * HZ)
-+
-+/* Maximum possible inode number (only 32-bit inodes are supported now) */
-+#define MAX_INUM 0xFFFFFFFF
-+
-+/* Number of non-data journal heads */
-+#define NONDATA_JHEADS_CNT 2
-+
-+/* Garbage collector head */
-+#define GCHD 0
-+/* Base journal head number */
-+#define BASEHD 1
-+/* First "general purpose" journal head */
-+#define DATAHD 2
-+
-+/*
-+ * How much a directory entry/extended attribute entry adds to the parent/host
-+ * inode.
-+ */
-+#define CALC_DENT_SIZE(name_len) ALIGN(UBIFS_DENT_NODE_SZ + (name_len) + 1, 8)
-+
-+/*
-+ * Znodes which were not touched for 'OLD_ZNODE_AGE' seconds are considered
-+ * "old", and znode which were touched last 'YOUNG_ZNODE_AGE' seconds ago are
-+ * considered "young". This is used by shrinker when selecting znode to trim
-+ * off.
-+ */
-+#define OLD_ZNODE_AGE 20
-+#define YOUNG_ZNODE_AGE 5
-+
-+/*
-+ * Some compressors, like LZO, may end up with more data then the input buffer.
-+ * So UBIFS always allocates larger output buffer, to be sure the compressor
-+ * will not corrupt memory in case of worst case compression.
-+ */
-+#define WORST_COMPR_FACTOR 2
-+
-+/* Maximum expected tree height for use by bottom_up_buf */
-+#define BOTTOM_UP_HEIGHT 64
-+
-+/*
-+ * Znode flags (actually, bit numbers which store the flags).
-+ *
-+ * DIRTY_ZNODE: znode is dirty
-+ * COW_ZNODE: znode is being committed and a new instance of this znode has to
-+ * be created before changing this znode
-+ * OBSOLETE_ZNODE: znode is obsolete, which means it was deleted, but it is
-+ * still in the commit list and the ongoing commit operation
-+ * will commit it, and delete this znode after it is done
-+ */
-+enum {
-+ DIRTY_ZNODE = 0,
-+ COW_ZNODE = 1,
-+ OBSOLETE_ZNODE = 2
-+};
-+
-+/*
-+ * Commit states.
-+ *
-+ * COMMIT_RESTING: commit is not wanted
-+ * COMMIT_BACKGROUND: background commit has been requested
-+ * COMMIT_REQUIRED: commit is required
-+ * COMMIT_RUNNING_BACKGROUND: background commit is running
-+ * COMMIT_RUNNING_REQUIRED: commit is running and it is required
-+ * COMMIT_BROKEN: commit failed
-+ */
-+enum {
-+ COMMIT_RESTING = 0,
-+ COMMIT_BACKGROUND,
-+ COMMIT_REQUIRED,
-+ COMMIT_RUNNING_BACKGROUND,
-+ COMMIT_RUNNING_REQUIRED,
-+ COMMIT_BROKEN,
-+};
-+
-+/*
-+ * 'ubifs_scan_a_node()' return values.
-+ *
-+ * SCANNED_GARBAGE: scanned garbage
-+ * SCANNED_EMPTY_SPACE: scanned empty space
-+ * SCANNED_A_NODE: scanned a valid node
-+ * SCANNED_A_CORRUPT_NODE: scanned a corrupted node
-+ * SCANNED_A_BAD_PAD_NODE: scanned a padding node with invalid pad length
-+ *
-+ * Greater than zero means: 'scanned that number of padding bytes'
-+ */
-+enum {
-+ SCANNED_GARBAGE = 0,
-+ SCANNED_EMPTY_SPACE = -1,
-+ SCANNED_A_NODE = -2,
-+ SCANNED_A_CORRUPT_NODE = -3,
-+ SCANNED_A_BAD_PAD_NODE = -4,
-+};
-+
-+/*
-+ * LPT cnode flag bits.
-+ *
-+ * DIRTY_CNODE: cnode is dirty
-+ * COW_CNODE: cnode is being committed and must be copied before writing
-+ * OBSOLETE_CNODE: cnode is being committed and has been copied (or deleted),
-+ * so it can (and must) be freed when the commit is finished
-+ */
-+enum {
-+ DIRTY_CNODE = 0,
-+ COW_CNODE = 1,
-+ OBSOLETE_CNODE = 2,
-+};
-+
-+/*
-+ * Dirty flag bits (lpt_drty_flgs) for LPT special nodes.
-+ *
-+ * LTAB_DIRTY: ltab node is dirty
-+ * LSAVE_DIRTY: lsave node is dirty
-+ */
-+enum {
-+ LTAB_DIRTY = 1,
-+ LSAVE_DIRTY = 2,
-+};
-+
-+/*
-+ * Return codes used by the garbage collector.
-+ * @LEB_FREED: the logical eraseblock was freed and is ready to use
-+ * @LEB_FREED_IDX: indexing LEB was freed and can be used only after the commit
-+ * @LEB_RETAINED: the logical eraseblock was freed and retained for GC purposes
-+ */
-+enum {
-+ LEB_FREED,
-+ LEB_FREED_IDX,
-+ LEB_RETAINED,
-+};
-+
-+/**
-+ * struct ubifs_old_idx - index node obsoleted since last commit start.
-+ * @rb: rb-tree node
-+ * @lnum: LEB number of obsoleted index node
-+ * @offs: offset of obsoleted index node
-+ */
-+struct ubifs_old_idx {
-+ struct rb_node rb;
-+ int lnum;
-+ int offs;
-+};
-+
-+/* The below union makes it easier to deal with keys */
-+union ubifs_key {
-+ uint8_t u8[CUR_MAX_KEY_LEN];
-+ uint32_t u32[CUR_MAX_KEY_LEN/4];
-+ uint64_t u64[CUR_MAX_KEY_LEN/8];
-+ __le32 j32[CUR_MAX_KEY_LEN/4];
-+};
-+
-+/**
-+ * struct ubifs_scan_node - UBIFS scanned node information.
-+ * @list: list of scanned nodes
-+ * @key: key of node scanned (if it has one)
-+ * @sqnum: sequence number
-+ * @type: type of node scanned
-+ * @offs: offset with LEB of node scanned
-+ * @len: length of node scanned
-+ * @node: raw node
-+ */
-+struct ubifs_scan_node {
-+ struct list_head list;
-+ union ubifs_key key;
-+ unsigned long long sqnum;
-+ int type;
-+ int offs;
-+ int len;
-+ void *node;
-+};
-+
-+/**
-+ * struct ubifs_scan_leb - UBIFS scanned LEB information.
-+ * @lnum: logical eraseblock number
-+ * @nodes_cnt: number of nodes scanned
-+ * @nodes: list of struct ubifs_scan_node
-+ * @endpt: end point (and therefore the start of empty space)
-+ * @ecc: read returned -EBADMSG
-+ * @buf: buffer containing entire LEB scanned
-+ */
-+struct ubifs_scan_leb {
-+ int lnum;
-+ int nodes_cnt;
-+ struct list_head nodes;
-+ int endpt;
-+ int ecc;
-+ void *buf;
-+};
-+
-+/**
-+ * struct ubifs_gced_idx_leb - garbage-collected indexing LEB.
-+ * @list: list
-+ * @lnum: LEB number
-+ * @unmap: OK to unmap this LEB
-+ *
-+ * This data structure is used to temporary store garbage-collected indexing
-+ * LEBs - they are not released immediately, but only after the next commit.
-+ * This is needed to guarantee recoverability.
-+ */
-+struct ubifs_gced_idx_leb {
-+ struct list_head list;
-+ int lnum;
-+ int unmap;
-+};
-+
-+/**
-+ * struct ubifs_inode - UBIFS in-memory inode description.
-+ * @vfs_inode: VFS inode description object
-+ * @creat_sqnum: sequence number at time of creation
-+ * @xattr_size: summarized size of all extended attributes in bytes, protected
-+ * by @inode->i_lock
-+ * @xattr_cnt: count of extended attributes this inode has
-+ * @xattr_names: sum of lengths of all extended attribute names belonging to
-+ * this inode
-+ * @dirty: non-zero if the inode is dirty
-+ * @xattr: non-zero if this is an extended attribute inode
-+ * @budgeted: non-zero if the inode has been budgeted (used for debugging)
-+ * @budg_mutex: serializes inode budgeting and write-back
-+ * @flags: inode flags (@UBIFS_COMPR_FL, etc)
-+ * @compr_type: default compression type used for this inode
-+ * @data_len: length of the data attached to the inode
-+ * @data: inode's data
-+ *
-+ * UBIFS has its own inode mutex, besides the VFS 'i_mutex'. The reason for
-+ * this is budgeting - UBIFS has to budget each operation. So, if an operation
-+ * is going to mark an inode dirty, it has to allocate budget for this. It
-+ * cannot just mark it dirty because there is no guarantee there will be enough
-+ * flash space when it is time to write the inode back. This means that UBIFS
-+ * has to have full control over "clean <-> dirty" transitions of inodes (and
-+ * pages actually, but it is easy for pages, because we have
-+ * 'ubifs_prepare_write()' which is called _before_ every page change). But
-+ * unfortunately, VFS marks inodes dirty in many places, and it does not ask
-+ * the file-system if it is allowed to do so (there is a notifier, but it is
-+ * not enough), i.e., there is no mechanism to synchronize with this. So we
-+ * introduce our own dirty flag to UBIFS inodes and our own inode mutex to
-+ * serialize "clean <-> dirty" transitions.
-+ */
-+struct ubifs_inode {
-+ struct inode vfs_inode;
-+ unsigned long long creat_sqnum;
-+ long long xattr_size;
-+ int xattr_cnt;
-+ int xattr_names;
-+ unsigned int dirty:1;
-+ unsigned int xattr:1;
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ unsigned int budgeted:1;
-+#endif
-+ struct mutex budg_mutex;
-+ int flags;
-+ int compr_type;
-+ int data_len;
-+ void *data;
-+};
-+
-+/**
-+ * struct ubifs_unclean_leb - records a LEB recovered under read-only mode.
-+ * @list: list
-+ * @lnum: LEB number of recovered LEB
-+ * @endpt: offset where recovery ended
-+ *
-+ * This structure records a LEB identified during recovery that needs to be
-+ * cleaned but was not because UBIFS was mounted read-only. The information
-+ * is used to clean the LEB when remounting to read-write mode.
-+ */
-+struct ubifs_unclean_leb {
-+ struct list_head list;
-+ int lnum;
-+ int endpt;
-+};
-+
-+/*
-+ * LEB properties flags.
-+ *
-+ * LPROPS_UNCAT: not categorized
-+ * LPROPS_DIRTY: dirty > 0, not index
-+ * LPROPS_DIRTY_IDX: dirty + free > UBIFS_CH_SZ and index
-+ * LPROPS_FREE: free > 0, not empty, not index
-+ * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs
-+ * LPROPS_EMPTY: LEB is empty, not taken
-+ * LPROPS_FREEABLE: free + dirty == leb_size, not index, not taken
-+ * LPROPS_FRDI_IDX: free + dirty == leb_size and index, may be taken
-+ * LPROPS_CAT_MASK: mask for the LEB categories above
-+ * LPROPS_TAKEN: LEB was taken (this flag is not saved on the media)
-+ * LPROPS_INDEX: LEB contains indexing nodes (this flag also exists on flash)
-+ */
-+enum {
-+ LPROPS_UNCAT = 0,
-+ LPROPS_DIRTY = 1,
-+ LPROPS_DIRTY_IDX = 2,
-+ LPROPS_FREE = 3,
-+ LPROPS_HEAP_CNT = 3,
-+ LPROPS_EMPTY = 4,
-+ LPROPS_FREEABLE = 5,
-+ LPROPS_FRDI_IDX = 6,
-+ LPROPS_CAT_MASK = 15,
-+ LPROPS_TAKEN = 16,
-+ LPROPS_INDEX = 32,
-+};
-+
-+/**
-+ * struct ubifs_lprops - logical eraseblock properties.
-+ * @free: amount of free space in bytes
-+ * @dirty: amount of dirty space in bytes
-+ * @flags: LEB properties flags (see above)
-+ * @lnum: LEB number
-+ * @list: list of same-category lprops (for LPROPS_EMPTY and LPROPS_FREEABLE)
-+ * @hpos: heap position in heap of same-category lprops (other categories)
-+ */
-+struct ubifs_lprops {
-+ int free;
-+ int dirty;
-+ int flags;
-+ int lnum;
-+ union {
-+ struct list_head list;
-+ int hpos;
-+ };
-+};
-+
-+/**
-+ * struct ubifs_lpt_lprops - LPT logical eraseblock properties.
-+ * @free: amount of free space in bytes
-+ * @dirty: amount of dirty space in bytes
-+ * @tgc: trivial GC flag (1 => unmap after commit end)
-+ * @cmt: commit flag (1 => reserved for commit)
-+ */
-+struct ubifs_lpt_lprops {
-+ int free;
-+ int dirty;
-+ unsigned tgc : 1;
-+ unsigned cmt : 1;
-+};
-+
-+/**
-+ * struct ubifs_lp_stats - statistics of eraseblocks in the main area.
-+ * @empty_lebs: number of empty LEBs
-+ * @taken_empty_lebs: number of taken LEBs
-+ * @idx_lebs: number of indexing LEBs
-+ * @total_free: total free space in bytes
-+ * @total_dirty: total dirty space in bytes
-+ * @total_used: total used space in bytes (includes only data LEBs)
-+ * @total_dead: total dead space in bytes (includes only data LEBs)
-+ * @total_dark: total dark space in bytes (includes only data LEBs)
-+ *
-+ * N.B. total_dirty and total_used are different to other total_* fields,
-+ * because they account _all_ LEBs, not just data LEBs.
-+ *
-+ * 'taken_empty_lebs' counts the LEBs that are in the transient state of having
-+ * been 'taken' for use but not yet written to. 'taken_empty_lebs' is needed
-+ * to account correctly for gc_lnum, otherwise 'empty_lebs' could be used
-+ * by itself (in which case 'unused_lebs' would be a better name). In the case
-+ * of gc_lnum, it is 'taken' at mount time or whenever a LEB is retained by GC,
-+ * but unlike other empty LEBs that are 'taken', it may not be written straight
-+ * away (i.e. before the next commit start or unmount), so either gc_lnum must
-+ * be specially accounted for, or the current approach followed i.e. count it
-+ * under 'taken_empty_lebs'.
-+ */
-+struct ubifs_lp_stats {
-+ int empty_lebs;
-+ int taken_empty_lebs;
-+ int idx_lebs;
-+ long long total_free;
-+ long long total_dirty;
-+ long long total_used;
-+ long long total_dead;
-+ long long total_dark;
-+};
-+
-+struct ubifs_nnode;
-+
-+/**
-+ * struct ubifs_cnode - LEB Properties Tree common node.
-+ * @parent: parent nnode
-+ * @cnext: next cnode to commit
-+ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
-+ * @iip: index in parent
-+ * @level: level in the tree (zero for pnodes, greater than zero for nnodes)
-+ * @num: node number
-+ */
-+struct ubifs_cnode {
-+ struct ubifs_nnode *parent;
-+ struct ubifs_cnode *cnext;
-+ unsigned long flags;
-+ int iip;
-+ int level;
-+ int num;
-+};
-+
-+/**
-+ * struct ubifs_pnode - LEB Properties Tree leaf node.
-+ * @parent: parent nnode
-+ * @cnext: next cnode to commit
-+ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
-+ * @iip: index in parent
-+ * @level: level in the tree (always zero for pnodes)
-+ * @num: node number
-+ * @lprops: LEB properties array
-+ */
-+struct ubifs_pnode {
-+ struct ubifs_nnode *parent;
-+ struct ubifs_cnode *cnext;
-+ unsigned long flags;
-+ int iip;
-+ int level;
-+ int num;
-+ struct ubifs_lprops lprops[UBIFS_LPT_FANOUT];
-+};
-+
-+/**
-+ * struct ubifs_nbranch - LEB Properties Tree internal node branch.
-+ * @lnum: LEB number of child
-+ * @offs: offset of child
-+ * @nnode: nnode child
-+ * @pnode: pnode child
-+ * @cnode: cnode child
-+ */
-+struct ubifs_nbranch {
-+ int lnum;
-+ int offs;
-+ union {
-+ struct ubifs_nnode *nnode;
-+ struct ubifs_pnode *pnode;
-+ struct ubifs_cnode *cnode;
-+ };
-+};
-+
-+/**
-+ * struct ubifs_nnode - LEB Properties Tree internal node.
-+ * @parent: parent nnode
-+ * @cnext: next cnode to commit
-+ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
-+ * @iip: index in parent
-+ * @level: level in the tree (always greater than zero for nnodes)
-+ * @num: node number
-+ * @nbranch: branches to child nodes
-+ */
-+struct ubifs_nnode {
-+ struct ubifs_nnode *parent;
-+ struct ubifs_cnode *cnext;
-+ unsigned long flags;
-+ int iip;
-+ int level;
-+ int num;
-+ struct ubifs_nbranch nbranch[UBIFS_LPT_FANOUT];
-+};
-+
-+/**
-+ * struct ubifs_lpt_heap - heap of categorized lprops.
-+ * @arr: heap array
-+ * @cnt: number in heap
-+ * @max_cnt: maximum number allowed in heap
-+ *
-+ * There are %LPROPS_HEAP_CNT heaps.
-+ */
-+struct ubifs_lpt_heap {
-+ struct ubifs_lprops **arr;
-+ int cnt;
-+ int max_cnt;
-+};
-+
-+/*
-+ * Return codes for LPT scan callback function.
-+ *
-+ * LPT_SCAN_CONTINUE: continue scanning
-+ * LPT_SCAN_ADD: add the LEB properties scanned to the tree in memory
-+ * LPT_SCAN_STOP: stop scanning
-+ */
-+enum {
-+ LPT_SCAN_CONTINUE = 0,
-+ LPT_SCAN_ADD = 1,
-+ LPT_SCAN_STOP = 2,
-+};
-+
-+struct ubifs_info;
-+
-+/* Callback used by the 'ubifs_lpt_scan_nolock()' function */
-+typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c,
-+ const struct ubifs_lprops *lprops,
-+ int in_tree, void *data);
-+
-+/**
-+ * struct ubifs_wbuf - UBIFS write-buffer.
-+ * @c: UBIFS file-system description object
-+ * @buf: write-buffer (of min. flash I/O unit size)
-+ * @lnum: logical eraseblock number the write-buffer points to
-+ * @offs: write-buffer offset in this logical eraseblock
-+ * @avail: number of bytes available in the write-buffer
-+ * @used: number of used bytes in the write-buffer
-+ * @dtype: type of data stored in this LEB (%UBI_LONGTERM, %UBI_SHORTTERM,
-+ * %UBI_UNKNOWN)
-+ * @jhead: journal head the mutex belongs to (note, needed only to shut lockdep
-+ * up by 'mutex_lock_nested()).
-+ * @sync_callback: write-buffer synchronization callback
-+ * @io_mutex: serializes write-buffer I/O
-+ * @lock: serializes @buf, @lnum, @offs, @avail, @used, @next_ino and @inodes
-+ * fields
-+ * @timer: write-buffer timer
-+ * @timeout: timer expire interval in jiffies
-+ * @need_sync: it is set if its timer expired and needs sync
-+ * @next_ino: points to the next position of the following inode number
-+ * @inodes: stores the inode numbers of the nodes which are in wbuf
-+ *
-+ * The write-buffer synchronization callback is called when the write-buffer is
-+ * synchronized in order to notify how much space was wasted due to
-+ * write-buffer padding and how much free space is left in the LEB.
-+ *
-+ * Note: the fields @buf, @lnum, @offs, @avail and @used can be read under
-+ * spin-lock or mutex because they are written under both mutex and spin-lock.
-+ * @buf is appended to under mutex but overwritten under both mutex and
-+ * spin-lock. Thus the data between @buf and @buf + @used can be read under
-+ * spinlock.
-+ */
-+struct ubifs_wbuf {
-+ struct ubifs_info *c;
-+ void *buf;
-+ int lnum;
-+ int offs;
-+ int avail;
-+ int used;
-+ int dtype;
-+ int jhead;
-+ int (*sync_callback)(struct ubifs_info *c, int lnum, int free, int pad);
-+ struct mutex io_mutex;
-+ spinlock_t lock;
-+ struct timer_list timer;
-+ int timeout;
-+ int need_sync;
-+ int next_ino;
-+ ino_t *inodes;
-+};
-+
-+/**
-+ * struct ubifs_bud - bud logical eraseblock.
-+ * @lnum: logical eraseblock number
-+ * @start: where the (uncommitted) bud data starts
-+ * @jhead: journal head number this bud belongs to
-+ * @list: link in the list buds belonging to the same journal head
-+ * @rb: link in the tree of all buds
-+ */
-+struct ubifs_bud {
-+ int lnum;
-+ int start;
-+ int jhead;
-+ struct list_head list;
-+ struct rb_node rb;
-+};
-+
-+/**
-+ * struct ubifs_jhead - journal head.
-+ * @wbuf: head's write-buffer
-+ * @buds_list: list of bud LEBs belonging to this journal head
-+ *
-+ * Note, the @buds list is protected by the @c->buds_lock.
-+ */
-+struct ubifs_jhead {
-+ struct ubifs_wbuf wbuf;
-+ struct list_head buds_list;
-+};
-+
-+/**
-+ * struct ubifs_zbranch - key/coordinate/length branch stored in znodes.
-+ * @key: key
-+ * @znode: znode address in memory
-+ * @lnum: LEB number of the indexing node
-+ * @offs: offset of the indexing node within @lnum
-+ * @len: target node length
-+ */
-+struct ubifs_zbranch {
-+ union ubifs_key key;
-+ union {
-+ struct ubifs_znode *znode;
-+ void *leaf;
-+ };
-+ int lnum;
-+ int offs;
-+ int len;
-+};
-+
-+/**
-+ * struct ubifs_znode - in-memory representation of an indexing node.
-+ * @parent: parent znode or NULL if it is the root
-+ * @cnext: next znode to commit
-+ * @flags: znode flags (%DIRTY_ZNODE, %COW_ZNODE or %OBSOLETE_ZNODE)
-+ * @time: last access time (seconds)
-+ * @level: level of the entry in the TNC tree
-+ * @child_cnt: count of child znodes
-+ * @iip: index in parent's zbranch array
-+ * @alt: lower bound of key range has altered i.e. child inserted at slot 0
-+ * @lnum: LEB number of the corresponding indexing node
-+ * @offs: offset of the corresponding indexing node
-+ * @len: length of the corresponding indexing node
-+ * @zbranch: array of znode branches (@c->fanout elements)
-+ */
-+struct ubifs_znode {
-+ struct ubifs_znode *parent;
-+ struct ubifs_znode *cnext;
-+ unsigned long flags;
-+ unsigned long time;
-+ int level;
-+ int child_cnt;
-+ int iip;
-+ int alt;
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ int lnum, offs, len;
-+#endif
-+ struct ubifs_zbranch zbranch[];
-+};
-+
-+/**
-+ * struct ubifs_node_range - node length range description data structure.
-+ * @len: fixed node length
-+ * @min_len: minimum possible node length
-+ * @max_len: maximum possible node length
-+ *
-+ * If @max_len is %0, the node has fixed length @len.
-+ */
-+struct ubifs_node_range {
-+ union {
-+ int len;
-+ int min_len;
-+ };
-+ int max_len;
-+};
-+
-+/**
-+ * struct ubifs_compressor - UBIFS compressor description structure.
-+ * @compr_type: compressor type (%UBIFS_COMPR_LZO, etc)
-+ * @cc: cryptoapi compressor handle
-+ * @comp_mutex: mutex used during compression
-+ * @decomp_mutex: mutex used during decompression
-+ * @name: compressor name
-+ * @capi_name: cryptoapi compressor name
-+ */
-+struct ubifs_compressor {
-+ int compr_type;
-+ struct crypto_comp *cc;
-+ struct mutex *comp_mutex;
-+ struct mutex *decomp_mutex;
-+ const char *name;
-+ const char *capi_name;
-+};
-+
-+/**
-+ * struct ubifs_budget_req - budget requirements of an operation.
-+ *
-+ * @new_ino: non-zero if the operation adds a new inode
-+ * @dirtied_ino: how many inodes the operation makes dirty
-+ * @new_page: non-zero if the operation adds a new page
-+ * @dirtied_page: non-zero if the operation makes a page dirty
-+ * @new_dent: non-zero if the operation adds a new directory entry
-+ * @mod_dent: non-zero if the operation removes or modifies an existing
-+ * directory entry
-+ * @new_ino_d: now much data newly created inode contains
-+ * @dirtied_ino_d: now much data dirtied inode contains
-+ * @idx_growth: how much the index will supposedly grow
-+ * @data_growth: how much new data the operation will supposedly add
-+ * @dd_growth: how much data that makes other data dirty the operation will
-+ * supposedly add
-+ *
-+ * @idx_growth, @data_growth and @dd_growth are not used in budget request. The
-+ * budgeting subsystem caches index and data growth values there to avoid
-+ * re-calculating them when the budget is released. However, if @idx_growth is
-+ * %-1, it is calculated by the release function using other fields.
-+ *
-+ * An inode may contain 4KiB of data at max., thus the widths of @new_ino_d
-+ * is 13 bits, and @dirtied_ino_d - 15, because up to 4 inodes may be made
-+ * dirty by the re-name operation.
-+ */
-+struct ubifs_budget_req {
-+ unsigned int new_ino:1;
-+ unsigned int dirtied_ino:4;
-+ unsigned int new_page:1;
-+ unsigned int dirtied_page:1;
-+ unsigned int new_dent:1;
-+ unsigned int mod_dent:1;
-+/* TODO: remove compatibility stuff as late as possible */
-+#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE
-+ unsigned int locked_pg:1;
-+#endif
-+ unsigned int new_ino_d:13;
-+ unsigned int dirtied_ino_d:15;
-+ int idx_growth;
-+ int data_growth;
-+ int dd_growth;
-+};
-+
-+/**
-+ * struct ubifs_orphan - stores the inode number of an orphan.
-+ * @rb: rb-tree node of rb-tree of orphans sorted by inode number
-+ * @list: list head of list of orphans in order added
-+ * @new_list: list head of list of orphans added since the last commit
-+ * @cnext: next orphan to commit
-+ * @dnext: next orphan to delete
-+ * @inum: inode number
-+ * @new: %1 => added since the last commit, otherwise %0
-+ */
-+struct ubifs_orphan {
-+ struct rb_node rb;
-+ struct list_head list;
-+ struct list_head new_list;
-+ struct ubifs_orphan *cnext;
-+ struct ubifs_orphan *dnext;
-+ ino_t inum;
-+ int new;
-+};
-+
-+/**
-+ * struct ubifs_mount_opts - UBIFS-specific mount options information.
-+ * @unmount_mode: selected unmount mode (%0 default, %1 normal, %2 fast)
-+ */
-+struct ubifs_mount_opts {
-+ unsigned int unmount_mode:2;
-+};
-+
-+/**
-+ * struct ubifs_info - UBIFS file-system description data structure
-+ * (per-superblock).
-+ * @vfs_sb: VFS @struct super_block object
-+ *
-+ * @highest_inum: highest used inode number
-+ * @vfs_gen: VFS inode generation counter
-+ * @max_sqnum: current global sequence number
-+ * @cmt_no: commit number (last successfully completed commit)
-+ * @cnt_lock: protects @highest_inum, @vfs_gen, and @max_sqnum counters
-+ * @fmt_version: UBIFS on-flash format version
-+ *
-+ * @lhead_lnum: log head logical eraseblock number
-+ * @lhead_offs: log head offset
-+ * @ltail_lnum: log tail logical eraseblock number (offset is always 0)
-+ * @log_mutex: protects the log, @lhead_lnum, @lhead_offs, @ltail_lnum, and
-+ * @bud_bytes
-+ * @min_log_bytes: minimum required number of bytes in the log
-+ * @cmt_bud_bytes: used during commit to temporarily amount of bytes in
-+ * committed buds
-+ *
-+ * @buds: tree of all buds indexed by bud LEB number
-+ * @bud_bytes: how many bytes of flash is used by buds
-+ * @buds_lock: protects the @buds tree, @bud_bytes, and per-journal head bud
-+ * lists
-+ * @jhead_cnt: count of journal heads
-+ * @jheads: journal heads (head zero is base head)
-+ * @max_bud_bytes: maximum number of bytes allowed in buds
-+ * @bg_bud_bytes: number of bud bytes when background commit is initiated
-+ * @old_buds: buds to be released after commit ends
-+ * @max_bud_cnt: maximum number of buds
-+ *
-+ * @commit_sem: synchronizes committer with other processes
-+ * @cmt_state: commit state
-+ * @cs_lock: commit state lock
-+ * @cmt_wq: wait queue to sleep on if the log is full and a commit is running
-+ * @fast_unmount: do not run journal commit before unmounting
-+ * @big_lpt: flag that LPT is too big to write whole during commit
-+ *
-+ * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and
-+ * @calc_idx_sz
-+ * @zroot: zbranch which points to the root index node and znode
-+ * @cnext: next znode to commit
-+ * @enext: next znode to commit to empty space
-+ * @gap_lebs: array of LEBs used by the in-gaps commit method
-+ * @cbuf: commit buffer
-+ * @ileb_buf: buffer for commit in-the-gaps method
-+ * @ileb_len: length of data in ileb_buf
-+ * @ihead_lnum: LEB number of index head
-+ * @ihead_offs: offset of index head
-+ * @ilebs: pre-allocated index LEBs
-+ * @ileb_cnt: number of pre-allocated index LEBs
-+ * @ileb_nxt: next pre-allocated index LEBs
-+ * @old_idx: tree of index nodes obsoleted since the last commit start
-+ * @bottom_up_buf: a buffer which is used by 'dirty_cow_bottom_up()' in tnc.c
-+ * @new_ihead_lnum: used by debugging to check ihead_lnum
-+ * @new_ihead_offs: used by debugging to check ihead_offs
-+ *
-+ * @mst_node: master node
-+ * @mst_offs: offset of valid master node
-+ * @mst_mutex: protects the master node area, @mst_node, and @mst_offs
-+ *
-+ * @log_lebs: number of logical eraseblocks in the log
-+ * @log_bytes: log size in bytes
-+ * @log_last: last LEB of the log
-+ * @lpt_lebs: number of LEBs used for lprops table
-+ * @lpt_first: first LEB of the lprops table area
-+ * @lpt_last: last LEB of the lprops table area
-+ * @orph_lebs: number of LEBs used for the orphan area
-+ * @orph_first: first LEB of the orphan area
-+ * @orph_last: last LEB of the orphan area
-+ * @main_lebs: count of LEBs in the main area
-+ * @main_first: first LEB of the main area
-+ * @main_bytes: main area size in bytes
-+ * @default_compr: default compression type
-+ *
-+ * @key_hash_type: type of the key hash
-+ * @key_hash: direntry key hash function
-+ * @key_fmt: key format
-+ * @key_len: key length
-+ * @fanout: fanout of the index tree (number of links per indexing node)
-+ *
-+ * @min_io_size: minimal input/output unit size
-+ * @min_io_shift: number of bits in @min_io_size minus one
-+ * @leb_size: logical eraseblock size in bytes
-+ * @half_leb_size: half LEB size
-+ * @leb_cnt: count of logical eraseblocks
-+ * @max_leb_cnt: maximum count of logical eraseblocks
-+ * @old_leb_cnt: count of logical eraseblocks before resize
-+ * @ro_media: the underlying UBI volume is read-only
-+ *
-+ * @dirty_pg_cnt: number of dirty pages (not used)
-+ * @dirty_ino_cnt: number of dirty inodes (not used)
-+ * @dirty_zn_cnt: number of dirty znodes
-+ * @clean_zn_cnt: number of clean znodes
-+ *
-+ * @budg_idx_growth: amount of bytes budgeted for index growth
-+ * @budg_data_growth: amount of bytes budgeted for cached data
-+ * @budg_dd_growth: amount of bytes budgeted for cached data that will make
-+ * other data dirty
-+ * @budg_uncommitted_idx: amount of bytes were budgeted for growth of the index,
-+ * but which still have to be taken into account because
-+ * the index has not been committed so far
-+ * @space_lock: protects @budg_idx_growth, @budg_data_growth, @budg_dd_growth,
-+ * @budg_uncommited_idx, @min_idx_lebs, @old_idx_sz, and @lst;
-+ * @min_idx_lebs: minimum number of LEBs required for the index
-+ * @old_idx_sz: size of index on flash
-+ * @calc_idx_sz: temporary variable which is used to calculate new index size
-+ * (contains accurate new index size at end of TNC commit start)
-+ * @lst: lprops statistics
-+ *
-+ * @page_budget: budget for a page
-+ * @inode_budget: budget for an inode
-+ * @dent_budget: budget for a directory entry
-+ *
-+ * @ref_node_alsz: size of the LEB reference node aligned to the min. flash
-+ * I/O unit
-+ * @mst_node_alsz: master node aligned size
-+ * @min_idx_node_sz: minimum indexing node aligned on 8-bytes boundary
-+ * @max_idx_node_sz: maximum indexing node aligned on 8-bytes boundary
-+ * @max_inode_sz: maximum possible inode size in bytes
-+ * @max_znode_sz: size of znode in bytes
-+ * @dead_wm: LEB dead space watermark
-+ * @dark_wm: LEB dark space watermark
-+ * @block_cnt: count of 4KiB blocks on the FS
-+ *
-+ * @ranges: UBIFS node length ranges
-+ * @ubi: UBI volume descriptor
-+ * @di: UBI device information
-+ * @vi: UBI volume information
-+ *
-+ * @orph_tree: rb-tree of orphan inode numbers
-+ * @orph_list: list of orphan inode numbers in order added
-+ * @orph_new: list of orphan inode numbers added since last commit
-+ * @orph_cnext: next orphan to commit
-+ * @orph_dnext: next orphan to delete
-+ * @orphan_lock: lock for orph_tree and orph_new
-+ * @orph_buf: buffer for orphan nodes
-+ * @new_orphans: number of orphans since last commit
-+ * @cmt_orphans: number of orphans being committed
-+ * @tot_orphans: number of orphans in the rb_tree
-+ * @max_orphans: maximum number of orphans allowed
-+ * @ohead_lnum: orphan head LEB number
-+ * @ohead_offs: orphan head offset
-+ * @no_orphs: non-zero if there are no orphans
-+ *
-+ * @bgt: UBIFS background thread
-+ * @bgt_name: background thread name
-+ * @need_bgt: if background thread should run
-+ * @need_wbuf_sync: if write-buffers have to be synchronized
-+ *
-+ * @gc_lnum: LEB number used for garbage collection
-+ * @sbuf: a buffer of LEB size used by GC and replay for scanning
-+ * @idx_gc: list of index LEBs that have been garbage collected
-+ * @idx_gc_cnt: number of elements on the idx_gc list
-+ *
-+ * @infos_list: links all 'ubifs_info' objects
-+ * @umount_mutex: serializes shrinker and un-mount
-+ * @shrinker_run_no: shrinker run number
-+ *
-+ * @space_bits: number of bits needed to record free or dirty space
-+ * @lpt_lnum_bits: number of bits needed to record a LEB number in the LPT
-+ * @lpt_offs_bits: number of bits needed to record an offset in the LPT
-+ * @lpt_spc_bits: number of bits needed to space in the LPT
-+ * @pcnt_bits: number of bits needed to record pnode or nnode number
-+ * @lnum_bits: number of bits needed to record LEB number
-+ * @nnode_sz: size of on-flash nnode
-+ * @pnode_sz: size of on-flash pnode
-+ * @ltab_sz: size of on-flash LPT lprops table
-+ * @lsave_sz: size of on-flash LPT save table
-+ * @pnode_cnt: number of pnodes
-+ * @nnode_cnt: number of nnodes
-+ * @lpt_hght: height of the LPT
-+ * @pnodes_have: number of pnodes in memory
-+ *
-+ * @lp_mutex: protects lprops table and all the other lprops-related fields
-+ * @lpt_lnum: LEB number of the root nnode of the LPT
-+ * @lpt_offs: offset of the root nnode of the LPT
-+ * @nhead_lnum: LEB number of LPT head
-+ * @nhead_offs: offset of LPT head
-+ * @lpt_drty_flgs: dirty flags for LPT special nodes e.g. ltab
-+ * @dirty_nn_cnt: number of dirty nnodes
-+ * @dirty_pn_cnt: number of dirty pnodes
-+ * @lpt_sz: LPT size
-+ * @lpt_nod_buf: buffer for an on-flash nnode or pnode
-+ * @lpt_buf: buffer of LEB size used by LPT
-+ * @nroot: address in memory of the root nnode of the LPT
-+ * @lpt_cnext: next LPT node to commit
-+ * @lpt_heap: array of heaps of categorized lprops
-+ * @dirty_idx: a (reverse sorted) copy of the LPROPS_DIRTY_IDX heap as at
-+ * previous commit start
-+ * @uncat_list: list of un-categorized LEBs
-+ * @empty_list: list of empty LEBs
-+ * @freeable_list: list of freeable non-index LEBs (free + dirty == leb_size)
-+ * @frdi_idx_list: list of freeable index LEBs (free + dirty == leb_size)
-+ * @freeable_cnt: number of freeable LEBs in @freeable_list
-+ *
-+ * @ltab_lnum: LEB number of LPT's own lprops table
-+ * @ltab_offs: offset of LPT's own lprops table
-+ * @ltab: LPT's own lprops table
-+ * @ltab_cmt: LPT's own lprops table (commit copy)
-+ * @lsave_cnt: number of LEB numbers in LPT's save table
-+ * @lsave_lnum: LEB number of LPT's save table
-+ * @lsave_offs: offset of LPT's save table
-+ * @lsave: LPT's save table
-+ * @lscan_lnum: LEB number of last LPT scan
-+ *
-+ * @rp_size: size of the reserved pool in bytes
-+ * @report_rp_size: size of the reserved pool reported to userspace
-+ * @rp_uid: reserved pool user ID
-+ * @rp_gid: reserved pool group ID
-+ *
-+ * @empty: if the UBI device is empty
-+ * @replay_tree: temporary tree used during journal replay
-+ * @replay_list: temporary list used during journal replay
-+ * @replay_buds: list of buds to replay
-+ * @cs_sqnum: sequence number of first node in the log (commit start node)
-+ * @replay_sqnum: sequence number of node currently being replayed
-+ * @need_recovery: file-system needs recovery
-+ * @replaying: set to %1 during journal replay
-+ * @unclean_leb_list: LEBs to recover when mounting ro to rw
-+ * @rcvrd_mst_node: recovered master node to write when mounting ro to rw
-+ * @size_tree: inode size information for recovery
-+ * @recovery_needs_commit: a commit must be done before unmounting
-+ * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY)
-+ * @mount_opts: UBIFS-specific mount options
-+ *
-+ * @dbg_buf: a buffer of LEB size used for debugging purposes
-+ * @old_zroot: old index root - used by 'dbg_check_old_index()'
-+ * @old_zroot_level: old index root level - used by 'dbg_check_old_index()'
-+ * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()'
-+ * @failure_mode: failure mode for recovery testing
-+ * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
-+ * @fail_timeout: time in jiffies when delay of failure mode expires
-+ * @fail_cnt: current number of calls to failure mode I/O functions
-+ * @fail_cnt_max: number of calls by which to delay failure mode
-+ */
-+struct ubifs_info {
-+ struct super_block *vfs_sb;
-+
-+ ino_t highest_inum;
-+ unsigned int vfs_gen;
-+ unsigned long long max_sqnum;
-+ unsigned long long cmt_no;
-+ spinlock_t cnt_lock;
-+ int fmt_version;
-+
-+ int lhead_lnum;
-+ int lhead_offs;
-+ int ltail_lnum;
-+ struct mutex log_mutex;
-+ int min_log_bytes;
-+ long long cmt_bud_bytes;
-+
-+ struct rb_root buds;
-+ long long bud_bytes;
-+ spinlock_t buds_lock;
-+ int jhead_cnt;
-+ struct ubifs_jhead *jheads;
-+ long long max_bud_bytes;
-+ long long bg_bud_bytes;
-+ struct list_head old_buds;
-+ int max_bud_cnt;
-+
-+ struct rw_semaphore commit_sem;
-+ int cmt_state;
-+ spinlock_t cs_lock;
-+ wait_queue_head_t cmt_wq;
-+ unsigned int fast_unmount:1;
-+ unsigned int big_lpt:1;
-+
-+ struct mutex tnc_mutex;
-+ struct ubifs_zbranch zroot;
-+ struct ubifs_znode *cnext;
-+ struct ubifs_znode *enext;
-+ int *gap_lebs;
-+ void *cbuf;
-+ void *ileb_buf;
-+ int ileb_len;
-+ int ihead_lnum;
-+ int ihead_offs;
-+ int *ilebs;
-+ int ileb_cnt;
-+ int ileb_nxt;
-+ struct rb_root old_idx;
-+ int *bottom_up_buf;
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ int new_ihead_lnum;
-+ int new_ihead_offs;
-+#endif
-+
-+ struct ubifs_mst_node *mst_node;
-+ int mst_offs;
-+ struct mutex mst_mutex;
-+
-+ int log_lebs;
-+ long long log_bytes;
-+ int log_last;
-+ int lpt_lebs;
-+ int lpt_first;
-+ int lpt_last;
-+ int orph_lebs;
-+ int orph_first;
-+ int orph_last;
-+ int main_lebs;
-+ int main_first;
-+ long long main_bytes;
-+ int default_compr;
-+
-+ uint8_t key_hash_type;
-+ uint32_t (*key_hash)(const char *str, int len);
-+ int key_fmt;
-+ int key_len;
-+ int fanout;
-+
-+ int min_io_size;
-+ int min_io_shift;
-+ int leb_size;
-+ int half_leb_size;
-+ int leb_cnt;
-+ int max_leb_cnt;
-+ int old_leb_cnt;
-+ int ro_media;
-+
-+ atomic_long_t dirty_pg_cnt;
-+ atomic_long_t dirty_ino_cnt;
-+ atomic_long_t dirty_zn_cnt;
-+ atomic_long_t clean_zn_cnt;
-+
-+ long long budg_idx_growth;
-+ long long budg_data_growth;
-+ long long budg_dd_growth;
-+ long long budg_uncommitted_idx;
-+ spinlock_t space_lock;
-+ int min_idx_lebs;
-+ unsigned long long old_idx_sz;
-+ unsigned long long calc_idx_sz;
-+ struct ubifs_lp_stats lst;
-+
-+ int page_budget;
-+ int inode_budget;
-+ int dent_budget;
-+
-+ int ref_node_alsz;
-+ int mst_node_alsz;
-+ int min_idx_node_sz;
-+ int max_idx_node_sz;
-+ long long max_inode_sz;
-+ int max_znode_sz;
-+ int dead_wm;
-+ int dark_wm;
-+ int block_cnt;
-+
-+ struct ubifs_node_range ranges[UBIFS_NODE_TYPES_CNT];
-+ struct ubi_volume_desc *ubi;
-+ struct ubi_device_info di;
-+ struct ubi_volume_info vi;
-+
-+ struct rb_root orph_tree;
-+ struct list_head orph_list;
-+ struct list_head orph_new;
-+ struct ubifs_orphan *orph_cnext;
-+ struct ubifs_orphan *orph_dnext;
-+ spinlock_t orphan_lock;
-+ void *orph_buf;
-+ int new_orphans;
-+ int cmt_orphans;
-+ int tot_orphans;
-+ int max_orphans;
-+ int ohead_lnum;
-+ int ohead_offs;
-+ int no_orphs;
-+
-+ struct task_struct *bgt;
-+ char bgt_name[sizeof(BGT_NAME_PATTERN) + 9];
-+ int need_bgt;
-+ int need_wbuf_sync;
-+
-+ int gc_lnum;
-+ void *sbuf;
-+ struct list_head idx_gc;
-+ int idx_gc_cnt;
-+
-+ struct list_head infos_list;
-+ struct mutex umount_mutex;
-+ unsigned int shrinker_run_no;
-+
-+ int space_bits;
-+ int lpt_lnum_bits;
-+ int lpt_offs_bits;
-+ int lpt_spc_bits;
-+ int pcnt_bits;
-+ int lnum_bits;
-+ int nnode_sz;
-+ int pnode_sz;
-+ int ltab_sz;
-+ int lsave_sz;
-+ int pnode_cnt;
-+ int nnode_cnt;
-+ int lpt_hght;
-+ int pnodes_have;
-+
-+ struct mutex lp_mutex;
-+ int lpt_lnum;
-+ int lpt_offs;
-+ int nhead_lnum;
-+ int nhead_offs;
-+ int lpt_drty_flgs;
-+ int dirty_nn_cnt;
-+ int dirty_pn_cnt;
-+ long long lpt_sz;
-+ void *lpt_nod_buf;
-+ void *lpt_buf;
-+ struct ubifs_nnode *nroot;
-+ struct ubifs_cnode *lpt_cnext;
-+ struct ubifs_lpt_heap lpt_heap[LPROPS_HEAP_CNT];
-+ struct ubifs_lpt_heap dirty_idx;
-+ struct list_head uncat_list;
-+ struct list_head empty_list;
-+ struct list_head freeable_list;
-+ struct list_head frdi_idx_list;
-+ int freeable_cnt;
-+
-+ int ltab_lnum;
-+ int ltab_offs;
-+ struct ubifs_lpt_lprops *ltab;
-+ struct ubifs_lpt_lprops *ltab_cmt;
-+ int lsave_cnt;
-+ int lsave_lnum;
-+ int lsave_offs;
-+ int *lsave;
-+ int lscan_lnum;
-+
-+ long long rp_size;
-+ long long report_rp_size;
-+ uid_t rp_uid;
-+ gid_t rp_gid;
-+
-+ /* The below fields are used only during mounting and re-mounting */
-+ int empty;
-+ struct rb_root replay_tree;
-+ struct list_head replay_list;
-+ struct list_head replay_buds;
-+ unsigned long long cs_sqnum;
-+ unsigned long long replay_sqnum;
-+ int need_recovery;
-+ int replaying;
-+ struct list_head unclean_leb_list;
-+ struct ubifs_mst_node *rcvrd_mst_node;
-+ struct rb_root size_tree;
-+ int recovery_needs_commit;
-+ int remounting_rw;
-+ struct ubifs_mount_opts mount_opts;
-+
-+#ifdef CONFIG_UBIFS_FS_DEBUG
-+ void *dbg_buf;
-+ struct ubifs_zbranch old_zroot;
-+ int old_zroot_level;
-+ unsigned long long old_zroot_sqnum;
-+ int failure_mode;
-+ int fail_delay;
-+ unsigned long fail_timeout;
-+ unsigned int fail_cnt;
-+ unsigned int fail_cnt_max;
-+#endif
-+};
-+
-+extern struct list_head ubifs_infos;
-+extern spinlock_t ubifs_infos_lock;
-+extern atomic_long_t ubifs_clean_zn_cnt;
-+extern struct kmem_cache *ubifs_inode_slab;
-+extern struct super_operations ubifs_super_operations;
-+extern struct address_space_operations ubifs_file_address_operations;
-+extern struct file_operations ubifs_file_operations;
-+extern struct inode_operations ubifs_file_inode_operations;
-+extern struct file_operations ubifs_dir_operations;
-+extern struct inode_operations ubifs_dir_inode_operations;
-+extern struct inode_operations ubifs_symlink_inode_operations;
-+extern struct backing_dev_info ubifs_backing_dev_info;
-+extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
-+
-+/* io.c */
-+int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
-+int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
-+ int dtype);
-+int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf);
-+int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
-+ int lnum, int offs);
-+int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
-+ int lnum, int offs);
-+int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
-+ int offs, int dtype);
-+int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
-+ int offs, int quiet);
-+void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
-+void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last);
-+int ubifs_io_init(struct ubifs_info *c);
-+void ubifs_pad(const struct ubifs_info *c, void *buf, int pad);
-+int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf);
-+int ubifs_bg_wbufs_sync(struct ubifs_info *c);
-+void ubifs_wbuf_add_ino_nolock(struct ubifs_wbuf *wbuf, ino_t inum);
-+int ubifs_sync_wbufs_by_inodes(struct ubifs_info *c,
-+ struct inode * const *inodes, int count);
-+
-+/* scan.c */
-+struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
-+ int offs, void *sbuf);
-+void ubifs_scan_destroy(struct ubifs_scan_leb *sleb);
-+int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
-+ int offs, int quiet);
-+struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
-+ int offs, void *sbuf);
-+void ubifs_end_scan(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
-+ int lnum, int offs);
-+int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
-+ void *buf, int offs);
-+void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
-+ void *buf);
-+
-+/* log.c */
-+void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud);
-+void ubifs_create_buds_lists(struct ubifs_info *c);
-+int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs);
-+struct ubifs_bud *ubifs_search_bud(struct ubifs_info *c, int lnum);
-+struct ubifs_wbuf *ubifs_get_wbuf(struct ubifs_info *c, int lnum);
-+int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum);
-+int ubifs_log_end_commit(struct ubifs_info *c, int new_ltail_lnum);
-+int ubifs_log_post_commit(struct ubifs_info *c, int old_ltail_lnum);
-+int ubifs_consolidate_log(struct ubifs_info *c);
-+
-+/* journal.c */
-+int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
-+ const struct qstr *nm, const struct inode *inode,
-+ int deletion, int sync, int xent);
-+int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
-+ const union ubifs_key *key, const void *buf, int len);
-+int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode,
-+ int last_reference, int sync);
-+int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
-+ const struct dentry *old_dentry,
-+ const struct inode *new_dir,
-+ const struct dentry *new_dentry, int sync);
-+int ubifs_jnl_truncate(struct ubifs_info *c, ino_t inum,
-+ loff_t old_size, loff_t new_size);
-+int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
-+ const struct inode *inode, const struct qstr *nm,
-+ int sync);
-+int ubifs_jnl_write_2_inodes(struct ubifs_info *c, const struct inode *inode1,
-+ const struct inode *inode2, int sync);
-+
-+/* budget.c */
-+int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req);
-+void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req);
-+int ubifs_budget_inode_op(struct ubifs_info *c, struct inode *inode,
-+ struct ubifs_budget_req *req);
-+void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode,
-+ struct ubifs_budget_req *req);
-+void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
-+ struct ubifs_budget_req *req);
-+int ubifs_budget_ino_cleaning(struct ubifs_info *c, struct inode *inode,
-+ struct ubifs_budget_req *req);
-+void ubifs_release_ino_clean(struct ubifs_info *c, struct inode *inode,
-+ struct ubifs_budget_req *req);
-+long long ubifs_budg_get_free_space(struct ubifs_info *c);
-+int ubifs_calc_min_idx_lebs(struct ubifs_info *c);
-+void ubifs_convert_page_budget(struct ubifs_info *c);
-+void ubifs_release_new_page_budget(struct ubifs_info *c);
-+long long ubifs_calc_available(const struct ubifs_info *c);
-+
-+/* find.c */
-+int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free,
-+ int squeeze);
-+int ubifs_find_free_leb_for_idx(struct ubifs_info *c);
-+int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
-+ int min_space, int pick_free);
-+int ubifs_find_dirty_idx_leb(struct ubifs_info *c);
-+int ubifs_save_dirty_idx_lnums(struct ubifs_info *c);
-+
-+/* tnc.c */
-+int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key,
-+ void *node);
-+int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
-+ void *node, int *lnum, int *offs);
-+int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
-+ void *node, const struct qstr *nm);
-+int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum,
-+ int offs, int len);
-+int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key,
-+ int old_lnum, int old_offs, int lnum, int offs, int len);
-+int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key,
-+ int lnum, int offs, int len, const struct qstr *nm);
-+int ubifs_tnc_remove(struct ubifs_info *c, const union ubifs_key *key);
-+int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key,
-+ const struct qstr *nm);
-+int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key,
-+ union ubifs_key *to_key);
-+int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum);
-+struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c,
-+ union ubifs_key *key,
-+ const struct qstr *nm);
-+void ubifs_tnc_close(struct ubifs_info *c);
-+int ubifs_tnc_has_node(struct ubifs_info *c, union ubifs_key *key, int level,
-+ int lnum, int offs, int is_idx);
-+int ubifs_dirty_idx_node(struct ubifs_info *c, union ubifs_key *key, int level,
-+ int lnum, int offs);
-+/* Shared by tnc.c for tnc_commit.c */
-+void destroy_old_idx(struct ubifs_info *c);
-+int is_idx_node_in_tnc(struct ubifs_info *c, union ubifs_key *key, int level,
-+ int lnum, int offs);
-+int insert_old_idx_znode(struct ubifs_info *c, struct ubifs_znode *znode);
-+
-+/* tnc_misc.c */
-+struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr,
-+ struct ubifs_znode *znode);
-+int ubifs_search_zbranch(const struct ubifs_info *c,
-+ const struct ubifs_znode *znode,
-+ const union ubifs_key *key, int *n);
-+struct ubifs_znode *ubifs_tnc_postorder_first(struct ubifs_znode *znode);
-+struct ubifs_znode *ubifs_tnc_postorder_next(struct ubifs_znode *znode);
-+long ubifs_destroy_tnc_subtree(struct ubifs_znode *zr);
-+
-+/* tnc_commit.c */
-+int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot);
-+int ubifs_tnc_end_commit(struct ubifs_info *c);
-+
-+/* shrinker.c */
-+int ubifs_shrinker(int nr_to_scan, gfp_t gfp_mask);
-+
-+/* commit.c */
-+int ubifs_bg_thread(void *info);
-+void ubifs_commit_required(struct ubifs_info *c);
-+void ubifs_request_bg_commit(struct ubifs_info *c);
-+int ubifs_run_commit(struct ubifs_info *c);
-+void ubifs_recovery_commit(struct ubifs_info *c);
-+int ubifs_gc_should_commit(struct ubifs_info *c);
-+void ubifs_wait_for_commit(struct ubifs_info *c);
-+
-+/* master.c */
-+int ubifs_read_master(struct ubifs_info *c);
-+int ubifs_write_master(struct ubifs_info *c);
-+
-+/* sb.c */
-+int ubifs_read_superblock(struct ubifs_info *c);
-+struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c);
-+int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup);
-+
-+/* replay.c */
-+int ubifs_validate_entry(struct ubifs_info *c,
-+ const struct ubifs_dent_node *dent);
-+int ubifs_replay_journal(struct ubifs_info *c);
-+
-+/* gc.c */
-+int ubifs_garbage_collect(struct ubifs_info *c, int anyway);
-+int ubifs_gc_start_commit(struct ubifs_info *c);
-+int ubifs_gc_end_commit(struct ubifs_info *c);
-+void ubifs_destroy_idx_gc(struct ubifs_info *c);
-+int ubifs_get_idx_gc_leb(struct ubifs_info *c);
-+int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp);
-+
-+/* orphan.c */
-+int ubifs_add_orphan(struct ubifs_info *c, ino_t inum);
-+void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum);
-+int ubifs_orphan_start_commit(struct ubifs_info *c);
-+int ubifs_orphan_end_commit(struct ubifs_info *c);
-+int ubifs_mount_orphans(struct ubifs_info *c, int unclean);
-+
-+/* lpt.c */
-+int ubifs_calc_lpt_geom(struct ubifs_info *c);
-+int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
-+ int *lpt_lebs, int *big_lpt);
-+int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr);
-+struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum);
-+struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum);
-+int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
-+ ubifs_lpt_scan_callback scan_cb, void *data);
-+
-+/* Shared by lpt.c for lpt_commit.c */
-+void ubifs_pack_lsave(struct ubifs_info *c, void *buf, int *lsave);
-+void ubifs_pack_ltab(struct ubifs_info *c, void *buf,
-+ struct ubifs_lpt_lprops *ltab);
-+void ubifs_pack_pnode(struct ubifs_info *c, void *buf,
-+ struct ubifs_pnode *pnode);
-+void ubifs_pack_nnode(struct ubifs_info *c, void *buf,
-+ struct ubifs_nnode *nnode);
-+struct ubifs_pnode *ubifs_get_pnode(struct ubifs_info *c,
-+ struct ubifs_nnode *parent, int iip);
-+struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c,
-+ struct ubifs_nnode *parent, int iip);
-+int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip);
-+void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty);
-+void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode);
-+uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits);
-+struct ubifs_nnode *ubifs_first_nnode(struct ubifs_info *c, int *hght);
-+
-+/* lpt_commit.c */
-+int ubifs_lpt_start_commit(struct ubifs_info *c);
-+int ubifs_lpt_end_commit(struct ubifs_info *c);
-+int ubifs_lpt_post_commit(struct ubifs_info *c);
-+void ubifs_lpt_free(struct ubifs_info *c, int wr_only);
-+
-+/* lprops.c */
-+void ubifs_get_lprops(struct ubifs_info *c);
-+const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
-+ const struct ubifs_lprops *lp,
-+ int free, int dirty, int flags,
-+ int idx_gc_cnt);
-+void ubifs_release_lprops(struct ubifs_info *c);
-+void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *stats);
-+void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
-+ int cat);
-+void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops,
-+ struct ubifs_lprops *new_lprops);
-+void ubifs_ensure_cat(struct ubifs_info *c, struct ubifs_lprops *lprops);
-+int ubifs_categorize_lprops(const struct ubifs_info *c,
-+ const struct ubifs_lprops *lprops);
-+int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
-+ int flags_set, int flags_clean, int idx_gc_cnt);
-+int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
-+ int flags_set, int flags_clean);
-+int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp);
-+const struct ubifs_lprops *ubifs_fast_find_free(struct ubifs_info *c);
-+const struct ubifs_lprops *ubifs_fast_find_empty(struct ubifs_info *c);
-+const struct ubifs_lprops *ubifs_fast_find_freeable(struct ubifs_info *c);
-+const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c);
-+
-+/* file.c */
-+int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync);
-+int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
-+
-+/* dir.c */
-+struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
-+ int mode);
-+int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
-+ struct kstat *stat);
-+
-+/* xattr.c */
-+int ubifs_setxattr(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags);
-+ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
-+ size_t size);
-+ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size);
-+int ubifs_removexattr(struct dentry *dentry, const char *name);
-+
-+/* super.c */
-+struct inode *ubifs_iget(struct super_block *sb, unsigned long inum);
-+
-+/* recovery.c */
-+int ubifs_recover_master_node(struct ubifs_info *c);
-+int ubifs_write_rcvrd_mst_node(struct ubifs_info *c);
-+struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
-+ int offs, void *sbuf, int grouped);
-+struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
-+ int offs, void *sbuf);
-+int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf);
-+int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf);
-+int ubifs_recover_gc_lnum(struct ubifs_info *c);
-+int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
-+ int deletion, loff_t new_size);
-+int ubifs_recover_size(struct ubifs_info *c);
-+void ubifs_destroy_size_tree(struct ubifs_info *c);
-+
-+/* ioctl.c */
-+long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-+void ubifs_set_inode_flags(struct inode *inode);
-+#ifdef CONFIG_COMPAT
-+long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-+#endif
-+
-+/* compressor.c */
-+int __init ubifs_compressors_init(void);
-+void __exit ubifs_compressors_exit(void);
-+void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
-+ int *compr_type);
-+int ubifs_decompress(const void *buf, int len, void *out, int *out_len,
-+ int compr_type);
-+
-+#include "debug.h"
-+#include "misc.h"
-+#include "key.h"
-+
-+#endif /* !__UBIFS_H__ */
---- linux-2.6.24.7.old/fs/ubifs/xattr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24.7/fs/ubifs/xattr.c 2009-04-12 18:13:57.000000000 +0200
-@@ -0,0 +1,582 @@
-+/*
-+ * This file is part of UBIFS.
-+ *
-+ * Copyright (C) 2006-2008 Nokia Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ * Authors: Artem Bityutskiy (Битюцкий Артём)
-+ * Adrian Hunter
-+ */
-+
-+/*
-+ * This file implements UBIFS extended attributes support.
-+ *
-+ * Extended attributes are implemented as regular inodes with attached data,
-+ * which limits extended attribute size to UBIFS block size (4KiB). Names of
-+ * extended attributes are described by extended attribute entries (xentries),
-+ * which are almost identical to directory entries, but have different key type.
-+ *
-+ * In other words, the situation with extended attributes is very similar to
-+ * directories. Indeed, any inode (but of course not xattr inodes) may have a
-+ * number of associated xentries, just like directory inodes have associated
-+ * directory entries. Extended attribute entries store the name of the extended
-+ * attribute, the host inode number, and the extended attribute inode number.
-+ * Similarly, direntries store the name, the parent and the target inode
-+ * numbers. Thus, most of the common UBIFS mechanisms may be re-used for
-+ * extended attributes.
-+ *
-+ * The number of extended attributes is not limited, but there is Linux
-+ * limitation on the maximum possible size of the list of all extended
-+ * attributes associated with an inode (%XATTR_LIST_MAX), so UBIFS makes sure
-+ * the sum of all extended attribute names of the inode does not exceed that
-+ * limit.
-+ *
-+ * Extended attributes are synchronous, which means they are written to the
-+ * flash media synchronously and there is no write-back for extended attribute
-+ * inodes. The extended attribute values are not stored in compressed form on
-+ * the media.
-+ *
-+ * Since extended attributes are represented by regular inodes, they are cached
-+ * in the VFS inode cache. The xentries are cached in the LNC cache (see
-+ * tnc.c).
-+ *
-+ * ACL support is not implemented.
-+ */
-+
-+#include
-+#include
-+#include "ubifs.h"
-+
-+/* How many bytes an extended attribute adds to the host inode */
-+#define CALC_XATTR_BYTES(data_len) ALIGN(UBIFS_INO_NODE_SZ + (data_len) + 1, 8)
-+
-+/*
-+ * Extended attribute type constants.
-+ *
-+ * USER_XATTR: user extended attribute ("user.*")
-+ * TRUSTED_XATTR: trusted extended attribute ("trusted.*)
-+ * SECURITY_XATTR: security extended attribute ("security.*")
-+ */
-+enum {
-+ USER_XATTR,
-+ TRUSTED_XATTR,
-+ SECURITY_XATTR,
-+};
-+
-+static struct inode_operations none_inode_operations;
-+static struct address_space_operations none_address_operations;
-+static struct file_operations none_file_operations;
-+
-+/**
-+ * create_xattr - create an extended attribute.
-+ * @c: UBIFS file-system description object
-+ * @host: host inode
-+ * @nm: extended attribute name
-+ * @value: extended attribute value
-+ * @size: size of extended attribute value
-+ *
-+ * This is a helper function which creates an extended attribute of name @nm
-+ * and value @value for inode @host. The host inode is also updated on flash
-+ * because the ctime and extended attribute accounting data changes. This
-+ * function returns zero in case of success and a negative error code in case
-+ * of failure.
-+ */
-+static int create_xattr(struct ubifs_info *c, struct inode *host,
-+ const struct qstr *nm, const void *value, int size)
-+{
-+ struct ubifs_inode *ui, *host_ui = ubifs_inode(host);
-+ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
-+ .new_ino_d = size };
-+ struct inode *inode;
-+ int err;
-+
-+ /*
-+ * Linux limits the maximum size of the extended attribute names list
-+ * to %XATTR_LIST_MAX. This means we should not allow creating more*
-+ * extended attributes if the name list becomes larger. This limitation
-+ * is artificial for UBIFS, though.
-+ */
-+ if (host_ui->xattr_names + host_ui->xattr_cnt +
-+ nm->len + 1 > XATTR_LIST_MAX)
-+ return -ENOSPC;
-+
-+ err = ubifs_budget_inode_op(c, host, &req);
-+ if (err)
-+ return err;
-+
-+ inode = ubifs_new_inode(c, host, S_IFREG | S_IRWXUGO);
-+ if (IS_ERR(inode)) {
-+ err = PTR_ERR(inode);
-+ goto out_budg;
-+ }
-+
-+ /* Re-define all operations to be "nothing" */
-+ inode->i_mapping->a_ops = &none_address_operations;
-+ inode->i_op = &none_inode_operations;
-+ inode->i_fop = &none_file_operations;
-+
-+ inode->i_flags |= S_SYNC | S_NOATIME | S_NOCMTIME | S_NOQUOTA;
-+ ui = ubifs_inode(inode);
-+ ui->xattr = 1;
-+ ui->data = kmalloc(size, GFP_NOFS);
-+ if (!ui->data) {
-+ err = -ENOMEM;
-+ goto out_inode;
-+ }
-+
-+ memcpy(ui->data, value, size);
-+ host->i_ctime = ubifs_current_time(host);
-+ host_ui->xattr_cnt += 1;
-+ spin_lock(&host->i_lock);
-+ host_ui->xattr_size += CALC_DENT_SIZE(nm->len);
-+ host_ui->xattr_size += CALC_XATTR_BYTES(size);
-+ spin_unlock(&host->i_lock);
-+ host_ui->xattr_names += nm->len;
-+
-+ /*
-+ * We do not use i_size_write() because nobody can race with us as we
-+ * are holding host @host->i_mutex - every xattr operation for this
-+ * inode is serialized by it.
-+ */
-+ inode->i_size = size;
-+ ui->data_len = size;
-+
-+ /*
-+ * Note, it is important that 'ubifs_jnl_update()' writes the @host
-+ * inode last, so when it gets synchronized and the write-buffer is
-+ * flushed, the extended attribute is flushed as well.
-+ */
-+ err = ubifs_jnl_update(c, host, nm, inode, 0, IS_DIRSYNC(host), 1);
-+ if (err)
-+ goto out_cancel;
-+
-+ ubifs_release_ino_clean(c, host, &req);
-+ insert_inode_hash(inode);
-+ iput(inode);
-+ return 0;
-+
-+out_cancel:
-+ host_ui->xattr_cnt -= 1;
-+ spin_lock(&host->i_lock);
-+ host_ui->xattr_size -= CALC_DENT_SIZE(nm->len);
-+ host_ui->xattr_size -= CALC_XATTR_BYTES(size);
-+ spin_unlock(&host->i_lock);
-+out_inode:
-+ make_bad_inode(inode);
-+ iput(inode);
-+out_budg:
-+ ubifs_cancel_ino_op(c, host, &req);
-+ return err;
-+}
-+
-+/**
-+ * change_xattr - change an extended attribute.
-+ * @c: UBIFS file-system description object
-+ * @host: host inode
-+ * @inode: extended attribute inode
-+ * @value: extended attribute value
-+ * @size: size of extended attribute value
-+ *
-+ * This helper function changes the value of extended attribute @inode with new
-+ * data from @value. Returns zero in case of success and a negative error code
-+ * in case of failure.
-+ */
-+static int change_xattr(struct ubifs_info *c, struct inode *host,
-+ struct inode *inode, const void *value, int size)
-+{
-+ struct ubifs_inode *host_ui = ubifs_inode(host);
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+ struct ubifs_budget_req req = { .dirtied_ino = 1,
-+ .dirtied_ino_d = ui->data_len };
-+ int err;
-+
-+ ubifs_assert(ui->data_len == inode->i_size);
-+
-+ err = ubifs_budget_inode_op(c, host, &req);
-+ if (err)
-+ return err;
-+
-+ host->i_ctime = ubifs_current_time(host);
-+ spin_lock(&host->i_lock);
-+ host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
-+ host_ui->xattr_size += CALC_XATTR_BYTES(size);
-+ spin_unlock(&host->i_lock);
-+
-+ kfree(ui->data);
-+ ui->data = kmalloc(size, GFP_NOFS);
-+ if (!ui->data) {
-+ err = -ENOMEM;
-+ goto out_budg;
-+ }
-+
-+ memcpy(ui->data, value, size);
-+ inode->i_size = size;
-+ ui->data_len = size;
-+
-+ /*
-+ * It is important to write the host inode after the xattr inode
-+ * because if the host inode gets synchronized, then the extended
-+ * attribute inode gets synchronized, because it goes before the host
-+ * inode in the write-buffer.
-+ */
-+ err = ubifs_jnl_write_2_inodes(c, inode, host, IS_DIRSYNC(host));
-+ if (err)
-+ goto out_cancel;
-+
-+ ubifs_release_ino_clean(c, host, &req);
-+ return 0;
-+
-+out_cancel:
-+ spin_lock(&host->i_lock);
-+ host_ui->xattr_size -= CALC_XATTR_BYTES(size);
-+ host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
-+ spin_unlock(&host->i_lock);
-+ make_bad_inode(inode);
-+out_budg:
-+ ubifs_cancel_ino_op(c, host, &req);
-+ return err;
-+}
-+
-+/**
-+ * check_namespace - check extended attribute name-space.
-+ * @nm: extended attribute name
-+ *
-+ * This function makes sure the extended attribute name belongs to one of the
-+ * supported extended attribute name-spaces. Returns name-space index in case
-+ * of success and a negative error code in case of failure.
-+ */
-+static int check_namespace(const struct qstr *nm)
-+{
-+ int type;
-+
-+ if (nm->len > UBIFS_MAX_NLEN)
-+ return -ENAMETOOLONG;
-+
-+ if (!strncmp(nm->name, XATTR_TRUSTED_PREFIX,
-+ XATTR_TRUSTED_PREFIX_LEN)) {
-+ if (nm->name[sizeof(XATTR_TRUSTED_PREFIX) - 1] == '\0')
-+ return -EINVAL;
-+ type = TRUSTED_XATTR;
-+ } else if (!strncmp(nm->name, XATTR_USER_PREFIX,
-+ XATTR_USER_PREFIX_LEN)) {
-+ if (nm->name[XATTR_USER_PREFIX_LEN] == '\0')
-+ return -EINVAL;
-+ type = USER_XATTR;
-+ } else if (!strncmp(nm->name, XATTR_SECURITY_PREFIX,
-+ XATTR_SECURITY_PREFIX_LEN)) {
-+ if (nm->name[sizeof(XATTR_SECURITY_PREFIX) - 1] == '\0')
-+ return -EINVAL;
-+ type = SECURITY_XATTR;
-+ } else
-+ return -EOPNOTSUPP;
-+
-+ return type;
-+}
-+
-+int ubifs_setxattr(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ struct inode *inode, *host = dentry->d_inode;
-+ struct ubifs_info *c = host->i_sb->s_fs_info;
-+ struct qstr nm = { .name = name, .len = strlen(name) };
-+ struct ubifs_dent_node *xent;
-+ union ubifs_key key;
-+ int err, type;
-+
-+ dbg_gen("xattr '%s', host ino %lu ('%.*s'), size %zd", name,
-+ host->i_ino, dentry->d_name.len, dentry->d_name.name, size);
-+ ubifs_assert(ubifs_inode(host)->xattr_cnt >= 0);
-+ ubifs_assert(ubifs_inode(host)->xattr_size >= 0);
-+ ubifs_assert(ubifs_inode(host)->xattr_names >= 0);
-+
-+ if (size > UBIFS_MAX_INO_DATA)
-+ return -ERANGE;
-+
-+ type = check_namespace(&nm);
-+ if (type < 0)
-+ return type;
-+
-+ xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS);
-+ if (!xent)
-+ return -ENOMEM;
-+
-+ /*
-+ * The extended attribute entries are stored in LNC, so multiple
-+ * look-ups do not involve reading the flash.
-+ */
-+ xent_key_init(c, &key, host->i_ino, &nm);
-+ err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
-+ if (err) {
-+ if (err != -ENOENT)
-+ goto out_free;
-+
-+ if (flags & XATTR_REPLACE)
-+ /* We are asked not to create the xattr */
-+ err = -ENODATA;
-+ else
-+ err = create_xattr(c, host, &nm, value, size);
-+ goto out_free;
-+ }
-+
-+ if (flags & XATTR_CREATE) {
-+ /* We are asked not to replace the xattr */
-+ err = -EEXIST;
-+ goto out_free;
-+ }
-+
-+ inode = ubifs_iget(c->vfs_sb, le64_to_cpu(xent->inum));
-+ if (IS_ERR(inode)) {
-+ ubifs_err("dead extended attribute entry, error %d", err);
-+ ubifs_ro_mode(c, err);
-+ err = PTR_ERR(inode);
-+ goto out_free;
-+ }
-+
-+ err = change_xattr(c, host, inode, value, size);
-+ iput(inode);
-+
-+out_free:
-+ kfree(xent);
-+ return err;
-+}
-+
-+ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
-+ size_t size)
-+{
-+ struct inode *inode, *host = dentry->d_inode;
-+ struct ubifs_info *c = host->i_sb->s_fs_info;
-+ struct qstr nm = { .name = name, .len = strlen(name) };
-+ struct ubifs_inode *ui;
-+ struct ubifs_dent_node *xent;
-+ union ubifs_key key;
-+ int err;
-+
-+ dbg_gen("xattr '%s', ino %lu ('%.*s'), buf size %zd", name,
-+ host->i_ino, dentry->d_name.len, dentry->d_name.name, size);
-+ ubifs_assert(ubifs_inode(host)->xattr_cnt >= 0);
-+ ubifs_assert(ubifs_inode(host)->xattr_size >= 0);
-+ ubifs_assert(ubifs_inode(host)->xattr_names >= 0);
-+
-+ err = check_namespace(&nm);
-+ if (err < 0)
-+ return err;
-+
-+ xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS);
-+ if (!xent)
-+ return -ENOMEM;
-+
-+ mutex_lock(&host->i_mutex);
-+ xent_key_init(c, &key, host->i_ino, &nm);
-+ err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
-+ if (err) {
-+ if (err == -ENOENT)
-+ err = -ENODATA;
-+ goto out_unlock;
-+ }
-+
-+ inode = ubifs_iget(c->vfs_sb, le64_to_cpu(xent->inum));
-+ if (IS_ERR(inode)) {
-+ ubifs_err("dead extended attribute entry, error %d", err);
-+ ubifs_ro_mode(c, err);
-+ err = PTR_ERR(inode);
-+ goto out_unlock;
-+ }
-+
-+ ui = ubifs_inode(inode);
-+ ubifs_assert(inode->i_size == ui->data_len);
-+ ubifs_assert(ubifs_inode(host)->xattr_size > ui->data_len);
-+
-+ if (buf) {
-+ /* If @buf is %NULL we are supposed to return the length */
-+ if (ui->data_len > size) {
-+ dbg_err("buffer size %zd, xattr len %d",
-+ size, ui->data_len);
-+ err = -ERANGE;
-+ goto out_iput;
-+ }
-+
-+ memcpy(buf, ui->data, ui->data_len);
-+ }
-+ err = ui->data_len;
-+
-+out_iput:
-+ iput(inode);
-+out_unlock:
-+ mutex_unlock(&host->i_mutex);
-+ kfree(xent);
-+ return err;
-+}
-+
-+ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ struct inode *host = dentry->d_inode;
-+ struct ubifs_info *c = host->i_sb->s_fs_info;
-+ struct ubifs_inode *host_ui = ubifs_inode(host);
-+ union ubifs_key key;
-+ struct ubifs_dent_node *xent, *pxent = NULL;
-+ int err, len, written = 0;
-+ struct qstr nm = { .name = NULL };
-+
-+ dbg_gen("ino %lu ('%.*s'), buffer size %zd", host->i_ino,
-+ dentry->d_name.len, dentry->d_name.name, size);
-+ ubifs_assert(host_ui->xattr_cnt >= 0);
-+ ubifs_assert(host_ui->xattr_size >= 0);
-+ ubifs_assert(host_ui->xattr_names >= 0);
-+
-+ len = host_ui->xattr_names + host_ui->xattr_cnt;
-+ if (!buffer)
-+ /*
-+ * We should return the minimum buffer size which will fit a
-+ * null-terminated list of all the extended attribute names.
-+ */
-+ return len;
-+
-+ if (len > size)
-+ return -ERANGE;
-+
-+ lowest_xent_key(c, &key, host->i_ino);
-+
-+ mutex_lock(&host->i_mutex);
-+ while (1) {
-+ int type;
-+
-+ xent = ubifs_tnc_next_ent(c, &key, &nm);
-+ if (unlikely(IS_ERR(xent))) {
-+ err = PTR_ERR(xent);
-+ break;
-+ }
-+
-+ nm.name = xent->name;
-+ nm.len = le16_to_cpu(xent->nlen);
-+
-+ type = check_namespace(&nm);
-+ if (unlikely(type < 0)) {
-+ err = type;
-+ break;
-+ }
-+
-+ /* Show trusted namespace only for "power" users */
-+ if (type != TRUSTED_XATTR || capable(CAP_SYS_ADMIN)) {
-+ memcpy(buffer + written, nm.name, nm.len + 1);
-+ written += nm.len + 1;
-+ }
-+
-+ kfree(pxent);
-+ pxent = xent;
-+ key_read(c, &xent->key, &key);
-+ }
-+ mutex_unlock(&host->i_mutex);
-+
-+ kfree(pxent);
-+ if (err != -ENOENT) {
-+ ubifs_err("cannot find next direntry, error %d", err);
-+ return err;
-+ }
-+
-+ ubifs_assert(written <= size);
-+ return written;
-+}
-+
-+static int remove_xattr(struct ubifs_info *c, struct inode *host,
-+ struct inode *inode, const struct qstr *nm)
-+{
-+ struct ubifs_inode *host_ui = ubifs_inode(host);
-+ struct ubifs_inode *ui = ubifs_inode(inode);
-+ struct ubifs_budget_req req = { .dirtied_ino = 1, .mod_dent = 1 };
-+ int err;
-+
-+ ubifs_assert(ui->data_len == inode->i_size);
-+
-+ err = ubifs_budget_inode_op(c, host, &req);
-+ if (err)
-+ return err;
-+
-+ host->i_ctime = ubifs_current_time(host);
-+ host_ui->xattr_cnt -= 1;
-+ spin_lock(&host->i_lock);
-+ host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
-+ spin_unlock(&host->i_lock);
-+ host_ui->xattr_names -= nm->len;
-+
-+ err = ubifs_jnl_delete_xattr(c, host, inode, nm, IS_DIRSYNC(host));
-+ if (err)
-+ goto out_cancel;
-+
-+ ubifs_release_ino_clean(c, host, &req);
-+ return 0;
-+
-+out_cancel:
-+ ubifs_cancel_ino_op(c, host, &req);
-+ host_ui->xattr_cnt += 1;
-+ spin_lock(&host->i_lock);
-+ host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
-+ spin_unlock(&host->i_lock);
-+ make_bad_inode(inode);
-+ return err;
-+}
-+
-+int ubifs_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct inode *inode, *host = dentry->d_inode;
-+ struct ubifs_info *c = host->i_sb->s_fs_info;
-+ struct qstr nm = { .name = name, .len = strlen(name) };
-+ struct ubifs_dent_node *xent;
-+ union ubifs_key key;
-+ int err;
-+
-+ dbg_gen("xattr '%s', ino %lu ('%.*s')", name,
-+ host->i_ino, dentry->d_name.len, dentry->d_name.name);
-+ ubifs_assert(mutex_is_locked(&host->i_mutex));
-+ ubifs_assert(ubifs_inode(host)->xattr_cnt >= 0);
-+ ubifs_assert(ubifs_inode(host)->xattr_size >= 0);
-+ ubifs_assert(ubifs_inode(host)->xattr_names >= 0);
-+
-+ err = check_namespace(&nm);
-+ if (err < 0)
-+ return err;
-+
-+ xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS);
-+ if (!xent)
-+ return -ENOMEM;
-+
-+ xent_key_init(c, &key, host->i_ino, &nm);
-+ err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
-+ if (err) {
-+ if (err == -ENOENT)
-+ err = -ENODATA;
-+ goto out_free;
-+ }
-+
-+ inode = ubifs_iget(c->vfs_sb, le64_to_cpu(xent->inum));
-+ if (IS_ERR(inode)) {
-+ ubifs_err("dead extended attribute node entry");
-+ ubifs_ro_mode(c, err);
-+ err = PTR_ERR(inode);
-+ goto out_free;
-+ }
-+
-+ ubifs_assert(inode->i_nlink == 1);
-+ inode->i_nlink = 0;
-+ err = remove_xattr(c, host, inode, &nm);
-+ if (err)
-+ inode->i_nlink = 1;
-+
-+ /* If @i_nlink is 0, 'iput()' will delete the inode */
-+ iput(inode);
-+
-+out_free:
-+ kfree(xent);
-+ return err;
-+}
]