@@ -210,6 +210,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry,
f->inocache->pino_nlink, inode->i_mapping->nrpages);
d_instantiate_new(dentry, inode);
+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
return 0;
fail:
@@ -430,6 +431,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
jffs2_complete_reservation(c);
d_instantiate_new(dentry, inode);
+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
return 0;
fail:
@@ -574,6 +576,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
jffs2_complete_reservation(c);
d_instantiate_new(dentry, inode);
+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
return 0;
fail:
@@ -745,6 +748,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
jffs2_complete_reservation(c);
d_instantiate_new(dentry, inode);
+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
return 0;
fail:
@@ -208,6 +208,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
spin_unlock(&c->inocache_lock);
BUG();
+ /* fall through */
+ case INO_STATE_CREATING:
case INO_STATE_READING:
/* We need to wait for it to finish, lest we move on
and trigger the BUG() above while we haven't yet
@@ -394,6 +396,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
spin_unlock(&c->inocache_lock);
BUG();
+ /* fall through */
+ case INO_STATE_CREATING:
+ /* We can't process this inode while it is being created
+ * to avoid a deadlock condition the inode is locked.
+ * However, to finish the creation we need to unlock the
+ * alloc_sem() and because we dropped the alloc_sem we must
+ * return to start again from the beginning.
+ */
case INO_STATE_READING:
/* Someone's currently trying to read it. We must wait for
them to finish and then go through the full iget() route
@@ -192,6 +192,7 @@ struct jffs2_inode_cache {
#define INO_STATE_GC 4 /* GCing a 'pristine' node */
#define INO_STATE_READING 5 /* In read_inode() */
#define INO_STATE_CLEARING 6 /* In clear_inode() */
+#define INO_STATE_CREATING 7 /* Inode locked! GC can't touch */
#define INO_FLAGS_XATTR_CHECKED 0x01 /* has no duplicate xattr_ref */
#define INO_FLAGS_IS_DIR 0x02 /* is a directory */
@@ -1336,6 +1336,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
goto retry_inocache;
case INO_STATE_READING:
+ case INO_STATE_CREATING:
case INO_STATE_PRESENT:
/* Eep. This should never happen. It can
happen if Linux calls read_inode() again
@@ -518,7 +518,8 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
(void *)(buf?:c->wbuf) + (ref_offset(raw) - start));
} else if (unlikely(ic->state != INO_STATE_PRESENT &&
ic->state != INO_STATE_CHECKEDABSENT &&
- ic->state != INO_STATE_GC)) {
+ ic->state != INO_STATE_GC &&
+ ic->state != INO_STATE_CREATING)) {
JFFS2_ERROR("Inode #%u is in strange state %d!\n", ic->ino, ic->state);
BUG();
}
@@ -35,7 +35,11 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
f->inocache = ic;
f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
- f->inocache->state = INO_STATE_PRESENT;
+ f->inocache->state = INO_STATE_CREATING;
+ /* The initial state can't be INO_STATE_PRESENT to avoid a deadlock in
+ * GC because the new inode is still locked and the GC needs to lock
+ * the inode to get it.
+ */
jffs2_add_ino_cache(c, f->inocache);
jffs2_dbg(1, "%s(): Assigned ino# %d\n", __func__, f->inocache->ino);
Correct AB-BA deadlock between the GC kthread and a process that is creating a new file, symlink, and etc. Create a new JFFS2 inode state to signalizing that the inode can't be acquired by the GC because is being created. When this state happens, the GC releases the alloc_sem, sleep, and then tries again. To create a new file, the JFSS2 request a new locked inode to the Linux's FS layer and then insert inside of some JFFS2's Erase Block. To finish the creation, the process needs to acquire the alloc_sem semaphore. Just at the end that the inode is released by the JFFS2. If the GC starts to process an Erase Block that contains an inode that is being created, can occur an AB-BA deadlock if the GC acquires the alloc_sem before the end of the inode's creation because the CG needs to acquire all inodes inside the EB to finish the iteration. This deadlock can occur more frequently with partition mounted with sync flag (not usual). Signed-off-by: Wagner Popov dos Santos <wpopov@gmail.com> --- fs/jffs2/dir.c | 4 ++++ fs/jffs2/gc.c | 10 ++++++++++ fs/jffs2/nodelist.h | 1 + fs/jffs2/readinode.c | 1 + fs/jffs2/wbuf.c | 3 ++- fs/jffs2/write.c | 6 +++++- 6 files changed, 23 insertions(+), 2 deletions(-)