Commit b522412aeabadbb302fd4338eaabf09d10e2d29c

Authored by Al Viro
1 parent 964f536966

Sanitize ->fsync() for FAT

* mark directory data blocks as assoc. metadata
* add new inode to deal with FAT, mark FAT blocks as assoc. metadata of that
* now ->fsync() is trivial both for files and directories

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 7 changed files with 49 additions and 19 deletions Side-by-side Diff

... ... @@ -840,7 +840,7 @@
840 840 #ifdef CONFIG_COMPAT
841 841 .compat_ioctl = fat_compat_dir_ioctl,
842 842 #endif
843   - .fsync = file_fsync,
  843 + .fsync = fat_file_fsync,
844 844 };
845 845  
846 846 static int fat_get_short_entry(struct inode *dir, loff_t *pos,
... ... @@ -967,7 +967,7 @@
967 967 de++;
968 968 nr_slots--;
969 969 }
970   - mark_buffer_dirty(bh);
  970 + mark_buffer_dirty_inode(bh, dir);
971 971 if (IS_DIRSYNC(dir))
972 972 err = sync_dirty_buffer(bh);
973 973 brelse(bh);
... ... @@ -1001,7 +1001,7 @@
1001 1001 de--;
1002 1002 nr_slots--;
1003 1003 }
1004   - mark_buffer_dirty(bh);
  1004 + mark_buffer_dirty_inode(bh, dir);
1005 1005 if (IS_DIRSYNC(dir))
1006 1006 err = sync_dirty_buffer(bh);
1007 1007 brelse(bh);
... ... @@ -1051,7 +1051,7 @@
1051 1051 }
1052 1052 memset(bhs[n]->b_data, 0, sb->s_blocksize);
1053 1053 set_buffer_uptodate(bhs[n]);
1054   - mark_buffer_dirty(bhs[n]);
  1054 + mark_buffer_dirty_inode(bhs[n], dir);
1055 1055  
1056 1056 n++;
1057 1057 blknr++;
... ... @@ -1131,7 +1131,7 @@
1131 1131 de[0].size = de[1].size = 0;
1132 1132 memset(de + 2, 0, sb->s_blocksize - 2 * sizeof(*de));
1133 1133 set_buffer_uptodate(bhs[0]);
1134   - mark_buffer_dirty(bhs[0]);
  1134 + mark_buffer_dirty_inode(bhs[0], dir);
1135 1135  
1136 1136 err = fat_zeroed_cluster(dir, blknr, 1, bhs, MAX_BUF_PER_PAGE);
1137 1137 if (err)
... ... @@ -1193,7 +1193,7 @@
1193 1193 slots += copy;
1194 1194 size -= copy;
1195 1195 set_buffer_uptodate(bhs[n]);
1196   - mark_buffer_dirty(bhs[n]);
  1196 + mark_buffer_dirty_inode(bhs[n], dir);
1197 1197 if (!size)
1198 1198 break;
1199 1199 n++;
... ... @@ -1293,7 +1293,7 @@
1293 1293 for (i = 0; i < long_bhs; i++) {
1294 1294 int copy = min_t(int, sb->s_blocksize - offset, size);
1295 1295 memcpy(bhs[i]->b_data + offset, slots, copy);
1296   - mark_buffer_dirty(bhs[i]);
  1296 + mark_buffer_dirty_inode(bhs[i], dir);
1297 1297 offset = 0;
1298 1298 slots += copy;
1299 1299 size -= copy;
... ... @@ -1304,7 +1304,7 @@
1304 1304 /* Fill the short name slot. */
1305 1305 int copy = min_t(int, sb->s_blocksize - offset, size);
1306 1306 memcpy(bhs[i]->b_data + offset, slots, copy);
1307   - mark_buffer_dirty(bhs[i]);
  1307 + mark_buffer_dirty_inode(bhs[i], dir);
1308 1308 if (IS_DIRSYNC(dir))
1309 1309 err = sync_dirty_buffer(bhs[i]);
1310 1310 }
... ... @@ -74,6 +74,7 @@
74 74  
75 75 int fatent_shift;
76 76 struct fatent_operations *fatent_ops;
  77 + struct inode *fat_inode;
77 78  
78 79 spinlock_t inode_hash_lock;
79 80 struct hlist_head inode_hashtable[FAT_HASH_SIZE];
... ... @@ -251,6 +252,7 @@
251 252 } u;
252 253 int nr_bhs;
253 254 struct buffer_head *bhs[2];
  255 + struct inode *fat_inode;
254 256 };
255 257  
256 258 static inline void fatent_init(struct fat_entry *fatent)
... ... @@ -259,6 +261,7 @@
259 261 fatent->entry = 0;
260 262 fatent->u.ent32_p = NULL;
261 263 fatent->bhs[0] = fatent->bhs[1] = NULL;
  264 + fatent->fat_inode = NULL;
262 265 }
263 266  
264 267 static inline void fatent_set_entry(struct fat_entry *fatent, int entry)
... ... @@ -275,6 +278,7 @@
275 278 brelse(fatent->bhs[i]);
276 279 fatent->nr_bhs = 0;
277 280 fatent->bhs[0] = fatent->bhs[1] = NULL;
  281 + fatent->fat_inode = NULL;
278 282 }
279 283  
280 284 extern void fat_ent_access_init(struct super_block *sb);
... ... @@ -296,6 +300,8 @@
296 300 extern void fat_truncate(struct inode *inode);
297 301 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
298 302 struct kstat *stat);
  303 +extern int fat_file_fsync(struct file *file, struct dentry *dentry,
  304 + int datasync);
299 305  
300 306 /* fat/inode.c */
301 307 extern void fat_attach(struct inode *inode, loff_t i_pos);
... ... @@ -73,6 +73,8 @@
73 73 struct buffer_head **bhs = fatent->bhs;
74 74  
75 75 WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
  76 + fatent->fat_inode = MSDOS_SB(sb)->fat_inode;
  77 +
76 78 bhs[0] = sb_bread(sb, blocknr);
77 79 if (!bhs[0])
78 80 goto err;
... ... @@ -103,6 +105,7 @@
103 105 struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
104 106  
105 107 WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
  108 + fatent->fat_inode = MSDOS_SB(sb)->fat_inode;
106 109 fatent->bhs[0] = sb_bread(sb, blocknr);
107 110 if (!fatent->bhs[0]) {
108 111 printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
109 112  
... ... @@ -167,9 +170,9 @@
167 170 }
168 171 spin_unlock(&fat12_entry_lock);
169 172  
170   - mark_buffer_dirty(fatent->bhs[0]);
  173 + mark_buffer_dirty_inode(fatent->bhs[0], fatent->fat_inode);
171 174 if (fatent->nr_bhs == 2)
172   - mark_buffer_dirty(fatent->bhs[1]);
  175 + mark_buffer_dirty_inode(fatent->bhs[1], fatent->fat_inode);
173 176 }
174 177  
175 178 static void fat16_ent_put(struct fat_entry *fatent, int new)
... ... @@ -178,7 +181,7 @@
178 181 new = EOF_FAT16;
179 182  
180 183 *fatent->u.ent16_p = cpu_to_le16(new);
181   - mark_buffer_dirty(fatent->bhs[0]);
  184 + mark_buffer_dirty_inode(fatent->bhs[0], fatent->fat_inode);
182 185 }
183 186  
184 187 static void fat32_ent_put(struct fat_entry *fatent, int new)
... ... @@ -189,7 +192,7 @@
189 192 WARN_ON(new & 0xf0000000);
190 193 new |= le32_to_cpu(*fatent->u.ent32_p) & ~0x0fffffff;
191 194 *fatent->u.ent32_p = cpu_to_le32(new);
192   - mark_buffer_dirty(fatent->bhs[0]);
  195 + mark_buffer_dirty_inode(fatent->bhs[0], fatent->fat_inode);
193 196 }
194 197  
195 198 static int fat12_ent_next(struct fat_entry *fatent)
... ... @@ -381,7 +384,7 @@
381 384 }
382 385 memcpy(c_bh->b_data, bhs[n]->b_data, sb->s_blocksize);
383 386 set_buffer_uptodate(c_bh);
384   - mark_buffer_dirty(c_bh);
  387 + mark_buffer_dirty_inode(c_bh, sbi->fat_inode);
385 388 if (sb->s_flags & MS_SYNCHRONOUS)
386 389 err = sync_dirty_buffer(c_bh);
387 390 brelse(c_bh);
... ... @@ -133,6 +133,18 @@
133 133 return 0;
134 134 }
135 135  
  136 +int fat_file_fsync(struct file *filp, struct dentry *dentry, int datasync)
  137 +{
  138 + struct inode *inode = dentry->d_inode;
  139 + int res, err;
  140 +
  141 + res = simple_fsync(filp, dentry, datasync);
  142 + err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);
  143 +
  144 + return res ? res : err;
  145 +}
  146 +
  147 +
136 148 const struct file_operations fat_file_operations = {
137 149 .llseek = generic_file_llseek,
138 150 .read = do_sync_read,
... ... @@ -142,7 +154,7 @@
142 154 .mmap = generic_file_mmap,
143 155 .release = fat_file_release,
144 156 .ioctl = fat_generic_ioctl,
145   - .fsync = file_fsync,
  157 + .fsync = fat_file_fsync,
146 158 .splice_read = generic_file_splice_read,
147 159 };
148 160  
... ... @@ -458,6 +458,8 @@
458 458 if (sb->s_dirt)
459 459 fat_write_super(sb);
460 460  
  461 + iput(sbi->fat_inode);
  462 +
461 463 if (sbi->nls_disk) {
462 464 unload_nls(sbi->nls_disk);
463 465 sbi->nls_disk = NULL;
... ... @@ -1183,7 +1185,7 @@
1183 1185 int fat_fill_super(struct super_block *sb, void *data, int silent,
1184 1186 const struct inode_operations *fs_dir_inode_ops, int isvfat)
1185 1187 {
1186   - struct inode *root_inode = NULL;
  1188 + struct inode *root_inode = NULL, *fat_inode = NULL;
1187 1189 struct buffer_head *bh;
1188 1190 struct fat_boot_sector *b;
1189 1191 struct msdos_sb_info *sbi;
... ... @@ -1423,6 +1425,11 @@
1423 1425 }
1424 1426  
1425 1427 error = -ENOMEM;
  1428 + fat_inode = new_inode(sb);
  1429 + if (!fat_inode)
  1430 + goto out_fail;
  1431 + MSDOS_I(fat_inode)->i_pos = 0;
  1432 + sbi->fat_inode = fat_inode;
1426 1433 root_inode = new_inode(sb);
1427 1434 if (!root_inode)
1428 1435 goto out_fail;
... ... @@ -1448,6 +1455,8 @@
1448 1455 " on dev %s.\n", sb->s_id);
1449 1456  
1450 1457 out_fail:
  1458 + if (fat_inode)
  1459 + iput(fat_inode);
1451 1460 if (root_inode)
1452 1461 iput(root_inode);
1453 1462 if (sbi->nls_io)
fs/fat/namei_msdos.c
... ... @@ -544,7 +544,7 @@
544 544 int start = MSDOS_I(new_dir)->i_logstart;
545 545 dotdot_de->start = cpu_to_le16(start);
546 546 dotdot_de->starthi = cpu_to_le16(start >> 16);
547   - mark_buffer_dirty(dotdot_bh);
  547 + mark_buffer_dirty_inode(dotdot_bh, old_inode);
548 548 if (IS_DIRSYNC(new_dir)) {
549 549 err = sync_dirty_buffer(dotdot_bh);
550 550 if (err)
... ... @@ -586,7 +586,7 @@
586 586 int start = MSDOS_I(old_dir)->i_logstart;
587 587 dotdot_de->start = cpu_to_le16(start);
588 588 dotdot_de->starthi = cpu_to_le16(start >> 16);
589   - mark_buffer_dirty(dotdot_bh);
  589 + mark_buffer_dirty_inode(dotdot_bh, old_inode);
590 590 corrupt |= sync_dirty_buffer(dotdot_bh);
591 591 }
592 592 error_inode:
... ... @@ -965,7 +965,7 @@
965 965 int start = MSDOS_I(new_dir)->i_logstart;
966 966 dotdot_de->start = cpu_to_le16(start);
967 967 dotdot_de->starthi = cpu_to_le16(start >> 16);
968   - mark_buffer_dirty(dotdot_bh);
  968 + mark_buffer_dirty_inode(dotdot_bh, old_inode);
969 969 if (IS_DIRSYNC(new_dir)) {
970 970 err = sync_dirty_buffer(dotdot_bh);
971 971 if (err)
... ... @@ -1009,7 +1009,7 @@
1009 1009 int start = MSDOS_I(old_dir)->i_logstart;
1010 1010 dotdot_de->start = cpu_to_le16(start);
1011 1011 dotdot_de->starthi = cpu_to_le16(start >> 16);
1012   - mark_buffer_dirty(dotdot_bh);
  1012 + mark_buffer_dirty_inode(dotdot_bh, old_inode);
1013 1013 corrupt |= sync_dirty_buffer(dotdot_bh);
1014 1014 }
1015 1015 error_inode: