diff options
author | Artem B. Bityutskiy <dedekind@infradead.org> | 2005-08-17 09:46:26 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@mtd.linutronix.de> | 2005-11-06 14:25:59 -0500 |
commit | 3a69e0cd22cf34920508a4032d53e41251925f53 (patch) | |
tree | f6f862aa743e3de98e348c20d84a26772da06195 /fs | |
parent | 01d445f89d68187c9ada7b58ca939dbb987c9fbd (diff) |
[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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jffs2/dir.c | 21 | ||||
-rw-r--r-- | fs/jffs2/gc.c | 12 | ||||
-rw-r--r-- | fs/jffs2/nodelist.h | 6 | ||||
-rw-r--r-- | fs/jffs2/readinode.c | 4 | ||||
-rw-r--r-- | fs/jffs2/write.c | 11 |
5 files changed, 37 insertions, 17 deletions
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 5738df223775..0fd15aaf2458 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * For licensing information, see the file 'LICENCE' in this directory. | 8 | * For licensing information, see the file 'LICENCE' in this directory. |
9 | * | 9 | * |
10 | * $Id: dir.c,v 1.87 2005/07/17 11:13:46 dedekind Exp $ | 10 | * $Id: dir.c,v 1.88 2005/08/17 13:46:22 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -232,11 +232,14 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) | |||
232 | struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); | 232 | struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); |
233 | struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode); | 233 | struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode); |
234 | int ret; | 234 | int ret; |
235 | uint32_t now = get_seconds(); | ||
235 | 236 | ||
236 | ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, | 237 | ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, |
237 | dentry->d_name.len, dead_f); | 238 | dentry->d_name.len, dead_f, now); |
238 | if (dead_f->inocache) | 239 | if (dead_f->inocache) |
239 | dentry->d_inode->i_nlink = dead_f->inocache->nlink; | 240 | dentry->d_inode->i_nlink = dead_f->inocache->nlink; |
241 | if (!ret) | ||
242 | dir_i->i_mtime = dir_i->i_ctime = ITIME(now); | ||
240 | return ret; | 243 | return ret; |
241 | } | 244 | } |
242 | /***********************************************************************/ | 245 | /***********************************************************************/ |
@@ -249,6 +252,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de | |||
249 | struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); | 252 | struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); |
250 | int ret; | 253 | int ret; |
251 | uint8_t type; | 254 | uint8_t type; |
255 | uint32_t now; | ||
252 | 256 | ||
253 | /* Don't let people make hard links to bad inodes. */ | 257 | /* Don't let people make hard links to bad inodes. */ |
254 | if (!f->inocache) | 258 | if (!f->inocache) |
@@ -261,13 +265,15 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de | |||
261 | type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; | 265 | type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; |
262 | if (!type) type = DT_REG; | 266 | if (!type) type = DT_REG; |
263 | 267 | ||
264 | ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len); | 268 | now = get_seconds(); |
269 | ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now); | ||
265 | 270 | ||
266 | if (!ret) { | 271 | if (!ret) { |
267 | down(&f->sem); | 272 | down(&f->sem); |
268 | old_dentry->d_inode->i_nlink = ++f->inocache->nlink; | 273 | old_dentry->d_inode->i_nlink = ++f->inocache->nlink; |
269 | up(&f->sem); | 274 | up(&f->sem); |
270 | d_instantiate(dentry, old_dentry->d_inode); | 275 | d_instantiate(dentry, old_dentry->d_inode); |
276 | dir_i->i_mtime = dir_i->i_ctime = ITIME(now); | ||
271 | atomic_inc(&old_dentry->d_inode->i_count); | 277 | atomic_inc(&old_dentry->d_inode->i_count); |
272 | } | 278 | } |
273 | return ret; | 279 | return ret; |
@@ -716,6 +722,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
716 | struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); | 722 | struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); |
717 | struct jffs2_inode_info *victim_f = NULL; | 723 | struct jffs2_inode_info *victim_f = NULL; |
718 | uint8_t type; | 724 | uint8_t type; |
725 | uint32_t now; | ||
719 | 726 | ||
720 | /* The VFS will check for us and prevent trying to rename a | 727 | /* The VFS will check for us and prevent trying to rename a |
721 | * file over a directory and vice versa, but if it's a directory, | 728 | * 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, | |||
749 | type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; | 756 | type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; |
750 | if (!type) type = DT_REG; | 757 | if (!type) type = DT_REG; |
751 | 758 | ||
759 | now = get_seconds(); | ||
752 | ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), | 760 | ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), |
753 | old_dentry->d_inode->i_ino, type, | 761 | old_dentry->d_inode->i_ino, type, |
754 | new_dentry->d_name.name, new_dentry->d_name.len); | 762 | new_dentry->d_name.name, new_dentry->d_name.len, now); |
755 | 763 | ||
756 | if (ret) | 764 | if (ret) |
757 | return ret; | 765 | return ret; |
@@ -775,7 +783,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
775 | 783 | ||
776 | /* Unlink the original */ | 784 | /* Unlink the original */ |
777 | ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), | 785 | ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), |
778 | old_dentry->d_name.name, old_dentry->d_name.len, NULL); | 786 | old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); |
779 | 787 | ||
780 | /* We don't touch inode->i_nlink */ | 788 | /* We don't touch inode->i_nlink */ |
781 | 789 | ||
@@ -792,12 +800,15 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
792 | /* Might as well let the VFS know */ | 800 | /* Might as well let the VFS know */ |
793 | d_instantiate(new_dentry, old_dentry->d_inode); | 801 | d_instantiate(new_dentry, old_dentry->d_inode); |
794 | atomic_inc(&old_dentry->d_inode->i_count); | 802 | atomic_inc(&old_dentry->d_inode->i_count); |
803 | new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now); | ||
795 | return ret; | 804 | return ret; |
796 | } | 805 | } |
797 | 806 | ||
798 | if (S_ISDIR(old_dentry->d_inode->i_mode)) | 807 | if (S_ISDIR(old_dentry->d_inode->i_mode)) |
799 | old_dir_i->i_nlink--; | 808 | old_dir_i->i_nlink--; |
800 | 809 | ||
810 | new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); | ||
811 | |||
801 | return 0; | 812 | return 0; |
802 | } | 813 | } |
803 | 814 | ||
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 362cfeed7327..def97157ecbd 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * For licensing information, see the file 'LICENCE' in this directory. | 8 | * For licensing information, see the file 'LICENCE' in this directory. |
9 | * | 9 | * |
10 | * $Id: gc.c,v 1.152 2005/07/24 15:14:14 dedekind Exp $ | 10 | * $Id: gc.c,v 1.153 2005/08/17 13:46:22 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -771,7 +771,12 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er | |||
771 | rd.pino = cpu_to_je32(f->inocache->ino); | 771 | rd.pino = cpu_to_je32(f->inocache->ino); |
772 | rd.version = cpu_to_je32(++f->highest_version); | 772 | rd.version = cpu_to_je32(++f->highest_version); |
773 | rd.ino = cpu_to_je32(fd->ino); | 773 | rd.ino = cpu_to_je32(fd->ino); |
774 | rd.mctime = cpu_to_je32(max(JFFS2_F_I_MTIME(f), JFFS2_F_I_CTIME(f))); | 774 | /* If the times on this inode were set by explicit utime() they can be different, |
775 | so refrain from splatting them. */ | ||
776 | if (JFFS2_F_I_MTIME(f) == JFFS2_F_I_CTIME(f)) | ||
777 | rd.mctime = cpu_to_je32(JFFS2_F_I_MTIME(f)); | ||
778 | else | ||
779 | rd.mctime = cpu_to_je32(0); | ||
775 | rd.type = fd->type; | 780 | rd.type = fd->type; |
776 | rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); | 781 | rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); |
777 | rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); | 782 | 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 | |||
883 | kfree(rd); | 888 | kfree(rd); |
884 | } | 889 | } |
885 | 890 | ||
891 | /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, | ||
892 | we should update the metadata node with those times accordingly */ | ||
893 | |||
886 | /* No need for it any more. Just mark it obsolete and remove it from the list */ | 894 | /* No need for it any more. Just mark it obsolete and remove it from the list */ |
887 | while (*fdp) { | 895 | while (*fdp) { |
888 | if ((*fdp) == fd) { | 896 | if ((*fdp) == fd) { |
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index adee3c6eb448..ce47d5530a70 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * For licensing information, see the file 'LICENCE' in this directory. | 8 | * For licensing information, see the file 'LICENCE' in this directory. |
9 | * | 9 | * |
10 | * $Id: nodelist.h,v 1.137 2005/08/01 12:05:19 dedekind Exp $ | 10 | * $Id: nodelist.h,v 1.138 2005/08/17 13:46:23 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -336,8 +336,8 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
336 | struct jffs2_raw_inode *ri, unsigned char *buf, | 336 | struct jffs2_raw_inode *ri, unsigned char *buf, |
337 | uint32_t offset, uint32_t writelen, uint32_t *retlen); | 337 | uint32_t offset, uint32_t writelen, uint32_t *retlen); |
338 | 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); | 338 | 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); |
339 | 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); | 339 | 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); |
340 | 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); | 340 | 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); |
341 | 341 | ||
342 | 342 | ||
343 | /* readinode.c */ | 343 | /* readinode.c */ |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 50a62dd33e3e..6d5adaba4062 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * For licensing information, see the file 'LICENCE' in this directory. | 8 | * For licensing information, see the file 'LICENCE' in this directory. |
9 | * | 9 | * |
10 | * $Id: readinode.c,v 1.139 2005/08/04 11:41:31 dedekind Exp $ | 10 | * $Id: readinode.c,v 1.140 2005/08/17 13:46:23 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -139,7 +139,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
139 | fd->type = rd->type; | 139 | fd->type = rd->type; |
140 | 140 | ||
141 | /* Pick out the mctime of the latest dirent */ | 141 | /* Pick out the mctime of the latest dirent */ |
142 | if(fd->version > *mctime_ver) { | 142 | if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) { |
143 | *mctime_ver = fd->version; | 143 | *mctime_ver = fd->version; |
144 | *latest_mctime = je32_to_cpu(rd->mctime); | 144 | *latest_mctime = je32_to_cpu(rd->mctime); |
145 | } | 145 | } |
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 4c418e69cfc6..0a194759bbbd 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * For licensing information, see the file 'LICENCE' in this directory. | 8 | * For licensing information, see the file 'LICENCE' in this directory. |
9 | * | 9 | * |
10 | * $Id: write.c,v 1.94 2005/07/20 15:50:51 dedekind Exp $ | 10 | * $Id: write.c,v 1.95 2005/08/17 13:46:23 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -533,7 +533,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
533 | 533 | ||
534 | 534 | ||
535 | int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | 535 | int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, |
536 | const char *name, int namelen, struct jffs2_inode_info *dead_f) | 536 | const char *name, int namelen, struct jffs2_inode_info *dead_f, |
537 | uint32_t time) | ||
537 | { | 538 | { |
538 | struct jffs2_raw_dirent *rd; | 539 | struct jffs2_raw_dirent *rd; |
539 | struct jffs2_full_dirent *fd; | 540 | struct jffs2_full_dirent *fd; |
@@ -565,7 +566,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |||
565 | rd->pino = cpu_to_je32(dir_f->inocache->ino); | 566 | rd->pino = cpu_to_je32(dir_f->inocache->ino); |
566 | rd->version = cpu_to_je32(++dir_f->highest_version); | 567 | rd->version = cpu_to_je32(++dir_f->highest_version); |
567 | rd->ino = cpu_to_je32(0); | 568 | rd->ino = cpu_to_je32(0); |
568 | rd->mctime = cpu_to_je32(get_seconds()); | 569 | rd->mctime = cpu_to_je32(time); |
569 | rd->nsize = namelen; | 570 | rd->nsize = namelen; |
570 | rd->type = DT_UNKNOWN; | 571 | rd->type = DT_UNKNOWN; |
571 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | 572 | 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, | |||
646 | } | 647 | } |
647 | 648 | ||
648 | 649 | ||
649 | 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) | 650 | 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) |
650 | { | 651 | { |
651 | struct jffs2_raw_dirent *rd; | 652 | struct jffs2_raw_dirent *rd; |
652 | struct jffs2_full_dirent *fd; | 653 | 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 | |||
674 | rd->pino = cpu_to_je32(dir_f->inocache->ino); | 675 | rd->pino = cpu_to_je32(dir_f->inocache->ino); |
675 | rd->version = cpu_to_je32(++dir_f->highest_version); | 676 | rd->version = cpu_to_je32(++dir_f->highest_version); |
676 | rd->ino = cpu_to_je32(ino); | 677 | rd->ino = cpu_to_je32(ino); |
677 | rd->mctime = cpu_to_je32(get_seconds()); | 678 | rd->mctime = cpu_to_je32(time); |
678 | rd->nsize = namelen; | 679 | rd->nsize = namelen; |
679 | 680 | ||
680 | rd->type = type; | 681 | rd->type = type; |