aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/build.c31
-rw-r--r--fs/jffs2/debug.h8
-rw-r--r--fs/jffs2/dir.c42
-rw-r--r--fs/jffs2/erase.c9
-rw-r--r--fs/jffs2/fs.c14
-rw-r--r--fs/jffs2/gc.c8
-rw-r--r--fs/jffs2/nodelist.h5
-rw-r--r--fs/jffs2/nodemgmt.c2
-rw-r--r--fs/jffs2/os-linux.h2
-rw-r--r--fs/jffs2/readinode.c16
-rw-r--r--fs/jffs2/scan.c9
-rw-r--r--fs/jffs2/super.c15
-rw-r--r--fs/jffs2/wbuf.c2
-rw-r--r--fs/jffs2/write.c17
-rw-r--r--fs/jffs2/xattr.c8
15 files changed, 114 insertions, 74 deletions
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index d58f845ccb85..c5e1450d79f9 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -46,7 +46,7 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
46 46
47 47
48static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, 48static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
49 struct jffs2_inode_cache *ic) 49 struct jffs2_inode_cache *ic)
50{ 50{
51 struct jffs2_full_dirent *fd; 51 struct jffs2_full_dirent *fd;
52 52
@@ -68,11 +68,17 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
68 continue; 68 continue;
69 } 69 }
70 70
71 if (child_ic->nlink++ && fd->type == DT_DIR) { 71 if (fd->type == DT_DIR) {
72 JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", 72 if (child_ic->pino_nlink) {
73 fd->name, fd->ino, ic->ino); 73 JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n",
74 /* TODO: What do we do about it? */ 74 fd->name, fd->ino, ic->ino);
75 } 75 /* TODO: What do we do about it? */
76 } else {
77 child_ic->pino_nlink = ic->ino;
78 }
79 } else
80 child_ic->pino_nlink++;
81
76 dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino); 82 dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino);
77 /* Can't free scan_dents so far. We might need them in pass 2 */ 83 /* Can't free scan_dents so far. We might need them in pass 2 */
78 } 84 }
@@ -125,7 +131,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
125 dbg_fsbuild("pass 2 starting\n"); 131 dbg_fsbuild("pass 2 starting\n");
126 132
127 for_each_inode(i, c, ic) { 133 for_each_inode(i, c, ic) {
128 if (ic->nlink) 134 if (ic->pino_nlink)
129 continue; 135 continue;
130 136
131 jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); 137 jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
@@ -232,16 +238,19 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c,
232 /* Reduce nlink of the child. If it's now zero, stick it on the 238 /* Reduce nlink of the child. If it's now zero, stick it on the
233 dead_fds list to be cleaned up later. Else just free the fd */ 239 dead_fds list to be cleaned up later. Else just free the fd */
234 240
235 child_ic->nlink--; 241 if (fd->type == DT_DIR)
242 child_ic->pino_nlink = 0;
243 else
244 child_ic->pino_nlink--;
236 245
237 if (!child_ic->nlink) { 246 if (!child_ic->pino_nlink) {
238 dbg_fsbuild("inode #%u (\"%s\") has now got zero nlink, adding to dead_fds list.\n", 247 dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n",
239 fd->ino, fd->name); 248 fd->ino, fd->name);
240 fd->next = *dead_fds; 249 fd->next = *dead_fds;
241 *dead_fds = fd; 250 *dead_fds = fd;
242 } else { 251 } else {
243 dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", 252 dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n",
244 fd->ino, fd->name, child_ic->nlink); 253 fd->ino, fd->name, child_ic->pino_nlink);
245 jffs2_free_full_dirent(fd); 254 jffs2_free_full_dirent(fd);
246 } 255 }
247 } 256 }
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index 9645275023e6..a113ecc3bafe 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -82,28 +82,28 @@
82 do { \ 82 do { \
83 printk(JFFS2_ERR_MSG_PREFIX \ 83 printk(JFFS2_ERR_MSG_PREFIX \
84 " (%d) %s: " fmt, task_pid_nr(current), \ 84 " (%d) %s: " fmt, task_pid_nr(current), \
85 __FUNCTION__ , ##__VA_ARGS__); \ 85 __func__ , ##__VA_ARGS__); \
86 } while(0) 86 } while(0)
87 87
88#define JFFS2_WARNING(fmt, ...) \ 88#define JFFS2_WARNING(fmt, ...) \
89 do { \ 89 do { \
90 printk(JFFS2_WARN_MSG_PREFIX \ 90 printk(JFFS2_WARN_MSG_PREFIX \
91 " (%d) %s: " fmt, task_pid_nr(current), \ 91 " (%d) %s: " fmt, task_pid_nr(current), \
92 __FUNCTION__ , ##__VA_ARGS__); \ 92 __func__ , ##__VA_ARGS__); \
93 } while(0) 93 } while(0)
94 94
95#define JFFS2_NOTICE(fmt, ...) \ 95#define JFFS2_NOTICE(fmt, ...) \
96 do { \ 96 do { \
97 printk(JFFS2_NOTICE_MSG_PREFIX \ 97 printk(JFFS2_NOTICE_MSG_PREFIX \
98 " (%d) %s: " fmt, task_pid_nr(current), \ 98 " (%d) %s: " fmt, task_pid_nr(current), \
99 __FUNCTION__ , ##__VA_ARGS__); \ 99 __func__ , ##__VA_ARGS__); \
100 } while(0) 100 } while(0)
101 101
102#define JFFS2_DEBUG(fmt, ...) \ 102#define JFFS2_DEBUG(fmt, ...) \
103 do { \ 103 do { \
104 printk(JFFS2_DBG_MSG_PREFIX \ 104 printk(JFFS2_DBG_MSG_PREFIX \
105 " (%d) %s: " fmt, task_pid_nr(current), \ 105 " (%d) %s: " fmt, task_pid_nr(current), \
106 __FUNCTION__ , ##__VA_ARGS__); \ 106 __func__ , ##__VA_ARGS__); \
107 } while(0) 107 } while(0)
108 108
109/* 109/*
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index c63e7a96af0d..c0c141f6fde1 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -208,6 +208,13 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
208 f = JFFS2_INODE_INFO(inode); 208 f = JFFS2_INODE_INFO(inode);
209 dir_f = JFFS2_INODE_INFO(dir_i); 209 dir_f = JFFS2_INODE_INFO(dir_i);
210 210
211 /* jffs2_do_create() will want to lock it, _after_ reserving
212 space and taking c-alloc_sem. If we keep it locked here,
213 lockdep gets unhappy (although it's a false positive;
214 nothing else will be looking at this inode yet so there's
215 no chance of AB-BA deadlock involving its f->sem). */
216 mutex_unlock(&f->sem);
217
211 ret = jffs2_do_create(c, dir_f, f, ri, 218 ret = jffs2_do_create(c, dir_f, f, ri,
212 dentry->d_name.name, dentry->d_name.len); 219 dentry->d_name.name, dentry->d_name.len);
213 if (ret) 220 if (ret)
@@ -219,7 +226,8 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
219 d_instantiate(dentry, inode); 226 d_instantiate(dentry, inode);
220 227
221 D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", 228 D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
222 inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages)); 229 inode->i_ino, inode->i_mode, inode->i_nlink,
230 f->inocache->pino_nlink, inode->i_mapping->nrpages));
223 return 0; 231 return 0;
224 232
225 fail: 233 fail:
@@ -243,7 +251,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
243 ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, 251 ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
244 dentry->d_name.len, dead_f, now); 252 dentry->d_name.len, dead_f, now);
245 if (dead_f->inocache) 253 if (dead_f->inocache)
246 dentry->d_inode->i_nlink = dead_f->inocache->nlink; 254 dentry->d_inode->i_nlink = dead_f->inocache->pino_nlink;
247 if (!ret) 255 if (!ret)
248 dir_i->i_mtime = dir_i->i_ctime = ITIME(now); 256 dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
249 return ret; 257 return ret;
@@ -276,7 +284,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
276 284
277 if (!ret) { 285 if (!ret) {
278 mutex_lock(&f->sem); 286 mutex_lock(&f->sem);
279 old_dentry->d_inode->i_nlink = ++f->inocache->nlink; 287 old_dentry->d_inode->i_nlink = ++f->inocache->pino_nlink;
280 mutex_unlock(&f->sem); 288 mutex_unlock(&f->sem);
281 d_instantiate(dentry, old_dentry->d_inode); 289 d_instantiate(dentry, old_dentry->d_inode);
282 dir_i->i_mtime = dir_i->i_ctime = ITIME(now); 290 dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
@@ -493,11 +501,14 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
493 501
494 inode->i_op = &jffs2_dir_inode_operations; 502 inode->i_op = &jffs2_dir_inode_operations;
495 inode->i_fop = &jffs2_dir_operations; 503 inode->i_fop = &jffs2_dir_operations;
496 /* Directories get nlink 2 at start */
497 inode->i_nlink = 2;
498 504
499 f = JFFS2_INODE_INFO(inode); 505 f = JFFS2_INODE_INFO(inode);
500 506
507 /* Directories get nlink 2 at start */
508 inode->i_nlink = 2;
509 /* but ic->pino_nlink is the parent ino# */
510 f->inocache->pino_nlink = dir_i->i_ino;
511
501 ri->data_crc = cpu_to_je32(0); 512 ri->data_crc = cpu_to_je32(0);
502 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 513 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
503 514
@@ -594,17 +605,25 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
594 605
595static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) 606static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
596{ 607{
608 struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
609 struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
597 struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); 610 struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
598 struct jffs2_full_dirent *fd; 611 struct jffs2_full_dirent *fd;
599 int ret; 612 int ret;
613 uint32_t now = get_seconds();
600 614
601 for (fd = f->dents ; fd; fd = fd->next) { 615 for (fd = f->dents ; fd; fd = fd->next) {
602 if (fd->ino) 616 if (fd->ino)
603 return -ENOTEMPTY; 617 return -ENOTEMPTY;
604 } 618 }
605 ret = jffs2_unlink(dir_i, dentry); 619
606 if (!ret) 620 ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
621 dentry->d_name.len, f, now);
622 if (!ret) {
623 dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
624 clear_nlink(dentry->d_inode);
607 drop_nlink(dir_i); 625 drop_nlink(dir_i);
626 }
608 return ret; 627 return ret;
609} 628}
610 629
@@ -817,7 +836,10 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
817 inode which didn't exist. */ 836 inode which didn't exist. */
818 if (victim_f->inocache) { 837 if (victim_f->inocache) {
819 mutex_lock(&victim_f->sem); 838 mutex_lock(&victim_f->sem);
820 victim_f->inocache->nlink--; 839 if (S_ISDIR(new_dentry->d_inode->i_mode))
840 victim_f->inocache->pino_nlink = 0;
841 else
842 victim_f->inocache->pino_nlink--;
821 mutex_unlock(&victim_f->sem); 843 mutex_unlock(&victim_f->sem);
822 } 844 }
823 } 845 }
@@ -838,8 +860,8 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
838 struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); 860 struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
839 mutex_lock(&f->sem); 861 mutex_lock(&f->sem);
840 inc_nlink(old_dentry->d_inode); 862 inc_nlink(old_dentry->d_inode);
841 if (f->inocache) 863 if (f->inocache && !S_ISDIR(old_dentry->d_inode->i_mode))
842 f->inocache->nlink++; 864 f->inocache->pino_nlink++;
843 mutex_unlock(&f->sem); 865 mutex_unlock(&f->sem);
844 866
845 printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret); 867 printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index 25a640e566d3..dddb2a6c9e2c 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -294,7 +294,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
294 break; 294 break;
295#endif 295#endif
296 default: 296 default:
297 if (ic->nodes == (void *)ic && ic->nlink == 0) 297 if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
298 jffs2_del_ino_cache(c, ic); 298 jffs2_del_ino_cache(c, ic);
299 } 299 }
300} 300}
@@ -332,7 +332,8 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
332 if (c->mtd->point) { 332 if (c->mtd->point) {
333 unsigned long *wordebuf; 333 unsigned long *wordebuf;
334 334
335 ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf); 335 ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size,
336 &retlen, &ebuf, NULL);
336 if (ret) { 337 if (ret) {
337 D1(printk(KERN_DEBUG "MTD point failed %d\n", ret)); 338 D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
338 goto do_flash_read; 339 goto do_flash_read;
@@ -340,7 +341,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
340 if (retlen < c->sector_size) { 341 if (retlen < c->sector_size) {
341 /* Don't muck about if it won't let us point to the whole erase sector */ 342 /* Don't muck about if it won't let us point to the whole erase sector */
342 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen)); 343 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
343 c->mtd->unpoint(c->mtd, ebuf, jeb->offset, retlen); 344 c->mtd->unpoint(c->mtd, jeb->offset, retlen);
344 goto do_flash_read; 345 goto do_flash_read;
345 } 346 }
346 wordebuf = ebuf-sizeof(*wordebuf); 347 wordebuf = ebuf-sizeof(*wordebuf);
@@ -349,7 +350,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
349 if (*++wordebuf != ~0) 350 if (*++wordebuf != ~0)
350 break; 351 break;
351 } while(--retlen); 352 } while(--retlen);
352 c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size); 353 c->mtd->unpoint(c->mtd, jeb->offset, c->sector_size);
353 if (retlen) { 354 if (retlen) {
354 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n", 355 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
355 *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf)); 356 *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 3eb1c84b0a33..086c43830221 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -273,7 +273,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
273 inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime)); 273 inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
274 inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime)); 274 inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));
275 275
276 inode->i_nlink = f->inocache->nlink; 276 inode->i_nlink = f->inocache->pino_nlink;
277 277
278 inode->i_blocks = (inode->i_size + 511) >> 9; 278 inode->i_blocks = (inode->i_size + 511) >> 9;
279 279
@@ -286,13 +286,12 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
286 case S_IFDIR: 286 case S_IFDIR:
287 { 287 {
288 struct jffs2_full_dirent *fd; 288 struct jffs2_full_dirent *fd;
289 inode->i_nlink = 2; /* parent and '.' */
289 290
290 for (fd=f->dents; fd; fd = fd->next) { 291 for (fd=f->dents; fd; fd = fd->next) {
291 if (fd->type == DT_DIR && fd->ino) 292 if (fd->type == DT_DIR && fd->ino)
292 inc_nlink(inode); 293 inc_nlink(inode);
293 } 294 }
294 /* and '..' */
295 inc_nlink(inode);
296 /* Root dir gets i_nlink 3 for some reason */ 295 /* Root dir gets i_nlink 3 for some reason */
297 if (inode->i_ino == 1) 296 if (inode->i_ino == 1)
298 inc_nlink(inode); 297 inc_nlink(inode);
@@ -586,11 +585,12 @@ void jffs2_gc_release_inode(struct jffs2_sb_info *c,
586} 585}
587 586
588struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, 587struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
589 int inum, int nlink) 588 int inum, int unlinked)
590{ 589{
591 struct inode *inode; 590 struct inode *inode;
592 struct jffs2_inode_cache *ic; 591 struct jffs2_inode_cache *ic;
593 if (!nlink) { 592
593 if (unlinked) {
594 /* The inode has zero nlink but its nodes weren't yet marked 594 /* The inode has zero nlink but its nodes weren't yet marked
595 obsolete. This has to be because we're still waiting for 595 obsolete. This has to be because we're still waiting for
596 the final (close() and) iput() to happen. 596 the final (close() and) iput() to happen.
@@ -638,8 +638,8 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
638 return ERR_CAST(inode); 638 return ERR_CAST(inode);
639 } 639 }
640 if (is_bad_inode(inode)) { 640 if (is_bad_inode(inode)) {
641 printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n", 641 printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. unlinked %d\n",
642 inum, nlink); 642 inum, unlinked);
643 /* NB. This will happen again. We need to do something appropriate here. */ 643 /* NB. This will happen again. We need to do something appropriate here. */
644 iput(inode); 644 iput(inode);
645 return ERR_PTR(-EIO); 645 return ERR_PTR(-EIO);
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index bad005664e30..090c556ffed2 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -161,8 +161,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
161 continue; 161 continue;
162 } 162 }
163 163
164 if (!ic->nlink) { 164 if (!ic->pino_nlink) {
165 D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n", 165 D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink/pino zero\n",
166 ic->ino)); 166 ic->ino));
167 spin_unlock(&c->inocache_lock); 167 spin_unlock(&c->inocache_lock);
168 jffs2_xattr_delete_inode(c, ic); 168 jffs2_xattr_delete_inode(c, ic);
@@ -398,10 +398,10 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
398 it's vaguely possible. */ 398 it's vaguely possible. */
399 399
400 inum = ic->ino; 400 inum = ic->ino;
401 nlink = ic->nlink; 401 nlink = ic->pino_nlink;
402 spin_unlock(&c->inocache_lock); 402 spin_unlock(&c->inocache_lock);
403 403
404 f = jffs2_gc_fetch_inode(c, inum, nlink); 404 f = jffs2_gc_fetch_inode(c, inum, !nlink);
405 if (IS_ERR(f)) { 405 if (IS_ERR(f)) {
406 ret = PTR_ERR(f); 406 ret = PTR_ERR(f);
407 goto release_sem; 407 goto release_sem;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 8219df6eb6d8..1750445556c3 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -177,7 +177,10 @@ struct jffs2_inode_cache {
177#ifdef CONFIG_JFFS2_FS_XATTR 177#ifdef CONFIG_JFFS2_FS_XATTR
178 struct jffs2_xattr_ref *xref; 178 struct jffs2_xattr_ref *xref;
179#endif 179#endif
180 int nlink; 180 uint32_t pino_nlink; /* Directories store parent inode
181 here; other inodes store nlink.
182 Zero always means that it's
183 completely unlinked. */
181}; 184};
182 185
183/* Inode states for 'state' above. We need the 'GC' state to prevent 186/* Inode states for 'state' above. We need the 'GC' state to prevent
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 9df8f3ef20df..a9bf9603c1ba 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -709,7 +709,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
709 break; 709 break;
710#endif 710#endif
711 default: 711 default:
712 if (ic->nodes == (void *)ic && ic->nlink == 0) 712 if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
713 jffs2_del_ino_cache(c, ic); 713 jffs2_del_ino_cache(c, ic);
714 break; 714 break;
715 } 715 }
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 1b10d2594092..2cc866cf134f 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -187,7 +187,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent);
187void jffs2_gc_release_inode(struct jffs2_sb_info *c, 187void jffs2_gc_release_inode(struct jffs2_sb_info *c,
188 struct jffs2_inode_info *f); 188 struct jffs2_inode_info *f);
189struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, 189struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
190 int inum, int nlink); 190 int inum, int unlinked);
191 191
192unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, 192unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
193 struct jffs2_inode_info *f, 193 struct jffs2_inode_info *f,
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 4cb4d76de07f..6ca08ad887c0 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -63,10 +63,11 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
63 /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), 63 /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
64 * adding and jffs2_flash_read_end() interface. */ 64 * adding and jffs2_flash_read_end() interface. */
65 if (c->mtd->point) { 65 if (c->mtd->point) {
66 err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); 66 err = c->mtd->point(c->mtd, ofs, len, &retlen,
67 (void **)&buffer, NULL);
67 if (!err && retlen < len) { 68 if (!err && retlen < len) {
68 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); 69 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
69 c->mtd->unpoint(c->mtd, buffer, ofs, retlen); 70 c->mtd->unpoint(c->mtd, ofs, retlen);
70 } else if (err) 71 } else if (err)
71 JFFS2_WARNING("MTD point failed: error code %d.\n", err); 72 JFFS2_WARNING("MTD point failed: error code %d.\n", err);
72 else 73 else
@@ -100,7 +101,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
100 kfree(buffer); 101 kfree(buffer);
101#ifndef __ECOS 102#ifndef __ECOS
102 else 103 else
103 c->mtd->unpoint(c->mtd, buffer, ofs, len); 104 c->mtd->unpoint(c->mtd, ofs, len);
104#endif 105#endif
105 106
106 if (crc != tn->data_crc) { 107 if (crc != tn->data_crc) {
@@ -136,7 +137,7 @@ free_out:
136 kfree(buffer); 137 kfree(buffer);
137#ifndef __ECOS 138#ifndef __ECOS
138 else 139 else
139 c->mtd->unpoint(c->mtd, buffer, ofs, len); 140 c->mtd->unpoint(c->mtd, ofs, len);
140#endif 141#endif
141 return err; 142 return err;
142} 143}
@@ -1123,7 +1124,8 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
1123 size_t retlen; 1124 size_t retlen;
1124 int ret; 1125 int ret;
1125 1126
1126 dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); 1127 dbg_readinode("ino #%u pino/nlink is %d\n", f->inocache->ino,
1128 f->inocache->pino_nlink);
1127 1129
1128 memset(&rii, 0, sizeof(rii)); 1130 memset(&rii, 0, sizeof(rii));
1129 1131
@@ -1358,7 +1360,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
1358 } 1360 }
1359 dbg_readinode("creating inocache for root inode\n"); 1361 dbg_readinode("creating inocache for root inode\n");
1360 memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); 1362 memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
1361 f->inocache->ino = f->inocache->nlink = 1; 1363 f->inocache->ino = f->inocache->pino_nlink = 1;
1362 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; 1364 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
1363 f->inocache->state = INO_STATE_READING; 1365 f->inocache->state = INO_STATE_READING;
1364 jffs2_add_ino_cache(c, f->inocache); 1366 jffs2_add_ino_cache(c, f->inocache);
@@ -1401,7 +1403,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
1401 jffs2_clear_acl(f); 1403 jffs2_clear_acl(f);
1402 jffs2_xattr_delete_inode(c, f->inocache); 1404 jffs2_xattr_delete_inode(c, f->inocache);
1403 mutex_lock(&f->sem); 1405 mutex_lock(&f->sem);
1404 deleted = f->inocache && !f->inocache->nlink; 1406 deleted = f->inocache && !f->inocache->pino_nlink;
1405 1407
1406 if (f->inocache && f->inocache->state != INO_STATE_CHECKING) 1408 if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
1407 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING); 1409 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 272872d27fd5..1d437de1e9a8 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -97,11 +97,12 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
97 size_t pointlen; 97 size_t pointlen;
98 98
99 if (c->mtd->point) { 99 if (c->mtd->point) {
100 ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf); 100 ret = c->mtd->point(c->mtd, 0, c->mtd->size, &pointlen,
101 (void **)&flashbuf, NULL);
101 if (!ret && pointlen < c->mtd->size) { 102 if (!ret && pointlen < c->mtd->size) {
102 /* Don't muck about if it won't let us point to the whole flash */ 103 /* Don't muck about if it won't let us point to the whole flash */
103 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen)); 104 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen));
104 c->mtd->unpoint(c->mtd, flashbuf, 0, pointlen); 105 c->mtd->unpoint(c->mtd, 0, pointlen);
105 flashbuf = NULL; 106 flashbuf = NULL;
106 } 107 }
107 if (ret) 108 if (ret)
@@ -267,7 +268,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
267 kfree(flashbuf); 268 kfree(flashbuf);
268#ifndef __ECOS 269#ifndef __ECOS
269 else 270 else
270 c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); 271 c->mtd->unpoint(c->mtd, 0, c->mtd->size);
271#endif 272#endif
272 if (s) 273 if (s)
273 kfree(s); 274 kfree(s);
@@ -940,7 +941,7 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin
940 ic->nodes = (void *)ic; 941 ic->nodes = (void *)ic;
941 jffs2_add_ino_cache(c, ic); 942 jffs2_add_ino_cache(c, ic);
942 if (ino == 1) 943 if (ino == 1)
943 ic->nlink = 1; 944 ic->pino_nlink = 1;
944 return ic; 945 return ic;
945} 946}
946 947
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index f3353df178e7..7da69eae49e4 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -31,11 +31,12 @@ static struct kmem_cache *jffs2_inode_cachep;
31 31
32static struct inode *jffs2_alloc_inode(struct super_block *sb) 32static struct inode *jffs2_alloc_inode(struct super_block *sb)
33{ 33{
34 struct jffs2_inode_info *ei; 34 struct jffs2_inode_info *f;
35 ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL); 35
36 if (!ei) 36 f = kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL);
37 if (!f)
37 return NULL; 38 return NULL;
38 return &ei->vfs_inode; 39 return &f->vfs_inode;
39} 40}
40 41
41static void jffs2_destroy_inode(struct inode *inode) 42static void jffs2_destroy_inode(struct inode *inode)
@@ -45,10 +46,10 @@ static void jffs2_destroy_inode(struct inode *inode)
45 46
46static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo) 47static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
47{ 48{
48 struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; 49 struct jffs2_inode_info *f = foo;
49 50
50 mutex_init(&ei->sem); 51 mutex_init(&f->sem);
51 inode_init_once(&ei->vfs_inode); 52 inode_init_once(&f->vfs_inode);
52} 53}
53 54
54static int jffs2_sync_fs(struct super_block *sb, int wait) 55static int jffs2_sync_fs(struct super_block *sb, int wait)
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 8de52b607678..0e78b00035e4 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -494,7 +494,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
494 /* If it's an in-core inode, then we have to adjust any 494 /* If it's an in-core inode, then we have to adjust any
495 full_dirent or full_dnode structure to point to the 495 full_dirent or full_dnode structure to point to the
496 new version instead of the old */ 496 new version instead of the old */
497 f = jffs2_gc_fetch_inode(c, ic->ino, ic->nlink); 497 f = jffs2_gc_fetch_inode(c, ic->ino, !ic->pino_nlink);
498 if (IS_ERR(f)) { 498 if (IS_ERR(f)) {
499 /* Should never happen; it _must_ be present */ 499 /* Should never happen; it _must_ be present */
500 JFFS2_ERROR("Failed to iget() ino #%u, err %ld\n", 500 JFFS2_ERROR("Failed to iget() ino #%u, err %ld\n",
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 665fce9797d3..ca29440e9435 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -19,7 +19,8 @@
19#include "compr.h" 19#include "compr.h"
20 20
21 21
22int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri) 22int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
23 uint32_t mode, struct jffs2_raw_inode *ri)
23{ 24{
24 struct jffs2_inode_cache *ic; 25 struct jffs2_inode_cache *ic;
25 26
@@ -31,7 +32,7 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint
31 memset(ic, 0, sizeof(*ic)); 32 memset(ic, 0, sizeof(*ic));
32 33
33 f->inocache = ic; 34 f->inocache = ic;
34 f->inocache->nlink = 1; 35 f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
35 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; 36 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
36 f->inocache->state = INO_STATE_PRESENT; 37 f->inocache->state = INO_STATE_PRESENT;
37 38
@@ -438,10 +439,10 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
438 ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, 439 ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
439 JFFS2_SUMMARY_INODE_SIZE); 440 JFFS2_SUMMARY_INODE_SIZE);
440 D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); 441 D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
441 if (ret) { 442 if (ret)
442 mutex_unlock(&f->sem);
443 return ret; 443 return ret;
444 } 444
445 mutex_lock(&f->sem);
445 446
446 ri->data_crc = cpu_to_je32(0); 447 ri->data_crc = cpu_to_je32(0);
447 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 448 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
@@ -635,9 +636,9 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
635 jffs2_mark_node_obsolete(c, fd->raw); 636 jffs2_mark_node_obsolete(c, fd->raw);
636 jffs2_free_full_dirent(fd); 637 jffs2_free_full_dirent(fd);
637 } 638 }
638 } 639 dead_f->inocache->pino_nlink = 0;
639 640 } else
640 dead_f->inocache->nlink--; 641 dead_f->inocache->pino_nlink--;
641 /* NB: Caller must set inode nlink if appropriate */ 642 /* NB: Caller must set inode nlink if appropriate */
642 mutex_unlock(&dead_f->sem); 643 mutex_unlock(&dead_f->sem);
643 } 644 }
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index e48665984cb3..082e844ab2db 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -82,7 +82,7 @@ static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_
82static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 82static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
83{ 83{
84 /* must be called under down_write(xattr_sem) */ 84 /* must be called under down_write(xattr_sem) */
85 D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version)); 85 D1(dbg_xattr("%s: xid=%u, version=%u\n", __func__, xd->xid, xd->version));
86 if (xd->xname) { 86 if (xd->xname) {
87 c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len); 87 c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
88 kfree(xd->xname); 88 kfree(xd->xname);
@@ -592,7 +592,7 @@ void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache
592 When an inode with XATTR is removed, those XATTRs must be removed. */ 592 When an inode with XATTR is removed, those XATTRs must be removed. */
593 struct jffs2_xattr_ref *ref, *_ref; 593 struct jffs2_xattr_ref *ref, *_ref;
594 594
595 if (!ic || ic->nlink > 0) 595 if (!ic || ic->pino_nlink > 0)
596 return; 596 return;
597 597
598 down_write(&c->xattr_sem); 598 down_write(&c->xattr_sem);
@@ -829,7 +829,7 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
829 ref->xd and ref->ic are not valid yet. */ 829 ref->xd and ref->ic are not valid yet. */
830 xd = jffs2_find_xattr_datum(c, ref->xid); 830 xd = jffs2_find_xattr_datum(c, ref->xid);
831 ic = jffs2_get_ino_cache(c, ref->ino); 831 ic = jffs2_get_ino_cache(c, ref->ino);
832 if (!xd || !ic || !ic->nlink) { 832 if (!xd || !ic || !ic->pino_nlink) {
833 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n", 833 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
834 ref->ino, ref->xid, ref->xseqno); 834 ref->ino, ref->xid, ref->xseqno);
835 ref->xseqno |= XREF_DELETE_MARKER; 835 ref->xseqno |= XREF_DELETE_MARKER;
@@ -1252,7 +1252,7 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
1252 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); 1252 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
1253 if (rc) { 1253 if (rc) {
1254 JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n", 1254 JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
1255 __FUNCTION__, rc, totlen); 1255 __func__, rc, totlen);
1256 rc = rc ? rc : -EBADFD; 1256 rc = rc ? rc : -EBADFD;
1257 goto out; 1257 goto out;
1258 } 1258 }