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/fs.h>
1662306a36Sopenharmony_ci#include <linux/crc32.h>
1762306a36Sopenharmony_ci#include <linux/pagemap.h>
1862306a36Sopenharmony_ci#include <linux/mtd/mtd.h>
1962306a36Sopenharmony_ci#include "nodelist.h"
2062306a36Sopenharmony_ci#include "compr.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ciint jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
2462306a36Sopenharmony_ci		       uint32_t mode, struct jffs2_raw_inode *ri)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	struct jffs2_inode_cache *ic;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	ic = jffs2_alloc_inode_cache();
2962306a36Sopenharmony_ci	if (!ic) {
3062306a36Sopenharmony_ci		return -ENOMEM;
3162306a36Sopenharmony_ci	}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	memset(ic, 0, sizeof(*ic));
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	f->inocache = ic;
3662306a36Sopenharmony_ci	f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
3762306a36Sopenharmony_ci	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
3862306a36Sopenharmony_ci	f->inocache->state = INO_STATE_PRESENT;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	jffs2_add_ino_cache(c, f->inocache);
4162306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): Assigned ino# %d\n", __func__, f->inocache->ino);
4262306a36Sopenharmony_ci	ri->ino = cpu_to_je32(f->inocache->ino);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
4562306a36Sopenharmony_ci	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
4662306a36Sopenharmony_ci	ri->totlen = cpu_to_je32(PAD(sizeof(*ri)));
4762306a36Sopenharmony_ci	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
4862306a36Sopenharmony_ci	ri->mode = cpu_to_jemode(mode);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	f->highest_version = 1;
5162306a36Sopenharmony_ci	ri->version = cpu_to_je32(f->highest_version);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	return 0;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it,
5762306a36Sopenharmony_ci   write it to the flash, link it into the existing inode/fragment list */
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistruct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
6062306a36Sopenharmony_ci					   struct jffs2_raw_inode *ri, const unsigned char *data,
6162306a36Sopenharmony_ci					   uint32_t datalen, int alloc_mode)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	struct jffs2_full_dnode *fn;
6562306a36Sopenharmony_ci	size_t retlen;
6662306a36Sopenharmony_ci	uint32_t flash_ofs;
6762306a36Sopenharmony_ci	struct kvec vecs[2];
6862306a36Sopenharmony_ci	int ret;
6962306a36Sopenharmony_ci	int retried = 0;
7062306a36Sopenharmony_ci	unsigned long cnt = 2;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) {
7362306a36Sopenharmony_ci		pr_crit("Eep. CRC not correct in jffs2_write_dnode()\n");
7462306a36Sopenharmony_ci		BUG();
7562306a36Sopenharmony_ci	}
7662306a36Sopenharmony_ci	   );
7762306a36Sopenharmony_ci	vecs[0].iov_base = ri;
7862306a36Sopenharmony_ci	vecs[0].iov_len = sizeof(*ri);
7962306a36Sopenharmony_ci	vecs[1].iov_base = (unsigned char *)data;
8062306a36Sopenharmony_ci	vecs[1].iov_len = datalen;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
8362306a36Sopenharmony_ci		pr_warn("%s(): ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n",
8462306a36Sopenharmony_ci			__func__, je32_to_cpu(ri->totlen),
8562306a36Sopenharmony_ci			sizeof(*ri), datalen);
8662306a36Sopenharmony_ci	}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	fn = jffs2_alloc_full_dnode();
8962306a36Sopenharmony_ci	if (!fn)
9062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	/* check number of valid vecs */
9362306a36Sopenharmony_ci	if (!datalen || !data)
9462306a36Sopenharmony_ci		cnt = 1;
9562306a36Sopenharmony_ci retry:
9662306a36Sopenharmony_ci	flash_ofs = write_ofs(c);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) {
10162306a36Sopenharmony_ci		BUG_ON(!retried);
10262306a36Sopenharmony_ci		jffs2_dbg(1, "%s(): dnode_version %d, highest version %d -> updating dnode\n",
10362306a36Sopenharmony_ci			  __func__,
10462306a36Sopenharmony_ci			  je32_to_cpu(ri->version), f->highest_version);
10562306a36Sopenharmony_ci		ri->version = cpu_to_je32(++f->highest_version);
10662306a36Sopenharmony_ci		ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
10762306a36Sopenharmony_ci	}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen,
11062306a36Sopenharmony_ci				 (alloc_mode==ALLOC_GC)?0:f->inocache->ino);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	if (ret || (retlen != sizeof(*ri) + datalen)) {
11362306a36Sopenharmony_ci		pr_notice("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
11462306a36Sopenharmony_ci			  sizeof(*ri) + datalen, flash_ofs, ret, retlen);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci		/* Mark the space as dirtied */
11762306a36Sopenharmony_ci		if (retlen) {
11862306a36Sopenharmony_ci			/* Don't change raw->size to match retlen. We may have
11962306a36Sopenharmony_ci			   written the node header already, and only the data will
12062306a36Sopenharmony_ci			   seem corrupted, in which case the scan would skip over
12162306a36Sopenharmony_ci			   any node we write before the original intended end of
12262306a36Sopenharmony_ci			   this node */
12362306a36Sopenharmony_ci			jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL);
12462306a36Sopenharmony_ci		} else {
12562306a36Sopenharmony_ci			pr_notice("Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n",
12662306a36Sopenharmony_ci				  flash_ofs);
12762306a36Sopenharmony_ci		}
12862306a36Sopenharmony_ci		if (!retried && alloc_mode != ALLOC_NORETRY) {
12962306a36Sopenharmony_ci			/* Try to reallocate space and retry */
13062306a36Sopenharmony_ci			uint32_t dummy;
13162306a36Sopenharmony_ci			struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci			retried = 1;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci			jffs2_dbg(1, "Retrying failed write.\n");
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci			jffs2_dbg_acct_sanity_check(c,jeb);
13862306a36Sopenharmony_ci			jffs2_dbg_acct_paranoia_check(c, jeb);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci			if (alloc_mode == ALLOC_GC) {
14162306a36Sopenharmony_ci				ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &dummy,
14262306a36Sopenharmony_ci							     JFFS2_SUMMARY_INODE_SIZE);
14362306a36Sopenharmony_ci			} else {
14462306a36Sopenharmony_ci				/* Locking pain */
14562306a36Sopenharmony_ci				mutex_unlock(&f->sem);
14662306a36Sopenharmony_ci				jffs2_complete_reservation(c);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci				ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
14962306a36Sopenharmony_ci							  alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
15062306a36Sopenharmony_ci				mutex_lock(&f->sem);
15162306a36Sopenharmony_ci			}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci			if (!ret) {
15462306a36Sopenharmony_ci				flash_ofs = write_ofs(c);
15562306a36Sopenharmony_ci				jffs2_dbg(1, "Allocated space at 0x%08x to retry failed write.\n",
15662306a36Sopenharmony_ci					  flash_ofs);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci				jffs2_dbg_acct_sanity_check(c,jeb);
15962306a36Sopenharmony_ci				jffs2_dbg_acct_paranoia_check(c, jeb);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci				goto retry;
16262306a36Sopenharmony_ci			}
16362306a36Sopenharmony_ci			jffs2_dbg(1, "Failed to allocate space to retry failed write: %d!\n",
16462306a36Sopenharmony_ci				  ret);
16562306a36Sopenharmony_ci		}
16662306a36Sopenharmony_ci		/* Release the full_dnode which is now useless, and return */
16762306a36Sopenharmony_ci		jffs2_free_full_dnode(fn);
16862306a36Sopenharmony_ci		return ERR_PTR(ret?ret:-EIO);
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci	/* Mark the space used */
17162306a36Sopenharmony_ci	/* If node covers at least a whole page, or if it starts at the
17262306a36Sopenharmony_ci	   beginning of a page and runs to the end of the file, or if
17362306a36Sopenharmony_ci	   it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
17462306a36Sopenharmony_ci	*/
17562306a36Sopenharmony_ci	if ((je32_to_cpu(ri->dsize) >= PAGE_SIZE) ||
17662306a36Sopenharmony_ci	    ( ((je32_to_cpu(ri->offset)&(PAGE_SIZE-1))==0) &&
17762306a36Sopenharmony_ci	      (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) ==  je32_to_cpu(ri->isize)))) {
17862306a36Sopenharmony_ci		flash_ofs |= REF_PRISTINE;
17962306a36Sopenharmony_ci	} else {
18062306a36Sopenharmony_ci		flash_ofs |= REF_NORMAL;
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci	fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache);
18362306a36Sopenharmony_ci	if (IS_ERR(fn->raw)) {
18462306a36Sopenharmony_ci		void *hold_err = fn->raw;
18562306a36Sopenharmony_ci		/* Release the full_dnode which is now useless, and return */
18662306a36Sopenharmony_ci		jffs2_free_full_dnode(fn);
18762306a36Sopenharmony_ci		return ERR_CAST(hold_err);
18862306a36Sopenharmony_ci	}
18962306a36Sopenharmony_ci	fn->ofs = je32_to_cpu(ri->offset);
19062306a36Sopenharmony_ci	fn->size = je32_to_cpu(ri->dsize);
19162306a36Sopenharmony_ci	fn->frags = 0;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	jffs2_dbg(1, "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n",
19462306a36Sopenharmony_ci		  flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize),
19562306a36Sopenharmony_ci		  je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
19662306a36Sopenharmony_ci		  je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen));
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	if (retried) {
19962306a36Sopenharmony_ci		jffs2_dbg_acct_sanity_check(c,NULL);
20062306a36Sopenharmony_ci	}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	return fn;
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistruct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
20662306a36Sopenharmony_ci					     struct jffs2_raw_dirent *rd, const unsigned char *name,
20762306a36Sopenharmony_ci					     uint32_t namelen, int alloc_mode)
20862306a36Sopenharmony_ci{
20962306a36Sopenharmony_ci	struct jffs2_full_dirent *fd;
21062306a36Sopenharmony_ci	size_t retlen;
21162306a36Sopenharmony_ci	struct kvec vecs[2];
21262306a36Sopenharmony_ci	uint32_t flash_ofs;
21362306a36Sopenharmony_ci	int retried = 0;
21462306a36Sopenharmony_ci	int ret;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	jffs2_dbg(1, "%s(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n",
21762306a36Sopenharmony_ci		  __func__,
21862306a36Sopenharmony_ci		  je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino),
21962306a36Sopenharmony_ci		  je32_to_cpu(rd->name_crc));
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
22262306a36Sopenharmony_ci		pr_crit("Eep. CRC not correct in jffs2_write_dirent()\n");
22362306a36Sopenharmony_ci		BUG();
22462306a36Sopenharmony_ci	   });
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	if (strnlen(name, namelen) != namelen) {
22762306a36Sopenharmony_ci		/* This should never happen, but seems to have done on at least one
22862306a36Sopenharmony_ci		   occasion: https://dev.laptop.org/ticket/4184 */
22962306a36Sopenharmony_ci		pr_crit("Error in jffs2_write_dirent() -- name contains zero bytes!\n");
23062306a36Sopenharmony_ci		pr_crit("Directory inode #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x\n",
23162306a36Sopenharmony_ci			je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino),
23262306a36Sopenharmony_ci			je32_to_cpu(rd->name_crc));
23362306a36Sopenharmony_ci		WARN_ON(1);
23462306a36Sopenharmony_ci		return ERR_PTR(-EIO);
23562306a36Sopenharmony_ci	}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	vecs[0].iov_base = rd;
23862306a36Sopenharmony_ci	vecs[0].iov_len = sizeof(*rd);
23962306a36Sopenharmony_ci	vecs[1].iov_base = (unsigned char *)name;
24062306a36Sopenharmony_ci	vecs[1].iov_len = namelen;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	fd = jffs2_alloc_full_dirent(namelen+1);
24362306a36Sopenharmony_ci	if (!fd)
24462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	fd->version = je32_to_cpu(rd->version);
24762306a36Sopenharmony_ci	fd->ino = je32_to_cpu(rd->ino);
24862306a36Sopenharmony_ci	fd->nhash = full_name_hash(NULL, name, namelen);
24962306a36Sopenharmony_ci	fd->type = rd->type;
25062306a36Sopenharmony_ci	memcpy(fd->name, name, namelen);
25162306a36Sopenharmony_ci	fd->name[namelen]=0;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci retry:
25462306a36Sopenharmony_ci	flash_ofs = write_ofs(c);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {
25962306a36Sopenharmony_ci		BUG_ON(!retried);
26062306a36Sopenharmony_ci		jffs2_dbg(1, "%s(): dirent_version %d, highest version %d -> updating dirent\n",
26162306a36Sopenharmony_ci			  __func__,
26262306a36Sopenharmony_ci			  je32_to_cpu(rd->version), f->highest_version);
26362306a36Sopenharmony_ci		rd->version = cpu_to_je32(++f->highest_version);
26462306a36Sopenharmony_ci		fd->version = je32_to_cpu(rd->version);
26562306a36Sopenharmony_ci		rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen,
26962306a36Sopenharmony_ci				 (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino));
27062306a36Sopenharmony_ci	if (ret || (retlen != sizeof(*rd) + namelen)) {
27162306a36Sopenharmony_ci		pr_notice("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
27262306a36Sopenharmony_ci			  sizeof(*rd) + namelen, flash_ofs, ret, retlen);
27362306a36Sopenharmony_ci		/* Mark the space as dirtied */
27462306a36Sopenharmony_ci		if (retlen) {
27562306a36Sopenharmony_ci			jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL);
27662306a36Sopenharmony_ci		} else {
27762306a36Sopenharmony_ci			pr_notice("Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n",
27862306a36Sopenharmony_ci				  flash_ofs);
27962306a36Sopenharmony_ci		}
28062306a36Sopenharmony_ci		if (!retried) {
28162306a36Sopenharmony_ci			/* Try to reallocate space and retry */
28262306a36Sopenharmony_ci			uint32_t dummy;
28362306a36Sopenharmony_ci			struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci			retried = 1;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci			jffs2_dbg(1, "Retrying failed write.\n");
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci			jffs2_dbg_acct_sanity_check(c,jeb);
29062306a36Sopenharmony_ci			jffs2_dbg_acct_paranoia_check(c, jeb);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci			if (alloc_mode == ALLOC_GC) {
29362306a36Sopenharmony_ci				ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &dummy,
29462306a36Sopenharmony_ci							     JFFS2_SUMMARY_DIRENT_SIZE(namelen));
29562306a36Sopenharmony_ci			} else {
29662306a36Sopenharmony_ci				/* Locking pain */
29762306a36Sopenharmony_ci				mutex_unlock(&f->sem);
29862306a36Sopenharmony_ci				jffs2_complete_reservation(c);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci				ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
30162306a36Sopenharmony_ci							  alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
30262306a36Sopenharmony_ci				mutex_lock(&f->sem);
30362306a36Sopenharmony_ci			}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci			if (!ret) {
30662306a36Sopenharmony_ci				flash_ofs = write_ofs(c);
30762306a36Sopenharmony_ci				jffs2_dbg(1, "Allocated space at 0x%08x to retry failed write\n",
30862306a36Sopenharmony_ci					  flash_ofs);
30962306a36Sopenharmony_ci				jffs2_dbg_acct_sanity_check(c,jeb);
31062306a36Sopenharmony_ci				jffs2_dbg_acct_paranoia_check(c, jeb);
31162306a36Sopenharmony_ci				goto retry;
31262306a36Sopenharmony_ci			}
31362306a36Sopenharmony_ci			jffs2_dbg(1, "Failed to allocate space to retry failed write: %d!\n",
31462306a36Sopenharmony_ci				  ret);
31562306a36Sopenharmony_ci		}
31662306a36Sopenharmony_ci		/* Release the full_dnode which is now useless, and return */
31762306a36Sopenharmony_ci		jffs2_free_full_dirent(fd);
31862306a36Sopenharmony_ci		return ERR_PTR(ret?ret:-EIO);
31962306a36Sopenharmony_ci	}
32062306a36Sopenharmony_ci	/* Mark the space used */
32162306a36Sopenharmony_ci	fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | dirent_node_state(rd),
32262306a36Sopenharmony_ci					      PAD(sizeof(*rd)+namelen), f->inocache);
32362306a36Sopenharmony_ci	if (IS_ERR(fd->raw)) {
32462306a36Sopenharmony_ci		void *hold_err = fd->raw;
32562306a36Sopenharmony_ci		/* Release the full_dirent which is now useless, and return */
32662306a36Sopenharmony_ci		jffs2_free_full_dirent(fd);
32762306a36Sopenharmony_ci		return ERR_CAST(hold_err);
32862306a36Sopenharmony_ci	}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	if (retried) {
33162306a36Sopenharmony_ci		jffs2_dbg_acct_sanity_check(c,NULL);
33262306a36Sopenharmony_ci	}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	return fd;
33562306a36Sopenharmony_ci}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci/* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that
33862306a36Sopenharmony_ci   we don't have to go digging in struct inode or its equivalent. It should set:
33962306a36Sopenharmony_ci   mode, uid, gid, (starting)isize, atime, ctime, mtime */
34062306a36Sopenharmony_ciint jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
34162306a36Sopenharmony_ci			    struct jffs2_raw_inode *ri, unsigned char *buf,
34262306a36Sopenharmony_ci			    uint32_t offset, uint32_t writelen, uint32_t *retlen)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	int ret = 0;
34562306a36Sopenharmony_ci	uint32_t writtenlen = 0;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): Ino #%u, ofs 0x%x, len 0x%x\n",
34862306a36Sopenharmony_ci		  __func__, f->inocache->ino, offset, writelen);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	while(writelen) {
35162306a36Sopenharmony_ci		struct jffs2_full_dnode *fn;
35262306a36Sopenharmony_ci		unsigned char *comprbuf = NULL;
35362306a36Sopenharmony_ci		uint16_t comprtype = JFFS2_COMPR_NONE;
35462306a36Sopenharmony_ci		uint32_t alloclen;
35562306a36Sopenharmony_ci		uint32_t datalen, cdatalen;
35662306a36Sopenharmony_ci		int retried = 0;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	retry:
35962306a36Sopenharmony_ci		jffs2_dbg(2, "jffs2_commit_write() loop: 0x%x to write to 0x%x\n",
36062306a36Sopenharmony_ci			  writelen, offset);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci		ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN,
36362306a36Sopenharmony_ci					&alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
36462306a36Sopenharmony_ci		if (ret) {
36562306a36Sopenharmony_ci			jffs2_dbg(1, "jffs2_reserve_space returned %d\n", ret);
36662306a36Sopenharmony_ci			break;
36762306a36Sopenharmony_ci		}
36862306a36Sopenharmony_ci		mutex_lock(&f->sem);
36962306a36Sopenharmony_ci		datalen = min_t(uint32_t, writelen,
37062306a36Sopenharmony_ci				PAGE_SIZE - (offset & (PAGE_SIZE-1)));
37162306a36Sopenharmony_ci		cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci		comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen);
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci		ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
37662306a36Sopenharmony_ci		ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
37762306a36Sopenharmony_ci		ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen);
37862306a36Sopenharmony_ci		ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci		ri->ino = cpu_to_je32(f->inocache->ino);
38162306a36Sopenharmony_ci		ri->version = cpu_to_je32(++f->highest_version);
38262306a36Sopenharmony_ci		ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen));
38362306a36Sopenharmony_ci		ri->offset = cpu_to_je32(offset);
38462306a36Sopenharmony_ci		ri->csize = cpu_to_je32(cdatalen);
38562306a36Sopenharmony_ci		ri->dsize = cpu_to_je32(datalen);
38662306a36Sopenharmony_ci		ri->compr = comprtype & 0xff;
38762306a36Sopenharmony_ci		ri->usercompr = (comprtype >> 8 ) & 0xff;
38862306a36Sopenharmony_ci		ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
38962306a36Sopenharmony_ci		ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci		fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci		jffs2_free_comprbuf(comprbuf, buf);
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci		if (IS_ERR(fn)) {
39662306a36Sopenharmony_ci			ret = PTR_ERR(fn);
39762306a36Sopenharmony_ci			mutex_unlock(&f->sem);
39862306a36Sopenharmony_ci			jffs2_complete_reservation(c);
39962306a36Sopenharmony_ci			if (!retried) {
40062306a36Sopenharmony_ci				/* Write error to be retried */
40162306a36Sopenharmony_ci				retried = 1;
40262306a36Sopenharmony_ci				jffs2_dbg(1, "Retrying node write in jffs2_write_inode_range()\n");
40362306a36Sopenharmony_ci				goto retry;
40462306a36Sopenharmony_ci			}
40562306a36Sopenharmony_ci			break;
40662306a36Sopenharmony_ci		}
40762306a36Sopenharmony_ci		ret = jffs2_add_full_dnode_to_inode(c, f, fn);
40862306a36Sopenharmony_ci		if (f->metadata) {
40962306a36Sopenharmony_ci			jffs2_mark_node_obsolete(c, f->metadata->raw);
41062306a36Sopenharmony_ci			jffs2_free_full_dnode(f->metadata);
41162306a36Sopenharmony_ci			f->metadata = NULL;
41262306a36Sopenharmony_ci		}
41362306a36Sopenharmony_ci		if (ret) {
41462306a36Sopenharmony_ci			/* Eep */
41562306a36Sopenharmony_ci			jffs2_dbg(1, "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n",
41662306a36Sopenharmony_ci				  ret);
41762306a36Sopenharmony_ci			jffs2_mark_node_obsolete(c, fn->raw);
41862306a36Sopenharmony_ci			jffs2_free_full_dnode(fn);
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci			mutex_unlock(&f->sem);
42162306a36Sopenharmony_ci			jffs2_complete_reservation(c);
42262306a36Sopenharmony_ci			break;
42362306a36Sopenharmony_ci		}
42462306a36Sopenharmony_ci		mutex_unlock(&f->sem);
42562306a36Sopenharmony_ci		jffs2_complete_reservation(c);
42662306a36Sopenharmony_ci		if (!datalen) {
42762306a36Sopenharmony_ci			pr_warn("Eep. We didn't actually write any data in jffs2_write_inode_range()\n");
42862306a36Sopenharmony_ci			ret = -EIO;
42962306a36Sopenharmony_ci			break;
43062306a36Sopenharmony_ci		}
43162306a36Sopenharmony_ci		jffs2_dbg(1, "increasing writtenlen by %d\n", datalen);
43262306a36Sopenharmony_ci		writtenlen += datalen;
43362306a36Sopenharmony_ci		offset += datalen;
43462306a36Sopenharmony_ci		writelen -= datalen;
43562306a36Sopenharmony_ci		buf += datalen;
43662306a36Sopenharmony_ci	}
43762306a36Sopenharmony_ci	*retlen = writtenlen;
43862306a36Sopenharmony_ci	return ret;
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ciint jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
44262306a36Sopenharmony_ci		    struct jffs2_inode_info *f, struct jffs2_raw_inode *ri,
44362306a36Sopenharmony_ci		    const struct qstr *qstr)
44462306a36Sopenharmony_ci{
44562306a36Sopenharmony_ci	struct jffs2_raw_dirent *rd;
44662306a36Sopenharmony_ci	struct jffs2_full_dnode *fn;
44762306a36Sopenharmony_ci	struct jffs2_full_dirent *fd;
44862306a36Sopenharmony_ci	uint32_t alloclen;
44962306a36Sopenharmony_ci	int ret;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	/* Try to reserve enough space for both node and dirent.
45262306a36Sopenharmony_ci	 * Just the node will do for now, though
45362306a36Sopenharmony_ci	 */
45462306a36Sopenharmony_ci	ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
45562306a36Sopenharmony_ci				JFFS2_SUMMARY_INODE_SIZE);
45662306a36Sopenharmony_ci	jffs2_dbg(1, "%s(): reserved 0x%x bytes\n", __func__, alloclen);
45762306a36Sopenharmony_ci	if (ret)
45862306a36Sopenharmony_ci		return ret;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	mutex_lock(&f->sem);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	ri->data_crc = cpu_to_je32(0);
46362306a36Sopenharmony_ci	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	jffs2_dbg(1, "jffs2_do_create created file with mode 0x%x\n",
46862306a36Sopenharmony_ci		  jemode_to_cpu(ri->mode));
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	if (IS_ERR(fn)) {
47162306a36Sopenharmony_ci		jffs2_dbg(1, "jffs2_write_dnode() failed\n");
47262306a36Sopenharmony_ci		/* Eeek. Wave bye bye */
47362306a36Sopenharmony_ci		mutex_unlock(&f->sem);
47462306a36Sopenharmony_ci		jffs2_complete_reservation(c);
47562306a36Sopenharmony_ci		return PTR_ERR(fn);
47662306a36Sopenharmony_ci	}
47762306a36Sopenharmony_ci	/* No data here. Only a metadata node, which will be
47862306a36Sopenharmony_ci	   obsoleted by the first data write
47962306a36Sopenharmony_ci	*/
48062306a36Sopenharmony_ci	f->metadata = fn;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	mutex_unlock(&f->sem);
48362306a36Sopenharmony_ci	jffs2_complete_reservation(c);
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode, qstr);
48662306a36Sopenharmony_ci	if (ret)
48762306a36Sopenharmony_ci		return ret;
48862306a36Sopenharmony_ci	ret = jffs2_init_acl_post(&f->vfs_inode);
48962306a36Sopenharmony_ci	if (ret)
49062306a36Sopenharmony_ci		return ret;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	ret = jffs2_reserve_space(c, sizeof(*rd)+qstr->len, &alloclen,
49362306a36Sopenharmony_ci				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(qstr->len));
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	if (ret) {
49662306a36Sopenharmony_ci		/* Eep. */
49762306a36Sopenharmony_ci		jffs2_dbg(1, "jffs2_reserve_space() for dirent failed\n");
49862306a36Sopenharmony_ci		return ret;
49962306a36Sopenharmony_ci	}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	rd = jffs2_alloc_raw_dirent();
50262306a36Sopenharmony_ci	if (!rd) {
50362306a36Sopenharmony_ci		/* Argh. Now we treat it like a normal delete */
50462306a36Sopenharmony_ci		jffs2_complete_reservation(c);
50562306a36Sopenharmony_ci		return -ENOMEM;
50662306a36Sopenharmony_ci	}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	mutex_lock(&dir_f->sem);
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
51162306a36Sopenharmony_ci	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
51262306a36Sopenharmony_ci	rd->totlen = cpu_to_je32(sizeof(*rd) + qstr->len);
51362306a36Sopenharmony_ci	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	rd->pino = cpu_to_je32(dir_f->inocache->ino);
51662306a36Sopenharmony_ci	rd->version = cpu_to_je32(++dir_f->highest_version);
51762306a36Sopenharmony_ci	rd->ino = ri->ino;
51862306a36Sopenharmony_ci	rd->mctime = ri->ctime;
51962306a36Sopenharmony_ci	rd->nsize = qstr->len;
52062306a36Sopenharmony_ci	rd->type = DT_REG;
52162306a36Sopenharmony_ci	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
52262306a36Sopenharmony_ci	rd->name_crc = cpu_to_je32(crc32(0, qstr->name, qstr->len));
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	fd = jffs2_write_dirent(c, dir_f, rd, qstr->name, qstr->len, ALLOC_NORMAL);
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	jffs2_free_raw_dirent(rd);
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	if (IS_ERR(fd)) {
52962306a36Sopenharmony_ci		/* dirent failed to write. Delete the inode normally
53062306a36Sopenharmony_ci		   as if it were the final unlink() */
53162306a36Sopenharmony_ci		jffs2_complete_reservation(c);
53262306a36Sopenharmony_ci		mutex_unlock(&dir_f->sem);
53362306a36Sopenharmony_ci		return PTR_ERR(fd);
53462306a36Sopenharmony_ci	}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	/* Link the fd into the inode's list, obsoleting an old
53762306a36Sopenharmony_ci	   one if necessary. */
53862306a36Sopenharmony_ci	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	jffs2_complete_reservation(c);
54162306a36Sopenharmony_ci	mutex_unlock(&dir_f->sem);
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	return 0;
54462306a36Sopenharmony_ci}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ciint jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
54862306a36Sopenharmony_ci		    const char *name, int namelen, struct jffs2_inode_info *dead_f,
54962306a36Sopenharmony_ci		    uint32_t time)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	struct jffs2_raw_dirent *rd;
55262306a36Sopenharmony_ci	struct jffs2_full_dirent *fd;
55362306a36Sopenharmony_ci	uint32_t alloclen;
55462306a36Sopenharmony_ci	int ret;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	if (!jffs2_can_mark_obsolete(c)) {
55762306a36Sopenharmony_ci		/* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci		rd = jffs2_alloc_raw_dirent();
56062306a36Sopenharmony_ci		if (!rd)
56162306a36Sopenharmony_ci			return -ENOMEM;
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci		ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
56462306a36Sopenharmony_ci					ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
56562306a36Sopenharmony_ci		if (ret) {
56662306a36Sopenharmony_ci			jffs2_free_raw_dirent(rd);
56762306a36Sopenharmony_ci			return ret;
56862306a36Sopenharmony_ci		}
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci		mutex_lock(&dir_f->sem);
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci		/* Build a deletion node */
57362306a36Sopenharmony_ci		rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
57462306a36Sopenharmony_ci		rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
57562306a36Sopenharmony_ci		rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
57662306a36Sopenharmony_ci		rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci		rd->pino = cpu_to_je32(dir_f->inocache->ino);
57962306a36Sopenharmony_ci		rd->version = cpu_to_je32(++dir_f->highest_version);
58062306a36Sopenharmony_ci		rd->ino = cpu_to_je32(0);
58162306a36Sopenharmony_ci		rd->mctime = cpu_to_je32(time);
58262306a36Sopenharmony_ci		rd->nsize = namelen;
58362306a36Sopenharmony_ci		rd->type = DT_UNKNOWN;
58462306a36Sopenharmony_ci		rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
58562306a36Sopenharmony_ci		rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci		fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_DELETION);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci		jffs2_free_raw_dirent(rd);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci		if (IS_ERR(fd)) {
59262306a36Sopenharmony_ci			jffs2_complete_reservation(c);
59362306a36Sopenharmony_ci			mutex_unlock(&dir_f->sem);
59462306a36Sopenharmony_ci			return PTR_ERR(fd);
59562306a36Sopenharmony_ci		}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci		/* File it. This will mark the old one obsolete. */
59862306a36Sopenharmony_ci		jffs2_add_fd_to_list(c, fd, &dir_f->dents);
59962306a36Sopenharmony_ci		mutex_unlock(&dir_f->sem);
60062306a36Sopenharmony_ci	} else {
60162306a36Sopenharmony_ci		uint32_t nhash = full_name_hash(NULL, name, namelen);
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci		fd = dir_f->dents;
60462306a36Sopenharmony_ci		/* We don't actually want to reserve any space, but we do
60562306a36Sopenharmony_ci		   want to be holding the alloc_sem when we write to flash */
60662306a36Sopenharmony_ci		mutex_lock(&c->alloc_sem);
60762306a36Sopenharmony_ci		mutex_lock(&dir_f->sem);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci		for (fd = dir_f->dents; fd; fd = fd->next) {
61062306a36Sopenharmony_ci			if (fd->nhash == nhash &&
61162306a36Sopenharmony_ci			    !memcmp(fd->name, name, namelen) &&
61262306a36Sopenharmony_ci			    !fd->name[namelen]) {
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci				jffs2_dbg(1, "Marking old dirent node (ino #%u) @%08x obsolete\n",
61562306a36Sopenharmony_ci					  fd->ino, ref_offset(fd->raw));
61662306a36Sopenharmony_ci				jffs2_mark_node_obsolete(c, fd->raw);
61762306a36Sopenharmony_ci				/* We don't want to remove it from the list immediately,
61862306a36Sopenharmony_ci				   because that screws up getdents()/seek() semantics even
61962306a36Sopenharmony_ci				   more than they're screwed already. Turn it into a
62062306a36Sopenharmony_ci				   node-less deletion dirent instead -- a placeholder */
62162306a36Sopenharmony_ci				fd->raw = NULL;
62262306a36Sopenharmony_ci				fd->ino = 0;
62362306a36Sopenharmony_ci				break;
62462306a36Sopenharmony_ci			}
62562306a36Sopenharmony_ci		}
62662306a36Sopenharmony_ci		mutex_unlock(&dir_f->sem);
62762306a36Sopenharmony_ci	}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	/* dead_f is NULL if this was a rename not a real unlink */
63062306a36Sopenharmony_ci	/* Also catch the !f->inocache case, where there was a dirent
63162306a36Sopenharmony_ci	   pointing to an inode which didn't exist. */
63262306a36Sopenharmony_ci	if (dead_f && dead_f->inocache) {
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci		mutex_lock(&dead_f->sem);
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci		if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {
63762306a36Sopenharmony_ci			while (dead_f->dents) {
63862306a36Sopenharmony_ci				/* There can be only deleted ones */
63962306a36Sopenharmony_ci				fd = dead_f->dents;
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci				dead_f->dents = fd->next;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci				if (fd->ino) {
64462306a36Sopenharmony_ci					pr_warn("Deleting inode #%u with active dentry \"%s\"->ino #%u\n",
64562306a36Sopenharmony_ci						dead_f->inocache->ino,
64662306a36Sopenharmony_ci						fd->name, fd->ino);
64762306a36Sopenharmony_ci				} else {
64862306a36Sopenharmony_ci					jffs2_dbg(1, "Removing deletion dirent for \"%s\" from dir ino #%u\n",
64962306a36Sopenharmony_ci						  fd->name,
65062306a36Sopenharmony_ci						  dead_f->inocache->ino);
65162306a36Sopenharmony_ci				}
65262306a36Sopenharmony_ci				if (fd->raw)
65362306a36Sopenharmony_ci					jffs2_mark_node_obsolete(c, fd->raw);
65462306a36Sopenharmony_ci				jffs2_free_full_dirent(fd);
65562306a36Sopenharmony_ci			}
65662306a36Sopenharmony_ci			dead_f->inocache->pino_nlink = 0;
65762306a36Sopenharmony_ci		} else
65862306a36Sopenharmony_ci			dead_f->inocache->pino_nlink--;
65962306a36Sopenharmony_ci		/* NB: Caller must set inode nlink if appropriate */
66062306a36Sopenharmony_ci		mutex_unlock(&dead_f->sem);
66162306a36Sopenharmony_ci	}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	jffs2_complete_reservation(c);
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	return 0;
66662306a36Sopenharmony_ci}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ciint jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time)
67062306a36Sopenharmony_ci{
67162306a36Sopenharmony_ci	struct jffs2_raw_dirent *rd;
67262306a36Sopenharmony_ci	struct jffs2_full_dirent *fd;
67362306a36Sopenharmony_ci	uint32_t alloclen;
67462306a36Sopenharmony_ci	int ret;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	rd = jffs2_alloc_raw_dirent();
67762306a36Sopenharmony_ci	if (!rd)
67862306a36Sopenharmony_ci		return -ENOMEM;
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
68162306a36Sopenharmony_ci				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
68262306a36Sopenharmony_ci	if (ret) {
68362306a36Sopenharmony_ci		jffs2_free_raw_dirent(rd);
68462306a36Sopenharmony_ci		return ret;
68562306a36Sopenharmony_ci	}
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	mutex_lock(&dir_f->sem);
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	/* Build a deletion node */
69062306a36Sopenharmony_ci	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
69162306a36Sopenharmony_ci	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
69262306a36Sopenharmony_ci	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
69362306a36Sopenharmony_ci	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	rd->pino = cpu_to_je32(dir_f->inocache->ino);
69662306a36Sopenharmony_ci	rd->version = cpu_to_je32(++dir_f->highest_version);
69762306a36Sopenharmony_ci	rd->ino = cpu_to_je32(ino);
69862306a36Sopenharmony_ci	rd->mctime = cpu_to_je32(time);
69962306a36Sopenharmony_ci	rd->nsize = namelen;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	rd->type = type;
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
70462306a36Sopenharmony_ci	rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	jffs2_free_raw_dirent(rd);
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	if (IS_ERR(fd)) {
71162306a36Sopenharmony_ci		jffs2_complete_reservation(c);
71262306a36Sopenharmony_ci		mutex_unlock(&dir_f->sem);
71362306a36Sopenharmony_ci		return PTR_ERR(fd);
71462306a36Sopenharmony_ci	}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	/* File it. This will mark the old one obsolete. */
71762306a36Sopenharmony_ci	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	jffs2_complete_reservation(c);
72062306a36Sopenharmony_ci	mutex_unlock(&dir_f->sem);
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	return 0;
72362306a36Sopenharmony_ci}
724