fat: fix writev(), add aio support
A message that is not in the archive (sent off-list or not yet received): [email protected]
OGAWA Hirofumi
maintainerPATCH 1/29 fat: fix writev(), add aio support
This patch fixes vectored write support on fat to do the nessecary non-standard action done in write() aswell.
Also adds aio support and makes read/write wrappers around the aio version.
From: Christoph Hellwig <[email protected]>
---
fs/fat/file.c | 31 ++++++++++++++++++++++++------- 1 files changed, 24 insertions(+), 7 deletions(-)
fs/fat/file.c renamed from fs/fat/file.c~fat_support-aio +24 -7
@@ -12,13 +12,28 @@#include <linux/smp_lock.h> #include <linux/buffer_head.h> -static ssize_t fat_file_write (struct file *filp,const char __user *buf, -size_t count,loff_t *ppos) +static ssize_t fat_file_aio_write (struct kiocb *iocb,const char __user *buf, +size_t count,loff_t pos) +{ +struct inode *inode = iocb->ki_filp->f_dentry->d_inode; +int retval; + + retval =generic_file_aio_write (iocb, buf, count, pos); +if (retval >0 ) { + inode->i_mtime = inode->i_ctime =CURRENT_TIME_SEC ; +MSDOS_I (inode)->i_attrs |=ATTR_ARCH ; +mark_inode_dirty (inode); + } +return retval; +} + +static ssize_t fat_file_writev (struct file *filp,const struct iovec *iov, +unsigned long nr_segs,loff_t *ppos) {struct inode *inode = filp->f_dentry->d_inode;int retval; - retval =generic_file_write (filp, buf, count, ppos); + retval =generic_file_writev (filp, iov, nr_segs, ppos);if (retval >0 ) { inode->i_mtime = inode->i_ctime =CURRENT_TIME_SEC ;MSDOS_I (inode)->i_attrs |=ATTR_ARCH ;
@@ -29,12 +44,14 @@ static ssize_t fat_file_write(struct filstruct file_operations fat_file_operations = { .llseek = generic_file_llseek, - .read = generic_file_read, - .write = fat_file_write, + .read = do_sync_read, + .write = do_sync_write, + .readv = generic_file_readv, + .writev = fat_file_writev, + .aio_read = generic_file_aio_read, + .aio_write = fat_file_aio_write, .mmap = generic_file_mmap, .fsync = file_fsync, - .readv = generic_file_readv, - .writev = generic_file_writev, .sendfile = generic_file_sendfile, };
_
OGAWA Hirofumi
maintainerPATCH 2/29 FAT: Updated FAT attributes patch
This updates the FAT attributes as well as (hopefully) corrects the handling of VFAT ctime. The FAT attributes are implemented as a 32-bit ioctl, per the previous discussions.
---
fs/fat/dir.c | 2 fs/fat/file.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++ fs/fat/inode.c | 38 ++++++++---------- fs/vfat/namei.c | 2 include/linux/msdos_fs.h | 22 +++++++--- 5 files changed, 135 insertions(+), 28 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~fat_attribute-ioctl +1 -1
@@ -639,7 +639,7 @@ static int fat_dir_ioctl(struct inode * both =1 ;break ;default : -return -EINVAL ; +return fat_generic_ioctl (inode, filp, cmd, arg); } d1 = (struct dirent __user *)arg;
fs/fat/file.c renamed from fs/fat/file.c~fat_attribute-ioctl +99 -0
111 lines not on this page · raw message
fs/fat/inode.c renamed from fs/fat/inode.c~fat_attribute-ioctl +18 -20
@@ -220,8 +220,7 @@ static int fat_calc_dir_size(struct inod/* doesn't deal with root inode */ static int fat_fill_inode (struct inode *inode,struct msdos_dir_entry *de) { -struct super_block *sb = inode->i_sb; -struct msdos_sb_info *sbi =MSDOS_SB (sb); +struct msdos_sb_info *sbi =MSDOS_SB (inode->i_sb);int error;MSDOS_I (inode)->i_pos =0 ;
@@ -266,9 +265,10 @@ static int fat_fill_inode(struct inode * inode->i_mapping->a_ops = &fat_aops;MSDOS_I (inode)->mmu_private = inode->i_size; } -if (de->attr &ATTR_SYS ) +if (de->attr &ATTR_SYS ) {if (sbi->options.sys_immutable) inode->i_flags |=S_IMMUTABLE ; + }MSDOS_I (inode)->i_attrs = de->attr &ATTR_UNUSED ;/* this is as close to the truth as we can get ... */ inode->i_blksize = sbi->cluster_size;
@@ -277,12 +277,15 @@ static int fat_fill_inode(struct inode * inode->i_mtime.tv_sec = inode->i_atime.tv_sec =date_dos2unix (le16_to_cpu (de->time),le16_to_cpu (de->date)); inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec =0 ; - inode->i_ctime.tv_sec = -MSDOS_SB (sb)->options.isvfat - ?date_dos2unix (le16_to_cpu (de->ctime),le16_to_cpu (de->cdate)) - : inode->i_mtime.tv_sec; - inode->i_ctime.tv_nsec = de->ctime_ms *1000000 ; -MSDOS_I (inode)->i_ctime_ms = de->ctime_ms; +if (sbi->options.isvfat) { +int secs = de->ctime_cs /100 ; +int csecs = de->ctime_cs %100 ; + inode->i_ctime.tv_sec = +date_dos2unix (le16_to_cpu (de->ctime), +le16_to_cpu (de->cdate)) + secs; + inode->i_ctime.tv_nsec = csecs *10000000 ; + }else + inode->i_ctime = inode->i_mtime;return 0 ; }
@@ -483,22 +486,18 @@ retry: raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) [i_pos & (sbi->dir_per_block -1 )]; -if (S_ISDIR (inode->i_mode)) { - raw_entry->attr =ATTR_DIR ; +if (S_ISDIR (inode->i_mode)) raw_entry->size =0 ; - } -else { - raw_entry->attr =ATTR_NONE ; +else raw_entry->size =cpu_to_le32 (inode->i_size); - } - raw_entry->attr |=MSDOS_MKATTR (inode->i_mode) | -MSDOS_I (inode)->i_attrs; + raw_entry->attr =fat_attr (inode); raw_entry->start =cpu_to_le16 (MSDOS_I (inode)->i_logstart); raw_entry->starthi =cpu_to_le16 (MSDOS_I (inode)->i_logstart >>16 );fat_date_unix2dos (inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);if (sbi->options.isvfat) {fat_date_unix2dos (inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); - raw_entry->ctime_ms =MSDOS_I (inode)->i_ctime_ms;/* use i_ctime.tv_nsec? */ + raw_entry->ctime_cs = (inode->i_ctime.tv_sec &1 ) *100 + + inode->i_ctime.tv_nsec /10000000 ; }spin_unlock (&sbi->inode_hash_lock);mark_buffer_dirty (bh);
@@ -1026,10 +1025,9 @@ static int fat_read_root(struct inode *iMSDOS_I (inode)->i_logstart =0 ;MSDOS_I (inode)->mmu_private = inode->i_size; -MSDOS_I (inode)->i_attrs =0 ; +MSDOS_I (inode)->i_attrs =ATTR_NONE ; inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec =0 ; inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec =0 ; -MSDOS_I (inode)->i_ctime_ms =0 ; inode->i_nlink =fat_subdirs (inode)+2 ;return 0 ;
fs/vfat/namei.c renamed from fs/vfat/namei.c~fat_attribute-ioctl +1 -1
@@ -649,7 +649,7 @@ shortname: de->lcase = lcase; de->adate = de->cdate = de->date =0 ; de->ctime = de->time =0 ; - de->ctime_ms =0 ; + de->ctime_cs =0 ; de->start =0 ; de->starthi =0 ; de->size =0 ;
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~fat_attribute-ioctl +16 -6
@@ -50,8 +50,6 @@#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)/* Convert attribute bits and a mask to the UNIX mode. */ #define MSDOS_MKMODE (a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO)) -/* Convert the UNIX mode to MS-DOS attribute bits. */ -#define MSDOS_MKATTR (m) ((m & S_IWUGO) ? ATTR_NONE : ATTR_RO)#define MSDOS_NAME 11/* maximum name length */ #define MSDOS_LONGNAME 256/* maximum name length */
@@ -100,8 +98,11 @@/* * ioctl commands */ -#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) -#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) +#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) +#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) +/* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */ +#define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) +#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32)/* * vfat shortname flags
@@ -152,7 +153,7 @@ struct msdos_dir_entry {__u8 name[8 ],ext[3 ];/* name and extension */ __u8 attr;/* attribute bits */ __u8 lcase;/* Case for base and extension */ -__u8 ctime_ms;/* Creation time, milliseconds */ +__u8 ctime_cs;/* Creation time, centiseconds (0-199) */ __le16 ctime;/* Creation time */ __le16 cdate;/* Creation date */ __le16 adate;/* Last access date */
@@ -257,7 +258,6 @@ struct msdos_inode_info {int i_start;/* first cluster or 0 */ int i_logstart;/* logical first cluster */ int i_attrs;/* unused attribute bits */ -int i_ctime_ms;/* unused change time in milliseconds */ loff_t i_pos;/* on-disk position of directory entry or 0 */ struct hlist_node i_fat_hash;/* hash by i_location */ struct inode vfs_inode;
@@ -273,6 +273,14 @@ static inline struct msdos_inode_info *M return container_of(inode, struct msdos_inode_info, vfs_inode); } +/* Return the FAT attribute byte for this inode */ +static inline u8 fat_attr (struct inode *inode) +{ +return ((inode->i_mode &S_IWUGO ) ?ATTR_NONE :ATTR_RO ) | + (S_ISDIR (inode->i_mode) ?ATTR_DIR :ATTR_NONE ) | +MSDOS_I (inode)->i_attrs; +} +static inline sector_t fat_clus_to_blknr (struct msdos_sb_info *sbi,int clus) {return ((sector_t )clus -FAT_START_ENT ) * sbi->sec_per_clus
@@ -328,6 +336,8 @@ extern int fat_scan(struct inode *dir, c struct msdos_dir_entry **res_de, loff_t *i_pos);/* fat/file.c */ +extern int fat_generic_ioctl (struct inode *inode,struct file *filp, +unsigned int cmd,unsigned long arg);extern struct file_operations fat_file_operations;extern struct inode_operations fat_file_inode_operations;extern int fat_notify_change (struct dentry * dentry,struct iattr * attr);
_
OGAWA Hirofumi
maintainerPATCH 3/29 FAT: fat_readdirx() with dotOK=yes fix
In the case of dotsOK, re-initialization of "ptname" pointer is needed, otherwise, "ptname" is pointing the previous start position.
This fixes it.
---
fs/fat/dir.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~fat_readdirx-fix +7 -3
@@ -442,9 +442,13 @@ ParseLong: long_slots =0 ; } -if ((de->attr &ATTR_HIDDEN ) &&MSDOS_SB (sb)->options.dotsOK) { - *ptname++ ='.' ; - dotoffset =1 ; +if (MSDOS_SB (sb)->options.dotsOK) { + ptname = bufname; + dotoffset =0 ; +if (de->attr &ATTR_HIDDEN ) { + *ptname++ ='.' ; + dotoffset =1 ; + } }memcpy (work, de->name,sizeof (de->name));
_
OGAWA Hirofumi
maintainerPATCH 4/29 let fat handle MS_SYNCHRONOUS flag
Adds MS_SYNCHRONOUS flag support.
---
fs/fat/cache.c | 8 ++++++++ fs/fat/dir.c | 26 +++++++++++++++++--------- fs/fat/file.c | 5 +++++ fs/fat/inode.c | 10 ++++++++++ fs/fat/misc.c | 2 ++ fs/vfat/namei.c | 31 ++++++++++++++++++++++++------- include/linux/msdos_fs.h | 1 + 7 files changed, 67 insertions(+), 16 deletions(-)
fs/fat/cache.c renamed from fs/fat/cache.c~sync03-fat_sync00 +8 -0
@@ -269,8 +269,12 @@ static int __fat_access(struct super_blo *p_last = (*p_last &0xf0 ) | (new_value >>8 ); }mark_buffer_dirty (bh2); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (bh2); }mark_buffer_dirty (bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (bh);for (copy =1 ; copy < sbi->fats; copy++) { b = sbi->fat_start + (first >> sb->s_blocksize_bits) + sbi->fat_length * copy;
@@ -283,10 +287,14 @@ static int __fat_access(struct super_blo }memcpy (c_bh2->b_data, bh2->b_data, sb->s_blocksize);mark_buffer_dirty (c_bh2); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (c_bh2);brelse (c_bh2); }memcpy (c_bh->b_data, bh->b_data, sb->s_blocksize);mark_buffer_dirty (c_bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (c_bh);brelse (c_bh); } }
fs/fat/dir.c renamed from fs/fat/dir.c~sync03-fat_sync00 +17 -9
@@ -778,6 +778,8 @@ static struct buffer_head *fat_extend_dimemset (bh->b_data,0 , sb->s_blocksize);set_buffer_uptodate (bh);mark_buffer_dirty (bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (bh);if (!res) res = bh;else
@@ -842,6 +844,7 @@ EXPORT_SYMBOL(fat_add_entries);int fat_new_dir (struct inode *dir,struct inode *parent,int is_vfat) { +struct super_block *sb = dir->i_sb;struct buffer_head *bh;struct msdos_dir_entry *de;__le16 date, time;
@@ -851,26 +854,31 @@ int fat_new_dir(struct inode *dir, strucreturn PTR_ERR (bh);/* zeroed out, so... */ -fat_date_unix2dos (dir->i_mtime.tv_sec,&time,&date); - de = (struct msdos_dir_entry *)&bh->b_data[0 ]; -memcpy (de[0 ].name,MSDOS_DOT ,MSDOS_NAME ); -memcpy (de[1 ].name,MSDOS_DOTDOT ,MSDOS_NAME ); +fat_date_unix2dos (dir->i_mtime.tv_sec, &time, &date); + de = (struct msdos_dir_entry *)bh->b_data; +memcpy (de[0 ].name,MSDOS_DOT ,MSDOS_NAME ); +memcpy (de[1 ].name,MSDOS_DOTDOT ,MSDOS_NAME ); de[0 ].attr = de[1 ].attr =ATTR_DIR ; de[0 ].time = de[1 ].time = time; de[0 ].date = de[1 ].date = date; -if (is_vfat) {/* extra timestamps */ +if (is_vfat) { +/* extra timestamps */ de[0 ].ctime = de[1 ].ctime = time; - de[0 ].adate = de[0 ].cdate = - de[1 ].adate = de[1 ].cdate = date; + de[0 ].adate = de[0 ].cdate = de[1 ].adate = de[1 ].cdate = date; } de[0 ].start =cpu_to_le16 (MSDOS_I (dir)->i_logstart); - de[0 ].starthi =cpu_to_le16 (MSDOS_I (dir)->i_logstart>>16 ); + de[0 ].starthi =cpu_to_le16 (MSDOS_I (dir)->i_logstart >>16 ); de[1 ].start =cpu_to_le16 (MSDOS_I (parent)->i_logstart); - de[1 ].starthi =cpu_to_le16 (MSDOS_I (parent)->i_logstart>>16 ); + de[1 ].starthi =cpu_to_le16 (MSDOS_I (parent)->i_logstart >>16 );mark_buffer_dirty (bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (bh);brelse (bh); + dir->i_atime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ;mark_inode_dirty (dir); +if (IS_SYNC (dir)) +fat_sync_inode (dir);return 0 ; }
fs/fat/file.c renamed from fs/fat/file.c~sync03-fat_sync00 +5 -0
@@ -23,6 +23,9 @@ static ssize_t fat_file_aio_write(struct inode->i_mtime = inode->i_ctime =CURRENT_TIME_SEC ;MSDOS_I (inode)->i_attrs |=ATTR_ARCH ;mark_inode_dirty (inode); +// check the locking rules +// if (IS_SYNC(inode)) +// fat_sync_inode(inode); }return retval; }
@@ -288,6 +291,8 @@ void fat_truncate(struct inode *inode)unlock_kernel (); inode->i_ctime = inode->i_mtime =CURRENT_TIME_SEC ;mark_inode_dirty (inode); +if (IS_SYNC (inode)) +fat_sync_inode (inode); }struct inode_operations fat_file_inode_operations = {
fs/fat/inode.c renamed from fs/fat/inode.c~sync03-fat_sync00 +10 -0
@@ -501,11 +501,21 @@ retry: }spin_unlock (&sbi->inode_hash_lock);mark_buffer_dirty (bh); +if (wait) +sync_dirty_buffer (bh);brelse (bh);unlock_kernel (); +return 0 ; } +int fat_sync_inode (struct inode *inode) +{ +return fat_write_inode (inode,1 ); +} + +EXPORT_SYMBOL (fat_sync_inode); +static int fat_show_options (struct seq_file *m,struct vfsmount *mnt);static struct super_operations fat_sops = { .alloc_inode = fat_alloc_inode,
fs/fat/misc.c renamed from fs/fat/misc.c~sync03-fat_sync00 +2 -0
@@ -75,6 +75,8 @@ void fat_clusters_flush(struct super_bloif (sbi->prev_free !=-1 ) fsinfo->next_cluster =cpu_to_le32 (sbi->prev_free);mark_buffer_dirty (bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (bh); }brelse (bh); }
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync03-fat_sync00 +24 -7
@@ -663,6 +663,7 @@ static int vfat_add_entry(struct inode * int is_dir, struct vfat_slot_info *sinfo_out, struct buffer_head **bh, struct msdos_dir_entry **de) { + struct super_block *sb = dir->i_sb;struct msdos_dir_slot *dir_slots;loff_t offset;int res, slots, slot;
@@ -702,6 +703,8 @@ static int vfat_add_entry(struct inode * }memcpy (*de, dir_slots + slot,sizeof (struct msdos_dir_slot ));mark_buffer_dirty (*bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (*bh); } res =0 ;
@@ -713,8 +716,9 @@ static int vfat_add_entry(struct inode * dir->i_mtime.tv_nsec =0 ; (*de)->ctime = (*de)->time; (*de)->adate = (*de)->cdate = (*de)->date; -mark_buffer_dirty (*bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (*bh);/* slots can't be less than 1 */ sinfo_out->long_slots = slots -1 ;
@@ -820,9 +824,12 @@ static int vfat_create(struct inode *dirif (!inode) goto out; res =0 ; + inode->i_version++; inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ;mark_inode_dirty (inode); - inode->i_version++; +if (IS_SYNC (inode)) +fat_sync_inode (inode); + dir->i_version++; dentry->d_time = dentry->d_parent->d_inode->i_version;d_instantiate (dentry, inode);
@@ -835,15 +842,20 @@ static void vfat_remove_entry(struct inostruct buffer_head *bh, struct msdos_dir_entry *de) { + struct super_block *sb = dir->i_sb;loff_t offset, i_pos;int i; -/* remove the shortname */ dir->i_mtime = dir->i_atime =CURRENT_TIME_SEC ; dir->i_version++;mark_inode_dirty (dir); + +/* remove the shortname */ de->name[0 ] =DELETED_FLAG ;mark_buffer_dirty (bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (bh); +/* remove the longname */ offset = sinfo->longname_offset; de =NULL ;
@@ -853,6 +865,8 @@ static void vfat_remove_entry(struct ino de->name[0 ] =DELETED_FLAG ; de->attr =ATTR_NONE ;mark_buffer_dirty (bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (bh); }brelse (bh); }
@@ -879,7 +893,7 @@ static int vfat_rmdir(struct inode *dir, inode->i_mtime = inode->i_atime =CURRENT_TIME_SEC ;fat_detach (inode);mark_inode_dirty (inode); -/* releases bh */ +/* releases bh and syncs it if necessary */ vfat_remove_entry (dir, &sinfo, bh, de); dir->i_nlink--; out:
@@ -903,7 +917,7 @@ static int vfat_unlink(struct inode *dir inode->i_mtime = inode->i_atime =CURRENT_TIME_SEC ;fat_detach (inode);mark_inode_dirty (inode); -/* releases bh */ +/* releases bh and syncs it if necessary */ vfat_remove_entry (dir, &sinfo, bh, de); out:unlock_kernel ();
@@ -949,7 +963,7 @@ mkdir_failed: inode->i_mtime = inode->i_atime =CURRENT_TIME_SEC ;fat_detach (inode);mark_inode_dirty (inode); -/* releases bh */ +/* releases bh ands syncs if necessary */ vfat_remove_entry (dir, &sinfo, bh, de);iput (inode); dir->i_nlink--;
@@ -1027,8 +1041,11 @@ static int vfat_rename(struct inode *oldif (is_dir) {int start =MSDOS_I (new_dir)->i_logstart; dotdot_de->start =cpu_to_le16 (start); - dotdot_de->starthi =cpu_to_le16 (start>>16 ); + dotdot_de->starthi =cpu_to_le16 (start >>16 );mark_buffer_dirty (dotdot_bh); +if (new_dir->i_sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (dotdot_bh); + old_dir->i_nlink--;if (new_inode) { new_inode->i_nlink--;
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync03-fat_sync00 +1 -0
@@ -349,6 +349,7 @@ extern void fat_detach(struct inode *inoextern struct inode *fat_iget (struct super_block *sb,loff_t i_pos);extern struct inode *fat_build_inode (struct super_block *sb,struct msdos_dir_entry *de,loff_t i_pos,int *res); +extern int fat_sync_inode (struct inode *inode);int fat_fill_super (struct super_block *sb,void *data,int silent,struct inode_operations *fs_dir_inode_ops,int isvfat);
_
Re: [PATCH 4/29] let fat handle MS_SYNCHRONOUS flag
fs/fat/cache.c static int __fat_access(struct super_blo · line 277
Quoted 3 lines
fs/fat/cache.c renamed from fs/fat/cache.c~sync03-fat_sync00 +2
-0mark_buffer_dirty (bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (bh);
These three lines are duplicated a lot. I think you want a helper ala:
static inline void fat_buffer_modified(struct super_block *sb,
struct buffer_head *bh)
{
mark_buffer_dirty(bh);
if (sb->s_flags & MS_SYNCHRONOUS)
sync_dirty_buffer(bh);
}OGAWA Hirofumi
maintainerRe: [PATCH 4/29] let fat handle MS_SYNCHRONOUS flag
Quoted 6 lines · Christoph Hellwig
fs/fat/cache.c static int __fat_access(struct super_blo · line 277
Quoted 3 lines
fs/fat/cache.c renamed from fs/fat/cache.c~sync03-fat_sync00 +2
-0mark_buffer_dirty (bh); +if (sb->s_flags &MS_SYNCHRONOUS ) +sync_dirty_buffer (bh);These three lines are duplicated a lot. I think you want a helper ala:
Quoted 7 lines
static inline void fat_buffer_modified(struct
super_block*sb,
structbuffer_head*bh){ mark_buffer_dirty(bh); if (sb->s_flags & MS_SYNCHRONOUS) sync_dirty_buffer(bh); }
Yes, I may want the following helper. However I'll put it as is for now.
static inline void fat_buffer_modified(struct super_block *sb,
struct buffer_head *bh, int wait)
{
int err = 0;
mark_buffer_dirty(bh);
if (wait)
err = sync_dirty_buffer(bh);
return err;
}Signature · 1 line
OGAWA Hirofumi <[email protected]>
OGAWA Hirofumi
maintainerPATCH 5/29 FAT: Rewrite the FAT (File Allocation Table) access stuff
In reply to OGAWA HirofumiIn order not to write the same block repeatedly, rewrite the FAT entry access stuff.
And this separates the "allocate the cluster" and "link to cluster chain" operations for expanding the file/dir safely. (fat_alloc_clusters() allocates the cluster, and fat_chain_add() links allocated cluster to the chain which inode has.)
---
fs/fat/Makefile | 2 fs/fat/cache.c | 145 +---------- fs/fat/dir.c | 15 - fs/fat/fatent.c | 590 +++++++++++++++++++++++++++++++++++++++++++++++ fs/fat/file.c | 69 ++--- fs/fat/inode.c | 60 ++-- fs/fat/misc.c | 122 ++++----- include/linux/msdos_fs.h | 57 +++- 8 files changed, 781 insertions(+), 279 deletions(-)
fs/fat/Makefile renamed from fs/fat/Makefile~sync05-fat_dep-fatent +1 -1
@@ -4,4 +4,4 @@ obj-$(CONFIG_FAT_FS) += fat.o -fat-objs := cache.o dir.o file.o inode.o misc.o +fat-objs := cache.o dir.o fatent.o file.o inode.o misc.o
fs/fat/cache.c renamed from fs/fat/cache.c~sync05-fat_dep-fatent +13 -132
185 lines not on this page · raw message
fs/fat/dir.c renamed from fs/fat/dir.c~sync05-fat_dep-fatent +10 -5
@@ -759,7 +759,7 @@ static struct buffer_head *fat_extend_di {struct super_block *sb = inode->i_sb;struct buffer_head *bh, *res =NULL ; -int nr, sec_per_clus =MSDOS_SB (sb)->sec_per_clus; +int err, cluster, sec_per_clus =MSDOS_SB (sb)->sec_per_clus;sector_t sector, last_sector;if (MSDOS_SB (sb)->fat_bits !=32 ) {
@@ -767,11 +767,16 @@ static struct buffer_head *fat_extend_direturn ERR_PTR (-ENOSPC ); } - nr =fat_add_cluster (inode); -if (nr <0 ) -return ERR_PTR (nr); + err =fat_alloc_clusters (inode, &cluster,1 ); +if (err) +return ERR_PTR (err); + err =fat_chain_add (inode, cluster,1 ); +if (err) { +fat_free_clusters (inode, cluster); +return ERR_PTR (err); + } - sector =fat_clus_to_blknr (MSDOS_SB (sb), nr); + sector =fat_clus_to_blknr (MSDOS_SB (sb), cluster); last_sector = sector + sec_per_clus;for ( ; sector < last_sector; sector++) {if ((bh =sb_getblk (sb, sector))) {
fs/fat/fatent.c new file +590 -0
590 lines not on this page · raw message
fs/fat/file.c renamed from fs/fat/file.c~sync05-fat_dep-fatent +35 -34
97 lines not on this page · raw message
fs/fat/inode.c renamed from fs/fat/inode.c~sync05-fat_dep-fatent +29 -31
96 lines not on this page · raw message
fs/fat/misc.c renamed from fs/fat/misc.c~sync05-fat_dep-fatent +56 -66
167 lines not on this page · raw message
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync05-fat_dep-fatent +47 -10
102 lines not on this page · raw message
_
OGAWA Hirofumi
maintainerPATCH 6/29 FAT: add debugging code to fatent.c
---
fs/fat/fatent.c | 20 ++++++++++++++++++++ include/linux/msdos_fs.h | 6 ++++++ 2 files changed, 26 insertions(+)
fs/fat/fatent.c renamed from fs/fat/fatent.c~sync05-fat_dep-fatent-debug +20 -0
@@ -21,6 +21,7 @@ static void fat12_ent_blocknr(struct sup {struct msdos_sb_info *sbi =MSDOS_SB (sb);int bytes = entry + (entry >>1 ); +WARN_ON (entry <FAT_START_ENT || sbi->max_cluster <= entry); *offset = bytes & (sb->s_blocksize -1 ); *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits); }
@@ -30,6 +31,7 @@ static void fat_ent_blocknr(struct super {struct msdos_sb_info *sbi =MSDOS_SB (sb);int bytes = (entry << sbi->fatent_shift); +WARN_ON (entry <FAT_START_ENT || sbi->max_cluster <= entry); *offset = bytes & (sb->s_blocksize -1 ); *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits); }
@@ -38,9 +40,11 @@ static void fat12_ent_set_ptr(struct fat {struct buffer_head **bhs = fatent->bhs;if (fatent->nr_bhs ==1 ) { +WARN_ON (offset >= (bhs[0 ]->b_size -1 )); fatent->u.ent12_p[0 ] = bhs[0 ]->b_data + offset; fatent->u.ent12_p[1 ] = bhs[0 ]->b_data + (offset +1 ); }else { +WARN_ON (offset != (bhs[0 ]->b_size -1 )); fatent->u.ent12_p[0 ] = bhs[0 ]->b_data + offset; fatent->u.ent12_p[1 ] = bhs[1 ]->b_data; }
@@ -48,11 +52,13 @@ static void fat12_ent_set_ptr(struct fatstatic void fat16_ent_set_ptr (struct fat_entry *fatent,int offset) { +WARN_ON (offset & (2 -1 )); fatent->u.ent16_p = (__le16 *)(fatent->bhs[0 ]->b_data + offset); }static void fat32_ent_set_ptr (struct fat_entry *fatent,int offset) { +WARN_ON (offset & (4 -1 )); fatent->u.ent32_p = (__le32 *)(fatent->bhs[0 ]->b_data + offset); }
@@ -61,6 +67,7 @@ static int fat12_ent_bread(struct super_ {struct buffer_head **bhs = fatent->bhs; +WARN_ON (blocknr <MSDOS_SB (sb)->fat_start); bhs[0 ] =sb_bread (sb, blocknr);if (!bhs[0 ]) goto err;
@@ -91,6 +98,7 @@ static int fat_ent_bread(struct super_bl {struct fatent_operations *ops =MSDOS_SB (sb)->fatent_ops; +WARN_ON (blocknr <MSDOS_SB (sb)->fat_start); fatent->bhs[0 ] =sb_bread (sb, blocknr);if (!fatent->bhs[0 ]) { printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
@@ -120,6 +128,7 @@ static int fat12_ent_get(struct fat_entrstatic int fat16_ent_get (struct fat_entry *fatent) {int next =le16_to_cpu (*fatent->u.ent16_p); +WARN_ON ((unsigned long )fatent->u.ent16_p & (2 -1 ));if (next >=BAD_FAT16 ) next =FAT_ENT_EOF ;return next;
@@ -128,6 +137,7 @@ static int fat16_ent_get(struct fat_entrstatic int fat32_ent_get (struct fat_entry *fatent) {int next =le32_to_cpu (*fatent->u.ent32_p) &0x0fffffff ; +WARN_ON ((unsigned long )fatent->u.ent32_p & (4 -1 ));if (next >=BAD_FAT32 ) next =FAT_ENT_EOF ;return next;
@@ -167,6 +177,7 @@ static void fat32_ent_put(struct fat_entif (new ==FAT_ENT_EOF ) new =EOF_FAT32 ; +WARN_ON (new &0xf0000000 ); new |=le32_to_cpu (*fatent->u.ent32_p) & ~0x0fffffff ; *fatent->u.ent32_p =cpu_to_le32 (new);mark_buffer_dirty (fatent->bhs[0 ]);
@@ -180,12 +191,16 @@ static int fat12_ent_next(struct fat_ent fatent->entry++;if (fatent->nr_bhs ==1 ) { +WARN_ON (ent12_p[0 ] > (u8 *)(bhs[0 ]->b_data + (bhs[0 ]->b_size -2 ))); +WARN_ON (ent12_p[1 ] > (u8 *)(bhs[0 ]->b_data + (bhs[0 ]->b_size -1 )));if (nextp < (u8 *)(bhs[0 ]->b_data + (bhs[0 ]->b_size -1 ))) { ent12_p[0 ] = nextp -1 ; ent12_p[1 ] = nextp;return 1 ; } }else { +WARN_ON (ent12_p[0 ] != (u8 *)(bhs[0 ]->b_data + (bhs[0 ]->b_size -1 ))); +WARN_ON (ent12_p[1 ] != (u8 *)bhs[1 ]->b_data); ent12_p[0 ] = nextp -1 ; ent12_p[1 ] = nextp;brelse (bhs[0 ]);
@@ -193,6 +208,8 @@ static int fat12_ent_next(struct fat_ent fatent->nr_bhs =1 ;return 1 ; } + ent12_p[0 ] =NULL ; + ent12_p[1 ] =NULL ;return 0 ; }
@@ -204,6 +221,7 @@ static int fat16_ent_next(struct fat_ent fatent->u.ent16_p++;return 1 ; } + fatent->u.ent16_p =NULL ;return 0 ; }
@@ -215,6 +233,7 @@ static int fat32_ent_next(struct fat_ent fatent->u.ent32_p++;return 1 ; } + fatent->u.ent32_p =NULL ;return 0 ; }
@@ -323,6 +342,7 @@ int fat_ent_read(struct inode *inode, streturn ops->ent_get (fatent); } +/* FIXME: We can write the blocks as more big chunk. */ static int fat_mirror_bhs (struct super_block *sb,struct buffer_head **bhs,int nr_bhs) {
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync05-fat_dep-fatent-debug +6 -0
@@ -348,19 +348,25 @@ struct fat_entry {static inline void fatent_init (struct fat_entry *fatent) { fatent->nr_bhs =0 ; + fatent->entry =0 ; + fatent->u.ent32_p =NULL ; + fatent->bhs[0 ] = fatent->bhs[1 ] =NULL ; }static inline void fatent_set_entry (struct fat_entry *fatent,int entry) { fatent->entry = entry; + fatent->u.ent32_p =NULL ; }static inline void fatent_brelse (struct fat_entry *fatent) {int i; + fatent->u.ent32_p =NULL ;for (i =0 ; i < fatent->nr_bhs; i++)brelse (fatent->bhs[i]); fatent->nr_bhs =0 ; + fatent->bhs[0 ] = fatent->bhs[1 ] =NULL ; }extern void fat_ent_access_init (struct super_block *sb);
_
OGAWA Hirofumi
maintainerPATCH 7/29 FAT: Use "unsigned int" for ->free_clusters and ->prev_free
This changes ->free_clusters and ->prev_free from "int" to "unsigned int". These value should be never negative value (but it's using 0xffffffff(-1) as undefined state).
With this changes, fatfs would handle the corruption of free_clusters more proper.
---
fs/fat/fatent.c | 3 +-- fs/fat/inode.c | 6 +++++- include/linux/msdos_fs.h | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-)
fs/fat/fatent.c renamed from fs/fat/fatent.c~sync05-fat_free-unsigned +1 -2
@@ -453,8 +453,7 @@ int fat_alloc_clusters(struct inode *inofatent_init (&fatent);fatent_set_entry (&fatent, sbi->prev_free +1 );while (count < sbi->max_cluster) { - fatent.entry %= sbi->max_cluster; -if (fatent.entry <FAT_START_ENT ) +if (fatent.entry >= sbi->max_cluster) fatent.entry =FAT_START_ENT ;fatent_set_entry (&fatent, fatent.entry); err =fat_ent_read_block (sb, &fatent);
fs/fat/inode.c renamed from fs/fat/inode.c~sync05-fat_free-unsigned +5 -1
@@ -1163,7 +1163,7 @@ int fat_fill_super(struct super_block *s sbi->fat_length =le16_to_cpu (b->fat_length); sbi->root_cluster =0 ; sbi->free_clusters =-1 ;/* Don't know yet */ - sbi->prev_free =-1 ; + sbi->prev_free =FAT_START_ENT ;if (!sbi->fat_length && b->fat32_length) {struct fat_boot_fsinfo *fsinfo;
@@ -1247,6 +1247,10 @@ int fat_fill_super(struct super_block *s/* check the free_clusters, it's not necessarily correct */ if (sbi->free_clusters !=-1 && sbi->free_clusters > total_clusters) sbi->free_clusters =-1 ; +/* check the prev_free, it's not necessarily correct */ + sbi->prev_free %= sbi->max_cluster; +if (sbi->prev_free <FAT_START_ENT ) + sbi->prev_free =FAT_START_ENT ;brelse (bh);
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync05-fat_free-unsigned +2 -2
@@ -225,8 +225,8 @@ struct msdos_sb_info {unsigned long root_cluster;/* first cluster of the root directory */ unsigned long fsinfo_sector;/* sector number of FAT32 fsinfo */ struct semaphore fat_lock; -int prev_free;/* previously allocated cluster number */ -int free_clusters;/* -1 if undefined */ +unsigned int prev_free;/* previously allocated cluster number */ +unsigned int free_clusters;/* -1 if undefined */ struct fat_mount_options options;struct nls_table *nls_disk;/* Codepage used on disk */ struct nls_table *nls_io;/* Charset used for input and display */
_
OGAWA Hirofumi
maintainerPATCH 8/29 FAT: "struct vfat_slot_info" cleanup
Add "struct fat_slot_info" for updating data of the directory entries.
1) Rename "struct vfat_slot_info" to "struct fat_slot_info"
2) Add "de" and "bh" to fat_slot_info instead of using argument.
3) Replace the "vfat_slot_info + de + bh" by new fat_slot_info
---
fs/vfat/namei.c | 126 ++++++++++++++++++++--------------------------- include/linux/msdos_fs.h | 8 +- 2 files changed, 61 insertions(+), 73 deletions(-)
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync06-fat_dir-cleanup +56 -70
@@ -660,16 +660,15 @@ out_free: }static int vfat_add_entry (struct inode *dir,struct qstr *qname, -int is_dir,struct vfat_slot_info *sinfo_out, -struct buffer_head **bh,struct msdos_dir_entry **de) +int is_dir,struct fat_slot_info *sinfo) {struct super_block *sb = dir->i_sb;struct msdos_dir_slot *dir_slots;loff_t offset;int res, slots, slot;unsigned int len; -struct msdos_dir_entry *dummy_de; -struct buffer_head *dummy_bh; +struct msdos_dir_entry *de, *dummy_de; +struct buffer_head *bh, *dummy_bh;loff_t dummy_i_pos; len =vfat_striptail_len (qname);
@@ -695,16 +694,16 @@ static int vfat_add_entry(struct inode *brelse (dummy_bh);/* Now create the new entry */ - *bh =NULL ; + bh =NULL ;for (slot =0 ; slot < slots; slot++) { -if (fat_get_entry (dir, &offset, bh, de, &sinfo_out->i_pos) <0 ) { +if (fat_get_entry (dir, &offset, &bh, &de, &sinfo->i_pos) <0 ) { res = -EIO ; goto cleanup; } -memcpy (*de, dir_slots + slot,sizeof (struct msdos_dir_slot )); -mark_buffer_dirty (*bh); +memcpy (de, dir_slots + slot,sizeof (struct msdos_dir_slot )); +mark_buffer_dirty (bh);if (sb->s_flags &MS_SYNCHRONOUS ) -sync_dirty_buffer (*bh); +sync_dirty_buffer (bh); } res =0 ;
@@ -712,18 +711,19 @@ static int vfat_add_entry(struct inode * dir->i_ctime = dir->i_mtime = dir->i_atime =CURRENT_TIME_SEC ;mark_inode_dirty (dir); -fat_date_unix2dos (dir->i_mtime.tv_sec, &(*de)->time, &(*de)->date); +fat_date_unix2dos (dir->i_mtime.tv_sec, &de->time, &de->date); dir->i_mtime.tv_nsec =0 ; - (*de)->ctime = (*de)->time; - (*de)->adate = (*de)->cdate = (*de)->date; -mark_buffer_dirty (*bh); + de->ctime = de->time; + de->adate = de->cdate = de->date; +mark_buffer_dirty (bh);if (sb->s_flags &MS_SYNCHRONOUS ) -sync_dirty_buffer (*bh); +sync_dirty_buffer (bh);/* slots can't be less than 1 */ - sinfo_out->long_slots = slots -1 ; - sinfo_out->longname_offset = - offset -sizeof (struct msdos_dir_slot ) * slots; + sinfo->slot_off = offset -sizeof (struct msdos_dir_slot ) * slots; + sinfo->nr_slots = slots -1 ; + sinfo->de = de; + sinfo->bh = bh; cleanup:kfree (dir_slots);
@@ -731,8 +731,7 @@ cleanup: }static int vfat_find (struct inode *dir,struct qstr *qname, -struct vfat_slot_info *sinfo,struct buffer_head **last_bh, -struct msdos_dir_entry **last_de) +struct fat_slot_info *sinfo) {struct super_block *sb = dir->i_sb;loff_t offset;
@@ -745,10 +744,10 @@ static int vfat_find(struct inode *dir, res =fat_search_long (dir, qname->name, len, (MSDOS_SB (sb)->options.name_check !='s' ), - &offset, &sinfo->longname_offset); + &offset, &sinfo->slot_off);if (res >0 ) { - sinfo->long_slots = res -1 ; -if (fat_get_entry (dir, &offset, last_bh, last_de, &sinfo->i_pos) >=0 ) + sinfo->nr_slots = res -1 ; +if (fat_get_entry (dir, &offset, &sinfo->bh, &sinfo->de, &sinfo->i_pos) >=0 )return 0 ; res = -EIO ; }
@@ -759,11 +758,9 @@ static struct dentry *vfat_lookup(struct struct nameidata *nd) {int res; -struct vfat_slot_info sinfo; +struct fat_slot_info sinfo;struct inode *inode;struct dentry *alias; -struct buffer_head *bh =NULL ; -struct msdos_dir_entry *de;int table;lock_kernel ();
@@ -771,13 +768,13 @@ static struct dentry *vfat_lookup(struct dentry->d_op = &vfat_dentry_ops[table]; inode =NULL ; - res =vfat_find (dir, &dentry->d_name, &sinfo, &bh, &de); + res =vfat_find (dir, &dentry->d_name, &sinfo);if (res <0 ) { table++; goto error; } - inode =fat_build_inode (dir->i_sb, de, sinfo.i_pos, &res); -brelse (bh); + inode =fat_build_inode (dir->i_sb, sinfo.de, sinfo.i_pos, &res); +brelse (sinfo.bh);if (res) {unlock_kernel ();return ERR_PTR (res);
@@ -810,17 +807,15 @@ static int vfat_create(struct inode *dir {struct super_block *sb = dir->i_sb;struct inode *inode =NULL ; -struct buffer_head *bh =NULL ; -struct msdos_dir_entry *de; -struct vfat_slot_info sinfo; +struct fat_slot_info sinfo;int res;lock_kernel (); - res =vfat_add_entry (dir, &dentry->d_name,0 , &sinfo, &bh, &de); + res =vfat_add_entry (dir, &dentry->d_name,0 , &sinfo);if (res <0 ) goto out; - inode =fat_build_inode (sb, de, sinfo.i_pos, &res); -brelse (bh); + inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos, &res); +brelse (sinfo.bh);if (!inode) goto out; res =0 ;
@@ -838,11 +833,11 @@ out:return res; } -static void vfat_remove_entry (struct inode *dir,struct vfat_slot_info *sinfo, -struct buffer_head *bh, -struct msdos_dir_entry *de) +static void vfat_remove_entry (struct inode *dir,struct fat_slot_info *sinfo) {struct super_block *sb = dir->i_sb; +struct msdos_dir_entry *de = sinfo->de; +struct buffer_head *bh = sinfo->bh;loff_t offset, i_pos;int i;
@@ -857,9 +852,9 @@ static void vfat_remove_entry(struct inosync_dirty_buffer (bh);/* remove the longname */ - offset = sinfo->longname_offset; + offset = sinfo->slot_off; de =NULL ; -for (i = sinfo->long_slots; i >0 ; --i) { +for (i = sinfo->nr_slots; i >0 ; --i) {if (fat_get_entry (dir, &offset, &bh, &de, &i_pos) <0 )continue ; de->name[0 ] =DELETED_FLAG ;
@@ -874,9 +869,7 @@ static void vfat_remove_entry(struct inostatic int vfat_rmdir (struct inode *dir,struct dentry *dentry) {struct inode *inode = dentry->d_inode; -struct vfat_slot_info sinfo; -struct buffer_head *bh =NULL ; -struct msdos_dir_entry *de; +struct fat_slot_info sinfo;int res;lock_kernel ();
@@ -884,7 +877,7 @@ static int vfat_rmdir(struct inode *dir,if (res) goto out; - res =vfat_find (dir, &dentry->d_name, &sinfo, &bh, &de); + res =vfat_find (dir, &dentry->d_name, &sinfo);if (res <0 ) goto out;
@@ -894,7 +887,7 @@ static int vfat_rmdir(struct inode *dir,fat_detach (inode);mark_inode_dirty (inode);/* releases bh and syncs it if necessary */ -vfat_remove_entry (dir, &sinfo, bh, de); +vfat_remove_entry (dir, &sinfo); dir->i_nlink--; out:unlock_kernel ();
@@ -904,13 +897,11 @@ out:static int vfat_unlink (struct inode *dir,struct dentry *dentry) {struct inode *inode = dentry->d_inode; -struct vfat_slot_info sinfo; -struct buffer_head *bh =NULL ; -struct msdos_dir_entry *de; +struct fat_slot_info sinfo;int res;lock_kernel (); - res =vfat_find (dir, &dentry->d_name, &sinfo, &bh, &de); + res =vfat_find (dir, &dentry->d_name, &sinfo);if (res <0 ) goto out; inode->i_nlink =0 ;
@@ -918,7 +909,7 @@ static int vfat_unlink(struct inode *dirfat_detach (inode);mark_inode_dirty (inode);/* releases bh and syncs it if necessary */ -vfat_remove_entry (dir, &sinfo, bh, de); +vfat_remove_entry (dir, &sinfo); out:unlock_kernel ();
@@ -929,16 +920,14 @@ static int vfat_mkdir(struct inode *dir, {struct super_block *sb = dir->i_sb;struct inode *inode =NULL ; -struct vfat_slot_info sinfo; -struct buffer_head *bh =NULL ; -struct msdos_dir_entry *de; +struct fat_slot_info sinfo;int res;lock_kernel (); - res =vfat_add_entry (dir, &dentry->d_name,1 , &sinfo, &bh, &de); + res =vfat_add_entry (dir, &dentry->d_name,1 , &sinfo);if (res <0 ) goto out; - inode =fat_build_inode (sb, de, sinfo.i_pos, &res); + inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos, &res);if (!inode) goto out_brelse; inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ;
@@ -953,7 +942,7 @@ static int vfat_mkdir(struct inode *dir, dentry->d_time = dentry->d_parent->d_inode->i_version;d_instantiate (dentry, inode); out_brelse: -brelse (bh); +brelse (sinfo.bh); out:unlock_kernel ();return res;
@@ -964,7 +953,7 @@ mkdir_failed:fat_detach (inode);mark_inode_dirty (inode);/* releases bh ands syncs if necessary */ -vfat_remove_entry (dir, &sinfo, bh, de); +vfat_remove_entry (dir, &sinfo);iput (inode); dir->i_nlink--; goto out;
@@ -973,24 +962,22 @@ mkdir_failed:static int vfat_rename (struct inode *old_dir,struct dentry *old_dentry,struct inode *new_dir,struct dentry *new_dentry) { -struct buffer_head *old_bh, *new_bh, *dotdot_bh; -struct msdos_dir_entry *old_de, *new_de, *dotdot_de; +struct buffer_head *dotdot_bh; +struct msdos_dir_entry *dotdot_de;loff_t dotdot_i_pos;struct inode *old_inode, *new_inode;int res, is_dir; -struct vfat_slot_info old_sinfo, sinfo; +struct fat_slot_info old_sinfo, sinfo; - old_bh = new_bh = dotdot_bh =NULL ; + old_sinfo.bh = sinfo.bh = dotdot_bh =NULL ; old_inode = old_dentry->d_inode; new_inode = new_dentry->d_inode;lock_kernel (); - res =vfat_find (old_dir, &old_dentry->d_name, &old_sinfo, &old_bh, - &old_de); + res =vfat_find (old_dir, &old_dentry->d_name, &old_sinfo);if (res <0 ) goto rename_done; is_dir =S_ISDIR (old_inode->i_mode); -if (is_dir) {if (fat_scan (old_inode,MSDOS_DOTDOT , &dotdot_bh, &dotdot_de, &dotdot_i_pos) <0 ) {
@@ -1000,8 +987,7 @@ static int vfat_rename(struct inode *old }if (new_dentry->d_inode) { - res =vfat_find (new_dir, &new_dentry->d_name, &sinfo, &new_bh, - &new_de); + res =vfat_find (new_dir, &new_dentry->d_name, &sinfo);if (res <0 ||MSDOS_I (new_inode)->i_pos != sinfo.i_pos) {/* WTF??? Cry and fail. */ printk (KERN_WARNING "vfat_rename: fs corrupted\n" );
@@ -1016,7 +1002,7 @@ static int vfat_rename(struct inode *oldfat_detach (new_inode); }else { res =vfat_add_entry (new_dir, &new_dentry->d_name, is_dir, - &sinfo, &new_bh, &new_de); + &sinfo);if (res <0 ) goto rename_done; }
@@ -1024,8 +1010,8 @@ static int vfat_rename(struct inode *old new_dir->i_version++;/* releases old_bh */ -vfat_remove_entry (old_dir, &old_sinfo, old_bh, old_de); - old_bh =NULL ; +vfat_remove_entry (old_dir, &old_sinfo); + old_sinfo.bh =NULL ;fat_detach (old_inode);fat_attach (old_inode, sinfo.i_pos);mark_inode_dirty (old_inode);
@@ -1057,8 +1043,8 @@ static int vfat_rename(struct inode *old rename_done:brelse (dotdot_bh); -brelse (old_bh); -brelse (new_bh); +brelse (old_sinfo.bh); +brelse (sinfo.bh);unlock_kernel ();return res; }
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync06-fat_dir-cleanup +5 -3
@@ -170,10 +170,12 @@ struct msdos_dir_slot {__u8 name11_12[4 ];/* last 2 characters in name */ }; -struct vfat_slot_info { -int long_slots;/* number of long slots in filename */ -loff_t longname_offset;/* dir offset for longname start */ +struct fat_slot_info {loff_t i_pos;/* on-disk position of directory entry */ +loff_t slot_off;/* offset for slot or de start */ +int nr_slots;/* number of slots + 1(de) in filename */ +struct msdos_dir_entry *de; +struct buffer_head *bh; };#ifdef __KERNEL__
_
OGAWA Hirofumi
maintainerPATCH 9/29 FAT: Use "struct fat_slot_info" for fat_search_long()
The fat_search_long() provide the "struct fat_slot_info" by this change. So, vfat_find() became to be enough simple, and it just returns 0 or error.
And the error check of vfat_find() is also simplify.
---
fs/fat/dir.c | 26 +++++++------ fs/vfat/namei.c | 89 ++++++++++++++++++++--------------------------- include/linux/msdos_fs.h | 3 - 3 files changed, 54 insertions(+), 64 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~sync06-fat_dir-cleanup2 +15 -11
@@ -136,7 +136,7 @@ fat_shortname2uni(struct nls_table *nls,* value is the total amount of slots, including the shortname entry. */ int fat_search_long (struct inode *inode,const unsigned char *name, -int name_len,int anycase,loff_t *spos,loff_t *lpos) +int name_len,struct fat_slot_info *sinfo) {struct super_block *sb = inode->i_sb;struct buffer_head *bh =NULL ;
@@ -149,12 +149,14 @@ int fat_search_long(struct inode *inode,unsigned char work[8 ], bufname[260 ];/* 256 + 4 */ int uni_xlate =MSDOS_SB (sb)->options.unicode_xlate;int utf8 =MSDOS_SB (sb)->options.utf8; +int anycase = (MSDOS_SB (sb)->options.name_check !='s' );unsigned short opt_shortname =MSDOS_SB (sb)->options.shortname; -int chl, i, j, last_u, res =0 ; +int chl, i, j, last_u, err;loff_t i_pos, cpos =0 ; + err = -ENOENT ;while (1 ) { -if (fat_get_entry (inode,&cpos,&bh,&de,&i_pos) ==-1 ) +if (fat_get_entry (inode, &cpos, &bh, &de, &i_pos) ==-1 ) goto EODir; parse_record: long_slots =0 ;
@@ -288,15 +290,17 @@ parse_long: } Found: - res = long_slots +1 ; - *spos = cpos -sizeof (struct msdos_dir_entry ); - *lpos = cpos - res*sizeof (struct msdos_dir_entry ); + sinfo->i_pos = i_pos; + sinfo->slot_off = cpos - (long_slots +1 ) *sizeof (*de); + sinfo->nr_slots = long_slots; + sinfo->de = de; + sinfo->bh = bh; + err =0 ; EODir: -brelse (bh); -if (unicode) { -free_page ((unsigned long ) unicode); - } -return res; +if (unicode) +free_page ((unsigned long )unicode); + +return err; }EXPORT_SYMBOL (fat_search_long);
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync06-fat_dir-cleanup2 +38 -51
193 lines not on this page · raw message
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync06-fat_dir-cleanup2 +1 -2
@@ -323,8 +323,7 @@ extern int fat_bmap(struct inode *inode,/* fat/dir.c */ extern struct file_operations fat_dir_operations;extern int fat_search_long (struct inode *inode,const unsigned char *name, -int name_len,int anycase, -loff_t *spos,loff_t *lpos); +int name_len,struct fat_slot_info *sinfo);extern int fat_add_entries (struct inode *dir,int slots,struct buffer_head **bh,struct msdos_dir_entry **de,loff_t *i_pos);
_
OGAWA Hirofumi
maintainerPATCH 10/29 FAT: Add fat_remove_entries()
This changes the fat_slot_info->nr_slot, now it's total counts which include a shortname entry. And this adds a fat_remove_entries() which use the ->nr_slots.
In order not to write out the same block repeatedly, fat_remove_entries() was rewritten from vfat_remove_entries().
---
fs/fat/dir.c | 103 +++++++++++++++++++++++++++++++++++++++++++---- fs/vfat/namei.c | 81 ++++++++++++------------------------ include/linux/msdos_fs.h | 1 3 files changed, 124 insertions(+), 61 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~sync06-fat_dir-cleanup3 +96 -7
@@ -144,7 +144,7 @@ int fat_search_long(struct inode *inode,struct nls_table *nls_io =MSDOS_SB (sb)->nls_io;struct nls_table *nls_disk =MSDOS_SB (sb)->nls_disk;wchar_t bufuname[14 ]; -unsigned char xlate_len, long_slots; +unsigned char xlate_len, nr_slots;wchar_t *unicode =NULL ;unsigned char work[8 ], bufname[260 ];/* 256 + 4 */ int uni_xlate =MSDOS_SB (sb)->options.unicode_xlate;
@@ -159,7 +159,7 @@ int fat_search_long(struct inode *inode,if (fat_get_entry (inode, &cpos, &bh, &de, &i_pos) ==-1 ) goto EODir; parse_record: - long_slots =0 ; + nr_slots =0 ;if (de->name[0 ] ==DELETED_FLAG )continue ;if (de->attr !=ATTR_EXT && (de->attr &ATTR_VOLUME ))
@@ -191,7 +191,7 @@ parse_long: slots = id & ~0x40 ;if (slots >20 || !slots)/* ceil(256 * 2 / 26) */ continue ; - long_slots = slots; + nr_slots = slots; alias_checksum = ds->alias_checksum; slot = slots;
@@ -228,7 +228,7 @@ parse_long:for (sum =0 , i =0 ; i <11 ; i++) sum = (((sum&1 )<<7 )|((sum&0xfe )>>1 )) + de->name[i];if (sum != alias_checksum) - long_slots =0 ; + nr_slots =0 ; }memcpy (work, de->name,sizeof (de->name));
@@ -276,7 +276,7 @@ parse_long: xlate_len))) goto Found; -if (long_slots) { +if (nr_slots) { xlate_len = utf8 ?utf8_wcstombs (bufname, unicode,sizeof (bufname)) :uni16_to_x8 (bufname, unicode, uni_xlate, nls_io);
@@ -290,9 +290,10 @@ parse_long: } Found: + nr_slots++;/* include the de */ sinfo->i_pos = i_pos; - sinfo->slot_off = cpos - (long_slots +1 ) *sizeof (*de); - sinfo->nr_slots = long_slots; + sinfo->slot_off = cpos - nr_slots *sizeof (*de); + sinfo->nr_slots = nr_slots; sinfo->de = de; sinfo->bh = bh; err =0 ;
@@ -759,6 +760,94 @@ int fat_scan(struct inode *dir, const unEXPORT_SYMBOL (fat_scan); +static int __fat_remove_entries (struct inode *dir,loff_t pos,int nr_slots) +{ +struct super_block *sb = dir->i_sb; +struct buffer_head *bh; +struct msdos_dir_entry *de, *endp; +loff_t i_pos; +int err =0 , orig_slots; + +while (nr_slots) { + bh =NULL ; +if (fat_get_entry (dir, &pos, &bh, &de, &i_pos) <0 ) { + err = -EIO ; +break ; + } + + orig_slots = nr_slots; + endp = (struct msdos_dir_entry *)(bh->b_data + sb->s_blocksize); +while (nr_slots && de < endp) { + de->name[0 ] =DELETED_FLAG ; + de++; + nr_slots--; + } +mark_buffer_dirty (bh); +if (IS_DIRSYNC (dir)) + err =sync_dirty_buffer (bh); +brelse (bh); +if (err) +break ; + +/* pos is *next* de's position, so this does `- sizeof(de)' */ + pos += ((orig_slots - nr_slots) *sizeof (*de)) -sizeof (*de); + } + +return err; +} + +int fat_remove_entries (struct inode *dir,struct fat_slot_info *sinfo) +{ +struct msdos_dir_entry *de; +struct buffer_head *bh; +int err =0 , nr_slots; + +/* +* First stage: Remove the shortname. By this, the directory +* entry is removed. +*/ + nr_slots = sinfo->nr_slots; + de = sinfo->de; + sinfo->de =NULL ; + bh = sinfo->bh; + sinfo->bh =NULL ; +while (nr_slots && de >= (struct msdos_dir_entry *)bh->b_data) { + de->name[0 ] =DELETED_FLAG ; + de--; + nr_slots--; + } +mark_buffer_dirty (bh); +if (IS_DIRSYNC (dir)) + err =sync_dirty_buffer (bh); +brelse (bh); +if (err) +return err; + dir->i_version++; + +if (nr_slots) { +/* +* Second stage: remove the remaining longname slots. +* (This directory entry is already removed, and so return +* the success) +*/ + err =__fat_remove_entries (dir, sinfo->slot_off, nr_slots); +if (err) { +printk (KERN_WARNING +"FAT: Couldn't remove the long name slots\n" ); + } + } + + dir->i_mtime = dir->i_atime =CURRENT_TIME_SEC ; +if (IS_DIRSYNC (dir)) + (void )fat_sync_inode (dir); +else +mark_inode_dirty (dir); + +return 0 ; +} + +EXPORT_SYMBOL (fat_remove_entries); +static struct buffer_head *fat_extend_dir (struct inode *inode) {struct super_block *sb = inode->i_sb;
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync06-fat_dir-cleanup3 +27 -54
173 lines not on this page · raw message
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync06-fat_dir-cleanup3 +1 -0
@@ -333,6 +333,7 @@ extern int fat_subdirs(struct inode *dirextern int fat_scan (struct inode *dir,const unsigned char *name,struct buffer_head **res_bh,struct msdos_dir_entry **res_de,loff_t *i_pos); +extern int fat_remove_entries (struct inode *dir,struct fat_slot_info *sinfo);/* fat/fatent.c */ struct fat_entry {
_
OGAWA Hirofumi
maintainerPATCH 11/29 FAT: fat_build_inode() cleanup
Just use ERR_PTR() instead of getting the error code by additional argument.
---
fs/fat/inode.c | 62 ++++++++++++++++++++++------------------------- fs/msdos/namei.c | 17 +++++++----- fs/vfat/namei.c | 19 ++++++++------ include/linux/msdos_fs.h | 2 - 4 files changed, 52 insertions(+), 48 deletions(-)
fs/fat/inode.c renamed from fs/fat/inode.c~sync06-fat_dir-cleanup4 +30 -32
@@ -304,23 +304,25 @@ static int fat_fill_inode(struct inode * }struct inode *fat_build_inode (struct super_block *sb, -struct msdos_dir_entry *de,loff_t i_pos,int *res) +struct msdos_dir_entry *de,loff_t i_pos) {struct inode *inode; - *res =0 ; +int err; + inode =fat_iget (sb, i_pos);if (inode) goto out; inode =new_inode (sb); - *res = -ENOMEM ; -if (!inode) +if (!inode) { + inode =ERR_PTR (-ENOMEM ); goto out; + } inode->i_ino =iunique (sb,MSDOS_ROOT_INO ); inode->i_version =1 ; - *res =fat_fill_inode (inode, de); -if (*res <0 ) { + err =fat_fill_inode (inode, de); +if (err) {iput (inode); - inode =NULL ; + inode =ERR_PTR (err); goto out; }fat_attach (inode, i_pos);
@@ -643,39 +645,35 @@ fat_encode_fh(struct dentry *de, __u32 *static struct dentry *fat_get_parent (struct dentry *child) { -struct buffer_head *bh=NULL ; -struct msdos_dir_entry *de =NULL ; -struct dentry *parent =NULL ; -int res; -loff_t i_pos =0 ; +struct buffer_head *bh; +struct msdos_dir_entry *de; +loff_t i_pos; +struct dentry *parent;struct inode *inode; +int err;lock_kernel (); - res =fat_scan (child->d_inode,MSDOS_DOTDOT , &bh, &de, &i_pos); -if (res <0 ) + err =fat_scan (child->d_inode,MSDOS_DOTDOT , &bh, &de, &i_pos); +if (err) { + parent =ERR_PTR (err); goto out; - inode =fat_build_inode (child->d_sb, de, i_pos, &res); -if (res) + } + inode =fat_build_inode (child->d_sb, de, i_pos); +brelse (bh); +if (IS_ERR (inode)) { + parent =ERR_PTR (PTR_ERR (inode)); goto out; -if (!inode) - res = -EACCES ; -else { - parent =d_alloc_anon (inode); -if (!parent) { -iput (inode); - res = -ENOMEM ; - } } - - out: -if (bh) -brelse (bh); + parent =d_alloc_anon (inode); +if (!parent) { +iput (inode); + parent =ERR_PTR (-ENOMEM ); + } +out:unlock_kernel (); -if (res) -return ERR_PTR (res); -else -return parent; + +return parent; }static struct export_operations fat_export_ops = {
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync06-fat_dir-cleanup4 +10 -7
@@ -236,9 +236,11 @@ static struct dentry *msdos_lookup(struc goto add;if (res <0 ) goto out; - inode =fat_build_inode (sb, de, i_pos, &res); -if (res) + inode =fat_build_inode (sb, de, i_pos); +if (IS_ERR (inode)) { + res =PTR_ERR (inode); goto out; + } add: res =0 ; dentry =d_splice_alias (inode, dentry);
@@ -314,11 +316,11 @@ static int msdos_create(struct inode *diunlock_kernel ();return res; } - inode =fat_build_inode (dir->i_sb, de, i_pos, &res); + inode =fat_build_inode (dir->i_sb, de, i_pos);brelse (bh); -if (!inode) { +if (IS_ERR (inode)) {unlock_kernel (); -return res; +return PTR_ERR (inode); } inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ;mark_inode_dirty (inode);
@@ -392,9 +394,10 @@ static int msdos_mkdir(struct inode *dir res =msdos_add_entry (dir, msdos_name, &bh, &de, &i_pos,1 , is_hid);if (res) goto out_unlock; - inode =fat_build_inode (dir->i_sb, de, i_pos, &res); -if (!inode) { + inode =fat_build_inode (dir->i_sb, de, i_pos); +if (IS_ERR (inode)) {brelse (bh); + res =PTR_ERR (inode); goto out_unlock; } res =0 ;
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync06-fat_dir-cleanup4 +11 -8
@@ -757,11 +757,11 @@ static struct dentry *vfat_lookup(struct table++; goto error; } - inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos, &err); + inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos);brelse (sinfo.bh); -if (err) { +if (IS_ERR (inode)) {unlock_kernel (); -return ERR_PTR (err); +return ERR_PTR (PTR_ERR (inode)); } alias =d_find_alias (inode);if (alias) {
@@ -798,10 +798,12 @@ static int vfat_create(struct inode *dir res =vfat_add_entry (dir, &dentry->d_name,0 , &sinfo);if (res <0 ) goto out; - inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos, &res); + inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos);brelse (sinfo.bh); -if (!inode) +if (IS_ERR (inode)) { + res =PTR_ERR (inode); goto out; + } res =0 ; inode->i_version++; inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ;
@@ -883,9 +885,11 @@ static int vfat_mkdir(struct inode *dir, res =vfat_add_entry (dir, &dentry->d_name,1 , &sinfo);if (res <0 ) goto out; - inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos, &res); -if (!inode) + inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos); +if (IS_ERR (inode)) { + res =PTR_ERR (inode); goto out_brelse; + } inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ;mark_inode_dirty (inode); inode->i_version++;
@@ -967,7 +971,6 @@ static int vfat_rename(struct inode *old } new_dir->i_version++; -/* releases old_bh */ err =fat_remove_entries (old_dir, &old_sinfo);/* and releases bh */ old_sinfo.bh =NULL ;if (err)
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync06-fat_dir-cleanup4 +1 -1
@@ -394,7 +394,7 @@ extern void fat_attach(struct inode *inoextern void fat_detach (struct inode *inode);extern struct inode *fat_iget (struct super_block *sb,loff_t i_pos);extern struct inode *fat_build_inode (struct super_block *sb, -struct msdos_dir_entry *de,loff_t i_pos,int *res); +struct msdos_dir_entry *de,loff_t i_pos);extern int fat_sync_inode (struct inode *inode);extern int fat_fill_super (struct super_block *sb,void *data,int silent,struct inode_operations *fs_dir_inode_ops,int isvfat);
_
OGAWA Hirofumi
maintainerPATCH 12/29 FAT: Use "struct fat_slot_info" for fat_scan()
Use "struct fat_slot_info" for fat_scan(). But ".." entry can not provide valid informations for inode, so add the fat_get_dotdot_entry() as special case.
---
fs/fat/dir.c | 41 +++++++++++++++++----- fs/fat/inode.c | 2 - fs/msdos/namei.c | 84 ++++++++++++++++++++++++++--------------------- fs/vfat/namei.c | 16 +++----- include/linux/msdos_fs.h | 5 +- 5 files changed, 88 insertions(+), 60 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~sync06-fat_dir-cleanup5 +31 -10
@@ -510,9 +510,9 @@ ParseLong: j = last_u; lpos = cpos - (long_slots+1 )*sizeof (struct msdos_dir_entry ); -if (!memcmp (de->name,MSDOS_DOT ,11 )) +if (!memcmp (de->name,MSDOS_DOT ,MSDOS_NAME )) inum = inode->i_ino; -else if (!memcmp (de->name,MSDOS_DOTDOT ,11 )) { +else if (!memcmp (de->name,MSDOS_DOTDOT ,MSDOS_NAME )) { inum =parent_ino (filp->f_dentry); }else {struct inode *tmp =fat_iget (sb, i_pos);
@@ -695,6 +695,26 @@ static int fat_get_short_entry(struct inreturn -ENOENT ; } +/* +* The ".." entry can not provide the "struct fat_slot_info" informations +* for inode. So, this function provide the some informations only. +*/ +int fat_get_dotdot_entry (struct inode *dir,struct buffer_head **bh, +struct msdos_dir_entry **de,loff_t *i_pos) +{ +loff_t offset; + + offset =0 ; + *bh =NULL ; +while (fat_get_short_entry (dir, &offset, bh, de, i_pos) >=0 ) { +if (!strncmp ((*de)->name,MSDOS_DOTDOT ,MSDOS_NAME )) +return 0 ; + } +return -ENOENT ; +} + +EXPORT_SYMBOL (fat_get_dotdot_entry); +/* See if directory is empty */ int fat_dir_empty (struct inode *dir) {
@@ -744,16 +764,17 @@ int fat_subdirs(struct inode *dir)* Returns an error code or zero. */ int fat_scan (struct inode *dir,const unsigned char *name, -struct buffer_head **bh,struct msdos_dir_entry **de, -loff_t *i_pos) +struct fat_slot_info *sinfo) { -loff_t cpos; - - *bh =NULL ; - cpos =0 ; -while (fat_get_short_entry (dir, &cpos, bh, de, i_pos) >=0 ) { -if (!strncmp ((*de)->name, name,MSDOS_NAME )) + sinfo->slot_off =0 ; + sinfo->bh =NULL ; +while (fat_get_short_entry (dir, &sinfo->slot_off, &sinfo->bh, + &sinfo->de, &sinfo->i_pos) >=0 ) { +if (!strncmp (sinfo->de->name, name,MSDOS_NAME )) { + sinfo->slot_off -=sizeof (*sinfo->de); + sinfo->nr_slots =1 ;return 0 ; + } }return -ENOENT ; }
fs/fat/inode.c renamed from fs/fat/inode.c~sync06-fat_dir-cleanup5 +1 -1
@@ -654,7 +654,7 @@ static struct dentry *fat_get_parent(strlock_kernel (); - err =fat_scan (child->d_inode,MSDOS_DOTDOT , &bh, &de, &i_pos); + err =fat_get_dotdot_entry (child->d_inode, &bh, &de, &i_pos);if (err) { parent =ERR_PTR (err); goto out;
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync06-fat_dir-cleanup5 +47 -37
188 lines not on this page · raw message
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync06-fat_dir-cleanup5 +6 -10
@@ -208,15 +208,11 @@ static int vfat_valid_longname(const unsstatic int vfat_find_form (struct inode *dir,unsigned char *name) { -struct msdos_dir_entry *de; -struct buffer_head *bh =NULL ; -loff_t i_pos; -int res; - - res =fat_scan (dir, name, &bh, &de, &i_pos); -brelse (bh); -if (res <0 ) +struct fat_slot_info sinfo; +int err =fat_scan (dir, name, &sinfo); +if (err)return -ENOENT ; +brelse (sinfo.bh);return 0 ; }
@@ -938,8 +934,8 @@ static int vfat_rename(struct inode *old is_dir =S_ISDIR (old_inode->i_mode);if (is_dir) { -if (fat_scan (old_inode,MSDOS_DOTDOT , &dotdot_bh, - &dotdot_de, &dotdot_i_pos) <0 ) { +if (fat_get_dotdot_entry (old_inode, &dotdot_bh, &dotdot_de, + &dotdot_i_pos) <0 ) { err = -EIO ; goto out; }
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync06-fat_dir-cleanup5 +3 -2
@@ -331,8 +331,9 @@ extern int fat_new_dir(struct inode *dirextern int fat_dir_empty (struct inode *dir);extern int fat_subdirs (struct inode *dir);extern int fat_scan (struct inode *dir,const unsigned char *name, -struct buffer_head **res_bh, -struct msdos_dir_entry **res_de,loff_t *i_pos); +struct fat_slot_info *sinfo); +extern int fat_get_dotdot_entry (struct inode *dir,struct buffer_head **bh, +struct msdos_dir_entry **de,loff_t *i_pos);extern int fat_remove_entries (struct inode *dir,struct fat_slot_info *sinfo);/* fat/fatent.c */
_
OGAWA Hirofumi
maintainerPATCH 13/29 FAT: Use "struct fat_slot_info" for msdos_find()
The msdos_find() provide the "struct fat_slot_info". Then some cleanups.
---
fs/msdos/namei.c | 88 ++++++++++++++++++++++--------------------------------- 1 files changed, 36 insertions(+), 52 deletions(-)
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync06-fat_dir-cleanup6 +36 -52
@@ -137,11 +137,9 @@ static int msdos_format_name(const unsig/***** Locates a directory entry. Uses unformatted name. */ static int msdos_find (struct inode *dir,const unsigned char *name,int len, -struct buffer_head **bh,struct msdos_dir_entry **de, -loff_t *i_pos) +struct fat_slot_info *sinfo) {struct msdos_sb_info *sbi =MSDOS_SB (dir->i_sb); -struct fat_slot_info sinfo;unsigned char msdos_name[MSDOS_NAME ];int err;
@@ -149,22 +147,17 @@ static int msdos_find(struct inode *dir,if (err)return -ENOENT ; - err =fat_scan (dir, msdos_name, &sinfo); + err =fat_scan (dir, msdos_name, sinfo);if (!err && sbi->options.dotsOK) {if (name[0 ] =='.' ) { -if (!(sinfo.de->attr &ATTR_HIDDEN )) +if (!(sinfo->de->attr &ATTR_HIDDEN )) err = -ENOENT ; }else { -if (sinfo.de->attr &ATTR_HIDDEN ) +if (sinfo->de->attr &ATTR_HIDDEN ) err = -ENOENT ; }if (err) -brelse (sinfo.bh); - } -if (!err) { - *i_pos = sinfo.i_pos; - *de = sinfo.de; - *bh = sinfo.bh; +brelse (sinfo->bh); }return err; }
@@ -228,22 +221,20 @@ static struct dentry *msdos_lookup(struc struct nameidata *nd) {struct super_block *sb = dir->i_sb; +struct fat_slot_info sinfo;struct inode *inode =NULL ; -struct msdos_dir_entry *de; -struct buffer_head *bh =NULL ; -loff_t i_pos;int res; dentry->d_op = &msdos_dentry_operations;lock_kernel (); - res =msdos_find (dir, dentry->d_name.name, dentry->d_name.len, &bh, - &de, &i_pos); + res =msdos_find (dir, dentry->d_name.name, dentry->d_name.len, &sinfo);if (res == -ENOENT ) goto add;if (res <0 ) goto out; - inode =fat_build_inode (sb, de, i_pos); + inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos); +brelse (sinfo.bh);if (IS_ERR (inode)) { res =PTR_ERR (inode); goto out;
@@ -254,7 +245,6 @@ add:if (dentry) dentry->d_op = &msdos_dentry_operations; out: -brelse (bh);unlock_kernel ();if (!res)return dentry;
@@ -341,39 +331,35 @@ static int msdos_create(struct inode *distatic int msdos_rmdir (struct inode *dir,struct dentry *dentry) {struct inode *inode = dentry->d_inode; -loff_t i_pos; -int res; -struct buffer_head *bh; -struct msdos_dir_entry *de; +struct fat_slot_info sinfo; +int err; - bh =NULL ;lock_kernel (); - res =msdos_find (dir, dentry->d_name.name, dentry->d_name.len, - &bh, &de, &i_pos); -if (res <0 ) - goto rmdir_done;/* * Check whether the directory is not in use, then check * whether it is empty. */ - res =fat_dir_empty (inode); -if (res) - goto rmdir_done; + err =fat_dir_empty (inode); +if (err) + goto out; + err =msdos_find (dir, dentry->d_name.name, dentry->d_name.len, &sinfo); +if (err) + goto out; - de->name[0 ] =DELETED_FLAG ; -mark_buffer_dirty (bh); + sinfo.de->name[0 ] =DELETED_FLAG ; +mark_buffer_dirty (sinfo.bh); +brelse (sinfo.bh);fat_detach (inode); inode->i_nlink =0 ; inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ; - dir->i_nlink--;mark_inode_dirty (inode); -mark_inode_dirty (dir); - res =0 ; -rmdir_done: -brelse (bh); + dir->i_nlink--; +mark_inode_dirty (dir); +out:unlock_kernel (); -return res; + +return err; }/***** Make a directory */
@@ -420,6 +406,7 @@ static int msdos_mkdir(struct inode *dirif (res) goto mkdir_error;brelse (bh); +d_instantiate (dentry, inode); res =0 ;
@@ -445,30 +432,27 @@ mkdir_error:static int msdos_unlink (struct inode *dir,struct dentry *dentry) {struct inode *inode = dentry->d_inode; -loff_t i_pos; -int res; -struct buffer_head *bh; -struct msdos_dir_entry *de; +struct fat_slot_info sinfo; +int err; - bh =NULL ;lock_kernel (); - res =msdos_find (dir, dentry->d_name.name, dentry->d_name.len, - &bh, &de, &i_pos); -if (res <0 ) + err =msdos_find (dir, dentry->d_name.name, dentry->d_name.len, &sinfo); +if (err) goto unlink_done; - de->name[0 ] =DELETED_FLAG ; -mark_buffer_dirty (bh); + sinfo.de->name[0 ] =DELETED_FLAG ; +mark_buffer_dirty (sinfo.bh); +brelse (sinfo.bh);fat_detach (inode); -brelse (bh); inode->i_nlink =0 ; inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ;mark_inode_dirty (inode); +mark_inode_dirty (dir); - res =0 ; unlink_done:unlock_kernel (); -return res; + +return err; } static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
_
OGAWA Hirofumi
maintainerPATCH 14/29 FAT: vfat_build_slots() cleanup
With this, the vfat_build_slots() builds the completely data including the timestamp and cluster. (But this is not using "cluster", it's not complete yet)
---
fs/vfat/namei.c | 110 ++++++++++++++++++++++++++------------------------------ 1 files changed, 52 insertions(+), 58 deletions(-)
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync07-fat_dir +52 -58
@@ -575,8 +575,9 @@ xlate_to_uni(const unsigned char *name, }static int vfat_build_slots (struct inode *dir,const unsigned char *name, -int len,struct msdos_dir_slot *ds, -int *slots,int is_dir) +int len,int is_dir,int cluster, +struct timespec *ts, +struct msdos_dir_slot *slots,int *nr_slots) {struct msdos_sb_info *sbi =MSDOS_SB (dir->i_sb);struct fat_mount_options *opts = &sbi->options;
@@ -586,83 +587,85 @@ static int vfat_build_slots(struct inodeunsigned char cksum, lcase;unsigned char msdos_name[MSDOS_NAME ];wchar_t *uname; -int res, slot, ulen, usize, i; +__le16 time, date; +int err, ulen, usize, i;loff_t offset; - *slots =0 ; - res =vfat_valid_longname (name, len); -if (res) -return res; + *nr_slots =0 ; + err =vfat_valid_longname (name, len); +if (err) +return err; page =__get_free_page (GFP_KERNEL );if (!page)return -ENOMEM ; uname = (wchar_t *)page; - res =xlate_to_uni (name, len, (unsigned char *)uname, &ulen, &usize, + err =xlate_to_uni (name, len, (unsigned char *)uname, &ulen, &usize, opts->unicode_xlate, opts->utf8, sbi->nls_io); -if (res <0 ) +if (err) goto out_free; - res =vfat_is_used_badchars (uname, ulen); -if (res <0 ) + err =vfat_is_used_badchars (uname, ulen); +if (err) goto out_free; - res =vfat_create_shortname (dir, sbi->nls_disk, uname, ulen, + err =vfat_create_shortname (dir, sbi->nls_disk, uname, ulen, msdos_name, &lcase); -if (res <0 ) +if (err <0 ) goto out_free; -else if (res ==1 ) { - de = (struct msdos_dir_entry *)ds; - res =0 ; +else if (err ==1 ) { + de = (struct msdos_dir_entry *)slots; + err =0 ; goto shortname; }/* build the entry of long file name */ - *slots = usize /13 ;for (cksum = i =0 ; i <11 ; i++) cksum = (((cksum&1 )<<7 )|((cksum&0xfe )>>1 )) + msdos_name[i]; -for (ps = ds, slot = *slots; slot >0 ; slot--, ps++) { - ps->id = slot; + *nr_slots = usize /13 ; +for (ps = slots, i = *nr_slots; i >0 ; i--, ps++) { + ps->id = i; ps->attr =ATTR_EXT ; ps->reserved =0 ; ps->alias_checksum = cksum; ps->start =0 ; - offset = (slot -1 ) *13 ; + offset = (i -1 ) *13 ;fatwchar_to16 (ps->name0_4, uname + offset,5 );fatwchar_to16 (ps->name5_10, uname + offset +5 ,6 );fatwchar_to16 (ps->name11_12, uname + offset +11 ,2 ); } - ds[0 ].id |=0x40 ; + slots[0 ].id |=0x40 ; de = (struct msdos_dir_entry *)ps; shortname:/* build the entry of 8.3 alias name */ - (*slots)++; + (*nr_slots)++;memcpy (de->name, msdos_name,MSDOS_NAME ); de->attr = is_dir ?ATTR_DIR :ATTR_ARCH ; de->lcase = lcase; - de->adate = de->cdate = de->date =0 ; - de->ctime = de->time =0 ; +fat_date_unix2dos (ts->tv_sec, &time, &date); + de->time = de->ctime = time; + de->date = de->cdate = de->adate = date; de->ctime_cs =0 ; - de->start =0 ; - de->starthi =0 ; + de->start =cpu_to_le16 (cluster); + de->starthi =cpu_to_le16 (cluster >>16 ); de->size =0 ; - out_free:free_page (page); -return res; +return err; } -static int vfat_add_entry (struct inode *dir,struct qstr *qname, -int is_dir,struct fat_slot_info *sinfo) +static int vfat_add_entry (struct inode *dir,struct qstr *qname,int is_dir, +struct fat_slot_info *sinfo) {struct super_block *sb = dir->i_sb; -struct msdos_dir_slot *dir_slots; -loff_t offset; -int res, slots, slot; +struct msdos_dir_slot *slots; +struct timespec ts;unsigned int len; +int err, i, nr_slots; +loff_t offset;struct msdos_dir_entry *de, *dummy_de;struct buffer_head *bh, *dummy_bh;loff_t dummy_i_pos;
@@ -671,59 +674,50 @@ static int vfat_add_entry(struct inode *if (len ==0 )return -ENOENT ; - dir_slots =kmalloc (sizeof (*dir_slots) *MSDOS_SLOTS ,GFP_KERNEL ); -if (dir_slots ==NULL ) + slots =kmalloc (sizeof (*slots) *MSDOS_SLOTS ,GFP_KERNEL ); +if (slots ==NULL )return -ENOMEM ; - res =vfat_build_slots (dir, qname->name, len, - dir_slots, &slots, is_dir); -if (res <0 ) + ts =CURRENT_TIME_SEC ; + err =vfat_build_slots (dir, qname->name, len, is_dir,0 , &ts, + slots, &nr_slots); +if (err) goto cleanup;/* build the empty directory entry of number of slots */ offset = -fat_add_entries (dir, slots, &dummy_bh, &dummy_de, &dummy_i_pos); +fat_add_entries (dir, nr_slots, &dummy_bh, &dummy_de, &dummy_i_pos);if (offset <0 ) { - res = offset; + err = offset; goto cleanup; }brelse (dummy_bh);/* Now create the new entry */ bh =NULL ; -for (slot =0 ; slot < slots; slot++) { +for (i =0 ; i < nr_slots; i++) {if (fat_get_entry (dir, &offset, &bh, &de, &sinfo->i_pos) <0 ) { - res = -EIO ; + err = -EIO ; goto cleanup; } -memcpy (de, dir_slots + slot,sizeof (struct msdos_dir_slot )); +memcpy (de, slots + i,sizeof (struct msdos_dir_slot ));mark_buffer_dirty (bh);if (sb->s_flags &MS_SYNCHRONOUS )sync_dirty_buffer (bh); } - res =0 ;/* update timestamp */ - dir->i_ctime = dir->i_mtime = dir->i_atime =CURRENT_TIME_SEC ; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts;mark_inode_dirty (dir); -fat_date_unix2dos (dir->i_mtime.tv_sec, &de->time, &de->date); - dir->i_mtime.tv_nsec =0 ; - de->ctime = de->time; - de->adate = de->cdate = de->date; -mark_buffer_dirty (bh); -if (sb->s_flags &MS_SYNCHRONOUS ) -sync_dirty_buffer (bh); -/* slots can't be less than 1 */ - sinfo->slot_off = offset -sizeof (struct msdos_dir_slot ) * slots; - sinfo->nr_slots = slots; + sinfo->slot_off = offset -sizeof (struct msdos_dir_slot ) * nr_slots; + sinfo->nr_slots = nr_slots; sinfo->de = de; sinfo->bh = bh; - cleanup: -kfree (dir_slots); -return res; +kfree (slots); +return err; } static int vfat_find(struct inode *dir, struct qstr *qname,
_
OGAWA Hirofumi
maintainerPATCH 15/29 FAT: Use a same timestamp on some operations path
---
fs/vfat/namei.c | 63 +++++++++++++++++++++++++++++++------------------------- 1 files changed, 35 insertions(+), 28 deletions(-)
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync07-fat_dir2 +35 -28
@@ -658,11 +658,11 @@ out_free: }static int vfat_add_entry (struct inode *dir,struct qstr *qname,int is_dir, +struct timespec *ts,struct fat_slot_info *sinfo) {struct super_block *sb = dir->i_sb;struct msdos_dir_slot *slots; -struct timespec ts;unsigned int len;int err, i, nr_slots;loff_t offset;
@@ -678,8 +678,7 @@ static int vfat_add_entry(struct inode *if (slots ==NULL )return -ENOMEM ; - ts =CURRENT_TIME_SEC ; - err =vfat_build_slots (dir, qname->name, len, is_dir,0 , &ts, + err =vfat_build_slots (dir, qname->name, len, is_dir,0 , ts, slots, &nr_slots);if (err) goto cleanup;
@@ -707,7 +706,7 @@ static int vfat_add_entry(struct inode * }/* update timestamp */ - dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + dir->i_ctime = dir->i_mtime = dir->i_atime = *ts;mark_inode_dirty (dir);/* slots can't be less than 1 */
@@ -780,33 +779,33 @@ static int vfat_create(struct inode *dir struct nameidata *nd) {struct super_block *sb = dir->i_sb; -struct inode *inode =NULL ; +struct inode *inode;struct fat_slot_info sinfo; -int res; +struct timespec ts; +int err;lock_kernel (); - res =vfat_add_entry (dir, &dentry->d_name,0 , &sinfo); -if (res <0 ) + + ts =CURRENT_TIME_SEC ; + err =vfat_add_entry (dir, &dentry->d_name,0 , &ts, &sinfo); +if (err) goto out; inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos);brelse (sinfo.bh);if (IS_ERR (inode)) { - res =PTR_ERR (inode); + err =PTR_ERR (inode); goto out; } - res =0 ; inode->i_version++; - inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ; -mark_inode_dirty (inode); -if (IS_SYNC (inode)) -fat_sync_inode (inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; +/* timestamp is already written, so mark_inode_dirty() is unneeded. */ dir->i_version++; dentry->d_time = dentry->d_parent->d_inode->i_version;d_instantiate (dentry, inode); out:unlock_kernel (); -return res; +return err; }static int vfat_rmdir (struct inode *dir,struct dentry *dentry)
@@ -869,37 +868,42 @@ static int vfat_mkdir(struct inode *dir,struct super_block *sb = dir->i_sb;struct inode *inode =NULL ;struct fat_slot_info sinfo; -int res; +struct timespec ts; +int err;lock_kernel (); - res =vfat_add_entry (dir, &dentry->d_name,1 , &sinfo); -if (res <0 ) + + ts =CURRENT_TIME_SEC ; + err =vfat_add_entry (dir, &dentry->d_name,1 , &ts, &sinfo); +if (err) goto out; inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos);if (IS_ERR (inode)) { - res =PTR_ERR (inode); + err =PTR_ERR (inode); goto out_brelse; } - inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ; -mark_inode_dirty (inode); inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; +/* timestamp is already written, so mark_inode_dirty() is unneeded. */ + dir->i_version++; dir->i_nlink++; inode->i_nlink =2 ;/* no need to mark them dirty */ - res =fat_new_dir (inode, dir,1 ); -if (res <0 ) + err =fat_new_dir (inode, dir,1 ); +if (err) goto mkdir_failed; + dentry->d_time = dentry->d_parent->d_inode->i_version;d_instantiate (dentry, inode); out_brelse:brelse (sinfo.bh); out:unlock_kernel (); -return res; +return err; mkdir_failed: inode->i_nlink =0 ; - inode->i_mtime = inode->i_atime =CURRENT_TIME_SEC ; + inode->i_mtime = inode->i_atime = ts;fat_detach (inode);mark_inode_dirty (inode);fat_remove_entries (dir, &sinfo);/* and releases bh */
@@ -917,6 +921,7 @@ static int vfat_rename(struct inode *oldstruct inode *old_inode, *new_inode;int err, is_dir;struct fat_slot_info old_sinfo, sinfo; +struct timespec ts; old_sinfo.bh = dotdot_bh =NULL ; old_inode = old_dentry->d_inode;
@@ -935,6 +940,7 @@ static int vfat_rename(struct inode *old } } + ts =CURRENT_TIME_SEC ;if (new_dentry->d_inode) { err =vfat_find (new_dir, &new_dentry->d_name, &sinfo);if (err)
@@ -953,7 +959,7 @@ static int vfat_rename(struct inode *old }fat_detach (new_inode); }else { - err =vfat_add_entry (new_dir, &new_dentry->d_name, is_dir, + err =vfat_add_entry (new_dir, &new_dentry->d_name, is_dir, &ts, &sinfo);if (err) goto out;
@@ -972,11 +978,12 @@ static int vfat_rename(struct inode *oldmark_inode_dirty (old_inode); old_dir->i_version++; - old_dir->i_ctime = old_dir->i_mtime =CURRENT_TIME_SEC ; + old_dir->i_ctime = old_dir->i_mtime = ts;mark_inode_dirty (old_dir); +if (new_inode) { new_inode->i_nlink--; - new_inode->i_ctime =CURRENT_TIME_SEC ; + new_inode->i_ctime = ts; }if (is_dir) {
_
OGAWA Hirofumi
maintainerPATCH 16/29 FAT: msdos_rename() cleanup
Cleans up the msdos_rename(). (use the logic similar to vfat_rename().)
---
fs/msdos/namei.c | 175 +++++++++++++++++++++++++++---------------------------- 1 files changed, 89 insertions(+), 86 deletions(-)
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync07-fat_dir3 +89 -86
@@ -458,146 +458,149 @@ unlink_done:static int do_msdos_rename (struct inode *old_dir,unsigned char *old_name,struct dentry *old_dentry,struct inode *new_dir,unsigned char *new_name, -struct dentry *new_dentry, -struct buffer_head *old_bh, -struct msdos_dir_entry *old_de,loff_t old_i_pos, -int is_hid) -{ -struct fat_slot_info sinfo; -struct buffer_head *new_bh =NULL , *dotdot_bh =NULL ; -struct msdos_dir_entry *new_de, *dotdot_de; +struct dentry *new_dentry,int is_hid) +{ +struct buffer_head *dotdot_bh; +struct msdos_dir_entry *dotdot_de; +loff_t dotdot_i_pos;struct inode *old_inode, *new_inode; -loff_t new_i_pos, dotdot_i_pos; -int error; -int is_dir; +struct fat_slot_info old_sinfo, sinfo; +int err, is_dir; + old_sinfo.bh = dotdot_bh =NULL ; old_inode = old_dentry->d_inode; new_inode = new_dentry->d_inode; - is_dir =S_ISDIR (old_inode->i_mode); - error =fat_scan (new_dir, new_name, &sinfo); -if (!error) { - new_i_pos = sinfo.i_pos; - new_bh = sinfo.bh; - new_de = sinfo.de; -if (!new_inode) - goto degenerate_case; + err =fat_scan (old_dir, old_name, &old_sinfo); +if (err) { + err = -EIO ; + goto out; } + + is_dir =S_ISDIR (old_inode->i_mode);if (is_dir) { -if (new_inode) { - error =fat_dir_empty (new_inode); -if (error) - goto out; - }if (fat_get_dotdot_entry (old_inode, &dotdot_bh, &dotdot_de, &dotdot_i_pos) <0 ) { - error = -EIO ; + err = -EIO ; goto out; } } -if (!new_bh) { - error =msdos_add_entry (new_dir, new_name, &new_bh, &new_de, - &new_i_pos, is_dir, is_hid); -if (error) + + err =fat_scan (new_dir, new_name, &sinfo); +if (!err) { +brelse (sinfo.bh); +if (!new_inode) { +/* "foo" -> ".foo" case. just change the ATTR_HIDDEN */ +if (sinfo.de != old_sinfo.de) { + err = -EINVAL ; + goto out; + } +if (is_hid) +MSDOS_I (old_inode)->i_attrs |=ATTR_HIDDEN ; +else +MSDOS_I (old_inode)->i_attrs &= ~ATTR_HIDDEN ; +mark_inode_dirty (old_inode); + + old_dir->i_version++; + old_dir->i_ctime = old_dir->i_mtime =CURRENT_TIME_SEC ; +mark_inode_dirty (old_dir); goto out; + } } - new_dir->i_version++; - -/* There we go */ +if (new_inode) { +if (err) + goto out; +if (MSDOS_I (new_inode)->i_pos != sinfo.i_pos) { +/* WTF??? Cry and fail. */ +printk (KERN_WARNING "msdos_rename: fs corrupted\n" ); + goto out; + } -if (new_inode) +if (is_dir) { + err =fat_dir_empty (new_inode); +if (err) + goto out; + }fat_detach (new_inode); - old_de->name[0 ] =DELETED_FLAG ; -mark_buffer_dirty (old_bh); + }else { + err =msdos_add_entry (new_dir, new_name, &sinfo.bh, &sinfo.de, + &sinfo.i_pos, is_dir, is_hid); +if (err) + goto out; +brelse (sinfo.bh); + } + new_dir->i_version++; + + old_sinfo.de->name[0 ] =DELETED_FLAG ; +mark_buffer_dirty (old_sinfo.bh); +brelse (old_sinfo.bh); + old_sinfo.bh =NULL ; +if (is_dir) + old_dir->i_nlink--;fat_detach (old_inode); -fat_attach (old_inode, new_i_pos); +fat_attach (old_inode, sinfo.i_pos);if (is_hid)MSDOS_I (old_inode)->i_attrs |=ATTR_HIDDEN ;else MSDOS_I (old_inode)->i_attrs &= ~ATTR_HIDDEN ;mark_inode_dirty (old_inode); + old_dir->i_version++; old_dir->i_ctime = old_dir->i_mtime =CURRENT_TIME_SEC ;mark_inode_dirty (old_dir); +if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime =CURRENT_TIME_SEC ;mark_inode_dirty (new_inode); } -if (dotdot_bh) { - dotdot_de->start =cpu_to_le16 (MSDOS_I (new_dir)->i_logstart); - dotdot_de->starthi = -cpu_to_le16 ((MSDOS_I (new_dir)->i_logstart) >>16 ); +if (is_dir) { +int start =MSDOS_I (new_dir)->i_logstart; + dotdot_de->start =cpu_to_le16 (start); + dotdot_de->starthi =cpu_to_le16 (start >>16 );mark_buffer_dirty (dotdot_bh); - old_dir->i_nlink--; -mark_inode_dirty (old_dir); +if (new_inode) { new_inode->i_nlink--; -mark_inode_dirty (new_inode); }else { new_dir->i_nlink++;mark_inode_dirty (new_dir); } } - error =0 ; out: -brelse (new_bh);brelse (dotdot_bh); -return error; - -degenerate_case: - error = -EINVAL ; -if (new_de != old_de) - goto out; -brelse (new_bh); -if (is_hid) -MSDOS_I (old_inode)->i_attrs |=ATTR_HIDDEN ; -else -MSDOS_I (old_inode)->i_attrs &= ~ATTR_HIDDEN ; -mark_inode_dirty (old_inode); - old_dir->i_version++; - old_dir->i_ctime = old_dir->i_mtime =CURRENT_TIME_SEC ; -mark_inode_dirty (old_dir); -return 0 ; +brelse (old_sinfo.bh); +return err; }/***** Rename, a wrapper for rename_same_dir & rename_diff_dir */ static int msdos_rename (struct inode *old_dir,struct dentry *old_dentry,struct inode *new_dir,struct dentry *new_dentry) { -struct fat_slot_info sinfo; -int error, is_hid, old_hid;/* if new file and old file are hidden */ unsigned char old_msdos_name[MSDOS_NAME ], new_msdos_name[MSDOS_NAME ]; +int err, is_hid;lock_kernel (); - error =msdos_format_name (old_dentry->d_name.name, - old_dentry->d_name.len, old_msdos_name, - &MSDOS_SB (old_dir->i_sb)->options); -if (error <0 ) - goto rename_done; - error =msdos_format_name (new_dentry->d_name.name, - new_dentry->d_name.len, new_msdos_name, - &MSDOS_SB (new_dir->i_sb)->options); -if (error <0 ) - goto rename_done; + + err =msdos_format_name (old_dentry->d_name.name, + old_dentry->d_name.len, old_msdos_name, + &MSDOS_SB (old_dir->i_sb)->options); +if (err) + goto out; + err =msdos_format_name (new_dentry->d_name.name, + new_dentry->d_name.len, new_msdos_name, + &MSDOS_SB (new_dir->i_sb)->options); +if (err) + goto out; is_hid = (new_dentry->d_name.name[0 ] =='.' ) && (new_msdos_name[0 ] !='.' ); - old_hid = - (old_dentry->d_name.name[0 ] =='.' ) && (old_msdos_name[0 ] !='.' ); - error =fat_scan (old_dir, old_msdos_name, &sinfo); -if (error <0 ) - goto rename_done; - - error =do_msdos_rename (old_dir, old_msdos_name, old_dentry, - new_dir, new_msdos_name, new_dentry, - sinfo.bh, sinfo.de, sinfo.i_pos, is_hid); -brelse (sinfo.bh); - -rename_done: + err =do_msdos_rename (old_dir, old_msdos_name, old_dentry, + new_dir, new_msdos_name, new_dentry, is_hid); +out:unlock_kernel (); -return error; +return err; }static struct inode_operations msdos_dir_inode_operations = {
_
OGAWA Hirofumi
maintainerPATCH 17/29 FAT: msdos_add_entry() cleanup
The msdos_add_entry() use similar interface to vfat_add_entry(). And use a same timestamp on some operations path.
---
fs/msdos/namei.c | 162 ++++++++++++++++++++++++++++--------------------------- 1 files changed, 84 insertions(+), 78 deletions(-)
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync07-fat_dir4 +84 -78
@@ -253,31 +253,38 @@ out:/***** Creates a directory entry (name is already formatted). */ static int msdos_add_entry (struct inode *dir,const unsigned char *name, -struct buffer_head **bh, -struct msdos_dir_entry **de, -loff_t *i_pos,int is_dir,int is_hid) +int is_dir,int is_hid,struct timespec *ts, +struct fat_slot_info *sinfo) { -int res; +struct msdos_dir_entry de; +__le16 time, date; +int offset; - res =fat_add_entries (dir,1 , bh, de, i_pos); -if (res <0 ) -return res; +memcpy (de.name, name,MSDOS_NAME ); + de.attr = is_dir ?ATTR_DIR :ATTR_ARCH ; +if (is_hid) + de.attr |=ATTR_HIDDEN ; + de.lcase =0 ; +fat_date_unix2dos (ts->tv_sec, &time, &date); + de.time = de.ctime = time; + de.date = de.cdate = de.adate = date; + de.ctime_cs =0 ; + de.start =0 ; + de.starthi =0 ; + de.size =0 ; + + offset =fat_add_entries (dir,1 , &sinfo->bh, &sinfo->de, &sinfo->i_pos); +if (offset <0 ) +return offset; + sinfo->slot_off = offset; + sinfo->nr_slots =1 ; -/* -* XXX all times should be set by caller upon successful completion. -*/ - dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ; +memcpy (sinfo->de, &de,sizeof (de)); +mark_buffer_dirty (sinfo->bh); + + dir->i_ctime = dir->i_mtime = *ts;mark_inode_dirty (dir); -memcpy ((*de)->name, name,MSDOS_NAME ); - (*de)->attr = is_dir ?ATTR_DIR :ATTR_ARCH ; -if (is_hid) - (*de)->attr |=ATTR_HIDDEN ; - (*de)->start =0 ; - (*de)->starthi =0 ; -fat_date_unix2dos (dir->i_mtime.tv_sec, &(*de)->time, &(*de)->date); - (*de)->size =0 ; -mark_buffer_dirty (*bh);return 0 ; }
@@ -286,45 +293,43 @@ static int msdos_create(struct inode *di struct nameidata *nd) {struct super_block *sb = dir->i_sb; -struct fat_slot_info sinfo; -struct buffer_head *bh; -struct msdos_dir_entry *de;struct inode *inode; -loff_t i_pos; -int res, is_hid; +struct fat_slot_info sinfo; +struct timespec ts;unsigned char msdos_name[MSDOS_NAME ]; +int err, is_hid;lock_kernel (); - res =msdos_format_name (dentry->d_name.name, dentry->d_name.len, + + err =msdos_format_name (dentry->d_name.name, dentry->d_name.len, msdos_name, &MSDOS_SB (sb)->options); -if (res <0 ) { -unlock_kernel (); -return res; - } +if (err) + goto out; is_hid = (dentry->d_name.name[0 ] =='.' ) && (msdos_name[0 ] !='.' );/* Have to do it due to foo vs. .foo conflicts */ if (!fat_scan (dir, msdos_name, &sinfo)) {brelse (sinfo.bh); -unlock_kernel (); -return -EINVAL ; + err = -EINVAL ; + goto out; } - res =msdos_add_entry (dir, msdos_name, &bh, &de, &i_pos,0 , is_hid); -if (res) { -unlock_kernel (); -return res; - } - inode =fat_build_inode (sb, de, i_pos); -brelse (bh); + ts =CURRENT_TIME_SEC ; + err =msdos_add_entry (dir, msdos_name,0 , is_hid, &ts, &sinfo); +if (err) + goto out; + inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos); +brelse (sinfo.bh);if (IS_ERR (inode)) { -unlock_kernel (); -return PTR_ERR (inode); + err =PTR_ERR (inode); + goto out; } - inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ; -mark_inode_dirty (inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; +/* timestamp is already written, so mark_inode_dirty() is unneeded. */ +d_instantiate (dentry, inode); +out:unlock_kernel (); -return 0 ; +return err; }/***** Remove a directory */
@@ -367,65 +372,63 @@ static int msdos_mkdir(struct inode *dir {struct super_block *sb = dir->i_sb;struct fat_slot_info sinfo; -struct buffer_head *bh; -struct msdos_dir_entry *de;struct inode *inode; -int res, is_hid;unsigned char msdos_name[MSDOS_NAME ]; -loff_t i_pos; +struct timespec ts; +int err, is_hid;lock_kernel (); - res =msdos_format_name (dentry->d_name.name, dentry->d_name.len, + + err =msdos_format_name (dentry->d_name.name, dentry->d_name.len, msdos_name, &MSDOS_SB (sb)->options); -if (res <0 ) { -unlock_kernel (); -return res; - } +if (err) + goto out; is_hid = (dentry->d_name.name[0 ] =='.' ) && (msdos_name[0 ] !='.' );/* foo vs .foo situation */ if (!fat_scan (dir, msdos_name, &sinfo)) {brelse (sinfo.bh); - res = -EINVAL ; - goto out_unlock; + err = -EINVAL ; + goto out; } - res =msdos_add_entry (dir, msdos_name, &bh, &de, &i_pos,1 , is_hid); -if (res) - goto out_unlock; - inode =fat_build_inode (dir->i_sb, de, i_pos); + ts =CURRENT_TIME_SEC ; + err =msdos_add_entry (dir, msdos_name,1 , is_hid, &ts, &sinfo); +if (err) + goto out; + inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos);if (IS_ERR (inode)) { -brelse (bh); - res =PTR_ERR (inode); - goto out_unlock; +brelse (sinfo.bh); + err =PTR_ERR (inode); + goto out; } + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; +/* timestamp is already written, so mark_inode_dirty() is unneeded. */ dir->i_nlink++; inode->i_nlink =2 ;/* no need to mark them dirty */ - res =fat_new_dir (inode, dir,0 ); -if (res) + err =fat_new_dir (inode, dir,0 ); +if (err) goto mkdir_error; -brelse (bh); +brelse (sinfo.bh);d_instantiate (dentry, inode); - res =0 ; - -out_unlock: +out:unlock_kernel (); -return res; +return err; mkdir_error: inode->i_nlink =0 ; - inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ; + inode->i_ctime = dir->i_ctime = dir->i_mtime = ts; dir->i_nlink--;mark_inode_dirty (inode);mark_inode_dirty (dir); - de->name[0 ] =DELETED_FLAG ; -mark_buffer_dirty (bh); -brelse (bh); + sinfo.de->name[0 ] =DELETED_FLAG ; +mark_buffer_dirty (sinfo.bh); +brelse (sinfo.bh);fat_detach (inode);iput (inode); - goto out_unlock; + goto out; }/***** Unlink a file */
@@ -465,6 +468,7 @@ static int do_msdos_rename(struct inodeloff_t dotdot_i_pos;struct inode *old_inode, *new_inode;struct fat_slot_info old_sinfo, sinfo; +struct timespec ts;int err, is_dir; old_sinfo.bh = dotdot_bh =NULL ;
@@ -507,6 +511,8 @@ static int do_msdos_rename(struct inode goto out; } } + + ts =CURRENT_TIME_SEC ;if (new_inode) {if (err) goto out;
@@ -523,8 +529,8 @@ static int do_msdos_rename(struct inode }fat_detach (new_inode); }else { - err =msdos_add_entry (new_dir, new_name, &sinfo.bh, &sinfo.de, - &sinfo.i_pos, is_dir, is_hid); + err =msdos_add_entry (new_dir, new_name, is_dir, is_hid, + &ts, &sinfo);if (err) goto out;brelse (sinfo.bh);
@@ -546,12 +552,12 @@ static int do_msdos_rename(struct inodemark_inode_dirty (old_inode); old_dir->i_version++; - old_dir->i_ctime = old_dir->i_mtime =CURRENT_TIME_SEC ; + old_dir->i_ctime = old_dir->i_mtime = ts;mark_inode_dirty (old_dir);if (new_inode) { new_inode->i_nlink--; - new_inode->i_ctime =CURRENT_TIME_SEC ; + new_inode->i_ctime = ts;mark_inode_dirty (new_inode); }if (is_dir) {
_
OGAWA Hirofumi
maintainerPATCH 18/29 FAT: Allocate the cluster before adding the directory entry
With this change, ->mkdir() uses the correct updating order.
---
fs/fat/dir.c | 155 +++++++++++++++++++++++++++++++++-------------- fs/fat/fatent.c | 3 fs/msdos/namei.c | 54 +++++++--------- fs/vfat/namei.c | 59 ++++++++--------- include/linux/msdos_fs.h | 2 5 files changed, 169 insertions(+), 104 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~sync07-fat_dir5 +112 -43
@@ -869,6 +869,118 @@ int fat_remove_entries(struct inode *dirEXPORT_SYMBOL (fat_remove_entries); +static int fat_zeroed_cluster (struct inode *dir,sector_t blknr,int nr_used, +struct buffer_head **bhs,int nr_bhs) +{ +struct super_block *sb = dir->i_sb; +sector_t last_blknr = blknr +MSDOS_SB (sb)->sec_per_clus; +int err, i, n; + +/* Zeroing the unused blocks on this cluster */ + blknr += nr_used; + n = nr_used; +while (blknr < last_blknr) { + bhs[n] =sb_getblk (sb, blknr); +if (!bhs[n]) { + err = -ENOMEM ; + goto error; + } +memset (bhs[n]->b_data,0 , sb->s_blocksize); +set_buffer_uptodate (bhs[n]); +mark_buffer_dirty (bhs[n]); + + n++; + blknr++; +if (n == nr_bhs) { +if (IS_DIRSYNC (dir)) { + err =fat_sync_bhs (bhs, n); +if (err) + goto error; + } +for (i =0 ; i < n; i++) +brelse (bhs[i]); + n =0 ; + } + } +if (IS_DIRSYNC (dir)) { + err =fat_sync_bhs (bhs, n); +if (err) + goto error; + } +for (i =0 ; i < n; i++) +brelse (bhs[i]); + +return 0 ; + +error: +for (i =0 ; i < n; i++) +bforget (bhs[i]); +return err; +} + +int fat_alloc_new_dir (struct inode *dir,struct timespec *ts) +{ +struct super_block *sb = dir->i_sb; +struct msdos_sb_info *sbi =MSDOS_SB (sb); +struct buffer_head *bhs[MAX_BUF_PER_PAGE ]; +struct msdos_dir_entry *de; +sector_t blknr; +__le16 date, time; +int err, cluster; + + err =fat_alloc_clusters (dir, &cluster,1 ); +if (err) + goto error; + + blknr =fat_clus_to_blknr (sbi, cluster); + bhs[0 ] =sb_getblk (sb, blknr); +if (!bhs[0 ]) { + err = -ENOMEM ; + goto error_free; + } + +fat_date_unix2dos (ts->tv_sec, &time, &date); + + de = (struct msdos_dir_entry *)bhs[0 ]->b_data; +/* filling the new directory slots ("." and ".." entries) */ +memcpy (de[0 ].name,MSDOS_DOT ,MSDOS_NAME ); +memcpy (de[1 ].name,MSDOS_DOTDOT ,MSDOS_NAME ); + de->attr = de[1 ].attr =ATTR_DIR ; + de[0 ].lcase = de[1 ].lcase =0 ; + de[0 ].time = de[1 ].time = time; + de[0 ].date = de[1 ].date = date; + de[0 ].ctime_cs = de[1 ].ctime_cs =0 ; +if (sbi->options.isvfat) { +/* extra timestamps */ + de[0 ].ctime = de[1 ].ctime = time; + de[0 ].adate = de[0 ].cdate = de[1 ].adate = de[1 ].cdate = date; + }else { + de[0 ].ctime = de[1 ].ctime =0 ; + de[0 ].adate = de[0 ].cdate = de[1 ].adate = de[1 ].cdate =0 ; + } + de[0 ].start =cpu_to_le16 (cluster); + de[0 ].starthi =cpu_to_le16 (cluster >>16 ); + de[1 ].start =cpu_to_le16 (MSDOS_I (dir)->i_logstart); + de[1 ].starthi =cpu_to_le16 (MSDOS_I (dir)->i_logstart >>16 ); + de[0 ].size = de[1 ].size =0 ; +memset (de +2 ,0 , sb->s_blocksize -2 *sizeof (*de)); +set_buffer_uptodate (bhs[0 ]); +mark_buffer_dirty (bhs[0 ]); + + err =fat_zeroed_cluster (dir, blknr,1 , bhs,MAX_BUF_PER_PAGE ); +if (err) + goto error_free; + +return cluster; + +error_free: +fat_free_clusters (dir, cluster); +error: +return err; +} + +EXPORT_SYMBOL (fat_alloc_new_dir); +static struct buffer_head *fat_extend_dir (struct inode *inode) {struct super_block *sb = inode->i_sb;
@@ -960,46 +1072,3 @@ int fat_add_entries(struct inode *dir,in }EXPORT_SYMBOL (fat_add_entries); - -int fat_new_dir (struct inode *dir,struct inode *parent,int is_vfat) -{ -struct super_block *sb = dir->i_sb; -struct buffer_head *bh; -struct msdos_dir_entry *de; -__le16 date, time; - - bh =fat_extend_dir (dir); -if (IS_ERR (bh)) -return PTR_ERR (bh); - -/* zeroed out, so... */ -fat_date_unix2dos (dir->i_mtime.tv_sec, &time, &date); - de = (struct msdos_dir_entry *)bh->b_data; -memcpy (de[0 ].name,MSDOS_DOT ,MSDOS_NAME ); -memcpy (de[1 ].name,MSDOS_DOTDOT ,MSDOS_NAME ); - de[0 ].attr = de[1 ].attr =ATTR_DIR ; - de[0 ].time = de[1 ].time = time; - de[0 ].date = de[1 ].date = date; -if (is_vfat) { -/* extra timestamps */ - de[0 ].ctime = de[1 ].ctime = time; - de[0 ].adate = de[0 ].cdate = de[1 ].adate = de[1 ].cdate = date; - } - de[0 ].start =cpu_to_le16 (MSDOS_I (dir)->i_logstart); - de[0 ].starthi =cpu_to_le16 (MSDOS_I (dir)->i_logstart >>16 ); - de[1 ].start =cpu_to_le16 (MSDOS_I (parent)->i_logstart); - de[1 ].starthi =cpu_to_le16 (MSDOS_I (parent)->i_logstart >>16 ); -mark_buffer_dirty (bh); -if (sb->s_flags &MS_SYNCHRONOUS ) -sync_dirty_buffer (bh); -brelse (bh); - - dir->i_atime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ; -mark_inode_dirty (dir); -if (IS_SYNC (dir)) -fat_sync_inode (dir); - -return 0 ; -} - -EXPORT_SYMBOL (fat_new_dir);
fs/fat/fatent.c renamed from fs/fat/fatent.c~sync07-fat_dir5 +3 -0
@@ -3,6 +3,7 @@* Released under GPL v2. */ +#include <linux/module.h> #include <linux/fs.h> #include <linux/msdos_fs.h>
@@ -577,6 +578,8 @@ error:return err; } +EXPORT_SYMBOL (fat_free_clusters); +int fat_count_free_clusters (struct super_block *sb) {struct msdos_sb_info *sbi =MSDOS_SB (sb);
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync07-fat_dir5 +24 -30
104 lines not on this page · raw message
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync07-fat_dir5 +29 -30
117 lines not on this page · raw message
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync07-fat_dir5 +1 -1
@@ -327,13 +327,13 @@ extern int fat_search_long(struct inodeextern int fat_add_entries (struct inode *dir,int slots,struct buffer_head **bh,struct msdos_dir_entry **de,loff_t *i_pos); -extern int fat_new_dir (struct inode *dir,struct inode *parent,int is_vfat);extern int fat_dir_empty (struct inode *dir);extern int fat_subdirs (struct inode *dir);extern int fat_scan (struct inode *dir,const unsigned char *name,struct fat_slot_info *sinfo);extern int fat_get_dotdot_entry (struct inode *dir,struct buffer_head **bh,struct msdos_dir_entry **de,loff_t *i_pos); +extern int fat_alloc_new_dir (struct inode *dir,struct timespec *ts);extern int fat_remove_entries (struct inode *dir,struct fat_slot_info *sinfo);/* fat/fatent.c */
_
OGAWA Hirofumi
maintainerPATCH 19/29 FAT: Rewrite fat_add_entries()
In order not to write out the same block repeatedly, rewrite the fat_add_entries().
---
fs/fat/dir.c | 261 ++++++++++++++++++++++++++++++++++------------- fs/msdos/namei.c | 13 -- fs/vfat/namei.c | 35 ------ include/linux/msdos_fs.h | 5 4 files changed, 198 insertions(+), 116 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~sync07-fat_dir6 +189 -72
@@ -981,94 +981,211 @@ error:EXPORT_SYMBOL (fat_alloc_new_dir); -static struct buffer_head *fat_extend_dir (struct inode *inode) +static int fat_add_new_entries (struct inode *dir,void *slots,int nr_slots, +int *nr_cluster,struct msdos_dir_entry **de, +struct buffer_head **bh,loff_t *i_pos) { -struct super_block *sb = inode->i_sb; -struct buffer_head *bh, *res =NULL ; -int err, cluster, sec_per_clus =MSDOS_SB (sb)->sec_per_clus; -sector_t sector, last_sector; - -if (MSDOS_SB (sb)->fat_bits !=32 ) { -if (inode->i_ino ==MSDOS_ROOT_INO ) -return ERR_PTR (-ENOSPC ); - } +struct super_block *sb = dir->i_sb; +struct msdos_sb_info *sbi =MSDOS_SB (sb); +struct buffer_head *bhs[MAX_BUF_PER_PAGE ]; +sector_t blknr, start_blknr, last_blknr; +unsigned long size, copy; +int err, i, n, offset, cluster[2 ]; + +/* +* The minimum cluster size is 512bytes, and maximum entry +* size is 32*slots (672bytes). So, iff the cluster size is +* 512bytes, we may need two clusters. +*/ + size = nr_slots *sizeof (struct msdos_dir_entry ); + *nr_cluster = (size + (sbi->cluster_size -1 )) >> sbi->cluster_bits; +BUG_ON (*nr_cluster >2 ); - err =fat_alloc_clusters (inode, &cluster,1 ); + err =fat_alloc_clusters (dir, cluster, *nr_cluster);if (err) -return ERR_PTR (err); - err =fat_chain_add (inode, cluster,1 ); -if (err) { -fat_free_clusters (inode, cluster); -return ERR_PTR (err); - } + goto error; - sector =fat_clus_to_blknr (MSDOS_SB (sb), cluster); - last_sector = sector + sec_per_clus; -for ( ; sector < last_sector; sector++) { -if ((bh =sb_getblk (sb, sector))) { -memset (bh->b_data,0 , sb->s_blocksize); -set_buffer_uptodate (bh); -mark_buffer_dirty (bh); -if (sb->s_flags &MS_SYNCHRONOUS ) -sync_dirty_buffer (bh); -if (!res) - res = bh; -else -brelse (bh); +/* +* First stage: Fill the directory entry. NOTE: This cluster +* is not referenced from any inode yet, so updates order is +* not important. +*/ + i = n = copy =0 ; +do { + start_blknr = blknr =fat_clus_to_blknr (sbi, cluster[i]); + last_blknr = start_blknr + sbi->sec_per_clus; +while (blknr < last_blknr) { + bhs[n] =sb_getblk (sb, blknr); +if (!bhs[n]) { + err = -ENOMEM ; + goto error_nomem; + } + +/* fill the directory entry */ + copy =min (size, sb->s_blocksize); +memcpy (bhs[n]->b_data, slots, copy); + slots += copy; + size -= copy; +set_buffer_uptodate (bhs[n]); +mark_buffer_dirty (bhs[n]); +if (!size) +break ; + n++; + blknr++; } - } -if (res ==NULL ) - res =ERR_PTR (-EIO ); -if (inode->i_size & (sb->s_blocksize -1 )) { -fat_fs_panic (sb,"Odd directory size" ); - inode->i_size = (inode->i_size + sb->s_blocksize) - & ~((loff_t )sb->s_blocksize -1 ); - } - inode->i_size +=MSDOS_SB (sb)->cluster_size; -MSDOS_I (inode)->mmu_private +=MSDOS_SB (sb)->cluster_size; + }while (++i < *nr_cluster); -return res; -} +memset (bhs[n]->b_data + copy,0 , sb->s_blocksize - copy); + offset = copy -sizeof (struct msdos_dir_entry ); +get_bh (bhs[n]); + *bh = bhs[n]; + *de = (struct msdos_dir_entry *)((*bh)->b_data + offset); + *i_pos = ((loff_t )blknr << sbi->dir_per_block_bits) + (offset >>MSDOS_DIR_BITS ); -/* This assumes that size of cluster is above the 32*slots */ +/* Second stage: clear the rest of cluster, and write outs */ + err =fat_zeroed_cluster (dir, start_blknr, ++n, bhs,MAX_BUF_PER_PAGE ); +if (err) + goto error_free; -int fat_add_entries (struct inode *dir,int slots,struct buffer_head **bh, -struct msdos_dir_entry **de,loff_t *i_pos) -{ -struct super_block *sb = dir->i_sb; -loff_t offset, curr; -int row; -struct buffer_head *new_bh; +return cluster[0 ]; - offset = curr =0 ; +error_free: +brelse (*bh); *bh =NULL ; - row =0 ; -while (fat_get_entry (dir, &curr, bh, de, i_pos) >-1 ) { + n =0 ; +error_nomem: +for (i =0 ; i < n; i++) +bforget (bhs[i]); +fat_free_clusters (dir, cluster[0 ]); +error: +return err; +} + +int fat_add_entries (struct inode *dir,void *slots,int nr_slots, +struct fat_slot_info *sinfo) +{ +struct super_block *sb = dir->i_sb; +struct msdos_sb_info *sbi =MSDOS_SB (sb); +struct buffer_head *bh, *prev, *bhs[3 ];/* 32*slots (672bytes) */ +struct msdos_dir_entry *de; +int err, free_slots, i, nr_bhs; +loff_t pos, i_pos; + + sinfo->nr_slots = nr_slots; + +/* First stage: search free direcotry entries */ + free_slots = nr_bhs =0 ; + bh = prev =NULL ; + pos =0 ; + err = -ENOSPC ; +while (fat_get_entry (dir, &pos, &bh, &de, &i_pos) >-1 ) {/* check the maximum size of directory */ -if (curr >=FAT_MAX_DIR_SIZE ) { -brelse (*bh); -return -ENOSPC ; - } +if (pos >=FAT_MAX_DIR_SIZE ) + goto error; -if (IS_FREE ((*de)->name)) { -if (++row == slots) -return offset; +if (IS_FREE (de->name)) { +if (prev != bh) { +get_bh (bh); + bhs[nr_bhs] = prev = bh; + nr_bhs++; + } + free_slots++; +if (free_slots == nr_slots) + goto found; }else { - row =0 ; - offset = curr; +for (i =0 ; i < nr_bhs; i++) +brelse (bhs[i]); + prev =NULL ; + free_slots = nr_bhs =0 ; } } -if ((dir->i_ino ==MSDOS_ROOT_INO ) && (MSDOS_SB (sb)->fat_bits !=32 )) -return -ENOSPC ; - new_bh =fat_extend_dir (dir); -if (IS_ERR (new_bh)) -return PTR_ERR (new_bh); -brelse (new_bh); -do { -fat_get_entry (dir, &curr, bh, de, i_pos); - }while (++row < slots); +if ((dir->i_ino ==MSDOS_ROOT_INO ) && (sbi->fat_bits !=32 )) + goto error; + +found: + err =0 ; + pos -= free_slots *sizeof (*de); + nr_slots -= free_slots; +if (free_slots) { +/* +* Second stage: filling the free entries with new entries. +* NOTE: If this slots has shortname, first, we write +* the long name slots, then write the short name. +*/ +int size = free_slots *sizeof (*de); +int offset = pos & (sb->s_blocksize -1 ); +int long_bhs = nr_bhs - (nr_slots ==0 ); + +/* Fill the long name slots. */ +for (i =0 ; i < long_bhs; i++) { +int copy =min_t (int, sb->s_blocksize - offset, size); +memcpy (bhs[i]->b_data + offset, slots, copy); +mark_buffer_dirty (bhs[i]); + offset =0 ; + slots += copy; + size -= copy; + } +if (long_bhs &&IS_DIRSYNC (dir)) + err =fat_sync_bhs (bhs, long_bhs); +if (!err && i < nr_bhs) { +/* Fill the short name slot. */ +int copy =min_t (int, sb->s_blocksize - offset, size); +memcpy (bhs[i]->b_data + offset, slots, copy); +mark_buffer_dirty (bhs[i]); +if (IS_DIRSYNC (dir)) + err =sync_dirty_buffer (bhs[i]); + } +for (i =0 ; i < nr_bhs; i++) +brelse (bhs[i]); +if (err) + goto error_remove; + } + +if (nr_slots) { +int cluster, nr_cluster; -return offset; +/* +* Third stage: allocate the cluster for new entries. +* And initialize the cluster with new entries, then +* add the cluster to dir. +*/ + cluster =fat_add_new_entries (dir, slots, nr_slots, &nr_cluster, + &de, &bh, &i_pos); +if (cluster <0 ) { + err = cluster; + goto error_remove; + } + err =fat_chain_add (dir, cluster, nr_cluster); +if (err) { +fat_free_clusters (dir, cluster); + goto error_remove; + } +if (dir->i_size & (sbi->cluster_size -1 )) { +fat_fs_panic (sb,"Odd directory size" ); + dir->i_size = (dir->i_size + sbi->cluster_size -1 ) + & ~((loff_t )sbi->cluster_size -1 ); + } + dir->i_size += nr_cluster << sbi->cluster_bits; +MSDOS_I (dir)->mmu_private += nr_cluster << sbi->cluster_bits; + } + sinfo->slot_off = pos; + sinfo->i_pos = i_pos; + sinfo->de = de; + sinfo->bh = bh; + +return 0 ; + +error: +brelse (bh); +for (i =0 ; i < nr_bhs; i++) +brelse (bhs[i]); +return err; + +error_remove: +brelse (bh); +if (free_slots) +__fat_remove_entries (dir, pos, free_slots); +return err; }EXPORT_SYMBOL (fat_add_entries);
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync07-fat_dir6 +4 -9
@@ -258,7 +258,7 @@ static int msdos_add_entry(struct inode {struct msdos_dir_entry de;__le16 time, date; -int offset; +int err;memcpy (de.name, name,MSDOS_NAME ); de.attr = is_dir ?ATTR_DIR :ATTR_ARCH ;
@@ -273,14 +273,9 @@ static int msdos_add_entry(struct inode de.starthi =cpu_to_le16 (cluster >>16 ); de.size =0 ; - offset =fat_add_entries (dir,1 , &sinfo->bh, &sinfo->de, &sinfo->i_pos); -if (offset <0 ) -return offset; - sinfo->slot_off = offset; - sinfo->nr_slots =1 ; - -memcpy (sinfo->de, &de,sizeof (de)); -mark_buffer_dirty (sinfo->bh); + err =fat_add_entries (dir, &de,1 , sinfo); +if (err) +return err; dir->i_ctime = dir->i_mtime = *ts;mark_inode_dirty (dir);
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync07-fat_dir6 +3 -32
@@ -661,14 +661,9 @@ static int vfat_add_entry(struct inode * int cluster, struct timespec *ts, struct fat_slot_info *sinfo) { - struct super_block *sb = dir->i_sb; struct msdos_dir_slot *slots;unsigned int len; -int err, i, nr_slots; -loff_t offset; -struct msdos_dir_entry *de, *dummy_de; -struct buffer_head *bh, *dummy_bh; -loff_t dummy_i_pos; +int err, nr_slots; len =vfat_striptail_len (qname);if (len ==0 )
@@ -683,37 +678,13 @@ static int vfat_add_entry(struct inode *if (err) goto cleanup; -/* build the empty directory entry of number of slots */ - offset = -fat_add_entries (dir, nr_slots, &dummy_bh, &dummy_de, &dummy_i_pos); -if (offset <0 ) { - err = offset; + err =fat_add_entries (dir, slots, nr_slots, sinfo); +if (err) goto cleanup; - } -brelse (dummy_bh); - -/* Now create the new entry */ - bh =NULL ; -for (i =0 ; i < nr_slots; i++) { -if (fat_get_entry (dir, &offset, &bh, &de, &sinfo->i_pos) <0 ) { - err = -EIO ; - goto cleanup; - } -memcpy (de, slots + i,sizeof (struct msdos_dir_slot )); -mark_buffer_dirty (bh); -if (sb->s_flags &MS_SYNCHRONOUS ) -sync_dirty_buffer (bh); - }/* update timestamp */ dir->i_ctime = dir->i_mtime = dir->i_atime = *ts;mark_inode_dirty (dir); - -/* slots can't be less than 1 */ - sinfo->slot_off = offset -sizeof (struct msdos_dir_slot ) * nr_slots; - sinfo->nr_slots = nr_slots; - sinfo->de = de; - sinfo->bh = bh; cleanup:kfree (slots);return err;
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync07-fat_dir6 +2 -3
@@ -324,9 +324,6 @@ extern int fat_bmap(struct inode *inode,extern struct file_operations fat_dir_operations;extern int fat_search_long (struct inode *inode,const unsigned char *name,int name_len,struct fat_slot_info *sinfo); -extern int fat_add_entries (struct inode *dir,int slots, -struct buffer_head **bh, -struct msdos_dir_entry **de,loff_t *i_pos);extern int fat_dir_empty (struct inode *dir);extern int fat_subdirs (struct inode *dir); extern int fat_scan(struct inode *dir, const unsigned char *name,
@@ -334,6 +331,8 @@ extern int fat_scan(struct inode *dir, cextern int fat_get_dotdot_entry (struct inode *dir,struct buffer_head **bh,struct msdos_dir_entry **de,loff_t *i_pos);extern int fat_alloc_new_dir (struct inode *dir,struct timespec *ts); +extern int fat_add_entries (struct inode *dir,void *slots,int nr_slots, +struct fat_slot_info *sinfo);extern int fat_remove_entries (struct inode *dir,struct fat_slot_info *sinfo);/* fat/fatent.c */
_
OGAWA Hirofumi
maintainerPATCH 20/29 FAT: Use fat_remove_entries() for msdos
---
fs/msdos/namei.c | 37 +++++++++++++++++-------------------- 1 files changed, 17 insertions(+), 20 deletions(-)
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync07-fat_dir7 +17 -20
@@ -346,16 +346,15 @@ static int msdos_rmdir(struct inode *dirif (err) goto out; - sinfo.de->name[0 ] =DELETED_FLAG ; -mark_buffer_dirty (sinfo.bh); -brelse (sinfo.bh); -fat_detach (inode); + err =fat_remove_entries (dir, &sinfo);/* and releases bh */ +if (err) + goto out; + dir->i_nlink--; + inode->i_nlink =0 ; - inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ; + inode->i_ctime =CURRENT_TIME_SEC ; +fat_detach (inode);mark_inode_dirty (inode); - - dir->i_nlink--; -mark_inode_dirty (dir); out:unlock_kernel ();
@@ -430,18 +429,16 @@ static int msdos_unlink(struct inode *dilock_kernel (); err =msdos_find (dir, dentry->d_name.name, dentry->d_name.len, &sinfo);if (err) - goto unlink_done; + goto out; - sinfo.de->name[0 ] =DELETED_FLAG ; -mark_buffer_dirty (sinfo.bh); -brelse (sinfo.bh); -fat_detach (inode); + err =fat_remove_entries (dir, &sinfo);/* and releases bh */ +if (err) + goto out; inode->i_nlink =0 ; - inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ; + inode->i_ctime =CURRENT_TIME_SEC ; +fat_detach (inode);mark_inode_dirty (inode); - -mark_inode_dirty (dir); -unlink_done: +out:unlock_kernel ();return err;
@@ -526,10 +523,10 @@ static int do_msdos_rename(struct inode } new_dir->i_version++; - old_sinfo.de->name[0 ] =DELETED_FLAG ; -mark_buffer_dirty (old_sinfo.bh); -brelse (old_sinfo.bh); + err =fat_remove_entries (old_dir, &old_sinfo);/* and releases bh */ old_sinfo.bh =NULL ; +if (err) + goto out;if (is_dir) old_dir->i_nlink--;fat_detach (old_inode);
_
OGAWA Hirofumi
maintainerPATCH 21/29 FAT: make the fat_get_entry()/fat__get_entry() the static
---
fs/fat/dir.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ fs/fat/misc.c | 50 ------------------------------------- include/linux/msdos_fs.h | 17 ------------ 3 files changed, 63 insertions(+), 67 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~sync08-fat_tweak1 +63 -0
@@ -22,6 +22,69 @@#include <linux/buffer_head.h> #include <asm/uaccess.h> +/* Returns the inode number of the directory entry at offset pos. If bh is +non-NULL, it is brelse'd before. Pos is incremented. The buffer header is +returned in bh. +AV. Most often we do it item-by-item. Makes sense to optimize. +AV. OK, there we go: if both bh and de are non-NULL we assume that we just +AV. want the next entry (took one explicit de=NULL in vfat/namei.c). +AV. It's done in fat_get_entry() (inlined), here the slow case lives. +AV. Additionally, when we return -1 (i.e. reached the end of directory) +AV. we make bh NULL. +*/ +static int fat__get_entry (struct inode *dir,loff_t *pos, +struct buffer_head **bh, +struct msdos_dir_entry **de,loff_t *i_pos) +{ +struct super_block *sb = dir->i_sb; +struct msdos_sb_info *sbi =MSDOS_SB (sb); +sector_t phys, iblock; +loff_t offset; +int err; + +next: + offset = *pos; +if (*bh) +brelse (*bh); + + *bh =NULL ; + iblock = *pos >> sb->s_blocksize_bits; + err =fat_bmap (dir, iblock, &phys); +if (err || !phys) +return -1 ;/* beyond EOF or error */ + + *bh =sb_bread (sb, phys); +if (*bh ==NULL ) { +printk (KERN_ERR "FAT: Directory bread(block %llu) failed\n" , + (unsigned long long )phys); +/* skip this block */ + *pos = (iblock +1 ) << sb->s_blocksize_bits; + goto next; + } + + offset &= sb->s_blocksize -1 ; + *pos +=sizeof (struct msdos_dir_entry ); + *de = (struct msdos_dir_entry *)((*bh)->b_data + offset); + *i_pos = ((loff_t )phys << sbi->dir_per_block_bits) + (offset >>MSDOS_DIR_BITS ); + +return 0 ; +} + +static inline int fat_get_entry (struct inode *dir,loff_t *pos, +struct buffer_head **bh, +struct msdos_dir_entry **de,loff_t *i_pos) +{ +/* Fast stuff first */ +if (*bh && *de && + (*de - (struct msdos_dir_entry *)(*bh)->b_data) <MSDOS_SB (dir->i_sb)->dir_per_block -1 ) { + *pos +=sizeof (struct msdos_dir_entry ); + (*de)++; + (*i_pos)++; +return 0 ; + } +return fat__get_entry (dir, pos, bh, de, i_pos); +} +/* * Convert Unicode 16 to UTF8, translated Unicode, or ASCII. * If uni_xlate is enabled and we can't get a 1:1 conversion, use a
fs/fat/misc.c renamed from fs/fat/misc.c~sync08-fat_tweak1 +0 -50
56 lines not on this page · raw message
include/linux/msdos_fs.h renamed from include/linux/msdos_fs.h~sync08-fat_tweak1 +0 -17
@@ -405,23 +405,6 @@ extern void fat_clusters_flush(struct suextern int fat_chain_add (struct inode *inode,int new_dclus,int nr_cluster);extern int date_dos2unix (unsigned short time,unsigned short date);extern void fat_date_unix2dos (int unix_date,__le16 *time,__le16 *date); -extern int fat__get_entry (struct inode *dir,loff_t *pos, -struct buffer_head **bh, -struct msdos_dir_entry **de,loff_t *i_pos); -static __inline__int fat_get_entry (struct inode *dir,loff_t *pos, -struct buffer_head **bh, -struct msdos_dir_entry **de,loff_t *i_pos) -{ -/* Fast stuff first */ -if (*bh && *de && - (*de - (struct msdos_dir_entry *)(*bh)->b_data) <MSDOS_SB (dir->i_sb)->dir_per_block -1 ) { - *pos +=sizeof (struct msdos_dir_entry ); - (*de)++; - (*i_pos)++; -return 0 ; - } -return fat__get_entry (dir, pos, bh, de, i_pos); -}extern int fat_sync_bhs (struct buffer_head **bhs,int nr_bhs);#endif /* __KERNEL__ */
_
OGAWA Hirofumi
maintainerPATCH 22/29 FAT: "i_pos" cleanup
The "i_pos" can calculate later, so this makes the "i_pos" when it's needed.
---
fs/fat/dir.c | 70 ++++++++++++++++++++++++++++++++--------------------------- 1 files changed, 39 insertions(+), 31 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~sync08-fat_tweak2 +39 -31
@@ -22,6 +22,14 @@#include <linux/buffer_head.h> #include <asm/uaccess.h> +static inline loff_t fat_make_i_pos (struct super_block *sb, +struct buffer_head *bh, +struct msdos_dir_entry *de) +{ +return ((loff_t )bh->b_blocknr <<MSDOS_SB (sb)->dir_per_block_bits) + | (de - (struct msdos_dir_entry *)bh->b_data); +} +/* Returns the inode number of the directory entry at offset pos. If bh is non-NULL, it is brelse'd before. Pos is incremented. The buffer header is returned in bh.
@@ -33,17 +41,14 @@AV. we make bh NULL. */ static int fat__get_entry (struct inode *dir,loff_t *pos, -struct buffer_head **bh, -struct msdos_dir_entry **de,loff_t *i_pos) +struct buffer_head **bh,struct msdos_dir_entry **de) {struct super_block *sb = dir->i_sb; -struct msdos_sb_info *sbi =MSDOS_SB (sb);sector_t phys, iblock; -loff_t offset; +int offset;int err; next: - offset = *pos;if (*bh)brelse (*bh);
@@ -62,27 +67,25 @@ next: goto next; } - offset &= sb->s_blocksize -1 ; + offset = *pos & (sb->s_blocksize -1 ); *pos +=sizeof (struct msdos_dir_entry ); *de = (struct msdos_dir_entry *)((*bh)->b_data + offset); - *i_pos = ((loff_t )phys << sbi->dir_per_block_bits) + (offset >>MSDOS_DIR_BITS );return 0 ; }static inline int fat_get_entry (struct inode *dir,loff_t *pos,struct buffer_head **bh, -struct msdos_dir_entry **de,loff_t *i_pos) +struct msdos_dir_entry **de) {/* Fast stuff first */ if (*bh && *de && (*de - (struct msdos_dir_entry *)(*bh)->b_data) <MSDOS_SB (dir->i_sb)->dir_per_block -1 ) { *pos +=sizeof (struct msdos_dir_entry ); (*de)++; - (*i_pos)++;return 0 ; } -return fat__get_entry (dir, pos, bh, de, i_pos); +return fat__get_entry (dir, pos, bh, de); }/*
@@ -214,12 +217,12 @@ int fat_search_long(struct inode *inode,int utf8 =MSDOS_SB (sb)->options.utf8;int anycase = (MSDOS_SB (sb)->options.name_check !='s' );unsigned short opt_shortname =MSDOS_SB (sb)->options.shortname; +loff_t cpos =0 ;int chl, i, j, last_u, err; -loff_t i_pos, cpos =0 ; err = -ENOENT ;while (1 ) { -if (fat_get_entry (inode, &cpos, &bh, &de, &i_pos) ==-1 ) +if (fat_get_entry (inode, &cpos, &bh, &de) ==-1 ) goto EODir; parse_record: nr_slots =0 ;
@@ -270,7 +273,7 @@ parse_long:if (ds->id &0x40 ) { unicode[offset +13 ] =0 ; } -if (fat_get_entry (inode,&cpos,&bh,&de,&i_pos)<0 ) +if (fat_get_entry (inode, &cpos, &bh, &de) <0 ) goto EODir;if (slot ==0 )break ;
@@ -354,11 +357,11 @@ parse_long: Found: nr_slots++;/* include the de */ - sinfo->i_pos = i_pos; sinfo->slot_off = cpos - nr_slots *sizeof (*de); sinfo->nr_slots = nr_slots; sinfo->de = de; sinfo->bh = bh; + sinfo->i_pos =fat_make_i_pos (sb, sinfo->bh, sinfo->de); err =0 ; EODir:if (unicode)
@@ -401,7 +404,7 @@ static int fat_readdirx(struct inode *inunsigned short opt_shortname =MSDOS_SB (sb)->options.shortname;unsigned long inum;int chi, chl, i, i2, j, last, last_u, dotoffset =0 ; -loff_t i_pos, cpos; +loff_t cpos;int ret =0 ;lock_kernel ();
@@ -429,7 +432,7 @@ static int fat_readdirx(struct inode *in bh =NULL ; GetNew: long_slots =0 ; -if (fat_get_entry (inode,&cpos,&bh,&de,&i_pos) ==-1 ) +if (fat_get_entry (inode, &cpos, &bh, &de) ==-1 ) goto EODir;/* Check for long filename entry */ if (isvfat) {
@@ -486,7 +489,7 @@ ParseLong:if (ds->id &0x40 ) { unicode[offset +13 ] =0 ; } -if (fat_get_entry (inode,&cpos,&bh,&de,&i_pos) ==-1 ) +if (fat_get_entry (inode, &cpos, &bh, &de) ==-1 ) goto EODir;if (slot ==0 )break ;
@@ -578,6 +581,7 @@ ParseLong:else if (!memcmp (de->name,MSDOS_DOTDOT ,MSDOS_NAME )) { inum =parent_ino (filp->f_dentry); }else { +loff_t i_pos =fat_make_i_pos (sb, bh, de);struct inode *tmp =fat_iget (sb, i_pos);if (tmp) { inum = tmp->i_ino;
@@ -748,9 +752,9 @@ struct file_operations fat_dir_operationstatic int fat_get_short_entry (struct inode *dir,loff_t *pos,struct buffer_head **bh, -struct msdos_dir_entry **de,loff_t *i_pos) +struct msdos_dir_entry **de) { -while (fat_get_entry (dir, pos, bh, de, i_pos) >=0 ) { +while (fat_get_entry (dir, pos, bh, de) >=0 ) {/* free entry or long name entry or volume label */ if (!IS_FREE ((*de)->name) && !((*de)->attr &ATTR_VOLUME ))return 0 ;
@@ -769,9 +773,11 @@ int fat_get_dotdot_entry(struct inode *d offset =0 ; *bh =NULL ; -while (fat_get_short_entry (dir, &offset, bh, de, i_pos) >=0 ) { -if (!strncmp ((*de)->name,MSDOS_DOTDOT ,MSDOS_NAME )) +while (fat_get_short_entry (dir, &offset, bh, de) >=0 ) { +if (!strncmp ((*de)->name,MSDOS_DOTDOT ,MSDOS_NAME )) { + *i_pos =fat_make_i_pos (dir->i_sb, *bh, *de);return 0 ; + } }return -ENOENT ; }
@@ -783,12 +789,12 @@ int fat_dir_empty(struct inode *dir) {struct buffer_head *bh;struct msdos_dir_entry *de; -loff_t cpos, i_pos; +loff_t cpos;int result =0 ; bh =NULL ; cpos =0 ; -while (fat_get_short_entry (dir, &cpos, &bh, &de, &i_pos) >=0 ) { +while (fat_get_short_entry (dir, &cpos, &bh, &de) >=0 ) {if (strncmp (de->name,MSDOS_DOT ,MSDOS_NAME ) &&strncmp (de->name,MSDOS_DOTDOT ,MSDOS_NAME )) { result = -ENOTEMPTY ;
@@ -809,12 +815,12 @@ int fat_subdirs(struct inode *dir) {struct buffer_head *bh;struct msdos_dir_entry *de; -loff_t cpos, i_pos; +loff_t cpos;int count =0 ; bh =NULL ; cpos =0 ; -while (fat_get_short_entry (dir, &cpos, &bh, &de, &i_pos) >=0 ) { +while (fat_get_short_entry (dir, &cpos, &bh, &de) >=0 ) {if (de->attr &ATTR_DIR ) count++; }
@@ -829,13 +835,16 @@ int fat_subdirs(struct inode *dir)int fat_scan (struct inode *dir,const unsigned char *name,struct fat_slot_info *sinfo) { +struct super_block *sb = dir->i_sb; + sinfo->slot_off =0 ; sinfo->bh =NULL ;while (fat_get_short_entry (dir, &sinfo->slot_off, &sinfo->bh, - &sinfo->de, &sinfo->i_pos) >=0 ) { + &sinfo->de) >=0 ) {if (!strncmp (sinfo->de->name, name,MSDOS_NAME )) { sinfo->slot_off -=sizeof (*sinfo->de); sinfo->nr_slots =1 ; + sinfo->i_pos =fat_make_i_pos (sb, sinfo->bh, sinfo->de);return 0 ; } }
@@ -849,12 +858,11 @@ static int __fat_remove_entries(struct istruct super_block *sb = dir->i_sb;struct buffer_head *bh;struct msdos_dir_entry *de, *endp; -loff_t i_pos;int err =0 , orig_slots;while (nr_slots) { bh =NULL ; -if (fat_get_entry (dir, &pos, &bh, &de, &i_pos) <0 ) { +if (fat_get_entry (dir, &pos, &bh, &de) <0 ) { err = -EIO ;break ; }
@@ -1103,7 +1111,7 @@ static int fat_add_new_entries(struct inget_bh (bhs[n]); *bh = bhs[n]; *de = (struct msdos_dir_entry *)((*bh)->b_data + offset); - *i_pos = ((loff_t )blknr << sbi->dir_per_block_bits) + (offset >>MSDOS_DIR_BITS ); + *i_pos =fat_make_i_pos (sb, *bh, *de);/* Second stage: clear the rest of cluster, and write outs */ err =fat_zeroed_cluster (dir, start_blknr, ++n, bhs,MAX_BUF_PER_PAGE );
@@ -1141,7 +1149,7 @@ int fat_add_entries(struct inode *dir, v bh = prev =NULL ; pos =0 ; err = -ENOSPC ; -while (fat_get_entry (dir, &pos, &bh, &de, &i_pos) >-1 ) { +while (fat_get_entry (dir, &pos, &bh, &de) >-1 ) {/* check the maximum size of directory */ if (pos >=FAT_MAX_DIR_SIZE ) goto error;
@@ -1232,9 +1240,9 @@ found:MSDOS_I (dir)->mmu_private += nr_cluster << sbi->cluster_bits; } sinfo->slot_off = pos; - sinfo->i_pos = i_pos; sinfo->de = de; sinfo->bh = bh; + sinfo->i_pos =fat_make_i_pos (sb, sinfo->bh, sinfo->de);return 0 ;
_
OGAWA Hirofumi
maintainerPATCH 23/29 FAT: Remove the multiple MSDOS_SB() call
Since MSDOS_SB() is inline function, it increases text size at each calls. I don't know whether there is __attribute__ for avoiding this.
This removes the multiple call.
---
fs/fat/dir.c | 30 ++++++++++++++++-------------- fs/vfat/namei.c | 8 ++++---- 2 files changed, 20 insertions(+), 18 deletions(-)
fs/fat/dir.c renamed from fs/fat/dir.c~sync08-fat_tweak3 +16 -14
@@ -205,18 +205,19 @@ int fat_search_long(struct inode *inode, int name_len, struct fat_slot_info *sinfo) { struct super_block *sb = inode->i_sb; +struct msdos_sb_info *sbi =MSDOS_SB (sb);struct buffer_head *bh =NULL ;struct msdos_dir_entry *de; -struct nls_table *nls_io =MSDOS_SB (sb)->nls_io; -struct nls_table *nls_disk =MSDOS_SB (sb)->nls_disk; +struct nls_table *nls_io = sbi->nls_io; +struct nls_table *nls_disk = sbi->nls_disk;wchar_t bufuname[14 ];unsigned char xlate_len, nr_slots;wchar_t *unicode =NULL ;unsigned char work[8 ], bufname[260 ];/* 256 + 4 */ -int uni_xlate =MSDOS_SB (sb)->options.unicode_xlate; -int utf8 =MSDOS_SB (sb)->options.utf8; -int anycase = (MSDOS_SB (sb)->options.name_check !='s' ); -unsigned short opt_shortname =MSDOS_SB (sb)->options.shortname; +int uni_xlate = sbi->options.unicode_xlate; +int utf8 = sbi->options.utf8; +int anycase = (sbi->options.name_check !='s' ); +unsigned short opt_shortname = sbi->options.shortname;loff_t cpos =0 ;int chl, i, j, last_u, err;
@@ -386,10 +387,11 @@ static int fat_readdirx(struct inode *in filldir_t filldir, int short_only, int both) { struct super_block *sb = inode->i_sb; +struct msdos_sb_info *sbi =MSDOS_SB (sb);struct buffer_head *bh;struct msdos_dir_entry *de; -struct nls_table *nls_io =MSDOS_SB (sb)->nls_io; -struct nls_table *nls_disk =MSDOS_SB (sb)->nls_disk; +struct nls_table *nls_io = sbi->nls_io; +struct nls_table *nls_disk = sbi->nls_disk;unsigned char long_slots;const char *fill_name;int fill_len;
@@ -397,11 +399,11 @@ static int fat_readdirx(struct inode *inwchar_t *unicode =NULL ;unsigned char c, work[8 ], bufname[56 ], *ptname = bufname;unsigned long lpos, dummy, *furrfu = &lpos; -int uni_xlate =MSDOS_SB (sb)->options.unicode_xlate; -int isvfat =MSDOS_SB (sb)->options.isvfat; -int utf8 =MSDOS_SB (sb)->options.utf8; -int nocase =MSDOS_SB (sb)->options.nocase; -unsigned short opt_shortname =MSDOS_SB (sb)->options.shortname; +int uni_xlate = sbi->options.unicode_xlate; +int isvfat = sbi->options.isvfat; +int utf8 = sbi->options.utf8; +int nocase = sbi->options.nocase; +unsigned short opt_shortname = sbi->options.shortname;unsigned long inum;int chi, chl, i, i2, j, last, last_u, dotoffset =0 ;loff_t cpos;
@@ -513,7 +515,7 @@ ParseLong: long_slots =0 ; } -if (MSDOS_SB (sb)->options.dotsOK) { +if (sbi->options.dotsOK) { ptname = bufname; dotoffset =0 ;if (de->attr &ATTR_HIDDEN ) {
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync08-fat_tweak3 +4 -4
@@ -301,6 +301,7 @@ static int vfat_create_shortname(struct wchar_t *uname, int ulen, unsigned char *name_res, unsigned char *lcase) { + struct fat_mount_options *opts = &MSDOS_SB(dir->i_sb)->options;wchar_t *ip, *ext_start, *end, *name_start;unsigned char base[9 ], ext[4 ], buf[8 ], *p;unsigned char charbuf[NLS_MAX_CHARSET_SIZE ];
@@ -308,7 +309,6 @@ static int vfat_create_shortname(structint sz =0 , extlen, baselen, i, numtail_baselen, numtail2_baselen;int is_shortname;struct shortname_info base_info, ext_info; -unsigned short opt_shortname =MSDOS_SB (dir->i_sb)->options.shortname; is_shortname =1 ;INIT_SHORTNAME_INFO (&base_info);
@@ -421,9 +421,9 @@ static int vfat_create_shortname(structif (vfat_find_form (dir, name_res) ==0 )return -EEXIST ; -if (opt_shortname &VFAT_SFN_CREATE_WIN95 ) { +if (opts->shortname &VFAT_SFN_CREATE_WIN95 ) {return (base_info.upper && ext_info.upper); - }else if (opt_shortname &VFAT_SFN_CREATE_WINNT ) { + }else if (opts->shortname &VFAT_SFN_CREATE_WINNT ) {if ((base_info.upper || base_info.lower) && (ext_info.upper || ext_info.lower)) {if (!base_info.upper && base_info.lower)
@@ -438,7 +438,7 @@ static int vfat_create_shortname(struct } } -if (MSDOS_SB (dir->i_sb)->options.numtail ==0 ) +if (opts->numtail ==0 )if (vfat_find_form (dir, name_res) <0 )return 0 ;
_
OGAWA Hirofumi
maintainerPATCH 24/29 FAT: Remove unneed mark_inode_dirty()
Some mark_inode_dirty() is unneeded. Those are already detached (it's not written) or change a ->i_nlink count only (fatfs don't have).
---
fs/msdos/namei.c | 11 +++-------- fs/vfat/namei.c | 10 +++------- 2 files changed, 6 insertions(+), 15 deletions(-)
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync08-fat_tweak4 +3 -8
@@ -354,7 +354,6 @@ static int msdos_rmdir(struct inode *dir inode->i_nlink =0 ; inode->i_ctime =CURRENT_TIME_SEC ;fat_detach (inode); -mark_inode_dirty (inode); out:unlock_kernel ();
@@ -403,7 +402,7 @@ static int msdos_mkdir(struct inode *dir/* the directory was completed, just return a error */ goto out; } - inode->i_nlink =2 ;/* no need to mark them dirty */ + inode->i_nlink =2 ; inode->i_mtime = inode->i_atime = inode->i_ctime = ts;/* timestamp is already written, so mark_inode_dirty() is unneeded. */
@@ -437,7 +436,6 @@ static int msdos_unlink(struct inode *di inode->i_nlink =0 ; inode->i_ctime =CURRENT_TIME_SEC ;fat_detach (inode); -mark_inode_dirty (inode); out:unlock_kernel ();
@@ -544,7 +542,6 @@ static int do_msdos_rename(struct inodeif (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = ts; -mark_inode_dirty (new_inode); }if (is_dir) {int start =MSDOS_I (new_dir)->i_logstart;
@@ -552,12 +549,10 @@ static int do_msdos_rename(struct inode dotdot_de->starthi =cpu_to_le16 (start >>16 );mark_buffer_dirty (dotdot_bh); -if (new_inode) { +if (new_inode) new_inode->i_nlink--; - }else { +else new_dir->i_nlink++; -mark_inode_dirty (new_dir); - } } out:brelse (dotdot_bh);
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync08-fat_tweak4 +3 -7
@@ -803,7 +803,6 @@ static int vfat_rmdir(struct inode *dir, inode->i_nlink =0 ; inode->i_mtime = inode->i_atime =CURRENT_TIME_SEC ;fat_detach (inode); -mark_inode_dirty (inode); out:unlock_kernel ();
@@ -828,7 +827,6 @@ static int vfat_unlink(struct inode *dir inode->i_nlink =0 ; inode->i_mtime = inode->i_atime =CURRENT_TIME_SEC ;fat_detach (inode); -mark_inode_dirty (inode); out:unlock_kernel ();
@@ -865,7 +863,7 @@ static int vfat_mkdir(struct inode *dir, goto out; } inode->i_version++; - inode->i_nlink =2 ;/* no need to mark them dirty */ + inode->i_nlink =2 ; inode->i_mtime = inode->i_atime = inode->i_ctime = ts;/* timestamp is already written, so mark_inode_dirty() is unneeded. */
@@ -964,12 +962,10 @@ static int vfat_rename(struct inode *oldif (new_dir->i_sb->s_flags &MS_SYNCHRONOUS )sync_dirty_buffer (dotdot_bh); -if (new_inode) { +if (new_inode) new_inode->i_nlink--; - }else { +else new_dir->i_nlink++; -mark_inode_dirty (new_dir); - } } out:brelse (dotdot_bh);
_
OGAWA Hirofumi
maintainerPATCH 25/29 FAT: Fix fat_truncate()
Instead of
mark_inode_dirty(inode); if (IS_SYNC(inode)) fat_sync_inode(inode);
use this
if (IS_SYNC(inode)) fat_sync_inode(inode); else mark_inode_dirty(inode);
And if occurs a error, restore the ->i_start and ->i_logstart.
---
fs/fat/file.c | 40 +++++++++++++++++++++++----------------- 1 files changed, 23 insertions(+), 17 deletions(-)
fs/fat/file.c renamed from fs/fat/file.c~sync08-fat_tweak5 +23 -17
@@ -212,7 +212,7 @@ EXPORT_SYMBOL(fat_notify_change);static int fat_free (struct inode *inode,int skip) {struct super_block *sb = inode->i_sb; -int ret, wait; +int err, wait, free_start, i_start, i_logstart;if (MSDOS_I (inode)->i_start ==0 )return 0 ;
@@ -223,7 +223,7 @@ static int fat_free(struct inode *inode, wait =IS_DIRSYNC (inode);if (skip) {struct fat_entry fatent; -int fclus, dclus; +int ret, fclus, dclus; ret =fat_get_cluster (inode, skip -1 , &fclus, &dclus);if (ret <0 )
@@ -242,8 +242,7 @@ static int fat_free(struct inode *inode, __FUNCTION__, MSDOS_I(inode)->i_pos); ret = -EIO ; }else if (ret >0 ) { -int err =fat_ent_write (inode, &fatent,FAT_ENT_EOF , - wait); + err =fat_ent_write (inode, &fatent,FAT_ENT_EOF , wait);if (err) ret = err; }
@@ -251,24 +250,36 @@ static int fat_free(struct inode *inode,if (ret <0 )return ret; + free_start = ret; + i_start = i_logstart =0 ;fat_cache_inval_inode (inode); }else {fat_cache_inval_inode (inode); - ret =MSDOS_I (inode)->i_start; + i_start = free_start =MSDOS_I (inode)->i_start; + i_logstart =MSDOS_I (inode)->i_logstart;MSDOS_I (inode)->i_start =0 ;MSDOS_I (inode)->i_logstart =0 ; -if (wait) { -int err =fat_sync_inode (inode); -if (err) -return err; - }else -mark_inode_dirty (inode); } +MSDOS_I (inode)->i_attrs |=ATTR_ARCH ; + inode->i_ctime = inode->i_mtime =CURRENT_TIME_SEC ; +if (wait) { + err =fat_sync_inode (inode); +if (err) + goto error; + }else +mark_inode_dirty (inode); inode->i_blocks = skip << (MSDOS_SB (sb)->cluster_bits -9 );/* Freeing the remained cluster chain */ -return fat_free_clusters (inode, ret); +return fat_free_clusters (inode, free_start); + +error: +if (i_start) { +MSDOS_I (inode)->i_start = i_start; +MSDOS_I (inode)->i_logstart = i_logstart; + } +return err; }void fat_truncate (struct inode *inode)
@@ -288,12 +299,7 @@ void fat_truncate(struct inode *inode)lock_kernel ();fat_free (inode, nr_clusters); -MSDOS_I (inode)->i_attrs |=ATTR_ARCH ;unlock_kernel (); - inode->i_ctime = inode->i_mtime =CURRENT_TIME_SEC ; -mark_inode_dirty (inode); -if (IS_SYNC (inode)) -fat_sync_inode (inode); }struct inode_operations fat_file_inode_operations = {
_
OGAWA Hirofumi
maintainerPATCH 26/29 FAT: Fix fat_write_inode()
Fix a missing error check for sync_buffer_dirty().
---
fs/fat/inode.c | 18 ++++++++++-------- 1 files changed, 10 insertions(+), 8 deletions(-)
fs/fat/inode.c renamed from fs/fat/inode.c~sync08-fat_tweak6 +10 -8
@@ -463,18 +463,20 @@ static int fat_write_inode(struct inodestruct buffer_head *bh;struct msdos_dir_entry *raw_entry;loff_t i_pos; +int err =0 ; retry: i_pos =MSDOS_I (inode)->i_pos; -if (inode->i_ino ==MSDOS_ROOT_INO || !i_pos) { +if (inode->i_ino ==MSDOS_ROOT_INO || !i_pos)return 0 ; - } +lock_kernel (); -if (!(bh =sb_bread (sb, i_pos >> sbi->dir_per_block_bits))) { + bh =sb_bread (sb, i_pos >> sbi->dir_per_block_bits); +if (!bh) {printk (KERN_ERR "FAT: unable to read inode block " "for updating (i_pos %lld)\n" , i_pos); -unlock_kernel (); -return -EIO ; + err = -EIO ; + goto out; }spin_lock (&sbi->inode_hash_lock);if (i_pos !=MSDOS_I (inode)->i_pos) {
@@ -502,11 +504,11 @@ retry:spin_unlock (&sbi->inode_hash_lock);mark_buffer_dirty (bh);if (wait) -sync_dirty_buffer (bh); + err =sync_dirty_buffer (bh);brelse (bh); +out:unlock_kernel (); - -return 0 ; +return err; }int fat_sync_inode (struct inode *inode)
_
OGAWA Hirofumi
maintainerPATCH 27/29 FAT: Use synchronous update for {vfat,msdos}_add_entry()
Use the synchronous updates, in order to guarantee that the writing to a disk is completeing when a system call returns.
---
fs/msdos/namei.c | 5 ++++- fs/vfat/namei.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-)
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync08-fat_tweak7 +4 -1
@@ -278,7 +278,10 @@ static int msdos_add_entry(struct inodereturn err; dir->i_ctime = dir->i_mtime = *ts; -mark_inode_dirty (dir); +if (IS_DIRSYNC (dir)) + (void )fat_sync_inode (dir); +else +mark_inode_dirty (dir);return 0 ; }
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync08-fat_tweak7 +4 -1
@@ -684,7 +684,10 @@ static int vfat_add_entry(struct inode */* update timestamp */ dir->i_ctime = dir->i_mtime = dir->i_atime = *ts; -mark_inode_dirty (dir); +if (IS_DIRSYNC (dir)) + (void )fat_sync_inode (dir); +else +mark_inode_dirty (dir); cleanup:kfree (slots);return err;
_
OGAWA Hirofumi
maintainerPATCH 28/29 FAT: Update ->rename() path
a) If old_dir == new_dir, we don't need to update the ".." entry, so this doesn't touch it if unneeded.
b) old algorithm is using
1) add a new entry (doen't point the data cluster yet).
2) remove a old entry.
3) switch the data cluster to new entry.
4) update a ".." entry
this order lose the data cluster when between 2) and 3).
Instead of above, this is using
1) add a new entry (doen't point the data cluster yet).
2) switch the data cluster to new entry.
3) update a ".." entry if needed.
4) remove a old entry.
this order would not lose the data cluster, but on disk metadata is corrupted on some point (later, fsck would recover this corruption without losing the data).
c) use synchronous update.
d) Fix the corrupted directory check created by 1 of new algorithm.
1) Fix fat_bmap(). If directory's ->i_start == 0, fat_bmap() is handling it as root directory, this removes that strange behavior.
2) On mkdir() path if directory's ->i_start == 0, returns -EIO.
---
fs/fat/cache.c | 4 - fs/fat/dir.c | 9 +++- fs/fat/misc.c | 2 fs/msdos/namei.c | 112 ++++++++++++++++++++++++++++++++++++++++++------------- fs/vfat/namei.c | 101 +++++++++++++++++++++++++++++++++++-------------- 5 files changed, 170 insertions(+), 58 deletions(-)
fs/fat/cache.c renamed from fs/fat/cache.c~sync08-fat_tweak8 +1 -3
@@ -303,9 +303,7 @@ int fat_bmap(struct inode *inode, sectorint cluster, offset; *phys =0 ; -if ((sbi->fat_bits !=32 ) && - (inode->i_ino ==MSDOS_ROOT_INO || (S_ISDIR (inode->i_mode) && - !MSDOS_I (inode)->i_start))) { +if ((sbi->fat_bits !=32 ) && (inode->i_ino ==MSDOS_ROOT_INO )) {if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits)) *phys = sector + sbi->dir_start;return 0 ;
fs/fat/dir.c renamed from fs/fat/dir.c~sync08-fat_tweak8 +8 -1
@@ -1172,8 +1172,15 @@ int fat_add_entries(struct inode *dir, v free_slots = nr_bhs =0 ; } } -if ((dir->i_ino ==MSDOS_ROOT_INO ) && (sbi->fat_bits !=32 )) +if (dir->i_ino ==MSDOS_ROOT_INO ) { +if (sbi->fat_bits !=32 ) + goto error; + }else if (MSDOS_I (dir)->i_start ==0 ) { +printk (KERN_ERR "FAT: Corrupted directory (i_pos %lld)\n" , +MSDOS_I (dir)->i_pos); + err = -EIO ; goto error; + } found: err =0 ;
fs/fat/misc.c renamed from fs/fat/misc.c~sync08-fat_tweak8 +2 -0
@@ -33,6 +33,8 @@ void fat_fs_panic(struct super_block *s, } } +EXPORT_SYMBOL (fat_fs_panic); +/* Flushes the number of free clusters on FAT32 */ /* XXX: Need to write one per FSINFO block. Currently only writes 1 */ void fat_clusters_flush (struct super_block *sb)
fs/msdos/namei.c renamed from fs/msdos/namei.c~sync08-fat_tweak8 +86 -26
169 lines not on this page · raw message
fs/vfat/namei.c renamed from fs/vfat/namei.c~sync08-fat_tweak8 +73 -28
150 lines not on this page · raw message
_
OGAWA Hirofumi
maintainerPATCH 29/29 FAT: Fix typo
Add a `:'.
---
fs/fat/misc.c | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-)
fs/fat/misc.c renamed from fs/fat/misc.c~sync08-fat_tweak9 +1 -1
@@ -48,7 +48,7 @@ void fat_clusters_flush(struct super_blo bh =sb_bread (sb, sbi->fsinfo_sector);if (bh ==NULL ) { -printk (KERN_ERR "FAT bread failed in fat_clusters_flush\n" ); +printk (KERN_ERR "FAT: bread failed in fat_clusters_flush\n" );return ; }
_
Re: [PATCH 23/29] FAT: Remove the multiple MSDOS_SB() call
In reply to OGAWA HirofumiQuoted 3 lines · OGAWA Hirofumi
Since
MSDOS_SB()is inline function, it increases text size at each calls. I don't know whether there is__attribute__for avoiding this.
If you mark it pure the compile should be smart enough to optimize way multiple invocations - heck for an inline it should be smart enough without annotaitons..
Anyway, your new version looks much more readable.
Re: [PATCH 23/29] FAT: Remove the multiple MSDOS_SB() call
In reply to OGAWA HirofumiQuoted 6 lines · OGAWA Hirofumi
Since
MSDOS_SB()is inline function, it increases text size at each calls. I don't know whether there is__attribute__for avoiding this.This removes the multiple call.
...
"inline" in the kernel is (for recent gcc's) mapped to __attribute__((always_inline)), and therefore the
"static inline struct msdos_sb_info *MSDOS_SB" does exactly the opposite of what you want.
You'd have to move this into a .c file to remove the "inline".
But considering that the whole function is
static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb)
{
return sb->s_fs_info;
}I'm quite surprised that there's any problem with it.
cu
Adrian
Signature · 4 lines
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon SeedOGAWA Hirofumi
maintainerRe: [PATCH 23/29] FAT: Remove the multiple MSDOS_SB() call
Quoted 7 lines · Adrian Bunk
Quoted 6 lines · OGAWA Hirofumi
Since
MSDOS_SB()is inline function, it increases text size at each calls. I don't know whether there is__attribute__for avoiding this.This removes the multiple call.
...
[...]
Quoted 6 lines
static inline struct
msdos_sb_info*MSDOS_SB(structsuper_block*sb){ return sb->s_fs_info; }I'm quite surprised that there's any problem with it.
Whoops, actually the cause was not inline. Sorry.
#define MSDOS_SB(x) ((struct msdos_sb_info *)(x)->s_fs_info)
was same result. This just needed my patch.
Signature · 1 line
OGAWA Hirofumi <[email protected]>
Re: [PATCH 2/29] FAT: Updated FAT attributes patch
In reply to OGAWA HirofumiQuoted 1 line · OGAWA Hirofumi
+/* <
linux/videotext.h> has used0x72('r') in collision, so skip a few */
These ioctls in videotext.h have been removed with 2.6.11. They were not used anywhere in the kernel.
Michael
OGAWA Hirofumi
maintainerRe: [PATCH 2/29] FAT: Updated FAT attributes patch
Quoted 5 lines · [email protected] (Michael Geng) writes:
Quoted 1 line · OGAWA Hirofumi
+/* <
linux/videotext.h> has used0x72('r') in collision, so skip a few */These ioctls in
videotext.hhave been removed with 2.6.11. They were not used anywhere in the kernel.
Thanks. I think we still had better skip them, because the app such as strace can handle it easily.
Signature · 1 line
OGAWA Hirofumi <[email protected]>
Re: [PATCH 2/29] FAT: Updated FAT attributes patch
In reply to Michael GengQuoted 5 lines · Michael Geng
Quoted 1 line · OGAWA Hirofumi
+/* <
linux/videotext.h> has used0x72('r') in collision, so skip a few */These ioctls in
videotext.hhave been removed with 2.6.11. They were not used anywhere in the kernel.
I'd rather avoid the collision anyway.
OGAWA Hirofumi
maintainerPATCH 1/1 FAT: Support synchronous updates
In reply to OGAWA Hirofumi[It seems that my first e-mail was lost, so this is re-post. If you received duplicated email, sorry.]
Hi,
These patches adds the -o sync' and -o dirsync' supports to fatfs. If user specified that option, the fatfs does traditional ordered updates by using synchronous writes. If compared to before, these patches will show a improvement of robustness I think.
`-o sync' - writes all buffers out before returning from syscall.
`-o dirsync' - writes the directory's metadata, and unreferencing
operations of data block.
remaining to be done
fat_generic_ioctl(), fat_notify_change(), ATTR_ARCH of fat_xxx_write[v],
and probably, filling hole in cont_prepare_write(),
NOTE: Since fatfs doesn't have link-count, unfortunately ->rename() is not safe order at all. It may make the shared blocks, but user shouldn't lose the data by ->rename().
Please apply.
Signature · 1 line
OGAWA Hirofumi <[email protected]>
Re: [PATCH] FAT: Support synchronous update
In reply to a message not in the archiveQuoted 21 lines · OGAWA Hirofumi
Hi,
These patches adds the
-o sync' and-o dirsync' supports to fatfs. If user specified that option, the fatfs does traditional ordered updates by using synchronous writes. If compared to before, these patches will show a improvement of robustness I think.`-o sync' - writes all buffers out before returning from syscall.
`-o dirsync' - writes the directory's metadata, and unreferencing
operations of data block.remaining to be done
fat_generic_ioctl(),fat_notify_change(),ATTR_ARCHof fat_xxx_write[v],
and probably, filling hole incont_prepare_write(),NOTE: Since fatfs doesn't have link-count, unfortunately ->rename() is not safe order at all. It may make the shared blocks, but user shouldn't lose the data by ->rename().
Quoted 10 lines
Please apply.
If you test this, please use attached dosfstools. This is fixing several bugs of dosfstools. And "2/29" patch from hpa adds new ioctl, the attached archive is also including the commands for testing it.
Signature · 1 line
OGAWA Hirofumi <[email protected]>
OK. This email was way too big for linux-kernel, so nobody saw it.
I put the modified fatfsprogs at
http://www.zip.com.au/~akpm/linux/patches/stuff/fatfsprogs.tar.bz2 and updated the changlog to mention that.
Is there an official place where people should go to download the modified fatfsprogs?
OGAWA Hirofumi
maintainerRe: [PATCH] FAT: Support synchronous update
Quoted 8 lines · Andrew Morton
OK. This email was way too big for linux-kernel, so nobody saw it.
I put the modified fatfsprogs at
http://www.zip.com.au/~akpm/linux/patches/stuff/fatfsprogs.tar.bz2 and updated the changlog to mention that.Is there an official place where people should go to download the modified fatfsprogs?
Oh, Thanks. Umm.. ok, I'll put fatfsprogs.tar.bz2 to the following for now.
http://user.parknet.co.jp/hirofumi/tmp/fatfsprogs.tar.bz2
Signature · 1 line
OGAWA Hirofumi <[email protected]>