aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fat
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fat')
-rw-r--r--fs/fat/cache.c14
-rw-r--r--fs/fat/dir.c28
-rw-r--r--fs/fat/fatent.c10
-rw-r--r--fs/fat/file.c38
-rw-r--r--fs/fat/inode.c119
-rw-r--r--fs/fat/misc.c8
6 files changed, 169 insertions, 48 deletions
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 77c24fcf712..1acc941245f 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -295,7 +295,8 @@ static int fat_bmap_cluster(struct inode *inode, int cluster)
295 return dclus; 295 return dclus;
296} 296}
297 297
298int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys) 298int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
299 unsigned long *mapped_blocks)
299{ 300{
300 struct super_block *sb = inode->i_sb; 301 struct super_block *sb = inode->i_sb;
301 struct msdos_sb_info *sbi = MSDOS_SB(sb); 302 struct msdos_sb_info *sbi = MSDOS_SB(sb);
@@ -303,9 +304,12 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys)
303 int cluster, offset; 304 int cluster, offset;
304 305
305 *phys = 0; 306 *phys = 0;
307 *mapped_blocks = 0;
306 if ((sbi->fat_bits != 32) && (inode->i_ino == MSDOS_ROOT_INO)) { 308 if ((sbi->fat_bits != 32) && (inode->i_ino == MSDOS_ROOT_INO)) {
307 if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits)) 309 if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits)) {
308 *phys = sector + sbi->dir_start; 310 *phys = sector + sbi->dir_start;
311 *mapped_blocks = 1;
312 }
309 return 0; 313 return 0;
310 } 314 }
311 last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1)) 315 last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1))
@@ -318,7 +322,11 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys)
318 cluster = fat_bmap_cluster(inode, cluster); 322 cluster = fat_bmap_cluster(inode, cluster);
319 if (cluster < 0) 323 if (cluster < 0)
320 return cluster; 324 return cluster;
321 else if (cluster) 325 else if (cluster) {
322 *phys = fat_clus_to_blknr(sbi, cluster) + offset; 326 *phys = fat_clus_to_blknr(sbi, cluster) + offset;
327 *mapped_blocks = sbi->sec_per_clus - offset;
328 if (*mapped_blocks > last_block - sector)
329 *mapped_blocks = last_block - sector;
330 }
323 return 0; 331 return 0;
324} 332}
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index ba824964b9b..db0de5c621c 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -45,8 +45,8 @@ static inline void fat_dir_readahead(struct inode *dir, sector_t iblock,
45 if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO)) 45 if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO))
46 return; 46 return;
47 47
48 bh = sb_getblk(sb, phys); 48 bh = sb_find_get_block(sb, phys);
49 if (bh && !buffer_uptodate(bh)) { 49 if (bh == NULL || !buffer_uptodate(bh)) {
50 for (sec = 0; sec < sbi->sec_per_clus; sec++) 50 for (sec = 0; sec < sbi->sec_per_clus; sec++)
51 sb_breadahead(sb, phys + sec); 51 sb_breadahead(sb, phys + sec);
52 } 52 }
@@ -68,8 +68,8 @@ static int fat__get_entry(struct inode *dir, loff_t *pos,
68{ 68{
69 struct super_block *sb = dir->i_sb; 69 struct super_block *sb = dir->i_sb;
70 sector_t phys, iblock; 70 sector_t phys, iblock;
71 int offset; 71 unsigned long mapped_blocks;
72 int err; 72 int err, offset;
73 73
74next: 74next:
75 if (*bh) 75 if (*bh)
@@ -77,7 +77,7 @@ next:
77 77
78 *bh = NULL; 78 *bh = NULL;
79 iblock = *pos >> sb->s_blocksize_bits; 79 iblock = *pos >> sb->s_blocksize_bits;
80 err = fat_bmap(dir, iblock, &phys); 80 err = fat_bmap(dir, iblock, &phys, &mapped_blocks);
81 if (err || !phys) 81 if (err || !phys)
82 return -1; /* beyond EOF or error */ 82 return -1; /* beyond EOF or error */
83 83
@@ -418,7 +418,7 @@ EODir:
418 return err; 418 return err;
419} 419}
420 420
421EXPORT_SYMBOL(fat_search_long); 421EXPORT_SYMBOL_GPL(fat_search_long);
422 422
423struct fat_ioctl_filldir_callback { 423struct fat_ioctl_filldir_callback {
424 struct dirent __user *dirent; 424 struct dirent __user *dirent;
@@ -729,13 +729,13 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp,
729 729
730 buf.dirent = d1; 730 buf.dirent = d1;
731 buf.result = 0; 731 buf.result = 0;
732 down(&inode->i_sem); 732 mutex_lock(&inode->i_mutex);
733 ret = -ENOENT; 733 ret = -ENOENT;
734 if (!IS_DEADDIR(inode)) { 734 if (!IS_DEADDIR(inode)) {
735 ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir, 735 ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir,
736 short_only, both); 736 short_only, both);
737 } 737 }
738 up(&inode->i_sem); 738 mutex_unlock(&inode->i_mutex);
739 if (ret >= 0) 739 if (ret >= 0)
740 ret = buf.result; 740 ret = buf.result;
741 return ret; 741 return ret;
@@ -780,7 +780,7 @@ int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
780 return -ENOENT; 780 return -ENOENT;
781} 781}
782 782
783EXPORT_SYMBOL(fat_get_dotdot_entry); 783EXPORT_SYMBOL_GPL(fat_get_dotdot_entry);
784 784
785/* See if directory is empty */ 785/* See if directory is empty */
786int fat_dir_empty(struct inode *dir) 786int fat_dir_empty(struct inode *dir)
@@ -803,7 +803,7 @@ int fat_dir_empty(struct inode *dir)
803 return result; 803 return result;
804} 804}
805 805
806EXPORT_SYMBOL(fat_dir_empty); 806EXPORT_SYMBOL_GPL(fat_dir_empty);
807 807
808/* 808/*
809 * fat_subdirs counts the number of sub-directories of dir. It can be run 809 * fat_subdirs counts the number of sub-directories of dir. It can be run
@@ -849,7 +849,7 @@ int fat_scan(struct inode *dir, const unsigned char *name,
849 return -ENOENT; 849 return -ENOENT;
850} 850}
851 851
852EXPORT_SYMBOL(fat_scan); 852EXPORT_SYMBOL_GPL(fat_scan);
853 853
854static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots) 854static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots)
855{ 855{
@@ -936,7 +936,7 @@ int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo)
936 return 0; 936 return 0;
937} 937}
938 938
939EXPORT_SYMBOL(fat_remove_entries); 939EXPORT_SYMBOL_GPL(fat_remove_entries);
940 940
941static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used, 941static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used,
942 struct buffer_head **bhs, int nr_bhs) 942 struct buffer_head **bhs, int nr_bhs)
@@ -1048,7 +1048,7 @@ error:
1048 return err; 1048 return err;
1049} 1049}
1050 1050
1051EXPORT_SYMBOL(fat_alloc_new_dir); 1051EXPORT_SYMBOL_GPL(fat_alloc_new_dir);
1052 1052
1053static int fat_add_new_entries(struct inode *dir, void *slots, int nr_slots, 1053static int fat_add_new_entries(struct inode *dir, void *slots, int nr_slots,
1054 int *nr_cluster, struct msdos_dir_entry **de, 1054 int *nr_cluster, struct msdos_dir_entry **de,
@@ -1264,4 +1264,4 @@ error_remove:
1264 return err; 1264 return err;
1265} 1265}
1266 1266
1267EXPORT_SYMBOL(fat_add_entries); 1267EXPORT_SYMBOL_GPL(fat_add_entries);
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 4164cd54c4d..a1a9e045121 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -476,6 +476,7 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
476 sbi->prev_free = entry; 476 sbi->prev_free = entry;
477 if (sbi->free_clusters != -1) 477 if (sbi->free_clusters != -1)
478 sbi->free_clusters--; 478 sbi->free_clusters--;
479 sb->s_dirt = 1;
479 480
480 cluster[idx_clus] = entry; 481 cluster[idx_clus] = entry;
481 idx_clus++; 482 idx_clus++;
@@ -496,6 +497,7 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
496 497
497 /* Couldn't allocate the free entries */ 498 /* Couldn't allocate the free entries */
498 sbi->free_clusters = 0; 499 sbi->free_clusters = 0;
500 sb->s_dirt = 1;
499 err = -ENOSPC; 501 err = -ENOSPC;
500 502
501out: 503out:
@@ -509,7 +511,6 @@ out:
509 } 511 }
510 for (i = 0; i < nr_bhs; i++) 512 for (i = 0; i < nr_bhs; i++)
511 brelse(bhs[i]); 513 brelse(bhs[i]);
512 fat_clusters_flush(sb);
513 514
514 if (err && idx_clus) 515 if (err && idx_clus)
515 fat_free_clusters(inode, cluster[0]); 516 fat_free_clusters(inode, cluster[0]);
@@ -542,8 +543,10 @@ int fat_free_clusters(struct inode *inode, int cluster)
542 } 543 }
543 544
544 ops->ent_put(&fatent, FAT_ENT_FREE); 545 ops->ent_put(&fatent, FAT_ENT_FREE);
545 if (sbi->free_clusters != -1) 546 if (sbi->free_clusters != -1) {
546 sbi->free_clusters++; 547 sbi->free_clusters++;
548 sb->s_dirt = 1;
549 }
547 550
548 if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) { 551 if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) {
549 if (sb->s_flags & MS_SYNCHRONOUS) { 552 if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -578,7 +581,7 @@ error:
578 return err; 581 return err;
579} 582}
580 583
581EXPORT_SYMBOL(fat_free_clusters); 584EXPORT_SYMBOL_GPL(fat_free_clusters);
582 585
583int fat_count_free_clusters(struct super_block *sb) 586int fat_count_free_clusters(struct super_block *sb)
584{ 587{
@@ -605,6 +608,7 @@ int fat_count_free_clusters(struct super_block *sb)
605 } while (fat_ent_next(sbi, &fatent)); 608 } while (fat_ent_next(sbi, &fatent));
606 } 609 }
607 sbi->free_clusters = free; 610 sbi->free_clusters = free;
611 sb->s_dirt = 1;
608 fatent_brelse(&fatent); 612 fatent_brelse(&fatent);
609out: 613out:
610 unlock_fat(sbi); 614 unlock_fat(sbi);
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 7134403d5be..e99c5a73b39 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -6,11 +6,13 @@
6 * regular file handling primitives for fat-based filesystems 6 * regular file handling primitives for fat-based filesystems
7 */ 7 */
8 8
9#include <linux/capability.h>
9#include <linux/module.h> 10#include <linux/module.h>
10#include <linux/time.h> 11#include <linux/time.h>
11#include <linux/msdos_fs.h> 12#include <linux/msdos_fs.h>
12#include <linux/smp_lock.h> 13#include <linux/smp_lock.h>
13#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/writeback.h>
14 16
15int fat_generic_ioctl(struct inode *inode, struct file *filp, 17int fat_generic_ioctl(struct inode *inode, struct file *filp,
16 unsigned int cmd, unsigned long arg) 18 unsigned int cmd, unsigned long arg)
@@ -40,7 +42,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
40 if (err) 42 if (err)
41 return err; 43 return err;
42 44
43 down(&inode->i_sem); 45 mutex_lock(&inode->i_mutex);
44 46
45 if (IS_RDONLY(inode)) { 47 if (IS_RDONLY(inode)) {
46 err = -EROFS; 48 err = -EROFS;
@@ -102,7 +104,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
102 MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED; 104 MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED;
103 mark_inode_dirty(inode); 105 mark_inode_dirty(inode);
104 up: 106 up:
105 up(&inode->i_sem); 107 mutex_unlock(&inode->i_mutex);
106 return err; 108 return err;
107 } 109 }
108 default: 110 default:
@@ -124,6 +126,24 @@ struct file_operations fat_file_operations = {
124 .sendfile = generic_file_sendfile, 126 .sendfile = generic_file_sendfile,
125}; 127};
126 128
129static int fat_cont_expand(struct inode *inode, loff_t size)
130{
131 struct address_space *mapping = inode->i_mapping;
132 loff_t start = inode->i_size, count = size - inode->i_size;
133 int err;
134
135 err = generic_cont_expand_simple(inode, size);
136 if (err)
137 goto out;
138
139 inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
140 mark_inode_dirty(inode);
141 if (IS_SYNC(inode))
142 err = sync_page_range_nolock(inode, mapping, start, count);
143out:
144 return err;
145}
146
127int fat_notify_change(struct dentry *dentry, struct iattr *attr) 147int fat_notify_change(struct dentry *dentry, struct iattr *attr)
128{ 148{
129 struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); 149 struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
@@ -132,11 +152,17 @@ int fat_notify_change(struct dentry *dentry, struct iattr *attr)
132 152
133 lock_kernel(); 153 lock_kernel();
134 154
135 /* FAT cannot truncate to a longer file */ 155 /*
156 * Expand the file. Since inode_setattr() updates ->i_size
157 * before calling the ->truncate(), but FAT needs to fill the
158 * hole before it.
159 */
136 if (attr->ia_valid & ATTR_SIZE) { 160 if (attr->ia_valid & ATTR_SIZE) {
137 if (attr->ia_size > inode->i_size) { 161 if (attr->ia_size > inode->i_size) {
138 error = -EPERM; 162 error = fat_cont_expand(inode, attr->ia_size);
139 goto out; 163 if (error || attr->ia_valid == ATTR_SIZE)
164 goto out;
165 attr->ia_valid &= ~ATTR_SIZE;
140 } 166 }
141 } 167 }
142 168
@@ -173,7 +199,7 @@ out:
173 return error; 199 return error;
174} 200}
175 201
176EXPORT_SYMBOL(fat_notify_change); 202EXPORT_SYMBOL_GPL(fat_notify_change);
177 203
178/* Free all clusters after the skip'th cluster. */ 204/* Free all clusters after the skip'th cluster. */
179static int fat_free(struct inode *inode, int skip) 205static int fat_free(struct inode *inode, int skip)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index a0f9b9fe130..e7f4aa7fc68 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -18,10 +18,12 @@
18#include <linux/seq_file.h> 18#include <linux/seq_file.h>
19#include <linux/msdos_fs.h> 19#include <linux/msdos_fs.h>
20#include <linux/pagemap.h> 20#include <linux/pagemap.h>
21#include <linux/mpage.h>
21#include <linux/buffer_head.h> 22#include <linux/buffer_head.h>
22#include <linux/mount.h> 23#include <linux/mount.h>
23#include <linux/vfs.h> 24#include <linux/vfs.h>
24#include <linux/parser.h> 25#include <linux/parser.h>
26#include <linux/uio.h>
25#include <asm/unaligned.h> 27#include <asm/unaligned.h>
26 28
27#ifndef CONFIG_FAT_DEFAULT_IOCHARSET 29#ifndef CONFIG_FAT_DEFAULT_IOCHARSET
@@ -48,51 +50,97 @@ static int fat_add_cluster(struct inode *inode)
48 return err; 50 return err;
49} 51}
50 52
51static int fat_get_block(struct inode *inode, sector_t iblock, 53static int __fat_get_blocks(struct inode *inode, sector_t iblock,
52 struct buffer_head *bh_result, int create) 54 unsigned long *max_blocks,
55 struct buffer_head *bh_result, int create)
53{ 56{
54 struct super_block *sb = inode->i_sb; 57 struct super_block *sb = inode->i_sb;
58 struct msdos_sb_info *sbi = MSDOS_SB(sb);
55 sector_t phys; 59 sector_t phys;
56 int err; 60 unsigned long mapped_blocks;
61 int err, offset;
57 62
58 err = fat_bmap(inode, iblock, &phys); 63 err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
59 if (err) 64 if (err)
60 return err; 65 return err;
61 if (phys) { 66 if (phys) {
62 map_bh(bh_result, sb, phys); 67 map_bh(bh_result, sb, phys);
68 *max_blocks = min(mapped_blocks, *max_blocks);
63 return 0; 69 return 0;
64 } 70 }
65 if (!create) 71 if (!create)
66 return 0; 72 return 0;
73
67 if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) { 74 if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
68 fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)", 75 fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)",
69 MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private); 76 MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
70 return -EIO; 77 return -EIO;
71 } 78 }
72 if (!((unsigned long)iblock & (MSDOS_SB(sb)->sec_per_clus - 1))) { 79
80 offset = (unsigned long)iblock & (sbi->sec_per_clus - 1);
81 if (!offset) {
82 /* TODO: multiple cluster allocation would be desirable. */
73 err = fat_add_cluster(inode); 83 err = fat_add_cluster(inode);
74 if (err) 84 if (err)
75 return err; 85 return err;
76 } 86 }
77 MSDOS_I(inode)->mmu_private += sb->s_blocksize; 87 /* available blocks on this cluster */
78 err = fat_bmap(inode, iblock, &phys); 88 mapped_blocks = sbi->sec_per_clus - offset;
89
90 *max_blocks = min(mapped_blocks, *max_blocks);
91 MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits;
92
93 err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
79 if (err) 94 if (err)
80 return err; 95 return err;
81 if (!phys) 96 BUG_ON(!phys);
82 BUG(); 97 BUG_ON(*max_blocks != mapped_blocks);
83 set_buffer_new(bh_result); 98 set_buffer_new(bh_result);
84 map_bh(bh_result, sb, phys); 99 map_bh(bh_result, sb, phys);
85 return 0; 100 return 0;
86} 101}
87 102
103static int fat_get_blocks(struct inode *inode, sector_t iblock,
104 unsigned long max_blocks,
105 struct buffer_head *bh_result, int create)
106{
107 struct super_block *sb = inode->i_sb;
108 int err;
109
110 err = __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
111 if (err)
112 return err;
113 bh_result->b_size = max_blocks << sb->s_blocksize_bits;
114 return 0;
115}
116
117static int fat_get_block(struct inode *inode, sector_t iblock,
118 struct buffer_head *bh_result, int create)
119{
120 unsigned long max_blocks = 1;
121 return __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
122}
123
88static int fat_writepage(struct page *page, struct writeback_control *wbc) 124static int fat_writepage(struct page *page, struct writeback_control *wbc)
89{ 125{
90 return block_write_full_page(page, fat_get_block, wbc); 126 return block_write_full_page(page, fat_get_block, wbc);
91} 127}
92 128
129static int fat_writepages(struct address_space *mapping,
130 struct writeback_control *wbc)
131{
132 return mpage_writepages(mapping, wbc, fat_get_block);
133}
134
93static int fat_readpage(struct file *file, struct page *page) 135static int fat_readpage(struct file *file, struct page *page)
94{ 136{
95 return block_read_full_page(page, fat_get_block); 137 return mpage_readpage(page, fat_get_block);
138}
139
140static int fat_readpages(struct file *file, struct address_space *mapping,
141 struct list_head *pages, unsigned nr_pages)
142{
143 return mpage_readpages(mapping, pages, nr_pages, fat_get_block);
96} 144}
97 145
98static int fat_prepare_write(struct file *file, struct page *page, 146static int fat_prepare_write(struct file *file, struct page *page,
@@ -115,6 +163,34 @@ static int fat_commit_write(struct file *file, struct page *page,
115 return err; 163 return err;
116} 164}
117 165
166static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
167 const struct iovec *iov,
168 loff_t offset, unsigned long nr_segs)
169{
170 struct file *file = iocb->ki_filp;
171 struct inode *inode = file->f_mapping->host;
172
173 if (rw == WRITE) {
174 /*
175 * FIXME: blockdev_direct_IO() doesn't use ->prepare_write(),
176 * so we need to update the ->mmu_private to block boundary.
177 *
178 * But we must fill the remaining area or hole by nul for
179 * updating ->mmu_private.
180 */
181 loff_t size = offset + iov_length(iov, nr_segs);
182 if (MSDOS_I(inode)->mmu_private < size)
183 return -EINVAL;
184 }
185
186 /*
187 * FAT need to use the DIO_LOCKING for avoiding the race
188 * condition of fat_get_block() and ->truncate().
189 */
190 return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
191 offset, nr_segs, fat_get_blocks, NULL);
192}
193
118static sector_t _fat_bmap(struct address_space *mapping, sector_t block) 194static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
119{ 195{
120 return generic_block_bmap(mapping, block, fat_get_block); 196 return generic_block_bmap(mapping, block, fat_get_block);
@@ -122,10 +198,13 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
122 198
123static struct address_space_operations fat_aops = { 199static struct address_space_operations fat_aops = {
124 .readpage = fat_readpage, 200 .readpage = fat_readpage,
201 .readpages = fat_readpages,
125 .writepage = fat_writepage, 202 .writepage = fat_writepage,
203 .writepages = fat_writepages,
126 .sync_page = block_sync_page, 204 .sync_page = block_sync_page,
127 .prepare_write = fat_prepare_write, 205 .prepare_write = fat_prepare_write,
128 .commit_write = fat_commit_write, 206 .commit_write = fat_commit_write,
207 .direct_IO = fat_direct_IO,
129 .bmap = _fat_bmap 208 .bmap = _fat_bmap
130}; 209};
131 210
@@ -182,7 +261,7 @@ void fat_attach(struct inode *inode, loff_t i_pos)
182 spin_unlock(&sbi->inode_hash_lock); 261 spin_unlock(&sbi->inode_hash_lock);
183} 262}
184 263
185EXPORT_SYMBOL(fat_attach); 264EXPORT_SYMBOL_GPL(fat_attach);
186 265
187void fat_detach(struct inode *inode) 266void fat_detach(struct inode *inode)
188{ 267{
@@ -193,7 +272,7 @@ void fat_detach(struct inode *inode)
193 spin_unlock(&sbi->inode_hash_lock); 272 spin_unlock(&sbi->inode_hash_lock);
194} 273}
195 274
196EXPORT_SYMBOL(fat_detach); 275EXPORT_SYMBOL_GPL(fat_detach);
197 276
198struct inode *fat_iget(struct super_block *sb, loff_t i_pos) 277struct inode *fat_iget(struct super_block *sb, loff_t i_pos)
199{ 278{
@@ -347,7 +426,7 @@ out:
347 return inode; 426 return inode;
348} 427}
349 428
350EXPORT_SYMBOL(fat_build_inode); 429EXPORT_SYMBOL_GPL(fat_build_inode);
351 430
352static void fat_delete_inode(struct inode *inode) 431static void fat_delete_inode(struct inode *inode)
353{ 432{
@@ -374,12 +453,17 @@ static void fat_clear_inode(struct inode *inode)
374 unlock_kernel(); 453 unlock_kernel();
375} 454}
376 455
377static void fat_put_super(struct super_block *sb) 456static void fat_write_super(struct super_block *sb)
378{ 457{
379 struct msdos_sb_info *sbi = MSDOS_SB(sb); 458 sb->s_dirt = 0;
380 459
381 if (!(sb->s_flags & MS_RDONLY)) 460 if (!(sb->s_flags & MS_RDONLY))
382 fat_clusters_flush(sb); 461 fat_clusters_flush(sb);
462}
463
464static void fat_put_super(struct super_block *sb)
465{
466 struct msdos_sb_info *sbi = MSDOS_SB(sb);
383 467
384 if (sbi->nls_disk) { 468 if (sbi->nls_disk) {
385 unload_nls(sbi->nls_disk); 469 unload_nls(sbi->nls_disk);
@@ -537,7 +621,7 @@ int fat_sync_inode(struct inode *inode)
537 return fat_write_inode(inode, 1); 621 return fat_write_inode(inode, 1);
538} 622}
539 623
540EXPORT_SYMBOL(fat_sync_inode); 624EXPORT_SYMBOL_GPL(fat_sync_inode);
541 625
542static int fat_show_options(struct seq_file *m, struct vfsmount *mnt); 626static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);
543static struct super_operations fat_sops = { 627static struct super_operations fat_sops = {
@@ -546,6 +630,7 @@ static struct super_operations fat_sops = {
546 .write_inode = fat_write_inode, 630 .write_inode = fat_write_inode,
547 .delete_inode = fat_delete_inode, 631 .delete_inode = fat_delete_inode,
548 .put_super = fat_put_super, 632 .put_super = fat_put_super,
633 .write_super = fat_write_super,
549 .statfs = fat_statfs, 634 .statfs = fat_statfs,
550 .clear_inode = fat_clear_inode, 635 .clear_inode = fat_clear_inode,
551 .remount_fs = fat_remount, 636 .remount_fs = fat_remount,
@@ -1347,7 +1432,7 @@ out_fail:
1347 return error; 1432 return error;
1348} 1433}
1349 1434
1350EXPORT_SYMBOL(fat_fill_super); 1435EXPORT_SYMBOL_GPL(fat_fill_super);
1351 1436
1352int __init fat_cache_init(void); 1437int __init fat_cache_init(void);
1353void fat_cache_destroy(void); 1438void fat_cache_destroy(void);
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 2a0df2122f5..32fb0a3f1da 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -33,7 +33,7 @@ void fat_fs_panic(struct super_block *s, const char *fmt, ...)
33 } 33 }
34} 34}
35 35
36EXPORT_SYMBOL(fat_fs_panic); 36EXPORT_SYMBOL_GPL(fat_fs_panic);
37 37
38/* Flushes the number of free clusters on FAT32 */ 38/* Flushes the number of free clusters on FAT32 */
39/* XXX: Need to write one per FSINFO block. Currently only writes 1 */ 39/* XXX: Need to write one per FSINFO block. Currently only writes 1 */
@@ -67,8 +67,6 @@ void fat_clusters_flush(struct super_block *sb)
67 if (sbi->prev_free != -1) 67 if (sbi->prev_free != -1)
68 fsinfo->next_cluster = cpu_to_le32(sbi->prev_free); 68 fsinfo->next_cluster = cpu_to_le32(sbi->prev_free);
69 mark_buffer_dirty(bh); 69 mark_buffer_dirty(bh);
70 if (sb->s_flags & MS_SYNCHRONOUS)
71 sync_dirty_buffer(bh);
72 } 70 }
73 brelse(bh); 71 brelse(bh);
74} 72}
@@ -194,7 +192,7 @@ void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
194 *date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9)); 192 *date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9));
195} 193}
196 194
197EXPORT_SYMBOL(fat_date_unix2dos); 195EXPORT_SYMBOL_GPL(fat_date_unix2dos);
198 196
199int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) 197int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
200{ 198{
@@ -222,4 +220,4 @@ int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
222 return err; 220 return err;
223} 221}
224 222
225EXPORT_SYMBOL(fat_sync_bhs); 223EXPORT_SYMBOL_GPL(fat_sync_bhs);