diff options
Diffstat (limited to 'fs/jffs2/dir.c')
-rw-r--r-- | fs/jffs2/dir.c | 42 |
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 | ||
595 | static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) | 606 | static 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); |