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

Configure Feed

Select the types of activity you want to include in your feed.

fs/ntfs3: fsync files by syncing parent inodes

Some xfstests expect fsync() on a file or directory to also persist
directory metadata up the parent chain. Using generic_file_fsync() is not
sufficient for ntfs, because parent directories are not explicitly
written out.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>

+81 -4
+1 -1
fs/ntfs3/dir.c
··· 668 668 .llseek = generic_file_llseek, 669 669 .read = generic_read_dir, 670 670 .iterate_shared = ntfs_readdir, 671 - .fsync = generic_file_fsync, 671 + .fsync = ntfs_file_fsync, 672 672 .open = ntfs_file_open, 673 673 .unlocked_ioctl = ntfs_ioctl, 674 674 #ifdef CONFIG_COMPAT
+27 -3
fs/ntfs3/file.c
··· 1443 1443 /* 1444 1444 * ntfs_file_fsync - file_operations::fsync 1445 1445 */ 1446 - static int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) 1446 + int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) 1447 1447 { 1448 1448 struct inode *inode = file_inode(file); 1449 - if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) 1449 + struct super_block *sb = inode->i_sb; 1450 + struct ntfs_sb_info *sbi = sb->s_fs_info; 1451 + int err, ret; 1452 + 1453 + if (unlikely(ntfs3_forced_shutdown(sb))) 1450 1454 return -EIO; 1451 1455 1452 - return generic_file_fsync(file, start, end, datasync); 1456 + ret = file_write_and_wait_range(file, start, end); 1457 + if (ret) 1458 + return ret; 1459 + 1460 + ret = write_inode_now(inode, !datasync); 1461 + 1462 + if (!ret) { 1463 + ret = ni_write_parents(ntfs_i(inode), !datasync); 1464 + } 1465 + 1466 + if (!ret) { 1467 + ntfs_set_state(sbi, NTFS_DIRTY_CLEAR); 1468 + ntfs_update_mftmirr(sbi, false); 1469 + } 1470 + 1471 + err = sync_blockdev(sb->s_bdev); 1472 + if (unlikely(err && !ret)) 1473 + ret = err; 1474 + if (!ret) 1475 + blkdev_issue_flush(sb->s_bdev); 1476 + return ret; 1453 1477 } 1454 1478 1455 1479 // clang-format off
+51
fs/ntfs3/frecord.c
··· 3002 3002 } 3003 3003 3004 3004 /* 3005 + * ni_write_parents 3006 + * 3007 + * Helper function for ntfs_file_fsync. 3008 + */ 3009 + int ni_write_parents(struct ntfs_inode *ni, int sync) 3010 + { 3011 + int err = 0; 3012 + struct ATTRIB *attr = NULL; 3013 + struct ATTR_LIST_ENTRY *le = NULL; 3014 + struct ntfs_sb_info *sbi = ni->mi.sbi; 3015 + struct super_block *sb = sbi->sb; 3016 + 3017 + while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL, 3018 + NULL))) { 3019 + struct inode *dir; 3020 + struct ATTR_FILE_NAME *fname; 3021 + 3022 + fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME); 3023 + if (!fname) 3024 + continue; 3025 + 3026 + /* Check simple case when parent inode equals current inode. */ 3027 + if (ino_get(&fname->home) == ni->vfs_inode.i_ino) { 3028 + if (MFT_REC_ROOT != ni->vfs_inode.i_ino) { 3029 + ntfs_set_state(sbi, NTFS_DIRTY_ERROR); 3030 + err = -EINVAL; 3031 + } 3032 + continue; 3033 + } 3034 + 3035 + dir = ntfs_iget5(sb, &fname->home, NULL); 3036 + if (IS_ERR(dir)) { 3037 + ntfs_inode_warn( 3038 + &ni->vfs_inode, 3039 + "failed to open parent directory r=%lx to write", 3040 + (long)ino_get(&fname->home)); 3041 + continue; 3042 + } 3043 + 3044 + if (!is_bad_inode(dir)) { 3045 + int err2 = write_inode_now(dir, sync); 3046 + if (!err) 3047 + err = err2; 3048 + } 3049 + iput(dir); 3050 + } 3051 + 3052 + return err; 3053 + } 3054 + 3055 + /* 3005 3056 * ni_update_parent 3006 3057 * 3007 3058 * Update duplicate info of ATTR_FILE_NAME in MFT and in parent directories.
+2
fs/ntfs3/ntfs_fs.h
··· 512 512 int ntfs_file_open(struct inode *inode, struct file *file); 513 513 int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 514 514 __u64 start, __u64 len); 515 + int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync); 515 516 long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg); 516 517 long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg); 517 518 extern const struct inode_operations ntfs_special_inode_operations; ··· 591 590 struct NTFS_DE *new_de); 592 591 593 592 bool ni_is_dirty(struct inode *inode); 593 + int ni_write_parents(struct ntfs_inode *ni, int sync); 594 594 595 595 /* Globals from fslog.c */ 596 596 bool check_index_header(const struct INDEX_HDR *hdr, size_t bytes);