···1414 alloc_sem1515 ---------16161717-The alloc_sem is a per-filesystem semaphore, used primarily to ensure1717+The alloc_sem is a per-filesystem mutex, used primarily to ensure1818contiguous allocation of space on the medium. It is automatically1919obtained during space allocations (jffs2_reserve_space()) and freed2020upon write completion (jffs2_complete_reservation()). Note that···4141Ordering constraints: See f->sem.424243434444- File Semaphore f->sem4444+ File Mutex f->sem4545 ---------------------46464747-This is the JFFS2-internal equivalent of the inode semaphore i->i_sem.4747+This is the JFFS2-internal equivalent of the inode mutex i->i_sem.4848It protects the contents of the jffs2_inode_info private inode data,4949including the linked list of node fragments (but see the notes below on5050erase_completion_lock), etc.···6060before calling the space allocation functions.61616262Instead of playing such games, we just have an extra internal6363-semaphore, which is obtained by the garbage collection code and also6363+mutex, which is obtained by the garbage collection code and also6464by the normal file system code _after_ allocation of space.65656666Ordering constraints: 67676868 1. Never attempt to allocate space or lock alloc_sem with 6969 any f->sem held.7070- 2. Never attempt to lock two file semaphores in one thread.7070+ 2. Never attempt to lock two file mutexes in one thread.7171 No ordering rules have been made for doing so.72727373···86868787Note that the per-inode list of physical nodes (f->nodes) is a special8888case. Any changes to _valid_ nodes (i.e. ->flash_offset & 1 == 0) in8989-the list are protected by the file semaphore f->sem. But the erase9090-code may remove _obsolete_ nodes from the list while holding only the8989+the list are protected by the file mutex f->sem. But the erase code9090+may remove _obsolete_ nodes from the list while holding only the9191erase_completion_lock. So you can walk the list only while holding the9292erase_completion_lock, and can drop the lock temporarily mid-walk as9393long as the pointer you're holding is to a _valid_ node, not an···124124 erase_free_sem125125 --------------126126127127-This semaphore is only used by the erase code which frees obsolete128128-node references and the jffs2_garbage_collect_deletion_dirent()129129-function. The latter function on NAND flash must read _obsolete_ nodes130130-to determine whether the 'deletion dirent' under consideration can be127127+This mutex is only used by the erase code which frees obsolete node128128+references and the jffs2_garbage_collect_deletion_dirent() function.129129+The latter function on NAND flash must read _obsolete_ nodes to130130+determine whether the 'deletion dirent' under consideration can be131131discarded or whether it is still required to show that an inode has132132been unlinked. Because reading from the flash may sleep, the133133erase_completion_lock cannot be held, so an alternative, more
···8686 dir_f = JFFS2_INODE_INFO(dir_i);8787 c = JFFS2_SB_INFO(dir_i->i_sb);88888989- down(&dir_f->sem);8989+ mutex_lock(&dir_f->sem);90909191 /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */9292 for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) {···9999 }100100 if (fd)101101 ino = fd->ino;102102- up(&dir_f->sem);102102+ mutex_unlock(&dir_f->sem);103103 if (ino) {104104 inode = jffs2_iget(dir_i->i_sb, ino);105105 if (IS_ERR(inode)) {···146146 }147147148148 curofs=1;149149- down(&f->sem);149149+ mutex_lock(&f->sem);150150 for (fd = f->dents; fd; fd = fd->next) {151151152152 curofs++;···166166 break;167167 offset++;168168 }169169- up(&f->sem);169169+ mutex_unlock(&f->sem);170170 out:171171 filp->f_pos = offset;172172 return 0;···275275 ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now);276276277277 if (!ret) {278278- down(&f->sem);278278+ mutex_lock(&f->sem);279279 old_dentry->d_inode->i_nlink = ++f->inocache->nlink;280280- up(&f->sem);280280+ mutex_unlock(&f->sem);281281 d_instantiate(dentry, old_dentry->d_inode);282282 dir_i->i_mtime = dir_i->i_ctime = ITIME(now);283283 atomic_inc(&old_dentry->d_inode->i_count);···351351352352 if (IS_ERR(fn)) {353353 /* Eeek. Wave bye bye */354354- up(&f->sem);354354+ mutex_unlock(&f->sem);355355 jffs2_complete_reservation(c);356356 jffs2_clear_inode(inode);357357 return PTR_ERR(fn);···361361 f->target = kmalloc(targetlen + 1, GFP_KERNEL);362362 if (!f->target) {363363 printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);364364- up(&f->sem);364364+ mutex_unlock(&f->sem);365365 jffs2_complete_reservation(c);366366 jffs2_clear_inode(inode);367367 return -ENOMEM;···374374 obsoleted by the first data write375375 */376376 f->metadata = fn;377377- up(&f->sem);377377+ mutex_unlock(&f->sem);378378379379 jffs2_complete_reservation(c);380380···406406 }407407408408 dir_f = JFFS2_INODE_INFO(dir_i);409409- down(&dir_f->sem);409409+ mutex_lock(&dir_f->sem);410410411411 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);412412 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);···429429 as if it were the final unlink() */430430 jffs2_complete_reservation(c);431431 jffs2_free_raw_dirent(rd);432432- up(&dir_f->sem);432432+ mutex_unlock(&dir_f->sem);433433 jffs2_clear_inode(inode);434434 return PTR_ERR(fd);435435 }···442442 one if necessary. */443443 jffs2_add_fd_to_list(c, fd, &dir_f->dents);444444445445- up(&dir_f->sem);445445+ mutex_unlock(&dir_f->sem);446446 jffs2_complete_reservation(c);447447448448 d_instantiate(dentry, inode);···507507508508 if (IS_ERR(fn)) {509509 /* Eeek. Wave bye bye */510510- up(&f->sem);510510+ mutex_unlock(&f->sem);511511 jffs2_complete_reservation(c);512512 jffs2_clear_inode(inode);513513 return PTR_ERR(fn);···516516 obsoleted by the first data write517517 */518518 f->metadata = fn;519519- up(&f->sem);519519+ mutex_unlock(&f->sem);520520521521 jffs2_complete_reservation(c);522522···548548 }549549550550 dir_f = JFFS2_INODE_INFO(dir_i);551551- down(&dir_f->sem);551551+ mutex_lock(&dir_f->sem);552552553553 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);554554 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);···571571 as if it were the final unlink() */572572 jffs2_complete_reservation(c);573573 jffs2_free_raw_dirent(rd);574574- up(&dir_f->sem);574574+ mutex_unlock(&dir_f->sem);575575 jffs2_clear_inode(inode);576576 return PTR_ERR(fd);577577 }···585585 one if necessary. */586586 jffs2_add_fd_to_list(c, fd, &dir_f->dents);587587588588- up(&dir_f->sem);588588+ mutex_unlock(&dir_f->sem);589589 jffs2_complete_reservation(c);590590591591 d_instantiate(dentry, inode);···673673674674 if (IS_ERR(fn)) {675675 /* Eeek. Wave bye bye */676676- up(&f->sem);676676+ mutex_unlock(&f->sem);677677 jffs2_complete_reservation(c);678678 jffs2_clear_inode(inode);679679 return PTR_ERR(fn);···682682 obsoleted by the first data write683683 */684684 f->metadata = fn;685685- up(&f->sem);685685+ mutex_unlock(&f->sem);686686687687 jffs2_complete_reservation(c);688688···714714 }715715716716 dir_f = JFFS2_INODE_INFO(dir_i);717717- down(&dir_f->sem);717717+ mutex_lock(&dir_f->sem);718718719719 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);720720 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);···740740 as if it were the final unlink() */741741 jffs2_complete_reservation(c);742742 jffs2_free_raw_dirent(rd);743743- up(&dir_f->sem);743743+ mutex_unlock(&dir_f->sem);744744 jffs2_clear_inode(inode);745745 return PTR_ERR(fd);746746 }···753753 one if necessary. */754754 jffs2_add_fd_to_list(c, fd, &dir_f->dents);755755756756- up(&dir_f->sem);756756+ mutex_unlock(&dir_f->sem);757757 jffs2_complete_reservation(c);758758759759 d_instantiate(dentry, inode);···780780 if (S_ISDIR(new_dentry->d_inode->i_mode)) {781781 struct jffs2_full_dirent *fd;782782783783- down(&victim_f->sem);783783+ mutex_lock(&victim_f->sem);784784 for (fd = victim_f->dents; fd; fd = fd->next) {785785 if (fd->ino) {786786- up(&victim_f->sem);786786+ mutex_unlock(&victim_f->sem);787787 return -ENOTEMPTY;788788 }789789 }790790- up(&victim_f->sem);790790+ mutex_unlock(&victim_f->sem);791791 }792792 }793793···816816 /* Don't oops if the victim was a dirent pointing to an817817 inode which didn't exist. */818818 if (victim_f->inocache) {819819- down(&victim_f->sem);819819+ mutex_lock(&victim_f->sem);820820 victim_f->inocache->nlink--;821821- up(&victim_f->sem);821821+ mutex_unlock(&victim_f->sem);822822 }823823 }824824···836836 if (ret) {837837 /* Oh shit. We really ought to make a single node which can do both atomically */838838 struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);839839- down(&f->sem);839839+ mutex_lock(&f->sem);840840 inc_nlink(old_dentry->d_inode);841841 if (f->inocache)842842 f->inocache->nlink++;843843- up(&f->sem);843843+ mutex_unlock(&f->sem);844844845845 printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);846846 /* Might as well let the VFS know */
+21-21
fs/jffs2/erase.c
···5050 instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);5151 if (!instr) {5252 printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");5353- down(&c->erase_free_sem);5353+ mutex_lock(&c->erase_free_sem);5454 spin_lock(&c->erase_completion_lock);5555 list_move(&jeb->list, &c->erase_pending_list);5656 c->erasing_size -= c->sector_size;5757 c->dirty_size += c->sector_size;5858 jeb->dirty_size = c->sector_size;5959 spin_unlock(&c->erase_completion_lock);6060- up(&c->erase_free_sem);6060+ mutex_unlock(&c->erase_free_sem);6161 return;6262 }6363···8484 if (ret == -ENOMEM || ret == -EAGAIN) {8585 /* Erase failed immediately. Refile it on the list */8686 D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));8787- down(&c->erase_free_sem);8787+ mutex_lock(&c->erase_free_sem);8888 spin_lock(&c->erase_completion_lock);8989 list_move(&jeb->list, &c->erase_pending_list);9090 c->erasing_size -= c->sector_size;9191 c->dirty_size += c->sector_size;9292 jeb->dirty_size = c->sector_size;9393 spin_unlock(&c->erase_completion_lock);9494- up(&c->erase_free_sem);9494+ mutex_unlock(&c->erase_free_sem);9595 return;9696 }9797···107107{108108 struct jffs2_eraseblock *jeb;109109110110- down(&c->erase_free_sem);110110+ mutex_lock(&c->erase_free_sem);111111112112 spin_lock(&c->erase_completion_lock);113113···118118 jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);119119 list_del(&jeb->list);120120 spin_unlock(&c->erase_completion_lock);121121- up(&c->erase_free_sem);121121+ mutex_unlock(&c->erase_free_sem);122122 jffs2_mark_erased_block(c, jeb);123123124124 if (!--count) {···139139 jffs2_free_jeb_node_refs(c, jeb);140140 list_add(&jeb->list, &c->erasing_list);141141 spin_unlock(&c->erase_completion_lock);142142- up(&c->erase_free_sem);142142+ mutex_unlock(&c->erase_free_sem);143143144144 jffs2_erase_block(c, jeb);145145···149149150150 /* Be nice */151151 yield();152152- down(&c->erase_free_sem);152152+ mutex_lock(&c->erase_free_sem);153153 spin_lock(&c->erase_completion_lock);154154 }155155156156 spin_unlock(&c->erase_completion_lock);157157- up(&c->erase_free_sem);157157+ mutex_unlock(&c->erase_free_sem);158158 done:159159 D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));160160}···162162static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)163163{164164 D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));165165- down(&c->erase_free_sem);165165+ mutex_lock(&c->erase_free_sem);166166 spin_lock(&c->erase_completion_lock);167167 list_move_tail(&jeb->list, &c->erase_complete_list);168168 spin_unlock(&c->erase_completion_lock);169169- up(&c->erase_free_sem);169169+ mutex_unlock(&c->erase_free_sem);170170 /* Ensure that kupdated calls us again to mark them clean */171171 jffs2_erase_pending_trigger(c);172172}···180180 failed too many times. */181181 if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {182182 /* We'd like to give this block another try. */183183- down(&c->erase_free_sem);183183+ mutex_lock(&c->erase_free_sem);184184 spin_lock(&c->erase_completion_lock);185185 list_move(&jeb->list, &c->erase_pending_list);186186 c->erasing_size -= c->sector_size;187187 c->dirty_size += c->sector_size;188188 jeb->dirty_size = c->sector_size;189189 spin_unlock(&c->erase_completion_lock);190190- up(&c->erase_free_sem);190190+ mutex_unlock(&c->erase_free_sem);191191 return;192192 }193193 }194194195195- down(&c->erase_free_sem);195195+ mutex_lock(&c->erase_free_sem);196196 spin_lock(&c->erase_completion_lock);197197 c->erasing_size -= c->sector_size;198198 c->bad_size += c->sector_size;199199 list_move(&jeb->list, &c->bad_list);200200 c->nr_erasing_blocks--;201201 spin_unlock(&c->erase_completion_lock);202202- up(&c->erase_free_sem);202202+ mutex_unlock(&c->erase_free_sem);203203 wake_up(&c->erase_wait);204204}205205···456456 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);457457 }458458459459- down(&c->erase_free_sem);459459+ mutex_lock(&c->erase_free_sem);460460 spin_lock(&c->erase_completion_lock);461461 c->erasing_size -= c->sector_size;462462 c->free_size += jeb->free_size;···469469 c->nr_erasing_blocks--;470470 c->nr_free_blocks++;471471 spin_unlock(&c->erase_completion_lock);472472- up(&c->erase_free_sem);472472+ mutex_unlock(&c->erase_free_sem);473473 wake_up(&c->erase_wait);474474 return;475475476476filebad:477477- down(&c->erase_free_sem);477477+ mutex_lock(&c->erase_free_sem);478478 spin_lock(&c->erase_completion_lock);479479 /* Stick it on a list (any list) so erase_failed can take it480480 right off again. Silly, but shouldn't happen often. */481481 list_add(&jeb->list, &c->erasing_list);482482 spin_unlock(&c->erase_completion_lock);483483- up(&c->erase_free_sem);483483+ mutex_unlock(&c->erase_free_sem);484484 jffs2_erase_failed(c, jeb, bad_offset);485485 return;486486487487refile:488488 /* Stick it back on the list from whence it came and come back later */489489 jffs2_erase_pending_trigger(c);490490- down(&c->erase_free_sem);490490+ mutex_lock(&c->erase_free_sem);491491 spin_lock(&c->erase_completion_lock);492492 list_add(&jeb->list, &c->erase_complete_list);493493 spin_unlock(&c->erase_completion_lock);494494- up(&c->erase_free_sem);494494+ mutex_unlock(&c->erase_free_sem);495495 return;496496}
+8-8
fs/jffs2/file.c
···115115 struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host);116116 int ret;117117118118- down(&f->sem);118118+ mutex_lock(&f->sem);119119 ret = jffs2_do_readpage_unlock(pg->mapping->host, pg);120120- up(&f->sem);120120+ mutex_unlock(&f->sem);121121 return ret;122122}123123···154154 if (ret)155155 goto out_page;156156157157- down(&f->sem);157157+ mutex_lock(&f->sem);158158 memset(&ri, 0, sizeof(ri));159159160160 ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);···181181 if (IS_ERR(fn)) {182182 ret = PTR_ERR(fn);183183 jffs2_complete_reservation(c);184184- up(&f->sem);184184+ mutex_unlock(&f->sem);185185 goto out_page;186186 }187187 ret = jffs2_add_full_dnode_to_inode(c, f, fn);···195195 jffs2_mark_node_obsolete(c, fn->raw);196196 jffs2_free_full_dnode(fn);197197 jffs2_complete_reservation(c);198198- up(&f->sem);198198+ mutex_unlock(&f->sem);199199 goto out_page;200200 }201201 jffs2_complete_reservation(c);202202 inode->i_size = pageofs;203203- up(&f->sem);203203+ mutex_unlock(&f->sem);204204 }205205206206 /*···209209 * case of a short-copy.210210 */211211 if (!PageUptodate(pg)) {212212- down(&f->sem);212212+ mutex_lock(&f->sem);213213 ret = jffs2_do_readpage_nolock(inode, pg);214214- up(&f->sem);214214+ mutex_unlock(&f->sem);215215 if (ret)216216 goto out_page;217217 }
+14-14
fs/jffs2/fs.c
···5151 mdata = (char *)&dev;5252 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));5353 } else if (S_ISLNK(inode->i_mode)) {5454- down(&f->sem);5454+ mutex_lock(&f->sem);5555 mdatalen = f->metadata->size;5656 mdata = kmalloc(f->metadata->size, GFP_USER);5757 if (!mdata) {5858- up(&f->sem);5858+ mutex_unlock(&f->sem);5959 return -ENOMEM;6060 }6161 ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);6262 if (ret) {6363- up(&f->sem);6363+ mutex_unlock(&f->sem);6464 kfree(mdata);6565 return ret;6666 }6767- up(&f->sem);6767+ mutex_unlock(&f->sem);6868 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));6969 }7070···8383 kfree(mdata);8484 return ret;8585 }8686- down(&f->sem);8686+ mutex_lock(&f->sem);8787 ivalid = iattr->ia_valid;88888989 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);···134134 if (IS_ERR(new_metadata)) {135135 jffs2_complete_reservation(c);136136 jffs2_free_raw_inode(ri);137137- up(&f->sem);137137+ mutex_unlock(&f->sem);138138 return PTR_ERR(new_metadata);139139 }140140 /* It worked. Update the inode */···165165 }166166 jffs2_free_raw_inode(ri);167167168168- up(&f->sem);168168+ mutex_unlock(&f->sem);169169 jffs2_complete_reservation(c);170170171171 /* We have to do the vmtruncate() without f->sem held, since···256256 c = JFFS2_SB_INFO(inode->i_sb);257257258258 jffs2_init_inode_info(f);259259- down(&f->sem);259259+ mutex_lock(&f->sem);260260261261 ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);262262263263 if (ret) {264264- up(&f->sem);264264+ mutex_unlock(&f->sem);265265 iget_failed(inode);266266 return ERR_PTR(ret);267267 }···338338 printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino);339339 }340340341341- up(&f->sem);341341+ mutex_unlock(&f->sem);342342343343 D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));344344 unlock_new_inode(inode);···347347error_io:348348 ret = -EIO;349349error:350350- up(&f->sem);350350+ mutex_unlock(&f->sem);351351 jffs2_do_clear_inode(c, f);352352 iget_failed(inode);353353 return ERR_PTR(ret);···388388 Flush the writebuffer, if neccecary, else we loose it */389389 if (!(sb->s_flags & MS_RDONLY)) {390390 jffs2_stop_garbage_collect_thread(c);391391- down(&c->alloc_sem);391391+ mutex_lock(&c->alloc_sem);392392 jffs2_flush_wbuf_pad(c);393393- up(&c->alloc_sem);393393+ mutex_unlock(&c->alloc_sem);394394 }395395396396 if (!(*flags & MS_RDONLY))···437437438438 f = JFFS2_INODE_INFO(inode);439439 jffs2_init_inode_info(f);440440- down(&f->sem);440440+ mutex_lock(&f->sem);441441442442 memset(ri, 0, sizeof(*ri));443443 /* Set OS-specific defaults for new inodes */
+16-16
fs/jffs2/gc.c
···126126 int ret = 0, inum, nlink;127127 int xattr = 0;128128129129- if (down_interruptible(&c->alloc_sem))129129+ if (mutex_lock_interruptible(&c->alloc_sem))130130 return -EINTR;131131132132 for (;;) {···143143 c->unchecked_size);144144 jffs2_dbg_dump_block_lists_nolock(c);145145 spin_unlock(&c->erase_completion_lock);146146- up(&c->alloc_sem);146146+ mutex_unlock(&c->alloc_sem);147147 return -ENOSPC;148148 }149149···190190 made no progress in this case, but that should be OK */191191 c->checked_ino--;192192193193- up(&c->alloc_sem);193193+ mutex_unlock(&c->alloc_sem);194194 sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);195195 return 0;196196···210210 printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino);211211212212 jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT);213213- up(&c->alloc_sem);213213+ mutex_unlock(&c->alloc_sem);214214 return ret;215215 }216216···223223 if (!jeb) {224224 D1 (printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"));225225 spin_unlock(&c->erase_completion_lock);226226- up(&c->alloc_sem);226226+ mutex_unlock(&c->alloc_sem);227227 return -EIO;228228 }229229···232232 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));233233234234 if (!jeb->used_size) {235235- up(&c->alloc_sem);235235+ mutex_unlock(&c->alloc_sem);236236 goto eraseit;237237 }238238···248248 jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size);249249 jeb->gc_node = raw;250250 spin_unlock(&c->erase_completion_lock);251251- up(&c->alloc_sem);251251+ mutex_unlock(&c->alloc_sem);252252 BUG();253253 }254254 }···266266 /* Just mark it obsolete */267267 jffs2_mark_node_obsolete(c, raw);268268 }269269- up(&c->alloc_sem);269269+ mutex_unlock(&c->alloc_sem);270270 goto eraseit_lock;271271 }272272···334334 */335335 printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n",336336 ic->ino, ic->state);337337- up(&c->alloc_sem);337337+ mutex_unlock(&c->alloc_sem);338338 spin_unlock(&c->inocache_lock);339339 BUG();340340···345345 the alloc_sem() (for marking nodes invalid) so we must346346 drop the alloc_sem before sleeping. */347347348348- up(&c->alloc_sem);348348+ mutex_unlock(&c->alloc_sem);349349 D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n",350350 ic->ino, ic->state));351351 sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);···416416 ret = -ENOSPC;417417 }418418 release_sem:419419- up(&c->alloc_sem);419419+ mutex_unlock(&c->alloc_sem);420420421421 eraseit_lock:422422 /* If we've finished this block, start it erasing */···445445 uint32_t start = 0, end = 0, nrfrags = 0;446446 int ret = 0;447447448448- down(&f->sem);448448+ mutex_lock(&f->sem);449449450450 /* Now we have the lock for this inode. Check that it's still the one at the head451451 of the list. */···525525 }526526 }527527 upnout:528528- up(&f->sem);528528+ mutex_unlock(&f->sem);529529530530 return ret;531531}···846846 /* Prevent the erase code from nicking the obsolete node refs while847847 we're looking at them. I really don't like this extra lock but848848 can't see any alternative. Suggestions on a postcard to... */849849- down(&c->erase_free_sem);849849+ mutex_lock(&c->erase_free_sem);850850851851 for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {852852···899899 /* OK. The name really does match. There really is still an older node on900900 the flash which our deletion dirent obsoletes. So we have to write out901901 a new deletion dirent to replace it */902902- up(&c->erase_free_sem);902902+ mutex_unlock(&c->erase_free_sem);903903904904 D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n",905905 ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino)));···908908 return jffs2_garbage_collect_dirent(c, jeb, f, fd);909909 }910910911911- up(&c->erase_free_sem);911911+ mutex_unlock(&c->erase_free_sem);912912 kfree(rd);913913 }914914
+1-1
fs/jffs2/jffs2_fs_i.h
···2424 before letting GC proceed. Or we'd have to put ugliness2525 into the GC code so it didn't attempt to obtain the i_mutex2626 for the inode(s) which are already locked */2727- struct semaphore sem;2727+ struct mutex sem;28282929 /* The highest (datanode) version number used for this ino */3030 uint32_t highest_version;
+3-3
fs/jffs2/jffs2_fs_sb.h
···1616#include <linux/spinlock.h>1717#include <linux/workqueue.h>1818#include <linux/completion.h>1919-#include <linux/semaphore.h>1919+#include <linux/mutex.h>2020#include <linux/timer.h>2121#include <linux/wait.h>2222#include <linux/list.h>···4444 struct completion gc_thread_start; /* GC thread start completion */4545 struct completion gc_thread_exit; /* GC thread exit completion port */46464747- struct semaphore alloc_sem; /* Used to protect all the following4747+ struct mutex alloc_sem; /* Used to protect all the following4848 fields, and also to protect against4949 out-of-order writing of nodes. And GC. */5050 uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER···104104 /* Sem to allow jffs2_garbage_collect_deletion_dirent to105105 drop the erase_completion_lock while it's holding a pointer106106 to an obsoleted node. I don't like this. Alternatives welcomed. */107107- struct semaphore erase_free_sem;107107+ struct mutex erase_free_sem;108108109109 uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */110110
+9-9
fs/jffs2/nodemgmt.c
···4848 minsize = PAD(minsize);49495050 D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize));5151- down(&c->alloc_sem);5151+ mutex_lock(&c->alloc_sem);52525353 D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n"));5454···8181 dirty, c->unchecked_size, c->sector_size));82828383 spin_unlock(&c->erase_completion_lock);8484- up(&c->alloc_sem);8484+ mutex_unlock(&c->alloc_sem);8585 return -ENOSPC;8686 }8787···104104 D1(printk(KERN_DEBUG "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",105105 avail, blocksneeded * c->sector_size));106106 spin_unlock(&c->erase_completion_lock);107107- up(&c->alloc_sem);107107+ mutex_unlock(&c->alloc_sem);108108 return -ENOSPC;109109 }110110111111- up(&c->alloc_sem);111111+ mutex_unlock(&c->alloc_sem);112112113113 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",114114 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,···124124 if (signal_pending(current))125125 return -EINTR;126126127127- down(&c->alloc_sem);127127+ mutex_lock(&c->alloc_sem);128128 spin_lock(&c->erase_completion_lock);129129 }130130···137137 if (!ret)138138 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);139139 if (ret)140140- up(&c->alloc_sem);140140+ mutex_unlock(&c->alloc_sem);141141 return ret;142142}143143···462462{463463 D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n"));464464 jffs2_garbage_collect_trigger(c);465465- up(&c->alloc_sem);465465+ mutex_unlock(&c->alloc_sem);466466}467467468468static inline int on_list(struct list_head *obj, struct list_head *head)···511511 any jffs2_raw_node_refs. So we don't need to stop erases from512512 happening, or protect against people holding an obsolete513513 jffs2_raw_node_ref without the erase_completion_lock. */514514- down(&c->erase_free_sem);514514+ mutex_lock(&c->erase_free_sem);515515 }516516517517 spin_lock(&c->erase_completion_lock);···714714 }715715716716 out_erase_sem:717717- up(&c->erase_free_sem);717717+ mutex_unlock(&c->erase_free_sem);718718}719719720720int jffs2_thread_should_wake(struct jffs2_sb_info *c)
+12-11
fs/jffs2/readinode.c
···11931193 JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",11941194 ret, retlen, sizeof(*latest_node));11951195 /* FIXME: If this fails, there seems to be a memory leak. Find it. */11961196- up(&f->sem);11961196+ mutex_unlock(&f->sem);11971197 jffs2_do_clear_inode(c, f);11981198 return ret?ret:-EIO;11991199 }···12021202 if (crc != je32_to_cpu(latest_node->node_crc)) {12031203 JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",12041204 f->inocache->ino, ref_offset(rii.latest_ref));12051205- up(&f->sem);12051205+ mutex_unlock(&f->sem);12061206 jffs2_do_clear_inode(c, f);12071207 return -EIO;12081208 }···12421242 f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);12431243 if (!f->target) {12441244 JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize));12451245- up(&f->sem);12451245+ mutex_unlock(&f->sem);12461246 jffs2_do_clear_inode(c, f);12471247 return -ENOMEM;12481248 }···12551255 ret = -EIO;12561256 kfree(f->target);12571257 f->target = NULL;12581258- up(&f->sem);12581258+ mutex_unlock(&f->sem);12591259 jffs2_do_clear_inode(c, f);12601260 return -ret;12611261 }···12731273 if (f->metadata) {12741274 JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",12751275 f->inocache->ino, jemode_to_cpu(latest_node->mode));12761276- up(&f->sem);12761276+ mutex_unlock(&f->sem);12771277 jffs2_do_clear_inode(c, f);12781278 return -EIO;12791279 }12801280 if (!frag_first(&f->fragtree)) {12811281 JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",12821282 f->inocache->ino, jemode_to_cpu(latest_node->mode));12831283- up(&f->sem);12831283+ mutex_unlock(&f->sem);12841284 jffs2_do_clear_inode(c, f);12851285 return -EIO;12861286 }···12891289 JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",12901290 f->inocache->ino, jemode_to_cpu(latest_node->mode));12911291 /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */12921292- up(&f->sem);12921292+ mutex_unlock(&f->sem);12931293 jffs2_do_clear_inode(c, f);12941294 return -EIO;12951295 }···13791379 if (!f)13801380 return -ENOMEM;1381138113821382- init_MUTEX_LOCKED(&f->sem);13821382+ mutex_init(&f->sem);13831383+ mutex_lock(&f->sem);13831384 f->inocache = ic;1384138513851386 ret = jffs2_do_read_inode_internal(c, f, &n);13861387 if (!ret) {13871387- up(&f->sem);13881388+ mutex_unlock(&f->sem);13881389 jffs2_do_clear_inode(c, f);13891390 }13901391 kfree (f);···1399139814001399 jffs2_clear_acl(f);14011400 jffs2_xattr_delete_inode(c, f->inocache);14021402- down(&f->sem);14011401+ mutex_lock(&f->sem);14031402 deleted = f->inocache && !f->inocache->nlink;1404140314051404 if (f->inocache && f->inocache->state != INO_STATE_CHECKING)···14311430 jffs2_del_ino_cache(c, f->inocache);14321431 }1433143214341434- up(&f->sem);14331433+ mutex_unlock(&f->sem);14351434}