aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/dir.c')
-rw-r--r--fs/jffs2/dir.c42
1 files changed, 32 insertions, 10 deletions
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);