18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * JFFS2 -- Journalling Flash File System, Version 2.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright © 2001-2007 Red Hat, Inc.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Created by David Woodhouse <dwmw2@infradead.org>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * For licensing information, see the file 'LICENCE' in this directory.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/kernel.h>
158c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h>
168c2ecf20Sopenharmony_ci#include <linux/compiler.h>
178c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
188c2ecf20Sopenharmony_ci#include "nodelist.h"
198c2ecf20Sopenharmony_ci#include "debug.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/*
228c2ecf20Sopenharmony_ci * Check whether the user is allowed to write.
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_cistatic int jffs2_rp_can_write(struct jffs2_sb_info *c)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	uint32_t avail;
278c2ecf20Sopenharmony_ci	struct jffs2_mount_opts *opts = &c->mount_opts;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	avail = c->dirty_size + c->free_size + c->unchecked_size +
308c2ecf20Sopenharmony_ci		c->erasing_size - c->resv_blocks_write * c->sector_size
318c2ecf20Sopenharmony_ci		- c->nospc_dirty_size;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	if (avail < 2 * opts->rp_size)
348c2ecf20Sopenharmony_ci		jffs2_dbg(1, "rpsize %u, dirty_size %u, free_size %u, "
358c2ecf20Sopenharmony_ci			  "erasing_size %u, unchecked_size %u, "
368c2ecf20Sopenharmony_ci			  "nr_erasing_blocks %u, avail %u, resrv %u\n",
378c2ecf20Sopenharmony_ci			  opts->rp_size, c->dirty_size, c->free_size,
388c2ecf20Sopenharmony_ci			  c->erasing_size, c->unchecked_size,
398c2ecf20Sopenharmony_ci			  c->nr_erasing_blocks, avail, c->nospc_dirty_size);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	if (avail > opts->rp_size)
428c2ecf20Sopenharmony_ci		return 1;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	/* Always allow root */
458c2ecf20Sopenharmony_ci	if (capable(CAP_SYS_RESOURCE))
468c2ecf20Sopenharmony_ci		return 1;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	jffs2_dbg(1, "forbid writing\n");
498c2ecf20Sopenharmony_ci	return 0;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/**
538c2ecf20Sopenharmony_ci *	jffs2_reserve_space - request physical space to write nodes to flash
548c2ecf20Sopenharmony_ci *	@c: superblock info
558c2ecf20Sopenharmony_ci *	@minsize: Minimum acceptable size of allocation
568c2ecf20Sopenharmony_ci *	@len: Returned value of allocation length
578c2ecf20Sopenharmony_ci *	@prio: Allocation type - ALLOC_{NORMAL,DELETION}
588c2ecf20Sopenharmony_ci *
598c2ecf20Sopenharmony_ci *	Requests a block of physical space on the flash. Returns zero for success
608c2ecf20Sopenharmony_ci *	and puts 'len' into the appropriate place, or returns -ENOSPC or other
618c2ecf20Sopenharmony_ci *	error if appropriate. Doesn't return len since that's
628c2ecf20Sopenharmony_ci *
638c2ecf20Sopenharmony_ci *	If it returns zero, jffs2_reserve_space() also downs the per-filesystem
648c2ecf20Sopenharmony_ci *	allocation semaphore, to prevent more than one allocation from being
658c2ecf20Sopenharmony_ci *	active at any time. The semaphore is later released by jffs2_commit_allocation()
668c2ecf20Sopenharmony_ci *
678c2ecf20Sopenharmony_ci *	jffs2_reserve_space() may trigger garbage collection in order to make room
688c2ecf20Sopenharmony_ci *	for the requested allocation.
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic int jffs2_do_reserve_space(struct jffs2_sb_info *c,  uint32_t minsize,
728c2ecf20Sopenharmony_ci				  uint32_t *len, uint32_t sumsize);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ciint jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
758c2ecf20Sopenharmony_ci			uint32_t *len, int prio, uint32_t sumsize)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	int ret = -EAGAIN;
788c2ecf20Sopenharmony_ci	int blocksneeded = c->resv_blocks_write;
798c2ecf20Sopenharmony_ci	/* align it */
808c2ecf20Sopenharmony_ci	minsize = PAD(minsize);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize);
838c2ecf20Sopenharmony_ci	mutex_lock(&c->alloc_sem);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	jffs2_dbg(1, "%s(): alloc sem got\n", __func__);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	spin_lock(&c->erase_completion_lock);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	/*
908c2ecf20Sopenharmony_ci	 * Check if the free space is greater then size of the reserved pool.
918c2ecf20Sopenharmony_ci	 * If not, only allow root to proceed with writing.
928c2ecf20Sopenharmony_ci	 */
938c2ecf20Sopenharmony_ci	if (prio != ALLOC_DELETION && !jffs2_rp_can_write(c)) {
948c2ecf20Sopenharmony_ci		ret = -ENOSPC;
958c2ecf20Sopenharmony_ci		goto out;
968c2ecf20Sopenharmony_ci	}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	/* this needs a little more thought (true <tglx> :)) */
998c2ecf20Sopenharmony_ci	while(ret == -EAGAIN) {
1008c2ecf20Sopenharmony_ci		while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
1018c2ecf20Sopenharmony_ci			uint32_t dirty, avail;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci			/* calculate real dirty size
1048c2ecf20Sopenharmony_ci			 * dirty_size contains blocks on erase_pending_list
1058c2ecf20Sopenharmony_ci			 * those blocks are counted in c->nr_erasing_blocks.
1068c2ecf20Sopenharmony_ci			 * If one block is actually erased, it is not longer counted as dirty_space
1078c2ecf20Sopenharmony_ci			 * but it is counted in c->nr_erasing_blocks, so we add it and subtract it
1088c2ecf20Sopenharmony_ci			 * with c->nr_erasing_blocks * c->sector_size again.
1098c2ecf20Sopenharmony_ci			 * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks
1108c2ecf20Sopenharmony_ci			 * This helps us to force gc and pick eventually a clean block to spread the load.
1118c2ecf20Sopenharmony_ci			 * We add unchecked_size here, as we hopefully will find some space to use.
1128c2ecf20Sopenharmony_ci			 * This will affect the sum only once, as gc first finishes checking
1138c2ecf20Sopenharmony_ci			 * of nodes.
1148c2ecf20Sopenharmony_ci			 */
1158c2ecf20Sopenharmony_ci			dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size + c->unchecked_size;
1168c2ecf20Sopenharmony_ci			if (dirty < c->nospc_dirty_size) {
1178c2ecf20Sopenharmony_ci				if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {
1188c2ecf20Sopenharmony_ci					jffs2_dbg(1, "%s(): Low on dirty space to GC, but it's a deletion. Allowing...\n",
1198c2ecf20Sopenharmony_ci						  __func__);
1208c2ecf20Sopenharmony_ci					break;
1218c2ecf20Sopenharmony_ci				}
1228c2ecf20Sopenharmony_ci				jffs2_dbg(1, "dirty size 0x%08x + unchecked_size 0x%08x < nospc_dirty_size 0x%08x, returning -ENOSPC\n",
1238c2ecf20Sopenharmony_ci					  dirty, c->unchecked_size,
1248c2ecf20Sopenharmony_ci					  c->sector_size);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci				spin_unlock(&c->erase_completion_lock);
1278c2ecf20Sopenharmony_ci				mutex_unlock(&c->alloc_sem);
1288c2ecf20Sopenharmony_ci				return -ENOSPC;
1298c2ecf20Sopenharmony_ci			}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci			/* Calc possibly available space. Possibly available means that we
1328c2ecf20Sopenharmony_ci			 * don't know, if unchecked size contains obsoleted nodes, which could give us some
1338c2ecf20Sopenharmony_ci			 * more usable space. This will affect the sum only once, as gc first finishes checking
1348c2ecf20Sopenharmony_ci			 * of nodes.
1358c2ecf20Sopenharmony_ci			 + Return -ENOSPC, if the maximum possibly available space is less or equal than
1368c2ecf20Sopenharmony_ci			 * blocksneeded * sector_size.
1378c2ecf20Sopenharmony_ci			 * This blocks endless gc looping on a filesystem, which is nearly full, even if
1388c2ecf20Sopenharmony_ci			 * the check above passes.
1398c2ecf20Sopenharmony_ci			 */
1408c2ecf20Sopenharmony_ci			avail = c->free_size + c->dirty_size + c->erasing_size + c->unchecked_size;
1418c2ecf20Sopenharmony_ci			if ( (avail / c->sector_size) <= blocksneeded) {
1428c2ecf20Sopenharmony_ci				if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {
1438c2ecf20Sopenharmony_ci					jffs2_dbg(1, "%s(): Low on possibly available space, but it's a deletion. Allowing...\n",
1448c2ecf20Sopenharmony_ci						  __func__);
1458c2ecf20Sopenharmony_ci					break;
1468c2ecf20Sopenharmony_ci				}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci				jffs2_dbg(1, "max. available size 0x%08x  < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
1498c2ecf20Sopenharmony_ci					  avail, blocksneeded * c->sector_size);
1508c2ecf20Sopenharmony_ci				spin_unlock(&c->erase_completion_lock);
1518c2ecf20Sopenharmony_ci				mutex_unlock(&c->alloc_sem);
1528c2ecf20Sopenharmony_ci				return -ENOSPC;
1538c2ecf20Sopenharmony_ci			}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci			mutex_unlock(&c->alloc_sem);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_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",
1588c2ecf20Sopenharmony_ci				  c->nr_free_blocks, c->nr_erasing_blocks,
1598c2ecf20Sopenharmony_ci				  c->free_size, c->dirty_size, c->wasted_size,
1608c2ecf20Sopenharmony_ci				  c->used_size, c->erasing_size, c->bad_size,
1618c2ecf20Sopenharmony_ci				  c->free_size + c->dirty_size +
1628c2ecf20Sopenharmony_ci				  c->wasted_size + c->used_size +
1638c2ecf20Sopenharmony_ci				  c->erasing_size + c->bad_size,
1648c2ecf20Sopenharmony_ci				  c->flash_size);
1658c2ecf20Sopenharmony_ci			spin_unlock(&c->erase_completion_lock);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci			ret = jffs2_garbage_collect_pass(c);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci			if (ret == -EAGAIN) {
1708c2ecf20Sopenharmony_ci				spin_lock(&c->erase_completion_lock);
1718c2ecf20Sopenharmony_ci				if (c->nr_erasing_blocks &&
1728c2ecf20Sopenharmony_ci				    list_empty(&c->erase_pending_list) &&
1738c2ecf20Sopenharmony_ci				    list_empty(&c->erase_complete_list)) {
1748c2ecf20Sopenharmony_ci					DECLARE_WAITQUEUE(wait, current);
1758c2ecf20Sopenharmony_ci					set_current_state(TASK_UNINTERRUPTIBLE);
1768c2ecf20Sopenharmony_ci					add_wait_queue(&c->erase_wait, &wait);
1778c2ecf20Sopenharmony_ci					jffs2_dbg(1, "%s waiting for erase to complete\n",
1788c2ecf20Sopenharmony_ci						  __func__);
1798c2ecf20Sopenharmony_ci					spin_unlock(&c->erase_completion_lock);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci					schedule();
1828c2ecf20Sopenharmony_ci					remove_wait_queue(&c->erase_wait, &wait);
1838c2ecf20Sopenharmony_ci				} else
1848c2ecf20Sopenharmony_ci					spin_unlock(&c->erase_completion_lock);
1858c2ecf20Sopenharmony_ci			} else if (ret)
1868c2ecf20Sopenharmony_ci				return ret;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci			cond_resched();
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci			if (signal_pending(current))
1918c2ecf20Sopenharmony_ci				return -EINTR;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci			mutex_lock(&c->alloc_sem);
1948c2ecf20Sopenharmony_ci			spin_lock(&c->erase_completion_lock);
1958c2ecf20Sopenharmony_ci		}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci		ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
1988c2ecf20Sopenharmony_ci		if (ret) {
1998c2ecf20Sopenharmony_ci			jffs2_dbg(1, "%s(): ret is %d\n", __func__, ret);
2008c2ecf20Sopenharmony_ci		}
2018c2ecf20Sopenharmony_ci	}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ciout:
2048c2ecf20Sopenharmony_ci	spin_unlock(&c->erase_completion_lock);
2058c2ecf20Sopenharmony_ci	if (!ret)
2068c2ecf20Sopenharmony_ci		ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
2078c2ecf20Sopenharmony_ci	if (ret)
2088c2ecf20Sopenharmony_ci		mutex_unlock(&c->alloc_sem);
2098c2ecf20Sopenharmony_ci	return ret;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ciint jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
2138c2ecf20Sopenharmony_ci			   uint32_t *len, uint32_t sumsize)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	int ret;
2168c2ecf20Sopenharmony_ci	minsize = PAD(minsize);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	while (true) {
2218c2ecf20Sopenharmony_ci		spin_lock(&c->erase_completion_lock);
2228c2ecf20Sopenharmony_ci		ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
2238c2ecf20Sopenharmony_ci		if (ret) {
2248c2ecf20Sopenharmony_ci			jffs2_dbg(1, "%s(): looping, ret is %d\n",
2258c2ecf20Sopenharmony_ci				  __func__, ret);
2268c2ecf20Sopenharmony_ci		}
2278c2ecf20Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci		if (ret == -EAGAIN)
2308c2ecf20Sopenharmony_ci			cond_resched();
2318c2ecf20Sopenharmony_ci		else
2328c2ecf20Sopenharmony_ci			break;
2338c2ecf20Sopenharmony_ci	}
2348c2ecf20Sopenharmony_ci	if (!ret)
2358c2ecf20Sopenharmony_ci		ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	return ret;
2388c2ecf20Sopenharmony_ci}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci/* Classify nextblock (clean, dirty of verydirty) and force to select an other one */
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistatic void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	if (c->nextblock == NULL) {
2478c2ecf20Sopenharmony_ci		jffs2_dbg(1, "%s(): Erase block at 0x%08x has already been placed in a list\n",
2488c2ecf20Sopenharmony_ci			  __func__, jeb->offset);
2498c2ecf20Sopenharmony_ci		return;
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci	/* Check, if we have a dirty block now, or if it was dirty already */
2528c2ecf20Sopenharmony_ci	if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) {
2538c2ecf20Sopenharmony_ci		c->dirty_size += jeb->wasted_size;
2548c2ecf20Sopenharmony_ci		c->wasted_size -= jeb->wasted_size;
2558c2ecf20Sopenharmony_ci		jeb->dirty_size += jeb->wasted_size;
2568c2ecf20Sopenharmony_ci		jeb->wasted_size = 0;
2578c2ecf20Sopenharmony_ci		if (VERYDIRTY(c, jeb->dirty_size)) {
2588c2ecf20Sopenharmony_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",
2598c2ecf20Sopenharmony_ci				  jeb->offset, jeb->free_size, jeb->dirty_size,
2608c2ecf20Sopenharmony_ci				  jeb->used_size);
2618c2ecf20Sopenharmony_ci			list_add_tail(&jeb->list, &c->very_dirty_list);
2628c2ecf20Sopenharmony_ci		} else {
2638c2ecf20Sopenharmony_ci			jffs2_dbg(1, "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
2648c2ecf20Sopenharmony_ci				  jeb->offset, jeb->free_size, jeb->dirty_size,
2658c2ecf20Sopenharmony_ci				  jeb->used_size);
2668c2ecf20Sopenharmony_ci			list_add_tail(&jeb->list, &c->dirty_list);
2678c2ecf20Sopenharmony_ci		}
2688c2ecf20Sopenharmony_ci	} else {
2698c2ecf20Sopenharmony_ci		jffs2_dbg(1, "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
2708c2ecf20Sopenharmony_ci			  jeb->offset, jeb->free_size, jeb->dirty_size,
2718c2ecf20Sopenharmony_ci			  jeb->used_size);
2728c2ecf20Sopenharmony_ci		list_add_tail(&jeb->list, &c->clean_list);
2738c2ecf20Sopenharmony_ci	}
2748c2ecf20Sopenharmony_ci	c->nextblock = NULL;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci/* Select a new jeb for nextblock */
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic int jffs2_find_nextblock(struct jffs2_sb_info *c)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	struct list_head *next;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	/* Take the next block off the 'free' list */
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	if (list_empty(&c->free_list)) {
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		if (!c->nr_erasing_blocks &&
2898c2ecf20Sopenharmony_ci			!list_empty(&c->erasable_list)) {
2908c2ecf20Sopenharmony_ci			struct jffs2_eraseblock *ejeb;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci			ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list);
2938c2ecf20Sopenharmony_ci			list_move_tail(&ejeb->list, &c->erase_pending_list);
2948c2ecf20Sopenharmony_ci			c->nr_erasing_blocks++;
2958c2ecf20Sopenharmony_ci			jffs2_garbage_collect_trigger(c);
2968c2ecf20Sopenharmony_ci			jffs2_dbg(1, "%s(): Triggering erase of erasable block at 0x%08x\n",
2978c2ecf20Sopenharmony_ci				  __func__, ejeb->offset);
2988c2ecf20Sopenharmony_ci		}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci		if (!c->nr_erasing_blocks &&
3018c2ecf20Sopenharmony_ci			!list_empty(&c->erasable_pending_wbuf_list)) {
3028c2ecf20Sopenharmony_ci			jffs2_dbg(1, "%s(): Flushing write buffer\n",
3038c2ecf20Sopenharmony_ci				  __func__);
3048c2ecf20Sopenharmony_ci			/* c->nextblock is NULL, no update to c->nextblock allowed */
3058c2ecf20Sopenharmony_ci			spin_unlock(&c->erase_completion_lock);
3068c2ecf20Sopenharmony_ci			jffs2_flush_wbuf_pad(c);
3078c2ecf20Sopenharmony_ci			spin_lock(&c->erase_completion_lock);
3088c2ecf20Sopenharmony_ci			/* Have another go. It'll be on the erasable_list now */
3098c2ecf20Sopenharmony_ci			return -EAGAIN;
3108c2ecf20Sopenharmony_ci		}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci		if (!c->nr_erasing_blocks) {
3138c2ecf20Sopenharmony_ci			/* Ouch. We're in GC, or we wouldn't have got here.
3148c2ecf20Sopenharmony_ci			   And there's no space left. At all. */
3158c2ecf20Sopenharmony_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",
3168c2ecf20Sopenharmony_ci				c->nr_erasing_blocks, c->nr_free_blocks,
3178c2ecf20Sopenharmony_ci				list_empty(&c->erasable_list) ? "yes" : "no",
3188c2ecf20Sopenharmony_ci				list_empty(&c->erasing_list) ? "yes" : "no",
3198c2ecf20Sopenharmony_ci				list_empty(&c->erase_pending_list) ? "yes" : "no");
3208c2ecf20Sopenharmony_ci			return -ENOSPC;
3218c2ecf20Sopenharmony_ci		}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
3248c2ecf20Sopenharmony_ci		/* Don't wait for it; just erase one right now */
3258c2ecf20Sopenharmony_ci		jffs2_erase_pending_blocks(c, 1);
3268c2ecf20Sopenharmony_ci		spin_lock(&c->erase_completion_lock);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci		/* An erase may have failed, decreasing the
3298c2ecf20Sopenharmony_ci		   amount of free space available. So we must
3308c2ecf20Sopenharmony_ci		   restart from the beginning */
3318c2ecf20Sopenharmony_ci		return -EAGAIN;
3328c2ecf20Sopenharmony_ci	}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	next = c->free_list.next;
3358c2ecf20Sopenharmony_ci	list_del(next);
3368c2ecf20Sopenharmony_ci	c->nextblock = list_entry(next, struct jffs2_eraseblock, list);
3378c2ecf20Sopenharmony_ci	c->nr_free_blocks--;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	jffs2_sum_reset_collected(c->summary); /* reset collected summary */
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
3428c2ecf20Sopenharmony_ci	/* adjust write buffer offset, else we get a non contiguous write bug */
3438c2ecf20Sopenharmony_ci	if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len)
3448c2ecf20Sopenharmony_ci		c->wbuf_ofs = 0xffffffff;
3458c2ecf20Sopenharmony_ci#endif
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	jffs2_dbg(1, "%s(): new nextblock = 0x%08x\n",
3488c2ecf20Sopenharmony_ci		  __func__, c->nextblock->offset);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	return 0;
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci/* Called with alloc sem _and_ erase_completion_lock */
3548c2ecf20Sopenharmony_cistatic int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
3558c2ecf20Sopenharmony_ci				  uint32_t *len, uint32_t sumsize)
3568c2ecf20Sopenharmony_ci{
3578c2ecf20Sopenharmony_ci	struct jffs2_eraseblock *jeb = c->nextblock;
3588c2ecf20Sopenharmony_ci	uint32_t reserved_size;				/* for summary information at the end of the jeb */
3598c2ecf20Sopenharmony_ci	int ret;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci restart:
3628c2ecf20Sopenharmony_ci	reserved_size = 0;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	if (jffs2_sum_active() && (sumsize != JFFS2_SUMMARY_NOSUM_SIZE)) {
3658c2ecf20Sopenharmony_ci							/* NOSUM_SIZE means not to generate summary */
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci		if (jeb) {
3688c2ecf20Sopenharmony_ci			reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE);
3698c2ecf20Sopenharmony_ci			dbg_summary("minsize=%d , jeb->free=%d ,"
3708c2ecf20Sopenharmony_ci						"summary->size=%d , sumsize=%d\n",
3718c2ecf20Sopenharmony_ci						minsize, jeb->free_size,
3728c2ecf20Sopenharmony_ci						c->summary->sum_size, sumsize);
3738c2ecf20Sopenharmony_ci		}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci		/* Is there enough space for writing out the current node, or we have to
3768c2ecf20Sopenharmony_ci		   write out summary information now, close this jeb and select new nextblock? */
3778c2ecf20Sopenharmony_ci		if (jeb && (PAD(minsize) + PAD(c->summary->sum_size + sumsize +
3788c2ecf20Sopenharmony_ci					JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size)) {
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci			/* Has summary been disabled for this jeb? */
3818c2ecf20Sopenharmony_ci			if (jffs2_sum_is_disabled(c->summary)) {
3828c2ecf20Sopenharmony_ci				sumsize = JFFS2_SUMMARY_NOSUM_SIZE;
3838c2ecf20Sopenharmony_ci				goto restart;
3848c2ecf20Sopenharmony_ci			}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci			/* Writing out the collected summary information */
3878c2ecf20Sopenharmony_ci			dbg_summary("generating summary for 0x%08x.\n", jeb->offset);
3888c2ecf20Sopenharmony_ci			ret = jffs2_sum_write_sumnode(c);
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci			if (ret)
3918c2ecf20Sopenharmony_ci				return ret;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci			if (jffs2_sum_is_disabled(c->summary)) {
3948c2ecf20Sopenharmony_ci				/* jffs2_write_sumnode() couldn't write out the summary information
3958c2ecf20Sopenharmony_ci				   diabling summary for this jeb and free the collected information
3968c2ecf20Sopenharmony_ci				 */
3978c2ecf20Sopenharmony_ci				sumsize = JFFS2_SUMMARY_NOSUM_SIZE;
3988c2ecf20Sopenharmony_ci				goto restart;
3998c2ecf20Sopenharmony_ci			}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci			jffs2_close_nextblock(c, jeb);
4028c2ecf20Sopenharmony_ci			jeb = NULL;
4038c2ecf20Sopenharmony_ci			/* keep always valid value in reserved_size */
4048c2ecf20Sopenharmony_ci			reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE);
4058c2ecf20Sopenharmony_ci		}
4068c2ecf20Sopenharmony_ci	} else {
4078c2ecf20Sopenharmony_ci		if (jeb && minsize > jeb->free_size) {
4088c2ecf20Sopenharmony_ci			uint32_t waste;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci			/* Skip the end of this block and file it as having some dirty space */
4118c2ecf20Sopenharmony_ci			/* If there's a pending write to it, flush now */
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci			if (jffs2_wbuf_dirty(c)) {
4148c2ecf20Sopenharmony_ci				spin_unlock(&c->erase_completion_lock);
4158c2ecf20Sopenharmony_ci				jffs2_dbg(1, "%s(): Flushing write buffer\n",
4168c2ecf20Sopenharmony_ci					  __func__);
4178c2ecf20Sopenharmony_ci				jffs2_flush_wbuf_pad(c);
4188c2ecf20Sopenharmony_ci				spin_lock(&c->erase_completion_lock);
4198c2ecf20Sopenharmony_ci				jeb = c->nextblock;
4208c2ecf20Sopenharmony_ci				goto restart;
4218c2ecf20Sopenharmony_ci			}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci			spin_unlock(&c->erase_completion_lock);
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci			ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci			/* Just lock it again and continue. Nothing much can change because
4288c2ecf20Sopenharmony_ci			   we hold c->alloc_sem anyway. In fact, it's not entirely clear why
4298c2ecf20Sopenharmony_ci			   we hold c->erase_completion_lock in the majority of this function...
4308c2ecf20Sopenharmony_ci			   but that's a question for another (more caffeine-rich) day. */
4318c2ecf20Sopenharmony_ci			spin_lock(&c->erase_completion_lock);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci			if (ret)
4348c2ecf20Sopenharmony_ci				return ret;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci			waste = jeb->free_size;
4378c2ecf20Sopenharmony_ci			jffs2_link_node_ref(c, jeb,
4388c2ecf20Sopenharmony_ci					    (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
4398c2ecf20Sopenharmony_ci					    waste, NULL);
4408c2ecf20Sopenharmony_ci			/* FIXME: that made it count as dirty. Convert to wasted */
4418c2ecf20Sopenharmony_ci			jeb->dirty_size -= waste;
4428c2ecf20Sopenharmony_ci			c->dirty_size -= waste;
4438c2ecf20Sopenharmony_ci			jeb->wasted_size += waste;
4448c2ecf20Sopenharmony_ci			c->wasted_size += waste;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci			jffs2_close_nextblock(c, jeb);
4478c2ecf20Sopenharmony_ci			jeb = NULL;
4488c2ecf20Sopenharmony_ci		}
4498c2ecf20Sopenharmony_ci	}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (!jeb) {
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci		ret = jffs2_find_nextblock(c);
4548c2ecf20Sopenharmony_ci		if (ret)
4558c2ecf20Sopenharmony_ci			return ret;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci		jeb = c->nextblock;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci		if (jeb->free_size != c->sector_size - c->cleanmarker_size) {
4608c2ecf20Sopenharmony_ci			pr_warn("Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n",
4618c2ecf20Sopenharmony_ci				jeb->offset, jeb->free_size);
4628c2ecf20Sopenharmony_ci			goto restart;
4638c2ecf20Sopenharmony_ci		}
4648c2ecf20Sopenharmony_ci	}
4658c2ecf20Sopenharmony_ci	/* OK, jeb (==c->nextblock) is now pointing at a block which definitely has
4668c2ecf20Sopenharmony_ci	   enough space */
4678c2ecf20Sopenharmony_ci	*len = jeb->free_size - reserved_size;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size &&
4708c2ecf20Sopenharmony_ci	    !jeb->first_node->next_in_ino) {
4718c2ecf20Sopenharmony_ci		/* Only node in it beforehand was a CLEANMARKER node (we think).
4728c2ecf20Sopenharmony_ci		   So mark it obsolete now that there's going to be another node
4738c2ecf20Sopenharmony_ci		   in the block. This will reduce used_size to zero but We've
4748c2ecf20Sopenharmony_ci		   already set c->nextblock so that jffs2_mark_node_obsolete()
4758c2ecf20Sopenharmony_ci		   won't try to refile it to the dirty_list.
4768c2ecf20Sopenharmony_ci		*/
4778c2ecf20Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
4788c2ecf20Sopenharmony_ci		jffs2_mark_node_obsolete(c, jeb->first_node);
4798c2ecf20Sopenharmony_ci		spin_lock(&c->erase_completion_lock);
4808c2ecf20Sopenharmony_ci	}
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	jffs2_dbg(1, "%s(): Giving 0x%x bytes at 0x%x\n",
4838c2ecf20Sopenharmony_ci		  __func__,
4848c2ecf20Sopenharmony_ci		  *len, jeb->offset + (c->sector_size - jeb->free_size));
4858c2ecf20Sopenharmony_ci	return 0;
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci/**
4898c2ecf20Sopenharmony_ci *	jffs2_add_physical_node_ref - add a physical node reference to the list
4908c2ecf20Sopenharmony_ci *	@c: superblock info
4918c2ecf20Sopenharmony_ci *	@new: new node reference to add
4928c2ecf20Sopenharmony_ci *	@len: length of this physical node
4938c2ecf20Sopenharmony_ci *
4948c2ecf20Sopenharmony_ci *	Should only be used to report nodes for which space has been allocated
4958c2ecf20Sopenharmony_ci *	by jffs2_reserve_space.
4968c2ecf20Sopenharmony_ci *
4978c2ecf20Sopenharmony_ci *	Must be called with the alloc_sem held.
4988c2ecf20Sopenharmony_ci */
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_cistruct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
5018c2ecf20Sopenharmony_ci						       uint32_t ofs, uint32_t len,
5028c2ecf20Sopenharmony_ci						       struct jffs2_inode_cache *ic)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	struct jffs2_eraseblock *jeb;
5058c2ecf20Sopenharmony_ci	struct jffs2_raw_node_ref *new;
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	jeb = &c->blocks[ofs / c->sector_size];
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	jffs2_dbg(1, "%s(): Node at 0x%x(%d), size 0x%x\n",
5108c2ecf20Sopenharmony_ci		  __func__, ofs & ~3, ofs & 3, len);
5118c2ecf20Sopenharmony_ci#if 1
5128c2ecf20Sopenharmony_ci	/* Allow non-obsolete nodes only to be added at the end of c->nextblock,
5138c2ecf20Sopenharmony_ci	   if c->nextblock is set. Note that wbuf.c will file obsolete nodes
5148c2ecf20Sopenharmony_ci	   even after refiling c->nextblock */
5158c2ecf20Sopenharmony_ci	if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
5168c2ecf20Sopenharmony_ci	    && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
5178c2ecf20Sopenharmony_ci		pr_warn("argh. node added in wrong place at 0x%08x(%d)\n",
5188c2ecf20Sopenharmony_ci			ofs & ~3, ofs & 3);
5198c2ecf20Sopenharmony_ci		if (c->nextblock)
5208c2ecf20Sopenharmony_ci			pr_warn("nextblock 0x%08x", c->nextblock->offset);
5218c2ecf20Sopenharmony_ci		else
5228c2ecf20Sopenharmony_ci			pr_warn("No nextblock");
5238c2ecf20Sopenharmony_ci		pr_cont(", expected at %08x\n",
5248c2ecf20Sopenharmony_ci			jeb->offset + (c->sector_size - jeb->free_size));
5258c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
5268c2ecf20Sopenharmony_ci	}
5278c2ecf20Sopenharmony_ci#endif
5288c2ecf20Sopenharmony_ci	spin_lock(&c->erase_completion_lock);
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
5338c2ecf20Sopenharmony_ci		/* If it lives on the dirty_list, jffs2_reserve_space will put it there */
5348c2ecf20Sopenharmony_ci		jffs2_dbg(1, "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
5358c2ecf20Sopenharmony_ci			  jeb->offset, jeb->free_size, jeb->dirty_size,
5368c2ecf20Sopenharmony_ci			  jeb->used_size);
5378c2ecf20Sopenharmony_ci		if (jffs2_wbuf_dirty(c)) {
5388c2ecf20Sopenharmony_ci			/* Flush the last write in the block if it's outstanding */
5398c2ecf20Sopenharmony_ci			spin_unlock(&c->erase_completion_lock);
5408c2ecf20Sopenharmony_ci			jffs2_flush_wbuf_pad(c);
5418c2ecf20Sopenharmony_ci			spin_lock(&c->erase_completion_lock);
5428c2ecf20Sopenharmony_ci		}
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci		list_add_tail(&jeb->list, &c->clean_list);
5458c2ecf20Sopenharmony_ci		c->nextblock = NULL;
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci	jffs2_dbg_acct_sanity_check_nolock(c,jeb);
5488c2ecf20Sopenharmony_ci	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	spin_unlock(&c->erase_completion_lock);
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	return new;
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_civoid jffs2_complete_reservation(struct jffs2_sb_info *c)
5578c2ecf20Sopenharmony_ci{
5588c2ecf20Sopenharmony_ci	jffs2_dbg(1, "jffs2_complete_reservation()\n");
5598c2ecf20Sopenharmony_ci	spin_lock(&c->erase_completion_lock);
5608c2ecf20Sopenharmony_ci	jffs2_garbage_collect_trigger(c);
5618c2ecf20Sopenharmony_ci	spin_unlock(&c->erase_completion_lock);
5628c2ecf20Sopenharmony_ci	mutex_unlock(&c->alloc_sem);
5638c2ecf20Sopenharmony_ci}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_cistatic inline int on_list(struct list_head *obj, struct list_head *head)
5668c2ecf20Sopenharmony_ci{
5678c2ecf20Sopenharmony_ci	struct list_head *this;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	list_for_each(this, head) {
5708c2ecf20Sopenharmony_ci		if (this == obj) {
5718c2ecf20Sopenharmony_ci			jffs2_dbg(1, "%p is on list at %p\n", obj, head);
5728c2ecf20Sopenharmony_ci			return 1;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci		}
5758c2ecf20Sopenharmony_ci	}
5768c2ecf20Sopenharmony_ci	return 0;
5778c2ecf20Sopenharmony_ci}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_civoid jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref)
5808c2ecf20Sopenharmony_ci{
5818c2ecf20Sopenharmony_ci	struct jffs2_eraseblock *jeb;
5828c2ecf20Sopenharmony_ci	int blocknr;
5838c2ecf20Sopenharmony_ci	struct jffs2_unknown_node n;
5848c2ecf20Sopenharmony_ci	int ret, addedsize;
5858c2ecf20Sopenharmony_ci	size_t retlen;
5868c2ecf20Sopenharmony_ci	uint32_t freed_len;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	if(unlikely(!ref)) {
5898c2ecf20Sopenharmony_ci		pr_notice("EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
5908c2ecf20Sopenharmony_ci		return;
5918c2ecf20Sopenharmony_ci	}
5928c2ecf20Sopenharmony_ci	if (ref_obsolete(ref)) {
5938c2ecf20Sopenharmony_ci		jffs2_dbg(1, "%s(): called with already obsolete node at 0x%08x\n",
5948c2ecf20Sopenharmony_ci			  __func__, ref_offset(ref));
5958c2ecf20Sopenharmony_ci		return;
5968c2ecf20Sopenharmony_ci	}
5978c2ecf20Sopenharmony_ci	blocknr = ref->flash_offset / c->sector_size;
5988c2ecf20Sopenharmony_ci	if (blocknr >= c->nr_blocks) {
5998c2ecf20Sopenharmony_ci		pr_notice("raw node at 0x%08x is off the end of device!\n",
6008c2ecf20Sopenharmony_ci			  ref->flash_offset);
6018c2ecf20Sopenharmony_ci		BUG();
6028c2ecf20Sopenharmony_ci	}
6038c2ecf20Sopenharmony_ci	jeb = &c->blocks[blocknr];
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	if (jffs2_can_mark_obsolete(c) && !jffs2_is_readonly(c) &&
6068c2ecf20Sopenharmony_ci	    !(c->flags & (JFFS2_SB_FLAG_SCANNING | JFFS2_SB_FLAG_BUILDING))) {
6078c2ecf20Sopenharmony_ci		/* Hm. This may confuse static lock analysis. If any of the above
6088c2ecf20Sopenharmony_ci		   three conditions is false, we're going to return from this
6098c2ecf20Sopenharmony_ci		   function without actually obliterating any nodes or freeing
6108c2ecf20Sopenharmony_ci		   any jffs2_raw_node_refs. So we don't need to stop erases from
6118c2ecf20Sopenharmony_ci		   happening, or protect against people holding an obsolete
6128c2ecf20Sopenharmony_ci		   jffs2_raw_node_ref without the erase_completion_lock. */
6138c2ecf20Sopenharmony_ci		mutex_lock(&c->erase_free_sem);
6148c2ecf20Sopenharmony_ci	}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	spin_lock(&c->erase_completion_lock);
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	freed_len = ref_totlen(c, jeb, ref);
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	if (ref_flags(ref) == REF_UNCHECKED) {
6218c2ecf20Sopenharmony_ci		D1(if (unlikely(jeb->unchecked_size < freed_len)) {
6228c2ecf20Sopenharmony_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",
6238c2ecf20Sopenharmony_ci					  freed_len, blocknr,
6248c2ecf20Sopenharmony_ci					  ref->flash_offset, jeb->used_size);
6258c2ecf20Sopenharmony_ci			BUG();
6268c2ecf20Sopenharmony_ci		})
6278c2ecf20Sopenharmony_ci			jffs2_dbg(1, "Obsoleting previously unchecked node at 0x%08x of len %x\n",
6288c2ecf20Sopenharmony_ci				  ref_offset(ref), freed_len);
6298c2ecf20Sopenharmony_ci		jeb->unchecked_size -= freed_len;
6308c2ecf20Sopenharmony_ci		c->unchecked_size -= freed_len;
6318c2ecf20Sopenharmony_ci	} else {
6328c2ecf20Sopenharmony_ci		D1(if (unlikely(jeb->used_size < freed_len)) {
6338c2ecf20Sopenharmony_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",
6348c2ecf20Sopenharmony_ci					  freed_len, blocknr,
6358c2ecf20Sopenharmony_ci					  ref->flash_offset, jeb->used_size);
6368c2ecf20Sopenharmony_ci			BUG();
6378c2ecf20Sopenharmony_ci		})
6388c2ecf20Sopenharmony_ci			jffs2_dbg(1, "Obsoleting node at 0x%08x of len %#x: ",
6398c2ecf20Sopenharmony_ci				  ref_offset(ref), freed_len);
6408c2ecf20Sopenharmony_ci		jeb->used_size -= freed_len;
6418c2ecf20Sopenharmony_ci		c->used_size -= freed_len;
6428c2ecf20Sopenharmony_ci	}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	// Take care, that wasted size is taken into concern
6458c2ecf20Sopenharmony_ci	if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
6468c2ecf20Sopenharmony_ci		jffs2_dbg(1, "Dirtying\n");
6478c2ecf20Sopenharmony_ci		addedsize = freed_len;
6488c2ecf20Sopenharmony_ci		jeb->dirty_size += freed_len;
6498c2ecf20Sopenharmony_ci		c->dirty_size += freed_len;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci		/* Convert wasted space to dirty, if not a bad block */
6528c2ecf20Sopenharmony_ci		if (jeb->wasted_size) {
6538c2ecf20Sopenharmony_ci			if (on_list(&jeb->list, &c->bad_used_list)) {
6548c2ecf20Sopenharmony_ci				jffs2_dbg(1, "Leaving block at %08x on the bad_used_list\n",
6558c2ecf20Sopenharmony_ci					  jeb->offset);
6568c2ecf20Sopenharmony_ci				addedsize = 0; /* To fool the refiling code later */
6578c2ecf20Sopenharmony_ci			} else {
6588c2ecf20Sopenharmony_ci				jffs2_dbg(1, "Converting %d bytes of wasted space to dirty in block at %08x\n",
6598c2ecf20Sopenharmony_ci					  jeb->wasted_size, jeb->offset);
6608c2ecf20Sopenharmony_ci				addedsize += jeb->wasted_size;
6618c2ecf20Sopenharmony_ci				jeb->dirty_size += jeb->wasted_size;
6628c2ecf20Sopenharmony_ci				c->dirty_size += jeb->wasted_size;
6638c2ecf20Sopenharmony_ci				c->wasted_size -= jeb->wasted_size;
6648c2ecf20Sopenharmony_ci				jeb->wasted_size = 0;
6658c2ecf20Sopenharmony_ci			}
6668c2ecf20Sopenharmony_ci		}
6678c2ecf20Sopenharmony_ci	} else {
6688c2ecf20Sopenharmony_ci		jffs2_dbg(1, "Wasting\n");
6698c2ecf20Sopenharmony_ci		addedsize = 0;
6708c2ecf20Sopenharmony_ci		jeb->wasted_size += freed_len;
6718c2ecf20Sopenharmony_ci		c->wasted_size += freed_len;
6728c2ecf20Sopenharmony_ci	}
6738c2ecf20Sopenharmony_ci	ref->flash_offset = ref_offset(ref) | REF_OBSOLETE;
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	jffs2_dbg_acct_sanity_check_nolock(c, jeb);
6768c2ecf20Sopenharmony_ci	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	if (c->flags & JFFS2_SB_FLAG_SCANNING) {
6798c2ecf20Sopenharmony_ci		/* Flash scanning is in progress. Don't muck about with the block
6808c2ecf20Sopenharmony_ci		   lists because they're not ready yet, and don't actually
6818c2ecf20Sopenharmony_ci		   obliterate nodes that look obsolete. If they weren't
6828c2ecf20Sopenharmony_ci		   marked obsolete on the flash at the time they _became_
6838c2ecf20Sopenharmony_ci		   obsolete, there was probably a reason for that. */
6848c2ecf20Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
6858c2ecf20Sopenharmony_ci		/* We didn't lock the erase_free_sem */
6868c2ecf20Sopenharmony_ci		return;
6878c2ecf20Sopenharmony_ci	}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	if (jeb == c->nextblock) {
6908c2ecf20Sopenharmony_ci		jffs2_dbg(2, "Not moving nextblock 0x%08x to dirty/erase_pending list\n",
6918c2ecf20Sopenharmony_ci			  jeb->offset);
6928c2ecf20Sopenharmony_ci	} else if (!jeb->used_size && !jeb->unchecked_size) {
6938c2ecf20Sopenharmony_ci		if (jeb == c->gcblock) {
6948c2ecf20Sopenharmony_ci			jffs2_dbg(1, "gcblock at 0x%08x completely dirtied. Clearing gcblock...\n",
6958c2ecf20Sopenharmony_ci				  jeb->offset);
6968c2ecf20Sopenharmony_ci			c->gcblock = NULL;
6978c2ecf20Sopenharmony_ci		} else {
6988c2ecf20Sopenharmony_ci			jffs2_dbg(1, "Eraseblock at 0x%08x completely dirtied. Removing from (dirty?) list...\n",
6998c2ecf20Sopenharmony_ci				  jeb->offset);
7008c2ecf20Sopenharmony_ci			list_del(&jeb->list);
7018c2ecf20Sopenharmony_ci		}
7028c2ecf20Sopenharmony_ci		if (jffs2_wbuf_dirty(c)) {
7038c2ecf20Sopenharmony_ci			jffs2_dbg(1, "...and adding to erasable_pending_wbuf_list\n");
7048c2ecf20Sopenharmony_ci			list_add_tail(&jeb->list, &c->erasable_pending_wbuf_list);
7058c2ecf20Sopenharmony_ci		} else {
7068c2ecf20Sopenharmony_ci			if (jiffies & 127) {
7078c2ecf20Sopenharmony_ci				/* Most of the time, we just erase it immediately. Otherwise we
7088c2ecf20Sopenharmony_ci				   spend ages scanning it on mount, etc. */
7098c2ecf20Sopenharmony_ci				jffs2_dbg(1, "...and adding to erase_pending_list\n");
7108c2ecf20Sopenharmony_ci				list_add_tail(&jeb->list, &c->erase_pending_list);
7118c2ecf20Sopenharmony_ci				c->nr_erasing_blocks++;
7128c2ecf20Sopenharmony_ci				jffs2_garbage_collect_trigger(c);
7138c2ecf20Sopenharmony_ci			} else {
7148c2ecf20Sopenharmony_ci				/* Sometimes, however, we leave it elsewhere so it doesn't get
7158c2ecf20Sopenharmony_ci				   immediately reused, and we spread the load a bit. */
7168c2ecf20Sopenharmony_ci				jffs2_dbg(1, "...and adding to erasable_list\n");
7178c2ecf20Sopenharmony_ci				list_add_tail(&jeb->list, &c->erasable_list);
7188c2ecf20Sopenharmony_ci			}
7198c2ecf20Sopenharmony_ci		}
7208c2ecf20Sopenharmony_ci		jffs2_dbg(1, "Done OK\n");
7218c2ecf20Sopenharmony_ci	} else if (jeb == c->gcblock) {
7228c2ecf20Sopenharmony_ci		jffs2_dbg(2, "Not moving gcblock 0x%08x to dirty_list\n",
7238c2ecf20Sopenharmony_ci			  jeb->offset);
7248c2ecf20Sopenharmony_ci	} else if (ISDIRTY(jeb->dirty_size) && !ISDIRTY(jeb->dirty_size - addedsize)) {
7258c2ecf20Sopenharmony_ci		jffs2_dbg(1, "Eraseblock at 0x%08x is freshly dirtied. Removing from clean list...\n",
7268c2ecf20Sopenharmony_ci			  jeb->offset);
7278c2ecf20Sopenharmony_ci		list_del(&jeb->list);
7288c2ecf20Sopenharmony_ci		jffs2_dbg(1, "...and adding to dirty_list\n");
7298c2ecf20Sopenharmony_ci		list_add_tail(&jeb->list, &c->dirty_list);
7308c2ecf20Sopenharmony_ci	} else if (VERYDIRTY(c, jeb->dirty_size) &&
7318c2ecf20Sopenharmony_ci		   !VERYDIRTY(c, jeb->dirty_size - addedsize)) {
7328c2ecf20Sopenharmony_ci		jffs2_dbg(1, "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n",
7338c2ecf20Sopenharmony_ci			  jeb->offset);
7348c2ecf20Sopenharmony_ci		list_del(&jeb->list);
7358c2ecf20Sopenharmony_ci		jffs2_dbg(1, "...and adding to very_dirty_list\n");
7368c2ecf20Sopenharmony_ci		list_add_tail(&jeb->list, &c->very_dirty_list);
7378c2ecf20Sopenharmony_ci	} else {
7388c2ecf20Sopenharmony_ci		jffs2_dbg(1, "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n",
7398c2ecf20Sopenharmony_ci			  jeb->offset, jeb->free_size, jeb->dirty_size,
7408c2ecf20Sopenharmony_ci			  jeb->used_size);
7418c2ecf20Sopenharmony_ci	}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	spin_unlock(&c->erase_completion_lock);
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	if (!jffs2_can_mark_obsolete(c) || jffs2_is_readonly(c) ||
7468c2ecf20Sopenharmony_ci		(c->flags & JFFS2_SB_FLAG_BUILDING)) {
7478c2ecf20Sopenharmony_ci		/* We didn't lock the erase_free_sem */
7488c2ecf20Sopenharmony_ci		return;
7498c2ecf20Sopenharmony_ci	}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	/* The erase_free_sem is locked, and has been since before we marked the node obsolete
7528c2ecf20Sopenharmony_ci	   and potentially put its eraseblock onto the erase_pending_list. Thus, we know that
7538c2ecf20Sopenharmony_ci	   the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet
7548c2ecf20Sopenharmony_ci	   by jffs2_free_jeb_node_refs() in erase.c. Which is nice. */
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	jffs2_dbg(1, "obliterating obsoleted node at 0x%08x\n",
7578c2ecf20Sopenharmony_ci		  ref_offset(ref));
7588c2ecf20Sopenharmony_ci	ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
7598c2ecf20Sopenharmony_ci	if (ret) {
7608c2ecf20Sopenharmony_ci		pr_warn("Read error reading from obsoleted node at 0x%08x: %d\n",
7618c2ecf20Sopenharmony_ci			ref_offset(ref), ret);
7628c2ecf20Sopenharmony_ci		goto out_erase_sem;
7638c2ecf20Sopenharmony_ci	}
7648c2ecf20Sopenharmony_ci	if (retlen != sizeof(n)) {
7658c2ecf20Sopenharmony_ci		pr_warn("Short read from obsoleted node at 0x%08x: %zd\n",
7668c2ecf20Sopenharmony_ci			ref_offset(ref), retlen);
7678c2ecf20Sopenharmony_ci		goto out_erase_sem;
7688c2ecf20Sopenharmony_ci	}
7698c2ecf20Sopenharmony_ci	if (PAD(je32_to_cpu(n.totlen)) != PAD(freed_len)) {
7708c2ecf20Sopenharmony_ci		pr_warn("Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n",
7718c2ecf20Sopenharmony_ci			je32_to_cpu(n.totlen), freed_len);
7728c2ecf20Sopenharmony_ci		goto out_erase_sem;
7738c2ecf20Sopenharmony_ci	}
7748c2ecf20Sopenharmony_ci	if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) {
7758c2ecf20Sopenharmony_ci		jffs2_dbg(1, "Node at 0x%08x was already marked obsolete (nodetype 0x%04x)\n",
7768c2ecf20Sopenharmony_ci			  ref_offset(ref), je16_to_cpu(n.nodetype));
7778c2ecf20Sopenharmony_ci		goto out_erase_sem;
7788c2ecf20Sopenharmony_ci	}
7798c2ecf20Sopenharmony_ci	/* XXX FIXME: This is ugly now */
7808c2ecf20Sopenharmony_ci	n.nodetype = cpu_to_je16(je16_to_cpu(n.nodetype) & ~JFFS2_NODE_ACCURATE);
7818c2ecf20Sopenharmony_ci	ret = jffs2_flash_write(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
7828c2ecf20Sopenharmony_ci	if (ret) {
7838c2ecf20Sopenharmony_ci		pr_warn("Write error in obliterating obsoleted node at 0x%08x: %d\n",
7848c2ecf20Sopenharmony_ci			ref_offset(ref), ret);
7858c2ecf20Sopenharmony_ci		goto out_erase_sem;
7868c2ecf20Sopenharmony_ci	}
7878c2ecf20Sopenharmony_ci	if (retlen != sizeof(n)) {
7888c2ecf20Sopenharmony_ci		pr_warn("Short write in obliterating obsoleted node at 0x%08x: %zd\n",
7898c2ecf20Sopenharmony_ci			ref_offset(ref), retlen);
7908c2ecf20Sopenharmony_ci		goto out_erase_sem;
7918c2ecf20Sopenharmony_ci	}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	/* Nodes which have been marked obsolete no longer need to be
7948c2ecf20Sopenharmony_ci	   associated with any inode. Remove them from the per-inode list.
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	   Note we can't do this for NAND at the moment because we need
7978c2ecf20Sopenharmony_ci	   obsolete dirent nodes to stay on the lists, because of the
7988c2ecf20Sopenharmony_ci	   horridness in jffs2_garbage_collect_deletion_dirent(). Also
7998c2ecf20Sopenharmony_ci	   because we delete the inocache, and on NAND we need that to
8008c2ecf20Sopenharmony_ci	   stay around until all the nodes are actually erased, in order
8018c2ecf20Sopenharmony_ci	   to stop us from giving the same inode number to another newly
8028c2ecf20Sopenharmony_ci	   created inode. */
8038c2ecf20Sopenharmony_ci	if (ref->next_in_ino) {
8048c2ecf20Sopenharmony_ci		struct jffs2_inode_cache *ic;
8058c2ecf20Sopenharmony_ci		struct jffs2_raw_node_ref **p;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci		spin_lock(&c->erase_completion_lock);
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci		ic = jffs2_raw_ref_to_ic(ref);
8108c2ecf20Sopenharmony_ci		for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
8118c2ecf20Sopenharmony_ci			;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci		*p = ref->next_in_ino;
8148c2ecf20Sopenharmony_ci		ref->next_in_ino = NULL;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci		switch (ic->class) {
8178c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_FS_XATTR
8188c2ecf20Sopenharmony_ci			case RAWNODE_CLASS_XATTR_DATUM:
8198c2ecf20Sopenharmony_ci				jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
8208c2ecf20Sopenharmony_ci				break;
8218c2ecf20Sopenharmony_ci			case RAWNODE_CLASS_XATTR_REF:
8228c2ecf20Sopenharmony_ci				jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
8238c2ecf20Sopenharmony_ci				break;
8248c2ecf20Sopenharmony_ci#endif
8258c2ecf20Sopenharmony_ci			default:
8268c2ecf20Sopenharmony_ci				if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
8278c2ecf20Sopenharmony_ci					jffs2_del_ino_cache(c, ic);
8288c2ecf20Sopenharmony_ci				break;
8298c2ecf20Sopenharmony_ci		}
8308c2ecf20Sopenharmony_ci		spin_unlock(&c->erase_completion_lock);
8318c2ecf20Sopenharmony_ci	}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci out_erase_sem:
8348c2ecf20Sopenharmony_ci	mutex_unlock(&c->erase_free_sem);
8358c2ecf20Sopenharmony_ci}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ciint jffs2_thread_should_wake(struct jffs2_sb_info *c)
8388c2ecf20Sopenharmony_ci{
8398c2ecf20Sopenharmony_ci	int ret = 0;
8408c2ecf20Sopenharmony_ci	uint32_t dirty;
8418c2ecf20Sopenharmony_ci	int nr_very_dirty = 0;
8428c2ecf20Sopenharmony_ci	struct jffs2_eraseblock *jeb;
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	if (!list_empty(&c->erase_complete_list) ||
8458c2ecf20Sopenharmony_ci	    !list_empty(&c->erase_pending_list))
8468c2ecf20Sopenharmony_ci		return 1;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	if (c->unchecked_size) {
8498c2ecf20Sopenharmony_ci		jffs2_dbg(1, "jffs2_thread_should_wake(): unchecked_size %d, check_ino #%d\n",
8508c2ecf20Sopenharmony_ci			  c->unchecked_size, c->check_ino);
8518c2ecf20Sopenharmony_ci		return 1;
8528c2ecf20Sopenharmony_ci	}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	/* dirty_size contains blocks on erase_pending_list
8558c2ecf20Sopenharmony_ci	 * those blocks are counted in c->nr_erasing_blocks.
8568c2ecf20Sopenharmony_ci	 * If one block is actually erased, it is not longer counted as dirty_space
8578c2ecf20Sopenharmony_ci	 * but it is counted in c->nr_erasing_blocks, so we add it and subtract it
8588c2ecf20Sopenharmony_ci	 * with c->nr_erasing_blocks * c->sector_size again.
8598c2ecf20Sopenharmony_ci	 * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks
8608c2ecf20Sopenharmony_ci	 * This helps us to force gc and pick eventually a clean block to spread the load.
8618c2ecf20Sopenharmony_ci	 */
8628c2ecf20Sopenharmony_ci	dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size;
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger &&
8658c2ecf20Sopenharmony_ci			(dirty > c->nospc_dirty_size))
8668c2ecf20Sopenharmony_ci		ret = 1;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	list_for_each_entry(jeb, &c->very_dirty_list, list) {
8698c2ecf20Sopenharmony_ci		nr_very_dirty++;
8708c2ecf20Sopenharmony_ci		if (nr_very_dirty == c->vdirty_blocks_gctrigger) {
8718c2ecf20Sopenharmony_ci			ret = 1;
8728c2ecf20Sopenharmony_ci			/* In debug mode, actually go through and count them all */
8738c2ecf20Sopenharmony_ci			D1(continue);
8748c2ecf20Sopenharmony_ci			break;
8758c2ecf20Sopenharmony_ci		}
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	jffs2_dbg(1, "%s(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x, vdirty_blocks %d: %s\n",
8798c2ecf20Sopenharmony_ci		  __func__, c->nr_free_blocks, c->nr_erasing_blocks,
8808c2ecf20Sopenharmony_ci		  c->dirty_size, nr_very_dirty, ret ? "yes" : "no");
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	return ret;
8838c2ecf20Sopenharmony_ci}
884