Commit 391517ec authored by Hirofumi Ogawa's avatar Hirofumi Ogawa Committed by Linus Torvalds

[PATCH] 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.
Signed-off-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent be3a386a
...@@ -253,31 +253,38 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, ...@@ -253,31 +253,38 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
/***** Creates a directory entry (name is already formatted). */ /***** Creates a directory entry (name is already formatted). */
static int msdos_add_entry(struct inode *dir, const unsigned char *name, static int msdos_add_entry(struct inode *dir, const unsigned char *name,
struct buffer_head **bh, int is_dir, int is_hid, struct timespec *ts,
struct msdos_dir_entry **de, struct fat_slot_info *sinfo)
loff_t *i_pos, int is_dir, int is_hid)
{ {
int res; struct msdos_dir_entry de;
__le16 time, date;
res = fat_add_entries(dir, 1, bh, de, i_pos); int offset;
if (res < 0)
return res;
/* memcpy(de.name, name, MSDOS_NAME);
* XXX all times should be set by caller upon successful completion. de.attr = is_dir ? ATTR_DIR : ATTR_ARCH;
*/ if (is_hid)
dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; 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;
memcpy(sinfo->de, &de, sizeof(de));
mark_buffer_dirty(sinfo->bh);
dir->i_ctime = dir->i_mtime = *ts;
mark_inode_dirty(dir); 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; return 0;
} }
...@@ -286,45 +293,43 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, ...@@ -286,45 +293,43 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd) struct nameidata *nd)
{ {
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
struct fat_slot_info sinfo;
struct buffer_head *bh;
struct msdos_dir_entry *de;
struct inode *inode; struct inode *inode;
loff_t i_pos; struct fat_slot_info sinfo;
int res, is_hid; struct timespec ts;
unsigned char msdos_name[MSDOS_NAME]; unsigned char msdos_name[MSDOS_NAME];
int err, is_hid;
lock_kernel(); 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); msdos_name, &MSDOS_SB(sb)->options);
if (res < 0) { if (err)
unlock_kernel(); goto out;
return res;
}
is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.'); is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
/* Have to do it due to foo vs. .foo conflicts */ /* Have to do it due to foo vs. .foo conflicts */
if (!fat_scan(dir, msdos_name, &sinfo)) { if (!fat_scan(dir, msdos_name, &sinfo)) {
brelse(sinfo.bh); brelse(sinfo.bh);
unlock_kernel(); err = -EINVAL;
return -EINVAL; goto out;
} }
res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 0, is_hid); ts = CURRENT_TIME_SEC;
if (res) { err = msdos_add_entry(dir, msdos_name, 0, is_hid, &ts, &sinfo);
unlock_kernel(); if (err)
return res; goto out;
} inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
inode = fat_build_inode(sb, de, i_pos); brelse(sinfo.bh);
brelse(bh);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
unlock_kernel(); err = PTR_ERR(inode);
return PTR_ERR(inode); goto out;
} }
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
mark_inode_dirty(inode); /* timestamp is already written, so mark_inode_dirty() is unneeded. */
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
out:
unlock_kernel(); unlock_kernel();
return 0; return err;
} }
/***** Remove a directory */ /***** Remove a directory */
...@@ -367,65 +372,63 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -367,65 +372,63 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{ {
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
struct fat_slot_info sinfo; struct fat_slot_info sinfo;
struct buffer_head *bh;
struct msdos_dir_entry *de;
struct inode *inode; struct inode *inode;
int res, is_hid;
unsigned char msdos_name[MSDOS_NAME]; unsigned char msdos_name[MSDOS_NAME];
loff_t i_pos; struct timespec ts;
int err, is_hid;
lock_kernel(); 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); msdos_name, &MSDOS_SB(sb)->options);
if (res < 0) { if (err)
unlock_kernel(); goto out;
return res;
}
is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.'); is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
/* foo vs .foo situation */ /* foo vs .foo situation */
if (!fat_scan(dir, msdos_name, &sinfo)) { if (!fat_scan(dir, msdos_name, &sinfo)) {
brelse(sinfo.bh); brelse(sinfo.bh);
res = -EINVAL; err = -EINVAL;
goto out_unlock; goto out;
} }
res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 1, is_hid); ts = CURRENT_TIME_SEC;
if (res) err = msdos_add_entry(dir, msdos_name, 1, is_hid, &ts, &sinfo);
goto out_unlock; if (err)
inode = fat_build_inode(dir->i_sb, de, i_pos); goto out;
inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
brelse(bh); brelse(sinfo.bh);
res = PTR_ERR(inode); err = PTR_ERR(inode);
goto out_unlock; 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++; dir->i_nlink++;
inode->i_nlink = 2; /* no need to mark them dirty */ inode->i_nlink = 2; /* no need to mark them dirty */
res = fat_new_dir(inode, dir, 0); err = fat_new_dir(inode, dir, 0);
if (res) if (err)
goto mkdir_error; goto mkdir_error;
brelse(bh); brelse(sinfo.bh);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
res = 0; out:
out_unlock:
unlock_kernel(); unlock_kernel();
return res; return err;
mkdir_error: mkdir_error:
inode->i_nlink = 0; 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--; dir->i_nlink--;
mark_inode_dirty(inode); mark_inode_dirty(inode);
mark_inode_dirty(dir); mark_inode_dirty(dir);
de->name[0] = DELETED_FLAG; sinfo.de->name[0] = DELETED_FLAG;
mark_buffer_dirty(bh); mark_buffer_dirty(sinfo.bh);
brelse(bh); brelse(sinfo.bh);
fat_detach(inode); fat_detach(inode);
iput(inode); iput(inode);
goto out_unlock; goto out;
} }
/***** Unlink a file */ /***** Unlink a file */
...@@ -465,6 +468,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, ...@@ -465,6 +468,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
loff_t dotdot_i_pos; loff_t dotdot_i_pos;
struct inode *old_inode, *new_inode; struct inode *old_inode, *new_inode;
struct fat_slot_info old_sinfo, sinfo; struct fat_slot_info old_sinfo, sinfo;
struct timespec ts;
int err, is_dir; int err, is_dir;
old_sinfo.bh = dotdot_bh = NULL; old_sinfo.bh = dotdot_bh = NULL;
...@@ -507,6 +511,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, ...@@ -507,6 +511,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
goto out; goto out;
} }
} }
ts = CURRENT_TIME_SEC;
if (new_inode) { if (new_inode) {
if (err) if (err)
goto out; goto out;
...@@ -523,8 +529,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, ...@@ -523,8 +529,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
} }
fat_detach(new_inode); fat_detach(new_inode);
} else { } else {
err = msdos_add_entry(new_dir, new_name, &sinfo.bh, &sinfo.de, err = msdos_add_entry(new_dir, new_name, is_dir, is_hid,
&sinfo.i_pos, is_dir, is_hid); &ts, &sinfo);
if (err) if (err)
goto out; goto out;
brelse(sinfo.bh); brelse(sinfo.bh);
...@@ -546,12 +552,12 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, ...@@ -546,12 +552,12 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
mark_inode_dirty(old_inode); mark_inode_dirty(old_inode);
old_dir->i_version++; 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); mark_inode_dirty(old_dir);
if (new_inode) { if (new_inode) {
new_inode->i_nlink--; new_inode->i_nlink--;
new_inode->i_ctime = CURRENT_TIME_SEC; new_inode->i_ctime = ts;
mark_inode_dirty(new_inode); mark_inode_dirty(new_inode);
} }
if (is_dir) { if (is_dir) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment