/** * ubifs_log_post_commit - things to do after commit is completed. * @c: UBIFS file-system description object * @old_ltail_lnum: old log tail LEB number * * Release buds only after commit is completed, because they must be unchanged * if recovery is needed. * * Unmap log LEBs only after commit is completed, because they may be needed for * recovery. * * This function returns %0 on success and a negative error code on failure. */ int ubifs_log_post_commit(struct ubifs_info *c, int old_ltail_lnum) { int lnum, err = 0; while (!list_empty(&c->old_buds)) { struct ubifs_bud *bud; bud = list_entry(c->old_buds.next, struct ubifs_bud, list); err = ubifs_return_leb(c, bud->lnum); if (err) return err; list_del(&bud->list); kfree(bud); } mutex_lock(&c->log_mutex); for (lnum = old_ltail_lnum; lnum != c->ltail_lnum; lnum = ubifs_next_log_lnum(c, lnum)) { dbg_log("unmap log LEB %d", lnum); err = ubifs_leb_unmap(c, lnum); if (err) goto out; } out: mutex_unlock(&c->log_mutex); return err; }
/** * run_gc - run garbage collector. * @c: UBIFS file-system description object * * This function runs garbage collector to make some more free space. Returns * zero if a free LEB has been produced, %-EAGAIN if commit is required, and a * negative error code in case of failure. */ static int run_gc(struct ubifs_info *c) { int err, lnum; /* Make some free space by garbage-collecting dirty space */ down_read(&c->commit_sem); lnum = ubifs_garbage_collect(c, 1); up_read(&c->commit_sem); if (lnum < 0) return lnum; /* GC freed one LEB, return it to lprops */ dbg_budg("GC freed LEB %d", lnum); err = ubifs_return_leb(c, lnum); if (err) return err; return 0; }
/** * reserve_space - reserve space in the journal. * @c: UBIFS file-system description object * @jhead: journal head number * @len: node length * * This function reserves space in journal head @head. If the reservation * succeeded, the journal head stays locked and later has to be unlocked using * 'release_head()'. 'write_node()' and 'write_head()' functions also unlock * it. Returns zero in case of success, %-EAGAIN if commit has to be done, and * other negative error codes in case of other failures. */ static int reserve_space(struct ubifs_info *c, int jhead, int len) { int err = 0, err1, retries = 0, avail, lnum, offs, free, squeeze; struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf; /* * Typically, the base head has smaller nodes written to it, so it is * better to try to allocate space at the ends of eraseblocks. This is * what the squeeze parameter does. */ squeeze = (jhead == BASEHD); again: mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); avail = c->leb_size - wbuf->offs - wbuf->used; if (wbuf->lnum != -1 && avail >= len) return 0; /* * Write buffer wasn't seek'ed or there is no enough space - look for an * LEB with some empty space. */ lnum = ubifs_find_free_space(c, len, &free, squeeze); if (lnum >= 0) { /* Found an LEB, add it to the journal head */ offs = c->leb_size - free; err = ubifs_add_bud_to_log(c, jhead, lnum, offs); if (err) goto out_return; /* A new bud was successfully allocated and added to the log */ goto out; } err = lnum; if (err != -ENOSPC) goto out_unlock; /* * No free space, we have to run garbage collector to make * some. But the write-buffer mutex has to be unlocked because * GC have to sync write buffers, which may lead a deadlock. */ dbg_jrn("no free space jhead %d, run GC", jhead); mutex_unlock(&wbuf->io_mutex); lnum = ubifs_garbage_collect(c, 0); if (lnum < 0) { err = lnum; if (err != -ENOSPC) return err; /* * GC could not make a free LEB. But someone else may * have allocated new bud for this journal head, * because we dropped the 'io_mutex', so try once * again. */ dbg_jrn("GC couldn't make a free LEB for jhead %d", jhead); if (retries++ < 2) { dbg_jrn("retry (%d)", retries); goto again; } dbg_jrn("return -ENOSPC"); return err; } mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); dbg_jrn("got LEB %d for jhead %d", lnum, jhead); avail = c->leb_size - wbuf->offs - wbuf->used; if (wbuf->lnum != -1 && avail >= len) { /* * Someone else has switched the journal head and we have * enough space now. This happens when more then one process is * trying to write to the same journal head at the same time. */ dbg_jrn("return LEB %d back, already have LEB %d:%d", lnum, wbuf->lnum, wbuf->offs + wbuf->used); err = ubifs_return_leb(c, lnum); if (err) goto out_unlock; return 0; } err = ubifs_add_bud_to_log(c, jhead, lnum, 0); if (err) goto out_return; offs = 0; out: err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, UBI_SHORTTERM); if (err) goto out_unlock; return 0; out_unlock: mutex_unlock(&wbuf->io_mutex); return err; out_return: /* An error occurred and the LEB has to be returned to lprops */ ubifs_assert(err < 0); err1 = ubifs_return_leb(c, lnum); if (err1 && err == -EAGAIN) /* * Return original error code 'err' only if it is not * '-EAGAIN', which is not really an error. Otherwise, return * the error code of 'ubifs_return_leb()'. */ err = err1; mutex_unlock(&wbuf->io_mutex); return err; }