162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * JFFS2 -- Journalling Flash File System, Version 2.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright © 2001-2007 Red Hat, Inc.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Created by David Woodhouse <dwmw2@infradead.org>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * For licensing information, see the file 'LICENCE' in this directory.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/kernel.h>
1562306a36Sopenharmony_ci#include <linux/mtd/mtd.h>
1662306a36Sopenharmony_ci#include <linux/compiler.h>
1762306a36Sopenharmony_ci#include <linux/sched/signal.h>
1862306a36Sopenharmony_ci#include "nodelist.h"
1962306a36Sopenharmony_ci#include "debug.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci * Check whether the user is allowed to write.
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_cistatic int jffs2_rp_can_write(struct jffs2_sb_info *c)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	uint32_t avail;
2762306a36Sopenharmony_ci	struct jffs2_mount_opts *opts = &c->mount_opts;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	avail = c->dirty_size + c->free_size + c->unchecked_size +
3062306a36Sopenharmony_ci		c->erasing_size - c->resv_blocks_write * c->sector_size
3162306a36Sopenharmony_ci		- c->nospc_dirty_size;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	if (avail < 2 * opts->rp_size)
3462306a36Sopenharmony_ci		jffs2_dbg(1, "rpsize %u, dirty_size %u, free_size %u, "
3562306a36Sopenharmony_ci			  "erasing_size %u, unchecked_size %u, "
3662306a36Sopenharmony_ci			  "nr_erasing_blocks %u, avail %u, resrv %u\n",
3762306a36Sopenharmony_ci			  opts->rp_size, c->dirty_size, c->free_size,
3862306a36Sopenharmony_ci			  c->erasing_size, c->unchecked_size,
3962306a36Sopenharmony_ci			  c->nr_erasing_blocks, avail, c->nospc_dirty_size);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (avail > opts->rp_size)
4262306a36Sopenharmony_ci		return 1;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	/* Always allow root */
4562306a36Sopenharmony_ci	if (capable(CAP_SYS_RESOURCE))
4662306a36Sopenharmony_ci		return 1;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	jffs2_dbg(1, "forbid writing\n");
4962306a36Sopenharmony_ci	return 0;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/**
5362306a36Sopenharmony_ci *	jffs2_reserve_space - request physical space to write nodes to flash
5462306a36Sopenharmony_ci *	@c: superblock info
5562306a36Sopenharmony_ci *	@minsize: Minimum acceptable size of allocation
5662306a36Sopenharmony_ci *	@len: Returned value of allocation length
5762306a36Sopenharmony_ci *	@prio: Allocation type - ALLOC_{NORMAL,DELETION}
5862306a36Sopenharmony_ci *
5962306a36Sopenharmony_ci *	Requests a block of physical space on the flash. Returns zero for success
6062306a36Sopenharmony_ci *	and puts 'len' into the appropriate place, or returns -ENOSPC or other
6162306a36Sopenharmony_ci *	error if appropriate. Doesn't return len since that's
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci *	If it returns zero, jffs2_reserve_space() also downs the per-filesystem
6462306a36Sopenharmony_ci *	allocation semaphore, to prevent more than one allocation from being
6562306a36Sopenharmony_ci *	active at any time. The semaphore is later released by jffs2_commit_allocation()
6662306a36Sopenharmony_ci *
6762306a36Sopenharmony_ci *	jffs2_reserve_space() may trigger garbage collection in order to make room
6862306a36Sopenharmony_ci *	for the requested allocation.
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic int jffs2_do_reserve_space(struct jffs2_sb_info *c,  uint32_t minsize,
7262306a36Sopenharmony_ci				  uint32_t *len, uint32_t sumsize);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ciint jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
7562306a36Sopenharmony_ci			uint32_t *len, int prio, uint32_t sumsize)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	int ret = -EAGAIN;
7862306a36Sopenharmony_ci	int blocksneeded = c->resv_blocks_write;
7962306a36Sopenharmony_ci	/* align it */
8062306a36Sopenharmony_ci	minsize = PAD(minsize);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize);
8362306a36Sopenharmony_ci	mutex_lock(&c->alloc_sem);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): alloc sem got\n", __func__);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	spin_lock(&c->erase_completion_lock);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	/*
9062306a36Sopenharmony_ci	 * Check if the free space is greater then size of the reserved pool.
9162306a36Sopenharmony_ci	 * If not, only allow root to proceed with writing.
9262306a36Sopenharmony_ci	 */
9362306a36Sopenharmony_ci	if (prio != ALLOC_DELETION && !jffs2_rp_can_write(c)) {
9462306a36Sopenharmony_ci		ret = -ENOSPC;
9562306a36Sopenharmony_ci		goto out;
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	/* this needs a little more thought (true <tglx> :)) */
9962306a36Sopenharmony_ci	while(ret == -EAGAIN) {
10062306a36Sopenharmony_ci		while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
10162306a36Sopenharmony_ci			uint32_t dirty, avail;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci			/* calculate real dirty size
10462306a36Sopenharmony_ci			 * dirty_size contains blocks on erase_pending_list
10562306a36Sopenharmony_ci			 * those blocks are counted in c->nr_erasing_blocks.
10662306a36Sopenharmony_ci			 * If one block is actually erased, it is not longer counted as dirty_space
10762306a36Sopenharmony_ci			 * but it is counted in c->nr_erasing_blocks, so we add it and subtract it
10862306a36Sopenharmony_ci			 * with c->nr_erasing_blocks * c->sector_size again.
10962306a36Sopenharmony_ci			 * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks
11062306a36Sopenharmony_ci			 * This helps us to force gc and pick eventually a clean block to spread the load.
11162306a36Sopenharmony_ci			 * We add unchecked_size here, as we hopefully will find some space to use.
11262306a36Sopenharmony_ci			 * This will affect the sum only once, as gc first finishes checking
11362306a36Sopenharmony_ci			 * of nodes.
11462306a36Sopenharmony_ci			 */
11562306a36Sopenharmony_ci			dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size + c->unchecked_size;
11662306a36Sopenharmony_ci			if (dirty < c->nospc_dirty_size) {
11762306a36Sopenharmony_ci				if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {
11862306a36Sopenharmony_ci					jffs2_dbg(1, "%s(): Low on dirty space to GC, but it's a deletion. Allowing...\n",
11962306a36Sopenharmony_ci						  __func__);
12062306a36Sopenharmony_ci					break;
12162306a36Sopenharmony_ci				}
12262306a36Sopenharmony_ci				jffs2_dbg(1, "dirty size 0x%08x + unchecked_size 0x%08x < nospc_dirty_size 0x%08x, returning -ENOSPC\n",
12362306a36Sopenharmony_ci					  dirty, c->unchecked_size,
12462306a36Sopenharmony_ci					  c->sector_size);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci				spin_unlock(&c->erase_completion_lock);
12762306a36Sopenharmony_ci				mutex_unlock(&c->alloc_sem);
12862306a36Sopenharmony_ci				return -ENOSPC;
12962306a36Sopenharmony_ci			}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci			/* Calc possibly available space. Possibly available means that we
13262306a36Sopenharmony_ci			 * don't know, if unchecked size contains obsoleted nodes, which could give us some
13362306a36Sopenharmony_ci			 * more usable space. This will affect the sum only once, as gc first finishes checking
13462306a36Sopenharmony_ci			 * of nodes.
13562306a36Sopenharmony_ci			 + Return -ENOSPC, if the maximum possibly available space is less or equal than
13662306a36Sopenharmony_ci			 * blocksneeded * sector_size.
13762306a36Sopenharmony_ci			 * This blocks endless gc looping on a filesystem, which is nearly full, even if
13862306a36Sopenharmony_ci			 * the check above passes.
13962306a36Sopenharmony_ci			 */
14062306a36Sopenharmony_ci			avail = c->free_size + c->dirty_size + c->erasing_size + c->unchecked_size;
14162306a36Sopenharmony_ci			if ( (avail / c->sector_size) <= blocksneeded) {
14262306a36Sopenharmony_ci				if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {
14362306a36Sopenharmony_ci					jffs2_dbg(1, "%s(): Low on possibly available space, but it's a deletion. Allowing...\n",
14462306a36Sopenharmony_ci						  __func__);
14562306a36Sopenharmony_ci					break;
14662306a36Sopenharmony_ci				}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci				jffs2_dbg(1, "max. available size 0x%08x  < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
14962306a36Sopenharmony_ci					  avail, blocksneeded * c->sector_size);
15062306a36Sopenharmony_ci				spin_unlock(&c->erase_completion_lock);
15162306a36Sopenharmony_ci				mutex_unlock(&c->alloc_sem);
15262306a36Sopenharmony_ci				return -ENOSPC;
15362306a36Sopenharmony_ci			}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci			mutex_unlock(&c->alloc_sem);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci			jffs2_dbg(1, "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",
15862306a36Sopenharmony_ci				  c->nr_free_blocks, c->nr_erasing_blocks,
15962306a36Sopenharmony_ci				  c->free_size, c->dirty_size, c->wasted_size,
16062306a36Sopenharmony_ci				  c->used_size, c->erasing_size, c->bad_size,
16162306a36Sopenharmony_ci				  c->free_size + c->dirty_size +
16262306a36Sopenharmony_ci				  c->wasted_size + c->used_size +
16362306a36Sopenharmony_ci				  c->erasing_size + c->bad_size,
16462306a36Sopenharmony_ci				  c->flash_size);
16562306a36Sopenharmony_ci			spin_unlock(&c->erase_completion_lock);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci			ret = jffs2_garbage_collect_pass(c);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci			if (ret == -EAGAIN) {
17062306a36Sopenharmony_ci				spin_lock(&c->erase_completion_lock);
17162306a36Sopenharmony_ci				if (c->nr_erasing_blocks &&
17262306a36Sopenharmony_ci				    list_empty(&c->erase_pending_list) &&
17362306a36Sopenharmony_ci				    list_empty(&c->erase_complete_list)) {
17462306a36Sopenharmony_ci					DECLARE_WAITQUEUE(wait, current);
17562306a36Sopenharmony_ci					set_current_state(TASK_UNINTERRUPTIBLE);
17662306a36Sopenharmony_ci					add_wait_queue(&c->erase_wait, &wait);
17762306a36Sopenharmony_ci					jffs2_dbg(1, "%s waiting for erase to complete\n",
17862306a36Sopenharmony_ci						  __func__);
17962306a36Sopenharmony_ci					spin_unlock(&c->erase_completion_lock);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci					schedule();
18262306a36Sopenharmony_ci					remove_wait_queue(&c->erase_wait, &wait);
18362306a36Sopenharmony_ci				} else
18462306a36Sopenharmony_ci					spin_unlock(&c->erase_completion_lock);
18562306a36Sopenharmony_ci			} else if (ret)
18662306a36Sopenharmony_ci				return ret;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci			cond_resched();
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci			if (signal_pending(current))
19162306a36Sopenharmony_ci				return -EINTR;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci			mutex_lock(&c->alloc_sem);
19462306a36Sopenharmony_ci			spin_lock(&c->erase_completion_lock);
19562306a36Sopenharmony_ci		}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci		ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
19862306a36Sopenharmony_ci		if (ret) {
19962306a36Sopenharmony_ci			jffs2_dbg(1, "%s(): ret is %d\n", __func__, ret);
20062306a36Sopenharmony_ci		}
20162306a36Sopenharmony_ci	}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ciout:
20462306a36Sopenharmony_ci	spin_unlock(&c->erase_completion_lock);
20562306a36Sopenharmony_ci	if (!ret)
20662306a36Sopenharmony_ci		ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
20762306a36Sopenharmony_ci	if (ret)
20862306a36Sopenharmony_ci		mutex_unlock(&c->alloc_sem);
20962306a36Sopenharmony_ci	return ret;
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ciint jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
21362306a36Sopenharmony_ci			   uint32_t *len, uint32_t sumsize)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	int ret;
21662306a36Sopenharmony_ci	minsize = PAD(minsize);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	while (true) {
22162306a36Sopenharmony_ci		spin_lock(&c->erase_completion_lock);
22262306a36Sopenharmony_ci		ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
22362306a36Sopenharmony_ci		if (ret) {
22462306a36Sopenharmony_ci			jffs2_dbg(1, "%s(): looping, ret is %d\n",
22562306a36Sopenharmony_ci				  __func__, ret);
22662306a36Sopenharmony_ci		}
22762306a36Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci		if (ret == -EAGAIN)
23062306a36Sopenharmony_ci			cond_resched();
23162306a36Sopenharmony_ci		else
23262306a36Sopenharmony_ci			break;
23362306a36Sopenharmony_ci	}
23462306a36Sopenharmony_ci	if (!ret)
23562306a36Sopenharmony_ci		ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	return ret;
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci/* Classify nextblock (clean, dirty of verydirty) and force to select an other one */
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistatic void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
24462306a36Sopenharmony_ci{
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	if (c->nextblock == NULL) {
24762306a36Sopenharmony_ci		jffs2_dbg(1, "%s(): Erase block at 0x%08x has already been placed in a list\n",
24862306a36Sopenharmony_ci			  __func__, jeb->offset);
24962306a36Sopenharmony_ci		return;
25062306a36Sopenharmony_ci	}
25162306a36Sopenharmony_ci	/* Check, if we have a dirty block now, or if it was dirty already */
25262306a36Sopenharmony_ci	if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) {
25362306a36Sopenharmony_ci		c->dirty_size += jeb->wasted_size;
25462306a36Sopenharmony_ci		c->wasted_size -= jeb->wasted_size;
25562306a36Sopenharmony_ci		jeb->dirty_size += jeb->wasted_size;
25662306a36Sopenharmony_ci		jeb->wasted_size = 0;
25762306a36Sopenharmony_ci		if (VERYDIRTY(c, jeb->dirty_size)) {
25862306a36Sopenharmony_ci			jffs2_dbg(1, "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
25962306a36Sopenharmony_ci				  jeb->offset, jeb->free_size, jeb->dirty_size,
26062306a36Sopenharmony_ci				  jeb->used_size);
26162306a36Sopenharmony_ci			list_add_tail(&jeb->list, &c->very_dirty_list);
26262306a36Sopenharmony_ci		} else {
26362306a36Sopenharmony_ci			jffs2_dbg(1, "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
26462306a36Sopenharmony_ci				  jeb->offset, jeb->free_size, jeb->dirty_size,
26562306a36Sopenharmony_ci				  jeb->used_size);
26662306a36Sopenharmony_ci			list_add_tail(&jeb->list, &c->dirty_list);
26762306a36Sopenharmony_ci		}
26862306a36Sopenharmony_ci	} else {
26962306a36Sopenharmony_ci		jffs2_dbg(1, "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
27062306a36Sopenharmony_ci			  jeb->offset, jeb->free_size, jeb->dirty_size,
27162306a36Sopenharmony_ci			  jeb->used_size);
27262306a36Sopenharmony_ci		list_add_tail(&jeb->list, &c->clean_list);
27362306a36Sopenharmony_ci	}
27462306a36Sopenharmony_ci	c->nextblock = NULL;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci/* Select a new jeb for nextblock */
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic int jffs2_find_nextblock(struct jffs2_sb_info *c)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	struct list_head *next;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* Take the next block off the 'free' list */
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	if (list_empty(&c->free_list)) {
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci		if (!c->nr_erasing_blocks &&
28962306a36Sopenharmony_ci			!list_empty(&c->erasable_list)) {
29062306a36Sopenharmony_ci			struct jffs2_eraseblock *ejeb;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci			ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list);
29362306a36Sopenharmony_ci			list_move_tail(&ejeb->list, &c->erase_pending_list);
29462306a36Sopenharmony_ci			c->nr_erasing_blocks++;
29562306a36Sopenharmony_ci			jffs2_garbage_collect_trigger(c);
29662306a36Sopenharmony_ci			jffs2_dbg(1, "%s(): Triggering erase of erasable block at 0x%08x\n",
29762306a36Sopenharmony_ci				  __func__, ejeb->offset);
29862306a36Sopenharmony_ci		}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci		if (!c->nr_erasing_blocks &&
30162306a36Sopenharmony_ci			!list_empty(&c->erasable_pending_wbuf_list)) {
30262306a36Sopenharmony_ci			jffs2_dbg(1, "%s(): Flushing write buffer\n",
30362306a36Sopenharmony_ci				  __func__);
30462306a36Sopenharmony_ci			/* c->nextblock is NULL, no update to c->nextblock allowed */
30562306a36Sopenharmony_ci			spin_unlock(&c->erase_completion_lock);
30662306a36Sopenharmony_ci			jffs2_flush_wbuf_pad(c);
30762306a36Sopenharmony_ci			spin_lock(&c->erase_completion_lock);
30862306a36Sopenharmony_ci			/* Have another go. It'll be on the erasable_list now */
30962306a36Sopenharmony_ci			return -EAGAIN;
31062306a36Sopenharmony_ci		}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci		if (!c->nr_erasing_blocks) {
31362306a36Sopenharmony_ci			/* Ouch. We're in GC, or we wouldn't have got here.
31462306a36Sopenharmony_ci			   And there's no space left. At all. */
31562306a36Sopenharmony_ci			pr_crit("Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n",
31662306a36Sopenharmony_ci				c->nr_erasing_blocks, c->nr_free_blocks,
31762306a36Sopenharmony_ci				list_empty(&c->erasable_list) ? "yes" : "no",
31862306a36Sopenharmony_ci				list_empty(&c->erasing_list) ? "yes" : "no",
31962306a36Sopenharmony_ci				list_empty(&c->erase_pending_list) ? "yes" : "no");
32062306a36Sopenharmony_ci			return -ENOSPC;
32162306a36Sopenharmony_ci		}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
32462306a36Sopenharmony_ci		/* Don't wait for it; just erase one right now */
32562306a36Sopenharmony_ci		jffs2_erase_pending_blocks(c, 1);
32662306a36Sopenharmony_ci		spin_lock(&c->erase_completion_lock);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci		/* An erase may have failed, decreasing the
32962306a36Sopenharmony_ci		   amount of free space available. So we must
33062306a36Sopenharmony_ci		   restart from the beginning */
33162306a36Sopenharmony_ci		return -EAGAIN;
33262306a36Sopenharmony_ci	}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	next = c->free_list.next;
33562306a36Sopenharmony_ci	list_del(next);
33662306a36Sopenharmony_ci	c->nextblock = list_entry(next, struct jffs2_eraseblock, list);
33762306a36Sopenharmony_ci	c->nr_free_blocks--;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	jffs2_sum_reset_collected(c->summary); /* reset collected summary */
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
34262306a36Sopenharmony_ci	/* adjust write buffer offset, else we get a non contiguous write bug */
34362306a36Sopenharmony_ci	if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len)
34462306a36Sopenharmony_ci		c->wbuf_ofs = 0xffffffff;
34562306a36Sopenharmony_ci#endif
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): new nextblock = 0x%08x\n",
34862306a36Sopenharmony_ci		  __func__, c->nextblock->offset);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	return 0;
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci/* Called with alloc sem _and_ erase_completion_lock */
35462306a36Sopenharmony_cistatic int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
35562306a36Sopenharmony_ci				  uint32_t *len, uint32_t sumsize)
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci	struct jffs2_eraseblock *jeb = c->nextblock;
35862306a36Sopenharmony_ci	uint32_t reserved_size;				/* for summary information at the end of the jeb */
35962306a36Sopenharmony_ci	int ret;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci restart:
36262306a36Sopenharmony_ci	reserved_size = 0;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	if (jffs2_sum_active() && (sumsize != JFFS2_SUMMARY_NOSUM_SIZE)) {
36562306a36Sopenharmony_ci							/* NOSUM_SIZE means not to generate summary */
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci		if (jeb) {
36862306a36Sopenharmony_ci			reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE);
36962306a36Sopenharmony_ci			dbg_summary("minsize=%d , jeb->free=%d ,"
37062306a36Sopenharmony_ci						"summary->size=%d , sumsize=%d\n",
37162306a36Sopenharmony_ci						minsize, jeb->free_size,
37262306a36Sopenharmony_ci						c->summary->sum_size, sumsize);
37362306a36Sopenharmony_ci		}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci		/* Is there enough space for writing out the current node, or we have to
37662306a36Sopenharmony_ci		   write out summary information now, close this jeb and select new nextblock? */
37762306a36Sopenharmony_ci		if (jeb && (PAD(minsize) + PAD(c->summary->sum_size + sumsize +
37862306a36Sopenharmony_ci					JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size)) {
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci			/* Has summary been disabled for this jeb? */
38162306a36Sopenharmony_ci			if (jffs2_sum_is_disabled(c->summary)) {
38262306a36Sopenharmony_ci				sumsize = JFFS2_SUMMARY_NOSUM_SIZE;
38362306a36Sopenharmony_ci				goto restart;
38462306a36Sopenharmony_ci			}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci			/* Writing out the collected summary information */
38762306a36Sopenharmony_ci			dbg_summary("generating summary for 0x%08x.\n", jeb->offset);
38862306a36Sopenharmony_ci			ret = jffs2_sum_write_sumnode(c);
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci			if (ret)
39162306a36Sopenharmony_ci				return ret;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci			if (jffs2_sum_is_disabled(c->summary)) {
39462306a36Sopenharmony_ci				/* jffs2_write_sumnode() couldn't write out the summary information
39562306a36Sopenharmony_ci				   diabling summary for this jeb and free the collected information
39662306a36Sopenharmony_ci				 */
39762306a36Sopenharmony_ci				sumsize = JFFS2_SUMMARY_NOSUM_SIZE;
39862306a36Sopenharmony_ci				goto restart;
39962306a36Sopenharmony_ci			}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci			jffs2_close_nextblock(c, jeb);
40262306a36Sopenharmony_ci			jeb = NULL;
40362306a36Sopenharmony_ci			/* keep always valid value in reserved_size */
40462306a36Sopenharmony_ci			reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE);
40562306a36Sopenharmony_ci		}
40662306a36Sopenharmony_ci	} else {
40762306a36Sopenharmony_ci		if (jeb && minsize > jeb->free_size) {
40862306a36Sopenharmony_ci			uint32_t waste;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci			/* Skip the end of this block and file it as having some dirty space */
41162306a36Sopenharmony_ci			/* If there's a pending write to it, flush now */
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci			if (jffs2_wbuf_dirty(c)) {
41462306a36Sopenharmony_ci				spin_unlock(&c->erase_completion_lock);
41562306a36Sopenharmony_ci				jffs2_dbg(1, "%s(): Flushing write buffer\n",
41662306a36Sopenharmony_ci					  __func__);
41762306a36Sopenharmony_ci				jffs2_flush_wbuf_pad(c);
41862306a36Sopenharmony_ci				spin_lock(&c->erase_completion_lock);
41962306a36Sopenharmony_ci				jeb = c->nextblock;
42062306a36Sopenharmony_ci				goto restart;
42162306a36Sopenharmony_ci			}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci			spin_unlock(&c->erase_completion_lock);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci			ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci			/* Just lock it again and continue. Nothing much can change because
42862306a36Sopenharmony_ci			   we hold c->alloc_sem anyway. In fact, it's not entirely clear why
42962306a36Sopenharmony_ci			   we hold c->erase_completion_lock in the majority of this function...
43062306a36Sopenharmony_ci			   but that's a question for another (more caffeine-rich) day. */
43162306a36Sopenharmony_ci			spin_lock(&c->erase_completion_lock);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci			if (ret)
43462306a36Sopenharmony_ci				return ret;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci			waste = jeb->free_size;
43762306a36Sopenharmony_ci			jffs2_link_node_ref(c, jeb,
43862306a36Sopenharmony_ci					    (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
43962306a36Sopenharmony_ci					    waste, NULL);
44062306a36Sopenharmony_ci			/* FIXME: that made it count as dirty. Convert to wasted */
44162306a36Sopenharmony_ci			jeb->dirty_size -= waste;
44262306a36Sopenharmony_ci			c->dirty_size -= waste;
44362306a36Sopenharmony_ci			jeb->wasted_size += waste;
44462306a36Sopenharmony_ci			c->wasted_size += waste;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci			jffs2_close_nextblock(c, jeb);
44762306a36Sopenharmony_ci			jeb = NULL;
44862306a36Sopenharmony_ci		}
44962306a36Sopenharmony_ci	}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	if (!jeb) {
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci		ret = jffs2_find_nextblock(c);
45462306a36Sopenharmony_ci		if (ret)
45562306a36Sopenharmony_ci			return ret;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci		jeb = c->nextblock;
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci		if (jeb->free_size != c->sector_size - c->cleanmarker_size) {
46062306a36Sopenharmony_ci			pr_warn("Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n",
46162306a36Sopenharmony_ci				jeb->offset, jeb->free_size);
46262306a36Sopenharmony_ci			goto restart;
46362306a36Sopenharmony_ci		}
46462306a36Sopenharmony_ci	}
46562306a36Sopenharmony_ci	/* OK, jeb (==c->nextblock) is now pointing at a block which definitely has
46662306a36Sopenharmony_ci	   enough space */
46762306a36Sopenharmony_ci	*len = jeb->free_size - reserved_size;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size &&
47062306a36Sopenharmony_ci	    !jeb->first_node->next_in_ino) {
47162306a36Sopenharmony_ci		/* Only node in it beforehand was a CLEANMARKER node (we think).
47262306a36Sopenharmony_ci		   So mark it obsolete now that there's going to be another node
47362306a36Sopenharmony_ci		   in the block. This will reduce used_size to zero but We've
47462306a36Sopenharmony_ci		   already set c->nextblock so that jffs2_mark_node_obsolete()
47562306a36Sopenharmony_ci		   won't try to refile it to the dirty_list.
47662306a36Sopenharmony_ci		*/
47762306a36Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
47862306a36Sopenharmony_ci		jffs2_mark_node_obsolete(c, jeb->first_node);
47962306a36Sopenharmony_ci		spin_lock(&c->erase_completion_lock);
48062306a36Sopenharmony_ci	}
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): Giving 0x%x bytes at 0x%x\n",
48362306a36Sopenharmony_ci		  __func__,
48462306a36Sopenharmony_ci		  *len, jeb->offset + (c->sector_size - jeb->free_size));
48562306a36Sopenharmony_ci	return 0;
48662306a36Sopenharmony_ci}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci/**
48962306a36Sopenharmony_ci *	jffs2_add_physical_node_ref - add a physical node reference to the list
49062306a36Sopenharmony_ci *	@c: superblock info
49162306a36Sopenharmony_ci *	@new: new node reference to add
49262306a36Sopenharmony_ci *	@len: length of this physical node
49362306a36Sopenharmony_ci *
49462306a36Sopenharmony_ci *	Should only be used to report nodes for which space has been allocated
49562306a36Sopenharmony_ci *	by jffs2_reserve_space.
49662306a36Sopenharmony_ci *
49762306a36Sopenharmony_ci *	Must be called with the alloc_sem held.
49862306a36Sopenharmony_ci */
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_cistruct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
50162306a36Sopenharmony_ci						       uint32_t ofs, uint32_t len,
50262306a36Sopenharmony_ci						       struct jffs2_inode_cache *ic)
50362306a36Sopenharmony_ci{
50462306a36Sopenharmony_ci	struct jffs2_eraseblock *jeb;
50562306a36Sopenharmony_ci	struct jffs2_raw_node_ref *new;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	jeb = &c->blocks[ofs / c->sector_size];
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): Node at 0x%x(%d), size 0x%x\n",
51062306a36Sopenharmony_ci		  __func__, ofs & ~3, ofs & 3, len);
51162306a36Sopenharmony_ci#if 1
51262306a36Sopenharmony_ci	/* Allow non-obsolete nodes only to be added at the end of c->nextblock,
51362306a36Sopenharmony_ci	   if c->nextblock is set. Note that wbuf.c will file obsolete nodes
51462306a36Sopenharmony_ci	   even after refiling c->nextblock */
51562306a36Sopenharmony_ci	if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
51662306a36Sopenharmony_ci	    && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
51762306a36Sopenharmony_ci		pr_warn("argh. node added in wrong place at 0x%08x(%d)\n",
51862306a36Sopenharmony_ci			ofs & ~3, ofs & 3);
51962306a36Sopenharmony_ci		if (c->nextblock)
52062306a36Sopenharmony_ci			pr_warn("nextblock 0x%08x", c->nextblock->offset);
52162306a36Sopenharmony_ci		else
52262306a36Sopenharmony_ci			pr_warn("No nextblock");
52362306a36Sopenharmony_ci		pr_cont(", expected at %08x\n",
52462306a36Sopenharmony_ci			jeb->offset + (c->sector_size - jeb->free_size));
52562306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
52662306a36Sopenharmony_ci	}
52762306a36Sopenharmony_ci#endif
52862306a36Sopenharmony_ci	spin_lock(&c->erase_completion_lock);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
53362306a36Sopenharmony_ci		/* If it lives on the dirty_list, jffs2_reserve_space will put it there */
53462306a36Sopenharmony_ci		jffs2_dbg(1, "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
53562306a36Sopenharmony_ci			  jeb->offset, jeb->free_size, jeb->dirty_size,
53662306a36Sopenharmony_ci			  jeb->used_size);
53762306a36Sopenharmony_ci		if (jffs2_wbuf_dirty(c)) {
53862306a36Sopenharmony_ci			/* Flush the last write in the block if it's outstanding */
53962306a36Sopenharmony_ci			spin_unlock(&c->erase_completion_lock);
54062306a36Sopenharmony_ci			jffs2_flush_wbuf_pad(c);
54162306a36Sopenharmony_ci			spin_lock(&c->erase_completion_lock);
54262306a36Sopenharmony_ci		}
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci		list_add_tail(&jeb->list, &c->clean_list);
54562306a36Sopenharmony_ci		c->nextblock = NULL;
54662306a36Sopenharmony_ci	}
54762306a36Sopenharmony_ci	jffs2_dbg_acct_sanity_check_nolock(c,jeb);
54862306a36Sopenharmony_ci	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	spin_unlock(&c->erase_completion_lock);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	return new;
55362306a36Sopenharmony_ci}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_civoid jffs2_complete_reservation(struct jffs2_sb_info *c)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	jffs2_dbg(1, "jffs2_complete_reservation()\n");
55962306a36Sopenharmony_ci	spin_lock(&c->erase_completion_lock);
56062306a36Sopenharmony_ci	jffs2_garbage_collect_trigger(c);
56162306a36Sopenharmony_ci	spin_unlock(&c->erase_completion_lock);
56262306a36Sopenharmony_ci	mutex_unlock(&c->alloc_sem);
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_cistatic inline int on_list(struct list_head *obj, struct list_head *head)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	struct list_head *this;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	list_for_each(this, head) {
57062306a36Sopenharmony_ci		if (this == obj) {
57162306a36Sopenharmony_ci			jffs2_dbg(1, "%p is on list at %p\n", obj, head);
57262306a36Sopenharmony_ci			return 1;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci		}
57562306a36Sopenharmony_ci	}
57662306a36Sopenharmony_ci	return 0;
57762306a36Sopenharmony_ci}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_civoid jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref)
58062306a36Sopenharmony_ci{
58162306a36Sopenharmony_ci	struct jffs2_eraseblock *jeb;
58262306a36Sopenharmony_ci	int blocknr;
58362306a36Sopenharmony_ci	struct jffs2_unknown_node n;
58462306a36Sopenharmony_ci	int ret, addedsize;
58562306a36Sopenharmony_ci	size_t retlen;
58662306a36Sopenharmony_ci	uint32_t freed_len;
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	if(unlikely(!ref)) {
58962306a36Sopenharmony_ci		pr_notice("EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
59062306a36Sopenharmony_ci		return;
59162306a36Sopenharmony_ci	}
59262306a36Sopenharmony_ci	if (ref_obsolete(ref)) {
59362306a36Sopenharmony_ci		jffs2_dbg(1, "%s(): called with already obsolete node at 0x%08x\n",
59462306a36Sopenharmony_ci			  __func__, ref_offset(ref));
59562306a36Sopenharmony_ci		return;
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci	blocknr = ref->flash_offset / c->sector_size;
59862306a36Sopenharmony_ci	if (blocknr >= c->nr_blocks) {
59962306a36Sopenharmony_ci		pr_notice("raw node at 0x%08x is off the end of device!\n",
60062306a36Sopenharmony_ci			  ref->flash_offset);
60162306a36Sopenharmony_ci		BUG();
60262306a36Sopenharmony_ci	}
60362306a36Sopenharmony_ci	jeb = &c->blocks[blocknr];
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	if (jffs2_can_mark_obsolete(c) && !jffs2_is_readonly(c) &&
60662306a36Sopenharmony_ci	    !(c->flags & (JFFS2_SB_FLAG_SCANNING | JFFS2_SB_FLAG_BUILDING))) {
60762306a36Sopenharmony_ci		/* Hm. This may confuse static lock analysis. If any of the above
60862306a36Sopenharmony_ci		   three conditions is false, we're going to return from this
60962306a36Sopenharmony_ci		   function without actually obliterating any nodes or freeing
61062306a36Sopenharmony_ci		   any jffs2_raw_node_refs. So we don't need to stop erases from
61162306a36Sopenharmony_ci		   happening, or protect against people holding an obsolete
61262306a36Sopenharmony_ci		   jffs2_raw_node_ref without the erase_completion_lock. */
61362306a36Sopenharmony_ci		mutex_lock(&c->erase_free_sem);
61462306a36Sopenharmony_ci	}
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	spin_lock(&c->erase_completion_lock);
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	freed_len = ref_totlen(c, jeb, ref);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	if (ref_flags(ref) == REF_UNCHECKED) {
62162306a36Sopenharmony_ci		D1(if (unlikely(jeb->unchecked_size < freed_len)) {
62262306a36Sopenharmony_ci				pr_notice("raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n",
62362306a36Sopenharmony_ci					  freed_len, blocknr,
62462306a36Sopenharmony_ci					  ref->flash_offset, jeb->used_size);
62562306a36Sopenharmony_ci			BUG();
62662306a36Sopenharmony_ci		})
62762306a36Sopenharmony_ci			jffs2_dbg(1, "Obsoleting previously unchecked node at 0x%08x of len %x\n",
62862306a36Sopenharmony_ci				  ref_offset(ref), freed_len);
62962306a36Sopenharmony_ci		jeb->unchecked_size -= freed_len;
63062306a36Sopenharmony_ci		c->unchecked_size -= freed_len;
63162306a36Sopenharmony_ci	} else {
63262306a36Sopenharmony_ci		D1(if (unlikely(jeb->used_size < freed_len)) {
63362306a36Sopenharmony_ci				pr_notice("raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n",
63462306a36Sopenharmony_ci					  freed_len, blocknr,
63562306a36Sopenharmony_ci					  ref->flash_offset, jeb->used_size);
63662306a36Sopenharmony_ci			BUG();
63762306a36Sopenharmony_ci		})
63862306a36Sopenharmony_ci			jffs2_dbg(1, "Obsoleting node at 0x%08x of len %#x: ",
63962306a36Sopenharmony_ci				  ref_offset(ref), freed_len);
64062306a36Sopenharmony_ci		jeb->used_size -= freed_len;
64162306a36Sopenharmony_ci		c->used_size -= freed_len;
64262306a36Sopenharmony_ci	}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	// Take care, that wasted size is taken into concern
64562306a36Sopenharmony_ci	if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
64662306a36Sopenharmony_ci		jffs2_dbg(1, "Dirtying\n");
64762306a36Sopenharmony_ci		addedsize = freed_len;
64862306a36Sopenharmony_ci		jeb->dirty_size += freed_len;
64962306a36Sopenharmony_ci		c->dirty_size += freed_len;
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci		/* Convert wasted space to dirty, if not a bad block */
65262306a36Sopenharmony_ci		if (jeb->wasted_size) {
65362306a36Sopenharmony_ci			if (on_list(&jeb->list, &c->bad_used_list)) {
65462306a36Sopenharmony_ci				jffs2_dbg(1, "Leaving block at %08x on the bad_used_list\n",
65562306a36Sopenharmony_ci					  jeb->offset);
65662306a36Sopenharmony_ci				addedsize = 0; /* To fool the refiling code later */
65762306a36Sopenharmony_ci			} else {
65862306a36Sopenharmony_ci				jffs2_dbg(1, "Converting %d bytes of wasted space to dirty in block at %08x\n",
65962306a36Sopenharmony_ci					  jeb->wasted_size, jeb->offset);
66062306a36Sopenharmony_ci				addedsize += jeb->wasted_size;
66162306a36Sopenharmony_ci				jeb->dirty_size += jeb->wasted_size;
66262306a36Sopenharmony_ci				c->dirty_size += jeb->wasted_size;
66362306a36Sopenharmony_ci				c->wasted_size -= jeb->wasted_size;
66462306a36Sopenharmony_ci				jeb->wasted_size = 0;
66562306a36Sopenharmony_ci			}
66662306a36Sopenharmony_ci		}
66762306a36Sopenharmony_ci	} else {
66862306a36Sopenharmony_ci		jffs2_dbg(1, "Wasting\n");
66962306a36Sopenharmony_ci		addedsize = 0;
67062306a36Sopenharmony_ci		jeb->wasted_size += freed_len;
67162306a36Sopenharmony_ci		c->wasted_size += freed_len;
67262306a36Sopenharmony_ci	}
67362306a36Sopenharmony_ci	ref->flash_offset = ref_offset(ref) | REF_OBSOLETE;
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	jffs2_dbg_acct_sanity_check_nolock(c, jeb);
67662306a36Sopenharmony_ci	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	if (c->flags & JFFS2_SB_FLAG_SCANNING) {
67962306a36Sopenharmony_ci		/* Flash scanning is in progress. Don't muck about with the block
68062306a36Sopenharmony_ci		   lists because they're not ready yet, and don't actually
68162306a36Sopenharmony_ci		   obliterate nodes that look obsolete. If they weren't
68262306a36Sopenharmony_ci		   marked obsolete on the flash at the time they _became_
68362306a36Sopenharmony_ci		   obsolete, there was probably a reason for that. */
68462306a36Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
68562306a36Sopenharmony_ci		/* We didn't lock the erase_free_sem */
68662306a36Sopenharmony_ci		return;
68762306a36Sopenharmony_ci	}
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	if (jeb == c->nextblock) {
69062306a36Sopenharmony_ci		jffs2_dbg(2, "Not moving nextblock 0x%08x to dirty/erase_pending list\n",
69162306a36Sopenharmony_ci			  jeb->offset);
69262306a36Sopenharmony_ci	} else if (!jeb->used_size && !jeb->unchecked_size) {
69362306a36Sopenharmony_ci		if (jeb == c->gcblock) {
69462306a36Sopenharmony_ci			jffs2_dbg(1, "gcblock at 0x%08x completely dirtied. Clearing gcblock...\n",
69562306a36Sopenharmony_ci				  jeb->offset);
69662306a36Sopenharmony_ci			c->gcblock = NULL;
69762306a36Sopenharmony_ci		} else {
69862306a36Sopenharmony_ci			jffs2_dbg(1, "Eraseblock at 0x%08x completely dirtied. Removing from (dirty?) list...\n",
69962306a36Sopenharmony_ci				  jeb->offset);
70062306a36Sopenharmony_ci			list_del(&jeb->list);
70162306a36Sopenharmony_ci		}
70262306a36Sopenharmony_ci		if (jffs2_wbuf_dirty(c)) {
70362306a36Sopenharmony_ci			jffs2_dbg(1, "...and adding to erasable_pending_wbuf_list\n");
70462306a36Sopenharmony_ci			list_add_tail(&jeb->list, &c->erasable_pending_wbuf_list);
70562306a36Sopenharmony_ci		} else {
70662306a36Sopenharmony_ci			if (jiffies & 127) {
70762306a36Sopenharmony_ci				/* Most of the time, we just erase it immediately. Otherwise we
70862306a36Sopenharmony_ci				   spend ages scanning it on mount, etc. */
70962306a36Sopenharmony_ci				jffs2_dbg(1, "...and adding to erase_pending_list\n");
71062306a36Sopenharmony_ci				list_add_tail(&jeb->list, &c->erase_pending_list);
71162306a36Sopenharmony_ci				c->nr_erasing_blocks++;
71262306a36Sopenharmony_ci				jffs2_garbage_collect_trigger(c);
71362306a36Sopenharmony_ci			} else {
71462306a36Sopenharmony_ci				/* Sometimes, however, we leave it elsewhere so it doesn't get
71562306a36Sopenharmony_ci				   immediately reused, and we spread the load a bit. */
71662306a36Sopenharmony_ci				jffs2_dbg(1, "...and adding to erasable_list\n");
71762306a36Sopenharmony_ci				list_add_tail(&jeb->list, &c->erasable_list);
71862306a36Sopenharmony_ci			}
71962306a36Sopenharmony_ci		}
72062306a36Sopenharmony_ci		jffs2_dbg(1, "Done OK\n");
72162306a36Sopenharmony_ci	} else if (jeb == c->gcblock) {
72262306a36Sopenharmony_ci		jffs2_dbg(2, "Not moving gcblock 0x%08x to dirty_list\n",
72362306a36Sopenharmony_ci			  jeb->offset);
72462306a36Sopenharmony_ci	} else if (ISDIRTY(jeb->dirty_size) && !ISDIRTY(jeb->dirty_size - addedsize)) {
72562306a36Sopenharmony_ci		jffs2_dbg(1, "Eraseblock at 0x%08x is freshly dirtied. Removing from clean list...\n",
72662306a36Sopenharmony_ci			  jeb->offset);
72762306a36Sopenharmony_ci		list_del(&jeb->list);
72862306a36Sopenharmony_ci		jffs2_dbg(1, "...and adding to dirty_list\n");
72962306a36Sopenharmony_ci		list_add_tail(&jeb->list, &c->dirty_list);
73062306a36Sopenharmony_ci	} else if (VERYDIRTY(c, jeb->dirty_size) &&
73162306a36Sopenharmony_ci		   !VERYDIRTY(c, jeb->dirty_size - addedsize)) {
73262306a36Sopenharmony_ci		jffs2_dbg(1, "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n",
73362306a36Sopenharmony_ci			  jeb->offset);
73462306a36Sopenharmony_ci		list_del(&jeb->list);
73562306a36Sopenharmony_ci		jffs2_dbg(1, "...and adding to very_dirty_list\n");
73662306a36Sopenharmony_ci		list_add_tail(&jeb->list, &c->very_dirty_list);
73762306a36Sopenharmony_ci	} else {
73862306a36Sopenharmony_ci		jffs2_dbg(1, "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n",
73962306a36Sopenharmony_ci			  jeb->offset, jeb->free_size, jeb->dirty_size,
74062306a36Sopenharmony_ci			  jeb->used_size);
74162306a36Sopenharmony_ci	}
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	spin_unlock(&c->erase_completion_lock);
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	if (!jffs2_can_mark_obsolete(c) || jffs2_is_readonly(c) ||
74662306a36Sopenharmony_ci		(c->flags & JFFS2_SB_FLAG_BUILDING)) {
74762306a36Sopenharmony_ci		/* We didn't lock the erase_free_sem */
74862306a36Sopenharmony_ci		return;
74962306a36Sopenharmony_ci	}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	/* The erase_free_sem is locked, and has been since before we marked the node obsolete
75262306a36Sopenharmony_ci	   and potentially put its eraseblock onto the erase_pending_list. Thus, we know that
75362306a36Sopenharmony_ci	   the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet
75462306a36Sopenharmony_ci	   by jffs2_free_jeb_node_refs() in erase.c. Which is nice. */
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	jffs2_dbg(1, "obliterating obsoleted node at 0x%08x\n",
75762306a36Sopenharmony_ci		  ref_offset(ref));
75862306a36Sopenharmony_ci	ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
75962306a36Sopenharmony_ci	if (ret) {
76062306a36Sopenharmony_ci		pr_warn("Read error reading from obsoleted node at 0x%08x: %d\n",
76162306a36Sopenharmony_ci			ref_offset(ref), ret);
76262306a36Sopenharmony_ci		goto out_erase_sem;
76362306a36Sopenharmony_ci	}
76462306a36Sopenharmony_ci	if (retlen != sizeof(n)) {
76562306a36Sopenharmony_ci		pr_warn("Short read from obsoleted node at 0x%08x: %zd\n",
76662306a36Sopenharmony_ci			ref_offset(ref), retlen);
76762306a36Sopenharmony_ci		goto out_erase_sem;
76862306a36Sopenharmony_ci	}
76962306a36Sopenharmony_ci	if (PAD(je32_to_cpu(n.totlen)) != PAD(freed_len)) {
77062306a36Sopenharmony_ci		pr_warn("Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n",
77162306a36Sopenharmony_ci			je32_to_cpu(n.totlen), freed_len);
77262306a36Sopenharmony_ci		goto out_erase_sem;
77362306a36Sopenharmony_ci	}
77462306a36Sopenharmony_ci	if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) {
77562306a36Sopenharmony_ci		jffs2_dbg(1, "Node at 0x%08x was already marked obsolete (nodetype 0x%04x)\n",
77662306a36Sopenharmony_ci			  ref_offset(ref), je16_to_cpu(n.nodetype));
77762306a36Sopenharmony_ci		goto out_erase_sem;
77862306a36Sopenharmony_ci	}
77962306a36Sopenharmony_ci	/* XXX FIXME: This is ugly now */
78062306a36Sopenharmony_ci	n.nodetype = cpu_to_je16(je16_to_cpu(n.nodetype) & ~JFFS2_NODE_ACCURATE);
78162306a36Sopenharmony_ci	ret = jffs2_flash_write(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
78262306a36Sopenharmony_ci	if (ret) {
78362306a36Sopenharmony_ci		pr_warn("Write error in obliterating obsoleted node at 0x%08x: %d\n",
78462306a36Sopenharmony_ci			ref_offset(ref), ret);
78562306a36Sopenharmony_ci		goto out_erase_sem;
78662306a36Sopenharmony_ci	}
78762306a36Sopenharmony_ci	if (retlen != sizeof(n)) {
78862306a36Sopenharmony_ci		pr_warn("Short write in obliterating obsoleted node at 0x%08x: %zd\n",
78962306a36Sopenharmony_ci			ref_offset(ref), retlen);
79062306a36Sopenharmony_ci		goto out_erase_sem;
79162306a36Sopenharmony_ci	}
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	/* Nodes which have been marked obsolete no longer need to be
79462306a36Sopenharmony_ci	   associated with any inode. Remove them from the per-inode list.
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	   Note we can't do this for NAND at the moment because we need
79762306a36Sopenharmony_ci	   obsolete dirent nodes to stay on the lists, because of the
79862306a36Sopenharmony_ci	   horridness in jffs2_garbage_collect_deletion_dirent(). Also
79962306a36Sopenharmony_ci	   because we delete the inocache, and on NAND we need that to
80062306a36Sopenharmony_ci	   stay around until all the nodes are actually erased, in order
80162306a36Sopenharmony_ci	   to stop us from giving the same inode number to another newly
80262306a36Sopenharmony_ci	   created inode. */
80362306a36Sopenharmony_ci	if (ref->next_in_ino) {
80462306a36Sopenharmony_ci		struct jffs2_inode_cache *ic;
80562306a36Sopenharmony_ci		struct jffs2_raw_node_ref **p;
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci		spin_lock(&c->erase_completion_lock);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci		ic = jffs2_raw_ref_to_ic(ref);
81062306a36Sopenharmony_ci		for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
81162306a36Sopenharmony_ci			;
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci		*p = ref->next_in_ino;
81462306a36Sopenharmony_ci		ref->next_in_ino = NULL;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci		switch (ic->class) {
81762306a36Sopenharmony_ci#ifdef CONFIG_JFFS2_FS_XATTR
81862306a36Sopenharmony_ci			case RAWNODE_CLASS_XATTR_DATUM:
81962306a36Sopenharmony_ci				jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
82062306a36Sopenharmony_ci				break;
82162306a36Sopenharmony_ci			case RAWNODE_CLASS_XATTR_REF:
82262306a36Sopenharmony_ci				jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
82362306a36Sopenharmony_ci				break;
82462306a36Sopenharmony_ci#endif
82562306a36Sopenharmony_ci			default:
82662306a36Sopenharmony_ci				if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
82762306a36Sopenharmony_ci					jffs2_del_ino_cache(c, ic);
82862306a36Sopenharmony_ci				break;
82962306a36Sopenharmony_ci		}
83062306a36Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
83162306a36Sopenharmony_ci	}
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci out_erase_sem:
83462306a36Sopenharmony_ci	mutex_unlock(&c->erase_free_sem);
83562306a36Sopenharmony_ci}
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ciint jffs2_thread_should_wake(struct jffs2_sb_info *c)
83862306a36Sopenharmony_ci{
83962306a36Sopenharmony_ci	int ret = 0;
84062306a36Sopenharmony_ci	uint32_t dirty;
84162306a36Sopenharmony_ci	int nr_very_dirty = 0;
84262306a36Sopenharmony_ci	struct jffs2_eraseblock *jeb;
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	if (!list_empty(&c->erase_complete_list) ||
84562306a36Sopenharmony_ci	    !list_empty(&c->erase_pending_list))
84662306a36Sopenharmony_ci		return 1;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	if (c->unchecked_size) {
84962306a36Sopenharmony_ci		jffs2_dbg(1, "jffs2_thread_should_wake(): unchecked_size %d, check_ino #%d\n",
85062306a36Sopenharmony_ci			  c->unchecked_size, c->check_ino);
85162306a36Sopenharmony_ci		return 1;
85262306a36Sopenharmony_ci	}
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	/* dirty_size contains blocks on erase_pending_list
85562306a36Sopenharmony_ci	 * those blocks are counted in c->nr_erasing_blocks.
85662306a36Sopenharmony_ci	 * If one block is actually erased, it is not longer counted as dirty_space
85762306a36Sopenharmony_ci	 * but it is counted in c->nr_erasing_blocks, so we add it and subtract it
85862306a36Sopenharmony_ci	 * with c->nr_erasing_blocks * c->sector_size again.
85962306a36Sopenharmony_ci	 * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks
86062306a36Sopenharmony_ci	 * This helps us to force gc and pick eventually a clean block to spread the load.
86162306a36Sopenharmony_ci	 */
86262306a36Sopenharmony_ci	dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size;
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger &&
86562306a36Sopenharmony_ci			(dirty > c->nospc_dirty_size))
86662306a36Sopenharmony_ci		ret = 1;
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	list_for_each_entry(jeb, &c->very_dirty_list, list) {
86962306a36Sopenharmony_ci		nr_very_dirty++;
87062306a36Sopenharmony_ci		if (nr_very_dirty == c->vdirty_blocks_gctrigger) {
87162306a36Sopenharmony_ci			ret = 1;
87262306a36Sopenharmony_ci			/* In debug mode, actually go through and count them all */
87362306a36Sopenharmony_ci			D1(continue);
87462306a36Sopenharmony_ci			break;
87562306a36Sopenharmony_ci		}
87662306a36Sopenharmony_ci	}
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x, vdirty_blocks %d: %s\n",
87962306a36Sopenharmony_ci		  __func__, c->nr_free_blocks, c->nr_erasing_blocks,
88062306a36Sopenharmony_ci		  c->dirty_size, nr_very_dirty, ret ? "yes" : "no");
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	return ret;
88362306a36Sopenharmony_ci}
884