]> git.hungrycats.org Git - linux/commitdiff
[PATCH] fat: fs/fat/* cleanup
authorHirofumi Ogawa <hirofumi@mail.parknet.co.jp>
Fri, 21 Jan 2005 00:14:33 +0000 (16:14 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 21 Jan 2005 00:14:33 +0000 (16:14 -0800)
This patch is just cleanup (whitespace, and place of functions is changed).
No changes of logic.

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/fat/cache.c
fs/fat/dir.c
fs/fat/file.c
fs/fat/inode.c
fs/fat/misc.c
include/linux/msdos_fs.h

index c94447df328f6975bb2b088e8632849004c93a72..9de8c61d51b2c3f270dcdecaf772ff4d861d0bf3 100644 (file)
@@ -296,7 +296,7 @@ static int __fat_access(struct super_block *sb, int nr, int new_value)
        return next;
 }
 
-/* 
+/*
  * Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
  * new_value is != -1, that FAT entry is replaced by it.
  */
@@ -343,7 +343,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
        int nr;
 
        BUG_ON(MSDOS_I(inode)->i_start == 0);
-       
+
        *fclus = 0;
        *dclus = MSDOS_I(inode)->i_start;
        if (cluster == 0)
@@ -368,7 +368,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
 
                nr = fat_access(sb, *dclus, -1);
                if (nr < 0)
-                       return nr;
+                       return nr;
                else if (nr == FAT_ENT_FREE) {
                        fat_fs_panic(sb, "%s: invalid cluster chain"
                                     " (i_pos %lld)", __FUNCTION__,
@@ -437,65 +437,3 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys)
        }
        return 0;
 }
-
-/* Free all clusters after the skip'th cluster. */
-int fat_free(struct inode *inode, int skip)
-{
-       struct super_block *sb = inode->i_sb;
-       int nr, ret, fclus, dclus;
-
-       if (MSDOS_I(inode)->i_start == 0)
-               return 0;
-
-       if (skip) {
-               ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
-               if (ret < 0)
-                       return ret;
-               else if (ret == FAT_ENT_EOF)
-                       return 0;
-
-               nr = fat_access(sb, dclus, -1);
-               if (nr == FAT_ENT_EOF)
-                       return 0;
-               else if (nr > 0) {
-                       /*
-                        * write a new EOF, and get the remaining cluster
-                        * chain for freeing.
-                        */
-                       nr = fat_access(sb, dclus, FAT_ENT_EOF);
-               }
-               if (nr < 0)
-                       return nr;
-
-               fat_cache_inval_inode(inode);
-       } else {
-               fat_cache_inval_inode(inode);
-
-               nr = MSDOS_I(inode)->i_start;
-               MSDOS_I(inode)->i_start = 0;
-               MSDOS_I(inode)->i_logstart = 0;
-               mark_inode_dirty(inode);
-       }
-
-       lock_fat(sb);
-       do {
-               nr = fat_access(sb, nr, FAT_ENT_FREE);
-               if (nr < 0)
-                       goto error;
-               else if (nr == FAT_ENT_FREE) {
-                       fat_fs_panic(sb, "%s: deleting beyond EOF (i_pos %lld)",
-                                    __FUNCTION__, MSDOS_I(inode)->i_pos);
-                       nr = -EIO;
-                       goto error;
-               }
-               if (MSDOS_SB(sb)->free_clusters != -1)
-                       MSDOS_SB(sb)->free_clusters++;
-               inode->i_blocks -= MSDOS_SB(sb)->cluster_size >> 9;
-       } while (nr != FAT_ENT_EOF);
-       fat_clusters_flush(sb);
-       nr = 0;
-error:
-       unlock_fat(sb);
-
-       return nr;
-}
index 91e22d5ddad6a5212613875d6d42e1138fa7525a..f5fd49583dde494aa21b8f43854eae1756422be9 100644 (file)
 #include <linux/dirent.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
-
 #include <asm/uaccess.h>
 
-static int fat_dir_ioctl(struct inode * inode, struct file * filp,
-                 unsigned int cmd, unsigned long arg);
-static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir);
-
-struct file_operations fat_dir_operations = {
-       .read           = generic_read_dir,
-       .readdir        = fat_readdir,
-       .ioctl          = fat_dir_ioctl,
-       .fsync          = file_fsync,
-};
-
 /*
  * Convert Unicode 16 to UTF8, translated Unicode, or ASCII.
  * If uni_xlate is enabled and we can't get a 1:1 conversion, use a
@@ -44,9 +32,8 @@ struct file_operations fat_dir_operations = {
  * but ignore that right now.
  * Ahem... Stack smashing in ring 0 isn't fun. Fixed.
  */
-static int
-uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,
-           struct nls_table *nls)
+static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,
+                      struct nls_table *nls)
 {
        wchar_t *ip, ec;
        unsigned char *op, nc;
@@ -84,20 +71,6 @@ uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,
        return (op - ascii);
 }
 
-#if 0
-static void dump_de(struct msdos_dir_entry *de)
-{
-       int i;
-       unsigned char *p = (unsigned char *) de;
-       printk("[");
-
-       for (i = 0; i < 32; i++, p++) {
-               printk("%02x ", *p);
-       }
-       printk("]\n");
-}
-#endif
-
 static inline int
 fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
 {
@@ -123,17 +96,17 @@ fat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *un
                charlen = 1;
        } else if (charlen <= 1) {
                unsigned char nc = t->charset2lower[*c];
-               
+
                if (!nc)
                        nc = *c;
-               
+
                if ( (charlen = t->char2uni(&nc, 1, uni)) < 0) {
                        *uni = 0x003f;  /* a question mark */
                        charlen = 1;
                }
        } else
                *uni = wc;
-       
+
        return charlen;
 }
 
@@ -150,7 +123,7 @@ fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size,
        else if (opt & VFAT_SFN_DISPLAY_WINNT) {
                if (lower)
                        len = fat_short2lower_uni(nls, buf, buf_size, uni_buf);
-               else 
+               else
                        len = fat_short2uni(nls, buf, buf_size, uni_buf);
        } else
                len = fat_short2uni(nls, buf, buf_size, uni_buf);
@@ -326,6 +299,8 @@ EODir:
        return res;
 }
 
+EXPORT_SYMBOL(fat_search_long);
+
 struct fat_ioctl_filldir_callback {
        struct dirent __user *dirent;
        int result;
@@ -336,8 +311,6 @@ struct fat_ioctl_filldir_callback {
        int short_len;
 };
 
-EXPORT_SYMBOL(fat_search_long);
-
 static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
                        filldir_t filldir, int short_only, int both)
 {
@@ -362,7 +335,7 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
        int chi, chl, i, i2, j, last, last_u, dotoffset = 0;
        loff_t i_pos, cpos;
        int ret = 0;
-       
+
        lock_kernel();
 
        cpos = filp->f_pos;
@@ -385,7 +358,7 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
                goto out;
        }
 
-       bh = NULL;
+       bh = NULL;
 GetNew:
        long_slots = 0;
        if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
@@ -694,6 +667,132 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp,
        return ret;
 }
 
+struct file_operations fat_dir_operations = {
+       .read           = generic_read_dir,
+       .readdir        = fat_readdir,
+       .ioctl          = fat_dir_ioctl,
+       .fsync          = file_fsync,
+};
+
+static int fat_get_short_entry(struct inode *dir, loff_t *pos,
+                              struct buffer_head **bh,
+                              struct msdos_dir_entry **de, loff_t *i_pos)
+{
+       while (fat_get_entry(dir, pos, bh, de, i_pos) >= 0) {
+               /* free entry or long name entry or volume label */
+               if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME))
+                       return 0;
+       }
+       return -ENOENT;
+}
+
+/* See if directory is empty */
+int fat_dir_empty(struct inode *dir)
+{
+       struct buffer_head *bh;
+       struct msdos_dir_entry *de;
+       loff_t cpos, i_pos;
+       int result = 0;
+
+       bh = NULL;
+       cpos = 0;
+       while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
+               if (strncmp(de->name, MSDOS_DOT   , MSDOS_NAME) &&
+                   strncmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
+                       result = -ENOTEMPTY;
+                       break;
+               }
+       }
+       brelse(bh);
+       return result;
+}
+
+EXPORT_SYMBOL(fat_dir_empty);
+
+/*
+ * fat_subdirs counts the number of sub-directories of dir. It can be run
+ * on directories being created.
+ */
+int fat_subdirs(struct inode *dir)
+{
+       struct buffer_head *bh;
+       struct msdos_dir_entry *de;
+       loff_t cpos, i_pos;
+       int count = 0;
+
+       bh = NULL;
+       cpos = 0;
+       while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
+               if (de->attr & ATTR_DIR)
+                       count++;
+       }
+       brelse(bh);
+       return count;
+}
+
+/*
+ * Scans a directory for a given file (name points to its formatted name).
+ * Returns an error code or zero.
+ */
+int fat_scan(struct inode *dir, const unsigned char *name,
+            struct buffer_head **bh, struct msdos_dir_entry **de,
+            loff_t *i_pos)
+{
+       loff_t cpos;
+
+       *bh = NULL;
+       cpos = 0;
+       while (fat_get_short_entry(dir, &cpos, bh, de, i_pos) >= 0) {
+               if (!strncmp((*de)->name, name, MSDOS_NAME))
+                       return 0;
+       }
+       return -ENOENT;
+}
+
+EXPORT_SYMBOL(fat_scan);
+
+static struct buffer_head *fat_extend_dir(struct inode *inode)
+{
+       struct super_block *sb = inode->i_sb;
+       struct buffer_head *bh, *res = NULL;
+       int nr, sec_per_clus = MSDOS_SB(sb)->sec_per_clus;
+       sector_t sector, last_sector;
+
+       if (MSDOS_SB(sb)->fat_bits != 32) {
+               if (inode->i_ino == MSDOS_ROOT_INO)
+                       return ERR_PTR(-ENOSPC);
+       }
+
+       nr = fat_add_cluster(inode);
+       if (nr < 0)
+               return ERR_PTR(nr);
+
+       sector = ((sector_t)nr - 2) * sec_per_clus + MSDOS_SB(sb)->data_start;
+       last_sector = sector + sec_per_clus;
+       for ( ; sector < last_sector; sector++) {
+               if ((bh = sb_getblk(sb, sector))) {
+                       memset(bh->b_data, 0, sb->s_blocksize);
+                       set_buffer_uptodate(bh);
+                       mark_buffer_dirty(bh);
+                       if (!res)
+                               res = bh;
+                       else
+                               brelse(bh);
+               }
+       }
+       if (res == NULL)
+               res = ERR_PTR(-EIO);
+       if (inode->i_size & (sb->s_blocksize - 1)) {
+               fat_fs_panic(sb, "Odd directory size");
+               inode->i_size = (inode->i_size + sb->s_blocksize)
+                       & ~((loff_t)sb->s_blocksize - 1);
+       }
+       inode->i_size += MSDOS_SB(sb)->cluster_size;
+       MSDOS_I(inode)->mmu_private += MSDOS_SB(sb)->cluster_size;
+
+       return res;
+}
+
 /* This assumes that size of cluster is above the 32*slots */
 
 int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
@@ -722,7 +821,7 @@ int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
                        offset = curr;
                }
        }
-       if ((dir->i_ino == MSDOS_ROOT_INO) && (MSDOS_SB(sb)->fat_bits != 32)) 
+       if ((dir->i_ino == MSDOS_ROOT_INO) && (MSDOS_SB(sb)->fat_bits != 32))
                return -ENOSPC;
        new_bh = fat_extend_dir(dir);
        if (IS_ERR(new_bh))
@@ -773,80 +872,3 @@ int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat)
 }
 
 EXPORT_SYMBOL(fat_new_dir);
-
-static int fat_get_short_entry(struct inode *dir, loff_t *pos,
-                              struct buffer_head **bh,
-                              struct msdos_dir_entry **de, loff_t *i_pos)
-{
-       while (fat_get_entry(dir, pos, bh, de, i_pos) >= 0) {
-               /* free entry or long name entry or volume label */
-               if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME))
-                       return 0;
-       }
-       return -ENOENT;
-}
-
-/* See if directory is empty */
-int fat_dir_empty(struct inode *dir)
-{
-       struct buffer_head *bh;
-       struct msdos_dir_entry *de;
-       loff_t cpos, i_pos;
-       int result = 0;
-
-       bh = NULL;
-       cpos = 0;
-       while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
-               if (strncmp(de->name, MSDOS_DOT   , MSDOS_NAME) &&
-                   strncmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
-                       result = -ENOTEMPTY;
-                       break;
-               }
-       }
-       brelse(bh);
-       return result;
-}
-
-EXPORT_SYMBOL(fat_dir_empty);
-
-/*
- * fat_subdirs counts the number of sub-directories of dir. It can be run
- * on directories being created.
- */
-int fat_subdirs(struct inode *dir)
-{
-       struct buffer_head *bh;
-       struct msdos_dir_entry *de;
-       loff_t cpos, i_pos;
-       int count = 0;
-
-       bh = NULL;
-       cpos = 0;
-       while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
-               if (de->attr & ATTR_DIR)
-                       count++;
-       }
-       brelse(bh);
-       return count;
-}
-
-/*
- * Scans a directory for a given file (name points to its formatted name).
- * Returns an error code or zero.
- */
-int fat_scan(struct inode *dir, const unsigned char *name,
-            struct buffer_head **bh, struct msdos_dir_entry **de,
-            loff_t *i_pos)
-{
-       loff_t cpos;
-
-       *bh = NULL;
-       cpos = 0;
-       while (fat_get_short_entry(dir, &cpos, bh, de, i_pos) >= 0) {
-               if (!strncmp((*de)->name, name, MSDOS_NAME))
-                       return 0;
-       }
-       return -ENOENT;
-}
-
-EXPORT_SYMBOL(fat_scan);
index 16606a151e263ba449c2ebd96419945f1fe22aba..815f219064c502f69ca71d80839d6759176649c0 100644 (file)
@@ -6,13 +6,26 @@
  *  regular file handling primitives for fat-based filesystems
  */
 
+#include <linux/module.h>
 #include <linux/time.h>
 #include <linux/msdos_fs.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 
 static ssize_t fat_file_write(struct file *filp, const char __user *buf,
-                             size_t count, loff_t *ppos);
+                             size_t count, loff_t *ppos)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       int retval;
+
+       retval = generic_file_write(filp, buf, count, ppos);
+       if (retval > 0) {
+               inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+               MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+               mark_inode_dirty(inode);
+       }
+       return retval;
+}
 
 struct file_operations fat_file_operations = {
        .llseek         = generic_file_llseek,
@@ -25,63 +38,117 @@ struct file_operations fat_file_operations = {
        .sendfile       = generic_file_sendfile,
 };
 
-struct inode_operations fat_file_inode_operations = {
-       .truncate       = fat_truncate,
-       .setattr        = fat_notify_change,
-};
-
-int fat_get_block(struct inode *inode, sector_t iblock,
-                 struct buffer_head *bh_result, int create)
+int fat_notify_change(struct dentry *dentry, struct iattr *attr)
 {
-       struct super_block *sb = inode->i_sb;
-       sector_t phys;
-       int err;
-
-       err = fat_bmap(inode, iblock, &phys);
-       if (err)
-               return err;
-       if (phys) {
-               map_bh(bh_result, sb, phys);
-               return 0;
+       struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
+       struct inode *inode = dentry->d_inode;
+       int mask, error = 0;
+
+       lock_kernel();
+
+       /* FAT cannot truncate to a longer file */
+       if (attr->ia_valid & ATTR_SIZE) {
+               if (attr->ia_size > inode->i_size) {
+                       error = -EPERM;
+                       goto out;
+               }
        }
-       if (!create)
-               return 0;
-       if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
-               fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)",
-                            MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
-               return -EIO;
+
+       error = inode_change_ok(inode, attr);
+       if (error) {
+               if (sbi->options.quiet)
+                       error = 0;
+               goto out;
        }
-       if (!((unsigned long)iblock & (MSDOS_SB(sb)->sec_per_clus - 1))) {
-               int error;
+       if (((attr->ia_valid & ATTR_UID) &&
+            (attr->ia_uid != sbi->options.fs_uid)) ||
+           ((attr->ia_valid & ATTR_GID) &&
+            (attr->ia_gid != sbi->options.fs_gid)) ||
+           ((attr->ia_valid & ATTR_MODE) &&
+            (attr->ia_mode & ~MSDOS_VALID_MODE)))
+               error = -EPERM;
 
-               error = fat_add_cluster(inode);
-               if (error < 0)
-                       return error;
+       if (error) {
+               if (sbi->options.quiet)
+                       error = 0;
+               goto out;
        }
-       MSDOS_I(inode)->mmu_private += sb->s_blocksize;
-       err = fat_bmap(inode, iblock, &phys);
-       if (err)
-               return err;
-       if (!phys)
-               BUG();
-       set_buffer_new(bh_result);
-       map_bh(bh_result, sb, phys);
-       return 0;
+       error = inode_setattr(inode, attr);
+       if (error)
+               goto out;
+
+       if (S_ISDIR(inode->i_mode))
+               mask = sbi->options.fs_dmask;
+       else
+               mask = sbi->options.fs_fmask;
+       inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
+out:
+       unlock_kernel();
+       return error;
 }
 
-static ssize_t fat_file_write(struct file *filp, const char __user *buf,
-                             size_t count, loff_t *ppos)
+EXPORT_SYMBOL(fat_notify_change);
+
+/* Free all clusters after the skip'th cluster. */
+static int fat_free(struct inode *inode, int skip)
 {
-       struct inode *inode = filp->f_dentry->d_inode;
-       int retval;
+       struct super_block *sb = inode->i_sb;
+       int nr, ret, fclus, dclus;
 
-       retval = generic_file_write(filp, buf, count, ppos);
-       if (retval > 0) {
-               inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
-               MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+       if (MSDOS_I(inode)->i_start == 0)
+               return 0;
+
+       if (skip) {
+               ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
+               if (ret < 0)
+                       return ret;
+               else if (ret == FAT_ENT_EOF)
+                       return 0;
+
+               nr = fat_access(sb, dclus, -1);
+               if (nr == FAT_ENT_EOF)
+                       return 0;
+               else if (nr > 0) {
+                       /*
+                        * write a new EOF, and get the remaining cluster
+                        * chain for freeing.
+                        */
+                       nr = fat_access(sb, dclus, FAT_ENT_EOF);
+               }
+               if (nr < 0)
+                       return nr;
+
+               fat_cache_inval_inode(inode);
+       } else {
+               fat_cache_inval_inode(inode);
+
+               nr = MSDOS_I(inode)->i_start;
+               MSDOS_I(inode)->i_start = 0;
+               MSDOS_I(inode)->i_logstart = 0;
                mark_inode_dirty(inode);
        }
-       return retval;
+
+       lock_fat(sb);
+       do {
+               nr = fat_access(sb, nr, FAT_ENT_FREE);
+               if (nr < 0)
+                       goto error;
+               else if (nr == FAT_ENT_FREE) {
+                       fat_fs_panic(sb, "%s: deleting beyond EOF (i_pos %lld)",
+                                    __FUNCTION__, MSDOS_I(inode)->i_pos);
+                       nr = -EIO;
+                       goto error;
+               }
+               if (MSDOS_SB(sb)->free_clusters != -1)
+                       MSDOS_SB(sb)->free_clusters++;
+               inode->i_blocks -= MSDOS_SB(sb)->cluster_size >> 9;
+       } while (nr != FAT_ENT_EOF);
+       fat_clusters_flush(sb);
+       nr = 0;
+error:
+       unlock_fat(sb);
+
+       return nr;
 }
 
 void fat_truncate(struct inode *inode)
@@ -90,7 +157,7 @@ void fat_truncate(struct inode *inode)
        const unsigned int cluster_size = sbi->cluster_size;
        int nr_clusters;
 
-       /* 
+       /*
         * This protects against truncating a file bigger than it was then
         * trying to write into the hole.
         */
@@ -106,3 +173,8 @@ void fat_truncate(struct inode *inode)
        inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
 }
+
+struct inode_operations fat_file_inode_operations = {
+       .truncate       = fat_truncate,
+       .setattr        = fat_notify_change,
+};
index 5f148b0822c8d5fc630a7902f6539f6eea7d3565..487ae266c2b575294e2d77ce6c33d468d1967b94 100644 (file)
@@ -7,7 +7,7 @@
  *
  *  Fixes:
  *
- *     Max Cohan: Fixed invalid FSINFO offset when info_sector is 0
+ *     Max Cohan: Fixed invalid FSINFO offset when info_sector is 0
  */
 
 #include <linux/module.h>
 static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
 static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
 
-static int fat_statfs(struct super_block *sb, struct kstatfs *buf);
-static int fat_write_inode(struct inode *inode, int wait);
+
+static int fat_get_block(struct inode *inode, sector_t iblock,
+                        struct buffer_head *bh_result, int create)
+{
+       struct super_block *sb = inode->i_sb;
+       sector_t phys;
+       int err;
+
+       err = fat_bmap(inode, iblock, &phys);
+       if (err)
+               return err;
+       if (phys) {
+               map_bh(bh_result, sb, phys);
+               return 0;
+       }
+       if (!create)
+               return 0;
+       if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
+               fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)",
+                            MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
+               return -EIO;
+       }
+       if (!((unsigned long)iblock & (MSDOS_SB(sb)->sec_per_clus - 1))) {
+               int error;
+
+               error = fat_add_cluster(inode);
+               if (error < 0)
+                       return error;
+       }
+       MSDOS_I(inode)->mmu_private += sb->s_blocksize;
+       err = fat_bmap(inode, iblock, &phys);
+       if (err)
+               return err;
+       if (!phys)
+               BUG();
+       set_buffer_new(bh_result);
+       map_bh(bh_result, sb, phys);
+       return 0;
+}
+
+static int fat_writepage(struct page *page, struct writeback_control *wbc)
+{
+       return block_write_full_page(page, fat_get_block, wbc);
+}
+
+static int fat_readpage(struct file *file, struct page *page)
+{
+       return block_read_full_page(page, fat_get_block);
+}
+
+static int fat_prepare_write(struct file *file, struct page *page,
+                            unsigned from, unsigned to)
+{
+       return cont_prepare_write(page, from, to, fat_get_block,
+                                 &MSDOS_I(page->mapping->host)->mmu_private);
+}
+
+static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
+{
+       return generic_block_bmap(mapping, block, fat_get_block);
+}
+
+static struct address_space_operations fat_aops = {
+       .readpage       = fat_readpage,
+       .writepage      = fat_writepage,
+       .sync_page      = block_sync_page,
+       .prepare_write  = fat_prepare_write,
+       .commit_write   = generic_commit_write,
+       .bmap           = _fat_bmap
+};
 
 /*
  * New FAT inode stuff. We do the following:
@@ -122,7 +190,102 @@ struct inode *fat_iget(struct super_block *sb, loff_t i_pos)
        return inode;
 }
 
-static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de);
+static int is_exec(unsigned char *extension)
+{
+       unsigned char *exe_extensions = "EXECOMBAT", *walk;
+
+       for (walk = exe_extensions; *walk; walk += 3)
+               if (!strncmp(extension, walk, 3))
+                       return 1;
+       return 0;
+}
+
+static int fat_calc_dir_size(struct inode *inode)
+{
+       struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+       int ret, fclus, dclus;
+
+       inode->i_size = 0;
+       if (MSDOS_I(inode)->i_start == 0)
+               return 0;
+
+       ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
+       if (ret < 0)
+               return ret;
+       inode->i_size = (fclus + 1) << sbi->cluster_bits;
+
+       return 0;
+}
+
+/* doesn't deal with root inode */
+static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
+{
+       struct super_block *sb = inode->i_sb;
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       int error;
+
+       MSDOS_I(inode)->i_pos = 0;
+       inode->i_uid = sbi->options.fs_uid;
+       inode->i_gid = sbi->options.fs_gid;
+       inode->i_version++;
+       inode->i_generation = get_seconds();
+
+       if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {
+               inode->i_generation &= ~1;
+               inode->i_mode = MSDOS_MKMODE(de->attr,
+                       S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR;
+               inode->i_op = sbi->dir_ops;
+               inode->i_fop = &fat_dir_operations;
+
+               MSDOS_I(inode)->i_start = le16_to_cpu(de->start);
+               if (sbi->fat_bits == 32)
+                       MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16);
+
+               MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
+               error = fat_calc_dir_size(inode);
+               if (error < 0)
+                       return error;
+               MSDOS_I(inode)->mmu_private = inode->i_size;
+
+               inode->i_nlink = fat_subdirs(inode);
+       } else { /* not a directory */
+               inode->i_generation |= 1;
+               inode->i_mode = MSDOS_MKMODE(de->attr,
+                   ((sbi->options.showexec &&
+                       !is_exec(de->ext))
+                       ? S_IRUGO|S_IWUGO : S_IRWXUGO)
+                   & ~sbi->options.fs_fmask) | S_IFREG;
+               MSDOS_I(inode)->i_start = le16_to_cpu(de->start);
+               if (sbi->fat_bits == 32)
+                       MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16);
+
+               MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
+               inode->i_size = le32_to_cpu(de->size);
+               inode->i_op = &fat_file_inode_operations;
+               inode->i_fop = &fat_file_operations;
+               inode->i_mapping->a_ops = &fat_aops;
+               MSDOS_I(inode)->mmu_private = inode->i_size;
+       }
+       if(de->attr & ATTR_SYS)
+               if (sbi->options.sys_immutable)
+                       inode->i_flags |= S_IMMUTABLE;
+       MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
+       /* this is as close to the truth as we can get ... */
+       inode->i_blksize = sbi->cluster_size;
+       inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
+                          & ~((loff_t)sbi->cluster_size - 1)) >> 9;
+       inode->i_mtime.tv_sec = inode->i_atime.tv_sec =
+               date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date));
+       inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0;
+       inode->i_ctime.tv_sec =
+               MSDOS_SB(sb)->options.isvfat
+               ? date_dos2unix(le16_to_cpu(de->ctime), le16_to_cpu(de->cdate))
+               : inode->i_mtime.tv_sec;
+       inode->i_ctime.tv_nsec = de->ctime_ms * 1000000;
+       MSDOS_I(inode)->i_ctime_ms = de->ctime_ms;
+
+       return 0;
+}
 
 struct inode *fat_build_inode(struct super_block *sb,
                        struct msdos_dir_entry *de, loff_t i_pos, int *res)
@@ -196,10 +359,324 @@ static void fat_put_super(struct super_block *sb)
                sbi->options.iocharset = fat_default_iocharset;
        }
 
-       sb->s_fs_info = NULL;
-       kfree(sbi);
+       sb->s_fs_info = NULL;
+       kfree(sbi);
+}
+
+static kmem_cache_t *fat_inode_cachep;
+
+static struct inode *fat_alloc_inode(struct super_block *sb)
+{
+       struct msdos_inode_info *ei;
+       ei = kmem_cache_alloc(fat_inode_cachep, SLAB_KERNEL);
+       if (!ei)
+               return NULL;
+       return &ei->vfs_inode;
+}
+
+static void fat_destroy_inode(struct inode *inode)
+{
+       kmem_cache_free(fat_inode_cachep, MSDOS_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+       struct msdos_inode_info *ei = (struct msdos_inode_info *)foo;
+
+       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+           SLAB_CTOR_CONSTRUCTOR) {
+               spin_lock_init(&ei->cache_lru_lock);
+               ei->nr_caches = 0;
+               ei->cache_valid_id = FAT_CACHE_VALID + 1;
+               INIT_LIST_HEAD(&ei->cache_lru);
+               INIT_HLIST_NODE(&ei->i_fat_hash);
+               inode_init_once(&ei->vfs_inode);
+       }
+}
+
+static int __init fat_init_inodecache(void)
+{
+       fat_inode_cachep = kmem_cache_create("fat_inode_cache",
+                                            sizeof(struct msdos_inode_info),
+                                            0, SLAB_RECLAIM_ACCOUNT,
+                                            init_once, NULL);
+       if (fat_inode_cachep == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+static void __exit fat_destroy_inodecache(void)
+{
+       if (kmem_cache_destroy(fat_inode_cachep))
+               printk(KERN_INFO "fat_inode_cache: not all structures were freed\n");
+}
+
+static int fat_remount(struct super_block *sb, int *flags, char *data)
+{
+       *flags |= MS_NODIRATIME;
+       return 0;
+}
+
+static int fat_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+       int free, nr, ret;
+
+       if (MSDOS_SB(sb)->free_clusters != -1)
+               free = MSDOS_SB(sb)->free_clusters;
+       else {
+               lock_fat(sb);
+               if (MSDOS_SB(sb)->free_clusters != -1)
+                       free = MSDOS_SB(sb)->free_clusters;
+               else {
+                       free = 0;
+                       for (nr = 2; nr < MSDOS_SB(sb)->clusters + 2; nr++) {
+                               ret = fat_access(sb, nr, -1);
+                               if (ret < 0) {
+                                       unlock_fat(sb);
+                                       return ret;
+                               } else if (ret == FAT_ENT_FREE)
+                                       free++;
+                       }
+                       MSDOS_SB(sb)->free_clusters = free;
+               }
+               unlock_fat(sb);
+       }
+
+       buf->f_type = sb->s_magic;
+       buf->f_bsize = MSDOS_SB(sb)->cluster_size;
+       buf->f_blocks = MSDOS_SB(sb)->clusters;
+       buf->f_bfree = free;
+       buf->f_bavail = free;
+       buf->f_namelen = MSDOS_SB(sb)->options.isvfat ? 260 : 12;
+
+       return 0;
+}
+
+static int fat_write_inode(struct inode *inode, int wait)
+{
+       struct super_block *sb = inode->i_sb;
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       struct buffer_head *bh;
+       struct msdos_dir_entry *raw_entry;
+       loff_t i_pos;
+
+retry:
+       i_pos = MSDOS_I(inode)->i_pos;
+       if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
+               return 0;
+       }
+       lock_kernel();
+       if (!(bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits))) {
+               printk(KERN_ERR "FAT: unable to read inode block "
+                      "for updating (i_pos %lld)\n", i_pos);
+               unlock_kernel();
+               return -EIO;
+       }
+       spin_lock(&sbi->inode_hash_lock);
+       if (i_pos != MSDOS_I(inode)->i_pos) {
+               spin_unlock(&sbi->inode_hash_lock);
+               brelse(bh);
+               unlock_kernel();
+               goto retry;
+       }
+
+       raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
+           [i_pos & (sbi->dir_per_block - 1)];
+       if (S_ISDIR(inode->i_mode)) {
+               raw_entry->attr = ATTR_DIR;
+               raw_entry->size = 0;
+       }
+       else {
+               raw_entry->attr = ATTR_NONE;
+               raw_entry->size = cpu_to_le32(inode->i_size);
+       }
+       raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
+           MSDOS_I(inode)->i_attrs;
+       raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
+       raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
+       fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
+       if (sbi->options.isvfat) {
+               fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
+               raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */
+       }
+       spin_unlock(&sbi->inode_hash_lock);
+       mark_buffer_dirty(bh);
+       brelse(bh);
+       unlock_kernel();
+       return 0;
+}
+
+static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);
+static struct super_operations fat_sops = {
+       .alloc_inode    = fat_alloc_inode,
+       .destroy_inode  = fat_destroy_inode,
+       .write_inode    = fat_write_inode,
+       .delete_inode   = fat_delete_inode,
+       .put_super      = fat_put_super,
+       .statfs         = fat_statfs,
+       .clear_inode    = fat_clear_inode,
+       .remount_fs     = fat_remount,
+
+       .read_inode     = make_bad_inode,
+
+       .show_options   = fat_show_options,
+};
+
+/*
+ * a FAT file handle with fhtype 3 is
+ *  0/  i_ino - for fast, reliable lookup if still in the cache
+ *  1/  i_generation - to see if i_ino is still valid
+ *          bit 0 == 0 iff directory
+ *  2/  i_pos(8-39) - if ino has changed, but still in cache
+ *  3/  i_pos(4-7)|i_logstart - to semi-verify inode found at i_pos
+ *  4/  i_pos(0-3)|parent->i_logstart - maybe used to hunt for the file on disc
+ *
+ * Hack for NFSv2: Maximum FAT entry number is 28bits and maximum
+ * i_pos is 40bits (blocknr(32) + dir offset(8)), so two 4bits
+ * of i_logstart is used to store the directory entry offset.
+ */
+
+static struct dentry *
+fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype,
+             int (*acceptable)(void *context, struct dentry *de),
+             void *context)
+{
+       if (fhtype != 3)
+               return ERR_PTR(-ESTALE);
+       if (len < 5)
+               return ERR_PTR(-ESTALE);
+
+       return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context);
+}
+
+static struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
+{
+       struct inode *inode = NULL;
+       struct dentry *result;
+       __u32 *fh = inump;
+
+       inode = iget(sb, fh[0]);
+       if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) {
+               if (inode)
+                       iput(inode);
+               inode = NULL;
+       }
+       if (!inode) {
+               loff_t i_pos;
+               int i_logstart = fh[3] & 0x0fffffff;
+
+               i_pos = (loff_t)fh[2] << 8;
+               i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28);
+
+               /* try 2 - see if i_pos is in F-d-c
+                * require i_logstart to be the same
+                * Will fail if you truncate and then re-write
+                */
+
+               inode = fat_iget(sb, i_pos);
+               if (inode && MSDOS_I(inode)->i_logstart != i_logstart) {
+                       iput(inode);
+                       inode = NULL;
+               }
+       }
+       if (!inode) {
+               /* For now, do nothing
+                * What we could do is:
+                * follow the file starting at fh[4], and record
+                * the ".." entry, and the name of the fh[2] entry.
+                * The follow the ".." file finding the next step up.
+                * This way we build a path to the root of
+                * the tree. If this works, we lookup the path and so
+                * get this inode into the cache.
+                * Finally try the fat_iget lookup again
+                * If that fails, then weare totally out of luck
+                * But all that is for another day
+                */
+       }
+       if (!inode)
+               return ERR_PTR(-ESTALE);
+
+
+       /* now to find a dentry.
+        * If possible, get a well-connected one
+        */
+       result = d_alloc_anon(inode);
+       if (result == NULL) {
+               iput(inode);
+               return ERR_PTR(-ENOMEM);
+       }
+       result->d_op = sb->s_root->d_op;
+       return result;
+}
+
+static int
+fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
+{
+       int len = *lenp;
+       struct inode *inode =  de->d_inode;
+       u32 ipos_h, ipos_m, ipos_l;
+
+       if (len < 5)
+               return 255; /* no room */
+
+       ipos_h = MSDOS_I(inode)->i_pos >> 8;
+       ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
+       ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28;
+       *lenp = 5;
+       fh[0] = inode->i_ino;
+       fh[1] = inode->i_generation;
+       fh[2] = ipos_h;
+       fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;
+       spin_lock(&de->d_lock);
+       fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart;
+       spin_unlock(&de->d_lock);
+       return 3;
+}
+
+static struct dentry *fat_get_parent(struct dentry *child)
+{
+       struct buffer_head *bh=NULL;
+       struct msdos_dir_entry *de = NULL;
+       struct dentry *parent = NULL;
+       int res;
+       loff_t i_pos = 0;
+       struct inode *inode;
+
+       lock_kernel();
+       res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &i_pos);
+
+       if (res < 0)
+               goto out;
+       inode = fat_build_inode(child->d_sb, de, i_pos, &res);
+       if (res)
+               goto out;
+       if (!inode)
+               res = -EACCES;
+       else {
+               parent = d_alloc_anon(inode);
+               if (!parent) {
+                       iput(inode);
+                       res = -ENOMEM;
+               }
+       }
+
+ out:
+       if(bh)
+               brelse(bh);
+       unlock_kernel();
+       if (res)
+               return ERR_PTR(res);
+       else
+               return parent;
 }
 
+static struct export_operations fat_export_ops = {
+       .decode_fh      = fat_decode_fh,
+       .encode_fh      = fat_encode_fh,
+       .get_dentry     = fat_get_dentry,
+       .get_parent     = fat_get_parent,
+};
+
 static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(mnt->mnt_sb);
@@ -516,23 +993,6 @@ static int parse_options(char *options, int is_vfat, int *debug,
 
        if (opts->unicode_xlate)
                opts->utf8 = 0;
-       
-       return 0;
-}
-
-static int fat_calc_dir_size(struct inode *inode)
-{
-       struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
-       int ret, fclus, dclus;
-
-       inode->i_size = 0;
-       if (MSDOS_I(inode)->i_start == 0)
-               return 0;
-
-       ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
-       if (ret < 0)
-               return ret;
-       inode->i_size = (fclus + 1) << sbi->cluster_bits;
 
        return 0;
 }
@@ -552,253 +1012,29 @@ static int fat_read_root(struct inode *inode)
        inode->i_op = sbi->dir_ops;
        inode->i_fop = &fat_dir_operations;
        if (sbi->fat_bits == 32) {
-               MSDOS_I(inode)->i_start = sbi->root_cluster;
-               error = fat_calc_dir_size(inode);
-               if (error < 0)
-                       return error;
-       } else {
-               MSDOS_I(inode)->i_start = 0;
-               inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry);
-       }
-       inode->i_blksize = sbi->cluster_size;
-       inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
-                          & ~((loff_t)sbi->cluster_size - 1)) >> 9;
-       MSDOS_I(inode)->i_logstart = 0;
-       MSDOS_I(inode)->mmu_private = inode->i_size;
-
-       MSDOS_I(inode)->i_attrs = 0;
-       inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
-       inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
-       MSDOS_I(inode)->i_ctime_ms = 0;
-       inode->i_nlink = fat_subdirs(inode)+2;
-
-       return 0;
-}
-
-/*
- * a FAT file handle with fhtype 3 is
- *  0/  i_ino - for fast, reliable lookup if still in the cache
- *  1/  i_generation - to see if i_ino is still valid
- *          bit 0 == 0 iff directory
- *  2/  i_pos(8-39) - if ino has changed, but still in cache
- *  3/  i_pos(4-7)|i_logstart - to semi-verify inode found at i_pos
- *  4/  i_pos(0-3)|parent->i_logstart - maybe used to hunt for the file on disc
- *
- * Hack for NFSv2: Maximum FAT entry number is 28bits and maximum
- * i_pos is 40bits (blocknr(32) + dir offset(8)), so two 4bits
- * of i_logstart is used to store the directory entry offset.
- */
-
-static struct dentry *
-fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype, 
-             int (*acceptable)(void *context, struct dentry *de),
-             void *context)
-{
-       if (fhtype != 3)
-               return ERR_PTR(-ESTALE);
-       if (len < 5)
-               return ERR_PTR(-ESTALE);
-
-       return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context);
-}
-
-static struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
-{
-       struct inode *inode = NULL;
-       struct dentry *result;
-       __u32 *fh = inump;
-
-       inode = iget(sb, fh[0]);
-       if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) {
-               if (inode)
-                       iput(inode);
-               inode = NULL;
-       }
-       if (!inode) {
-               loff_t i_pos;
-               int i_logstart = fh[3] & 0x0fffffff;
-
-               i_pos = (loff_t)fh[2] << 8;
-               i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28);
-
-               /* try 2 - see if i_pos is in F-d-c
-                * require i_logstart to be the same
-                * Will fail if you truncate and then re-write
-                */
-
-               inode = fat_iget(sb, i_pos);
-               if (inode && MSDOS_I(inode)->i_logstart != i_logstart) {
-                       iput(inode);
-                       inode = NULL;
-               }
-       }
-       if (!inode) {
-               /* For now, do nothing
-                * What we could do is:
-                * follow the file starting at fh[4], and record
-                * the ".." entry, and the name of the fh[2] entry.
-                * The follow the ".." file finding the next step up.
-                * This way we build a path to the root of
-                * the tree. If this works, we lookup the path and so
-                * get this inode into the cache.
-                * Finally try the fat_iget lookup again
-                * If that fails, then weare totally out of luck
-                * But all that is for another day
-                */
-       }
-       if (!inode)
-               return ERR_PTR(-ESTALE);
-
-       
-       /* now to find a dentry.
-        * If possible, get a well-connected one
-        */
-       result = d_alloc_anon(inode);
-       if (result == NULL) {
-               iput(inode);
-               return ERR_PTR(-ENOMEM);
-       }
-       result->d_op = sb->s_root->d_op;
-       return result;
-}
-
-static int
-fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
-{
-       int len = *lenp;
-       struct inode *inode =  de->d_inode;
-       u32 ipos_h, ipos_m, ipos_l;
-       
-       if (len < 5)
-               return 255; /* no room */
-
-       ipos_h = MSDOS_I(inode)->i_pos >> 8;
-       ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
-       ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28;
-       *lenp = 5;
-       fh[0] = inode->i_ino;
-       fh[1] = inode->i_generation;
-       fh[2] = ipos_h;
-       fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;
-       spin_lock(&de->d_lock);
-       fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart;
-       spin_unlock(&de->d_lock);
-       return 3;
-}
-
-static struct dentry *fat_get_parent(struct dentry *child)
-{
-       struct buffer_head *bh=NULL;
-       struct msdos_dir_entry *de = NULL;
-       struct dentry *parent = NULL;
-       int res;
-       loff_t i_pos = 0;
-       struct inode *inode;
-
-       lock_kernel();
-       res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &i_pos);
-
-       if (res < 0)
-               goto out;
-       inode = fat_build_inode(child->d_sb, de, i_pos, &res);
-       if (res)
-               goto out;
-       if (!inode)
-               res = -EACCES;
-       else {
-               parent = d_alloc_anon(inode);
-               if (!parent) {
-                       iput(inode);
-                       res = -ENOMEM;
-               }
-       }
-
- out:
-       if(bh)
-               brelse(bh);
-       unlock_kernel();
-       if (res)
-               return ERR_PTR(res);
-       else
-               return parent;
-}
-
-static kmem_cache_t *fat_inode_cachep;
-
-static struct inode *fat_alloc_inode(struct super_block *sb)
-{
-       struct msdos_inode_info *ei;
-       ei = (struct msdos_inode_info *)kmem_cache_alloc(fat_inode_cachep, SLAB_KERNEL);
-       if (!ei)
-               return NULL;
-       return &ei->vfs_inode;
-}
-
-static void fat_destroy_inode(struct inode *inode)
-{
-       kmem_cache_free(fat_inode_cachep, MSDOS_I(inode));
-}
-
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
-{
-       struct msdos_inode_info *ei = (struct msdos_inode_info *) foo;
-
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
-               spin_lock_init(&ei->cache_lru_lock);
-               ei->nr_caches = 0;
-               ei->cache_valid_id = FAT_CACHE_VALID + 1;
-               INIT_LIST_HEAD(&ei->cache_lru);
-               INIT_HLIST_NODE(&ei->i_fat_hash);
-               inode_init_once(&ei->vfs_inode);
-       }
-}
-int __init fat_init_inodecache(void)
-{
-       fat_inode_cachep = kmem_cache_create("fat_inode_cache",
-                                            sizeof(struct msdos_inode_info),
-                                            0, SLAB_RECLAIM_ACCOUNT,
-                                            init_once, NULL);
-       if (fat_inode_cachep == NULL)
-               return -ENOMEM;
-       return 0;
-}
+               MSDOS_I(inode)->i_start = sbi->root_cluster;
+               error = fat_calc_dir_size(inode);
+               if (error < 0)
+                       return error;
+       } else {
+               MSDOS_I(inode)->i_start = 0;
+               inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry);
+       }
+       inode->i_blksize = sbi->cluster_size;
+       inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
+                          & ~((loff_t)sbi->cluster_size - 1)) >> 9;
+       MSDOS_I(inode)->i_logstart = 0;
+       MSDOS_I(inode)->mmu_private = inode->i_size;
 
-void __exit fat_destroy_inodecache(void)
-{
-       if (kmem_cache_destroy(fat_inode_cachep))
-               printk(KERN_INFO "fat_inode_cache: not all structures were freed\n");
-}
+       MSDOS_I(inode)->i_attrs = 0;
+       inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
+       inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
+       MSDOS_I(inode)->i_ctime_ms = 0;
+       inode->i_nlink = fat_subdirs(inode)+2;
 
-static int fat_remount(struct super_block *sb, int *flags, char *data)
-{
-       *flags |= MS_NODIRATIME;
        return 0;
 }
 
-static struct super_operations fat_sops = { 
-       .alloc_inode    = fat_alloc_inode,
-       .destroy_inode  = fat_destroy_inode,
-       .write_inode    = fat_write_inode,
-       .delete_inode   = fat_delete_inode,
-       .put_super      = fat_put_super,
-       .statfs         = fat_statfs,
-       .clear_inode    = fat_clear_inode,
-       .remount_fs     = fat_remount,
-
-       .read_inode     = make_bad_inode,
-
-       .show_options   = fat_show_options,
-};
-
-static struct export_operations fat_export_ops = {
-       .decode_fh      = fat_decode_fh,
-       .encode_fh      = fat_encode_fh,
-       .get_dentry     = fat_get_dentry,
-       .get_parent     = fat_get_parent,
-};
-
 /*
  * Read the super block of an MS-DOS FS.
  */
@@ -937,7 +1173,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
                sbi->root_cluster = le32_to_cpu(b->root_cluster);
 
                sb->s_maxbytes = 0xffffffff;
-               
+
                /* MC - if info_sector is 0, don't multiply by 0 */
                sbi->fsinfo_sector = le16_to_cpu(b->info_sector);
                if (sbi->fsinfo_sector == 0)
@@ -1079,259 +1315,6 @@ out_fail:
 
 EXPORT_SYMBOL(fat_fill_super);
 
-static int fat_statfs(struct super_block *sb, struct kstatfs *buf)
-{
-       int free, nr, ret;
-       
-       if (MSDOS_SB(sb)->free_clusters != -1)
-               free = MSDOS_SB(sb)->free_clusters;
-       else {
-               lock_fat(sb);
-               if (MSDOS_SB(sb)->free_clusters != -1)
-                       free = MSDOS_SB(sb)->free_clusters;
-               else {
-                       free = 0;
-                       for (nr = 2; nr < MSDOS_SB(sb)->clusters + 2; nr++) {
-                               ret = fat_access(sb, nr, -1);
-                               if (ret < 0) {
-                                       unlock_fat(sb);
-                                       return ret;
-                               } else if (ret == FAT_ENT_FREE)
-                                       free++;
-                       }
-                       MSDOS_SB(sb)->free_clusters = free;
-               }
-               unlock_fat(sb);
-       }
-
-       buf->f_type = sb->s_magic;
-       buf->f_bsize = MSDOS_SB(sb)->cluster_size;
-       buf->f_blocks = MSDOS_SB(sb)->clusters;
-       buf->f_bfree = free;
-       buf->f_bavail = free;
-       buf->f_namelen = MSDOS_SB(sb)->options.isvfat ? 260 : 12;
-
-       return 0;
-}
-
-static int is_exec(unsigned char *extension)
-{
-       unsigned char *exe_extensions = "EXECOMBAT", *walk;
-
-       for (walk = exe_extensions; *walk; walk += 3)
-               if (!strncmp(extension, walk, 3))
-                       return 1;
-       return 0;
-}
-
-static int fat_writepage(struct page *page, struct writeback_control *wbc)
-{
-       return block_write_full_page(page,fat_get_block, wbc);
-}
-static int fat_readpage(struct file *file, struct page *page)
-{
-       return block_read_full_page(page,fat_get_block);
-}
-
-static int
-fat_prepare_write(struct file *file, struct page *page,
-                       unsigned from, unsigned to)
-{
-       return cont_prepare_write(page,from,to,fat_get_block,
-               &MSDOS_I(page->mapping->host)->mmu_private);
-}
-
-static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
-{
-       return generic_block_bmap(mapping,block,fat_get_block);
-}
-
-static struct address_space_operations fat_aops = {
-       .readpage       = fat_readpage,
-       .writepage      = fat_writepage,
-       .sync_page      = block_sync_page,
-       .prepare_write  = fat_prepare_write,
-       .commit_write   = generic_commit_write,
-       .bmap           = _fat_bmap
-};
-
-/* doesn't deal with root inode */
-static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
-{
-       struct super_block *sb = inode->i_sb;
-       struct msdos_sb_info *sbi = MSDOS_SB(sb);
-       int error;
-
-       MSDOS_I(inode)->i_pos = 0;
-       inode->i_uid = sbi->options.fs_uid;
-       inode->i_gid = sbi->options.fs_gid;
-       inode->i_version++;
-       inode->i_generation = get_seconds();
-       
-       if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {
-               inode->i_generation &= ~1;
-               inode->i_mode = MSDOS_MKMODE(de->attr,
-                       S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR;
-               inode->i_op = sbi->dir_ops;
-               inode->i_fop = &fat_dir_operations;
-
-               MSDOS_I(inode)->i_start = le16_to_cpu(de->start);
-               if (sbi->fat_bits == 32)
-                       MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16);
-
-               MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
-               error = fat_calc_dir_size(inode);
-               if (error < 0)
-                       return error;
-               MSDOS_I(inode)->mmu_private = inode->i_size;
-
-               inode->i_nlink = fat_subdirs(inode);
-       } else { /* not a directory */
-               inode->i_generation |= 1;
-               inode->i_mode = MSDOS_MKMODE(de->attr,
-                   ((sbi->options.showexec &&
-                      !is_exec(de->ext))
-                       ? S_IRUGO|S_IWUGO : S_IRWXUGO)
-                   & ~sbi->options.fs_fmask) | S_IFREG;
-               MSDOS_I(inode)->i_start = le16_to_cpu(de->start);
-               if (sbi->fat_bits == 32)
-                       MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16);
-
-               MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
-               inode->i_size = le32_to_cpu(de->size);
-               inode->i_op = &fat_file_inode_operations;
-               inode->i_fop = &fat_file_operations;
-               inode->i_mapping->a_ops = &fat_aops;
-               MSDOS_I(inode)->mmu_private = inode->i_size;
-       }
-       if(de->attr & ATTR_SYS)
-               if (sbi->options.sys_immutable)
-                       inode->i_flags |= S_IMMUTABLE;
-       MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
-       /* this is as close to the truth as we can get ... */
-       inode->i_blksize = sbi->cluster_size;
-       inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
-                          & ~((loff_t)sbi->cluster_size - 1)) >> 9;
-       inode->i_mtime.tv_sec = inode->i_atime.tv_sec =
-               date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date));
-       inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0;
-       inode->i_ctime.tv_sec =
-               MSDOS_SB(sb)->options.isvfat
-               ? date_dos2unix(le16_to_cpu(de->ctime), le16_to_cpu(de->cdate))
-               : inode->i_mtime.tv_sec;
-       inode->i_ctime.tv_nsec = de->ctime_ms * 1000000;
-       MSDOS_I(inode)->i_ctime_ms = de->ctime_ms;
-
-       return 0;
-}
-
-static int fat_write_inode(struct inode *inode, int wait)
-{
-       struct super_block *sb = inode->i_sb;
-       struct msdos_sb_info *sbi = MSDOS_SB(sb);
-       struct buffer_head *bh;
-       struct msdos_dir_entry *raw_entry;
-       loff_t i_pos;
-
-retry:
-       i_pos = MSDOS_I(inode)->i_pos;
-       if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
-               return 0;
-       }
-       lock_kernel();
-       if (!(bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits))) {
-               printk(KERN_ERR "FAT: unable to read inode block "
-                      "for updating (i_pos %lld)\n", i_pos);
-               unlock_kernel();
-               return -EIO;
-       }
-       spin_lock(&sbi->inode_hash_lock);
-       if (i_pos != MSDOS_I(inode)->i_pos) {
-               spin_unlock(&sbi->inode_hash_lock);
-               brelse(bh);
-               unlock_kernel();
-               goto retry;
-       }
-
-       raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
-           [i_pos & (sbi->dir_per_block - 1)];
-       if (S_ISDIR(inode->i_mode)) {
-               raw_entry->attr = ATTR_DIR;
-               raw_entry->size = 0;
-       }
-       else {
-               raw_entry->attr = ATTR_NONE;
-               raw_entry->size = cpu_to_le32(inode->i_size);
-       }
-       raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
-           MSDOS_I(inode)->i_attrs;
-       raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
-       raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
-       fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
-       if (sbi->options.isvfat) {
-               fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
-               raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */
-       }
-       spin_unlock(&sbi->inode_hash_lock);
-       mark_buffer_dirty(bh);
-       brelse(bh);
-       unlock_kernel();
-       return 0;
-}
-
-
-int fat_notify_change(struct dentry * dentry, struct iattr * attr)
-{
-       struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
-       struct inode *inode = dentry->d_inode;
-       int mask, error = 0;
-
-       lock_kernel();
-
-       /* FAT cannot truncate to a longer file */
-       if (attr->ia_valid & ATTR_SIZE) {
-               if (attr->ia_size > inode->i_size) {
-                       error = -EPERM;
-                       goto out;
-               }
-       }
-
-       error = inode_change_ok(inode, attr);
-       if (error) {
-               if (sbi->options.quiet)
-                       error = 0;
-               goto out;
-       }
-
-       if (((attr->ia_valid & ATTR_UID) && 
-            (attr->ia_uid != sbi->options.fs_uid)) ||
-           ((attr->ia_valid & ATTR_GID) && 
-            (attr->ia_gid != sbi->options.fs_gid)) ||
-           ((attr->ia_valid & ATTR_MODE) &&
-            (attr->ia_mode & ~MSDOS_VALID_MODE)))
-               error = -EPERM;
-
-       if (error) {
-               if (sbi->options.quiet)  
-                       error = 0;
-               goto out;
-       }
-       error = inode_setattr(inode, attr);
-       if (error)
-               goto out;
-
-       if (S_ISDIR(inode->i_mode))
-               mask = sbi->options.fs_dmask;
-       else
-               mask = sbi->options.fs_fmask;
-       inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
-out:
-       unlock_kernel();
-       return error;
-}
-
-EXPORT_SYMBOL(fat_notify_change);
-
 int __init fat_cache_init(void);
 void __exit fat_cache_destroy(void);
 
index 0d92c34f12315bca085d3ee923c1223d06887440..6f8fb81730ce3df23173a5b684b773099e1051ad 100644 (file)
@@ -88,8 +88,8 @@ int fat_add_cluster(struct inode *inode)
        struct super_block *sb = inode->i_sb;
        int ret, count, limit, new_dclus, new_fclus, last;
        int cluster_bits = MSDOS_SB(sb)->cluster_bits;
-       
-       /* 
+
+       /*
         * We must locate the last cluster of the file to add this new
         * one (new_dclus) to the end of the link list (the FAT).
         *
@@ -109,7 +109,7 @@ int fat_add_cluster(struct inode *inode)
 
        /* find free FAT entry */
        lock_fat(sb);
-       
+
        if (MSDOS_SB(sb)->free_clusters == 0) {
                unlock_fat(sb);
                return -ENOSPC;
@@ -145,7 +145,7 @@ int fat_add_cluster(struct inode *inode)
        if (MSDOS_SB(sb)->free_clusters != -1)
                MSDOS_SB(sb)->free_clusters--;
        fat_clusters_flush(sb);
-       
+
        unlock_fat(sb);
 
        /* add new one to the last of the cluster chain */
@@ -169,65 +169,23 @@ int fat_add_cluster(struct inode *inode)
        return new_dclus;
 }
 
-struct buffer_head *fat_extend_dir(struct inode *inode)
-{
-       struct super_block *sb = inode->i_sb;
-       struct buffer_head *bh, *res = NULL;
-       int nr, sec_per_clus = MSDOS_SB(sb)->sec_per_clus;
-       sector_t sector, last_sector;
-
-       if (MSDOS_SB(sb)->fat_bits != 32) {
-               if (inode->i_ino == MSDOS_ROOT_INO)
-                       return ERR_PTR(-ENOSPC);
-       }
-
-       nr = fat_add_cluster(inode);
-       if (nr < 0)
-               return ERR_PTR(nr);
-       
-       sector = ((sector_t)nr - 2) * sec_per_clus + MSDOS_SB(sb)->data_start;
-       last_sector = sector + sec_per_clus;
-       for ( ; sector < last_sector; sector++) {
-               if ((bh = sb_getblk(sb, sector))) {
-                       memset(bh->b_data, 0, sb->s_blocksize);
-                       set_buffer_uptodate(bh);
-                       mark_buffer_dirty(bh);
-                       if (!res)
-                               res = bh;
-                       else
-                               brelse(bh);
-               }
-       }
-       if (res == NULL)
-               res = ERR_PTR(-EIO);
-       if (inode->i_size & (sb->s_blocksize - 1)) {
-               fat_fs_panic(sb, "Odd directory size");
-               inode->i_size = (inode->i_size + sb->s_blocksize)
-                       & ~((loff_t)sb->s_blocksize - 1);
-       }
-       inode->i_size += MSDOS_SB(sb)->cluster_size;
-       MSDOS_I(inode)->mmu_private += MSDOS_SB(sb)->cluster_size;
-
-       return res;
-}
-
-/* Linear day numbers of the respective 1sts in non-leap years. */
-
-static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
-                 /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
-
-
 extern struct timezone sys_tz;
 
+/* Linear day numbers of the respective 1sts in non-leap years. */
+static int day_n[] = {
+   /* Jan  Feb  Mar  Apr   May  Jun  Jul  Aug  Sep  Oct  Nov  Dec */
+       0,  31,  59,  90,  120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0
+};
 
 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
-
-int date_dos2unix(unsigned short time,unsigned short date)
+int date_dos2unix(unsigned short time, unsigned short date)
 {
-       int month,year,secs;
+       int month, year, secs;
 
-       /* first subtract and mask after that... Otherwise, if
-          date == 0, bad things happen */
+       /*
+        * first subtract and mask after that... Otherwise, if
+        * date == 0, bad things happen
+        */
        month = ((date >> 5) - 1) & 15;
        year = date >> 9;
        secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
@@ -238,12 +196,10 @@ int date_dos2unix(unsigned short time,unsigned short date)
        return secs;
 }
 
-
 /* Convert linear UNIX date to a MS-DOS time/date pair. */
-
-void fat_date_unix2dos(int unix_date,__le16 *time, __le16 *date)
+void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
 {
-       int day,year,nl_day,month;
+       int day, year, nl_day, month;
 
        unix_date -= sys_tz.tz_minuteswest*60;
 
@@ -255,16 +211,18 @@ void fat_date_unix2dos(int unix_date,__le16 *time, __le16 *date)
            (((unix_date/3600) % 24) << 11));
        day = unix_date/86400-3652;
        year = day/365;
-       if ((year+3)/4+365*year > day) year--;
+       if ((year+3)/4+365*year > day)
+               year--;
        day -= (year+3)/4+365*year;
        if (day == 59 && !(year & 3)) {
                nl_day = day;
                month = 2;
-       }
-       else {
+       } else {
                nl_day = (year & 3) || day <= 59 ? day : day-1;
-               for (month = 0; month < 12; month++)
-                       if (day_n[month] > nl_day) break;
+               for (month = 0; month < 12; month++) {
+                       if (day_n[month] > nl_day)
+                               break;
+               }
        }
        *date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9));
 }
@@ -279,10 +237,10 @@ EXPORT_SYMBOL(fat_date_unix2dos);
    AV. want the next entry (took one explicit de=NULL in vfat/namei.c).
    AV. It's done in fat_get_entry() (inlined), here the slow case lives.
    AV. Additionally, when we return -1 (i.e. reached the end of directory)
-   AV. we make bh NULL. 
+   AV. we make bh NULL.
  */
 
-int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
+int fat__get_entry(struct inode *dir, loff_t *pos, struct buffer_head **bh,
                   struct msdos_dir_entry **de, loff_t *i_pos)
 {
        struct super_block *sb = dir->i_sb;
index c23a8d644926b8a1461470d6d2c5adfc8237b3b1..0d878d476397e4827154529ee8125ba6f93a271a 100644 (file)
 #define MSDOS_DPB_BITS 4               /* log2(MSDOS_DPB) */
 #define MSDOS_DPS      (SECTOR_SIZE / sizeof(struct msdos_dir_entry))
 #define MSDOS_DPS_BITS 4               /* log2(MSDOS_DPS) */
+#define CF_LE_W(v)     le16_to_cpu(v)
+#define CF_LE_L(v)     le32_to_cpu(v)
+#define CT_LE_W(v)     cpu_to_le16(v)
+#define CT_LE_L(v)     cpu_to_le32(v)
 
 
 #define MSDOS_SUPER_MAGIC 0x4d44 /* MD */
 #define FAT_MAX_DIR_ENTRIES    (65536)
 #define FAT_MAX_DIR_SIZE       (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS)
 
-#define ATTR_NONE    0 /* no attribute bits */
-#define ATTR_RO      1  /* read-only */
-#define ATTR_HIDDEN  2  /* hidden */
-#define ATTR_SYS     4  /* system */
-#define ATTR_VOLUME  8  /* volume label */
-#define ATTR_DIR     16 /* directory */
-#define ATTR_ARCH    32 /* archived */
+#define ATTR_NONE      0       /* no attribute bits */
+#define ATTR_RO                1       /* read-only */
+#define ATTR_HIDDEN    2       /* hidden */
+#define ATTR_SYS       4       /* system */
+#define ATTR_VOLUME    8       /* volume label */
+#define ATTR_DIR       16      /* directory */
+#define ATTR_ARCH      32      /* archived */
 
 /* attribute bits that are copied "as is" */
-#define ATTR_UNUSED  (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
+#define ATTR_UNUSED    (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
 /* bits that are used by the Windows 95/Windows NT extended FAT */
-#define ATTR_EXT     (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
+#define ATTR_EXT       (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
 
-#define CASE_LOWER_BASE 8      /* base is lower case */
-#define CASE_LOWER_EXT  16     /* extension is lower case */
+#define CASE_LOWER_BASE        8       /* base is lower case */
+#define CASE_LOWER_EXT 16      /* extension is lower case */
 
-#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
-#define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG)
+#define DELETED_FLAG   0xe5    /* marks file as deleted when in name[0] */
+#define IS_FREE(n)     (!*(n) || *(n) == DELETED_FLAG)
 
 /* valid file mode bits */
 #define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)
 /* Convert attribute bits and a mask to the UNIX mode. */
 #define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO))
 /* Convert the UNIX mode to MS-DOS attribute bits. */
-#define MSDOS_MKATTR(m) ((m & S_IWUGO) ? ATTR_NONE : ATTR_RO)
+#define MSDOS_MKATTR(m)        ((m & S_IWUGO) ? ATTR_NONE : ATTR_RO)
 
-#define MSDOS_NAME 11 /* maximum name length */
-#define MSDOS_LONGNAME 256 /* maximum name length */
-#define MSDOS_SLOTS 21  /* max # of slots needed for short and long names */
-#define MSDOS_DOT    ".          " /* ".", padded to MSDOS_NAME chars */
-#define MSDOS_DOTDOT "..         " /* "..", padded to MSDOS_NAME chars */
+#define MSDOS_NAME     11      /* maximum name length */
+#define MSDOS_LONGNAME 256     /* maximum name length */
+#define MSDOS_SLOTS    21      /* max # of slots for short and long names */
+#define MSDOS_DOT      ".          "   /* ".", padded to MSDOS_NAME chars */
+#define MSDOS_DOTDOT   "..         "   /* "..", padded to MSDOS_NAME chars */
 
 /* media of boot sector */
 #define FAT_VALID_MEDIA(x)     ((0xF8 <= (x) && (x) <= 0xFF) || (x) == 0xF0)
        MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x))
 
 /* maximum number of clusters */
-#define MAX_FAT12 0xFF4
-#define MAX_FAT16 0xFFF4
-#define MAX_FAT32 0x0FFFFFF6
-#define MAX_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : \
+#define MAX_FAT12      0xFF4
+#define MAX_FAT16      0xFFF4
+#define MAX_FAT32      0x0FFFFFF6
+#define MAX_FAT(s)     (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : \
        MSDOS_SB(s)->fat_bits == 16 ? MAX_FAT16 : MAX_FAT12)
 
 /* bad cluster mark */
-#define BAD_FAT12 0xFF7
-#define BAD_FAT16 0xFFF7
-#define BAD_FAT32 0x0FFFFFF7
-#define BAD_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? BAD_FAT32 : \
+#define BAD_FAT12      0xFF7
+#define BAD_FAT16      0xFFF7
+#define BAD_FAT32      0x0FFFFFF7
+#define BAD_FAT(s)     (MSDOS_SB(s)->fat_bits == 32 ? BAD_FAT32 : \
        MSDOS_SB(s)->fat_bits == 16 ? BAD_FAT16 : BAD_FAT12)
 
 /* standard EOF */
-#define EOF_FAT12 0xFFF
-#define EOF_FAT16 0xFFFF
-#define EOF_FAT32 0x0FFFFFFF
-#define EOF_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? EOF_FAT32 : \
+#define EOF_FAT12      0xFFF
+#define EOF_FAT16      0xFFFF
+#define EOF_FAT32      0x0FFFFFFF
+#define EOF_FAT(s)     (MSDOS_SB(s)->fat_bits == 32 ? EOF_FAT32 : \
        MSDOS_SB(s)->fat_bits == 16 ? EOF_FAT16 : EOF_FAT12)
 
 #define FAT_ENT_FREE   (0)
 #define        VFAT_IOCTL_READDIR_BOTH         _IOR('r', 1, struct dirent [2])
 #define        VFAT_IOCTL_READDIR_SHORT        _IOR('r', 2, struct dirent [2])
 
-/* 
+/*
  * vfat shortname flags
  */
 #define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */
 #define VFAT_SFN_CREATE_WIN95  0x0100 /* emulate win95 rule for create */
 #define VFAT_SFN_CREATE_WINNT  0x0200 /* emulate winnt rule for create */
 
-/*
- * Conversion from and to little-endian byte order. (no-op on i386/i486)
- *
- * Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian,
- * BE = big-endian, c: W = word (16 bits), L = longword (32 bits)
- */
-
-#define CF_LE_W(v) le16_to_cpu(v)
-#define CF_LE_L(v) le32_to_cpu(v)
-#define CT_LE_W(v) cpu_to_le16(v)
-#define CT_LE_L(v) cpu_to_le32(v)
-
 struct fat_boot_sector {
        __u8    ignored[3];     /* Boot strap short or near jump */
        __u8    system_id[8];   /* Name - can be used to special case
@@ -161,7 +153,7 @@ struct msdos_dir_entry {
        __le16  ctime;          /* Creation time */
        __le16  cdate;          /* Creation date */
        __le16  adate;          /* Last access date */
-       __le16   starthi;       /* High 16 bits of cluster in FAT32 */
+       __le16  starthi;        /* High 16 bits of cluster in FAT32 */
        __le16  time,date,start;/* time, date and first cluster */
        __le32  size;           /* file size (in bytes) */
 };
@@ -179,9 +171,9 @@ struct msdos_dir_slot {
 };
 
 struct vfat_slot_info {
-       int long_slots;                /* number of long slots in filename */
-       loff_t longname_offset;        /* dir offset for longname start */
-       loff_t i_pos;                  /* on-disk position of directory entry */
+       int long_slots;         /* number of long slots in filename */
+       loff_t longname_offset; /* dir offset for longname start */
+       loff_t i_pos;           /* on-disk position of directory entry */
 };
 
 #ifdef __KERNEL__
@@ -259,11 +251,11 @@ struct msdos_inode_info {
        unsigned int cache_valid_id;
 
        loff_t mmu_private;
-       int i_start;    /* first cluster or 0 */
-       int i_logstart; /* logical first cluster */
-       int i_attrs;    /* unused attribute bits */
-       int i_ctime_ms; /* unused change time in milliseconds */
-       loff_t i_pos;   /* on-disk position of directory entry or 0 */
+       int i_start;            /* first cluster or 0 */
+       int i_logstart;         /* logical first cluster */
+       int i_attrs;            /* unused attribute bits */
+       int i_ctime_ms;         /* unused change time in milliseconds */
+       loff_t i_pos;           /* on-disk position of directory entry or 0 */
        struct hlist_node i_fat_hash;   /* hash by i_location */
        struct inode vfs_inode;
 };
@@ -305,20 +297,20 @@ static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len)
 }
 
 /* fat/cache.c */
-extern int fat_access(struct super_block *sb, int nr, int new_value);
-extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
 extern void fat_cache_inval_inode(struct inode *inode);
+extern int fat_access(struct super_block *sb, int nr, int new_value);
 extern int fat_get_cluster(struct inode *inode, int cluster,
                           int *fclus, int *dclus);
-extern int fat_free(struct inode *inode, int skip);
+extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
 
 /* fat/dir.c */
 extern struct file_operations fat_dir_operations;
 extern int fat_search_long(struct inode *inode, const unsigned char *name,
                           int name_len, int anycase,
                           loff_t *spos, loff_t *lpos);
-extern int fat_add_entries(struct inode *dir, int slots, struct buffer_head **bh,
-                       struct msdos_dir_entry **de, loff_t *i_pos);
+extern int fat_add_entries(struct inode *dir, int slots,
+                          struct buffer_head **bh,
+                          struct msdos_dir_entry **de, loff_t *i_pos);
 extern int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat);
 extern int fat_dir_empty(struct inode *dir);
 extern int fat_subdirs(struct inode *dir);
@@ -329,8 +321,7 @@ extern int fat_scan(struct inode *dir, const unsigned char *name,
 /* fat/file.c */
 extern struct file_operations fat_file_operations;
 extern struct inode_operations fat_file_inode_operations;
-extern int fat_get_block(struct inode *inode, sector_t iblock,
-                        struct buffer_head *bh_result, int create);
+extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
 extern void fat_truncate(struct inode *inode);
 
 /* fat/inode.c */
@@ -341,7 +332,6 @@ extern struct inode *fat_build_inode(struct super_block *sb,
                        struct msdos_dir_entry *de, loff_t i_pos, int *res);
 int fat_fill_super(struct super_block *sb, void *data, int silent,
                   struct inode_operations *fs_dir_inode_ops, int isvfat);
-extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
 
 /* fat/misc.c */
 extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
@@ -349,7 +339,6 @@ extern void lock_fat(struct super_block *sb);
 extern void unlock_fat(struct super_block *sb);
 extern void fat_clusters_flush(struct super_block *sb);
 extern int fat_add_cluster(struct inode *inode);
-extern struct buffer_head *fat_extend_dir(struct inode *inode);
 extern int date_dos2unix(unsigned short time, unsigned short date);
 extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
 extern int fat__get_entry(struct inode *dir, loff_t *pos,