From: OGAWA Hirofumi This patch is just cleanup (whitespace, and place of functions is changed). No changes of logic. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton --- 25-akpm/fs/fat/cache.c | 68 -- 25-akpm/fs/fat/dir.c | 252 +++++---- 25-akpm/fs/fat/file.c | 168 ++++-- 25-akpm/fs/fat/inode.c | 1035 +++++++++++++++++++-------------------- 25-akpm/fs/fat/misc.c | 94 --- 25-akpm/include/linux/msdos_fs.h | 113 +--- 6 files changed, 846 insertions(+), 884 deletions(-) diff -puN fs/fat/cache.c~fat-fs-fat-cleanup fs/fat/cache.c --- 25/fs/fat/cache.c~fat-fs-fat-cleanup Tue Jan 18 14:53:46 2005 +++ 25-akpm/fs/fat/cache.c Tue Jan 18 14:53:46 2005 @@ -296,7 +296,7 @@ static int __fat_access(struct super_blo 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 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, 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 } 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; -} diff -puN fs/fat/dir.c~fat-fs-fat-cleanup fs/fat/dir.c --- 25/fs/fat/dir.c~fat-fs-fat-cleanup Tue Jan 18 14:53:46 2005 +++ 25-akpm/fs/fat/dir.c Tue Jan 18 14:53:46 2005 @@ -20,20 +20,8 @@ #include #include #include - #include -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_operation * 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_ 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, 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, 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 *in 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 *in 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 * 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,in 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, struc } 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); diff -puN fs/fat/file.c~fat-fs-fat-cleanup fs/fat/file.c --- 25/fs/fat/file.c~fat-fs-fat-cleanup Tue Jan 18 14:53:46 2005 +++ 25-akpm/fs/fat/file.c Tue Jan 18 14:53:46 2005 @@ -6,13 +6,26 @@ * regular file handling primitives for fat-based filesystems */ +#include #include #include #include #include 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_operatio .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; + struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); + struct inode *inode = dentry->d_inode; + int mask, error = 0; - 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; + 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 (!((unsigned long)iblock & (MSDOS_SB(sb)->sec_per_clus - 1))) { - int error; - error = fat_add_cluster(inode); - if (error < 0) - return error; + 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; } - 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, +}; diff -puN fs/fat/inode.c~fat-fs-fat-cleanup fs/fat/inode.c --- 25/fs/fat/inode.c~fat-fs-fat-cleanup Tue Jan 18 14:53:46 2005 +++ 25-akpm/fs/fat/inode.c Tue Jan 18 14:53:46 2005 @@ -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 @@ -32,8 +32,76 @@ 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_bloc 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) @@ -177,29 +340,343 @@ static void fat_clear_inode(struct inode static void fat_put_super(struct super_block *sb) { - struct msdos_sb_info *sbi = MSDOS_SB(sb); + struct msdos_sb_info *sbi = MSDOS_SB(sb); + + if (!(sb->s_flags & MS_RDONLY)) + fat_clusters_flush(sb); + + if (sbi->nls_disk) { + unload_nls(sbi->nls_disk); + sbi->nls_disk = NULL; + sbi->options.codepage = fat_default_codepage; + } + if (sbi->nls_io) { + unload_nls(sbi->nls_io); + sbi->nls_io = NULL; + } + if (sbi->options.iocharset != fat_default_iocharset) { + kfree(sbi->options.iocharset); + sbi->options.iocharset = fat_default_iocharset; + } + + 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; - if (!(sb->s_flags & MS_RDONLY)) - fat_clusters_flush(sb); + lock_kernel(); + res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &i_pos); - if (sbi->nls_disk) { - unload_nls(sbi->nls_disk); - sbi->nls_disk = NULL; - sbi->options.codepage = fat_default_codepage; - } - if (sbi->nls_io) { - unload_nls(sbi->nls_io); - sbi->nls_io = NULL; - } - if (sbi->options.iocharset != fat_default_iocharset) { - kfree(sbi->options.iocharset); - sbi->options.iocharset = fat_default_iocharset; + 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; + } } - sb->s_fs_info = NULL; - kfree(sbi); + 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, 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; } @@ -560,245 +1020,21 @@ static int fat_read_root(struct inode *i 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; -} + 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 *s 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); diff -puN fs/fat/misc.c~fat-fs-fat-cleanup fs/fat/misc.c --- 25/fs/fat/misc.c~fat-fs-fat-cleanup Tue Jan 18 14:53:46 2005 +++ 25-akpm/fs/fat/misc.c Tue Jan 18 14:53:46 2005 @@ -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,un 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,__l (((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; diff -puN include/linux/msdos_fs.h~fat-fs-fat-cleanup include/linux/msdos_fs.h --- 25/include/linux/msdos_fs.h~fat-fs-fat-cleanup Tue Jan 18 14:53:46 2005 +++ 25-akpm/include/linux/msdos_fs.h Tue Jan 18 14:53:46 2005 @@ -12,6 +12,10 @@ #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 */ @@ -23,37 +27,37 @@ #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) @@ -61,24 +65,24 @@ 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) @@ -96,7 +100,7 @@ #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 */ @@ -105,18 +109,6 @@ #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 *d } /* 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, c /* 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(str 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 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, _