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

fat: factor out reusable code in vfat_rename() as helper functions

The vfat_rename() function is quite big and there are code blocks that can
be moved into helper functions. This not only simplify the implementation
of that function but also allows these helpers to be reused.

For example, the helpers can be used by the handler of the RENAME_EXCHANGE
flag once this is implemented in a subsequent patch.

Link: https://lkml.kernel.org/r/20220610075721.1182745-3-javierm@redhat.com
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Alexander Larsson <alexl@redhat.com>
Cc: Christian Kellner <ckellner@redhat.com>
Cc: Chung-Chiang Cheng <cccheng@synology.com>
Cc: Colin Walters <walters@verbum.org>
Cc: Lennart Poettering <lennart@poettering.net>
Cc: Muhammad Usama Anjum <usama.anjum@collabora.com>
Cc: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

OGAWA Hirofumi and committed by
akpm
204d0320 019a0c9e

+57 -32
+57 -32
fs/fat/namei_vfat.c
··· 889 889 return err; 890 890 } 891 891 892 + static int vfat_get_dotdot_de(struct inode *inode, struct buffer_head **bh, 893 + struct msdos_dir_entry **de) 894 + { 895 + if (S_ISDIR(inode->i_mode)) { 896 + if (fat_get_dotdot_entry(inode, bh, de)) 897 + return -EIO; 898 + } 899 + return 0; 900 + } 901 + 902 + static int vfat_sync_ipos(struct inode *dir, struct inode *inode) 903 + { 904 + if (IS_DIRSYNC(dir)) 905 + return fat_sync_inode(inode); 906 + mark_inode_dirty(inode); 907 + return 0; 908 + } 909 + 910 + static int vfat_update_dotdot_de(struct inode *dir, struct inode *inode, 911 + struct buffer_head *dotdot_bh, 912 + struct msdos_dir_entry *dotdot_de) 913 + { 914 + fat_set_start(dotdot_de, MSDOS_I(dir)->i_logstart); 915 + mark_buffer_dirty_inode(dotdot_bh, inode); 916 + if (IS_DIRSYNC(dir)) 917 + return sync_dirty_buffer(dotdot_bh); 918 + return 0; 919 + } 920 + 921 + static void vfat_update_dir_metadata(struct inode *dir, struct timespec64 *ts) 922 + { 923 + inode_inc_iversion(dir); 924 + fat_truncate_time(dir, ts, S_CTIME | S_MTIME); 925 + if (IS_DIRSYNC(dir)) 926 + (void)fat_sync_inode(dir); 927 + else 928 + mark_inode_dirty(dir); 929 + } 930 + 892 931 static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, 893 932 struct inode *new_dir, struct dentry *new_dentry) 894 933 { 895 934 struct buffer_head *dotdot_bh; 896 - struct msdos_dir_entry *dotdot_de; 935 + struct msdos_dir_entry *dotdot_de = NULL; 897 936 struct inode *old_inode, *new_inode; 898 937 struct fat_slot_info old_sinfo, sinfo; 899 938 struct timespec64 ts; 900 939 loff_t new_i_pos; 901 - int err, is_dir, update_dotdot, corrupt = 0; 940 + int err, is_dir, corrupt = 0; 902 941 struct super_block *sb = old_dir->i_sb; 903 942 904 943 old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; ··· 948 909 if (err) 949 910 goto out; 950 911 951 - is_dir = S_ISDIR(old_inode->i_mode); 952 - update_dotdot = (is_dir && old_dir != new_dir); 953 - if (update_dotdot) { 954 - if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de)) { 955 - err = -EIO; 912 + if (old_dir != new_dir) { 913 + err = vfat_get_dotdot_de(old_inode, &dotdot_bh, &dotdot_de); 914 + if (err) 956 915 goto out; 957 - } 958 916 } 959 917 918 + is_dir = S_ISDIR(old_inode->i_mode); 960 919 ts = current_time(old_dir); 961 920 if (new_inode) { 962 921 if (is_dir) { ··· 975 938 976 939 fat_detach(old_inode); 977 940 fat_attach(old_inode, new_i_pos); 978 - if (IS_DIRSYNC(new_dir)) { 979 - err = fat_sync_inode(old_inode); 980 - if (err) 981 - goto error_inode; 982 - } else 983 - mark_inode_dirty(old_inode); 941 + err = vfat_sync_ipos(new_dir, old_inode); 942 + if (err) 943 + goto error_inode; 984 944 985 - if (update_dotdot) { 986 - fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart); 987 - mark_buffer_dirty_inode(dotdot_bh, old_inode); 988 - if (IS_DIRSYNC(new_dir)) { 989 - err = sync_dirty_buffer(dotdot_bh); 990 - if (err) 991 - goto error_dotdot; 992 - } 945 + if (dotdot_de) { 946 + err = vfat_update_dotdot_de(new_dir, old_inode, dotdot_bh, 947 + dotdot_de); 948 + if (err) 949 + goto error_dotdot; 993 950 drop_nlink(old_dir); 994 951 if (!new_inode) 995 952 inc_nlink(new_dir); ··· 993 962 old_sinfo.bh = NULL; 994 963 if (err) 995 964 goto error_dotdot; 996 - inode_inc_iversion(old_dir); 997 - fat_truncate_time(old_dir, &ts, S_CTIME|S_MTIME); 998 - if (IS_DIRSYNC(old_dir)) 999 - (void)fat_sync_inode(old_dir); 1000 - else 1001 - mark_inode_dirty(old_dir); 965 + vfat_update_dir_metadata(old_dir, &ts); 1002 966 1003 967 if (new_inode) { 1004 968 drop_nlink(new_inode); ··· 1013 987 /* data cluster is shared, serious corruption */ 1014 988 corrupt = 1; 1015 989 1016 - if (update_dotdot) { 1017 - fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart); 1018 - mark_buffer_dirty_inode(dotdot_bh, old_inode); 1019 - corrupt |= sync_dirty_buffer(dotdot_bh); 990 + if (dotdot_de) { 991 + corrupt |= vfat_update_dotdot_de(old_dir, old_inode, dotdot_bh, 992 + dotdot_de); 1020 993 } 1021 994 error_inode: 1022 995 fat_detach(old_inode);