Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

Al Viro b522412a 964f5369

+49 -19
+8 -8
fs/fat/dir.c
··· 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 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 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 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 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 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 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 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 }
+6
fs/fat/fat.h
··· 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]; ··· 252 251 } u; 253 252 int nr_bhs; 254 253 struct buffer_head *bhs[2]; 254 + struct inode *fat_inode; 255 255 }; 256 256 257 257 static inline void fatent_init(struct fat_entry *fatent) ··· 261 259 fatent->entry = 0; 262 260 fatent->u.ent32_p = NULL; 263 261 fatent->bhs[0] = fatent->bhs[1] = NULL; 262 + fatent->fat_inode = NULL; 264 263 } 265 264 266 265 static inline void fatent_set_entry(struct fat_entry *fatent, int entry) ··· 278 275 brelse(fatent->bhs[i]); 279 276 fatent->nr_bhs = 0; 280 277 fatent->bhs[0] = fatent->bhs[1] = NULL; 278 + fatent->fat_inode = NULL; 281 279 } 282 280 283 281 extern void fat_ent_access_init(struct super_block *sb); ··· 300 296 extern void fat_truncate(struct inode *inode); 301 297 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, 302 298 struct kstat *stat); 299 + extern int fat_file_fsync(struct file *file, struct dentry *dentry, 300 + int datasync); 303 301 304 302 /* fat/inode.c */ 305 303 extern void fat_attach(struct inode *inode, loff_t i_pos);
+8 -5
fs/fat/fatent.c
··· 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; ··· 105 103 struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops; 106 104 107 105 WARN_ON(blocknr < MSDOS_SB(sb)->fat_start); 106 + fatent->fat_inode = MSDOS_SB(sb)->fat_inode; 108 107 fatent->bhs[0] = sb_bread(sb, blocknr); 109 108 if (!fatent->bhs[0]) { 110 109 printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", ··· 170 167 } 171 168 spin_unlock(&fat12_entry_lock); 172 169 173 - mark_buffer_dirty(fatent->bhs[0]); 170 + mark_buffer_dirty_inode(fatent->bhs[0], fatent->fat_inode); 174 171 if (fatent->nr_bhs == 2) 175 - mark_buffer_dirty(fatent->bhs[1]); 172 + mark_buffer_dirty_inode(fatent->bhs[1], fatent->fat_inode); 176 173 } 177 174 178 175 static void fat16_ent_put(struct fat_entry *fatent, int new) ··· 181 178 new = EOF_FAT16; 182 179 183 180 *fatent->u.ent16_p = cpu_to_le16(new); 184 - mark_buffer_dirty(fatent->bhs[0]); 181 + mark_buffer_dirty_inode(fatent->bhs[0], fatent->fat_inode); 185 182 } 186 183 187 184 static void fat32_ent_put(struct fat_entry *fatent, int new) ··· 192 189 WARN_ON(new & 0xf0000000); 193 190 new |= le32_to_cpu(*fatent->u.ent32_p) & ~0x0fffffff; 194 191 *fatent->u.ent32_p = cpu_to_le32(new); 195 - mark_buffer_dirty(fatent->bhs[0]); 192 + mark_buffer_dirty_inode(fatent->bhs[0], fatent->fat_inode); 196 193 } 197 194 198 195 static int fat12_ent_next(struct fat_entry *fatent) ··· 384 381 } 385 382 memcpy(c_bh->b_data, bhs[n]->b_data, sb->s_blocksize); 386 383 set_buffer_uptodate(c_bh); 387 - mark_buffer_dirty(c_bh); 384 + mark_buffer_dirty_inode(c_bh, sbi->fat_inode); 388 385 if (sb->s_flags & MS_SYNCHRONOUS) 389 386 err = sync_dirty_buffer(c_bh); 390 387 brelse(c_bh);
+13 -1
fs/fat/file.c
··· 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, ··· 154 142 .mmap = generic_file_mmap, 155 143 .release = fat_file_release, 156 144 .ioctl = fat_generic_ioctl, 157 - .fsync = file_fsync, 145 + .fsync = fat_file_fsync, 158 146 .splice_read = generic_file_splice_read, 159 147 }; 160 148
+10 -1
fs/fat/inode.c
··· 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; ··· 1185 1183 int fat_fill_super(struct super_block *sb, void *data, int silent, 1186 1184 const struct inode_operations *fs_dir_inode_ops, int isvfat) 1187 1185 { 1188 - struct inode *root_inode = NULL; 1186 + struct inode *root_inode = NULL, *fat_inode = NULL; 1189 1187 struct buffer_head *bh; 1190 1188 struct fat_boot_sector *b; 1191 1189 struct msdos_sb_info *sbi; ··· 1425 1423 } 1426 1424 1427 1425 error = -ENOMEM; 1426 + fat_inode = new_inode(sb); 1427 + if (!fat_inode) 1428 + goto out_fail; 1429 + MSDOS_I(fat_inode)->i_pos = 0; 1430 + sbi->fat_inode = fat_inode; 1428 1431 root_inode = new_inode(sb); 1429 1432 if (!root_inode) 1430 1433 goto out_fail; ··· 1455 1448 " on dev %s.\n", sb->s_id); 1456 1449 1457 1450 out_fail: 1451 + if (fat_inode) 1452 + iput(fat_inode); 1458 1453 if (root_inode) 1459 1454 iput(root_inode); 1460 1455 if (sbi->nls_io)
+2 -2
fs/fat/namei_msdos.c
··· 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 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:
+2 -2
fs/fat/namei_vfat.c
··· 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 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: