[JFFS2] Fix JFFS2 [mc]time handling
From: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Artem B. Bityutskiy <dedekind@infradead.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
01d445f89d
commit
3a69e0cd22
5 changed files with 37 additions and 17 deletions
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* For licensing information, see the file 'LICENCE' in this directory.
|
||||
*
|
||||
* $Id: dir.c,v 1.87 2005/07/17 11:13:46 dedekind Exp $
|
||||
* $Id: dir.c,v 1.88 2005/08/17 13:46:22 dedekind Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -232,11 +232,14 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
|
|||
struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode);
|
||||
int ret;
|
||||
uint32_t now = get_seconds();
|
||||
|
||||
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
|
||||
dentry->d_name.len, dead_f);
|
||||
dentry->d_name.len, dead_f, now);
|
||||
if (dead_f->inocache)
|
||||
dentry->d_inode->i_nlink = dead_f->inocache->nlink;
|
||||
if (!ret)
|
||||
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
|
||||
return ret;
|
||||
}
|
||||
/***********************************************************************/
|
||||
|
@ -249,6 +252,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
|
|||
struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
int ret;
|
||||
uint8_t type;
|
||||
uint32_t now;
|
||||
|
||||
/* Don't let people make hard links to bad inodes. */
|
||||
if (!f->inocache)
|
||||
|
@ -261,13 +265,15 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
|
|||
type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
|
||||
if (!type) type = DT_REG;
|
||||
|
||||
ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len);
|
||||
now = get_seconds();
|
||||
ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now);
|
||||
|
||||
if (!ret) {
|
||||
down(&f->sem);
|
||||
old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
|
||||
up(&f->sem);
|
||||
d_instantiate(dentry, old_dentry->d_inode);
|
||||
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
|
||||
atomic_inc(&old_dentry->d_inode->i_count);
|
||||
}
|
||||
return ret;
|
||||
|
@ -716,6 +722,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
|
|||
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
|
||||
struct jffs2_inode_info *victim_f = NULL;
|
||||
uint8_t type;
|
||||
uint32_t now;
|
||||
|
||||
/* The VFS will check for us and prevent trying to rename a
|
||||
* file over a directory and vice versa, but if it's a directory,
|
||||
|
@ -749,9 +756,10 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
|
|||
type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
|
||||
if (!type) type = DT_REG;
|
||||
|
||||
now = get_seconds();
|
||||
ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
|
||||
old_dentry->d_inode->i_ino, type,
|
||||
new_dentry->d_name.name, new_dentry->d_name.len);
|
||||
new_dentry->d_name.name, new_dentry->d_name.len, now);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -775,7 +783,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
|
|||
|
||||
/* Unlink the original */
|
||||
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
|
||||
old_dentry->d_name.name, old_dentry->d_name.len, NULL);
|
||||
old_dentry->d_name.name, old_dentry->d_name.len, NULL, now);
|
||||
|
||||
/* We don't touch inode->i_nlink */
|
||||
|
||||
|
@ -792,12 +800,15 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
|
|||
/* Might as well let the VFS know */
|
||||
d_instantiate(new_dentry, old_dentry->d_inode);
|
||||
atomic_inc(&old_dentry->d_inode->i_count);
|
||||
new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (S_ISDIR(old_dentry->d_inode->i_mode))
|
||||
old_dir_i->i_nlink--;
|
||||
|
||||
new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* For licensing information, see the file 'LICENCE' in this directory.
|
||||
*
|
||||
* $Id: gc.c,v 1.152 2005/07/24 15:14:14 dedekind Exp $
|
||||
* $Id: gc.c,v 1.153 2005/08/17 13:46:22 dedekind Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -771,7 +771,12 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er
|
|||
rd.pino = cpu_to_je32(f->inocache->ino);
|
||||
rd.version = cpu_to_je32(++f->highest_version);
|
||||
rd.ino = cpu_to_je32(fd->ino);
|
||||
rd.mctime = cpu_to_je32(max(JFFS2_F_I_MTIME(f), JFFS2_F_I_CTIME(f)));
|
||||
/* If the times on this inode were set by explicit utime() they can be different,
|
||||
so refrain from splatting them. */
|
||||
if (JFFS2_F_I_MTIME(f) == JFFS2_F_I_CTIME(f))
|
||||
rd.mctime = cpu_to_je32(JFFS2_F_I_MTIME(f));
|
||||
else
|
||||
rd.mctime = cpu_to_je32(0);
|
||||
rd.type = fd->type;
|
||||
rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8));
|
||||
rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize));
|
||||
|
@ -883,6 +888,9 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
|
|||
kfree(rd);
|
||||
}
|
||||
|
||||
/* FIXME: If we're deleting a dirent which contains the current mtime and ctime,
|
||||
we should update the metadata node with those times accordingly */
|
||||
|
||||
/* No need for it any more. Just mark it obsolete and remove it from the list */
|
||||
while (*fdp) {
|
||||
if ((*fdp) == fd) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* For licensing information, see the file 'LICENCE' in this directory.
|
||||
*
|
||||
* $Id: nodelist.h,v 1.137 2005/08/01 12:05:19 dedekind Exp $
|
||||
* $Id: nodelist.h,v 1.138 2005/08/17 13:46:23 dedekind Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -336,8 +336,8 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|||
struct jffs2_raw_inode *ri, unsigned char *buf,
|
||||
uint32_t offset, uint32_t writelen, uint32_t *retlen);
|
||||
int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen);
|
||||
int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f);
|
||||
int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen);
|
||||
int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
|
||||
int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time);
|
||||
|
||||
|
||||
/* readinode.c */
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* For licensing information, see the file 'LICENCE' in this directory.
|
||||
*
|
||||
* $Id: readinode.c,v 1.139 2005/08/04 11:41:31 dedekind Exp $
|
||||
* $Id: readinode.c,v 1.140 2005/08/17 13:46:23 dedekind Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -139,7 +139,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
|
|||
fd->type = rd->type;
|
||||
|
||||
/* Pick out the mctime of the latest dirent */
|
||||
if(fd->version > *mctime_ver) {
|
||||
if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) {
|
||||
*mctime_ver = fd->version;
|
||||
*latest_mctime = je32_to_cpu(rd->mctime);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* For licensing information, see the file 'LICENCE' in this directory.
|
||||
*
|
||||
* $Id: write.c,v 1.94 2005/07/20 15:50:51 dedekind Exp $
|
||||
* $Id: write.c,v 1.95 2005/08/17 13:46:23 dedekind Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -533,7 +533,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|||
|
||||
|
||||
int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
||||
const char *name, int namelen, struct jffs2_inode_info *dead_f)
|
||||
const char *name, int namelen, struct jffs2_inode_info *dead_f,
|
||||
uint32_t time)
|
||||
{
|
||||
struct jffs2_raw_dirent *rd;
|
||||
struct jffs2_full_dirent *fd;
|
||||
|
@ -565,7 +566,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|||
rd->pino = cpu_to_je32(dir_f->inocache->ino);
|
||||
rd->version = cpu_to_je32(++dir_f->highest_version);
|
||||
rd->ino = cpu_to_je32(0);
|
||||
rd->mctime = cpu_to_je32(get_seconds());
|
||||
rd->mctime = cpu_to_je32(time);
|
||||
rd->nsize = namelen;
|
||||
rd->type = DT_UNKNOWN;
|
||||
rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
|
||||
|
@ -646,7 +647,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|||
}
|
||||
|
||||
|
||||
int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen)
|
||||
int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time)
|
||||
{
|
||||
struct jffs2_raw_dirent *rd;
|
||||
struct jffs2_full_dirent *fd;
|
||||
|
@ -674,7 +675,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
|
|||
rd->pino = cpu_to_je32(dir_f->inocache->ino);
|
||||
rd->version = cpu_to_je32(++dir_f->highest_version);
|
||||
rd->ino = cpu_to_je32(ino);
|
||||
rd->mctime = cpu_to_je32(get_seconds());
|
||||
rd->mctime = cpu_to_je32(time);
|
||||
rd->nsize = namelen;
|
||||
|
||||
rd->type = type;
|
||||
|
|
Loading…
Reference in a new issue