summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/fs/affs
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/fs/affs')
-rw-r--r--ANDROID_3.4.5/fs/affs/Changes343
-rw-r--r--ANDROID_3.4.5/fs/affs/Kconfig21
-rw-r--r--ANDROID_3.4.5/fs/affs/Makefile9
-rw-r--r--ANDROID_3.4.5/fs/affs/affs.h305
-rw-r--r--ANDROID_3.4.5/fs/affs/amigaffs.c515
-rw-r--r--ANDROID_3.4.5/fs/affs/bitmap.c390
-rw-r--r--ANDROID_3.4.5/fs/affs/dir.c156
-rw-r--r--ANDROID_3.4.5/fs/affs/file.c942
-rw-r--r--ANDROID_3.4.5/fs/affs/inode.c413
-rw-r--r--ANDROID_3.4.5/fs/affs/namei.c458
-rw-r--r--ANDROID_3.4.5/fs/affs/super.c622
-rw-r--r--ANDROID_3.4.5/fs/affs/symlink.c81
12 files changed, 0 insertions, 4255 deletions
diff --git a/ANDROID_3.4.5/fs/affs/Changes b/ANDROID_3.4.5/fs/affs/Changes
deleted file mode 100644
index a29409c1..00000000
--- a/ANDROID_3.4.5/fs/affs/Changes
+++ /dev/null
@@ -1,343 +0,0 @@
-(Note: I consider version numbers as cheap. That means
-that I do not like numbers like 0.1 and the like for
-things that can be used since quite some time. But
-then, 3.1 doesn't mean 'perfectly stable', too.)
-
-Known bugs:
------------
-
-- Doesn't work on the alpha. The only 64/32-bit
- problem that I'm aware of (pointer/int conversion
- in readdir()) gives compiler warnings but is
- apparently not causing the failure, as directory
- reads basically work (but all files are of size 0).
- Alas, I've got no alpha to debug. :-(
-
-- The partition checker (drivers/block/genhd.c)
- doesn't work with devices which have 256 byte
- blocks (some very old SCSI drives).
-
-- The feature to automatically make the fs clean
- might leave a trashed file system with the
- bitmap flag set valid.
-
-- When a file is truncated to a size that is not
- a multiple of the blocksize, the rest of the
- last allocated block is not cleared. Well,
- this fs never claimed to be Posix conformant.
-
-Please direct bug reports to: zippel@linux-m68k.org
-
-Version 3.20
-------------
-- kill kernel lock
-- fix for a possible bitmap corruption
-
-Version 3.19
-------------
-
-- sizeof changes from Kernel Janitor Project
-- several bug fixes found with fsx
-
-Version 3.18
-------------
-
-- change to global min macro + warning fixes
-- add module tags
-
-Version 3.17
-------------
-
-- locking fixes
-- wrong sign in __affs_hash_dentry
-- remove unnecessary check in affs_new_inode
-- enable international mode for dircache fs
-
-Version 3.16
-------------
-
-- use mark_buffer_dirty_inode instead of mark_buffer_dirty.
-- introduce affs_lock_{link|dir|ext}.
-
-Version 3.15
-------------
-
-- disable link to directories until we can properly support them.
-- locking fixes for link creation/removal.
-
-Version 3.14
-------------
-
-- correctly cut off long file names for compares
-- correctly initialize s_last_bmap
-
-Version 3.13
-------------
-
-Major cleanup for 2.4 [Roman Zippel]
-- new extended block handling
-- new bitmap allocation functions
-- locking should be safe for the future
-- cleanup of some interfaces
-
-Version 3.12
-------------
-
-more 2.4 fixes: [Roman Zippel]
-- s_lock changes
-- increased getblock mess
-- clear meta blocks
-
-Version 3.11
-------------
-
-- Converted to use 2.3.x page cache [Dave Jones <dave@powertweak.com>]
-- Corruption in truncate() bugfix [Ken Tyler <kent@werple.net.au>]
-
-Version 3.10
-------------
-
-- Changed partition checker to allow devices
- with physical blocks != 512 bytes.
-
-- The partition checker now also ignores the
- word at 0xd0 that Windows likes to write to.
-
-Version 3.9
------------
-
-- Moved cleanup from release_file() to put_inode().
- This makes the first one obsolete.
-
-- truncate() zeroes the unused remainder of a
- partially used last block when a file is truncated.
- It also marks the inode dirty now (which is not
- really necessary as notify_change() will do
- it anyway).
-
-- Added a few comments, fixed some typos (and
- introduced some new ones), made the debug messages
- more consistent. Changed a bad example in the
- doc file (affs.txt).
-
-- Sets the NOEXEC flag in read_super() for old file
- systems, since you can't run programs on them.
-
-Version 3.8
------------
-Bill Hawes kindly reviewed the affs and sent me the
-patches he did. They're marked (BH). Thanks, Bill!
-
-- Cleanup of error handling in read_super().
- Didn't release all resources in case of an
- error. (BH)
-
-- put_inode() releases the ext cache only if it's
- no longer needed. (BH)
-
-- One set of dentry callbacks is enough. (BH)
-
-- Cleanup of error handling in namei.c. (BH)
-
-- Cleanup of error handling in file.c. (BH)
-
-- The original blocksize of the device is
- restored when the fs is unmounted. (BH)
-
-- getblock() did not invalidate the key cache
- when it allocated a new block.
-
-- Removed some unnecessary locks as Bill
- suggested.
-
-- Simplified match_name(), changed all hashing
- and case insensitive name comparisons to use
- uppercase. This makes the tolower() routines
- obsolete.
-
-- Added mount option 'mufs' to force muFS
- uid/gid interpretation.
-
-- File mode changes were not updated on disk.
- This was fixed before, but somehow got lost.
-
-Version 3.7
------------
-
-- Added dentry callbacks to allow the dcache to
- operate case insensitive and length ignorant
- like the affs itself.
-
-- getblock() didn't update the lastblock field in the
- inode if the fs was not an OFS. This bug only shows
- up if a file was enlarged via truncate() and there
- was not enough space.
-
-- Remove some more superfluous code left over from
- the old link days ...
-
-- Fixed some oversights which were in patch 2.1.78.
-
-- Fixed a few typos.
-
-Version 3.6
------------
-
-- dentry changes. (Thanks to Jes Sorensen for his help.)
-
-- Fixed bug in balloc(): Superblock was not set dirty after
- the bitmap was changed, so the bitmap wasn't sync'd.
-
-- Fixed nasty bug in find_new_zone(): If the current
- zone number was zero, the loop didn't terminate,
- causing a solid lock-up.
-
-- Removed support for old-style directory reads.
-
-- Fixed bug in add_entry(): When doing a sorted insert,
- the pointer to the next entry in the hash chain wasn't
- correctly byte-swapped. Since most of the users of the
- affs use it on a 68k, they didn't notice. But why did
- I not find this during my tests?
-
-- Fixed some oversights (version wasn't updated on some
- directory changes).
-
-- Handling of hard links rewritten. To the VFS
- they appear now as normal Unix links. They are
- now resolved only once in lookup(). The backside
- is that unlink(), rename() and rmdir() have to
- be smart about them, but the result is worth the
- effort. This also led to some code cleanup.
-
-- Changed name type to unsigned char; the test for
- invalid filenames didn't work correctly.
- (Thanks to Michael Krause for pointing at this.)
-
-- Changed mapping of executable flag.
-
-- Changed all network byte-order macros to the
- recommended ones.
-
-- Added a remount function, so attempts to remount
- a dircache filesystem or one with errors read/write
- can be trapped. Previously, ro remounts didn't
- flush the super block, and rw remounts didn't
- create allocation zones ...
-
-- Call shrink_dcache_parent() in rmdir().
- (Thanks to Bill Hawes.)
-
-- Permission checks in unlink().
-
-- Allow mounting of volumes with superfluous
- bitmap pointers read only, also allows them
- to be remounted read/write.
-
-- Owner/Group defaults now to the fs user (i.e.
- the one that mounted it) instead of root. This
- obsoletes the mount options uid and gid.
-
-- Argument to volume option could overflow the
- name buffer. It is now silently truncated to
- 30 characters. (Damn it! This kind of bug
- is too embarrassing.)
-
-- Split inode.c into 2 files, the superblock
- routines desperately wanted their own file.
-
-- truncate() didn't allocate an extension block
- cache. If a file was extended by means of
- truncate(), this led to an Oops.
-
-- fsuser is now checked last.
-
-- rename() will not ignore changes in filename
- casing any more (though mv(1) still won't allow
- you to do "mv oldname OldName").
-
-Version 3.5
------------
-
-- Extension block caches are now allocated on
- demand instead of when a file is opened, as
- files can be read and written without opening
- them (e. g. the loopback device does this).
-
-- Removed an unused function.
-
-Version 3.4
------------
-
-- Hash chains are now sorted by block numbers.
- (Thanks to Kars de Jong for finding this.)
-- Removed all unnecessary external symbols.
-
-Version 3.3
------------
-
-- Tried to make all types 'correct' and consistent.
-- Errors and warnings are now reported via a
- function. They are all prefixed by a severity
- and have the same appearance:
- "AFFS: <function>: <error message>"
- (There's one exception to this, as in that function
- is no pointer to the super block available.)
-- The filesystem is remounted read-only after an
- error.
-- The names of newly created filesystem objects are
- now checked for validity.
-- Minor cleanups in comments.
-- Added this Changes file. At last!
-
-Version 3.2
------------
-
-- Extension block cache: Reading/writing of huge files
- (several MB) is much faster (of course the added
- overhead slows down opening, but this is hardly
- noticeable).
-- The same get_block()-routine can now be used for
- both OFS and FFS.
-- The super block is now searched in the block that
- was calculated and in the one following. This
- should remedy the round-off error introduced by
- the 1-k blocks that Linux uses.
-- Minor changes to adhere to the new VFS interface.
-- The number of used blocks is now also calculated
- if the filesystem is mounted read-only.
-- Prefixed some constants with AFFS_ to avoid name
- clashes.
-- Removed 'EXPERIMENTAL' status.
-
-Version 3.1
------------
-
-- Fixed a nasty bug which didn't allow read-only
- mounts.
-- Allow dir-cache filesystems to be mounted
- read only.
-- OFS support.
-- Several other changes I just cannot remember
- any more.
-
-Version 3.0
------------
-
-- Almost complete rewrite for the new VFS
- interface in Linux 1.3.
-- Write support.
-- Support for hard and symbolic links.
-- Lots of things I remember even less ...
-
-Version 2.0
------------
-
-- Fixed a few things to get it compiled.
-- Automatic root block calculation.
-- Partition checker for genhd.c
-
-========================================
-
-Let's just call Ray Burr's original affs
-'Version 1.0'.
diff --git a/ANDROID_3.4.5/fs/affs/Kconfig b/ANDROID_3.4.5/fs/affs/Kconfig
deleted file mode 100644
index cfad9afb..00000000
--- a/ANDROID_3.4.5/fs/affs/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-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 <file:Documentation/filesystems/affs.txt>
- and <file:fs/affs/Changes>.
-
- With this driver you can also mount disk files used by Bernd
- Schmidt's Un*X Amiga Emulator
- (<http://www.freiburg.linux.de/~uae/>).
- 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.
diff --git a/ANDROID_3.4.5/fs/affs/Makefile b/ANDROID_3.4.5/fs/affs/Makefile
deleted file mode 100644
index 3988b4a7..00000000
--- a/ANDROID_3.4.5/fs/affs/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the Linux affs filesystem routines.
-#
-
-#ccflags-y := -DDEBUG=1
-
-obj-$(CONFIG_AFFS_FS) += affs.o
-
-affs-objs := super.o namei.o inode.o file.o dir.o amigaffs.o bitmap.o symlink.o
diff --git a/ANDROID_3.4.5/fs/affs/affs.h b/ANDROID_3.4.5/fs/affs/affs.h
deleted file mode 100644
index 45a0ce45..00000000
--- a/ANDROID_3.4.5/fs/affs/affs.h
+++ /dev/null
@@ -1,305 +0,0 @@
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/buffer_head.h>
-#include <linux/amigaffs.h>
-#include <linux/mutex.h>
-
-/* AmigaOS allows file names with up to 30 characters length.
- * Names longer than that will be silently truncated. If you
- * want to disallow this, comment out the following #define.
- * Creating filesystem objects with longer names will then
- * result in an error (ENAMETOOLONG).
- */
-/*#define AFFS_NO_TRUNCATE */
-
-/* Ugly macros make the code more pretty. */
-
-#define GET_END_PTR(st,p,sz) ((st *)((char *)(p)+((sz)-sizeof(st))))
-#define AFFS_GET_HASHENTRY(data,hashkey) be32_to_cpu(((struct dir_front *)data)->hashtable[hashkey])
-#define AFFS_BLOCK(sb, bh, blk) (AFFS_HEAD(bh)->table[AFFS_SB(sb)->s_hashsize-1-(blk)])
-
-#ifdef __LITTLE_ENDIAN
-#define BO_EXBITS 0x18UL
-#elif defined(__BIG_ENDIAN)
-#define BO_EXBITS 0x00UL
-#else
-#error Endianness must be known for affs to work.
-#endif
-
-#define AFFS_HEAD(bh) ((struct affs_head *)(bh)->b_data)
-#define AFFS_TAIL(sb, bh) ((struct affs_tail *)((bh)->b_data+(sb)->s_blocksize-sizeof(struct affs_tail)))
-#define AFFS_ROOT_HEAD(bh) ((struct affs_root_head *)(bh)->b_data)
-#define AFFS_ROOT_TAIL(sb, bh) ((struct affs_root_tail *)((bh)->b_data+(sb)->s_blocksize-sizeof(struct affs_root_tail)))
-#define AFFS_DATA_HEAD(bh) ((struct affs_data_head *)(bh)->b_data)
-#define AFFS_DATA(bh) (((struct affs_data_head *)(bh)->b_data)->data)
-
-#define AFFS_CACHE_SIZE PAGE_SIZE
-
-#define AFFS_MAX_PREALLOC 32
-#define AFFS_LC_SIZE (AFFS_CACHE_SIZE/sizeof(u32)/2)
-#define AFFS_AC_SIZE (AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2)
-#define AFFS_AC_MASK (AFFS_AC_SIZE-1)
-
-struct affs_ext_key {
- u32 ext; /* idx of the extended block */
- u32 key; /* block number */
-};
-
-/*
- * affs fs inode data in memory
- */
-struct affs_inode_info {
- atomic_t i_opencnt;
- struct semaphore i_link_lock; /* Protects internal inode access. */
- struct semaphore i_ext_lock; /* Protects internal inode access. */
-#define i_hash_lock i_ext_lock
- u32 i_blkcnt; /* block count */
- u32 i_extcnt; /* extended block count */
- u32 *i_lc; /* linear cache of extended blocks */
- u32 i_lc_size;
- u32 i_lc_shift;
- u32 i_lc_mask;
- struct affs_ext_key *i_ac; /* associative cache of extended blocks */
- u32 i_ext_last; /* last accessed extended block */
- struct buffer_head *i_ext_bh; /* bh of last extended block */
- loff_t mmu_private;
- u32 i_protect; /* unused attribute bits */
- u32 i_lastalloc; /* last allocated block */
- int i_pa_cnt; /* number of preallocated blocks */
- struct inode vfs_inode;
-};
-
-/* short cut to get to the affs specific inode data */
-static inline struct affs_inode_info *AFFS_I(struct inode *inode)
-{
- return list_entry(inode, struct affs_inode_info, vfs_inode);
-}
-
-/*
- * super-block data in memory
- *
- * Block numbers are adjusted for their actual size
- *
- */
-
-struct affs_bm_info {
- u32 bm_key; /* Disk block number */
- u32 bm_free; /* Free blocks in here */
-};
-
-struct affs_sb_info {
- int s_partition_size; /* Partition size in blocks. */
- int s_reserved; /* Number of reserved blocks. */
- //u32 s_blksize; /* Initial device blksize */
- u32 s_data_blksize; /* size of the data block w/o header */
- u32 s_root_block; /* FFS root block number. */
- int s_hashsize; /* Size of hash table. */
- unsigned long s_flags; /* See below. */
- uid_t s_uid; /* uid to override */
- gid_t s_gid; /* gid to override */
- umode_t s_mode; /* mode to override */
- struct buffer_head *s_root_bh; /* Cached root block. */
- struct mutex s_bmlock; /* Protects bitmap access. */
- struct affs_bm_info *s_bitmap; /* Bitmap infos. */
- u32 s_bmap_count; /* # of bitmap blocks. */
- u32 s_bmap_bits; /* # of bits in one bitmap blocks */
- u32 s_last_bmap;
- struct buffer_head *s_bmap_bh;
- char *s_prefix; /* Prefix for volumes and assigns. */
- char s_volume[32]; /* Volume prefix for absolute symlinks. */
- spinlock_t symlink_lock; /* protects the previous two */
-};
-
-#define SF_INTL 0x0001 /* International filesystem. */
-#define SF_BM_VALID 0x0002 /* Bitmap is valid. */
-#define SF_IMMUTABLE 0x0004 /* Protection bits cannot be changed */
-#define SF_QUIET 0x0008 /* chmod errors will be not reported */
-#define SF_SETUID 0x0010 /* Ignore Amiga uid */
-#define SF_SETGID 0x0020 /* Ignore Amiga gid */
-#define SF_SETMODE 0x0040 /* Ignore Amiga protection bits */
-#define SF_MUFS 0x0100 /* Use MUFS uid/gid mapping */
-#define SF_OFS 0x0200 /* Old filesystem */
-#define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */
-#define SF_VERBOSE 0x0800 /* Talk about fs when mounting */
-
-/* short cut to get to the affs specific sb data */
-static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)
-{
- return sb->s_fs_info;
-}
-
-/* amigaffs.c */
-
-extern int affs_insert_hash(struct inode *inode, struct buffer_head *bh);
-extern int affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh);
-extern int affs_remove_header(struct dentry *dentry);
-extern u32 affs_checksum_block(struct super_block *sb, struct buffer_head *bh);
-extern void affs_fix_checksum(struct super_block *sb, struct buffer_head *bh);
-extern void secs_to_datestamp(time_t secs, struct affs_date *ds);
-extern umode_t prot_to_mode(u32 prot);
-extern void mode_to_prot(struct inode *inode);
-extern void affs_error(struct super_block *sb, const char *function, const char *fmt, ...);
-extern void affs_warning(struct super_block *sb, const char *function, const char *fmt, ...);
-extern int affs_check_name(const unsigned char *name, int len);
-extern int affs_copy_name(unsigned char *bstr, struct dentry *dentry);
-
-/* bitmap. c */
-
-extern u32 affs_count_free_blocks(struct super_block *s);
-extern void affs_free_block(struct super_block *sb, u32 block);
-extern u32 affs_alloc_block(struct inode *inode, u32 goal);
-extern int affs_init_bitmap(struct super_block *sb, int *flags);
-extern void affs_free_bitmap(struct super_block *sb);
-
-/* namei.c */
-
-extern int affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len);
-extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
-extern int affs_unlink(struct inode *dir, struct dentry *dentry);
-extern int affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *);
-extern int affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
-extern int affs_rmdir(struct inode *dir, struct dentry *dentry);
-extern int affs_link(struct dentry *olddentry, struct inode *dir,
- struct dentry *dentry);
-extern int affs_symlink(struct inode *dir, struct dentry *dentry,
- const char *symname);
-extern int affs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry);
-
-/* inode.c */
-
-extern unsigned long affs_parent_ino(struct inode *dir);
-extern struct inode *affs_new_inode(struct inode *dir);
-extern int affs_notify_change(struct dentry *dentry, struct iattr *attr);
-extern void affs_evict_inode(struct inode *inode);
-extern struct inode *affs_iget(struct super_block *sb,
- unsigned long ino);
-extern int affs_write_inode(struct inode *inode,
- struct writeback_control *wbc);
-extern int affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type);
-
-/* file.c */
-
-void affs_free_prealloc(struct inode *inode);
-extern void affs_truncate(struct inode *);
-int affs_file_fsync(struct file *, loff_t, loff_t, int);
-
-/* dir.c */
-
-extern void affs_dir_truncate(struct inode *);
-
-/* jump tables */
-
-extern const struct inode_operations affs_file_inode_operations;
-extern const struct inode_operations affs_dir_inode_operations;
-extern const struct inode_operations affs_symlink_inode_operations;
-extern const struct file_operations affs_file_operations;
-extern const struct file_operations affs_file_operations_ofs;
-extern const struct file_operations affs_dir_operations;
-extern const struct address_space_operations affs_symlink_aops;
-extern const struct address_space_operations affs_aops;
-extern const struct address_space_operations affs_aops_ofs;
-
-extern const struct dentry_operations affs_dentry_operations;
-extern const struct dentry_operations affs_intl_dentry_operations;
-
-static inline void
-affs_set_blocksize(struct super_block *sb, int size)
-{
- sb_set_blocksize(sb, size);
-}
-static inline struct buffer_head *
-affs_bread(struct super_block *sb, int block)
-{
- pr_debug("affs_bread: %d\n", block);
- if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size)
- return sb_bread(sb, block);
- return NULL;
-}
-static inline struct buffer_head *
-affs_getblk(struct super_block *sb, int block)
-{
- pr_debug("affs_getblk: %d\n", block);
- if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size)
- return sb_getblk(sb, block);
- return NULL;
-}
-static inline struct buffer_head *
-affs_getzeroblk(struct super_block *sb, int block)
-{
- struct buffer_head *bh;
- pr_debug("affs_getzeroblk: %d\n", block);
- if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size) {
- bh = sb_getblk(sb, block);
- lock_buffer(bh);
- memset(bh->b_data, 0 , sb->s_blocksize);
- set_buffer_uptodate(bh);
- unlock_buffer(bh);
- return bh;
- }
- return NULL;
-}
-static inline struct buffer_head *
-affs_getemptyblk(struct super_block *sb, int block)
-{
- struct buffer_head *bh;
- pr_debug("affs_getemptyblk: %d\n", block);
- if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size) {
- bh = sb_getblk(sb, block);
- wait_on_buffer(bh);
- set_buffer_uptodate(bh);
- return bh;
- }
- return NULL;
-}
-static inline void
-affs_brelse(struct buffer_head *bh)
-{
- if (bh)
- pr_debug("affs_brelse: %lld\n", (long long) bh->b_blocknr);
- brelse(bh);
-}
-
-static inline void
-affs_adjust_checksum(struct buffer_head *bh, u32 val)
-{
- u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[5]);
- ((__be32 *)bh->b_data)[5] = cpu_to_be32(tmp - val);
-}
-static inline void
-affs_adjust_bitmapchecksum(struct buffer_head *bh, u32 val)
-{
- u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[0]);
- ((__be32 *)bh->b_data)[0] = cpu_to_be32(tmp - val);
-}
-
-static inline void
-affs_lock_link(struct inode *inode)
-{
- down(&AFFS_I(inode)->i_link_lock);
-}
-static inline void
-affs_unlock_link(struct inode *inode)
-{
- up(&AFFS_I(inode)->i_link_lock);
-}
-static inline void
-affs_lock_dir(struct inode *inode)
-{
- down(&AFFS_I(inode)->i_hash_lock);
-}
-static inline void
-affs_unlock_dir(struct inode *inode)
-{
- up(&AFFS_I(inode)->i_hash_lock);
-}
-static inline void
-affs_lock_ext(struct inode *inode)
-{
- down(&AFFS_I(inode)->i_ext_lock);
-}
-static inline void
-affs_unlock_ext(struct inode *inode)
-{
- up(&AFFS_I(inode)->i_ext_lock);
-}
diff --git a/ANDROID_3.4.5/fs/affs/amigaffs.c b/ANDROID_3.4.5/fs/affs/amigaffs.c
deleted file mode 100644
index 52a64076..00000000
--- a/ANDROID_3.4.5/fs/affs/amigaffs.c
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * linux/fs/affs/amigaffs.c
- *
- * (c) 1996 Hans-Joachim Widmaier - Rewritten
- *
- * (C) 1993 Ray Burr - Amiga FFS filesystem.
- *
- * Please send bug reports to: hjw@zvw.de
- */
-
-#include "affs.h"
-
-extern struct timezone sys_tz;
-
-static char ErrorBuffer[256];
-
-/*
- * Functions for accessing Amiga-FFS structures.
- */
-
-
-/* Insert a header block bh into the directory dir
- * caller must hold AFFS_DIR->i_hash_lock!
- */
-
-int
-affs_insert_hash(struct inode *dir, struct buffer_head *bh)
-{
- struct super_block *sb = dir->i_sb;
- struct buffer_head *dir_bh;
- u32 ino, hash_ino;
- int offset;
-
- ino = bh->b_blocknr;
- offset = affs_hash_name(sb, AFFS_TAIL(sb, bh)->name + 1, AFFS_TAIL(sb, bh)->name[0]);
-
- pr_debug("AFFS: insert_hash(dir=%u, ino=%d)\n", (u32)dir->i_ino, ino);
-
- dir_bh = affs_bread(sb, dir->i_ino);
- if (!dir_bh)
- return -EIO;
-
- hash_ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[offset]);
- while (hash_ino) {
- affs_brelse(dir_bh);
- dir_bh = affs_bread(sb, hash_ino);
- if (!dir_bh)
- return -EIO;
- hash_ino = be32_to_cpu(AFFS_TAIL(sb, dir_bh)->hash_chain);
- }
- AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
- AFFS_TAIL(sb, bh)->hash_chain = 0;
- affs_fix_checksum(sb, bh);
-
- if (dir->i_ino == dir_bh->b_blocknr)
- AFFS_HEAD(dir_bh)->table[offset] = cpu_to_be32(ino);
- else
- AFFS_TAIL(sb, dir_bh)->hash_chain = cpu_to_be32(ino);
-
- affs_adjust_checksum(dir_bh, ino);
- mark_buffer_dirty_inode(dir_bh, dir);
- affs_brelse(dir_bh);
-
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
- dir->i_version++;
- mark_inode_dirty(dir);
-
- return 0;
-}
-
-/* Remove a header block from its directory.
- * caller must hold AFFS_DIR->i_hash_lock!
- */
-
-int
-affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh)
-{
- struct super_block *sb;
- struct buffer_head *bh;
- u32 rem_ino, hash_ino;
- __be32 ino;
- int offset, retval;
-
- sb = dir->i_sb;
- rem_ino = rem_bh->b_blocknr;
- offset = affs_hash_name(sb, AFFS_TAIL(sb, rem_bh)->name+1, AFFS_TAIL(sb, rem_bh)->name[0]);
- pr_debug("AFFS: remove_hash(dir=%d, ino=%d, hashval=%d)\n", (u32)dir->i_ino, rem_ino, offset);
-
- bh = affs_bread(sb, dir->i_ino);
- if (!bh)
- return -EIO;
-
- retval = -ENOENT;
- hash_ino = be32_to_cpu(AFFS_HEAD(bh)->table[offset]);
- while (hash_ino) {
- if (hash_ino == rem_ino) {
- ino = AFFS_TAIL(sb, rem_bh)->hash_chain;
- if (dir->i_ino == bh->b_blocknr)
- AFFS_HEAD(bh)->table[offset] = ino;
- else
- AFFS_TAIL(sb, bh)->hash_chain = ino;
- affs_adjust_checksum(bh, be32_to_cpu(ino) - hash_ino);
- mark_buffer_dirty_inode(bh, dir);
- AFFS_TAIL(sb, rem_bh)->parent = 0;
- retval = 0;
- break;
- }
- affs_brelse(bh);
- bh = affs_bread(sb, hash_ino);
- if (!bh)
- return -EIO;
- hash_ino = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain);
- }
-
- affs_brelse(bh);
-
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
- dir->i_version++;
- mark_inode_dirty(dir);
-
- return retval;
-}
-
-static void
-affs_fix_dcache(struct dentry *dentry, u32 entry_ino)
-{
- struct inode *inode = dentry->d_inode;
- void *data = dentry->d_fsdata;
- struct list_head *head, *next;
-
- spin_lock(&inode->i_lock);
- head = &inode->i_dentry;
- next = head->next;
- while (next != head) {
- dentry = list_entry(next, struct dentry, d_alias);
- if (entry_ino == (u32)(long)dentry->d_fsdata) {
- dentry->d_fsdata = data;
- break;
- }
- next = next->next;
- }
- spin_unlock(&inode->i_lock);
-}
-
-
-/* Remove header from link chain */
-
-static int
-affs_remove_link(struct dentry *dentry)
-{
- struct inode *dir, *inode = dentry->d_inode;
- struct super_block *sb = inode->i_sb;
- struct buffer_head *bh = NULL, *link_bh = NULL;
- u32 link_ino, ino;
- int retval;
-
- pr_debug("AFFS: remove_link(key=%ld)\n", inode->i_ino);
- retval = -EIO;
- bh = affs_bread(sb, inode->i_ino);
- if (!bh)
- goto done;
-
- link_ino = (u32)(long)dentry->d_fsdata;
- if (inode->i_ino == link_ino) {
- /* we can't remove the head of the link, as its blocknr is still used as ino,
- * so we remove the block of the first link instead.
- */
- link_ino = be32_to_cpu(AFFS_TAIL(sb, bh)->link_chain);
- link_bh = affs_bread(sb, link_ino);
- if (!link_bh)
- goto done;
-
- dir = affs_iget(sb, be32_to_cpu(AFFS_TAIL(sb, link_bh)->parent));
- if (IS_ERR(dir)) {
- retval = PTR_ERR(dir);
- goto done;
- }
-
- affs_lock_dir(dir);
- affs_fix_dcache(dentry, link_ino);
- retval = affs_remove_hash(dir, link_bh);
- if (retval) {
- affs_unlock_dir(dir);
- goto done;
- }
- mark_buffer_dirty_inode(link_bh, inode);
-
- memcpy(AFFS_TAIL(sb, bh)->name, AFFS_TAIL(sb, link_bh)->name, 32);
- retval = affs_insert_hash(dir, bh);
- if (retval) {
- affs_unlock_dir(dir);
- goto done;
- }
- mark_buffer_dirty_inode(bh, inode);
-
- affs_unlock_dir(dir);
- iput(dir);
- } else {
- link_bh = affs_bread(sb, link_ino);
- if (!link_bh)
- goto done;
- }
-
- while ((ino = be32_to_cpu(AFFS_TAIL(sb, bh)->link_chain)) != 0) {
- if (ino == link_ino) {
- __be32 ino2 = AFFS_TAIL(sb, link_bh)->link_chain;
- AFFS_TAIL(sb, bh)->link_chain = ino2;
- affs_adjust_checksum(bh, be32_to_cpu(ino2) - link_ino);
- mark_buffer_dirty_inode(bh, inode);
- retval = 0;
- /* Fix the link count, if bh is a normal header block without links */
- switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
- case ST_LINKDIR:
- case ST_LINKFILE:
- break;
- default:
- if (!AFFS_TAIL(sb, bh)->link_chain)
- set_nlink(inode, 1);
- }
- affs_free_block(sb, link_ino);
- goto done;
- }
- affs_brelse(bh);
- bh = affs_bread(sb, ino);
- if (!bh)
- goto done;
- }
- retval = -ENOENT;
-done:
- affs_brelse(link_bh);
- affs_brelse(bh);
- return retval;
-}
-
-
-static int
-affs_empty_dir(struct inode *inode)
-{
- struct super_block *sb = inode->i_sb;
- struct buffer_head *bh;
- int retval, size;
-
- retval = -EIO;
- bh = affs_bread(sb, inode->i_ino);
- if (!bh)
- goto done;
-
- retval = -ENOTEMPTY;
- for (size = AFFS_SB(sb)->s_hashsize - 1; size >= 0; size--)
- if (AFFS_HEAD(bh)->table[size])
- goto not_empty;
- retval = 0;
-not_empty:
- affs_brelse(bh);
-done:
- return retval;
-}
-
-
-/* Remove a filesystem object. If the object to be removed has
- * links to it, one of the links must be changed to inherit
- * the file or directory. As above, any inode will do.
- * The buffer will not be freed. If the header is a link, the
- * block will be marked as free.
- * This function returns a negative error number in case of
- * an error, else 0 if the inode is to be deleted or 1 if not.
- */
-
-int
-affs_remove_header(struct dentry *dentry)
-{
- struct super_block *sb;
- struct inode *inode, *dir;
- struct buffer_head *bh = NULL;
- int retval;
-
- dir = dentry->d_parent->d_inode;
- sb = dir->i_sb;
-
- retval = -ENOENT;
- inode = dentry->d_inode;
- if (!inode)
- goto done;
-
- pr_debug("AFFS: remove_header(key=%ld)\n", inode->i_ino);
- retval = -EIO;
- bh = affs_bread(sb, (u32)(long)dentry->d_fsdata);
- if (!bh)
- goto done;
-
- affs_lock_link(inode);
- affs_lock_dir(dir);
- switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
- case ST_USERDIR:
- /* if we ever want to support links to dirs
- * i_hash_lock of the inode must only be
- * taken after some checks
- */
- affs_lock_dir(inode);
- retval = affs_empty_dir(inode);
- affs_unlock_dir(inode);
- if (retval)
- goto done_unlock;
- break;
- default:
- break;
- }
-
- retval = affs_remove_hash(dir, bh);
- if (retval)
- goto done_unlock;
- mark_buffer_dirty_inode(bh, inode);
-
- affs_unlock_dir(dir);
-
- if (inode->i_nlink > 1)
- retval = affs_remove_link(dentry);
- else
- clear_nlink(inode);
- affs_unlock_link(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
-
-done:
- affs_brelse(bh);
- return retval;
-
-done_unlock:
- affs_unlock_dir(dir);
- affs_unlock_link(inode);
- goto done;
-}
-
-/* Checksum a block, do various consistency checks and optionally return
- the blocks type number. DATA points to the block. If their pointers
- are non-null, *PTYPE and *STYPE are set to the primary and secondary
- block types respectively, *HASHSIZE is set to the size of the hashtable
- (which lets us calculate the block size).
- Returns non-zero if the block is not consistent. */
-
-u32
-affs_checksum_block(struct super_block *sb, struct buffer_head *bh)
-{
- __be32 *ptr = (__be32 *)bh->b_data;
- u32 sum;
- int bsize;
-
- sum = 0;
- for (bsize = sb->s_blocksize / sizeof(__be32); bsize > 0; bsize--)
- sum += be32_to_cpu(*ptr++);
- return sum;
-}
-
-/*
- * Calculate the checksum of a disk block and store it
- * at the indicated position.
- */
-
-void
-affs_fix_checksum(struct super_block *sb, struct buffer_head *bh)
-{
- int cnt = sb->s_blocksize / sizeof(__be32);
- __be32 *ptr = (__be32 *)bh->b_data;
- u32 checksum;
- __be32 *checksumptr;
-
- checksumptr = ptr + 5;
- *checksumptr = 0;
- for (checksum = 0; cnt > 0; ptr++, cnt--)
- checksum += be32_to_cpu(*ptr);
- *checksumptr = cpu_to_be32(-checksum);
-}
-
-void
-secs_to_datestamp(time_t secs, struct affs_date *ds)
-{
- u32 days;
- u32 minute;
-
- secs -= sys_tz.tz_minuteswest * 60 + ((8 * 365 + 2) * 24 * 60 * 60);
- if (secs < 0)
- secs = 0;
- days = secs / 86400;
- secs -= days * 86400;
- minute = secs / 60;
- secs -= minute * 60;
-
- ds->days = cpu_to_be32(days);
- ds->mins = cpu_to_be32(minute);
- ds->ticks = cpu_to_be32(secs * 50);
-}
-
-umode_t
-prot_to_mode(u32 prot)
-{
- umode_t mode = 0;
-
- if (!(prot & FIBF_NOWRITE))
- mode |= S_IWUSR;
- if (!(prot & FIBF_NOREAD))
- mode |= S_IRUSR;
- if (!(prot & FIBF_NOEXECUTE))
- mode |= S_IXUSR;
- if (prot & FIBF_GRP_WRITE)
- mode |= S_IWGRP;
- if (prot & FIBF_GRP_READ)
- mode |= S_IRGRP;
- if (prot & FIBF_GRP_EXECUTE)
- mode |= S_IXGRP;
- if (prot & FIBF_OTR_WRITE)
- mode |= S_IWOTH;
- if (prot & FIBF_OTR_READ)
- mode |= S_IROTH;
- if (prot & FIBF_OTR_EXECUTE)
- mode |= S_IXOTH;
-
- return mode;
-}
-
-void
-mode_to_prot(struct inode *inode)
-{
- u32 prot = AFFS_I(inode)->i_protect;
- umode_t mode = inode->i_mode;
-
- if (!(mode & S_IXUSR))
- prot |= FIBF_NOEXECUTE;
- if (!(mode & S_IRUSR))
- prot |= FIBF_NOREAD;
- if (!(mode & S_IWUSR))
- prot |= FIBF_NOWRITE;
- if (mode & S_IXGRP)
- prot |= FIBF_GRP_EXECUTE;
- if (mode & S_IRGRP)
- prot |= FIBF_GRP_READ;
- if (mode & S_IWGRP)
- prot |= FIBF_GRP_WRITE;
- if (mode & S_IXOTH)
- prot |= FIBF_OTR_EXECUTE;
- if (mode & S_IROTH)
- prot |= FIBF_OTR_READ;
- if (mode & S_IWOTH)
- prot |= FIBF_OTR_WRITE;
-
- AFFS_I(inode)->i_protect = prot;
-}
-
-void
-affs_error(struct super_block *sb, const char *function, const char *fmt, ...)
-{
- va_list args;
-
- va_start(args,fmt);
- vsnprintf(ErrorBuffer,sizeof(ErrorBuffer),fmt,args);
- va_end(args);
-
- printk(KERN_CRIT "AFFS error (device %s): %s(): %s\n", sb->s_id,
- function,ErrorBuffer);
- if (!(sb->s_flags & MS_RDONLY))
- printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n");
- sb->s_flags |= MS_RDONLY;
-}
-
-void
-affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
-{
- va_list args;
-
- va_start(args,fmt);
- vsnprintf(ErrorBuffer,sizeof(ErrorBuffer),fmt,args);
- va_end(args);
-
- printk(KERN_WARNING "AFFS warning (device %s): %s(): %s\n", sb->s_id,
- function,ErrorBuffer);
-}
-
-/* Check if the name is valid for a affs object. */
-
-int
-affs_check_name(const unsigned char *name, int len)
-{
- int i;
-
- if (len > 30)
-#ifdef AFFS_NO_TRUNCATE
- return -ENAMETOOLONG;
-#else
- len = 30;
-#endif
-
- for (i = 0; i < len; i++) {
- if (name[i] < ' ' || name[i] == ':'
- || (name[i] > 0x7e && name[i] < 0xa0))
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* This function copies name to bstr, with at most 30
- * characters length. The bstr will be prepended by
- * a length byte.
- * NOTE: The name will must be already checked by
- * affs_check_name()!
- */
-
-int
-affs_copy_name(unsigned char *bstr, struct dentry *dentry)
-{
- int len = min(dentry->d_name.len, 30u);
-
- *bstr++ = len;
- memcpy(bstr, dentry->d_name.name, len);
- return len;
-}
diff --git a/ANDROID_3.4.5/fs/affs/bitmap.c b/ANDROID_3.4.5/fs/affs/bitmap.c
deleted file mode 100644
index 3e262711..00000000
--- a/ANDROID_3.4.5/fs/affs/bitmap.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * linux/fs/affs/bitmap.c
- *
- * (c) 1996 Hans-Joachim Widmaier
- *
- * bitmap.c contains the code that handles all bitmap related stuff -
- * block allocation, deallocation, calculation of free space.
- */
-
-#include <linux/slab.h>
-#include "affs.h"
-
-/* This is, of course, shamelessly stolen from fs/minix */
-
-static const int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
-
-static u32
-affs_count_free_bits(u32 blocksize, const void *data)
-{
- const u32 *map;
- u32 free;
- u32 tmp;
-
- map = data;
- free = 0;
- for (blocksize /= 4; blocksize > 0; blocksize--) {
- tmp = *map++;
- while (tmp) {
- free += nibblemap[tmp & 0xf];
- tmp >>= 4;
- }
- }
-
- return free;
-}
-
-u32
-affs_count_free_blocks(struct super_block *sb)
-{
- struct affs_bm_info *bm;
- u32 free;
- int i;
-
- pr_debug("AFFS: count_free_blocks()\n");
-
- if (sb->s_flags & MS_RDONLY)
- return 0;
-
- mutex_lock(&AFFS_SB(sb)->s_bmlock);
-
- bm = AFFS_SB(sb)->s_bitmap;
- free = 0;
- for (i = AFFS_SB(sb)->s_bmap_count; i > 0; bm++, i--)
- free += bm->bm_free;
-
- mutex_unlock(&AFFS_SB(sb)->s_bmlock);
-
- return free;
-}
-
-void
-affs_free_block(struct super_block *sb, u32 block)
-{
- struct affs_sb_info *sbi = AFFS_SB(sb);
- struct affs_bm_info *bm;
- struct buffer_head *bh;
- u32 blk, bmap, bit, mask, tmp;
- __be32 *data;
-
- pr_debug("AFFS: free_block(%u)\n", block);
-
- if (block > sbi->s_partition_size)
- goto err_range;
-
- blk = block - sbi->s_reserved;
- bmap = blk / sbi->s_bmap_bits;
- bit = blk % sbi->s_bmap_bits;
- bm = &sbi->s_bitmap[bmap];
-
- mutex_lock(&sbi->s_bmlock);
-
- bh = sbi->s_bmap_bh;
- if (sbi->s_last_bmap != bmap) {
- affs_brelse(bh);
- bh = affs_bread(sb, bm->bm_key);
- if (!bh)
- goto err_bh_read;
- sbi->s_bmap_bh = bh;
- sbi->s_last_bmap = bmap;
- }
-
- mask = 1 << (bit & 31);
- data = (__be32 *)bh->b_data + bit / 32 + 1;
-
- /* mark block free */
- tmp = be32_to_cpu(*data);
- if (tmp & mask)
- goto err_free;
- *data = cpu_to_be32(tmp | mask);
-
- /* fix checksum */
- tmp = be32_to_cpu(*(__be32 *)bh->b_data);
- *(__be32 *)bh->b_data = cpu_to_be32(tmp - mask);
-
- mark_buffer_dirty(bh);
- sb->s_dirt = 1;
- bm->bm_free++;
-
- mutex_unlock(&sbi->s_bmlock);
- return;
-
-err_free:
- affs_warning(sb,"affs_free_block","Trying to free block %u which is already free", block);
- mutex_unlock(&sbi->s_bmlock);
- return;
-
-err_bh_read:
- affs_error(sb,"affs_free_block","Cannot read bitmap block %u", bm->bm_key);
- sbi->s_bmap_bh = NULL;
- sbi->s_last_bmap = ~0;
- mutex_unlock(&sbi->s_bmlock);
- return;
-
-err_range:
- affs_error(sb, "affs_free_block","Block %u outside partition", block);
- return;
-}
-
-/*
- * Allocate a block in the given allocation zone.
- * Since we have to byte-swap the bitmap on little-endian
- * machines, this is rather expensive. Therefore we will
- * preallocate up to 16 blocks from the same word, if
- * possible. We are not doing preallocations in the
- * header zone, though.
- */
-
-u32
-affs_alloc_block(struct inode *inode, u32 goal)
-{
- struct super_block *sb;
- struct affs_sb_info *sbi;
- struct affs_bm_info *bm;
- struct buffer_head *bh;
- __be32 *data, *enddata;
- u32 blk, bmap, bit, mask, mask2, tmp;
- int i;
-
- sb = inode->i_sb;
- sbi = AFFS_SB(sb);
-
- pr_debug("AFFS: balloc(inode=%lu,goal=%u): ", inode->i_ino, goal);
-
- if (AFFS_I(inode)->i_pa_cnt) {
- pr_debug("%d\n", AFFS_I(inode)->i_lastalloc+1);
- AFFS_I(inode)->i_pa_cnt--;
- return ++AFFS_I(inode)->i_lastalloc;
- }
-
- if (!goal || goal > sbi->s_partition_size) {
- if (goal)
- affs_warning(sb, "affs_balloc", "invalid goal %d", goal);
- //if (!AFFS_I(inode)->i_last_block)
- // affs_warning(sb, "affs_balloc", "no last alloc block");
- goal = sbi->s_reserved;
- }
-
- blk = goal - sbi->s_reserved;
- bmap = blk / sbi->s_bmap_bits;
- bm = &sbi->s_bitmap[bmap];
-
- mutex_lock(&sbi->s_bmlock);
-
- if (bm->bm_free)
- goto find_bmap_bit;
-
-find_bmap:
- /* search for the next bmap buffer with free bits */
- i = sbi->s_bmap_count;
- do {
- if (--i < 0)
- goto err_full;
- bmap++;
- bm++;
- if (bmap < sbi->s_bmap_count)
- continue;
- /* restart search at zero */
- bmap = 0;
- bm = sbi->s_bitmap;
- } while (!bm->bm_free);
- blk = bmap * sbi->s_bmap_bits;
-
-find_bmap_bit:
-
- bh = sbi->s_bmap_bh;
- if (sbi->s_last_bmap != bmap) {
- affs_brelse(bh);
- bh = affs_bread(sb, bm->bm_key);
- if (!bh)
- goto err_bh_read;
- sbi->s_bmap_bh = bh;
- sbi->s_last_bmap = bmap;
- }
-
- /* find an unused block in this bitmap block */
- bit = blk % sbi->s_bmap_bits;
- data = (__be32 *)bh->b_data + bit / 32 + 1;
- enddata = (__be32 *)((u8 *)bh->b_data + sb->s_blocksize);
- mask = ~0UL << (bit & 31);
- blk &= ~31UL;
-
- tmp = be32_to_cpu(*data);
- if (tmp & mask)
- goto find_bit;
-
- /* scan the rest of the buffer */
- do {
- blk += 32;
- if (++data >= enddata)
- /* didn't find something, can only happen
- * if scan didn't start at 0, try next bmap
- */
- goto find_bmap;
- } while (!*data);
- tmp = be32_to_cpu(*data);
- mask = ~0;
-
-find_bit:
- /* finally look for a free bit in the word */
- bit = ffs(tmp & mask) - 1;
- blk += bit + sbi->s_reserved;
- mask2 = mask = 1 << (bit & 31);
- AFFS_I(inode)->i_lastalloc = blk;
-
- /* prealloc as much as possible within this word */
- while ((mask2 <<= 1)) {
- if (!(tmp & mask2))
- break;
- AFFS_I(inode)->i_pa_cnt++;
- mask |= mask2;
- }
- bm->bm_free -= AFFS_I(inode)->i_pa_cnt + 1;
-
- *data = cpu_to_be32(tmp & ~mask);
-
- /* fix checksum */
- tmp = be32_to_cpu(*(__be32 *)bh->b_data);
- *(__be32 *)bh->b_data = cpu_to_be32(tmp + mask);
-
- mark_buffer_dirty(bh);
- sb->s_dirt = 1;
-
- mutex_unlock(&sbi->s_bmlock);
-
- pr_debug("%d\n", blk);
- return blk;
-
-err_bh_read:
- affs_error(sb,"affs_read_block","Cannot read bitmap block %u", bm->bm_key);
- sbi->s_bmap_bh = NULL;
- sbi->s_last_bmap = ~0;
-err_full:
- mutex_unlock(&sbi->s_bmlock);
- pr_debug("failed\n");
- return 0;
-}
-
-int affs_init_bitmap(struct super_block *sb, int *flags)
-{
- struct affs_bm_info *bm;
- struct buffer_head *bmap_bh = NULL, *bh = NULL;
- __be32 *bmap_blk;
- u32 size, blk, end, offset, mask;
- int i, res = 0;
- struct affs_sb_info *sbi = AFFS_SB(sb);
-
- if (*flags & MS_RDONLY)
- return 0;
-
- if (!AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag) {
- printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n",
- sb->s_id);
- *flags |= MS_RDONLY;
- return 0;
- }
-
- sbi->s_last_bmap = ~0;
- sbi->s_bmap_bh = NULL;
- sbi->s_bmap_bits = sb->s_blocksize * 8 - 32;
- sbi->s_bmap_count = (sbi->s_partition_size - sbi->s_reserved +
- sbi->s_bmap_bits - 1) / sbi->s_bmap_bits;
- size = sbi->s_bmap_count * sizeof(*bm);
- bm = sbi->s_bitmap = kzalloc(size, GFP_KERNEL);
- if (!sbi->s_bitmap) {
- printk(KERN_ERR "AFFS: Bitmap allocation failed\n");
- return -ENOMEM;
- }
-
- bmap_blk = (__be32 *)sbi->s_root_bh->b_data;
- blk = sb->s_blocksize / 4 - 49;
- end = blk + 25;
-
- for (i = sbi->s_bmap_count; i > 0; bm++, i--) {
- affs_brelse(bh);
-
- bm->bm_key = be32_to_cpu(bmap_blk[blk]);
- bh = affs_bread(sb, bm->bm_key);
- if (!bh) {
- printk(KERN_ERR "AFFS: Cannot read bitmap\n");
- res = -EIO;
- goto out;
- }
- if (affs_checksum_block(sb, bh)) {
- printk(KERN_WARNING "AFFS: Bitmap %u invalid - mounting %s read only.\n",
- bm->bm_key, sb->s_id);
- *flags |= MS_RDONLY;
- goto out;
- }
- pr_debug("AFFS: read bitmap block %d: %d\n", blk, bm->bm_key);
- bm->bm_free = affs_count_free_bits(sb->s_blocksize - 4, bh->b_data + 4);
-
- /* Don't try read the extension if this is the last block,
- * but we also need the right bm pointer below
- */
- if (++blk < end || i == 1)
- continue;
- if (bmap_bh)
- affs_brelse(bmap_bh);
- bmap_bh = affs_bread(sb, be32_to_cpu(bmap_blk[blk]));
- if (!bmap_bh) {
- printk(KERN_ERR "AFFS: Cannot read bitmap extension\n");
- res = -EIO;
- goto out;
- }
- bmap_blk = (__be32 *)bmap_bh->b_data;
- blk = 0;
- end = sb->s_blocksize / 4 - 1;
- }
-
- offset = (sbi->s_partition_size - sbi->s_reserved) % sbi->s_bmap_bits;
- mask = ~(0xFFFFFFFFU << (offset & 31));
- pr_debug("last word: %d %d %d\n", offset, offset / 32 + 1, mask);
- offset = offset / 32 + 1;
-
- if (mask) {
- u32 old, new;
-
- /* Mark unused bits in the last word as allocated */
- old = be32_to_cpu(((__be32 *)bh->b_data)[offset]);
- new = old & mask;
- //if (old != new) {
- ((__be32 *)bh->b_data)[offset] = cpu_to_be32(new);
- /* fix checksum */
- //new -= old;
- //old = be32_to_cpu(*(__be32 *)bh->b_data);
- //*(__be32 *)bh->b_data = cpu_to_be32(old - new);
- //mark_buffer_dirty(bh);
- //}
- /* correct offset for the bitmap count below */
- //offset++;
- }
- while (++offset < sb->s_blocksize / 4)
- ((__be32 *)bh->b_data)[offset] = 0;
- ((__be32 *)bh->b_data)[0] = 0;
- ((__be32 *)bh->b_data)[0] = cpu_to_be32(-affs_checksum_block(sb, bh));
- mark_buffer_dirty(bh);
-
- /* recalculate bitmap count for last block */
- bm--;
- bm->bm_free = affs_count_free_bits(sb->s_blocksize - 4, bh->b_data + 4);
-
-out:
- affs_brelse(bh);
- affs_brelse(bmap_bh);
- return res;
-}
-
-void affs_free_bitmap(struct super_block *sb)
-{
- struct affs_sb_info *sbi = AFFS_SB(sb);
-
- if (!sbi->s_bitmap)
- return;
-
- affs_brelse(sbi->s_bmap_bh);
- sbi->s_bmap_bh = NULL;
- sbi->s_last_bmap = ~0;
- kfree(sbi->s_bitmap);
- sbi->s_bitmap = NULL;
-}
diff --git a/ANDROID_3.4.5/fs/affs/dir.c b/ANDROID_3.4.5/fs/affs/dir.c
deleted file mode 100644
index 8ca8f3a5..00000000
--- a/ANDROID_3.4.5/fs/affs/dir.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * linux/fs/affs/dir.c
- *
- * (c) 1996 Hans-Joachim Widmaier - Rewritten
- *
- * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
- *
- * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem.
- *
- * (C) 1991 Linus Torvalds - minix filesystem
- *
- * affs directory handling functions
- *
- */
-
-#include "affs.h"
-
-static int affs_readdir(struct file *, void *, filldir_t);
-
-const struct file_operations affs_dir_operations = {
- .read = generic_read_dir,
- .llseek = generic_file_llseek,
- .readdir = affs_readdir,
- .fsync = affs_file_fsync,
-};
-
-/*
- * directories can handle most operations...
- */
-const struct inode_operations affs_dir_inode_operations = {
- .create = affs_create,
- .lookup = affs_lookup,
- .link = affs_link,
- .unlink = affs_unlink,
- .symlink = affs_symlink,
- .mkdir = affs_mkdir,
- .rmdir = affs_rmdir,
- .rename = affs_rename,
- .setattr = affs_notify_change,
-};
-
-static int
-affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
-{
- struct inode *inode = filp->f_path.dentry->d_inode;
- struct super_block *sb = inode->i_sb;
- struct buffer_head *dir_bh;
- struct buffer_head *fh_bh;
- unsigned char *name;
- int namelen;
- u32 i;
- int hash_pos;
- int chain_pos;
- u32 f_pos;
- u32 ino;
- int stored;
- int res;
-
- pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)filp->f_pos);
-
- stored = 0;
- res = -EIO;
- dir_bh = NULL;
- fh_bh = NULL;
- f_pos = filp->f_pos;
-
- if (f_pos == 0) {
- filp->private_data = (void *)0;
- if (filldir(dirent, ".", 1, f_pos, inode->i_ino, DT_DIR) < 0)
- return 0;
- filp->f_pos = f_pos = 1;
- stored++;
- }
- if (f_pos == 1) {
- if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_path.dentry), DT_DIR) < 0)
- return stored;
- filp->f_pos = f_pos = 2;
- stored++;
- }
-
- affs_lock_dir(inode);
- chain_pos = (f_pos - 2) & 0xffff;
- hash_pos = (f_pos - 2) >> 16;
- if (chain_pos == 0xffff) {
- affs_warning(sb, "readdir", "More than 65535 entries in chain");
- chain_pos = 0;
- hash_pos++;
- filp->f_pos = ((hash_pos << 16) | chain_pos) + 2;
- }
- dir_bh = affs_bread(sb, inode->i_ino);
- if (!dir_bh)
- goto readdir_out;
-
- /* If the directory hasn't changed since the last call to readdir(),
- * we can jump directly to where we left off.
- */
- ino = (u32)(long)filp->private_data;
- if (ino && filp->f_version == inode->i_version) {
- pr_debug("AFFS: readdir() left off=%d\n", ino);
- goto inside;
- }
-
- ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
- for (i = 0; ino && i < chain_pos; i++) {
- fh_bh = affs_bread(sb, ino);
- if (!fh_bh) {
- affs_error(sb, "readdir","Cannot read block %d", i);
- goto readdir_out;
- }
- ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
- affs_brelse(fh_bh);
- fh_bh = NULL;
- }
- if (ino)
- goto inside;
- hash_pos++;
-
- for (; hash_pos < AFFS_SB(sb)->s_hashsize; hash_pos++) {
- ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
- if (!ino)
- continue;
- f_pos = (hash_pos << 16) + 2;
-inside:
- do {
- fh_bh = affs_bread(sb, ino);
- if (!fh_bh) {
- affs_error(sb, "readdir","Cannot read block %d", ino);
- goto readdir_done;
- }
-
- namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
- name = AFFS_TAIL(sb, fh_bh)->name + 1;
- pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n",
- namelen, name, ino, hash_pos, f_pos);
- if (filldir(dirent, name, namelen, f_pos, ino, DT_UNKNOWN) < 0)
- goto readdir_done;
- stored++;
- f_pos++;
- ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
- affs_brelse(fh_bh);
- fh_bh = NULL;
- } while (ino);
- }
-readdir_done:
- filp->f_pos = f_pos;
- filp->f_version = inode->i_version;
- filp->private_data = (void *)(long)ino;
- res = stored;
-
-readdir_out:
- affs_brelse(dir_bh);
- affs_brelse(fh_bh);
- affs_unlock_dir(inode);
- pr_debug("AFFS: readdir()=%d\n", stored);
- return res;
-}
diff --git a/ANDROID_3.4.5/fs/affs/file.c b/ANDROID_3.4.5/fs/affs/file.c
deleted file mode 100644
index 2f4c935c..00000000
--- a/ANDROID_3.4.5/fs/affs/file.c
+++ /dev/null
@@ -1,942 +0,0 @@
-/*
- * linux/fs/affs/file.c
- *
- * (c) 1996 Hans-Joachim Widmaier - Rewritten
- *
- * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
- *
- * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem.
- *
- * (C) 1991 Linus Torvalds - minix filesystem
- *
- * affs regular file handling primitives
- */
-
-#include "affs.h"
-
-#if PAGE_SIZE < 4096
-#error PAGE_SIZE must be at least 4096
-#endif
-
-static int affs_grow_extcache(struct inode *inode, u32 lc_idx);
-static struct buffer_head *affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext);
-static inline struct buffer_head *affs_get_extblock(struct inode *inode, u32 ext);
-static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
-static int affs_file_open(struct inode *inode, struct file *filp);
-static int affs_file_release(struct inode *inode, struct file *filp);
-
-const struct file_operations affs_file_operations = {
- .llseek = generic_file_llseek,
- .read = do_sync_read,
- .aio_read = generic_file_aio_read,
- .write = do_sync_write,
- .aio_write = generic_file_aio_write,
- .mmap = generic_file_mmap,
- .open = affs_file_open,
- .release = affs_file_release,
- .fsync = affs_file_fsync,
- .splice_read = generic_file_splice_read,
-};
-
-const struct inode_operations affs_file_inode_operations = {
- .truncate = affs_truncate,
- .setattr = affs_notify_change,
-};
-
-static int
-affs_file_open(struct inode *inode, struct file *filp)
-{
- pr_debug("AFFS: open(%lu,%d)\n",
- inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
- atomic_inc(&AFFS_I(inode)->i_opencnt);
- return 0;
-}
-
-static int
-affs_file_release(struct inode *inode, struct file *filp)
-{
- pr_debug("AFFS: release(%lu, %d)\n",
- inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
-
- if (atomic_dec_and_test(&AFFS_I(inode)->i_opencnt)) {
- mutex_lock(&inode->i_mutex);
- if (inode->i_size != AFFS_I(inode)->mmu_private)
- affs_truncate(inode);
- affs_free_prealloc(inode);
- mutex_unlock(&inode->i_mutex);
- }
-
- return 0;
-}
-
-static int
-affs_grow_extcache(struct inode *inode, u32 lc_idx)
-{
- struct super_block *sb = inode->i_sb;
- struct buffer_head *bh;
- u32 lc_max;
- int i, j, key;
-
- if (!AFFS_I(inode)->i_lc) {
- char *ptr = (char *)get_zeroed_page(GFP_NOFS);
- if (!ptr)
- return -ENOMEM;
- AFFS_I(inode)->i_lc = (u32 *)ptr;
- AFFS_I(inode)->i_ac = (struct affs_ext_key *)(ptr + AFFS_CACHE_SIZE / 2);
- }
-
- lc_max = AFFS_LC_SIZE << AFFS_I(inode)->i_lc_shift;
-
- if (AFFS_I(inode)->i_extcnt > lc_max) {
- u32 lc_shift, lc_mask, tmp, off;
-
- /* need to recalculate linear cache, start from old size */
- lc_shift = AFFS_I(inode)->i_lc_shift;
- tmp = (AFFS_I(inode)->i_extcnt / AFFS_LC_SIZE) >> lc_shift;
- for (; tmp; tmp >>= 1)
- lc_shift++;
- lc_mask = (1 << lc_shift) - 1;
-
- /* fix idx and old size to new shift */
- lc_idx >>= (lc_shift - AFFS_I(inode)->i_lc_shift);
- AFFS_I(inode)->i_lc_size >>= (lc_shift - AFFS_I(inode)->i_lc_shift);
-
- /* first shrink old cache to make more space */
- off = 1 << (lc_shift - AFFS_I(inode)->i_lc_shift);
- for (i = 1, j = off; j < AFFS_LC_SIZE; i++, j += off)
- AFFS_I(inode)->i_ac[i] = AFFS_I(inode)->i_ac[j];
-
- AFFS_I(inode)->i_lc_shift = lc_shift;
- AFFS_I(inode)->i_lc_mask = lc_mask;
- }
-
- /* fill cache to the needed index */
- i = AFFS_I(inode)->i_lc_size;
- AFFS_I(inode)->i_lc_size = lc_idx + 1;
- for (; i <= lc_idx; i++) {
- if (!i) {
- AFFS_I(inode)->i_lc[0] = inode->i_ino;
- continue;
- }
- key = AFFS_I(inode)->i_lc[i - 1];
- j = AFFS_I(inode)->i_lc_mask + 1;
- // unlock cache
- for (; j > 0; j--) {
- bh = affs_bread(sb, key);
- if (!bh)
- goto err;
- key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
- affs_brelse(bh);
- }
- // lock cache
- AFFS_I(inode)->i_lc[i] = key;
- }
-
- return 0;
-
-err:
- // lock cache
- return -EIO;
-}
-
-static struct buffer_head *
-affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext)
-{
- struct super_block *sb = inode->i_sb;
- struct buffer_head *new_bh;
- u32 blocknr, tmp;
-
- blocknr = affs_alloc_block(inode, bh->b_blocknr);
- if (!blocknr)
- return ERR_PTR(-ENOSPC);
-
- new_bh = affs_getzeroblk(sb, blocknr);
- if (!new_bh) {
- affs_free_block(sb, blocknr);
- return ERR_PTR(-EIO);
- }
-
- AFFS_HEAD(new_bh)->ptype = cpu_to_be32(T_LIST);
- AFFS_HEAD(new_bh)->key = cpu_to_be32(blocknr);
- AFFS_TAIL(sb, new_bh)->stype = cpu_to_be32(ST_FILE);
- AFFS_TAIL(sb, new_bh)->parent = cpu_to_be32(inode->i_ino);
- affs_fix_checksum(sb, new_bh);
-
- mark_buffer_dirty_inode(new_bh, inode);
-
- tmp = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
- if (tmp)
- affs_warning(sb, "alloc_ext", "previous extension set (%x)", tmp);
- AFFS_TAIL(sb, bh)->extension = cpu_to_be32(blocknr);
- affs_adjust_checksum(bh, blocknr - tmp);
- mark_buffer_dirty_inode(bh, inode);
-
- AFFS_I(inode)->i_extcnt++;
- mark_inode_dirty(inode);
-
- return new_bh;
-}
-
-static inline struct buffer_head *
-affs_get_extblock(struct inode *inode, u32 ext)
-{
- /* inline the simplest case: same extended block as last time */
- struct buffer_head *bh = AFFS_I(inode)->i_ext_bh;
- if (ext == AFFS_I(inode)->i_ext_last)
- get_bh(bh);
- else
- /* we have to do more (not inlined) */
- bh = affs_get_extblock_slow(inode, ext);
-
- return bh;
-}
-
-static struct buffer_head *
-affs_get_extblock_slow(struct inode *inode, u32 ext)
-{
- struct super_block *sb = inode->i_sb;
- struct buffer_head *bh;
- u32 ext_key;
- u32 lc_idx, lc_off, ac_idx;
- u32 tmp, idx;
-
- if (ext == AFFS_I(inode)->i_ext_last + 1) {
- /* read the next extended block from the current one */
- bh = AFFS_I(inode)->i_ext_bh;
- ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
- if (ext < AFFS_I(inode)->i_extcnt)
- goto read_ext;
- if (ext > AFFS_I(inode)->i_extcnt)
- BUG();
- bh = affs_alloc_extblock(inode, bh, ext);
- if (IS_ERR(bh))
- return bh;
- goto store_ext;
- }
-
- if (ext == 0) {
- /* we seek back to the file header block */
- ext_key = inode->i_ino;
- goto read_ext;
- }
-
- if (ext >= AFFS_I(inode)->i_extcnt) {
- struct buffer_head *prev_bh;
-
- /* allocate a new extended block */
- if (ext > AFFS_I(inode)->i_extcnt)
- BUG();
-
- /* get previous extended block */
- prev_bh = affs_get_extblock(inode, ext - 1);
- if (IS_ERR(prev_bh))
- return prev_bh;
- bh = affs_alloc_extblock(inode, prev_bh, ext);
- affs_brelse(prev_bh);
- if (IS_ERR(bh))
- return bh;
- goto store_ext;
- }
-
-again:
- /* check if there is an extended cache and whether it's large enough */
- lc_idx = ext >> AFFS_I(inode)->i_lc_shift;
- lc_off = ext & AFFS_I(inode)->i_lc_mask;
-
- if (lc_idx >= AFFS_I(inode)->i_lc_size) {
- int err;
-
- err = affs_grow_extcache(inode, lc_idx);
- if (err)
- return ERR_PTR(err);
- goto again;
- }
-
- /* every n'th key we find in the linear cache */
- if (!lc_off) {
- ext_key = AFFS_I(inode)->i_lc[lc_idx];
- goto read_ext;
- }
-
- /* maybe it's still in the associative cache */
- ac_idx = (ext - lc_idx - 1) & AFFS_AC_MASK;
- if (AFFS_I(inode)->i_ac[ac_idx].ext == ext) {
- ext_key = AFFS_I(inode)->i_ac[ac_idx].key;
- goto read_ext;
- }
-
- /* try to find one of the previous extended blocks */
- tmp = ext;
- idx = ac_idx;
- while (--tmp, --lc_off > 0) {
- idx = (idx - 1) & AFFS_AC_MASK;
- if (AFFS_I(inode)->i_ac[idx].ext == tmp) {
- ext_key = AFFS_I(inode)->i_ac[idx].key;
- goto find_ext;
- }
- }
-
- /* fall back to the linear cache */
- ext_key = AFFS_I(inode)->i_lc[lc_idx];
-find_ext:
- /* read all extended blocks until we find the one we need */
- //unlock cache
- do {
- bh = affs_bread(sb, ext_key);
- if (!bh)
- goto err_bread;
- ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
- affs_brelse(bh);
- tmp++;
- } while (tmp < ext);
- //lock cache
-
- /* store it in the associative cache */
- // recalculate ac_idx?
- AFFS_I(inode)->i_ac[ac_idx].ext = ext;
- AFFS_I(inode)->i_ac[ac_idx].key = ext_key;
-
-read_ext:
- /* finally read the right extended block */
- //unlock cache
- bh = affs_bread(sb, ext_key);
- if (!bh)
- goto err_bread;
- //lock cache
-
-store_ext:
- /* release old cached extended block and store the new one */
- affs_brelse(AFFS_I(inode)->i_ext_bh);
- AFFS_I(inode)->i_ext_last = ext;
- AFFS_I(inode)->i_ext_bh = bh;
- get_bh(bh);
-
- return bh;
-
-err_bread:
- affs_brelse(bh);
- return ERR_PTR(-EIO);
-}
-
-static int
-affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create)
-{
- struct super_block *sb = inode->i_sb;
- struct buffer_head *ext_bh;
- u32 ext;
-
- pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block);
-
- BUG_ON(block > (sector_t)0x7fffffffUL);
-
- if (block >= AFFS_I(inode)->i_blkcnt) {
- if (block > AFFS_I(inode)->i_blkcnt || !create)
- goto err_big;
- } else
- create = 0;
-
- //lock cache
- affs_lock_ext(inode);
-
- ext = (u32)block / AFFS_SB(sb)->s_hashsize;
- block -= ext * AFFS_SB(sb)->s_hashsize;
- ext_bh = affs_get_extblock(inode, ext);
- if (IS_ERR(ext_bh))
- goto err_ext;
- map_bh(bh_result, sb, (sector_t)be32_to_cpu(AFFS_BLOCK(sb, ext_bh, block)));
-
- if (create) {
- u32 blocknr = affs_alloc_block(inode, ext_bh->b_blocknr);
- if (!blocknr)
- goto err_alloc;
- set_buffer_new(bh_result);
- AFFS_I(inode)->mmu_private += AFFS_SB(sb)->s_data_blksize;
- AFFS_I(inode)->i_blkcnt++;
-
- /* store new block */
- if (bh_result->b_blocknr)
- affs_warning(sb, "get_block", "block already set (%x)", bh_result->b_blocknr);
- AFFS_BLOCK(sb, ext_bh, block) = cpu_to_be32(blocknr);
- AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(block + 1);
- affs_adjust_checksum(ext_bh, blocknr - bh_result->b_blocknr + 1);
- bh_result->b_blocknr = blocknr;
-
- if (!block) {
- /* insert first block into header block */
- u32 tmp = be32_to_cpu(AFFS_HEAD(ext_bh)->first_data);
- if (tmp)
- affs_warning(sb, "get_block", "first block already set (%d)", tmp);
- AFFS_HEAD(ext_bh)->first_data = cpu_to_be32(blocknr);
- affs_adjust_checksum(ext_bh, blocknr - tmp);
- }
- }
-
- affs_brelse(ext_bh);
- //unlock cache
- affs_unlock_ext(inode);
- return 0;
-
-err_big:
- affs_error(inode->i_sb,"get_block","strange block request %d", block);
- return -EIO;
-err_ext:
- // unlock cache
- affs_unlock_ext(inode);
- return PTR_ERR(ext_bh);
-err_alloc:
- brelse(ext_bh);
- clear_buffer_mapped(bh_result);
- bh_result->b_bdev = NULL;
- // unlock cache
- affs_unlock_ext(inode);
- return -ENOSPC;
-}
-
-static int affs_writepage(struct page *page, struct writeback_control *wbc)
-{
- return block_write_full_page(page, affs_get_block, wbc);
-}
-
-static int affs_readpage(struct file *file, struct page *page)
-{
- return block_read_full_page(page, affs_get_block);
-}
-
-static int affs_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata)
-{
- int ret;
-
- *pagep = NULL;
- ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
- affs_get_block,
- &AFFS_I(mapping->host)->mmu_private);
- if (unlikely(ret)) {
- loff_t isize = mapping->host->i_size;
- if (pos + len > isize)
- vmtruncate(mapping->host, isize);
- }
-
- return ret;
-}
-
-static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
-{
- return generic_block_bmap(mapping,block,affs_get_block);
-}
-
-const struct address_space_operations affs_aops = {
- .readpage = affs_readpage,
- .writepage = affs_writepage,
- .write_begin = affs_write_begin,
- .write_end = generic_write_end,
- .bmap = _affs_bmap
-};
-
-static inline struct buffer_head *
-affs_bread_ino(struct inode *inode, int block, int create)
-{
- struct buffer_head *bh, tmp_bh;
- int err;
-
- tmp_bh.b_state = 0;
- err = affs_get_block(inode, block, &tmp_bh, create);
- if (!err) {
- bh = affs_bread(inode->i_sb, tmp_bh.b_blocknr);
- if (bh) {
- bh->b_state |= tmp_bh.b_state;
- return bh;
- }
- err = -EIO;
- }
- return ERR_PTR(err);
-}
-
-static inline struct buffer_head *
-affs_getzeroblk_ino(struct inode *inode, int block)
-{
- struct buffer_head *bh, tmp_bh;
- int err;
-
- tmp_bh.b_state = 0;
- err = affs_get_block(inode, block, &tmp_bh, 1);
- if (!err) {
- bh = affs_getzeroblk(inode->i_sb, tmp_bh.b_blocknr);
- if (bh) {
- bh->b_state |= tmp_bh.b_state;
- return bh;
- }
- err = -EIO;
- }
- return ERR_PTR(err);
-}
-
-static inline struct buffer_head *
-affs_getemptyblk_ino(struct inode *inode, int block)
-{
- struct buffer_head *bh, tmp_bh;
- int err;
-
- tmp_bh.b_state = 0;
- err = affs_get_block(inode, block, &tmp_bh, 1);
- if (!err) {
- bh = affs_getemptyblk(inode->i_sb, tmp_bh.b_blocknr);
- if (bh) {
- bh->b_state |= tmp_bh.b_state;
- return bh;
- }
- err = -EIO;
- }
- return ERR_PTR(err);
-}
-
-static int
-affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
-{
- struct inode *inode = page->mapping->host;
- struct super_block *sb = inode->i_sb;
- struct buffer_head *bh;
- char *data;
- u32 bidx, boff, bsize;
- u32 tmp;
-
- pr_debug("AFFS: read_page(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);
- BUG_ON(from > to || to > PAGE_CACHE_SIZE);
- kmap(page);
- data = page_address(page);
- bsize = AFFS_SB(sb)->s_data_blksize;
- tmp = (page->index << PAGE_CACHE_SHIFT) + from;
- bidx = tmp / bsize;
- boff = tmp % bsize;
-
- while (from < to) {
- bh = affs_bread_ino(inode, bidx, 0);
- if (IS_ERR(bh))
- return PTR_ERR(bh);
- tmp = min(bsize - boff, to - from);
- BUG_ON(from + tmp > to || tmp > bsize);
- memcpy(data + from, AFFS_DATA(bh) + boff, tmp);
- affs_brelse(bh);
- bidx++;
- from += tmp;
- boff = 0;
- }
- flush_dcache_page(page);
- kunmap(page);
- return 0;
-}
-
-static int
-affs_extent_file_ofs(struct inode *inode, u32 newsize)
-{
- struct super_block *sb = inode->i_sb;
- struct buffer_head *bh, *prev_bh;
- u32 bidx, boff;
- u32 size, bsize;
- u32 tmp;
-
- pr_debug("AFFS: extent_file(%u, %d)\n", (u32)inode->i_ino, newsize);
- bsize = AFFS_SB(sb)->s_data_blksize;
- bh = NULL;
- size = AFFS_I(inode)->mmu_private;
- bidx = size / bsize;
- boff = size % bsize;
- if (boff) {
- bh = affs_bread_ino(inode, bidx, 0);
- if (IS_ERR(bh))
- return PTR_ERR(bh);
- tmp = min(bsize - boff, newsize - size);
- BUG_ON(boff + tmp > bsize || tmp > bsize);
- memset(AFFS_DATA(bh) + boff, 0, tmp);
- be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
- affs_fix_checksum(sb, bh);
- mark_buffer_dirty_inode(bh, inode);
- size += tmp;
- bidx++;
- } else if (bidx) {
- bh = affs_bread_ino(inode, bidx - 1, 0);
- if (IS_ERR(bh))
- return PTR_ERR(bh);
- }
-
- while (size < newsize) {
- prev_bh = bh;
- bh = affs_getzeroblk_ino(inode, bidx);
- if (IS_ERR(bh))
- goto out;
- tmp = min(bsize, newsize - size);
- BUG_ON(tmp > bsize);
- AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
- AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
- AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
- AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
- affs_fix_checksum(sb, bh);
- bh->b_state &= ~(1UL << BH_New);
- mark_buffer_dirty_inode(bh, inode);
- if (prev_bh) {
- u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
- if (tmp)
- affs_warning(sb, "extent_file_ofs", "next block already set for %d (%d)", bidx, tmp);
- AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
- affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
- mark_buffer_dirty_inode(prev_bh, inode);
- affs_brelse(prev_bh);
- }
- size += bsize;
- bidx++;
- }
- affs_brelse(bh);
- inode->i_size = AFFS_I(inode)->mmu_private = newsize;
- return 0;
-
-out:
- inode->i_size = AFFS_I(inode)->mmu_private = newsize;
- return PTR_ERR(bh);
-}
-
-static int
-affs_readpage_ofs(struct file *file, struct page *page)
-{
- struct inode *inode = page->mapping->host;
- u32 to;
- int err;
-
- pr_debug("AFFS: read_page(%u, %ld)\n", (u32)inode->i_ino, page->index);
- to = PAGE_CACHE_SIZE;
- if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) {
- to = inode->i_size & ~PAGE_CACHE_MASK;
- memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to);
- }
-
- err = affs_do_readpage_ofs(file, page, 0, to);
- if (!err)
- SetPageUptodate(page);
- unlock_page(page);
- return err;
-}
-
-static int affs_write_begin_ofs(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 page *page;
- pgoff_t index;
- int err = 0;
-
- pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len);
- if (pos > AFFS_I(inode)->mmu_private) {
- /* XXX: this probably leaves a too-big i_size in case of
- * failure. Should really be updating i_size at write_end time
- */
- err = affs_extent_file_ofs(inode, pos);
- if (err)
- return err;
- }
-
- index = pos >> PAGE_CACHE_SHIFT;
- page = grab_cache_page_write_begin(mapping, index, flags);
- if (!page)
- return -ENOMEM;
- *pagep = page;
-
- if (PageUptodate(page))
- return 0;
-
- /* XXX: inefficient but safe in the face of short writes */
- err = affs_do_readpage_ofs(file, page, 0, PAGE_CACHE_SIZE);
- if (err) {
- unlock_page(page);
- page_cache_release(page);
- }
- return err;
-}
-
-static int affs_write_end_ofs(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 super_block *sb = inode->i_sb;
- struct buffer_head *bh, *prev_bh;
- char *data;
- u32 bidx, boff, bsize;
- unsigned from, to;
- u32 tmp;
- int written;
-
- from = pos & (PAGE_CACHE_SIZE - 1);
- to = pos + len;
- /*
- * XXX: not sure if this can handle short copies (len < copied), but
- * we don't have to, because the page should always be uptodate here,
- * due to write_begin.
- */
-
- pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len);
- bsize = AFFS_SB(sb)->s_data_blksize;
- data = page_address(page);
-
- bh = NULL;
- written = 0;
- tmp = (page->index << PAGE_CACHE_SHIFT) + from;
- bidx = tmp / bsize;
- boff = tmp % bsize;
- if (boff) {
- bh = affs_bread_ino(inode, bidx, 0);
- if (IS_ERR(bh))
- return PTR_ERR(bh);
- tmp = min(bsize - boff, to - from);
- BUG_ON(boff + tmp > bsize || tmp > bsize);
- memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
- be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
- affs_fix_checksum(sb, bh);
- mark_buffer_dirty_inode(bh, inode);
- written += tmp;
- from += tmp;
- bidx++;
- } else if (bidx) {
- bh = affs_bread_ino(inode, bidx - 1, 0);
- if (IS_ERR(bh))
- return PTR_ERR(bh);
- }
- while (from + bsize <= to) {
- prev_bh = bh;
- bh = affs_getemptyblk_ino(inode, bidx);
- if (IS_ERR(bh))
- goto out;
- memcpy(AFFS_DATA(bh), data + from, bsize);
- if (buffer_new(bh)) {
- AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
- AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
- AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
- AFFS_DATA_HEAD(bh)->size = cpu_to_be32(bsize);
- AFFS_DATA_HEAD(bh)->next = 0;
- bh->b_state &= ~(1UL << BH_New);
- if (prev_bh) {
- u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
- if (tmp)
- affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
- AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
- affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
- mark_buffer_dirty_inode(prev_bh, inode);
- }
- }
- affs_brelse(prev_bh);
- affs_fix_checksum(sb, bh);
- mark_buffer_dirty_inode(bh, inode);
- written += bsize;
- from += bsize;
- bidx++;
- }
- if (from < to) {
- prev_bh = bh;
- bh = affs_bread_ino(inode, bidx, 1);
- if (IS_ERR(bh))
- goto out;
- tmp = min(bsize, to - from);
- BUG_ON(tmp > bsize);
- memcpy(AFFS_DATA(bh), data + from, tmp);
- if (buffer_new(bh)) {
- AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
- AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
- AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
- AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
- AFFS_DATA_HEAD(bh)->next = 0;
- bh->b_state &= ~(1UL << BH_New);
- if (prev_bh) {
- u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
- if (tmp)
- affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
- AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
- affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
- mark_buffer_dirty_inode(prev_bh, inode);
- }
- } else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)
- AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
- affs_brelse(prev_bh);
- affs_fix_checksum(sb, bh);
- mark_buffer_dirty_inode(bh, inode);
- written += tmp;
- from += tmp;
- bidx++;
- }
- SetPageUptodate(page);
-
-done:
- affs_brelse(bh);
- tmp = (page->index << PAGE_CACHE_SHIFT) + from;
- if (tmp > inode->i_size)
- inode->i_size = AFFS_I(inode)->mmu_private = tmp;
-
- unlock_page(page);
- page_cache_release(page);
-
- return written;
-
-out:
- bh = prev_bh;
- if (!written)
- written = PTR_ERR(bh);
- goto done;
-}
-
-const struct address_space_operations affs_aops_ofs = {
- .readpage = affs_readpage_ofs,
- //.writepage = affs_writepage_ofs,
- .write_begin = affs_write_begin_ofs,
- .write_end = affs_write_end_ofs
-};
-
-/* Free any preallocated blocks. */
-
-void
-affs_free_prealloc(struct inode *inode)
-{
- struct super_block *sb = inode->i_sb;
-
- pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino);
-
- while (AFFS_I(inode)->i_pa_cnt) {
- AFFS_I(inode)->i_pa_cnt--;
- affs_free_block(sb, ++AFFS_I(inode)->i_lastalloc);
- }
-}
-
-/* Truncate (or enlarge) a file to the requested size. */
-
-void
-affs_truncate(struct inode *inode)
-{
- struct super_block *sb = inode->i_sb;
- u32 ext, ext_key;
- u32 last_blk, blkcnt, blk;
- u32 size;
- struct buffer_head *ext_bh;
- int i;
-
- pr_debug("AFFS: truncate(inode=%d, oldsize=%u, newsize=%u)\n",
- (u32)inode->i_ino, (u32)AFFS_I(inode)->mmu_private, (u32)inode->i_size);
-
- last_blk = 0;
- ext = 0;
- if (inode->i_size) {
- last_blk = ((u32)inode->i_size - 1) / AFFS_SB(sb)->s_data_blksize;
- ext = last_blk / AFFS_SB(sb)->s_hashsize;
- }
-
- if (inode->i_size > AFFS_I(inode)->mmu_private) {
- struct address_space *mapping = inode->i_mapping;
- struct page *page;
- void *fsdata;
- u32 size = inode->i_size;
- int res;
-
- res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata);
- if (!res)
- res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata);
- else
- inode->i_size = AFFS_I(inode)->mmu_private;
- mark_inode_dirty(inode);
- return;
- } else if (inode->i_size == AFFS_I(inode)->mmu_private)
- return;
-
- // lock cache
- ext_bh = affs_get_extblock(inode, ext);
- if (IS_ERR(ext_bh)) {
- affs_warning(sb, "truncate", "unexpected read error for ext block %u (%d)",
- ext, PTR_ERR(ext_bh));
- return;
- }
- if (AFFS_I(inode)->i_lc) {
- /* clear linear cache */
- i = (ext + 1) >> AFFS_I(inode)->i_lc_shift;
- if (AFFS_I(inode)->i_lc_size > i) {
- AFFS_I(inode)->i_lc_size = i;
- for (; i < AFFS_LC_SIZE; i++)
- AFFS_I(inode)->i_lc[i] = 0;
- }
- /* clear associative cache */
- for (i = 0; i < AFFS_AC_SIZE; i++)
- if (AFFS_I(inode)->i_ac[i].ext >= ext)
- AFFS_I(inode)->i_ac[i].ext = 0;
- }
- ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
-
- blkcnt = AFFS_I(inode)->i_blkcnt;
- i = 0;
- blk = last_blk;
- if (inode->i_size) {
- i = last_blk % AFFS_SB(sb)->s_hashsize + 1;
- blk++;
- } else
- AFFS_HEAD(ext_bh)->first_data = 0;
- AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(i);
- size = AFFS_SB(sb)->s_hashsize;
- if (size > blkcnt - blk + i)
- size = blkcnt - blk + i;
- for (; i < size; i++, blk++) {
- affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
- AFFS_BLOCK(sb, ext_bh, i) = 0;
- }
- AFFS_TAIL(sb, ext_bh)->extension = 0;
- affs_fix_checksum(sb, ext_bh);
- mark_buffer_dirty_inode(ext_bh, inode);
- affs_brelse(ext_bh);
-
- if (inode->i_size) {
- AFFS_I(inode)->i_blkcnt = last_blk + 1;
- AFFS_I(inode)->i_extcnt = ext + 1;
- if (AFFS_SB(sb)->s_flags & SF_OFS) {
- struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0);
- u32 tmp;
- if (IS_ERR(bh)) {
- affs_warning(sb, "truncate", "unexpected read error for last block %u (%d)",
- ext, PTR_ERR(bh));
- return;
- }
- tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next);
- AFFS_DATA_HEAD(bh)->next = 0;
- affs_adjust_checksum(bh, -tmp);
- affs_brelse(bh);
- }
- } else {
- AFFS_I(inode)->i_blkcnt = 0;
- AFFS_I(inode)->i_extcnt = 1;
- }
- AFFS_I(inode)->mmu_private = inode->i_size;
- // unlock cache
-
- while (ext_key) {
- ext_bh = affs_bread(sb, ext_key);
- size = AFFS_SB(sb)->s_hashsize;
- if (size > blkcnt - blk)
- size = blkcnt - blk;
- for (i = 0; i < size; i++, blk++)
- affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
- affs_free_block(sb, ext_key);
- ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
- affs_brelse(ext_bh);
- }
- affs_free_prealloc(inode);
-}
-
-int affs_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
-{
- struct inode *inode = filp->f_mapping->host;
- int ret, err;
-
- err = filemap_write_and_wait_range(inode->i_mapping, start, end);
- if (err)
- return err;
-
- mutex_lock(&inode->i_mutex);
- ret = write_inode_now(inode, 0);
- err = sync_blockdev(inode->i_sb->s_bdev);
- if (!ret)
- ret = err;
- mutex_unlock(&inode->i_mutex);
- return ret;
-}
diff --git a/ANDROID_3.4.5/fs/affs/inode.c b/ANDROID_3.4.5/fs/affs/inode.c
deleted file mode 100644
index 88a4b0b5..00000000
--- a/ANDROID_3.4.5/fs/affs/inode.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * linux/fs/affs/inode.c
- *
- * (c) 1996 Hans-Joachim Widmaier - Rewritten
- *
- * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
- *
- * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
- *
- * (C) 1991 Linus Torvalds - minix filesystem
- */
-#include <linux/sched.h>
-#include <linux/gfp.h>
-#include "affs.h"
-
-extern const struct inode_operations affs_symlink_inode_operations;
-extern struct timezone sys_tz;
-
-struct inode *affs_iget(struct super_block *sb, unsigned long ino)
-{
- struct affs_sb_info *sbi = AFFS_SB(sb);
- struct buffer_head *bh;
- struct affs_head *head;
- struct affs_tail *tail;
- struct inode *inode;
- u32 block;
- u32 size;
- u32 prot;
- u16 id;
-
- inode = iget_locked(sb, ino);
- if (!inode)
- return ERR_PTR(-ENOMEM);
- if (!(inode->i_state & I_NEW))
- return inode;
-
- pr_debug("AFFS: affs_iget(%lu)\n", inode->i_ino);
-
- block = inode->i_ino;
- bh = affs_bread(sb, block);
- if (!bh) {
- affs_warning(sb, "read_inode", "Cannot read block %d", block);
- goto bad_inode;
- }
- if (affs_checksum_block(sb, bh) || be32_to_cpu(AFFS_HEAD(bh)->ptype) != T_SHORT) {
- affs_warning(sb,"read_inode",
- "Checksum or type (ptype=%d) error on inode %d",
- AFFS_HEAD(bh)->ptype, block);
- goto bad_inode;
- }
-
- head = AFFS_HEAD(bh);
- tail = AFFS_TAIL(sb, bh);
- prot = be32_to_cpu(tail->protect);
-
- inode->i_size = 0;
- set_nlink(inode, 1);
- inode->i_mode = 0;
- AFFS_I(inode)->i_extcnt = 1;
- AFFS_I(inode)->i_ext_last = ~1;
- AFFS_I(inode)->i_protect = prot;
- atomic_set(&AFFS_I(inode)->i_opencnt, 0);
- AFFS_I(inode)->i_blkcnt = 0;
- AFFS_I(inode)->i_lc = NULL;
- AFFS_I(inode)->i_lc_size = 0;
- AFFS_I(inode)->i_lc_shift = 0;
- AFFS_I(inode)->i_lc_mask = 0;
- AFFS_I(inode)->i_ac = NULL;
- AFFS_I(inode)->i_ext_bh = NULL;
- AFFS_I(inode)->mmu_private = 0;
- AFFS_I(inode)->i_lastalloc = 0;
- AFFS_I(inode)->i_pa_cnt = 0;
-
- if (sbi->s_flags & SF_SETMODE)
- inode->i_mode = sbi->s_mode;
- else
- inode->i_mode = prot_to_mode(prot);
-
- id = be16_to_cpu(tail->uid);
- if (id == 0 || sbi->s_flags & SF_SETUID)
- inode->i_uid = sbi->s_uid;
- else if (id == 0xFFFF && sbi->s_flags & SF_MUFS)
- inode->i_uid = 0;
- else
- inode->i_uid = id;
-
- id = be16_to_cpu(tail->gid);
- if (id == 0 || sbi->s_flags & SF_SETGID)
- inode->i_gid = sbi->s_gid;
- else if (id == 0xFFFF && sbi->s_flags & SF_MUFS)
- inode->i_gid = 0;
- else
- inode->i_gid = id;
-
- switch (be32_to_cpu(tail->stype)) {
- case ST_ROOT:
- inode->i_uid = sbi->s_uid;
- inode->i_gid = sbi->s_gid;
- /* fall through */
- case ST_USERDIR:
- if (be32_to_cpu(tail->stype) == ST_USERDIR ||
- sbi->s_flags & SF_SETMODE) {
- if (inode->i_mode & S_IRUSR)
- inode->i_mode |= S_IXUSR;
- if (inode->i_mode & S_IRGRP)
- inode->i_mode |= S_IXGRP;
- if (inode->i_mode & S_IROTH)
- inode->i_mode |= S_IXOTH;
- inode->i_mode |= S_IFDIR;
- } else
- inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR;
- /* Maybe it should be controlled by mount parameter? */
- //inode->i_mode |= S_ISVTX;
- inode->i_op = &affs_dir_inode_operations;
- inode->i_fop = &affs_dir_operations;
- break;
- case ST_LINKDIR:
-#if 0
- affs_warning(sb, "read_inode", "inode is LINKDIR");
- goto bad_inode;
-#else
- inode->i_mode |= S_IFDIR;
- /* ... and leave ->i_op and ->i_fop pointing to empty */
- break;
-#endif
- case ST_LINKFILE:
- affs_warning(sb, "read_inode", "inode is LINKFILE");
- goto bad_inode;
- case ST_FILE:
- size = be32_to_cpu(tail->size);
- inode->i_mode |= S_IFREG;
- AFFS_I(inode)->mmu_private = inode->i_size = size;
- if (inode->i_size) {
- AFFS_I(inode)->i_blkcnt = (size - 1) /
- sbi->s_data_blksize + 1;
- AFFS_I(inode)->i_extcnt = (AFFS_I(inode)->i_blkcnt - 1) /
- sbi->s_hashsize + 1;
- }
- if (tail->link_chain)
- set_nlink(inode, 2);
- inode->i_mapping->a_ops = (sbi->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops;
- inode->i_op = &affs_file_inode_operations;
- inode->i_fop = &affs_file_operations;
- break;
- case ST_SOFTLINK:
- inode->i_mode |= S_IFLNK;
- inode->i_op = &affs_symlink_inode_operations;
- inode->i_data.a_ops = &affs_symlink_aops;
- break;
- }
-
- inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec
- = (be32_to_cpu(tail->change.days) * (24 * 60 * 60) +
- be32_to_cpu(tail->change.mins) * 60 +
- be32_to_cpu(tail->change.ticks) / 50 +
- ((8 * 365 + 2) * 24 * 60 * 60)) +
- sys_tz.tz_minuteswest * 60;
- inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
- affs_brelse(bh);
- unlock_new_inode(inode);
- return inode;
-
-bad_inode:
- affs_brelse(bh);
- iget_failed(inode);
- return ERR_PTR(-EIO);
-}
-
-int
-affs_write_inode(struct inode *inode, struct writeback_control *wbc)
-{
- struct super_block *sb = inode->i_sb;
- struct buffer_head *bh;
- struct affs_tail *tail;
- uid_t uid;
- gid_t gid;
-
- pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino);
-
- if (!inode->i_nlink)
- // possibly free block
- return 0;
- bh = affs_bread(sb, inode->i_ino);
- if (!bh) {
- affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino);
- return -EIO;
- }
- tail = AFFS_TAIL(sb, bh);
- if (tail->stype == cpu_to_be32(ST_ROOT)) {
- secs_to_datestamp(inode->i_mtime.tv_sec,&AFFS_ROOT_TAIL(sb, bh)->root_change);
- } else {
- tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect);
- tail->size = cpu_to_be32(inode->i_size);
- secs_to_datestamp(inode->i_mtime.tv_sec,&tail->change);
- if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) {
- uid = inode->i_uid;
- gid = inode->i_gid;
- if (AFFS_SB(sb)->s_flags & SF_MUFS) {
- if (inode->i_uid == 0 || inode->i_uid == 0xFFFF)
- uid = inode->i_uid ^ ~0;
- if (inode->i_gid == 0 || inode->i_gid == 0xFFFF)
- gid = inode->i_gid ^ ~0;
- }
- if (!(AFFS_SB(sb)->s_flags & SF_SETUID))
- tail->uid = cpu_to_be16(uid);
- if (!(AFFS_SB(sb)->s_flags & SF_SETGID))
- tail->gid = cpu_to_be16(gid);
- }
- }
- affs_fix_checksum(sb, bh);
- mark_buffer_dirty_inode(bh, inode);
- affs_brelse(bh);
- affs_free_prealloc(inode);
- return 0;
-}
-
-int
-affs_notify_change(struct dentry *dentry, struct iattr *attr)
-{
- struct inode *inode = dentry->d_inode;
- int error;
-
- pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);
-
- error = inode_change_ok(inode,attr);
- if (error)
- goto out;
-
- if (((attr->ia_valid & ATTR_UID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETUID)) ||
- ((attr->ia_valid & ATTR_GID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETGID)) ||
- ((attr->ia_valid & ATTR_MODE) &&
- (AFFS_SB(inode->i_sb)->s_flags & (SF_SETMODE | SF_IMMUTABLE)))) {
- if (!(AFFS_SB(inode->i_sb)->s_flags & SF_QUIET))
- error = -EPERM;
- goto out;
- }
-
- if ((attr->ia_valid & ATTR_SIZE) &&
- attr->ia_size != i_size_read(inode)) {
- error = vmtruncate(inode, attr->ia_size);
- if (error)
- return error;
- }
-
- setattr_copy(inode, attr);
- mark_inode_dirty(inode);
-
- if (attr->ia_valid & ATTR_MODE)
- mode_to_prot(inode);
-out:
- return error;
-}
-
-void
-affs_evict_inode(struct inode *inode)
-{
- unsigned long cache_page;
- pr_debug("AFFS: evict_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
- truncate_inode_pages(&inode->i_data, 0);
-
- if (!inode->i_nlink) {
- inode->i_size = 0;
- affs_truncate(inode);
- }
-
- invalidate_inode_buffers(inode);
- end_writeback(inode);
- affs_free_prealloc(inode);
- cache_page = (unsigned long)AFFS_I(inode)->i_lc;
- if (cache_page) {
- pr_debug("AFFS: freeing ext cache\n");
- AFFS_I(inode)->i_lc = NULL;
- AFFS_I(inode)->i_ac = NULL;
- free_page(cache_page);
- }
- affs_brelse(AFFS_I(inode)->i_ext_bh);
- AFFS_I(inode)->i_ext_last = ~1;
- AFFS_I(inode)->i_ext_bh = NULL;
-
- if (!inode->i_nlink)
- affs_free_block(inode->i_sb, inode->i_ino);
-}
-
-struct inode *
-affs_new_inode(struct inode *dir)
-{
- struct super_block *sb = dir->i_sb;
- struct inode *inode;
- u32 block;
- struct buffer_head *bh;
-
- if (!(inode = new_inode(sb)))
- goto err_inode;
-
- if (!(block = affs_alloc_block(dir, dir->i_ino)))
- goto err_block;
-
- bh = affs_getzeroblk(sb, block);
- if (!bh)
- goto err_bh;
- mark_buffer_dirty_inode(bh, inode);
- affs_brelse(bh);
-
- inode->i_uid = current_fsuid();
- inode->i_gid = current_fsgid();
- inode->i_ino = block;
- set_nlink(inode, 1);
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
- atomic_set(&AFFS_I(inode)->i_opencnt, 0);
- AFFS_I(inode)->i_blkcnt = 0;
- AFFS_I(inode)->i_lc = NULL;
- AFFS_I(inode)->i_lc_size = 0;
- AFFS_I(inode)->i_lc_shift = 0;
- AFFS_I(inode)->i_lc_mask = 0;
- AFFS_I(inode)->i_ac = NULL;
- AFFS_I(inode)->i_ext_bh = NULL;
- AFFS_I(inode)->mmu_private = 0;
- AFFS_I(inode)->i_protect = 0;
- AFFS_I(inode)->i_lastalloc = 0;
- AFFS_I(inode)->i_pa_cnt = 0;
- AFFS_I(inode)->i_extcnt = 1;
- AFFS_I(inode)->i_ext_last = ~1;
-
- insert_inode_hash(inode);
-
- return inode;
-
-err_bh:
- affs_free_block(sb, block);
-err_block:
- iput(inode);
-err_inode:
- return NULL;
-}
-
-/*
- * Add an entry to a directory. Create the header block
- * and insert it into the hash table.
- */
-
-int
-affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type)
-{
- struct super_block *sb = dir->i_sb;
- struct buffer_head *inode_bh = NULL;
- struct buffer_head *bh = NULL;
- u32 block = 0;
- int retval;
-
- pr_debug("AFFS: add_entry(dir=%u, inode=%u, \"%*s\", type=%d)\n", (u32)dir->i_ino,
- (u32)inode->i_ino, (int)dentry->d_name.len, dentry->d_name.name, type);
-
- retval = -EIO;
- bh = affs_bread(sb, inode->i_ino);
- if (!bh)
- goto done;
-
- affs_lock_link(inode);
- switch (type) {
- case ST_LINKFILE:
- case ST_LINKDIR:
- retval = -ENOSPC;
- block = affs_alloc_block(dir, dir->i_ino);
- if (!block)
- goto err;
- retval = -EIO;
- inode_bh = bh;
- bh = affs_getzeroblk(sb, block);
- if (!bh)
- goto err;
- break;
- default:
- break;
- }
-
- AFFS_HEAD(bh)->ptype = cpu_to_be32(T_SHORT);
- AFFS_HEAD(bh)->key = cpu_to_be32(bh->b_blocknr);
- affs_copy_name(AFFS_TAIL(sb, bh)->name, dentry);
- AFFS_TAIL(sb, bh)->stype = cpu_to_be32(type);
- AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
-
- if (inode_bh) {
- __be32 chain;
- chain = AFFS_TAIL(sb, inode_bh)->link_chain;
- AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
- AFFS_TAIL(sb, bh)->link_chain = chain;
- AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
- affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
- mark_buffer_dirty_inode(inode_bh, inode);
- set_nlink(inode, 2);
- ihold(inode);
- }
- affs_fix_checksum(sb, bh);
- mark_buffer_dirty_inode(bh, inode);
- dentry->d_fsdata = (void *)(long)bh->b_blocknr;
-
- affs_lock_dir(dir);
- retval = affs_insert_hash(dir, bh);
- mark_buffer_dirty_inode(bh, inode);
- affs_unlock_dir(dir);
- affs_unlock_link(inode);
-
- d_instantiate(dentry, inode);
-done:
- affs_brelse(inode_bh);
- affs_brelse(bh);
- return retval;
-err:
- if (block)
- affs_free_block(sb, block);
- affs_unlock_link(inode);
- goto done;
-}
diff --git a/ANDROID_3.4.5/fs/affs/namei.c b/ANDROID_3.4.5/fs/affs/namei.c
deleted file mode 100644
index 47806940..00000000
--- a/ANDROID_3.4.5/fs/affs/namei.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * linux/fs/affs/namei.c
- *
- * (c) 1996 Hans-Joachim Widmaier - Rewritten
- *
- * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
- *
- * (C) 1991 Linus Torvalds - minix filesystem
- */
-
-#include "affs.h"
-
-typedef int (*toupper_t)(int);
-
-static int affs_toupper(int ch);
-static int affs_hash_dentry(const struct dentry *,
- const struct inode *, struct qstr *);
-static int affs_compare_dentry(const struct dentry *parent,
- const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
- unsigned int len, const char *str, const struct qstr *name);
-static int affs_intl_toupper(int ch);
-static int affs_intl_hash_dentry(const struct dentry *,
- const struct inode *, struct qstr *);
-static int affs_intl_compare_dentry(const struct dentry *parent,
- const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
- unsigned int len, const char *str, const struct qstr *name);
-
-const struct dentry_operations affs_dentry_operations = {
- .d_hash = affs_hash_dentry,
- .d_compare = affs_compare_dentry,
-};
-
-const struct dentry_operations affs_intl_dentry_operations = {
- .d_hash = affs_intl_hash_dentry,
- .d_compare = affs_intl_compare_dentry,
-};
-
-
-/* Simple toupper() for DOS\1 */
-
-static int
-affs_toupper(int ch)
-{
- return ch >= 'a' && ch <= 'z' ? ch -= ('a' - 'A') : ch;
-}
-
-/* International toupper() for DOS\3 ("international") */
-
-static int
-affs_intl_toupper(int ch)
-{
- return (ch >= 'a' && ch <= 'z') || (ch >= 0xE0
- && ch <= 0xFE && ch != 0xF7) ?
- ch - ('a' - 'A') : ch;
-}
-
-static inline toupper_t
-affs_get_toupper(struct super_block *sb)
-{
- return AFFS_SB(sb)->s_flags & SF_INTL ? affs_intl_toupper : affs_toupper;
-}
-
-/*
- * Note: the dentry argument is the parent dentry.
- */
-static inline int
-__affs_hash_dentry(struct qstr *qstr, toupper_t toupper)
-{
- const u8 *name = qstr->name;
- unsigned long hash;
- int i;
-
- i = affs_check_name(qstr->name, qstr->len);
- if (i)
- return i;
-
- hash = init_name_hash();
- i = min(qstr->len, 30u);
- for (; i > 0; name++, i--)
- hash = partial_name_hash(toupper(*name), hash);
- qstr->hash = end_name_hash(hash);
-
- return 0;
-}
-
-static int
-affs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
- struct qstr *qstr)
-{
- return __affs_hash_dentry(qstr, affs_toupper);
-}
-static int
-affs_intl_hash_dentry(const struct dentry *dentry, const struct inode *inode,
- struct qstr *qstr)
-{
- return __affs_hash_dentry(qstr, affs_intl_toupper);
-}
-
-static inline int __affs_compare_dentry(unsigned int len,
- const char *str, const struct qstr *name, toupper_t toupper)
-{
- const u8 *aname = str;
- const u8 *bname = name->name;
-
- /*
- * 'str' is the name of an already existing dentry, so the name
- * must be valid. 'name' must be validated first.
- */
-
- if (affs_check_name(name->name, name->len))
- return 1;
-
- /*
- * If the names are longer than the allowed 30 chars,
- * the excess is ignored, so their length may differ.
- */
- if (len >= 30) {
- if (name->len < 30)
- return 1;
- len = 30;
- } else if (len != name->len)
- return 1;
-
- for (; len > 0; len--)
- if (toupper(*aname++) != toupper(*bname++))
- return 1;
-
- return 0;
-}
-
-static int
-affs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
- unsigned int len, const char *str, const struct qstr *name)
-{
- return __affs_compare_dentry(len, str, name, affs_toupper);
-}
-static int
-affs_intl_compare_dentry(const struct dentry *parent,const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
- unsigned int len, const char *str, const struct qstr *name)
-{
- return __affs_compare_dentry(len, str, name, affs_intl_toupper);
-}
-
-/*
- * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure.
- */
-
-static inline int
-affs_match(struct dentry *dentry, const u8 *name2, toupper_t toupper)
-{
- const u8 *name = dentry->d_name.name;
- int len = dentry->d_name.len;
-
- if (len >= 30) {
- if (*name2 < 30)
- return 0;
- len = 30;
- } else if (len != *name2)
- return 0;
-
- for (name2++; len > 0; len--)
- if (toupper(*name++) != toupper(*name2++))
- return 0;
- return 1;
-}
-
-int
-affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len)
-{
- toupper_t toupper = affs_get_toupper(sb);
- int hash;
-
- hash = len = min(len, 30u);
- for (; len > 0; len--)
- hash = (hash * 13 + toupper(*name++)) & 0x7ff;
-
- return hash % AFFS_SB(sb)->s_hashsize;
-}
-
-static struct buffer_head *
-affs_find_entry(struct inode *dir, struct dentry *dentry)
-{
- struct super_block *sb = dir->i_sb;
- struct buffer_head *bh;
- toupper_t toupper = affs_get_toupper(sb);
- u32 key;
-
- pr_debug("AFFS: find_entry(\"%.*s\")\n", (int)dentry->d_name.len, dentry->d_name.name);
-
- bh = affs_bread(sb, dir->i_ino);
- if (!bh)
- return ERR_PTR(-EIO);
-
- key = be32_to_cpu(AFFS_HEAD(bh)->table[affs_hash_name(sb, dentry->d_name.name, dentry->d_name.len)]);
-
- for (;;) {
- affs_brelse(bh);
- if (key == 0)
- return NULL;
- bh = affs_bread(sb, key);
- if (!bh)
- return ERR_PTR(-EIO);
- if (affs_match(dentry, AFFS_TAIL(sb, bh)->name, toupper))
- return bh;
- key = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain);
- }
-}
-
-struct dentry *
-affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
- struct super_block *sb = dir->i_sb;
- struct buffer_head *bh;
- struct inode *inode = NULL;
-
- pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry->d_name.len,dentry->d_name.name);
-
- affs_lock_dir(dir);
- bh = affs_find_entry(dir, dentry);
- affs_unlock_dir(dir);
- if (IS_ERR(bh))
- return ERR_CAST(bh);
- if (bh) {
- u32 ino = bh->b_blocknr;
-
- /* store the real header ino in d_fsdata for faster lookups */
- dentry->d_fsdata = (void *)(long)ino;
- switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
- //link to dirs disabled
- //case ST_LINKDIR:
- case ST_LINKFILE:
- ino = be32_to_cpu(AFFS_TAIL(sb, bh)->original);
- }
- affs_brelse(bh);
- inode = affs_iget(sb, ino);
- if (IS_ERR(inode))
- return ERR_CAST(inode);
- }
- d_add(dentry, inode);
- return NULL;
-}
-
-int
-affs_unlink(struct inode *dir, struct dentry *dentry)
-{
- pr_debug("AFFS: unlink(dir=%d, %lu \"%.*s\")\n", (u32)dir->i_ino,
- dentry->d_inode->i_ino,
- (int)dentry->d_name.len, dentry->d_name.name);
-
- return affs_remove_header(dentry);
-}
-
-int
-affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
-{
- struct super_block *sb = dir->i_sb;
- struct inode *inode;
- int error;
-
- pr_debug("AFFS: create(%lu,\"%.*s\",0%ho)\n",dir->i_ino,(int)dentry->d_name.len,
- dentry->d_name.name,mode);
-
- inode = affs_new_inode(dir);
- if (!inode)
- return -ENOSPC;
-
- inode->i_mode = mode;
- mode_to_prot(inode);
- mark_inode_dirty(inode);
-
- inode->i_op = &affs_file_inode_operations;
- inode->i_fop = &affs_file_operations;
- inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops;
- error = affs_add_entry(dir, inode, dentry, ST_FILE);
- if (error) {
- clear_nlink(inode);
- iput(inode);
- return error;
- }
- return 0;
-}
-
-int
-affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
-{
- struct inode *inode;
- int error;
-
- pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%ho)\n",dir->i_ino,
- (int)dentry->d_name.len,dentry->d_name.name,mode);
-
- inode = affs_new_inode(dir);
- if (!inode)
- return -ENOSPC;
-
- inode->i_mode = S_IFDIR | mode;
- mode_to_prot(inode);
-
- inode->i_op = &affs_dir_inode_operations;
- inode->i_fop = &affs_dir_operations;
-
- error = affs_add_entry(dir, inode, dentry, ST_USERDIR);
- if (error) {
- clear_nlink(inode);
- mark_inode_dirty(inode);
- iput(inode);
- return error;
- }
- return 0;
-}
-
-int
-affs_rmdir(struct inode *dir, struct dentry *dentry)
-{
- pr_debug("AFFS: rmdir(dir=%u, %lu \"%.*s\")\n", (u32)dir->i_ino,
- dentry->d_inode->i_ino,
- (int)dentry->d_name.len, dentry->d_name.name);
-
- return affs_remove_header(dentry);
-}
-
-int
-affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
- struct super_block *sb = dir->i_sb;
- struct buffer_head *bh;
- struct inode *inode;
- char *p;
- int i, maxlen, error;
- char c, lc;
-
- pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir->i_ino,
- (int)dentry->d_name.len,dentry->d_name.name,symname);
-
- maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1;
- inode = affs_new_inode(dir);
- if (!inode)
- return -ENOSPC;
-
- inode->i_op = &affs_symlink_inode_operations;
- inode->i_data.a_ops = &affs_symlink_aops;
- inode->i_mode = S_IFLNK | 0777;
- mode_to_prot(inode);
-
- error = -EIO;
- bh = affs_bread(sb, inode->i_ino);
- if (!bh)
- goto err;
- i = 0;
- p = (char *)AFFS_HEAD(bh)->table;
- lc = '/';
- if (*symname == '/') {
- struct affs_sb_info *sbi = AFFS_SB(sb);
- while (*symname == '/')
- symname++;
- spin_lock(&sbi->symlink_lock);
- while (sbi->s_volume[i]) /* Cannot overflow */
- *p++ = sbi->s_volume[i++];
- spin_unlock(&sbi->symlink_lock);
- }
- while (i < maxlen && (c = *symname++)) {
- if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') {
- *p++ = '/';
- i++;
- symname += 2;
- lc = '/';
- } else if (c == '.' && lc == '/' && *symname == '/') {
- symname++;
- lc = '/';
- } else {
- *p++ = c;
- lc = c;
- i++;
- }
- if (lc == '/')
- while (*symname == '/')
- symname++;
- }
- *p = 0;
- mark_buffer_dirty_inode(bh, inode);
- affs_brelse(bh);
- mark_inode_dirty(inode);
-
- error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK);
- if (error)
- goto err;
-
- return 0;
-
-err:
- clear_nlink(inode);
- mark_inode_dirty(inode);
- iput(inode);
- return error;
-}
-
-int
-affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
-{
- struct inode *inode = old_dentry->d_inode;
-
- pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32)inode->i_ino, (u32)dir->i_ino,
- (int)dentry->d_name.len,dentry->d_name.name);
-
- return affs_add_entry(dir, inode, dentry, ST_LINKFILE);
-}
-
-int
-affs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
-{
- struct super_block *sb = old_dir->i_sb;
- struct buffer_head *bh = NULL;
- int retval;
-
- pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n",
- (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name,
- (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name);
-
- retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len);
- if (retval)
- return retval;
-
- /* Unlink destination if it already exists */
- if (new_dentry->d_inode) {
- retval = affs_remove_header(new_dentry);
- if (retval)
- return retval;
- }
-
- bh = affs_bread(sb, old_dentry->d_inode->i_ino);
- if (!bh)
- return -EIO;
-
- /* Remove header from its parent directory. */
- affs_lock_dir(old_dir);
- retval = affs_remove_hash(old_dir, bh);
- affs_unlock_dir(old_dir);
- if (retval)
- goto done;
-
- /* And insert it into the new directory with the new name. */
- affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry);
- affs_fix_checksum(sb, bh);
- affs_lock_dir(new_dir);
- retval = affs_insert_hash(new_dir, bh);
- affs_unlock_dir(new_dir);
- /* TODO: move it back to old_dir, if error? */
-
-done:
- mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir);
- affs_brelse(bh);
- return retval;
-}
diff --git a/ANDROID_3.4.5/fs/affs/super.c b/ANDROID_3.4.5/fs/affs/super.c
deleted file mode 100644
index 0782653a..00000000
--- a/ANDROID_3.4.5/fs/affs/super.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * linux/fs/affs/inode.c
- *
- * (c) 1996 Hans-Joachim Widmaier - Rewritten
- *
- * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
- *
- * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem.
- *
- * (C) 1991 Linus Torvalds - minix filesystem
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/statfs.h>
-#include <linux/parser.h>
-#include <linux/magic.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include "affs.h"
-
-extern struct timezone sys_tz;
-
-static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
-static int affs_remount (struct super_block *sb, int *flags, char *data);
-
-static void
-affs_commit_super(struct super_block *sb, int wait, int clean)
-{
- struct affs_sb_info *sbi = AFFS_SB(sb);
- struct buffer_head *bh = sbi->s_root_bh;
- struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh);
-
- tail->bm_flag = cpu_to_be32(clean);
- secs_to_datestamp(get_seconds(), &tail->disk_change);
- affs_fix_checksum(sb, bh);
- mark_buffer_dirty(bh);
- if (wait)
- sync_dirty_buffer(bh);
-}
-
-static void
-affs_put_super(struct super_block *sb)
-{
- struct affs_sb_info *sbi = AFFS_SB(sb);
- pr_debug("AFFS: put_super()\n");
-
- if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt)
- affs_commit_super(sb, 1, 1);
-
- kfree(sbi->s_prefix);
- affs_free_bitmap(sb);
- affs_brelse(sbi->s_root_bh);
- kfree(sbi);
- sb->s_fs_info = NULL;
-}
-
-static void
-affs_write_super(struct super_block *sb)
-{
- lock_super(sb);
- if (!(sb->s_flags & MS_RDONLY))
- affs_commit_super(sb, 1, 2);
- sb->s_dirt = 0;
- unlock_super(sb);
-
- pr_debug("AFFS: write_super() at %lu, clean=2\n", get_seconds());
-}
-
-static int
-affs_sync_fs(struct super_block *sb, int wait)
-{
- lock_super(sb);
- affs_commit_super(sb, wait, 2);
- sb->s_dirt = 0;
- unlock_super(sb);
- return 0;
-}
-
-static struct kmem_cache * affs_inode_cachep;
-
-static struct inode *affs_alloc_inode(struct super_block *sb)
-{
- struct affs_inode_info *i;
-
- i = kmem_cache_alloc(affs_inode_cachep, GFP_KERNEL);
- if (!i)
- return NULL;
-
- i->vfs_inode.i_version = 1;
- i->i_lc = NULL;
- i->i_ext_bh = NULL;
- i->i_pa_cnt = 0;
-
- return &i->vfs_inode;
-}
-
-static void affs_i_callback(struct rcu_head *head)
-{
- struct inode *inode = container_of(head, struct inode, i_rcu);
- kmem_cache_free(affs_inode_cachep, AFFS_I(inode));
-}
-
-static void affs_destroy_inode(struct inode *inode)
-{
- call_rcu(&inode->i_rcu, affs_i_callback);
-}
-
-static void init_once(void *foo)
-{
- struct affs_inode_info *ei = (struct affs_inode_info *) foo;
-
- sema_init(&ei->i_link_lock, 1);
- sema_init(&ei->i_ext_lock, 1);
- inode_init_once(&ei->vfs_inode);
-}
-
-static int init_inodecache(void)
-{
- affs_inode_cachep = kmem_cache_create("affs_inode_cache",
- sizeof(struct affs_inode_info),
- 0, (SLAB_RECLAIM_ACCOUNT|
- SLAB_MEM_SPREAD),
- init_once);
- if (affs_inode_cachep == NULL)
- return -ENOMEM;
- return 0;
-}
-
-static void destroy_inodecache(void)
-{
- kmem_cache_destroy(affs_inode_cachep);
-}
-
-static const struct super_operations affs_sops = {
- .alloc_inode = affs_alloc_inode,
- .destroy_inode = affs_destroy_inode,
- .write_inode = affs_write_inode,
- .evict_inode = affs_evict_inode,
- .put_super = affs_put_super,
- .write_super = affs_write_super,
- .sync_fs = affs_sync_fs,
- .statfs = affs_statfs,
- .remount_fs = affs_remount,
- .show_options = generic_show_options,
-};
-
-enum {
- Opt_bs, Opt_mode, Opt_mufs, Opt_prefix, Opt_protect,
- Opt_reserved, Opt_root, Opt_setgid, Opt_setuid,
- Opt_verbose, Opt_volume, Opt_ignore, Opt_err,
-};
-
-static const match_table_t tokens = {
- {Opt_bs, "bs=%u"},
- {Opt_mode, "mode=%o"},
- {Opt_mufs, "mufs"},
- {Opt_prefix, "prefix=%s"},
- {Opt_protect, "protect"},
- {Opt_reserved, "reserved=%u"},
- {Opt_root, "root=%u"},
- {Opt_setgid, "setgid=%u"},
- {Opt_setuid, "setuid=%u"},
- {Opt_verbose, "verbose"},
- {Opt_volume, "volume=%s"},
- {Opt_ignore, "grpquota"},
- {Opt_ignore, "noquota"},
- {Opt_ignore, "quota"},
- {Opt_ignore, "usrquota"},
- {Opt_err, NULL},
-};
-
-static int
-parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root,
- int *blocksize, char **prefix, char *volume, unsigned long *mount_opts)
-{
- char *p;
- substring_t args[MAX_OPT_ARGS];
-
- /* Fill in defaults */
-
- *uid = current_uid();
- *gid = current_gid();
- *reserved = 2;
- *root = -1;
- *blocksize = -1;
- volume[0] = ':';
- volume[1] = 0;
- *mount_opts = 0;
- if (!options)
- return 1;
-
- while ((p = strsep(&options, ",")) != NULL) {
- int token, n, option;
- if (!*p)
- continue;
-
- token = match_token(p, tokens, args);
- switch (token) {
- case Opt_bs:
- if (match_int(&args[0], &n))
- return 0;
- if (n != 512 && n != 1024 && n != 2048
- && n != 4096) {
- printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
- return 0;
- }
- *blocksize = n;
- break;
- case Opt_mode:
- if (match_octal(&args[0], &option))
- return 0;
- *mode = option & 0777;
- *mount_opts |= SF_SETMODE;
- break;
- case Opt_mufs:
- *mount_opts |= SF_MUFS;
- break;
- case Opt_prefix:
- *prefix = match_strdup(&args[0]);
- if (!*prefix)
- return 0;
- *mount_opts |= SF_PREFIX;
- break;
- case Opt_protect:
- *mount_opts |= SF_IMMUTABLE;
- break;
- case Opt_reserved:
- if (match_int(&args[0], reserved))
- return 0;
- break;
- case Opt_root:
- if (match_int(&args[0], root))
- return 0;
- break;
- case Opt_setgid:
- if (match_int(&args[0], &option))
- return 0;
- *gid = option;
- *mount_opts |= SF_SETGID;
- break;
- case Opt_setuid:
- if (match_int(&args[0], &option))
- return 0;
- *uid = option;
- *mount_opts |= SF_SETUID;
- break;
- case Opt_verbose:
- *mount_opts |= SF_VERBOSE;
- break;
- case Opt_volume: {
- char *vol = match_strdup(&args[0]);
- if (!vol)
- return 0;
- strlcpy(volume, vol, 32);
- kfree(vol);
- break;
- }
- case Opt_ignore:
- /* Silently ignore the quota options */
- break;
- default:
- printk("AFFS: Unrecognized mount option \"%s\" "
- "or missing value\n", p);
- return 0;
- }
- }
- return 1;
-}
-
-/* This function definitely needs to be split up. Some fine day I'll
- * hopefully have the guts to do so. Until then: sorry for the mess.
- */
-
-static int affs_fill_super(struct super_block *sb, void *data, int silent)
-{
- struct affs_sb_info *sbi;
- struct buffer_head *root_bh = NULL;
- struct buffer_head *boot_bh;
- struct inode *root_inode = NULL;
- s32 root_block;
- int size, blocksize;
- u32 chksum;
- int num_bm;
- int i, j;
- s32 key;
- uid_t uid;
- gid_t gid;
- int reserved;
- unsigned long mount_flags;
- int tmp_flags; /* fix remount prototype... */
- u8 sig[4];
- int ret = -EINVAL;
-
- save_mount_options(sb, data);
-
- pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
-
- sb->s_magic = AFFS_SUPER_MAGIC;
- sb->s_op = &affs_sops;
- sb->s_flags |= MS_NODIRATIME;
-
- sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
- if (!sbi)
- return -ENOMEM;
-
- sb->s_fs_info = sbi;
- mutex_init(&sbi->s_bmlock);
- spin_lock_init(&sbi->symlink_lock);
-
- if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
- &blocksize,&sbi->s_prefix,
- sbi->s_volume, &mount_flags)) {
- printk(KERN_ERR "AFFS: Error parsing options\n");
- kfree(sbi->s_prefix);
- kfree(sbi);
- return -EINVAL;
- }
- /* N.B. after this point s_prefix must be released */
-
- sbi->s_flags = mount_flags;
- sbi->s_mode = i;
- sbi->s_uid = uid;
- sbi->s_gid = gid;
- sbi->s_reserved= reserved;
-
- /* Get the size of the device in 512-byte blocks.
- * If we later see that the partition uses bigger
- * blocks, we will have to change it.
- */
-
- size = sb->s_bdev->bd_inode->i_size >> 9;
- pr_debug("AFFS: initial blocksize=%d, #blocks=%d\n", 512, size);
-
- affs_set_blocksize(sb, PAGE_SIZE);
- /* Try to find root block. Its location depends on the block size. */
-
- i = 512;
- j = 4096;
- if (blocksize > 0) {
- i = j = blocksize;
- size = size / (blocksize / 512);
- }
- for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) {
- sbi->s_root_block = root_block;
- if (root_block < 0)
- sbi->s_root_block = (reserved + size - 1) / 2;
- pr_debug("AFFS: setting blocksize to %d\n", blocksize);
- affs_set_blocksize(sb, blocksize);
- sbi->s_partition_size = size;
-
- /* The root block location that was calculated above is not
- * correct if the partition size is an odd number of 512-
- * byte blocks, which will be rounded down to a number of
- * 1024-byte blocks, and if there were an even number of
- * reserved blocks. Ideally, all partition checkers should
- * report the real number of blocks of the real blocksize,
- * but since this just cannot be done, we have to try to
- * find the root block anyways. In the above case, it is one
- * block behind the calculated one. So we check this one, too.
- */
- for (num_bm = 0; num_bm < 2; num_bm++) {
- pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, "
- "size=%d, reserved=%d\n",
- sb->s_id,
- sbi->s_root_block + num_bm,
- blocksize, size, reserved);
- root_bh = affs_bread(sb, sbi->s_root_block + num_bm);
- if (!root_bh)
- continue;
- if (!affs_checksum_block(sb, root_bh) &&
- be32_to_cpu(AFFS_ROOT_HEAD(root_bh)->ptype) == T_SHORT &&
- be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) {
- sbi->s_hashsize = blocksize / 4 - 56;
- sbi->s_root_block += num_bm;
- key = 1;
- goto got_root;
- }
- affs_brelse(root_bh);
- root_bh = NULL;
- }
- }
- if (!silent)
- printk(KERN_ERR "AFFS: No valid root block on device %s\n",
- sb->s_id);
- goto out_error;
-
- /* N.B. after this point bh must be released */
-got_root:
- root_block = sbi->s_root_block;
-
- /* Find out which kind of FS we have */
- boot_bh = sb_bread(sb, 0);
- if (!boot_bh) {
- printk(KERN_ERR "AFFS: Cannot read boot block\n");
- goto out_error;
- }
- memcpy(sig, boot_bh->b_data, 4);
- brelse(boot_bh);
- chksum = be32_to_cpu(*(__be32 *)sig);
-
- /* Dircache filesystems are compatible with non-dircache ones
- * when reading. As long as they aren't supported, writing is
- * not recommended.
- */
- if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
- || chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) {
- printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
- sb->s_id);
- sb->s_flags |= MS_RDONLY;
- }
- switch (chksum) {
- case MUFS_FS:
- case MUFS_INTLFFS:
- case MUFS_DCFFS:
- sbi->s_flags |= SF_MUFS;
- /* fall thru */
- case FS_INTLFFS:
- case FS_DCFFS:
- sbi->s_flags |= SF_INTL;
- break;
- case MUFS_FFS:
- sbi->s_flags |= SF_MUFS;
- break;
- case FS_FFS:
- break;
- case MUFS_OFS:
- sbi->s_flags |= SF_MUFS;
- /* fall thru */
- case FS_OFS:
- sbi->s_flags |= SF_OFS;
- sb->s_flags |= MS_NOEXEC;
- break;
- case MUFS_DCOFS:
- case MUFS_INTLOFS:
- sbi->s_flags |= SF_MUFS;
- case FS_DCOFS:
- case FS_INTLOFS:
- sbi->s_flags |= SF_INTL | SF_OFS;
- sb->s_flags |= MS_NOEXEC;
- break;
- default:
- printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n",
- sb->s_id, chksum);
- goto out_error;
- }
-
- if (mount_flags & SF_VERBOSE) {
- u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0];
- printk(KERN_NOTICE "AFFS: Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n",
- len > 31 ? 31 : len,
- AFFS_ROOT_TAIL(sb, root_bh)->disk_name + 1,
- sig, sig[3] + '0', blocksize);
- }
-
- sb->s_flags |= MS_NODEV | MS_NOSUID;
-
- sbi->s_data_blksize = sb->s_blocksize;
- if (sbi->s_flags & SF_OFS)
- sbi->s_data_blksize -= 24;
-
- /* Keep super block in cache */
- sbi->s_root_bh = root_bh;
- /* N.B. after this point s_root_bh must be released */
-
- tmp_flags = sb->s_flags;
- if (affs_init_bitmap(sb, &tmp_flags))
- goto out_error;
- sb->s_flags = tmp_flags;
-
- /* set up enough so that it can read an inode */
-
- root_inode = affs_iget(sb, root_block);
- if (IS_ERR(root_inode)) {
- ret = PTR_ERR(root_inode);
- goto out_error;
- }
-
- if (AFFS_SB(sb)->s_flags & SF_INTL)
- sb->s_d_op = &affs_intl_dentry_operations;
- else
- sb->s_d_op = &affs_dentry_operations;
-
- sb->s_root = d_make_root(root_inode);
- if (!sb->s_root) {
- printk(KERN_ERR "AFFS: Get root inode failed\n");
- goto out_error;
- }
-
- pr_debug("AFFS: s_flags=%lX\n",sb->s_flags);
- return 0;
-
- /*
- * Begin the cascaded cleanup ...
- */
-out_error:
- kfree(sbi->s_bitmap);
- affs_brelse(root_bh);
- kfree(sbi->s_prefix);
- kfree(sbi);
- sb->s_fs_info = NULL;
- return ret;
-}
-
-static int
-affs_remount(struct super_block *sb, int *flags, char *data)
-{
- struct affs_sb_info *sbi = AFFS_SB(sb);
- int blocksize;
- uid_t uid;
- gid_t gid;
- int mode;
- int reserved;
- int root_block;
- unsigned long mount_flags;
- int res = 0;
- char *new_opts = kstrdup(data, GFP_KERNEL);
- char volume[32];
- char *prefix = NULL;
-
- pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
-
- *flags |= MS_NODIRATIME;
-
- memcpy(volume, sbi->s_volume, 32);
- if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block,
- &blocksize, &prefix, volume,
- &mount_flags)) {
- kfree(prefix);
- kfree(new_opts);
- return -EINVAL;
- }
-
- replace_mount_options(sb, new_opts);
-
- sbi->s_flags = mount_flags;
- sbi->s_mode = mode;
- sbi->s_uid = uid;
- sbi->s_gid = gid;
- /* protect against readers */
- spin_lock(&sbi->symlink_lock);
- if (prefix) {
- kfree(sbi->s_prefix);
- sbi->s_prefix = prefix;
- }
- memcpy(sbi->s_volume, volume, 32);
- spin_unlock(&sbi->symlink_lock);
-
- if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
- return 0;
-
- if (*flags & MS_RDONLY) {
- affs_write_super(sb);
- affs_free_bitmap(sb);
- } else
- res = affs_init_bitmap(sb, flags);
-
- return res;
-}
-
-static int
-affs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
- struct super_block *sb = dentry->d_sb;
- int free;
- u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
-
- pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size,
- AFFS_SB(sb)->s_reserved);
-
- free = affs_count_free_blocks(sb);
- buf->f_type = AFFS_SUPER_MAGIC;
- buf->f_bsize = sb->s_blocksize;
- buf->f_blocks = AFFS_SB(sb)->s_partition_size - AFFS_SB(sb)->s_reserved;
- buf->f_bfree = free;
- buf->f_bavail = free;
- buf->f_fsid.val[0] = (u32)id;
- buf->f_fsid.val[1] = (u32)(id >> 32);
- buf->f_namelen = 30;
- return 0;
-}
-
-static struct dentry *affs_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
-{
- return mount_bdev(fs_type, flags, dev_name, data, affs_fill_super);
-}
-
-static struct file_system_type affs_fs_type = {
- .owner = THIS_MODULE,
- .name = "affs",
- .mount = affs_mount,
- .kill_sb = kill_block_super,
- .fs_flags = FS_REQUIRES_DEV,
-};
-
-static int __init init_affs_fs(void)
-{
- int err = init_inodecache();
- if (err)
- goto out1;
- err = register_filesystem(&affs_fs_type);
- if (err)
- goto out;
- return 0;
-out:
- destroy_inodecache();
-out1:
- return err;
-}
-
-static void __exit exit_affs_fs(void)
-{
- unregister_filesystem(&affs_fs_type);
- destroy_inodecache();
-}
-
-MODULE_DESCRIPTION("Amiga filesystem support for Linux");
-MODULE_LICENSE("GPL");
-
-module_init(init_affs_fs)
-module_exit(exit_affs_fs)
diff --git a/ANDROID_3.4.5/fs/affs/symlink.c b/ANDROID_3.4.5/fs/affs/symlink.c
deleted file mode 100644
index ee00f08c..00000000
--- a/ANDROID_3.4.5/fs/affs/symlink.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * linux/fs/affs/symlink.c
- *
- * 1995 Hans-Joachim Widmaier - Modified for affs.
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * affs symlink handling code
- */
-
-#include "affs.h"
-
-static int affs_symlink_readpage(struct file *file, struct page *page)
-{
- struct buffer_head *bh;
- struct inode *inode = page->mapping->host;
- char *link = kmap(page);
- struct slink_front *lf;
- int err;
- int i, j;
- char c;
- char lc;
-
- pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
-
- err = -EIO;
- bh = affs_bread(inode->i_sb, inode->i_ino);
- if (!bh)
- goto fail;
- i = 0;
- j = 0;
- lf = (struct slink_front *)bh->b_data;
- lc = 0;
-
- if (strchr(lf->symname,':')) { /* Handle assign or volume name */
- struct affs_sb_info *sbi = AFFS_SB(inode->i_sb);
- char *pf;
- spin_lock(&sbi->symlink_lock);
- pf = sbi->s_prefix ? sbi->s_prefix : "/";
- while (i < 1023 && (c = pf[i]))
- link[i++] = c;
- spin_unlock(&sbi->symlink_lock);
- while (i < 1023 && lf->symname[j] != ':')
- link[i++] = lf->symname[j++];
- if (i < 1023)
- link[i++] = '/';
- j++;
- lc = '/';
- }
- while (i < 1023 && (c = lf->symname[j])) {
- if (c == '/' && lc == '/' && i < 1020) { /* parent dir */
- link[i++] = '.';
- link[i++] = '.';
- }
- link[i++] = c;
- lc = c;
- j++;
- }
- link[i] = '\0';
- affs_brelse(bh);
- SetPageUptodate(page);
- kunmap(page);
- unlock_page(page);
- return 0;
-fail:
- SetPageError(page);
- kunmap(page);
- unlock_page(page);
- return err;
-}
-
-const struct address_space_operations affs_symlink_aops = {
- .readpage = affs_symlink_readpage,
-};
-
-const struct inode_operations affs_symlink_inode_operations = {
- .readlink = generic_readlink,
- .follow_link = page_follow_link_light,
- .put_link = page_put_link,
- .setattr = affs_notify_change,
-};