예제 #1
0
/**
 * switch_gc_head - switch the garbage collection journal head.
 * @c: UBIFS file-system description object
 * @buf: buffer to write
 * @len: length of the buffer to write
 * @lnum: LEB number written is returned here
 * @offs: offset written is returned here
 *
 * This function switch the GC head to the next LEB which is reserved in
 * @c->gc_lnum. Returns %0 in case of success, %-EAGAIN if commit is required,
 * and other negative error code in case of failures.
 */
static int switch_gc_head(struct ubifs_info *c)
{
	int err, gc_lnum = c->gc_lnum;
	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;

	ubifs_assert(gc_lnum != -1);
	dbg_gc("switch GC head from LEB %d:%d to LEB %d (waste %d bytes)",
	       wbuf->lnum, wbuf->offs + wbuf->used, gc_lnum,
	       c->leb_size - wbuf->offs - wbuf->used);

	err = ubifs_wbuf_sync_nolock(wbuf);
	if (err)
		return err;

	/*
	 * The GC write-buffer was synchronized, we may safely unmap
	 * 'c->gc_lnum'.
	 */
	err = ubifs_leb_unmap(c, gc_lnum);
	if (err)
		return err;

	err = ubifs_wbuf_sync_nolock(wbuf);
	if (err)
		return err;

	err = ubifs_add_bud_to_log(c, GCHD, gc_lnum, 0);
	if (err)
		return err;

	c->gc_lnum = -1;
	err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0, UBI_LONGTERM);
	return err;
}
예제 #2
0
/**
 * ubifs_sync_wbufs_by_inode - synchronize write-buffers for an inode.
 * @c: UBIFS file-system description object
 * @inode: inode to synchronize
 *
 * This function synchronizes write-buffers which contain nodes belonging to
 * @inode. Returns zero in case of success and a negative error code in case of
 * failure.
 */
int ubifs_sync_wbufs_by_inode(struct ubifs_info *c, struct inode *inode)
{
	int i, err = 0;

	for (i = 0; i < c->jhead_cnt; i++) {
		struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;

		if (i == GCHD)
			/*
			 * GC head is special, do not look at it. Even if the
			 * head contains something related to this inode, it is
			 * a _copy_ of corresponding on-flash node which sits
			 * somewhere else.
			 */
			continue;

		if (!wbuf_has_ino(wbuf, inode->i_ino))
			continue;

		mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
		if (wbuf_has_ino(wbuf, inode->i_ino))
			err = ubifs_wbuf_sync_nolock(wbuf);
		mutex_unlock(&wbuf->io_mutex);

		if (err) {
			ubifs_ro_mode(c, err);
			return err;
		}
	}
	return 0;
}
예제 #3
0
파일: io.c 프로젝트: aircross/ray
/**
 * ubifs_wbuf_seek_nolock - seek write-buffer.
 * @wbuf: write-buffer
 * @lnum: logical eraseblock number to seek to
 * @offs: logical eraseblock offset to seek to
 * @dtype: data type
 *
 * This function targets the write buffer to logical eraseblock @lnum:@offs.
 * The write-buffer is synchronized if it is not empty. Returns zero in case of
 * success and a negative error code in case of failure.
 */
int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
			   int dtype)
{
	const struct ubifs_info *c = wbuf->c;

	dbg_io("LEB %d:%d", lnum, offs);
	ubifs_assert(lnum >= 0 && lnum < c->leb_cnt);
	ubifs_assert(offs >= 0 && offs <= c->leb_size);
	ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7));
	ubifs_assert(lnum != wbuf->lnum);

	if (wbuf->used > 0) {
		int err = ubifs_wbuf_sync_nolock(wbuf);

		if (err)
			return err;
	}

	spin_lock(&wbuf->lock);
	wbuf->lnum = lnum;
	wbuf->offs = offs;
	wbuf->avail = c->min_io_size;
	wbuf->used = 0;
	spin_unlock(&wbuf->lock);
	wbuf->dtype = dtype;

	return 0;
}
예제 #4
0
/**
 * ubifs_bg_wbufs_sync - synchronize write-buffers.
 * @c: UBIFS file-system description object
 *
 * This function is called by background thread to synchronize write-buffers.
 * Returns zero in case of success and a negative error code in case of
 * failure.
 */
int ubifs_bg_wbufs_sync(struct ubifs_info *c)
{
	int err, i;

	ubifs_assert(!c->ro_media && !c->ro_mount);
	if (!c->need_wbuf_sync)
		return 0;
	c->need_wbuf_sync = 0;

	if (c->ro_error) {
		err = -EROFS;
		goto out_timers;
	}

	dbg_io("synchronize");
	for (i = 0; i < c->jhead_cnt; i++) {
		struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;

		cond_resched();

		/*
		 * If the mutex is locked then wbuf is being changed, so
		 * synchronization is not necessary.
		 */
		if (mutex_is_locked(&wbuf->io_mutex))
			continue;

		mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
		if (!wbuf->need_sync) {
			mutex_unlock(&wbuf->io_mutex);
			continue;
		}

		err = ubifs_wbuf_sync_nolock(wbuf);
		mutex_unlock(&wbuf->io_mutex);
		if (err) {
			ubifs_err("cannot sync write-buffer, error %d", err);
			ubifs_ro_mode(c, err);
			goto out_timers;
		}
	}

	return 0;

out_timers:
	/* Cancel all timers to prevent repeated errors */
	for (i = 0; i < c->jhead_cnt; i++) {
		struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;

		mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
		cancel_wbuf_timer_nolock(wbuf);
		mutex_unlock(&wbuf->io_mutex);
	}
	return err;
}
예제 #5
0
/**
 * write_head - write data to a journal head.
 * @c: UBIFS file-system description object
 * @jhead: journal head
 * @buf: buffer to write
 * @len: length to write
 * @lnum: LEB number written is returned here
 * @offs: offset written is returned here
 * @sync: non-zero if the write-buffer has to by synchronized
 *
 * This function is the same as 'write_node()' but it does not assume the
 * buffer it is writing is a node, so it does not prepare it (which means
 * initializing common header and calculating CRC).
 */
static int write_head(struct ubifs_info *c, int jhead, void *buf, int len,
		      int *lnum, int *offs, int sync)
{
	int err;
	struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf;

	ubifs_assert(jhead != GCHD);

	*lnum = c->jheads[jhead].wbuf.lnum;
	*offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used;
	dbg_jrn("jhead %d, LEB %d:%d, len %d", jhead, *lnum, *offs, len);

	err = ubifs_wbuf_write_nolock(wbuf, buf, len);
	if (err)
		return err;
	if (sync)
		err = ubifs_wbuf_sync_nolock(wbuf);
	return err;
}
예제 #6
0
/**
 * ubifs_sync_wbufs_by_inodes - synchronize write-buffers which have data.
 * belonging to specified inodes.
 * @c: UBIFS file-system description object
 * @inodes: array of inodes
 * @count: number of elements in @inodes
 *
 * This function synchronizes write-buffers which contain nodes belonging to
 * any inode specified in @inodes array. Returns zero in case of success and a
 * negative error code in case of failure.
 */
int ubifs_sync_wbufs_by_inodes(struct ubifs_info *c,
			       struct inode * const *inodes, int count)
{
	int i, j, err = 0;

	ubifs_assert(count);

	for (i = 0; i < c->jhead_cnt; i++) {
		struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;

		if (i == GCHD)
			/*
			 * GC head is special, do not look at it. Even if the
			 * head contains something related to this inode, it is
			 * a _copy_ of corresponding on-flash node which sits
			 * somewhere else.
			 */
			continue;

		for (j = 0; j < count && !err; j++)
			if (wbuf_has_ino(wbuf, inodes[j]->i_ino)) {
				mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
				if (wbuf_has_ino(wbuf, inodes[j]->i_ino))
					err = ubifs_wbuf_sync_nolock(wbuf);
				mutex_unlock(&wbuf->io_mutex);
				break;
			}

		if (err) {
			ubifs_ro_mode(c, err);
			break;
		}
	}

	return err;
}