[JFFS2] semaphore->mutex conversion
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
This commit is contained in:
Родитель
52f8301437
Коммит
ced2207036
|
@ -14,7 +14,7 @@ be fairly close.
|
|||
alloc_sem
|
||||
---------
|
||||
|
||||
The alloc_sem is a per-filesystem semaphore, used primarily to ensure
|
||||
The alloc_sem is a per-filesystem mutex, used primarily to ensure
|
||||
contiguous allocation of space on the medium. It is automatically
|
||||
obtained during space allocations (jffs2_reserve_space()) and freed
|
||||
upon write completion (jffs2_complete_reservation()). Note that
|
||||
|
@ -41,10 +41,10 @@ if the wbuf is currently holding any data is permitted, though.
|
|||
Ordering constraints: See f->sem.
|
||||
|
||||
|
||||
File Semaphore f->sem
|
||||
File Mutex f->sem
|
||||
---------------------
|
||||
|
||||
This is the JFFS2-internal equivalent of the inode semaphore i->i_sem.
|
||||
This is the JFFS2-internal equivalent of the inode mutex i->i_sem.
|
||||
It protects the contents of the jffs2_inode_info private inode data,
|
||||
including the linked list of node fragments (but see the notes below on
|
||||
erase_completion_lock), etc.
|
||||
|
@ -60,14 +60,14 @@ lead to deadlock, unless we played games with unlocking the i_sem
|
|||
before calling the space allocation functions.
|
||||
|
||||
Instead of playing such games, we just have an extra internal
|
||||
semaphore, which is obtained by the garbage collection code and also
|
||||
mutex, which is obtained by the garbage collection code and also
|
||||
by the normal file system code _after_ allocation of space.
|
||||
|
||||
Ordering constraints:
|
||||
|
||||
1. Never attempt to allocate space or lock alloc_sem with
|
||||
any f->sem held.
|
||||
2. Never attempt to lock two file semaphores in one thread.
|
||||
2. Never attempt to lock two file mutexes in one thread.
|
||||
No ordering rules have been made for doing so.
|
||||
|
||||
|
||||
|
@ -86,8 +86,8 @@ a simple spin_lock() rather than spin_lock_bh().
|
|||
|
||||
Note that the per-inode list of physical nodes (f->nodes) is a special
|
||||
case. Any changes to _valid_ nodes (i.e. ->flash_offset & 1 == 0) in
|
||||
the list are protected by the file semaphore f->sem. But the erase
|
||||
code may remove _obsolete_ nodes from the list while holding only the
|
||||
the list are protected by the file mutex f->sem. But the erase code
|
||||
may remove _obsolete_ nodes from the list while holding only the
|
||||
erase_completion_lock. So you can walk the list only while holding the
|
||||
erase_completion_lock, and can drop the lock temporarily mid-walk as
|
||||
long as the pointer you're holding is to a _valid_ node, not an
|
||||
|
@ -124,10 +124,10 @@ Ordering constraints:
|
|||
erase_free_sem
|
||||
--------------
|
||||
|
||||
This semaphore is only used by the erase code which frees obsolete
|
||||
node references and the jffs2_garbage_collect_deletion_dirent()
|
||||
function. The latter function on NAND flash must read _obsolete_ nodes
|
||||
to determine whether the 'deletion dirent' under consideration can be
|
||||
This mutex is only used by the erase code which frees obsolete node
|
||||
references and the jffs2_garbage_collect_deletion_dirent() function.
|
||||
The latter function on NAND flash must read _obsolete_ nodes to
|
||||
determine whether the 'deletion dirent' under consideration can be
|
||||
discarded or whether it is still required to show that an inode has
|
||||
been unlinked. Because reading from the flash may sleep, the
|
||||
erase_completion_lock cannot be held, so an alternative, more
|
||||
|
|
|
@ -62,9 +62,9 @@ __jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
|
|||
void
|
||||
__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
|
||||
{
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
__jffs2_dbg_fragtree_paranoia_check_nolock(f);
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -532,9 +532,9 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
|
|||
void
|
||||
__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
|
||||
{
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
jffs2_dbg_dump_fragtree_nolock(f);
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -86,7 +86,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
|
|||
dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
c = JFFS2_SB_INFO(dir_i->i_sb);
|
||||
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
/* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
|
||||
for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) {
|
||||
|
@ -99,7 +99,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
|
|||
}
|
||||
if (fd)
|
||||
ino = fd->ino;
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
if (ino) {
|
||||
inode = jffs2_iget(dir_i->i_sb, ino);
|
||||
if (IS_ERR(inode)) {
|
||||
|
@ -146,7 +146,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||
}
|
||||
|
||||
curofs=1;
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
for (fd = f->dents; fd; fd = fd->next) {
|
||||
|
||||
curofs++;
|
||||
|
@ -166,7 +166,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||
break;
|
||||
offset++;
|
||||
}
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
out:
|
||||
filp->f_pos = offset;
|
||||
return 0;
|
||||
|
@ -275,9 +275,9 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
|
|||
ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now);
|
||||
|
||||
if (!ret) {
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
d_instantiate(dentry, old_dentry->d_inode);
|
||||
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
|
||||
atomic_inc(&old_dentry->d_inode->i_count);
|
||||
|
@ -351,7 +351,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
|
|||
|
||||
if (IS_ERR(fn)) {
|
||||
/* Eeek. Wave bye bye */
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_clear_inode(inode);
|
||||
return PTR_ERR(fn);
|
||||
|
@ -361,7 +361,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
|
|||
f->target = kmalloc(targetlen + 1, GFP_KERNEL);
|
||||
if (!f->target) {
|
||||
printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_clear_inode(inode);
|
||||
return -ENOMEM;
|
||||
|
@ -374,7 +374,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
|
|||
obsoleted by the first data write
|
||||
*/
|
||||
f->metadata = fn;
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
|
@ -406,7 +406,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
|
|||
}
|
||||
|
||||
dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
|
||||
rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
|
||||
|
@ -429,7 +429,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
|
|||
as if it were the final unlink() */
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_free_raw_dirent(rd);
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
jffs2_clear_inode(inode);
|
||||
return PTR_ERR(fd);
|
||||
}
|
||||
|
@ -442,7 +442,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
|
|||
one if necessary. */
|
||||
jffs2_add_fd_to_list(c, fd, &dir_f->dents);
|
||||
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
d_instantiate(dentry, inode);
|
||||
|
@ -507,7 +507,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
|
|||
|
||||
if (IS_ERR(fn)) {
|
||||
/* Eeek. Wave bye bye */
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_clear_inode(inode);
|
||||
return PTR_ERR(fn);
|
||||
|
@ -516,7 +516,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
|
|||
obsoleted by the first data write
|
||||
*/
|
||||
f->metadata = fn;
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
|
@ -548,7 +548,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
|
|||
}
|
||||
|
||||
dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
|
||||
rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
|
||||
|
@ -571,7 +571,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
|
|||
as if it were the final unlink() */
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_free_raw_dirent(rd);
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
jffs2_clear_inode(inode);
|
||||
return PTR_ERR(fd);
|
||||
}
|
||||
|
@ -585,7 +585,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
|
|||
one if necessary. */
|
||||
jffs2_add_fd_to_list(c, fd, &dir_f->dents);
|
||||
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
d_instantiate(dentry, inode);
|
||||
|
@ -673,7 +673,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
|
|||
|
||||
if (IS_ERR(fn)) {
|
||||
/* Eeek. Wave bye bye */
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_clear_inode(inode);
|
||||
return PTR_ERR(fn);
|
||||
|
@ -682,7 +682,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
|
|||
obsoleted by the first data write
|
||||
*/
|
||||
f->metadata = fn;
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
|
@ -714,7 +714,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
|
|||
}
|
||||
|
||||
dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
|
||||
rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
|
||||
|
@ -740,7 +740,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
|
|||
as if it were the final unlink() */
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_free_raw_dirent(rd);
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
jffs2_clear_inode(inode);
|
||||
return PTR_ERR(fd);
|
||||
}
|
||||
|
@ -753,7 +753,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
|
|||
one if necessary. */
|
||||
jffs2_add_fd_to_list(c, fd, &dir_f->dents);
|
||||
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
d_instantiate(dentry, inode);
|
||||
|
@ -780,14 +780,14 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
|
|||
if (S_ISDIR(new_dentry->d_inode->i_mode)) {
|
||||
struct jffs2_full_dirent *fd;
|
||||
|
||||
down(&victim_f->sem);
|
||||
mutex_lock(&victim_f->sem);
|
||||
for (fd = victim_f->dents; fd; fd = fd->next) {
|
||||
if (fd->ino) {
|
||||
up(&victim_f->sem);
|
||||
mutex_unlock(&victim_f->sem);
|
||||
return -ENOTEMPTY;
|
||||
}
|
||||
}
|
||||
up(&victim_f->sem);
|
||||
mutex_unlock(&victim_f->sem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -816,9 +816,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
|
|||
/* Don't oops if the victim was a dirent pointing to an
|
||||
inode which didn't exist. */
|
||||
if (victim_f->inocache) {
|
||||
down(&victim_f->sem);
|
||||
mutex_lock(&victim_f->sem);
|
||||
victim_f->inocache->nlink--;
|
||||
up(&victim_f->sem);
|
||||
mutex_unlock(&victim_f->sem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,11 +836,11 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
|
|||
if (ret) {
|
||||
/* Oh shit. We really ought to make a single node which can do both atomically */
|
||||
struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
inc_nlink(old_dentry->d_inode);
|
||||
if (f->inocache)
|
||||
f->inocache->nlink++;
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
|
||||
printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
|
||||
/* Might as well let the VFS know */
|
||||
|
|
|
@ -50,14 +50,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
|
|||
instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
|
||||
if (!instr) {
|
||||
printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
list_move(&jeb->list, &c->erase_pending_list);
|
||||
c->erasing_size -= c->sector_size;
|
||||
c->dirty_size += c->sector_size;
|
||||
jeb->dirty_size = c->sector_size;
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -84,14 +84,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
|
|||
if (ret == -ENOMEM || ret == -EAGAIN) {
|
||||
/* Erase failed immediately. Refile it on the list */
|
||||
D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
list_move(&jeb->list, &c->erase_pending_list);
|
||||
c->erasing_size -= c->sector_size;
|
||||
c->dirty_size += c->sector_size;
|
||||
jeb->dirty_size = c->sector_size;
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
|
|||
{
|
||||
struct jffs2_eraseblock *jeb;
|
||||
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
|
||||
|
@ -118,7 +118,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
|
|||
jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
|
||||
list_del(&jeb->list);
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
jffs2_mark_erased_block(c, jeb);
|
||||
|
||||
if (!--count) {
|
||||
|
@ -139,7 +139,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
|
|||
jffs2_free_jeb_node_refs(c, jeb);
|
||||
list_add(&jeb->list, &c->erasing_list);
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
|
||||
jffs2_erase_block(c, jeb);
|
||||
|
||||
|
@ -149,12 +149,12 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
|
|||
|
||||
/* Be nice */
|
||||
yield();
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
}
|
||||
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
done:
|
||||
D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
|
||||
}
|
||||
|
@ -162,11 +162,11 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
|
|||
static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
|
||||
{
|
||||
D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
list_move_tail(&jeb->list, &c->erase_complete_list);
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
/* Ensure that kupdated calls us again to mark them clean */
|
||||
jffs2_erase_pending_trigger(c);
|
||||
}
|
||||
|
@ -180,26 +180,26 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock
|
|||
failed too many times. */
|
||||
if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
|
||||
/* We'd like to give this block another try. */
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
list_move(&jeb->list, &c->erase_pending_list);
|
||||
c->erasing_size -= c->sector_size;
|
||||
c->dirty_size += c->sector_size;
|
||||
jeb->dirty_size = c->sector_size;
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
c->erasing_size -= c->sector_size;
|
||||
c->bad_size += c->sector_size;
|
||||
list_move(&jeb->list, &c->bad_list);
|
||||
c->nr_erasing_blocks--;
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
wake_up(&c->erase_wait);
|
||||
}
|
||||
|
||||
|
@ -456,7 +456,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
|
|||
jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
|
||||
}
|
||||
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
c->erasing_size -= c->sector_size;
|
||||
c->free_size += jeb->free_size;
|
||||
|
@ -469,28 +469,28 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
|
|||
c->nr_erasing_blocks--;
|
||||
c->nr_free_blocks++;
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
wake_up(&c->erase_wait);
|
||||
return;
|
||||
|
||||
filebad:
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
/* Stick it on a list (any list) so erase_failed can take it
|
||||
right off again. Silly, but shouldn't happen often. */
|
||||
list_add(&jeb->list, &c->erasing_list);
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
jffs2_erase_failed(c, jeb, bad_offset);
|
||||
return;
|
||||
|
||||
refile:
|
||||
/* Stick it back on the list from whence it came and come back later */
|
||||
jffs2_erase_pending_trigger(c);
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
list_add(&jeb->list, &c->erase_complete_list);
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -115,9 +115,9 @@ static int jffs2_readpage (struct file *filp, struct page *pg)
|
|||
struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host);
|
||||
int ret;
|
||||
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
ret = jffs2_do_readpage_unlock(pg->mapping->host, pg);
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
|
|||
if (ret)
|
||||
goto out_page;
|
||||
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
memset(&ri, 0, sizeof(ri));
|
||||
|
||||
ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
|
||||
|
@ -181,7 +181,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
|
|||
if (IS_ERR(fn)) {
|
||||
ret = PTR_ERR(fn);
|
||||
jffs2_complete_reservation(c);
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
goto out_page;
|
||||
}
|
||||
ret = jffs2_add_full_dnode_to_inode(c, f, fn);
|
||||
|
@ -195,12 +195,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
|
|||
jffs2_mark_node_obsolete(c, fn->raw);
|
||||
jffs2_free_full_dnode(fn);
|
||||
jffs2_complete_reservation(c);
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
goto out_page;
|
||||
}
|
||||
jffs2_complete_reservation(c);
|
||||
inode->i_size = pageofs;
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -209,9 +209,9 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
|
|||
* case of a short-copy.
|
||||
*/
|
||||
if (!PageUptodate(pg)) {
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
ret = jffs2_do_readpage_nolock(inode, pg);
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
if (ret)
|
||||
goto out_page;
|
||||
}
|
||||
|
|
|
@ -51,20 +51,20 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
|
|||
mdata = (char *)&dev;
|
||||
D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
mdatalen = f->metadata->size;
|
||||
mdata = kmalloc(f->metadata->size, GFP_USER);
|
||||
if (!mdata) {
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
|
||||
if (ret) {
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
kfree(mdata);
|
||||
return ret;
|
||||
}
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
|
|||
kfree(mdata);
|
||||
return ret;
|
||||
}
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
ivalid = iattr->ia_valid;
|
||||
|
||||
ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
|
||||
|
@ -134,7 +134,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
|
|||
if (IS_ERR(new_metadata)) {
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_free_raw_inode(ri);
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
return PTR_ERR(new_metadata);
|
||||
}
|
||||
/* It worked. Update the inode */
|
||||
|
@ -165,7 +165,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
|
|||
}
|
||||
jffs2_free_raw_inode(ri);
|
||||
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
/* We have to do the vmtruncate() without f->sem held, since
|
||||
|
@ -256,12 +256,12 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
|
|||
c = JFFS2_SB_INFO(inode->i_sb);
|
||||
|
||||
jffs2_init_inode_info(f);
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
|
||||
ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
|
||||
|
||||
if (ret) {
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
iget_failed(inode);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
|
|||
printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino);
|
||||
}
|
||||
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
|
||||
D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
|
||||
unlock_new_inode(inode);
|
||||
|
@ -347,7 +347,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
|
|||
error_io:
|
||||
ret = -EIO;
|
||||
error:
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_do_clear_inode(c, f);
|
||||
iget_failed(inode);
|
||||
return ERR_PTR(ret);
|
||||
|
@ -388,9 +388,9 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
|
|||
Flush the writebuffer, if neccecary, else we loose it */
|
||||
if (!(sb->s_flags & MS_RDONLY)) {
|
||||
jffs2_stop_garbage_collect_thread(c);
|
||||
down(&c->alloc_sem);
|
||||
mutex_lock(&c->alloc_sem);
|
||||
jffs2_flush_wbuf_pad(c);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
}
|
||||
|
||||
if (!(*flags & MS_RDONLY))
|
||||
|
@ -437,7 +437,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
|
|||
|
||||
f = JFFS2_INODE_INFO(inode);
|
||||
jffs2_init_inode_info(f);
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
|
||||
memset(ri, 0, sizeof(*ri));
|
||||
/* Set OS-specific defaults for new inodes */
|
||||
|
|
|
@ -126,7 +126,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
int ret = 0, inum, nlink;
|
||||
int xattr = 0;
|
||||
|
||||
if (down_interruptible(&c->alloc_sem))
|
||||
if (mutex_lock_interruptible(&c->alloc_sem))
|
||||
return -EINTR;
|
||||
|
||||
for (;;) {
|
||||
|
@ -143,7 +143,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
c->unchecked_size);
|
||||
jffs2_dbg_dump_block_lists_nolock(c);
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
made no progress in this case, but that should be OK */
|
||||
c->checked_ino--;
|
||||
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
|
||||
return 0;
|
||||
|
||||
|
@ -210,7 +210,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino);
|
||||
|
||||
jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
if (!jeb) {
|
||||
D1 (printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"));
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -232,7 +232,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size));
|
||||
|
||||
if (!jeb->used_size) {
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
goto eraseit;
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size);
|
||||
jeb->gc_node = raw;
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
/* Just mark it obsolete */
|
||||
jffs2_mark_node_obsolete(c, raw);
|
||||
}
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
goto eraseit_lock;
|
||||
}
|
||||
|
||||
|
@ -334,7 +334,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
*/
|
||||
printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n",
|
||||
ic->ino, ic->state);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
spin_unlock(&c->inocache_lock);
|
||||
BUG();
|
||||
|
||||
|
@ -345,7 +345,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
the alloc_sem() (for marking nodes invalid) so we must
|
||||
drop the alloc_sem before sleeping. */
|
||||
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n",
|
||||
ic->ino, ic->state));
|
||||
sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
|
||||
|
@ -416,7 +416,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||
ret = -ENOSPC;
|
||||
}
|
||||
release_sem:
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
|
||||
eraseit_lock:
|
||||
/* If we've finished this block, start it erasing */
|
||||
|
@ -445,7 +445,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era
|
|||
uint32_t start = 0, end = 0, nrfrags = 0;
|
||||
int ret = 0;
|
||||
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
|
||||
/* Now we have the lock for this inode. Check that it's still the one at the head
|
||||
of the list. */
|
||||
|
@ -525,7 +525,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era
|
|||
}
|
||||
}
|
||||
upnout:
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -846,7 +846,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
|
|||
/* Prevent the erase code from nicking the obsolete node refs while
|
||||
we're looking at them. I really don't like this extra lock but
|
||||
can't see any alternative. Suggestions on a postcard to... */
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
|
||||
for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
|
||||
|
||||
|
@ -899,7 +899,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
|
|||
/* OK. The name really does match. There really is still an older node on
|
||||
the flash which our deletion dirent obsoletes. So we have to write out
|
||||
a new deletion dirent to replace it */
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
|
||||
D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n",
|
||||
ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino)));
|
||||
|
@ -908,7 +908,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
|
|||
return jffs2_garbage_collect_dirent(c, jeb, f, fd);
|
||||
}
|
||||
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
kfree(rd);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ struct jffs2_inode_info {
|
|||
before letting GC proceed. Or we'd have to put ugliness
|
||||
into the GC code so it didn't attempt to obtain the i_mutex
|
||||
for the inode(s) which are already locked */
|
||||
struct semaphore sem;
|
||||
struct mutex sem;
|
||||
|
||||
/* The highest (datanode) version number used for this ino */
|
||||
uint32_t highest_version;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/list.h>
|
||||
|
@ -44,7 +44,7 @@ struct jffs2_sb_info {
|
|||
struct completion gc_thread_start; /* GC thread start completion */
|
||||
struct completion gc_thread_exit; /* GC thread exit completion port */
|
||||
|
||||
struct semaphore alloc_sem; /* Used to protect all the following
|
||||
struct mutex alloc_sem; /* Used to protect all the following
|
||||
fields, and also to protect against
|
||||
out-of-order writing of nodes. And GC. */
|
||||
uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER
|
||||
|
@ -104,7 +104,7 @@ struct jffs2_sb_info {
|
|||
/* Sem to allow jffs2_garbage_collect_deletion_dirent to
|
||||
drop the erase_completion_lock while it's holding a pointer
|
||||
to an obsoleted node. I don't like this. Alternatives welcomed. */
|
||||
struct semaphore erase_free_sem;
|
||||
struct mutex erase_free_sem;
|
||||
|
||||
uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
|
|||
minsize = PAD(minsize);
|
||||
|
||||
D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize));
|
||||
down(&c->alloc_sem);
|
||||
mutex_lock(&c->alloc_sem);
|
||||
|
||||
D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n"));
|
||||
|
||||
|
@ -81,7 +81,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
|
|||
dirty, c->unchecked_size, c->sector_size));
|
||||
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
|
@ -104,11 +104,11 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
|
|||
D1(printk(KERN_DEBUG "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
|
||||
avail, blocksneeded * c->sector_size));
|
||||
spin_unlock(&c->erase_completion_lock);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
|
||||
D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n",
|
||||
c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size,
|
||||
|
@ -124,7 +124,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
|
|||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
|
||||
down(&c->alloc_sem);
|
||||
mutex_lock(&c->alloc_sem);
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
|
|||
if (!ret)
|
||||
ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
|
||||
if (ret)
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -462,7 +462,7 @@ void jffs2_complete_reservation(struct jffs2_sb_info *c)
|
|||
{
|
||||
D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n"));
|
||||
jffs2_garbage_collect_trigger(c);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
}
|
||||
|
||||
static inline int on_list(struct list_head *obj, struct list_head *head)
|
||||
|
@ -511,7 +511,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
|
|||
any jffs2_raw_node_refs. So we don't need to stop erases from
|
||||
happening, or protect against people holding an obsolete
|
||||
jffs2_raw_node_ref without the erase_completion_lock. */
|
||||
down(&c->erase_free_sem);
|
||||
mutex_lock(&c->erase_free_sem);
|
||||
}
|
||||
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
|
@ -714,7 +714,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
|
|||
}
|
||||
|
||||
out_erase_sem:
|
||||
up(&c->erase_free_sem);
|
||||
mutex_unlock(&c->erase_free_sem);
|
||||
}
|
||||
|
||||
int jffs2_thread_should_wake(struct jffs2_sb_info *c)
|
||||
|
|
|
@ -1193,7 +1193,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
|
|||
JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
|
||||
ret, retlen, sizeof(*latest_node));
|
||||
/* FIXME: If this fails, there seems to be a memory leak. Find it. */
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_do_clear_inode(c, f);
|
||||
return ret?ret:-EIO;
|
||||
}
|
||||
|
@ -1202,7 +1202,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
|
|||
if (crc != je32_to_cpu(latest_node->node_crc)) {
|
||||
JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
|
||||
f->inocache->ino, ref_offset(rii.latest_ref));
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_do_clear_inode(c, f);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -1242,7 +1242,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
|
|||
f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);
|
||||
if (!f->target) {
|
||||
JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize));
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_do_clear_inode(c, f);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -1255,7 +1255,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
|
|||
ret = -EIO;
|
||||
kfree(f->target);
|
||||
f->target = NULL;
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_do_clear_inode(c, f);
|
||||
return -ret;
|
||||
}
|
||||
|
@ -1273,14 +1273,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
|
|||
if (f->metadata) {
|
||||
JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
|
||||
f->inocache->ino, jemode_to_cpu(latest_node->mode));
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_do_clear_inode(c, f);
|
||||
return -EIO;
|
||||
}
|
||||
if (!frag_first(&f->fragtree)) {
|
||||
JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
|
||||
f->inocache->ino, jemode_to_cpu(latest_node->mode));
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_do_clear_inode(c, f);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -1289,7 +1289,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
|
|||
JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
|
||||
f->inocache->ino, jemode_to_cpu(latest_node->mode));
|
||||
/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_do_clear_inode(c, f);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -1379,12 +1379,13 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
|
|||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
init_MUTEX_LOCKED(&f->sem);
|
||||
mutex_init(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
f->inocache = ic;
|
||||
|
||||
ret = jffs2_do_read_inode_internal(c, f, &n);
|
||||
if (!ret) {
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_do_clear_inode(c, f);
|
||||
}
|
||||
kfree (f);
|
||||
|
@ -1398,7 +1399,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
|
|||
|
||||
jffs2_clear_acl(f);
|
||||
jffs2_xattr_delete_inode(c, f->inocache);
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
deleted = f->inocache && !f->inocache->nlink;
|
||||
|
||||
if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
|
||||
|
@ -1430,5 +1431,5 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
|
|||
jffs2_del_ino_cache(c, f->inocache);
|
||||
}
|
||||
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
|
|||
{
|
||||
struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
|
||||
|
||||
init_MUTEX(&ei->sem);
|
||||
mutex_init(&ei->sem);
|
||||
inode_init_once(&ei->vfs_inode);
|
||||
}
|
||||
|
||||
|
@ -55,9 +55,9 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
|
|||
{
|
||||
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
|
||||
|
||||
down(&c->alloc_sem);
|
||||
mutex_lock(&c->alloc_sem);
|
||||
jffs2_flush_wbuf_pad(c);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -95,8 +95,8 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
|
||||
/* Initialize JFFS2 superblock locks, the further initialization will
|
||||
* be done later */
|
||||
init_MUTEX(&c->alloc_sem);
|
||||
init_MUTEX(&c->erase_free_sem);
|
||||
mutex_init(&c->alloc_sem);
|
||||
mutex_init(&c->erase_free_sem);
|
||||
init_waitqueue_head(&c->erase_wait);
|
||||
init_waitqueue_head(&c->inocache_wq);
|
||||
spin_lock_init(&c->erase_completion_lock);
|
||||
|
@ -125,9 +125,9 @@ static void jffs2_put_super (struct super_block *sb)
|
|||
|
||||
D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
|
||||
|
||||
down(&c->alloc_sem);
|
||||
mutex_lock(&c->alloc_sem);
|
||||
jffs2_flush_wbuf_pad(c);
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
|
||||
jffs2_sum_exit(c);
|
||||
|
||||
|
|
|
@ -578,8 +578,8 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
|
|||
if (!jffs2_is_writebuffered(c))
|
||||
return 0;
|
||||
|
||||
if (!down_trylock(&c->alloc_sem)) {
|
||||
up(&c->alloc_sem);
|
||||
if (mutex_trylock(&c->alloc_sem)) {
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
|
||||
BUG();
|
||||
}
|
||||
|
@ -702,10 +702,10 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
|
|||
if (!c->wbuf)
|
||||
return 0;
|
||||
|
||||
down(&c->alloc_sem);
|
||||
mutex_lock(&c->alloc_sem);
|
||||
if (!jffs2_wbuf_pending_for_ino(c, ino)) {
|
||||
D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino));
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -725,14 +725,14 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
|
|||
} else while (old_wbuf_len &&
|
||||
old_wbuf_ofs == c->wbuf_ofs) {
|
||||
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
|
||||
D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() calls gc pass\n"));
|
||||
|
||||
ret = jffs2_garbage_collect_pass(c);
|
||||
if (ret) {
|
||||
/* GC failed. Flush it with padding instead */
|
||||
down(&c->alloc_sem);
|
||||
mutex_lock(&c->alloc_sem);
|
||||
down_write(&c->wbuf_sem);
|
||||
ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
|
||||
/* retry flushing wbuf in case jffs2_wbuf_recover
|
||||
|
@ -742,12 +742,12 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
|
|||
up_write(&c->wbuf_sem);
|
||||
break;
|
||||
}
|
||||
down(&c->alloc_sem);
|
||||
mutex_lock(&c->alloc_sem);
|
||||
}
|
||||
|
||||
D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() ends...\n"));
|
||||
|
||||
up(&c->alloc_sem);
|
||||
mutex_unlock(&c->alloc_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,12 +137,12 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
|
|||
JFFS2_SUMMARY_INODE_SIZE);
|
||||
} else {
|
||||
/* Locking pain */
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
|
||||
alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
|
@ -285,12 +285,12 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
|
|||
JFFS2_SUMMARY_DIRENT_SIZE(namelen));
|
||||
} else {
|
||||
/* Locking pain */
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
|
||||
alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
|
@ -353,7 +353,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|||
D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
|
||||
break;
|
||||
}
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1)));
|
||||
cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);
|
||||
|
||||
|
@ -381,7 +381,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|||
|
||||
if (IS_ERR(fn)) {
|
||||
ret = PTR_ERR(fn);
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
if (!retried) {
|
||||
/* Write error to be retried */
|
||||
|
@ -403,11 +403,11 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|||
jffs2_mark_node_obsolete(c, fn->raw);
|
||||
jffs2_free_full_dnode(fn);
|
||||
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
break;
|
||||
}
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
if (!datalen) {
|
||||
printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n");
|
||||
|
@ -439,7 +439,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|||
JFFS2_SUMMARY_INODE_SIZE);
|
||||
D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
|
||||
if (ret) {
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -454,7 +454,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|||
if (IS_ERR(fn)) {
|
||||
D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n"));
|
||||
/* Eeek. Wave bye bye */
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
return PTR_ERR(fn);
|
||||
}
|
||||
|
@ -463,7 +463,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|||
*/
|
||||
f->metadata = fn;
|
||||
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode);
|
||||
|
@ -489,7 +489,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
|
||||
rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
|
||||
|
@ -513,7 +513,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|||
/* dirent failed to write. Delete the inode normally
|
||||
as if it were the final unlink() */
|
||||
jffs2_complete_reservation(c);
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
return PTR_ERR(fd);
|
||||
}
|
||||
|
||||
|
@ -522,7 +522,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|||
jffs2_add_fd_to_list(c, fd, &dir_f->dents);
|
||||
|
||||
jffs2_complete_reservation(c);
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -551,7 +551,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|||
return ret;
|
||||
}
|
||||
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
/* Build a deletion node */
|
||||
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
|
||||
|
@ -574,21 +574,21 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|||
|
||||
if (IS_ERR(fd)) {
|
||||
jffs2_complete_reservation(c);
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
return PTR_ERR(fd);
|
||||
}
|
||||
|
||||
/* File it. This will mark the old one obsolete. */
|
||||
jffs2_add_fd_to_list(c, fd, &dir_f->dents);
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
} else {
|
||||
uint32_t nhash = full_name_hash(name, namelen);
|
||||
|
||||
fd = dir_f->dents;
|
||||
/* We don't actually want to reserve any space, but we do
|
||||
want to be holding the alloc_sem when we write to flash */
|
||||
down(&c->alloc_sem);
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&c->alloc_sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
for (fd = dir_f->dents; fd; fd = fd->next) {
|
||||
if (fd->nhash == nhash &&
|
||||
|
@ -607,7 +607,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|||
break;
|
||||
}
|
||||
}
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
}
|
||||
|
||||
/* dead_f is NULL if this was a rename not a real unlink */
|
||||
|
@ -615,7 +615,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|||
pointing to an inode which didn't exist. */
|
||||
if (dead_f && dead_f->inocache) {
|
||||
|
||||
down(&dead_f->sem);
|
||||
mutex_lock(&dead_f->sem);
|
||||
|
||||
if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {
|
||||
while (dead_f->dents) {
|
||||
|
@ -639,7 +639,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|||
|
||||
dead_f->inocache->nlink--;
|
||||
/* NB: Caller must set inode nlink if appropriate */
|
||||
up(&dead_f->sem);
|
||||
mutex_unlock(&dead_f->sem);
|
||||
}
|
||||
|
||||
jffs2_complete_reservation(c);
|
||||
|
@ -666,7 +666,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
|
|||
return ret;
|
||||
}
|
||||
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
/* Build a deletion node */
|
||||
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
|
||||
|
@ -691,7 +691,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
|
|||
|
||||
if (IS_ERR(fd)) {
|
||||
jffs2_complete_reservation(c);
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
return PTR_ERR(fd);
|
||||
}
|
||||
|
||||
|
@ -699,7 +699,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
|
|||
jffs2_add_fd_to_list(c, fd, &dir_f->dents);
|
||||
|
||||
jffs2_complete_reservation(c);
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче