From aa98d7cf59b5b0764d3502662053489585faf2fe Mon Sep 17 00:00:00 2001 From: KaiGai Kohei Date: Sat, 13 May 2006 15:09:47 +0900 Subject: [JFFS2][XATTR] XATTR support on JFFS2 (version. 5) This attached patches provide xattr support including POSIX-ACL and SELinux support on JFFS2 (version.5). There are some significant differences from previous version posted at last December. The biggest change is addition of EBS(Erase Block Summary) support. Currently, both kernel and usermode utility (sumtool) can recognize xattr nodes which have JFFS2_NODETYPE_XATTR/_XREF nodetype. In addition, some bugs are fixed. - A potential race condition was fixed. - Unexpected fail when updating a xattr by same name/value pair was fixed. - A bug when removing xattr name/value pair was fixed. The fundamental structures (such as using two new nodetypes and exclusion mechanism by rwsem) are unchanged. But most of implementation were reviewed and updated if necessary. Espacially, we had to change several internal implementations related to load_xattr_datum() to avoid a potential race condition. [1/2] xattr_on_jffs2.kernel.version-5.patch [2/2] xattr_on_jffs2.utils.version-5.patch Signed-off-by: KaiGai Kohei Signed-off-by: David Woodhouse --- fs/jffs2/xattr.c | 1271 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1271 insertions(+) create mode 100644 fs/jffs2/xattr.c (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c new file mode 100644 index 000000000000..c9a185c54ce7 --- /dev/null +++ b/fs/jffs2/xattr.c @@ -0,0 +1,1271 @@ +/* ------------------------------------------------------------------------- + * File: fs/jffs2/xattr.c + * XATTR support on JFFS2 FileSystem + * + * Implemented by KaiGai Kohei + * Copyright (C) 2006 NEC Corporation + * + * For licensing information, see the file 'LICENCE' in the jffs2 directory. + * ------------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nodelist.h" +/* -------- xdatum related functions ---------------- + * xattr_datum_hashkey(xprefix, xname, xvalue, xsize) + * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is + * the index of the xattr name/value pair cache (c->xattrindex). + * unload_xattr_datum(c, xd) + * is used to release xattr name/value pair and detach from c->xattrindex. + * reclaim_xattr_datum(c) + * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when + * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold + * is hard coded as 32KiB. + * delete_xattr_datum_node(c, xd) + * is used to delete a jffs2 node is dominated by xdatum. When EBS(Erase Block Summary) is + * enabled, it overwrites the obsolete node by myself. + * delete_xattr_datum(c, xd) + * is used to delete jffs2_xattr_datum object. It must be called with 0-value of reference + * counter. (It means how many jffs2_xattr_ref object refers this xdatum.) + * do_verify_xattr_datum(c, xd) + * is used to load the xdatum informations without name/value pair from the medium. + * It's necessary once, because those informations are not collected during mounting + * process when EBS is enabled. + * 0 will be returned, if success. An negative return value means recoverable error, and + * positive return value means unrecoverable error. Thus, caller must remove this xdatum + * and xref when it returned positive value. + * do_load_xattr_datum(c, xd) + * is used to load name/value pair from the medium. + * The meanings of return value is same as do_verify_xattr_datum(). + * load_xattr_datum(c, xd) + * is used to be as a wrapper of do_verify_xattr_datum() and do_load_xattr_datum(). + * If xd need to call do_verify_xattr_datum() at first, it's called before calling + * do_load_xattr_datum(). The meanings of return value is same as do_verify_xattr_datum(). + * save_xattr_datum(c, xd, phys_ofs) + * is used to write xdatum to medium. xd->version will be incremented. + * create_xattr_datum(c, xprefix, xname, xvalue, xsize, phys_ofs) + * is used to create new xdatum and write to medium. + * -------------------------------------------------- */ + +static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) +{ + int name_len = strlen(xname); + + return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize); +} + +static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version)); + if (xd->xname) { + c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len); + kfree(xd->xname); + } + + list_del_init(&xd->xindex); + xd->hashkey = 0; + xd->xname = NULL; + xd->xvalue = NULL; +} + +static void reclaim_xattr_datum(struct jffs2_sb_info *c) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_xattr_datum *xd, *_xd; + uint32_t target, before; + static int index = 0; + int count; + + if (c->xdatum_mem_threshold > c->xdatum_mem_usage) + return; + + before = c->xdatum_mem_usage; + target = c->xdatum_mem_usage * 4 / 5; /* 20% reduction */ + for (count = 0; count < XATTRINDEX_HASHSIZE; count++) { + list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) { + if (xd->flags & JFFS2_XFLAGS_HOT) { + xd->flags &= ~JFFS2_XFLAGS_HOT; + } else if (!(xd->flags & JFFS2_XFLAGS_BIND)) { + unload_xattr_datum(c, xd); + } + if (c->xdatum_mem_usage <= target) + goto out; + } + index = (index+1) % XATTRINDEX_HASHSIZE; + } + out: + JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n", + before, c->xdatum_mem_usage, before - c->xdatum_mem_usage); +} + +static void delete_xattr_datum_node(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_raw_xattr rx; + uint32_t length; + int rc; + + if (!xd->node) { + JFFS2_WARNING("xdatum (xid=%u) is removed twice.\n", xd->xid); + return; + } + if (jffs2_sum_active()) { + memset(&rx, 0xff, sizeof(struct jffs2_raw_xattr)); + rc = jffs2_flash_read(c, ref_offset(xd->node), + sizeof(struct jffs2_unknown_node), + &length, (char *)&rx); + if (rc || length != sizeof(struct jffs2_unknown_node)) { + JFFS2_ERROR("jffs2_flash_read()=%d, req=%u, read=%u at %#08x\n", + rc, sizeof(struct jffs2_unknown_node), + length, ref_offset(xd->node)); + } + rc = jffs2_flash_write(c, ref_offset(xd->node), sizeof(rx), + &length, (char *)&rx); + if (rc || length != sizeof(struct jffs2_raw_xattr)) { + JFFS2_ERROR("jffs2_flash_write()=%d, req=%u, wrote=%u ar %#08x\n", + rc, sizeof(rx), length, ref_offset(xd->node)); + } + } + spin_lock(&c->erase_completion_lock); + xd->node->next_in_ino = NULL; + spin_unlock(&c->erase_completion_lock); + jffs2_mark_node_obsolete(c, xd->node); + xd->node = NULL; +} + +static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + BUG_ON(xd->refcnt); + + unload_xattr_datum(c, xd); + if (xd->node) { + delete_xattr_datum_node(c, xd); + xd->node = NULL; + } + jffs2_free_xattr_datum(xd); +} + +static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_eraseblock *jeb; + struct jffs2_raw_xattr rx; + size_t readlen; + uint32_t crc, totlen; + int rc; + + BUG_ON(!xd->node); + BUG_ON(ref_flags(xd->node) != REF_UNCHECKED); + + rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx); + if (rc || readlen != sizeof(rx)) { + JFFS2_WARNING("jffs2_flash_read()=%d, req=%u, read=%u at %#08x\n", + rc, sizeof(rx), readlen, ref_offset(xd->node)); + return rc ? rc : -EIO; + } + crc = crc32(0, &rx, sizeof(rx) - 4); + if (crc != je32_to_cpu(rx.node_crc)) { + if (je32_to_cpu(rx.node_crc) != 0xffffffff) + JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", + ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc); + return EIO; + } + totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); + if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK + || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR + || je32_to_cpu(rx.totlen) != totlen + || je32_to_cpu(rx.xid) != xd->xid + || je32_to_cpu(rx.version) != xd->version) { + JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, " + "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n", + ref_offset(xd->node), je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK, + je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR, + je32_to_cpu(rx.totlen), totlen, + je32_to_cpu(rx.xid), xd->xid, + je32_to_cpu(rx.version), xd->version); + return EIO; + } + xd->xprefix = rx.xprefix; + xd->name_len = rx.name_len; + xd->value_len = je16_to_cpu(rx.value_len); + xd->data_crc = je32_to_cpu(rx.data_crc); + + /* This JFFS2_NODETYPE_XATTR node is checked */ + jeb = &c->blocks[ref_offset(xd->node) / c->sector_size]; + totlen = PAD(je32_to_cpu(rx.totlen)); + + spin_lock(&c->erase_completion_lock); + c->unchecked_size -= totlen; c->used_size += totlen; + jeb->unchecked_size -= totlen; jeb->used_size += totlen; + xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE; + spin_unlock(&c->erase_completion_lock); + + /* unchecked xdatum is chained with c->xattr_unchecked */ + list_del_init(&xd->xindex); + + dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n", + xd->xid, xd->version); + + return 0; +} + +static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + char *data; + size_t readlen; + uint32_t crc, length; + int i, ret, retry = 0; + + BUG_ON(!xd->node); + BUG_ON(ref_flags(xd->node) != REF_PRISTINE); + BUG_ON(!list_empty(&xd->xindex)); + retry: + length = xd->name_len + 1 + xd->value_len; + data = kmalloc(length, GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr), + length, &readlen, data); + + if (ret || length!=readlen) { + JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%d, at %#08x\n", + ret, length, readlen, ref_offset(xd->node)); + kfree(data); + return ret ? ret : -EIO; + } + + data[xd->name_len] = '\0'; + crc = crc32(0, data, length); + if (crc != xd->data_crc) { + JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)" + " at %#08x, read: 0x%08x calculated: 0x%08x\n", + ref_offset(xd->node), xd->data_crc, crc); + kfree(data); + return EIO; + } + + xd->flags |= JFFS2_XFLAGS_HOT; + xd->xname = data; + xd->xvalue = data + xd->name_len+1; + + c->xdatum_mem_usage += length; + + xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len); + i = xd->hashkey % XATTRINDEX_HASHSIZE; + list_add(&xd->xindex, &c->xattrindex[i]); + if (!retry) { + retry = 1; + reclaim_xattr_datum(c); + if (!xd->xname) + goto retry; + } + + dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n", + xd->xid, xd->xprefix, xd->xname); + + return 0; +} + +static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem); + * rc < 0 : recoverable error, try again + * rc = 0 : success + * rc > 0 : Unrecoverable error, this node should be deleted. + */ + int rc = 0; + BUG_ON(xd->xname); + if (!xd->node) + return EIO; + if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) { + rc = do_verify_xattr_datum(c, xd); + if (rc > 0) { + list_del_init(&xd->xindex); + delete_xattr_datum_node(c, xd); + } + } + if (!rc) + rc = do_load_xattr_datum(c, xd); + return rc; +} + +static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd, uint32_t phys_ofs) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_raw_xattr rx; + struct jffs2_raw_node_ref *raw; + struct kvec vecs[2]; + uint32_t length; + int rc, totlen; + + BUG_ON(!xd->xname); + + vecs[0].iov_base = ℞ + vecs[0].iov_len = PAD(sizeof(rx)); + vecs[1].iov_base = xd->xname; + vecs[1].iov_len = xd->name_len + 1 + xd->value_len; + totlen = vecs[0].iov_len + vecs[1].iov_len; + + raw = jffs2_alloc_raw_node_ref(); + if (!raw) + return -ENOMEM; + raw->flash_offset = phys_ofs; + raw->__totlen = PAD(totlen); + raw->next_phys = NULL; + raw->next_in_ino = (void *)xd; + + /* Setup raw-xattr */ + rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); + rx.totlen = cpu_to_je32(PAD(totlen)); + rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4)); + + rx.xid = cpu_to_je32(xd->xid); + rx.version = cpu_to_je32(++xd->version); + rx.xprefix = xd->xprefix; + rx.name_len = xd->name_len; + rx.value_len = cpu_to_je16(xd->value_len); + rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len)); + rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4)); + + rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0); + if (rc || totlen != length) { + JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n", + rc, totlen, length, phys_ofs); + rc = rc ? rc : -EIO; + if (length) { + raw->flash_offset |= REF_OBSOLETE; + raw->next_in_ino = NULL; + jffs2_add_physical_node_ref(c, raw); + jffs2_mark_node_obsolete(c, raw); + } else { + jffs2_free_raw_node_ref(raw); + } + return rc; + } + BUG_ON(raw->__totlen < sizeof(struct jffs2_raw_xattr)); + /* success */ + raw->flash_offset |= REF_PRISTINE; + jffs2_add_physical_node_ref(c, raw); + if (xd->node) + delete_xattr_datum_node(c, xd); + xd->node = raw; + + dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n", + xd->xid, xd->version, xd->xprefix, xd->xname); + + return 0; +} + +static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, + int xprefix, const char *xname, + const char *xvalue, int xsize, + uint32_t phys_ofs) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_xattr_datum *xd; + uint32_t hashkey, name_len; + char *data; + int i, rc; + + /* Search xattr_datum has same xname/xvalue by index */ + hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize); + i = hashkey % XATTRINDEX_HASHSIZE; + list_for_each_entry(xd, &c->xattrindex[i], xindex) { + if (xd->hashkey==hashkey + && xd->xprefix==xprefix + && xd->value_len==xsize + && !strcmp(xd->xname, xname) + && !memcmp(xd->xvalue, xvalue, xsize)) { + xd->refcnt++; + return xd; + } + } + + /* Not found, Create NEW XATTR-Cache */ + name_len = strlen(xname); + + xd = jffs2_alloc_xattr_datum(); + if (!xd) + return ERR_PTR(-ENOMEM); + + data = kmalloc(name_len + 1 + xsize, GFP_KERNEL); + if (!data) { + jffs2_free_xattr_datum(xd); + return ERR_PTR(-ENOMEM); + } + strcpy(data, xname); + memcpy(data + name_len + 1, xvalue, xsize); + + xd->refcnt = 1; + xd->xid = ++c->highest_xid; + xd->flags |= JFFS2_XFLAGS_HOT; + xd->xprefix = xprefix; + + xd->hashkey = hashkey; + xd->xname = data; + xd->xvalue = data + name_len + 1; + xd->name_len = name_len; + xd->value_len = xsize; + xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len); + + rc = save_xattr_datum(c, xd, phys_ofs); + if (rc) { + kfree(xd->xname); + jffs2_free_xattr_datum(xd); + return ERR_PTR(rc); + } + + /* Insert Hash Index */ + i = hashkey % XATTRINDEX_HASHSIZE; + list_add(&xd->xindex, &c->xattrindex[i]); + + c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len); + reclaim_xattr_datum(c); + + return xd; +} + +/* -------- xdatum related functions ---------------- + * verify_xattr_ref(c, ref) + * is used to load xref information from medium. Because summary data does not + * contain xid/ino, it's necessary to verify once while mounting process. + * delete_xattr_ref_node(c, ref) + * is used to delete a jffs2 node is dominated by xref. When EBS is enabled, + * it overwrites the obsolete node by myself. + * delete_xattr_ref(c, ref) + * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum + * is refered by this xref become 0, delete_xattr_datum() is called later. + * save_xattr_ref(c, ref, phys_ofs) + * is used to write xref to medium. + * create_xattr_ref(c, ic, xd, phys_ofs) + * is used to create a new xref and write to medium. + * jffs2_xattr_delete_inode(c, ic) + * is called to remove xrefs related to obsolete inode when inode is unlinked. + * jffs2_xattr_free_inode(c, ic) + * is called to release xattr related objects when unmounting. + * check_xattr_ref_ilist(c, ic) + * is used to confirm inode does not have duplicate xattr name/value pair. + * -------------------------------------------------- */ +static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) +{ + struct jffs2_eraseblock *jeb; + struct jffs2_raw_xref rr; + size_t readlen; + uint32_t crc, totlen; + int rc; + + BUG_ON(ref_flags(ref->node) != REF_UNCHECKED); + + rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr); + if (rc || sizeof(rr) != readlen) { + JFFS2_WARNING("jffs2_flash_read()=%d, req=%u, read=%u, at %#08x\n", + rc, sizeof(rr), readlen, ref_offset(ref->node)); + return rc ? rc : -EIO; + } + /* obsolete node */ + crc = crc32(0, &rr, sizeof(rr) - 4); + if (crc != je32_to_cpu(rr.node_crc)) { + if (je32_to_cpu(rr.node_crc) != 0xffffffff) + JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", + ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc); + return EIO; + } + if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK + || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF + || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) { + JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, " + "nodetype=%#04x/%#04x, totlen=%u/%u\n", + ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, + je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, + je32_to_cpu(rr.totlen), PAD(sizeof(rr))); + return EIO; + } + ref->ino = je32_to_cpu(rr.ino); + ref->xid = je32_to_cpu(rr.xid); + + /* fixup superblock/eraseblock info */ + jeb = &c->blocks[ref_offset(ref->node) / c->sector_size]; + totlen = PAD(sizeof(rr)); + + spin_lock(&c->erase_completion_lock); + c->unchecked_size -= totlen; c->used_size += totlen; + jeb->unchecked_size -= totlen; jeb->used_size += totlen; + ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE; + spin_unlock(&c->erase_completion_lock); + + dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n", + ref->ino, ref->xid, ref_offset(ref->node)); + return 0; +} + +static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) +{ + struct jffs2_raw_xref rr; + uint32_t length; + int rc; + + if (jffs2_sum_active()) { + memset(&rr, 0xff, sizeof(rr)); + rc = jffs2_flash_read(c, ref_offset(ref->node), + sizeof(struct jffs2_unknown_node), + &length, (char *)&rr); + if (rc || length != sizeof(struct jffs2_unknown_node)) { + JFFS2_ERROR("jffs2_flash_read()=%d, req=%u, read=%u at %#08x\n", + rc, sizeof(struct jffs2_unknown_node), + length, ref_offset(ref->node)); + } + rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr), + &length, (char *)&rr); + if (rc || length != sizeof(struct jffs2_raw_xref)) { + JFFS2_ERROR("jffs2_flash_write()=%d, req=%u, wrote=%u at %#08x\n", + rc, sizeof(rr), length, ref_offset(ref->node)); + } + } + spin_lock(&c->erase_completion_lock); + ref->node->next_in_ino = NULL; + spin_unlock(&c->erase_completion_lock); + jffs2_mark_node_obsolete(c, ref->node); + ref->node = NULL; +} + +static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_xattr_datum *xd; + + BUG_ON(!ref->node); + delete_xattr_ref_node(c, ref); + + list_del(&ref->ilist); + xd = ref->xd; + xd->refcnt--; + if (!xd->refcnt) + delete_xattr_datum(c, xd); + jffs2_free_xattr_ref(ref); +} + +static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, uint32_t phys_ofs) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_raw_node_ref *raw; + struct jffs2_raw_xref rr; + uint32_t length; + int ret; + + raw = jffs2_alloc_raw_node_ref(); + if (!raw) + return -ENOMEM; + raw->flash_offset = phys_ofs; + raw->__totlen = PAD(sizeof(rr)); + raw->next_phys = NULL; + raw->next_in_ino = (void *)ref; + + rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); + rr.totlen = cpu_to_je32(PAD(sizeof(rr))); + rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4)); + + rr.ino = cpu_to_je32(ref->ic->ino); + rr.xid = cpu_to_je32(ref->xd->xid); + rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4)); + + ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr); + if (ret || sizeof(rr) != length) { + JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n", + ret, sizeof(rr), length, phys_ofs); + ret = ret ? ret : -EIO; + if (length) { + raw->flash_offset |= REF_OBSOLETE; + raw->next_in_ino = NULL; + jffs2_add_physical_node_ref(c, raw); + jffs2_mark_node_obsolete(c, raw); + } else { + jffs2_free_raw_node_ref(raw); + } + return ret; + } + raw->flash_offset |= REF_PRISTINE; + + jffs2_add_physical_node_ref(c, raw); + if (ref->node) + delete_xattr_ref_node(c, ref); + ref->node = raw; + + dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid); + + return 0; +} + +static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, + struct jffs2_xattr_datum *xd, uint32_t phys_ofs) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_xattr_ref *ref; + int ret; + + ref = jffs2_alloc_xattr_ref(); + if (!ref) + return ERR_PTR(-ENOMEM); + ref->ic = ic; + ref->xd = xd; + + ret = save_xattr_ref(c, ref, phys_ofs); + if (ret) { + jffs2_free_xattr_ref(ref); + return ERR_PTR(ret); + } + + /* Chain to inode */ + list_add(&ref->ilist, &ic->ilist); + + return ref; /* success */ +} + +void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +{ + /* It's called from jffs2_clear_inode() on inode removing. + When an inode with XATTR is removed, those XATTRs must be removed. */ + struct jffs2_xattr_ref *ref, *_ref; + + if (!ic || ic->nlink > 0) + return; + + down_write(&c->xattr_sem); + list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist) + delete_xattr_ref(c, ref); + up_write(&c->xattr_sem); +} + +void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +{ + /* It's called from jffs2_free_ino_caches() until unmounting FS. */ + struct jffs2_xattr_datum *xd; + struct jffs2_xattr_ref *ref, *_ref; + + down_write(&c->xattr_sem); + list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist) { + list_del(&ref->ilist); + xd = ref->xd; + xd->refcnt--; + if (!xd->refcnt) { + unload_xattr_datum(c, xd); + jffs2_free_xattr_datum(xd); + } + jffs2_free_xattr_ref(ref); + } + up_write(&c->xattr_sem); +} + +static int check_xattr_ref_ilist(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +{ + /* success of check_xattr_ref_ilist() means taht inode (ic) dose not have + * duplicate name/value pairs. If duplicate name/value pair would be found, + * one will be removed. + */ + struct jffs2_xattr_ref *ref, *cmp; + int rc = 0; + + if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) + return 0; + down_write(&c->xattr_sem); + retry: + rc = 0; + list_for_each_entry(ref, &ic->ilist, ilist) { + if (!ref->xd->xname) { + rc = load_xattr_datum(c, ref->xd); + if (unlikely(rc > 0)) { + delete_xattr_ref(c, ref); + goto retry; + } else if (unlikely(rc < 0)) + goto out; + } + cmp = ref; + list_for_each_entry_continue(cmp, &ic->ilist, ilist) { + if (!cmp->xd->xname) { + ref->xd->flags |= JFFS2_XFLAGS_BIND; + rc = load_xattr_datum(c, cmp->xd); + ref->xd->flags &= ~JFFS2_XFLAGS_BIND; + if (unlikely(rc > 0)) { + delete_xattr_ref(c, cmp); + goto retry; + } else if (unlikely(rc < 0)) + goto out; + } + if (ref->xd->xprefix == cmp->xd->xprefix + && !strcmp(ref->xd->xname, cmp->xd->xname)) { + delete_xattr_ref(c, cmp); + goto retry; + } + } + } + ic->flags |= INO_FLAGS_XATTR_CHECKED; + out: + up_write(&c->xattr_sem); + + return rc; +} + +/* -------- xattr subsystem functions --------------- + * jffs2_init_xattr_subsystem(c) + * is used to initialize semaphore and list_head, and some variables. + * jffs2_find_xattr_datum(c, xid) + * is used to lookup xdatum while scanning process. + * jffs2_clear_xattr_subsystem(c) + * is used to release any xattr related objects. + * jffs2_build_xattr_subsystem(c) + * is used to associate xdatum and xref while super block building process. + * jffs2_setup_xattr_datum(c, xid, version) + * is used to insert xdatum while scanning process. + * -------------------------------------------------- */ +void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c) +{ + int i; + + for (i=0; i < XATTRINDEX_HASHSIZE; i++) + INIT_LIST_HEAD(&c->xattrindex[i]); + INIT_LIST_HEAD(&c->xattr_temp); + INIT_LIST_HEAD(&c->xattr_unchecked); + + init_rwsem(&c->xattr_sem); + c->xdatum_mem_usage = 0; + c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */ +} + +static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid) +{ + struct jffs2_xattr_datum *xd; + int i = xid % XATTRINDEX_HASHSIZE; + + /* It's only used in scanning/building process. */ + BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING))); + + list_for_each_entry(xd, &c->xattrindex[i], xindex) { + if (xd->xid==xid) + return xd; + } + return NULL; +} + +void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) +{ + struct jffs2_xattr_datum *xd, *_xd; + struct jffs2_xattr_ref *ref, *_ref; + int i; + + list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist) + jffs2_free_xattr_ref(ref); + + for (i=0; i < XATTRINDEX_HASHSIZE; i++) { + list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { + list_del(&xd->xindex); + if (xd->xname) + kfree(xd->xname); + jffs2_free_xattr_datum(xd); + } + } +} + +void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) +{ + struct jffs2_xattr_ref *ref, *_ref; + struct jffs2_xattr_datum *xd, *_xd; + struct jffs2_inode_cache *ic; + int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0; + + BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); + + /* Phase.1 */ + list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist) { + list_del_init(&ref->ilist); + /* checking REF_UNCHECKED nodes */ + if (ref_flags(ref->node) != REF_PRISTINE) { + if (verify_xattr_ref(c, ref)) { + delete_xattr_ref_node(c, ref); + jffs2_free_xattr_ref(ref); + continue; + } + } + /* At this point, ref->xid and ref->ino contain XID and inode number. + ref->xd and ref->ic are not valid yet. */ + xd = jffs2_find_xattr_datum(c, ref->xid); + ic = jffs2_get_ino_cache(c, ref->ino); + if (!xd || !ic) { + if (ref_flags(ref->node) != REF_UNCHECKED) + JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n", + ref->ino, ref->xid); + delete_xattr_ref_node(c, ref); + jffs2_free_xattr_ref(ref); + continue; + } + ref->xd = xd; + ref->ic = ic; + xd->refcnt++; + list_add_tail(&ref->ilist, &ic->ilist); + xref_count++; + } + /* After this, ref->xid/ino are NEVER used. */ + + /* Phase.2 */ + for (i=0; i < XATTRINDEX_HASHSIZE; i++) { + list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { + list_del_init(&xd->xindex); + if (!xd->refcnt) { + if (ref_flags(xd->node) != REF_UNCHECKED) + JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n", + xd->xid, xd->version, ref_offset(xd->node)); + delete_xattr_datum(c, xd); + continue; + } + if (ref_flags(xd->node) != REF_PRISTINE) { + dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n", + xd->xid, ref_offset(xd->node)); + list_add(&xd->xindex, &c->xattr_unchecked); + xdatum_unchecked_count++; + } + xdatum_count++; + } + } + /* build complete */ + JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and " + "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count); +} + +struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, + uint32_t xid, uint32_t version) +{ + struct jffs2_xattr_datum *xd, *_xd; + + _xd = jffs2_find_xattr_datum(c, xid); + if (_xd) { + dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n", + xid, version, _xd->version, ref_offset(_xd->node)); + if (version < _xd->version) + return ERR_PTR(-EEXIST); + } + xd = jffs2_alloc_xattr_datum(); + if (!xd) + return ERR_PTR(-ENOMEM); + xd->xid = xid; + xd->version = version; + if (xd->xid > c->highest_xid) + c->highest_xid = xd->xid; + list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]); + + if (_xd) { + list_del_init(&_xd->xindex); + delete_xattr_datum_node(c, _xd); + jffs2_free_xattr_datum(_xd); + } + return xd; +} + +/* -------- xattr subsystem functions --------------- + * xprefix_to_handler(xprefix) + * is used to translate xprefix into xattr_handler. + * jffs2_listxattr(dentry, buffer, size) + * is an implementation of listxattr handler on jffs2. + * do_jffs2_getxattr(inode, xprefix, xname, buffer, size) + * is an implementation of getxattr handler on jffs2. + * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags) + * is an implementation of setxattr handler on jffs2. + * -------------------------------------------------- */ +struct xattr_handler *jffs2_xattr_handlers[] = { + &jffs2_user_xattr_handler, +#ifdef CONFIG_JFFS2_FS_SECURITY + &jffs2_security_xattr_handler, +#endif +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + &jffs2_acl_access_xattr_handler, + &jffs2_acl_default_xattr_handler, +#endif + &jffs2_trusted_xattr_handler, + NULL +}; + +static struct xattr_handler *xprefix_to_handler(int xprefix) { + struct xattr_handler *ret; + + switch (xprefix) { + case JFFS2_XPREFIX_USER: + ret = &jffs2_user_xattr_handler; + break; +#ifdef CONFIG_JFFS2_FS_SECURITY + case JFFS2_XPREFIX_SECURITY: + ret = &jffs2_security_xattr_handler; + break; +#endif +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + case JFFS2_XPREFIX_ACL_ACCESS: + ret = &jffs2_acl_access_xattr_handler; + break; + case JFFS2_XPREFIX_ACL_DEFAULT: + ret = &jffs2_acl_default_xattr_handler; + break; +#endif + case JFFS2_XPREFIX_TRUSTED: + ret = &jffs2_trusted_xattr_handler; + break; + default: + ret = NULL; + break; + } + return ret; +} + +ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + struct inode *inode = dentry->d_inode; + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_inode_cache *ic = f->inocache; + struct jffs2_xattr_ref *ref; + struct jffs2_xattr_datum *xd; + struct xattr_handler *xhandle; + ssize_t len, rc; + int retry = 0; + + rc = check_xattr_ref_ilist(c, ic); + if (unlikely(rc)) + return rc; + + down_read(&c->xattr_sem); + retry: + len = 0; + list_for_each_entry(ref, &ic->ilist, ilist) { + BUG_ON(ref->ic != ic); + xd = ref->xd; + if (!xd->xname) { + /* xdatum is unchached */ + if (!retry) { + retry = 1; + up_read(&c->xattr_sem); + down_write(&c->xattr_sem); + goto retry; + } else { + rc = load_xattr_datum(c, xd); + if (unlikely(rc > 0)) { + delete_xattr_ref(c, ref); + goto retry; + } else if (unlikely(rc < 0)) + goto out; + } + } + xhandle = xprefix_to_handler(xd->xprefix); + if (!xhandle) + continue; + if (buffer) { + rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len); + } else { + rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len); + } + if (rc < 0) + goto out; + len += rc; + } + rc = len; + out: + if (!retry) { + up_read(&c->xattr_sem); + } else { + up_write(&c->xattr_sem); + } + return rc; +} + +int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, + char *buffer, size_t size) +{ + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_inode_cache *ic = f->inocache; + struct jffs2_xattr_datum *xd; + struct jffs2_xattr_ref *ref; + int rc, retry = 0; + + rc = check_xattr_ref_ilist(c, ic); + if (unlikely(rc)) + return rc; + + down_read(&c->xattr_sem); + retry: + list_for_each_entry(ref, &ic->ilist, ilist) { + BUG_ON(ref->ic!=ic); + + xd = ref->xd; + if (xd->xprefix != xprefix) + continue; + if (!xd->xname) { + /* xdatum is unchached */ + if (!retry) { + retry = 1; + up_read(&c->xattr_sem); + down_write(&c->xattr_sem); + goto retry; + } else { + rc = load_xattr_datum(c, xd); + if (unlikely(rc > 0)) { + delete_xattr_ref(c, ref); + goto retry; + } else if (unlikely(rc < 0)) { + goto out; + } + } + } + if (!strcmp(xname, xd->xname)) { + rc = xd->value_len; + if (buffer) { + if (size < rc) { + rc = -ERANGE; + } else { + memcpy(buffer, xd->xvalue, rc); + } + } + goto out; + } + } + rc = -ENODATA; + out: + if (!retry) { + up_read(&c->xattr_sem); + } else { + up_write(&c->xattr_sem); + } + return rc; +} + +int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, + const char *buffer, size_t size, int flags) +{ + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_inode_cache *ic = f->inocache; + struct jffs2_xattr_datum *xd; + struct jffs2_xattr_ref *ref, *newref; + uint32_t phys_ofs, length, request; + int rc; + + rc = check_xattr_ref_ilist(c, ic); + if (unlikely(rc)) + return rc; + + request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size); + rc = jffs2_reserve_space(c, request, &phys_ofs, &length, + ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE); + if (rc) { + JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); + return rc; + } + + /* Find existing xattr */ + down_write(&c->xattr_sem); + retry: + list_for_each_entry(ref, &ic->ilist, ilist) { + xd = ref->xd; + if (xd->xprefix != xprefix) + continue; + if (!xd->xname) { + rc = load_xattr_datum(c, xd); + if (unlikely(rc > 0)) { + delete_xattr_ref(c, ref); + goto retry; + } else if (unlikely(rc < 0)) + goto out; + } + if (!strcmp(xd->xname, xname)) { + if (flags & XATTR_CREATE) { + rc = -EEXIST; + goto out; + } + if (!buffer) { + delete_xattr_ref(c, ref); + rc = 0; + goto out; + } + goto found; + } + } + /* not found */ + ref = NULL; + if (flags & XATTR_REPLACE) { + rc = -ENODATA; + goto out; + } + if (!buffer) { + rc = -EINVAL; + goto out; + } + found: + xd = create_xattr_datum(c, xprefix, xname, buffer, size, phys_ofs); + if (IS_ERR(xd)) { + rc = PTR_ERR(xd); + goto out; + } + up_write(&c->xattr_sem); + jffs2_complete_reservation(c); + + /* create xattr_ref */ + request = PAD(sizeof(struct jffs2_raw_xref)); + rc = jffs2_reserve_space(c, request, &phys_ofs, &length, + ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE); + if (rc) { + JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); + down_write(&c->xattr_sem); + xd->refcnt--; + if (!xd->refcnt) + delete_xattr_datum(c, xd); + up_write(&c->xattr_sem); + return rc; + } + down_write(&c->xattr_sem); + newref = create_xattr_ref(c, ic, xd, phys_ofs); + if (IS_ERR(newref)) { + rc = PTR_ERR(newref); + xd->refcnt--; + if (!xd->refcnt) + delete_xattr_datum(c, xd); + } else if (ref) { + /* If replaced xattr_ref exists */ + delete_xattr_ref(c, ref); + } + out: + up_write(&c->xattr_sem); + jffs2_complete_reservation(c); + return rc; +} + +/* -------- garbage collector functions ------------- + * jffs2_garbage_collect_xattr_datum(c, xd) + * is used to move xdatum into new node. + * jffs2_garbage_collect_xattr_ref(c, ref) + * is used to move xref into new node. + * jffs2_garbage_collect_xattr(c, ic) + * is used to call appropriate garbage collector function, if argument + * pointer (ic) is the reference of xdatum/xref. + * jffs2_verify_xattr(c) + * is used to call do_verify_xattr_datum() before garbage collecting. + * -------------------------------------------------- */ +static int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, + struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem), and called from GC thread */ + uint32_t phys_ofs, totlen, length, old_ofs; + int rc; + + BUG_ON(!xd->node); + + old_ofs = ref_offset(xd->node); + totlen = ref_totlen(c, c->gcblock, xd->node); + if (totlen < sizeof(struct jffs2_raw_xattr)) + return -EINVAL; + + if (!xd->xname) { + rc = load_xattr_datum(c, xd); + if (unlikely(rc > 0)) { + delete_xattr_datum_node(c, xd); + return 0; + } else if (unlikely(rc < 0)) + return -EINVAL; + } + rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XATTR_SIZE); + if (rc || length < totlen) { + JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen); + return rc ? rc : -EBADFD; + } + rc = save_xattr_datum(c, xd, phys_ofs); + if (!rc) + dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n", + xd->xid, xd->version, old_ofs, ref_offset(xd->node)); + return rc; +} + + +static int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, + struct jffs2_xattr_ref *ref) +{ + /* must be called under down(alloc_sem) */ + uint32_t phys_ofs, totlen, length, old_ofs; + int rc; + + BUG_ON(!ref->node); + + old_ofs = ref_offset(ref->node); + totlen = ref_totlen(c, c->gcblock, ref->node); + if (totlen != sizeof(struct jffs2_raw_xref)) + return -EINVAL; + rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XREF_SIZE); + if (rc || length < totlen) { + JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n", + __FUNCTION__, rc, totlen); + return rc ? rc : -EBADFD; + } + rc = save_xattr_ref(c, ref, phys_ofs); + if (!rc) + dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n", + ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node)); + return rc; +} + +int jffs2_garbage_collect_xattr(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +{ + struct jffs2_xattr_datum *xd; + struct jffs2_xattr_ref *ref; + int ret; + + switch (ic->class) { + case RAWNODE_CLASS_XATTR_DATUM: + spin_unlock(&c->erase_completion_lock); + + down_write(&c->xattr_sem); + xd = (struct jffs2_xattr_datum *)ic; + ret = xd ? jffs2_garbage_collect_xattr_datum(c, xd) : 0; + up_write(&c->xattr_sem); + break; + case RAWNODE_CLASS_XATTR_REF: + spin_unlock(&c->erase_completion_lock); + + down_write(&c->xattr_sem); + ref = (struct jffs2_xattr_ref *)ic; + ret = ref ? jffs2_garbage_collect_xattr_ref(c, ref) : 0; + up_write(&c->xattr_sem); + break; + default: + /* This node is not xattr_datum/xattr_ref */ + ret = 1; + break; + } + return ret; +} + +int jffs2_verify_xattr(struct jffs2_sb_info *c) +{ + struct jffs2_xattr_datum *xd, *_xd; + int rc; + + down_write(&c->xattr_sem); + list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { + rc = do_verify_xattr_datum(c, xd); + if (rc == 0) { + list_del_init(&xd->xindex); + break; + } else if (rc > 0) { + list_del_init(&xd->xindex); + delete_xattr_datum_node(c, xd); + } + } + up_write(&c->xattr_sem); + + return list_empty(&c->xattr_unchecked) ? 1 : 0; +} -- cgit v1.2.3-59-g8ed1b From 8f2b6f49c656dd4597904f8c20661d6b73cdbbeb Mon Sep 17 00:00:00 2001 From: KaiGai Kohei Date: Sat, 13 May 2006 15:15:07 +0900 Subject: [JFFS2][XATTR] Remove 'struct list_head ilist' from jffs2_inode_cache. This patch can reduce 4-byte of memory usage per inode_cache. [4/10] jffs2-xattr-v5.1-04-remove_ilist_from_ic.patch Signed-off-by: KaiGai Kohei --- fs/jffs2/jffs2_fs_sb.h | 2 +- fs/jffs2/malloc.c | 1 - fs/jffs2/nodelist.h | 2 +- fs/jffs2/readinode.c | 1 - fs/jffs2/scan.c | 6 ++-- fs/jffs2/summary.c | 3 +- fs/jffs2/write.c | 1 - fs/jffs2/xattr.c | 75 +++++++++++++++++++++++++++++++------------------- fs/jffs2/xattr.h | 7 +---- 9 files changed, 55 insertions(+), 43 deletions(-) (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 3b4e0edd6dbb..272fbea55192 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h @@ -119,8 +119,8 @@ struct jffs2_sb_info { #define XATTRINDEX_HASHSIZE (57) uint32_t highest_xid; struct list_head xattrindex[XATTRINDEX_HASHSIZE]; - struct list_head xattr_temp; struct list_head xattr_unchecked; + struct jffs2_xattr_ref *xref_temp; struct rw_semaphore xattr_sem; uint32_t xdatum_mem_usage; uint32_t xdatum_mem_threshold; diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 3d5b7ecfbf8d..f2473fa2fd16 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -259,7 +259,6 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void) memset(ref, 0, sizeof(struct jffs2_xattr_ref)); ref->class = RAWNODE_CLASS_XATTR_REF; - INIT_LIST_HEAD(&ref->ilist); return ref; } diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 6f6279cf4909..351d947c9375 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -117,7 +117,7 @@ struct jffs2_inode_cache { uint32_t ino; int nlink; #ifdef CONFIG_JFFS2_FS_XATTR - struct list_head ilist; + struct jffs2_xattr_ref *xref; #endif }; diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 61ccdf4f1042..e1acce8fb2bf 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -902,7 +902,6 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, f->inocache->ino = f->inocache->nlink = 1; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; f->inocache->state = INO_STATE_READING; - init_xattr_inode_cache(f->inocache); jffs2_add_ino_cache(c, f->inocache); } if (!f->inocache) { diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index f09689e320fe..0a79fc921e9f 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -408,14 +408,15 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock * ref->xid is used to store 32bit xid, xd is not used * ref->ino is used to store 32bit inode-number, ic is not used * Thoes variables are declared as union, thus using those - * are exclusive. In a similar way, ref->ilist is temporarily + * are exclusive. In a similar way, ref->next is temporarily * used to chain all xattr_ref object. It's re-chained to * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly. */ ref->node = raw; ref->ino = je32_to_cpu(rr->ino); ref->xid = je32_to_cpu(rr->xid); - list_add_tail(&ref->ilist, &c->xattr_temp); + ref->next = c->xref_temp; + c->xref_temp = ref; raw->__totlen = PAD(je32_to_cpu(rr->totlen)); raw->flash_offset = ofs | REF_PRISTINE; @@ -888,7 +889,6 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin ic->ino = ino; ic->nodes = (void *)ic; - init_xattr_inode_cache(ic); jffs2_add_ino_cache(c, ic); if (ino == 1) ic->nlink = 1; diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 5d9ec8e36528..831a42c13059 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -556,7 +556,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ref->ino = 0xfffffffe; ref->xid = 0xfffffffd; ref->node = raw; - list_add_tail(&ref->ilist, &c->xattr_temp); + ref->next = c->xref_temp; + c->xref_temp = ref; raw->__totlen = PAD(sizeof(struct jffs2_raw_xref)); raw->flash_offset = ofs | REF_UNCHECKED; diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index d5c78195f3b8..ff2b00b604ec 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -36,7 +36,6 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint f->inocache->nlink = 1; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; f->inocache->state = INO_STATE_PRESENT; - init_xattr_inode_cache(f->inocache); jffs2_add_ino_cache(c, f->inocache); D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index c9a185c54ce7..b16bc71c9cd2 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -456,7 +456,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, * is called to remove xrefs related to obsolete inode when inode is unlinked. * jffs2_xattr_free_inode(c, ic) * is called to release xattr related objects when unmounting. - * check_xattr_ref_ilist(c, ic) + * check_xattr_ref_inode(c, ic) * is used to confirm inode does not have duplicate xattr name/value pair. * -------------------------------------------------- */ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) @@ -549,7 +549,6 @@ static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *re BUG_ON(!ref->node); delete_xattr_ref_node(c, ref); - list_del(&ref->ilist); xd = ref->xd; xd->refcnt--; if (!xd->refcnt) @@ -629,7 +628,8 @@ static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct } /* Chain to inode */ - list_add(&ref->ilist, &ic->ilist); + ref->next = ic->xref; + ic->xref = ref; return ref; /* success */ } @@ -644,8 +644,11 @@ void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache return; down_write(&c->xattr_sem); - list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist) + for (ref = ic->xref; ref; ref = _ref) { + _ref = ref->next; delete_xattr_ref(c, ref); + } + ic->xref = NULL; up_write(&c->xattr_sem); } @@ -656,8 +659,8 @@ void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i struct jffs2_xattr_ref *ref, *_ref; down_write(&c->xattr_sem); - list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist) { - list_del(&ref->ilist); + for (ref = ic->xref; ref; ref = _ref) { + _ref = ref->next; xd = ref->xd; xd->refcnt--; if (!xd->refcnt) { @@ -666,16 +669,17 @@ void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i } jffs2_free_xattr_ref(ref); } + ic->xref = NULL; up_write(&c->xattr_sem); } -static int check_xattr_ref_ilist(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) { - /* success of check_xattr_ref_ilist() means taht inode (ic) dose not have + /* success of check_xattr_ref_inode() means taht inode (ic) dose not have * duplicate name/value pairs. If duplicate name/value pair would be found, * one will be removed. */ - struct jffs2_xattr_ref *ref, *cmp; + struct jffs2_xattr_ref *ref, *cmp, **pref; int rc = 0; if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) @@ -683,22 +687,23 @@ static int check_xattr_ref_ilist(struct jffs2_sb_info *c, struct jffs2_inode_cac down_write(&c->xattr_sem); retry: rc = 0; - list_for_each_entry(ref, &ic->ilist, ilist) { + for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { if (!ref->xd->xname) { rc = load_xattr_datum(c, ref->xd); if (unlikely(rc > 0)) { + *pref = ref->next; delete_xattr_ref(c, ref); goto retry; } else if (unlikely(rc < 0)) goto out; } - cmp = ref; - list_for_each_entry_continue(cmp, &ic->ilist, ilist) { + for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) { if (!cmp->xd->xname) { ref->xd->flags |= JFFS2_XFLAGS_BIND; rc = load_xattr_datum(c, cmp->xd); ref->xd->flags &= ~JFFS2_XFLAGS_BIND; if (unlikely(rc > 0)) { + *pref = cmp->next; delete_xattr_ref(c, cmp); goto retry; } else if (unlikely(rc < 0)) @@ -706,6 +711,7 @@ static int check_xattr_ref_ilist(struct jffs2_sb_info *c, struct jffs2_inode_cac } if (ref->xd->xprefix == cmp->xd->xprefix && !strcmp(ref->xd->xname, cmp->xd->xname)) { + *pref = cmp->next; delete_xattr_ref(c, cmp); goto retry; } @@ -736,8 +742,8 @@ void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c) for (i=0; i < XATTRINDEX_HASHSIZE; i++) INIT_LIST_HEAD(&c->xattrindex[i]); - INIT_LIST_HEAD(&c->xattr_temp); INIT_LIST_HEAD(&c->xattr_unchecked); + c->xref_temp = NULL; init_rwsem(&c->xattr_sem); c->xdatum_mem_usage = 0; @@ -765,8 +771,11 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) struct jffs2_xattr_ref *ref, *_ref; int i; - list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist) + for (ref=c->xref_temp; ref; ref = _ref) { + _ref = ref->next; jffs2_free_xattr_ref(ref); + } + c->xref_temp = NULL; for (i=0; i < XATTRINDEX_HASHSIZE; i++) { list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { @@ -788,8 +797,8 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); /* Phase.1 */ - list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist) { - list_del_init(&ref->ilist); + for (ref=c->xref_temp; ref; ref=_ref) { + _ref = ref->next; /* checking REF_UNCHECKED nodes */ if (ref_flags(ref->node) != REF_PRISTINE) { if (verify_xattr_ref(c, ref)) { @@ -813,9 +822,11 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) ref->xd = xd; ref->ic = ic; xd->refcnt++; - list_add_tail(&ref->ilist, &ic->ilist); + ref->next = ic->xref; + ic->xref = ref; xref_count++; } + c->xref_temp = NULL; /* After this, ref->xid/ino are NEVER used. */ /* Phase.2 */ @@ -931,20 +942,20 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size) struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_cache *ic = f->inocache; - struct jffs2_xattr_ref *ref; + struct jffs2_xattr_ref *ref, **pref; struct jffs2_xattr_datum *xd; struct xattr_handler *xhandle; ssize_t len, rc; int retry = 0; - rc = check_xattr_ref_ilist(c, ic); + rc = check_xattr_ref_inode(c, ic); if (unlikely(rc)) return rc; down_read(&c->xattr_sem); retry: len = 0; - list_for_each_entry(ref, &ic->ilist, ilist) { + for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { BUG_ON(ref->ic != ic); xd = ref->xd; if (!xd->xname) { @@ -957,6 +968,7 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size) } else { rc = load_xattr_datum(c, xd); if (unlikely(rc > 0)) { + *pref = ref->next; delete_xattr_ref(c, ref); goto retry; } else if (unlikely(rc < 0)) @@ -992,16 +1004,16 @@ int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_cache *ic = f->inocache; struct jffs2_xattr_datum *xd; - struct jffs2_xattr_ref *ref; + struct jffs2_xattr_ref *ref, **pref; int rc, retry = 0; - rc = check_xattr_ref_ilist(c, ic); + rc = check_xattr_ref_inode(c, ic); if (unlikely(rc)) return rc; down_read(&c->xattr_sem); retry: - list_for_each_entry(ref, &ic->ilist, ilist) { + for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { BUG_ON(ref->ic!=ic); xd = ref->xd; @@ -1017,6 +1029,7 @@ int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, } else { rc = load_xattr_datum(c, xd); if (unlikely(rc > 0)) { + *pref = ref->next; delete_xattr_ref(c, ref); goto retry; } else if (unlikely(rc < 0)) { @@ -1053,11 +1066,11 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_cache *ic = f->inocache; struct jffs2_xattr_datum *xd; - struct jffs2_xattr_ref *ref, *newref; + struct jffs2_xattr_ref *ref, *newref, **pref; uint32_t phys_ofs, length, request; int rc; - rc = check_xattr_ref_ilist(c, ic); + rc = check_xattr_ref_inode(c, ic); if (unlikely(rc)) return rc; @@ -1072,13 +1085,14 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, /* Find existing xattr */ down_write(&c->xattr_sem); retry: - list_for_each_entry(ref, &ic->ilist, ilist) { + for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { xd = ref->xd; if (xd->xprefix != xprefix) continue; if (!xd->xname) { rc = load_xattr_datum(c, xd); if (unlikely(rc > 0)) { + *pref = ref->next; delete_xattr_ref(c, ref); goto retry; } else if (unlikely(rc < 0)) @@ -1090,6 +1104,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, goto out; } if (!buffer) { + *pref = ref->next; delete_xattr_ref(c, ref); rc = 0; goto out; @@ -1098,7 +1113,6 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, } } /* not found */ - ref = NULL; if (flags & XATTR_REPLACE) { rc = -ENODATA; goto out; @@ -1130,14 +1144,19 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, return rc; } down_write(&c->xattr_sem); + if (ref) + *pref = ref->next; newref = create_xattr_ref(c, ic, xd, phys_ofs); if (IS_ERR(newref)) { + if (ref) { + ref->next = ic->xref; + ic->xref = ref; + } rc = PTR_ERR(newref); xd->refcnt--; if (!xd->refcnt) delete_xattr_datum(c, xd); } else if (ref) { - /* If replaced xattr_ref exists */ delete_xattr_ref(c, ref); } out: diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index d157ad641ed4..0360097e5933 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h @@ -54,7 +54,7 @@ struct jffs2_xattr_ref struct jffs2_xattr_datum *xd; /* reference to jffs2_xattr_datum */ uint32_t xid; /* only used in sccanning/building */ }; - struct list_head ilist; /* chained from ic->ilist */ + struct jffs2_xattr_ref *next; /* chained from ic->xref_list */ }; #ifdef CONFIG_JFFS2_FS_XATTR @@ -86,9 +86,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); #define jffs2_setxattr generic_setxattr #define jffs2_removexattr generic_removexattr -/*---- Any inline initialize functions ----*/ -#define init_xattr_inode_cache(x) INIT_LIST_HEAD(&((x)->ilist)) - #else #define jffs2_init_xattr_subsystem(c) @@ -106,8 +103,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); #define jffs2_setxattr NULL #define jffs2_removexattr NULL -#define init_xattr_inode_cache(x) - #endif /* CONFIG_JFFS2_FS_XATTR */ #ifdef CONFIG_JFFS2_FS_SECURITY -- cgit v1.2.3-59-g8ed1b From 084702e00111eb9ffb6d8a5c1938b8e5423e40a8 Mon Sep 17 00:00:00 2001 From: KaiGai Kohei Date: Sat, 13 May 2006 15:16:13 +0900 Subject: [JFFS2][XATTR] Remove jffs2_garbage_collect_xattr(c, ic) Remove jffs2_garbage_collect_xattr(c, ic). jffs2_garbage_collect_xattr_datum/ref() are called from gc.c directly. In original implementation, jffs2_garbage_collect_xattr(c, ic) returns with holding a spinlock if 'ic' is inode_cache. But it returns after releasing a spinlock if 'ic' is xattr_datum/ref. It looks so confusable behavior. Thus, this patch makes caller manage locking/unlocking. [5/10] jffs2-xattr-v5.1-05-update_xattr_gc.patch Signed-off-by: KaiGai Kohei --- fs/jffs2/gc.c | 21 +++++++++++------ fs/jffs2/xattr.c | 68 +++++++++++++++++--------------------------------------- fs/jffs2/xattr.h | 4 ++-- 3 files changed, 36 insertions(+), 57 deletions(-) (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 4ea1b7f0ae78..a5ef9814f165 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -266,15 +266,22 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) ic = jffs2_raw_ref_to_ic(raw); +#ifdef CONFIG_JFFS2_FS_XATTR /* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr. - We can decide whether this node is inode or xattr by ic->class. - ret = 0 : ic is xattr_datum/xattr_ref, and GC was SUCCESSED. - ret < 0 : ic is xattr_datum/xattr_ref, but GC was FAILED. - ret > 0 : ic is NOT xattr_datum/xattr_ref. - */ - ret = jffs2_garbage_collect_xattr(c, ic); - if (ret <= 0) + * We can decide whether this node is inode or xattr by ic->class. */ + if (ic->class == RAWNODE_CLASS_XATTR_DATUM + || ic->class == RAWNODE_CLASS_XATTR_REF) { + BUG_ON(raw->next_in_ino != (void *)ic); + spin_unlock(&c->erase_completion_lock); + + if (ic->class == RAWNODE_CLASS_XATTR_DATUM) { + ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic); + } else { + ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic); + } goto release_sem; + } +#endif /* We need to hold the inocache. Either the erase_completion_lock or the inocache_lock are sufficient; we trade down since the inocache_lock diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index b16bc71c9cd2..9c1f401d12d7 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -1170,104 +1170,76 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, * is used to move xdatum into new node. * jffs2_garbage_collect_xattr_ref(c, ref) * is used to move xref into new node. - * jffs2_garbage_collect_xattr(c, ic) - * is used to call appropriate garbage collector function, if argument - * pointer (ic) is the reference of xdatum/xref. * jffs2_verify_xattr(c) * is used to call do_verify_xattr_datum() before garbage collecting. * -------------------------------------------------- */ -static int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, - struct jffs2_xattr_datum *xd) +int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) { - /* must be called under down_write(xattr_sem), and called from GC thread */ uint32_t phys_ofs, totlen, length, old_ofs; - int rc; + int rc = -EINVAL; + down_write(&c->xattr_sem); BUG_ON(!xd->node); old_ofs = ref_offset(xd->node); totlen = ref_totlen(c, c->gcblock, xd->node); if (totlen < sizeof(struct jffs2_raw_xattr)) - return -EINVAL; + goto out; if (!xd->xname) { rc = load_xattr_datum(c, xd); if (unlikely(rc > 0)) { delete_xattr_datum_node(c, xd); - return 0; + rc = 0; + goto out; } else if (unlikely(rc < 0)) - return -EINVAL; + goto out; } rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XATTR_SIZE); if (rc || length < totlen) { JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen); - return rc ? rc : -EBADFD; + rc = rc ? rc : -EBADFD; + goto out; } rc = save_xattr_datum(c, xd, phys_ofs); if (!rc) dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n", xd->xid, xd->version, old_ofs, ref_offset(xd->node)); + out: + up_write(&c->xattr_sem); return rc; } -static int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, - struct jffs2_xattr_ref *ref) +int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) { - /* must be called under down(alloc_sem) */ uint32_t phys_ofs, totlen, length, old_ofs; - int rc; + int rc = -EINVAL; + down_write(&c->xattr_sem); BUG_ON(!ref->node); old_ofs = ref_offset(ref->node); totlen = ref_totlen(c, c->gcblock, ref->node); if (totlen != sizeof(struct jffs2_raw_xref)) - return -EINVAL; + goto out; + rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XREF_SIZE); if (rc || length < totlen) { JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n", __FUNCTION__, rc, totlen); - return rc ? rc : -EBADFD; + rc = rc ? rc : -EBADFD; + goto out; } rc = save_xattr_ref(c, ref, phys_ofs); if (!rc) dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n", ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node)); + out: + up_write(&c->xattr_sem); return rc; } -int jffs2_garbage_collect_xattr(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -{ - struct jffs2_xattr_datum *xd; - struct jffs2_xattr_ref *ref; - int ret; - - switch (ic->class) { - case RAWNODE_CLASS_XATTR_DATUM: - spin_unlock(&c->erase_completion_lock); - - down_write(&c->xattr_sem); - xd = (struct jffs2_xattr_datum *)ic; - ret = xd ? jffs2_garbage_collect_xattr_datum(c, xd) : 0; - up_write(&c->xattr_sem); - break; - case RAWNODE_CLASS_XATTR_REF: - spin_unlock(&c->erase_completion_lock); - - down_write(&c->xattr_sem); - ref = (struct jffs2_xattr_ref *)ic; - ret = ref ? jffs2_garbage_collect_xattr_ref(c, ref) : 0; - up_write(&c->xattr_sem); - break; - default: - /* This node is not xattr_datum/xattr_ref */ - ret = 1; - break; - } - return ret; -} - int jffs2_verify_xattr(struct jffs2_sb_info *c) { struct jffs2_xattr_datum *xd, *_xd; diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index 0360097e5933..762814b7107b 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h @@ -69,7 +69,8 @@ extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); -extern int jffs2_garbage_collect_xattr(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); +extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd); +extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref); extern int jffs2_verify_xattr(struct jffs2_sb_info *c); extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, @@ -94,7 +95,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); #define jffs2_xattr_delete_inode(c, ic) #define jffs2_xattr_free_inode(c, ic) -#define jffs2_garbage_collect_xattr(c, ic) (1) #define jffs2_verify_xattr(c) (1) #define jffs2_xattr_handlers NULL -- cgit v1.2.3-59-g8ed1b From 652ecc20d1f5b4fd745c185c940e5b3afb2a0711 Mon Sep 17 00:00:00 2001 From: KaiGai Kohei Date: Sat, 13 May 2006 15:18:27 +0900 Subject: [JFFS2][XATTR] Unify each file header part with any jffs2 file. Unify each file header part with any jffs2 file. [7/10] jffs2-xattr-v5.1-07-unify_file_header.patch Signed-off-by: KaiGai Kohei --- fs/jffs2/acl.c | 15 ++++++++------- fs/jffs2/acl.h | 15 ++++++++------- fs/jffs2/security.c | 16 ++++++++-------- fs/jffs2/xattr.c | 16 ++++++++-------- fs/jffs2/xattr.h | 16 ++++++++-------- fs/jffs2/xattr_trusted.c | 15 ++++++++------- fs/jffs2/xattr_user.c | 15 ++++++++------- 7 files changed, 56 insertions(+), 52 deletions(-) (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index de173df84a83..1682278d9742 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -1,12 +1,13 @@ -/*-------------------------------------------------------------------------* - * File: fs/jffs2/acl.c - * POSIX ACL support on JFFS2 FileSystem +/* + * JFFS2 -- Journalling Flash File System, Version 2. * - * Implemented by KaiGai Kohei - * Copyright (C) 2006 NEC Corporation + * Copyright (C) 2006 NEC Corporation * - * For licensing information, see the file 'LICENCE' in the jffs2 directory. - *-------------------------------------------------------------------------*/ + * Created by KaiGai Kohei + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ #include #include #include diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h index 3f41e09200b8..54761fa8f233 100644 --- a/fs/jffs2/acl.h +++ b/fs/jffs2/acl.h @@ -1,12 +1,13 @@ -/*-------------------------------------------------------------------------* - * File: fs/jffs2/acl.h - * POSIX ACL support on JFFS2 FileSystem +/* + * JFFS2 -- Journalling Flash File System, Version 2. * - * Implemented by KaiGai Kohei - * Copyright (C) 2006 NEC Corporation + * Copyright (C) 2006 NEC Corporation * - * For licensing information, see the file 'LICENCE' in the jffs2 directory. - *-------------------------------------------------------------------------*/ + * Created by KaiGai Kohei + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ struct jffs2_acl_entry { jint16_t e_tag; jint16_t e_perm; diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c index 4b6c3b22524f..52a9894a6364 100644 --- a/fs/jffs2/security.c +++ b/fs/jffs2/security.c @@ -1,13 +1,13 @@ -/*-------------------------------------------------------------------------* - * File: fs/jffs2/security.c - * Security Labels support on JFFS2 FileSystem +/* + * JFFS2 -- Journalling Flash File System, Version 2. * - * Implemented by KaiGai Kohei - * Copyright (C) 2006 NEC Corporation + * Copyright (C) 2006 NEC Corporation * - * For licensing information, see the file 'LICENCE' in the jffs2 directory. - *-------------------------------------------------------------------------*/ - + * Created by KaiGai Kohei + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ #include #include #include diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 9c1f401d12d7..330e4491e73a 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -1,13 +1,13 @@ -/* ------------------------------------------------------------------------- - * File: fs/jffs2/xattr.c - * XATTR support on JFFS2 FileSystem +/* + * JFFS2 -- Journalling Flash File System, Version 2. * - * Implemented by KaiGai Kohei - * Copyright (C) 2006 NEC Corporation + * Copyright (C) 2006 NEC Corporation * - * For licensing information, see the file 'LICENCE' in the jffs2 directory. - * ------------------------------------------------------------------------- */ - + * Created by KaiGai Kohei + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ #include #include #include diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index 750d77ee6880..07cc737479f9 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h @@ -1,13 +1,13 @@ -/*-------------------------------------------------------------------------* - * File: fs/jffs2/xattr.c - * XATTR support on JFFS2 FileSystem +/* + * JFFS2 -- Journalling Flash File System, Version 2. * - * Implemented by KaiGai Kohei - * Copyright (C) 2006 NEC Corporation + * Copyright (C) 2006 NEC Corporation * - * For licensing information, see the file 'LICENCE' in the jffs2 directory. - *-------------------------------------------------------------------------*/ - + * Created by KaiGai Kohei + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ #ifndef _JFFS2_FS_XATTR_H_ #define _JFFS2_FS_XATTR_H_ diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c index a018c9c31a60..ed046e19dbfa 100644 --- a/fs/jffs2/xattr_trusted.c +++ b/fs/jffs2/xattr_trusted.c @@ -1,12 +1,13 @@ -/*-------------------------------------------------------------------------* - * File: fs/jffs2/xattr_trusted.c - * XATTR support on JFFS2 FileSystem +/* + * JFFS2 -- Journalling Flash File System, Version 2. * - * Implemented by KaiGai Kohei - * Copyright (C) 2006 NEC Corporation + * Copyright (C) 2006 NEC Corporation * - * For licensing information, see the file 'LICENCE' in the jffs2 directory. - *-------------------------------------------------------------------------*/ + * Created by KaiGai Kohei + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ #include #include #include diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c index d8c13636ea4c..2f8e9aa01ea0 100644 --- a/fs/jffs2/xattr_user.c +++ b/fs/jffs2/xattr_user.c @@ -1,12 +1,13 @@ -/*-------------------------------------------------------------------------* - * File: fs/jffs2/xattr_user.c - * XATTR support on JFFS2 FileSystem +/* + * JFFS2 -- Journalling Flash File System, Version 2. * - * Implemented by KaiGai Kohei - * Copyright (C) 2006 NEC Corporation + * Copyright (C) 2006 NEC Corporation * - * For licensing information, see the file 'LICENCE' in the jffs2 directory. - *-------------------------------------------------------------------------*/ + * Created by KaiGai Kohei + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ #include #include #include -- cgit v1.2.3-59-g8ed1b From 21b9879bf2817aca343cdda11ade6a87f5373e74 Mon Sep 17 00:00:00 2001 From: KaiGai Kohei Date: Sat, 13 May 2006 15:22:29 +0900 Subject: [JFFS2][XATTR] Fix obvious typo [2/2] jffs2-xattr-v5.2-02-fix_obvious_typo.patch Signed-off-by: KaiGai Kohei --- fs/jffs2/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 330e4491e73a..057bd4dcf665 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -438,7 +438,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, return xd; } -/* -------- xdatum related functions ---------------- +/* -------- xref related functions ------------------ * verify_xattr_ref(c, ref) * is used to load xref information from medium. Because summary data does not * contain xid/ino, it's necessary to verify once while mounting process. -- cgit v1.2.3-59-g8ed1b From b64335f2b740d6f5dbf5d3b04af30d407bf599f5 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sun, 21 May 2006 04:36:45 +0100 Subject: [JFFS2] Add length argument to jffs2_add_physical_node_ref() If __totlen is going away, we need to pass the length in separately. Also stop callers from needlessly setting ref->next_phys to NULL, since that's done for them... and since that'll also be going away soon. Signed-off-by: David Woodhouse --- fs/jffs2/gc.c | 6 ++---- fs/jffs2/nodelist.h | 2 +- fs/jffs2/nodemgmt.c | 6 ++---- fs/jffs2/wbuf.c | 4 +--- fs/jffs2/write.c | 12 ++++-------- fs/jffs2/xattr.c | 14 +++++--------- 6 files changed, 15 insertions(+), 29 deletions(-) (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index b0a5c407b476..4773ba24304f 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -627,8 +627,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, /* OK, all the CRCs are good; this node can just be copied as-is. */ retry: nraw->flash_offset = phys_ofs; - nraw->__totlen = rawlen; - nraw->next_phys = NULL; ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); @@ -640,7 +638,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, nraw->next_in_ino = NULL; nraw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, nraw); + jffs2_add_physical_node_ref(c, nraw, rawlen); jffs2_mark_node_obsolete(c, nraw); } else { printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); @@ -680,7 +678,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, goto out_node; } nraw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, nraw); + jffs2_add_physical_node_ref(c, nraw, rawlen); if (ic) { /* Link into per-inode list. This is safe because of the ic diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index ca15b3c731cf..94ef88787347 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -362,7 +362,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs uint32_t *len, int prio, uint32_t sumsize); int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize); -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); +int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len); void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index d6eab1b7ad53..4701556be49d 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -374,7 +374,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin * @c: superblock info * @new: new node reference to add * @len: length of this physical node - * @dirty: dirty flag for new node * * Should only be used to report nodes for which space has been allocated * by jffs2_reserve_space. @@ -382,13 +381,12 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin * Must be called with the alloc_sem held. */ -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) +int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len) { struct jffs2_eraseblock *jeb; - uint32_t len; jeb = &c->blocks[new->flash_offset / c->sector_size]; - len = ref_totlen(c, jeb, new); + new->__totlen = len; D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); #if 1 diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 4cebf0e57c46..676b83410f8c 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -312,11 +312,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) return; raw2->flash_offset = ofs | REF_OBSOLETE; - raw2->__totlen = ref_totlen(c, jeb, *first_raw); - raw2->next_phys = NULL; raw2->next_in_ino = NULL; - jffs2_add_physical_node_ref(c, raw2); + jffs2_add_physical_node_ref(c, raw2, ref_totlen(c, jeb, *first_raw)); } return; } diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index ff2b00b604ec..4462541d11f8 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -103,8 +103,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 fn->raw = raw; raw->flash_offset = flash_ofs; - raw->__totlen = PAD(sizeof(*ri)+datalen); - raw->next_phys = NULL; if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { BUG_ON(!retried); @@ -133,7 +131,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 any node we write before the original intended end of this node */ raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen)); jffs2_mark_node_obsolete(c, raw); } else { printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); @@ -191,7 +189,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 } else { raw->flash_offset |= REF_NORMAL; } - jffs2_add_physical_node_ref(c, raw); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen)); /* Link into per-inode list */ spin_lock(&c->erase_completion_lock); @@ -259,8 +257,6 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff fd->raw = raw; raw->flash_offset = flash_ofs; - raw->__totlen = PAD(sizeof(*rd)+namelen); - raw->next_phys = NULL; if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { BUG_ON(!retried); @@ -281,7 +277,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff if (retlen) { raw->next_in_ino = NULL; raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen)); jffs2_mark_node_obsolete(c, raw); } else { printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); @@ -327,7 +323,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff } /* Mark the space used */ raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen)); spin_lock(&c->erase_completion_lock); raw->next_in_ino = f->inocache->nodes; diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 057bd4dcf665..e16f8460ff04 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -322,8 +322,6 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x if (!raw) return -ENOMEM; raw->flash_offset = phys_ofs; - raw->__totlen = PAD(totlen); - raw->next_phys = NULL; raw->next_in_ino = (void *)xd; /* Setup raw-xattr */ @@ -348,17 +346,17 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x if (length) { raw->flash_offset |= REF_OBSOLETE; raw->next_in_ino = NULL; - jffs2_add_physical_node_ref(c, raw); + jffs2_add_physical_node_ref(c, raw, PAD(totlen)); jffs2_mark_node_obsolete(c, raw); } else { jffs2_free_raw_node_ref(raw); } return rc; } - BUG_ON(raw->__totlen < sizeof(struct jffs2_raw_xattr)); + /* success */ raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw); + jffs2_add_physical_node_ref(c, raw, PAD(totlen)); if (xd->node) delete_xattr_datum_node(c, xd); xd->node = raw; @@ -568,8 +566,6 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, if (!raw) return -ENOMEM; raw->flash_offset = phys_ofs; - raw->__totlen = PAD(sizeof(rr)); - raw->next_phys = NULL; raw->next_in_ino = (void *)ref; rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -589,7 +585,7 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, if (length) { raw->flash_offset |= REF_OBSOLETE; raw->next_in_ino = NULL; - jffs2_add_physical_node_ref(c, raw); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr))); jffs2_mark_node_obsolete(c, raw); } else { jffs2_free_raw_node_ref(raw); @@ -598,7 +594,7 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, } raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr))); if (ref->node) delete_xattr_ref_node(c, ref); ref->node = raw; -- cgit v1.2.3-59-g8ed1b From fcb7578719529898aef9edce8e409e457a1c2d15 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 22 May 2006 15:23:10 +0100 Subject: [JFFS2] Extend jffs2_link_node_ref() to link into per-inode list too. Let's avoid the potential for forgetting to set ref->next_in_ino, by doing it within jffs2_link_node_ref() instead. This highlights the ugliness of what we're currently doing with xattr_datum and xattr_ref structures -- we should find a nicer way of dealing with that. Signed-off-by: David Woodhouse --- fs/jffs2/erase.c | 3 +-- fs/jffs2/gc.c | 17 ++--------------- fs/jffs2/nodelist.c | 13 ++++++++++--- fs/jffs2/nodelist.h | 8 ++++++-- fs/jffs2/nodemgmt.c | 5 +++-- fs/jffs2/scan.c | 24 ++++++++---------------- fs/jffs2/summary.c | 30 ++++++++++-------------------- fs/jffs2/wbuf.c | 6 ++---- fs/jffs2/write.c | 23 ++++------------------- fs/jffs2/xattr.c | 15 +++++++-------- 10 files changed, 53 insertions(+), 91 deletions(-) (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index f677d6950fd4..0fc19a2fb5d9 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -410,10 +410,9 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb /* Everything else got zeroed before the erase */ jeb->free_size = c->sector_size; - marker_ref->next_in_ino = NULL; marker_ref->flash_offset = jeb->offset | REF_NORMAL; - jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size); + jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL); } spin_lock(&c->erase_completion_lock); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 4773ba24304f..153755bc1d53 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -634,11 +634,8 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", rawlen, phys_ofs, ret, retlen); if (retlen) { - /* Doesn't belong to any inode */ - nraw->next_in_ino = NULL; - nraw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, nraw, rawlen); + jffs2_add_physical_node_ref(c, nraw, rawlen, NULL); jffs2_mark_node_obsolete(c, nraw); } else { printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); @@ -678,18 +675,8 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, goto out_node; } nraw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, nraw, rawlen); + jffs2_add_physical_node_ref(c, nraw, rawlen, ic); - if (ic) { - /* Link into per-inode list. This is safe because of the ic - state being INO_STATE_GC. Note that if we're doing this - for an inode which is in-core, the 'nraw' pointer is then - going to be fetched from ic->nodes by our caller. */ - spin_lock(&c->erase_completion_lock); - nraw->next_in_ino = ic->nodes; - ic->nodes = nraw; - spin_unlock(&c->erase_completion_lock); - } jffs2_mark_node_obsolete(c, raw); D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 7d563f938b1c..d25d4919ca97 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -1048,7 +1048,8 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) } void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_node_ref *ref, uint32_t len) + struct jffs2_raw_node_ref *ref, uint32_t len, + struct jffs2_inode_cache *ic) { if (!jeb->first_node) jeb->first_node = ref; @@ -1065,6 +1066,13 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, } jeb->last_node = ref; + if (ic) { + ref->next_in_ino = ic->nodes; + ic->nodes = ref; + } else { + ref->next_in_ino = NULL; + } + switch(ref_flags(ref)) { case REF_UNCHECKED: c->unchecked_size += len; @@ -1120,12 +1128,11 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; ref->flash_offset |= REF_OBSOLETE; - ref->next_in_ino = 0; #ifdef TEST_TOTLEN ref->__totlen = size; #endif - jffs2_link_node_ref(c, jeb, ref, size); + jffs2_link_node_ref(c, jeb, ref, size, NULL); } return 0; diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 80d1fda2212b..ee5aedcffc12 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -307,7 +307,8 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_node_ref *ref, uint32_t len); + struct jffs2_raw_node_ref *ref, uint32_t len, + struct jffs2_inode_cache *ic); extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_node_ref *ref); @@ -318,7 +319,10 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs uint32_t *len, int prio, uint32_t sumsize); int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize); -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len); +int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, + struct jffs2_raw_node_ref *new, + uint32_t len, + struct jffs2_inode_cache *ic); void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 9a0f312cfcda..e10e58eab8e5 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -381,7 +381,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin * Must be called with the alloc_sem held. */ -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len) +int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, + uint32_t len, struct jffs2_inode_cache *ic) { struct jffs2_eraseblock *jeb; @@ -403,7 +404,7 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r #endif spin_lock(&c->erase_completion_lock); - jffs2_link_node_ref(c, jeb, new, len); + jffs2_link_node_ref(c, jeb, new, len, ic); if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) { /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index cffafec01e48..6fce703c0543 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -361,9 +361,9 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc xd->node = raw; raw->flash_offset = ofs | REF_PRISTINE; - raw->next_in_ino = (void *)xd; - jffs2_link_node_ref(c, jeb, raw, totlen); + jffs2_link_node_ref(c, jeb, raw, totlen, NULL); + /* FIXME */ raw->next_in_ino = (void *)xd; if (jffs2_sum_active()) jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); @@ -425,9 +425,9 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock c->xref_temp = ref; raw->flash_offset = ofs | REF_PRISTINE; - raw->next_in_ino = (void *)ref; - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rr->totlen))); + jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rr->totlen)), NULL); + /* FIXME */ raw->next_in_ino = (void *)ref; if (jffs2_sum_active()) jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); @@ -844,10 +844,9 @@ scan_more: printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n"); return -ENOMEM; } - marker_ref->next_in_ino = NULL; marker_ref->flash_offset = ofs | REF_NORMAL; - jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size); + jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL); ofs += PAD(c->cleanmarker_size); } @@ -892,8 +891,7 @@ scan_more: if (!ref) return -ENOMEM; ref->flash_offset = ofs | REF_PRISTINE; - ref->next_in_ino = 0; - jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen))); + jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen)), NULL); /* We can't summarise nodes we don't grok */ jffs2_sum_disable_collecting(s); @@ -1004,10 +1002,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc raw->flash_offset = ofs | REF_UNCHECKED; - raw->next_in_ino = ic->nodes; - ic->nodes = raw; - - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(ri->totlen))); + jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(ri->totlen)), ic); D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", je32_to_cpu(ri->ino), je32_to_cpu(ri->version), @@ -1082,10 +1077,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo } raw->flash_offset = ofs | REF_PRISTINE; - raw->next_in_ino = ic->nodes; - ic->nodes = raw; - - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rd->totlen))); + jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rd->totlen)), ic); fd->raw = raw; fd->next = NULL; diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 1451732e1fa7..351ba9f8185e 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -430,10 +430,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras raw->flash_offset |= REF_UNCHECKED; - raw->next_in_ino = ic->nodes; - ic->nodes = raw; - - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen))); + jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen)), ic); *pseudo_random += je32_to_cpu(spi->version); @@ -473,10 +470,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras } raw->flash_offset |= REF_PRISTINE; - raw->next_in_ino = ic->nodes; - ic->nodes = raw; - - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen))); + jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen)), ic); fd->raw = raw; fd->next = NULL; @@ -525,9 +519,9 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras xd->node = raw; raw->flash_offset |= REF_UNCHECKED; - raw->next_in_ino = (void *)xd; - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen))); + jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)), NULL); + /* FIXME */ raw->next_in_ino = (void *)xd; *pseudo_random += je32_to_cpu(spx->xid); sp += JFFS2_SUMMARY_XATTR_SIZE; @@ -561,9 +555,9 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras c->xref_temp = ref; raw->flash_offset |= REF_UNCHECKED; - raw->next_in_ino = (void *)ref; - jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref))); + jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)), NULL); + /* FIXME */ raw->next_in_ino = (void *)ref; *pseudo_random += raw->flash_offset; sp += JFFS2_SUMMARY_XREF_SIZE; @@ -664,9 +658,8 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb } marker_ref->flash_offset = jeb->offset | REF_NORMAL; - marker_ref->next_in_ino = NULL; - jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr)); + jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr), NULL); } } @@ -686,10 +679,9 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb return -ENOMEM; } - cache_ref->next_in_ino = NULL; cache_ref->flash_offset |= REF_NORMAL; - jffs2_link_node_ref(c, jeb, cache_ref, sumsize); + jffs2_link_node_ref(c, jeb, cache_ref, sumsize, NULL); if (unlikely(jeb->free_size)) { JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n", @@ -849,9 +841,8 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; ref->flash_offset |= REF_OBSOLETE; - ref->next_in_ino = 0; - jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size); + jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size, NULL); } c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; @@ -909,11 +900,10 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) return -ENOMEM; } - summary_ref->next_in_ino = NULL; summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; spin_lock(&c->erase_completion_lock); - jffs2_link_node_ref(c, jeb, summary_ref, infosize); + jffs2_link_node_ref(c, jeb, summary_ref, infosize, NULL); return 0; } diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 45e3573cf107..62f685faeba8 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -312,9 +312,8 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) return; raw2->flash_offset = ofs | REF_OBSOLETE; - raw2->next_in_ino = NULL; - jffs2_add_physical_node_ref(c, raw2, ref_totlen(c, jeb, *first_raw)); + jffs2_add_physical_node_ref(c, raw2, ref_totlen(c, jeb, *first_raw), NULL); } return; } @@ -507,11 +506,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) return -ENOMEM; ref->flash_offset = c->wbuf_ofs + c->wbuf_len; ref->flash_offset |= REF_OBSOLETE; - ref->next_in_ino = NULL; spin_lock(&c->erase_completion_lock); - jffs2_link_node_ref(c, jeb, ref, waste); + jffs2_link_node_ref(c, jeb, ref, waste, NULL); /* FIXME: that made it count as dirty. Convert to wasted */ jeb->dirty_size -= waste; c->dirty_size -= waste; diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 4462541d11f8..319a70f531f8 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -122,16 +122,13 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 /* Mark the space as dirtied */ if (retlen) { - /* Doesn't belong to any inode */ - raw->next_in_ino = NULL; - /* Don't change raw->size to match retlen. We may have written the node header already, and only the data will seem corrupted, in which case the scan would skip over any node we write before the original intended end of this node */ raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen)); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), NULL); jffs2_mark_node_obsolete(c, raw); } else { printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); @@ -189,13 +186,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 } else { raw->flash_offset |= REF_NORMAL; } - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen)); - - /* Link into per-inode list */ - spin_lock(&c->erase_completion_lock); - raw->next_in_ino = f->inocache->nodes; - f->inocache->nodes = raw; - spin_unlock(&c->erase_completion_lock); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), f->inocache); D1(printk(KERN_DEBUG "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", flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), @@ -275,9 +266,8 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff sizeof(*rd)+namelen, flash_ofs, ret, retlen); /* Mark the space as dirtied */ if (retlen) { - raw->next_in_ino = NULL; raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen)); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), NULL); jffs2_mark_node_obsolete(c, raw); } else { printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); @@ -323,12 +313,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff } /* Mark the space used */ raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen)); - - spin_lock(&c->erase_completion_lock); - raw->next_in_ino = f->inocache->nodes; - f->inocache->nodes = raw; - spin_unlock(&c->erase_completion_lock); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), f->inocache); if (retried) { jffs2_dbg_acct_sanity_check(c,NULL); diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index e16f8460ff04..76d166140381 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -322,7 +322,6 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x if (!raw) return -ENOMEM; raw->flash_offset = phys_ofs; - raw->next_in_ino = (void *)xd; /* Setup raw-xattr */ rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -345,8 +344,7 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x rc = rc ? rc : -EIO; if (length) { raw->flash_offset |= REF_OBSOLETE; - raw->next_in_ino = NULL; - jffs2_add_physical_node_ref(c, raw, PAD(totlen)); + jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL); jffs2_mark_node_obsolete(c, raw); } else { jffs2_free_raw_node_ref(raw); @@ -356,7 +354,9 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x /* success */ raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw, PAD(totlen)); + jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL); + /* FIXME */ raw->next_in_ino = (void *)xd; + if (xd->node) delete_xattr_datum_node(c, xd); xd->node = raw; @@ -566,7 +566,6 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, if (!raw) return -ENOMEM; raw->flash_offset = phys_ofs; - raw->next_in_ino = (void *)ref; rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); @@ -584,8 +583,7 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, ret = ret ? ret : -EIO; if (length) { raw->flash_offset |= REF_OBSOLETE; - raw->next_in_ino = NULL; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr))); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL); jffs2_mark_node_obsolete(c, raw); } else { jffs2_free_raw_node_ref(raw); @@ -594,7 +592,8 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, } raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr))); + jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL); + /* FIXME */ raw->next_in_ino = (void *)ref; if (ref->node) delete_xattr_ref_node(c, ref); ref->node = raw; -- cgit v1.2.3-59-g8ed1b From 9fe4854cd1f60273f9a3ece053f4789605f58a5e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 23 May 2006 00:38:06 +0100 Subject: [JFFS2] Remove flash offset argument from various functions. We don't need the upper layers to deal with the physical offset. It's _always_ c->nextblock->offset + c->sector_size - c->nextblock->free_size so we might as well just let the actual write functions deal with that. Signed-off-by: David Woodhouse --- fs/jffs2/dir.c | 40 +++++++++++++++++----------------- fs/jffs2/file.c | 8 +++---- fs/jffs2/fs.c | 8 +++---- fs/jffs2/gc.c | 34 ++++++++++++++--------------- fs/jffs2/nodelist.h | 23 ++++++++++++++------ fs/jffs2/nodemgmt.c | 26 +++++++++++----------- fs/jffs2/wbuf.c | 4 +++- fs/jffs2/write.c | 62 ++++++++++++++++++++++++++++++----------------------- fs/jffs2/xattr.c | 45 +++++++++++++++++++------------------- 9 files changed, 135 insertions(+), 115 deletions(-) (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index ff1b7950dd44..edd8371fc6a5 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -308,7 +308,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char struct jffs2_full_dnode *fn; struct jffs2_full_dirent *fd; int namelen; - uint32_t alloclen, phys_ofs; + uint32_t alloclen; int ret, targetlen = strlen(target); /* FIXME: If you care. We'd need to use frags for the target @@ -327,8 +327,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, - ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -356,7 +356,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - fn = jffs2_write_dnode(c, f, ri, target, targetlen, phys_ofs, ALLOC_NORMAL); + fn = jffs2_write_dnode(c, f, ri, target, targetlen, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -400,8 +400,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char return ret; } - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, - ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); @@ -433,7 +433,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); - fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); + fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); if (IS_ERR(fd)) { /* dirent failed to write. Delete the inode normally @@ -471,7 +471,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) struct jffs2_full_dnode *fn; struct jffs2_full_dirent *fd; int namelen; - uint32_t alloclen, phys_ofs; + uint32_t alloclen; int ret; mode |= S_IFDIR; @@ -486,8 +486,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, - JFFS2_SUMMARY_INODE_SIZE); + ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -512,7 +512,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ri->data_crc = cpu_to_je32(0); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); + fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -542,8 +542,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) return ret; } - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, - ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); @@ -575,7 +575,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); - fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); + fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); if (IS_ERR(fd)) { /* dirent failed to write. Delete the inode normally @@ -631,7 +631,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de int namelen; union jffs2_device_node dev; int devlen = 0; - uint32_t alloclen, phys_ofs; + uint32_t alloclen; int ret; if (!new_valid_dev(rdev)) @@ -650,7 +650,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, + ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { @@ -678,7 +678,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL); + fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -708,8 +708,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de return ret; } - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, - ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); @@ -744,7 +744,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); - fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); + fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); if (IS_ERR(fd)) { /* dirent failed to write. Delete the inode normally diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index e18c9437d58f..bb8844f40e48 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -134,13 +134,13 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; - uint32_t phys_ofs, alloc_len; + uint32_t alloc_len; D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs)); - ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, - ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) return ret; @@ -166,7 +166,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ri.data_crc = cpu_to_je32(0); - fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL); + fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_NORMAL); if (IS_ERR(fn)) { ret = PTR_ERR(fn); diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 79f70251a4eb..7b6c24b14f85 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -37,7 +37,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) unsigned char *mdata = NULL; int mdatalen = 0; unsigned int ivalid; - uint32_t phys_ofs, alloclen; + uint32_t alloclen; int ret; D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); ret = inode_change_ok(inode, iattr); @@ -79,8 +79,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) return -ENOMEM; } - ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, - ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); if (S_ISLNK(inode->i_mode & S_IFMT)) @@ -131,7 +131,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) else ri->data_crc = cpu_to_je32(0); - new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL); + new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL); if (S_ISLNK(inode->i_mode)) kfree(mdata); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 153755bc1d53..f9e982a65ac2 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -545,7 +545,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN; - ret = jffs2_reserve_space_gc(c, alloclen, &phys_ofs, &alloclen, rawlen); + ret = jffs2_reserve_space_gc(c, alloclen, &alloclen, rawlen); /* 'rawlen' is not the exact summary size; it is only an upper estimation */ if (ret) @@ -626,13 +626,13 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, /* OK, all the CRCs are good; this node can just be copied as-is. */ retry: - nraw->flash_offset = phys_ofs; + nraw->flash_offset = phys_ofs = write_ofs(c); ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); if (ret || (retlen != rawlen)) { printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", - rawlen, phys_ofs, ret, retlen); + rawlen, nraw->flash_offset, ret, retlen); if (retlen) { nraw->flash_offset |= REF_OBSOLETE; jffs2_add_physical_node_ref(c, nraw, rawlen, NULL); @@ -653,7 +653,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); - ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy, rawlen); + ret = jffs2_reserve_space_gc(c, rawlen, &dummy, rawlen); /* this is not the exact summary size of it, it is only an upper estimation */ @@ -696,7 +696,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ struct jffs2_node_frag *last_frag; union jffs2_device_node dev; char *mdata = NULL, mdatalen = 0; - uint32_t alloclen, phys_ofs, ilen; + uint32_t alloclen, ilen; int ret; if (S_ISBLK(JFFS2_F_I_MODE(f)) || @@ -722,7 +722,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ } - ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen, + ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &alloclen, JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", @@ -760,7 +760,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); - new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, phys_ofs, ALLOC_GC); + new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, ALLOC_GC); if (IS_ERR(new_fn)) { printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); @@ -781,7 +781,7 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er { struct jffs2_full_dirent *new_fd; struct jffs2_raw_dirent rd; - uint32_t alloclen, phys_ofs; + uint32_t alloclen; int ret; rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -803,14 +803,14 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen, + ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &alloclen, JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", sizeof(rd)+rd.nsize, ret); return ret; } - new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, phys_ofs, ALLOC_GC); + new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, ALLOC_GC); if (IS_ERR(new_fd)) { printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd)); @@ -938,7 +938,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras struct jffs2_raw_inode ri; struct jffs2_node_frag *frag; struct jffs2_full_dnode *new_fn; - uint32_t alloclen, phys_ofs, ilen; + uint32_t alloclen, ilen; int ret; D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", @@ -1017,14 +1017,14 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ri.data_crc = cpu_to_je32(0); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); - ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen, - JFFS2_SUMMARY_INODE_SIZE); + ret = jffs2_reserve_space_gc(c, sizeof(ri), &alloclen, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", sizeof(ri), ret); return ret; } - new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_GC); + new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_GC); if (IS_ERR(new_fn)) { printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn)); @@ -1086,7 +1086,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era { struct jffs2_full_dnode *new_fn; struct jffs2_raw_inode ri; - uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; + uint32_t alloclen, offset, orig_end, orig_start; int ret = 0; unsigned char *comprbuf = NULL, *writebuf; unsigned long pg; @@ -1243,7 +1243,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era uint32_t cdatalen; uint16_t comprtype = JFFS2_COMPR_NONE; - ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, + ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &alloclen, JFFS2_SUMMARY_INODE_SIZE); if (ret) { @@ -1280,7 +1280,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); - new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC); + new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, ALLOC_GC); jffs2_free_comprbuf(comprbuf, writebuf); diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 1e1c39da6da4..76f1b9419eea 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -167,6 +167,8 @@ struct jffs2_inode_cache { #define INOCACHE_HASHSIZE 128 +#define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size) + /* Larger representation of a raw node, kept in-core only when the struct inode for this particular ino is instantiated. @@ -325,9 +327,9 @@ extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, /* nodemgmt.c */ int jffs2_thread_should_wake(struct jffs2_sb_info *c); -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, +int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *len, int prio, uint32_t sumsize); -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, +int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *len, uint32_t sumsize); int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, @@ -339,14 +341,21 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref /* write.c */ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); -struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); -struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); +struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + struct jffs2_raw_inode *ri, const unsigned char *data, + uint32_t datalen, int alloc_mode); +struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + struct jffs2_raw_dirent *rd, const unsigned char *name, + uint32_t namelen, int alloc_mode); int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, unsigned char *buf, uint32_t offset, uint32_t writelen, uint32_t *retlen); -int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); -int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time); -int 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); +int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, + struct jffs2_raw_inode *ri, const char *name, int namelen); +int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, + int namelen, struct jffs2_inode_info *dead_f, uint32_t time); +int 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); /* readinode.c */ diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 34a452bdde05..8feb8749bc75 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -23,13 +23,12 @@ * jffs2_reserve_space - request physical space to write nodes to flash * @c: superblock info * @minsize: Minimum acceptable size of allocation - * @ofs: Returned value of node offset * @len: Returned value of allocation length * @prio: Allocation type - ALLOC_{NORMAL,DELETION} * * Requests a block of physical space on the flash. Returns zero for success - * and puts 'ofs' and 'len' into the appriopriate place, or returns -ENOSPC - * or other error if appropriate. + * and puts 'len' into the appropriate place, or returns -ENOSPC or other + * error if appropriate. Doesn't return len since that's * * If it returns zero, jffs2_reserve_space() also downs the per-filesystem * allocation semaphore, to prevent more than one allocation from being @@ -40,9 +39,9 @@ */ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, - uint32_t *ofs, uint32_t *len, uint32_t sumsize); + uint32_t *len, uint32_t sumsize); -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, +int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *len, int prio, uint32_t sumsize) { int ret = -EAGAIN; @@ -132,7 +131,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs spin_lock(&c->erase_completion_lock); } - ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); + ret = jffs2_do_reserve_space(c, minsize, len, sumsize); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); } @@ -143,8 +142,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs return ret; } -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, - uint32_t *len, uint32_t sumsize) +int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, + uint32_t *len, uint32_t sumsize) { int ret = -EAGAIN; minsize = PAD(minsize); @@ -153,7 +152,7 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * spin_lock(&c->erase_completion_lock); while(ret == -EAGAIN) { - ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); + ret = jffs2_do_reserve_space(c, minsize, len, sumsize); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); } @@ -259,10 +258,11 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) } /* Called with alloc sem _and_ erase_completion_lock */ -static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize) +static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, + uint32_t *len, uint32_t sumsize) { struct jffs2_eraseblock *jeb = c->nextblock; - uint32_t reserved_size; /* for summary information at the end of the jeb */ + uint32_t reserved_size; /* for summary information at the end of the jeb */ int ret; restart: @@ -349,7 +349,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin } /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has enough space */ - *ofs = jeb->offset + (c->sector_size - jeb->free_size); *len = jeb->free_size - reserved_size; if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && @@ -365,7 +364,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin spin_lock(&c->erase_completion_lock); } - D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", *len, *ofs)); + D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", + *len, jeb->offset + (c->sector_size - jeb->free_size))); return 0; } diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 087c2e438a6d..c7e3040240b2 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -265,12 +265,14 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) /* ... and get an allocation of space from a shiny new block instead */ - ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len, JFFS2_SUMMARY_NOSUM_SIZE); + ret = jffs2_reserve_space_gc(c, end-start, &len, JFFS2_SUMMARY_NOSUM_SIZE); if (ret) { printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); kfree(buf); return; } + ofs = write_ofs(c); + if (end-start >= c->wbuf_pagesize) { /* Need to do another write immediately, but it's possible that this is just because the wbuf itself is completely diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 319a70f531f8..0e12b7561b71 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -56,12 +56,15 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, write it to the flash, link it into the existing inode/fragment list */ -struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) +struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + struct jffs2_raw_inode *ri, const unsigned char *data, + uint32_t datalen, int alloc_mode) { struct jffs2_raw_node_ref *raw; struct jffs2_full_dnode *fn; size_t retlen; + uint32_t flash_ofs; struct kvec vecs[2]; int ret; int retried = 0; @@ -77,8 +80,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 vecs[1].iov_base = (unsigned char *)data; vecs[1].iov_len = datalen; - jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); - if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); } @@ -102,7 +103,9 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 retry: fn->raw = raw; - raw->flash_offset = flash_ofs; + raw->flash_offset = flash_ofs = write_ofs(c); + + jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { BUG_ON(!retried); @@ -147,19 +150,20 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, - &dummy, JFFS2_SUMMARY_INODE_SIZE); + ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &dummy, + JFFS2_SUMMARY_INODE_SIZE); } else { /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, - &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE); + ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy, + alloc_mode, JFFS2_SUMMARY_INODE_SIZE); down(&f->sem); } if (!ret) { + flash_ofs = write_ofs(c); D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); jffs2_dbg_acct_sanity_check(c,jeb); @@ -200,12 +204,15 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 return fn; } -struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode) +struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + struct jffs2_raw_dirent *rd, const unsigned char *name, + uint32_t namelen, int alloc_mode) { struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; size_t retlen; struct kvec vecs[2]; + uint32_t flash_ofs = write_ofs(c); int retried = 0; int ret; @@ -286,19 +293,20 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, - &dummy, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); + ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &dummy, + JFFS2_SUMMARY_DIRENT_SIZE(namelen)); } else { /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, - &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); + ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy, + alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); down(&f->sem); } if (!ret) { + flash_ofs = write_ofs(c); D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); @@ -339,14 +347,14 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn; unsigned char *comprbuf = NULL; uint16_t comprtype = JFFS2_COMPR_NONE; - uint32_t phys_ofs, alloclen; + uint32_t alloclen; uint32_t datalen, cdatalen; int retried = 0; retry: D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); - ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, + ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); @@ -374,7 +382,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); - fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY); + fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY); jffs2_free_comprbuf(comprbuf, buf); @@ -428,13 +436,13 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str struct jffs2_raw_dirent *rd; struct jffs2_full_dnode *fn; struct jffs2_full_dirent *fd; - uint32_t alloclen, phys_ofs; + uint32_t alloclen; int ret; /* Try to reserve enough space for both node and dirent. * Just the node will do for now, though */ - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, + ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); if (ret) { @@ -445,7 +453,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str ri->data_crc = cpu_to_je32(0); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); + fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL); D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", jemode_to_cpu(ri->mode))); @@ -464,7 +472,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { @@ -496,7 +504,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); - fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); + fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL); jffs2_free_raw_dirent(rd); @@ -525,7 +533,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, { struct jffs2_raw_dirent *rd; struct jffs2_full_dirent *fd; - uint32_t alloclen, phys_ofs; + uint32_t alloclen; int ret; if (1 /* alternative branch needs testing */ || @@ -536,7 +544,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, if (!rd) return -ENOMEM; - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { jffs2_free_raw_dirent(rd); @@ -560,7 +568,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); - fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); + fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_DELETION); jffs2_free_raw_dirent(rd); @@ -639,14 +647,14 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint { struct jffs2_raw_dirent *rd; struct jffs2_full_dirent *fd; - uint32_t alloclen, phys_ofs; + uint32_t alloclen; int ret; rd = jffs2_alloc_raw_dirent(); if (!rd) return -ENOMEM; - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { jffs2_free_raw_dirent(rd); @@ -672,7 +680,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); - fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); + fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL); jffs2_free_raw_dirent(rd); diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 76d166140381..008f91b1c171 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -49,9 +49,9 @@ * is used to be as a wrapper of do_verify_xattr_datum() and do_load_xattr_datum(). * If xd need to call do_verify_xattr_datum() at first, it's called before calling * do_load_xattr_datum(). The meanings of return value is same as do_verify_xattr_datum(). - * save_xattr_datum(c, xd, phys_ofs) + * save_xattr_datum(c, xd) * is used to write xdatum to medium. xd->version will be incremented. - * create_xattr_datum(c, xprefix, xname, xvalue, xsize, phys_ofs) + * create_xattr_datum(c, xprefix, xname, xvalue, xsize) * is used to create new xdatum and write to medium. * -------------------------------------------------- */ @@ -301,7 +301,7 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x return rc; } -static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd, uint32_t phys_ofs) +static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) { /* must be called under down_write(xattr_sem) */ struct jffs2_raw_xattr rx; @@ -309,6 +309,7 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x struct kvec vecs[2]; uint32_t length; int rc, totlen; + uint32_t phys_ofs = write_ofs(c); BUG_ON(!xd->xname); @@ -369,8 +370,7 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, int xprefix, const char *xname, - const char *xvalue, int xsize, - uint32_t phys_ofs) + const char *xvalue, int xsize) { /* must be called under down_write(xattr_sem) */ struct jffs2_xattr_datum *xd; @@ -419,7 +419,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, xd->value_len = xsize; xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len); - rc = save_xattr_datum(c, xd, phys_ofs); + rc = save_xattr_datum(c, xd); if (rc) { kfree(xd->xname); jffs2_free_xattr_datum(xd); @@ -446,9 +446,9 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, * delete_xattr_ref(c, ref) * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum * is refered by this xref become 0, delete_xattr_datum() is called later. - * save_xattr_ref(c, ref, phys_ofs) + * save_xattr_ref(c, ref) * is used to write xref to medium. - * create_xattr_ref(c, ic, xd, phys_ofs) + * create_xattr_ref(c, ic, xd) * is used to create a new xref and write to medium. * jffs2_xattr_delete_inode(c, ic) * is called to remove xrefs related to obsolete inode when inode is unlinked. @@ -554,12 +554,13 @@ static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *re jffs2_free_xattr_ref(ref); } -static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, uint32_t phys_ofs) +static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) { /* must be called under down_write(xattr_sem) */ struct jffs2_raw_node_ref *raw; struct jffs2_raw_xref rr; uint32_t length; + uint32_t phys_ofs = write_ofs(c); int ret; raw = jffs2_alloc_raw_node_ref(); @@ -604,7 +605,7 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, } static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, - struct jffs2_xattr_datum *xd, uint32_t phys_ofs) + struct jffs2_xattr_datum *xd) { /* must be called under down_write(xattr_sem) */ struct jffs2_xattr_ref *ref; @@ -616,7 +617,7 @@ static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct ref->ic = ic; ref->xd = xd; - ret = save_xattr_ref(c, ref, phys_ofs); + ret = save_xattr_ref(c, ref); if (ret) { jffs2_free_xattr_ref(ref); return ERR_PTR(ret); @@ -1062,7 +1063,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, struct jffs2_inode_cache *ic = f->inocache; struct jffs2_xattr_datum *xd; struct jffs2_xattr_ref *ref, *newref, **pref; - uint32_t phys_ofs, length, request; + uint32_t length, request; int rc; rc = check_xattr_ref_inode(c, ic); @@ -1070,7 +1071,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, return rc; request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size); - rc = jffs2_reserve_space(c, request, &phys_ofs, &length, + rc = jffs2_reserve_space(c, request, &length, ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE); if (rc) { JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); @@ -1117,7 +1118,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, goto out; } found: - xd = create_xattr_datum(c, xprefix, xname, buffer, size, phys_ofs); + xd = create_xattr_datum(c, xprefix, xname, buffer, size); if (IS_ERR(xd)) { rc = PTR_ERR(xd); goto out; @@ -1127,7 +1128,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, /* create xattr_ref */ request = PAD(sizeof(struct jffs2_raw_xref)); - rc = jffs2_reserve_space(c, request, &phys_ofs, &length, + rc = jffs2_reserve_space(c, request, &length, ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE); if (rc) { JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); @@ -1141,7 +1142,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, down_write(&c->xattr_sem); if (ref) *pref = ref->next; - newref = create_xattr_ref(c, ic, xd, phys_ofs); + newref = create_xattr_ref(c, ic, xd); if (IS_ERR(newref)) { if (ref) { ref->next = ic->xref; @@ -1170,7 +1171,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, * -------------------------------------------------- */ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) { - uint32_t phys_ofs, totlen, length, old_ofs; + uint32_t totlen, length, old_ofs; int rc = -EINVAL; down_write(&c->xattr_sem); @@ -1190,13 +1191,13 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt } else if (unlikely(rc < 0)) goto out; } - rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XATTR_SIZE); + rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); if (rc || length < totlen) { JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen); rc = rc ? rc : -EBADFD; goto out; } - rc = save_xattr_datum(c, xd, phys_ofs); + rc = save_xattr_datum(c, xd); if (!rc) dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n", xd->xid, xd->version, old_ofs, ref_offset(xd->node)); @@ -1208,7 +1209,7 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) { - uint32_t phys_ofs, totlen, length, old_ofs; + uint32_t totlen, length, old_ofs; int rc = -EINVAL; down_write(&c->xattr_sem); @@ -1219,14 +1220,14 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ if (totlen != sizeof(struct jffs2_raw_xref)) goto out; - rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XREF_SIZE); + rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); if (rc || length < totlen) { JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n", __FUNCTION__, rc, totlen); rc = rc ? rc : -EBADFD; goto out; } - rc = save_xattr_ref(c, ref, phys_ofs); + rc = save_xattr_ref(c, ref); if (!rc) dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n", ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node)); -- cgit v1.2.3-59-g8ed1b From 2f785402f39b96a077b6e62bf26164bfb8e0c980 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 24 May 2006 02:04:45 +0100 Subject: [JFFS2] Reduce visibility of raw_node_ref to upper layers of JFFS2 code. As the first step towards eliminating the ref->next_phys member and saving memory by using an _array_ of struct jffs2_raw_node_ref per eraseblock, stop the write functions from allocating their own refs; have them just _reserve_ the appropriate number instead. Then jffs2_link_node_ref() can just fill them in. Use a linked list of pre-allocated refs in the superblock, for now. Once we switch to an array, it'll just be a case of extending that array. Signed-off-by: David Woodhouse --- fs/jffs2/erase.c | 16 ++--- fs/jffs2/gc.c | 25 ++------ fs/jffs2/jffs2_fs_sb.h | 3 + fs/jffs2/malloc.c | 26 +++++++- fs/jffs2/nodelist.c | 51 ++++++++++------ fs/jffs2/nodelist.h | 19 +++--- fs/jffs2/nodemgmt.c | 39 ++++++------ fs/jffs2/scan.c | 77 +++++------------------ fs/jffs2/summary.c | 162 +++++++++++++++---------------------------------- fs/jffs2/wbuf.c | 26 +++----- fs/jffs2/write.c | 71 +++++++--------------- fs/jffs2/xattr.c | 38 +++--------- 12 files changed, 204 insertions(+), 349 deletions(-) (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 4616fed75730..f939f908b948 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -296,7 +296,7 @@ void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock * jffs2_remove_node_refs_from_ino_list(c, ref, jeb); /* else it was a non-inode node or already removed, so don't bother */ - jffs2_free_raw_node_ref(ref); + __jffs2_free_raw_node_ref(ref); } jeb->last_node = NULL; } @@ -351,7 +351,6 @@ fail: static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { - struct jffs2_raw_node_ref *marker_ref = NULL; size_t retlen; int ret; uint32_t bad_offset; @@ -384,11 +383,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb .totlen = cpu_to_je32(c->cleanmarker_size) }; - marker_ref = jffs2_alloc_raw_node_ref(); - if (!marker_ref) { - printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n"); - goto refile; - } + jffs2_prealloc_raw_node_refs(c, 1); marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); @@ -404,16 +399,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", jeb->offset, sizeof(marker), retlen); - jffs2_free_raw_node_ref(marker_ref); goto filebad; } /* Everything else got zeroed before the erase */ jeb->free_size = c->sector_size; - - marker_ref->flash_offset = jeb->offset | REF_NORMAL; - - jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL); + /* FIXME Special case for cleanmarker in empty block */ + jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL); } spin_lock(&c->erase_completion_lock); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index f9e982a65ac2..a22ff5df7fcc 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -528,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw) { union jffs2_node_union *node; - struct jffs2_raw_node_ref *nraw; size_t retlen; int ret; uint32_t phys_ofs, alloclen; @@ -618,30 +617,21 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, } } - nraw = jffs2_alloc_raw_node_ref(); - if (!nraw) { - ret = -ENOMEM; - goto out_node; - } - /* OK, all the CRCs are good; this node can just be copied as-is. */ retry: - nraw->flash_offset = phys_ofs = write_ofs(c); + phys_ofs = write_ofs(c); ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); if (ret || (retlen != rawlen)) { printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", - rawlen, nraw->flash_offset, ret, retlen); + rawlen, phys_ofs, ret, retlen); if (retlen) { - nraw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, nraw, rawlen, NULL); - jffs2_mark_node_obsolete(c, nraw); + jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL); } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); - jffs2_free_raw_node_ref(nraw); + printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs); } - if (!retried && (nraw = jffs2_alloc_raw_node_ref())) { + if (!retried) { /* Try to reallocate space and retry */ uint32_t dummy; struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; @@ -666,16 +656,13 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, goto retry; } D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); - jffs2_free_raw_node_ref(nraw); } - jffs2_free_raw_node_ref(nraw); if (!ret) ret = -EIO; goto out_node; } - nraw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, nraw, rawlen, ic); + jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic); jffs2_mark_node_obsolete(c, raw); D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 272fbea55192..67529f0a44dd 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h @@ -26,6 +26,9 @@ struct jffs2_inodirty; struct jffs2_sb_info { struct mtd_info *mtd; + struct jffs2_raw_node_ref *refs; + int reserved_refs; + uint32_t highest_ino; uint32_t checked_ino; diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index f2473fa2fd16..3df3250314a2 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -190,7 +190,29 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) kmem_cache_free(tmp_dnode_info_slab, x); } -struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) +int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr) +{ + struct jffs2_raw_node_ref *p = c->refs; + + dbg_memalloc("%d\n", nr); + + while (nr && p) { + p = p->next_in_ino; + nr--; + } + while (nr) { + p = __jffs2_alloc_raw_node_ref(); + if (!p) + return -ENOMEM; + p->next_in_ino = c->refs; + c->refs = p; + nr--; + } + c->reserved_refs = nr; + return 0; +} + +struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void) { struct jffs2_raw_node_ref *ret; ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); @@ -198,7 +220,7 @@ struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) return ret; } -void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) +void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) { dbg_memalloc("%p\n", x); kmem_cache_free(raw_node_ref_slab, x); diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index d25d4919ca97..1e6eabd730f2 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -953,13 +953,19 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) for (i=0; inr_blocks; i++) { this = c->blocks[i].first_node; - while(this) { + while (this) { next = this->next_phys; - jffs2_free_raw_node_ref(this); + __jffs2_free_raw_node_ref(this); this = next; } c->blocks[i].first_node = c->blocks[i].last_node = NULL; } + this = c->refs; + while (this) { + next = this->next_in_ino; + __jffs2_free_raw_node_ref(this); + this = next; + } } struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) @@ -1047,10 +1053,27 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) } } -void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_node_ref *ref, uint32_t len, - struct jffs2_inode_cache *ic) +struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb, + uint32_t ofs, uint32_t len, + struct jffs2_inode_cache *ic) { + struct jffs2_raw_node_ref *ref; + + /* These will be preallocated _very_ shortly. */ + ref = c->refs; + if (!c->refs) { + JFFS2_WARNING("Using non-preallocated refs!\n"); + ref = __jffs2_alloc_raw_node_ref(); + BUG_ON(!ref); + WARN_ON(1); + } else { + c->refs = ref->next_in_ino; + } + + ref->next_phys = NULL; + ref->flash_offset = ofs; + if (!jeb->first_node) jeb->first_node = ref; if (jeb->last_node) { @@ -1093,15 +1116,15 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, c->free_size -= len; jeb->free_size -= len; - ref->next_phys = NULL; #ifdef TEST_TOTLEN /* Set (and test) __totlen field... for now */ ref->__totlen = len; ref_totlen(c, jeb, ref); #endif + return ref; } -/* No locking. Do not use on a live file system */ +/* No locking, no reservation of 'ref'. Do not use on a live file system */ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size) { @@ -1121,18 +1144,10 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb jeb->dirty_size += size; jeb->free_size -= size; } else { - struct jffs2_raw_node_ref *ref; - ref = jffs2_alloc_raw_node_ref(); - if (!ref) - return -ENOMEM; - - ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; - ref->flash_offset |= REF_OBSOLETE; -#ifdef TEST_TOTLEN - ref->__totlen = size; -#endif + uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size; + ofs |= REF_OBSOLETE; - jffs2_link_node_ref(c, jeb, ref, size, NULL); + jffs2_link_node_ref(c, jeb, ofs, size, NULL); } return 0; diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 76f1b9419eea..7cc74d2ab4dc 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -318,9 +318,10 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); -void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_node_ref *ref, uint32_t len, - struct jffs2_inode_cache *ic); +struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb, + uint32_t ofs, uint32_t len, + struct jffs2_inode_cache *ic); extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_node_ref *ref); @@ -331,10 +332,9 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *len, int prio, uint32_t sumsize); int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *len, uint32_t sumsize); -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *new, - uint32_t len, - struct jffs2_inode_cache *ic); +struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, + uint32_t ofs, uint32_t len, + struct jffs2_inode_cache *ic); void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); @@ -378,8 +378,9 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void); void jffs2_free_raw_inode(struct jffs2_raw_inode *); struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void); void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *); -struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void); -void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *); +int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr); +struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void); +void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *); struct jffs2_node_frag *jffs2_alloc_node_frag(void); void jffs2_free_node_frag(struct jffs2_node_frag *); struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 8feb8749bc75..01bf2773fe4d 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -137,6 +137,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, } } spin_unlock(&c->erase_completion_lock); + if (!ret) + ret = jffs2_prealloc_raw_node_refs(c, 1); if (ret) up(&c->alloc_sem); return ret; @@ -158,6 +160,9 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, } } spin_unlock(&c->erase_completion_lock); + if (!ret) + ret = jffs2_prealloc_raw_node_refs(c, 1); + return ret; } @@ -381,30 +386,30 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, * Must be called with the alloc_sem held. */ -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, - uint32_t len, struct jffs2_inode_cache *ic) +struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, + uint32_t ofs, uint32_t len, + struct jffs2_inode_cache *ic) { struct jffs2_eraseblock *jeb; + struct jffs2_raw_node_ref *new; - jeb = &c->blocks[new->flash_offset / c->sector_size]; -#ifdef TEST_TOTLEN - new->__totlen = len; -#endif + jeb = &c->blocks[ofs / c->sector_size]; - D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); + D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", + ofs & ~3, ofs & 3, len)); #if 1 - /* we could get some obsolete nodes after nextblock was refiled - in wbuf.c */ - if ((c->nextblock || !ref_obsolete(new)) - &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) { + /* Allow non-obsolete nodes only to be added at the end of c->nextblock, + if c->nextblock is set. Note that wbuf.c will file obsolete nodes + even after refiling c->nextblock */ + if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE)) + && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) { printk(KERN_WARNING "argh. node added in wrong place\n"); - jffs2_free_raw_node_ref(new); - return -EINVAL; + return ERR_PTR(-EINVAL); } #endif spin_lock(&c->erase_completion_lock); - jffs2_link_node_ref(c, jeb, new, len, ic); + new = jffs2_link_node_ref(c, jeb, ofs, len, ic); if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) { /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ @@ -425,7 +430,7 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r spin_unlock(&c->erase_completion_lock); - return 0; + return new; } @@ -697,7 +702,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref } spin_unlock(&c->erase_completion_lock); - jffs2_free_raw_node_ref(n); + __jffs2_free_raw_node_ref(n); } /* Also merge with the previous node in the list, if there is one @@ -722,7 +727,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref jeb->gc_node=p; } p->next_phys = ref->next_phys; - jffs2_free_raw_node_ref(ref); + __jffs2_free_raw_node_ref(ref); } spin_unlock(&c->erase_completion_lock); } diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 6fce703c0543..87b0a416b6a0 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -317,7 +317,6 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc struct jffs2_summary *s) { struct jffs2_xattr_datum *xd; - struct jffs2_raw_node_ref *raw; uint32_t totlen, crc; int err; @@ -340,13 +339,8 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc return 0; } - raw = jffs2_alloc_raw_node_ref(); - if (!raw) - return -ENOMEM; - xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); if (IS_ERR(xd)) { - jffs2_free_raw_node_ref(raw); if (PTR_ERR(xd) == -EEXIST) { if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen))))) return err; @@ -358,12 +352,9 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc xd->name_len = rx->name_len; xd->value_len = je16_to_cpu(rx->value_len); xd->data_crc = je32_to_cpu(rx->data_crc); - xd->node = raw; - - raw->flash_offset = ofs | REF_PRISTINE; - jffs2_link_node_ref(c, jeb, raw, totlen, NULL); - /* FIXME */ raw->next_in_ino = (void *)xd; + xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL); + /* FIXME */ xd->node->next_in_ino = (void *)xd; if (jffs2_sum_active()) jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); @@ -377,7 +368,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock struct jffs2_summary *s) { struct jffs2_xattr_ref *ref; - struct jffs2_raw_node_ref *raw; uint32_t crc; int err; @@ -404,12 +394,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock if (!ref) return -ENOMEM; - raw = jffs2_alloc_raw_node_ref(); - if (!raw) { - jffs2_free_xattr_ref(ref); - return -ENOMEM; - } - /* BEFORE jffs2_build_xattr_subsystem() called, * ref->xid is used to store 32bit xid, xd is not used * ref->ino is used to store 32bit inode-number, ic is not used @@ -418,16 +402,13 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock * used to chain all xattr_ref object. It's re-chained to * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly. */ - ref->node = raw; ref->ino = je32_to_cpu(rr->ino); ref->xid = je32_to_cpu(rr->xid); ref->next = c->xref_temp; c->xref_temp = ref; - raw->flash_offset = ofs | REF_PRISTINE; - - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rr->totlen)), NULL); - /* FIXME */ raw->next_in_ino = (void *)ref; + ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL); + /* FIXME */ ref->node->next_in_ino = (void *)ref; if (jffs2_sum_active()) jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); @@ -597,6 +578,11 @@ scan_more: jffs2_dbg_acct_paranoia_check_nolock(c, jeb); + /* Make sure there are node refs available for use */ + err = jffs2_prealloc_raw_node_refs(c, 2); + if (err) + return err; + cond_resched(); if (ofs & 3) { @@ -839,14 +825,7 @@ scan_more: return err; ofs += PAD(sizeof(struct jffs2_unknown_node)); } else { - struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); - if (!marker_ref) { - printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n"); - return -ENOMEM; - } - marker_ref->flash_offset = ofs | REF_NORMAL; - - jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL); + jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL); ofs += PAD(c->cleanmarker_size); } @@ -884,14 +863,9 @@ scan_more: break; case JFFS2_FEATURE_RWCOMPAT_COPY: { - struct jffs2_raw_node_ref *ref; D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); - ref = jffs2_alloc_raw_node_ref(); - if (!ref) - return -ENOMEM; - ref->flash_offset = ofs | REF_PRISTINE; - jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen)), NULL); + jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL); /* We can't summarise nodes we don't grok */ jffs2_sum_disable_collecting(s); @@ -953,7 +927,6 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) { - struct jffs2_raw_node_ref *raw; struct jffs2_inode_cache *ic; uint32_t ino = je32_to_cpu(ri->ino); int err; @@ -969,12 +942,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc Which means that the _full_ amount of time to get to proper write mode with GC operational may actually be _longer_ than before. Sucks to be me. */ - raw = jffs2_alloc_raw_node_ref(); - if (!raw) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n"); - return -ENOMEM; - } - ic = jffs2_get_ino_cache(c, ino); if (!ic) { /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the @@ -988,21 +955,15 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen))))) return err; - jffs2_free_raw_node_ref(raw); return 0; } ic = jffs2_scan_make_ino_cache(c, ino); - if (!ic) { - jffs2_free_raw_node_ref(raw); + if (!ic) return -ENOMEM; - } } /* Wheee. It worked */ - - raw->flash_offset = ofs | REF_UNCHECKED; - - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(ri->totlen)), ic); + jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic); D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", je32_to_cpu(ri->ino), je32_to_cpu(ri->version), @@ -1021,7 +982,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) { - struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; struct jffs2_inode_cache *ic; uint32_t crc; @@ -1063,23 +1023,14 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo return err; return 0; } - raw = jffs2_alloc_raw_node_ref(); - if (!raw) { - jffs2_free_full_dirent(fd); - printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n"); - return -ENOMEM; - } ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); if (!ic) { jffs2_free_full_dirent(fd); - jffs2_free_raw_node_ref(raw); return -ENOMEM; } - raw->flash_offset = ofs | REF_PRISTINE; - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rd->totlen)), ic); + fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic); - fd->raw = raw; fd->next = NULL; fd->version = je32_to_cpu(rd->version); fd->ino = je32_to_cpu(rd->ino); diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 351ba9f8185e..ccb6803a6e41 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -369,22 +369,18 @@ no_mem: return -ENOMEM; } -static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - uint32_t offset) +static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb, + uint32_t ofs, uint32_t len, + struct jffs2_inode_cache *ic) { - struct jffs2_raw_node_ref *ref; /* If there was a gap, mark it dirty */ - if (offset > c->sector_size - jeb->free_size) { - int ret = jffs2_scan_dirty_space(c, jeb, offset - (c->sector_size - jeb->free_size)); - if (ret) - return NULL; + if ((ofs & ~3) > c->sector_size - jeb->free_size) { + /* Ew. Summary doesn't actually tell us explicitly about dirty space */ + jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size)); } - ref = jffs2_alloc_raw_node_ref(); - if (!ref) - return NULL; - ref->flash_offset = jeb->offset + offset; - return ref; + return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic); } /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ @@ -392,7 +388,6 @@ static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct j static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_summary *summary, uint32_t *pseudo_random) { - struct jffs2_raw_node_ref *raw; struct jffs2_inode_cache *ic; struct jffs2_full_dirent *fd; void *sp; @@ -404,6 +399,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras for (i=0; isum_num); i++) { dbg_summary("processing summary index %d\n", i); + /* Make sure there's a spare ref for dirty space */ + err = jffs2_prealloc_raw_node_refs(c, 2); + if (err) + return err; + switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { case JFFS2_NODETYPE_INODE: { struct jffs2_sum_inode_flash *spi; @@ -415,22 +415,14 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras jeb->offset + je32_to_cpu(spi->offset), jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen)); - raw = alloc_ref_at(c, jeb, je32_to_cpu(spi->offset)); - if (!raw) { - JFFS2_NOTICE("allocation of node reference failed\n"); - return -ENOMEM; - } - ic = jffs2_scan_make_ino_cache(c, ino); if (!ic) { JFFS2_NOTICE("scan_make_ino_cache failed\n"); - jffs2_free_raw_node_ref(raw); return -ENOMEM; } - raw->flash_offset |= REF_UNCHECKED; - - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen)), ic); + sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED, + PAD(je32_to_cpu(spi->totlen)), ic); *pseudo_random += je32_to_cpu(spi->version); @@ -455,24 +447,15 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras memcpy(&fd->name, spd->name, spd->nsize); fd->name[spd->nsize] = 0; - raw = alloc_ref_at(c, jeb, je32_to_cpu(spd->offset)); - if (!raw) { - jffs2_free_full_dirent(fd); - JFFS2_NOTICE("allocation of node reference failed\n"); - return -ENOMEM; - } - ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); if (!ic) { jffs2_free_full_dirent(fd); - jffs2_free_raw_node_ref(raw); return -ENOMEM; } - raw->flash_offset |= REF_PRISTINE; - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen)), ic); + fd->raw = sum_link_node_ref(c, jeb, je32_to_cpu(spd->offset) | REF_PRISTINE, + PAD(je32_to_cpu(spd->totlen)), ic); - fd->raw = raw; fd->next = NULL; fd->version = je32_to_cpu(spd->version); fd->ino = je32_to_cpu(spd->ino); @@ -497,15 +480,10 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras jeb->offset + je32_to_cpu(spx->offset), jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen), je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); - raw = alloc_ref_at(c, jeb, je32_to_cpu(spx->offset)); - if (!raw) { - JFFS2_NOTICE("allocation of node reference failed\n"); - return -ENOMEM; - } + xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); if (IS_ERR(xd)) { - jffs2_free_raw_node_ref(raw); if (PTR_ERR(xd) == -EEXIST) { /* a newer version of xd exists */ if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen)))) @@ -516,12 +494,10 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras JFFS2_NOTICE("allocation of xattr_datum failed\n"); return PTR_ERR(xd); } - xd->node = raw; - raw->flash_offset |= REF_UNCHECKED; - - jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)), NULL); - /* FIXME */ raw->next_in_ino = (void *)xd; + xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED, + PAD(je32_to_cpu(spx->totlen)), NULL); + /* FIXME */ xd->node->next_in_ino = (void *)xd; *pseudo_random += je32_to_cpu(spx->xid); sp += JFFS2_SUMMARY_XATTR_SIZE; @@ -537,29 +513,21 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras jeb->offset + je32_to_cpu(spr->offset), jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref))); - raw = alloc_ref_at(c, jeb, je32_to_cpu(spr->offset)); - if (!raw) { - JFFS2_NOTICE("allocation of node reference failed\n"); - return -ENOMEM; - } ref = jffs2_alloc_xattr_ref(); if (!ref) { JFFS2_NOTICE("allocation of xattr_datum failed\n"); - jffs2_free_raw_node_ref(raw); return -ENOMEM; } ref->ino = 0xfffffffe; ref->xid = 0xfffffffd; - ref->node = raw; ref->next = c->xref_temp; c->xref_temp = ref; - raw->flash_offset |= REF_UNCHECKED; + ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED, + PAD(sizeof(struct jffs2_raw_xref)), NULL); + /* FIXME */ ref->node->next_in_ino = (void *)ref; - jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)), NULL); - /* FIXME */ raw->next_in_ino = (void *)ref; - - *pseudo_random += raw->flash_offset; + *pseudo_random += ref->node->flash_offset; sp += JFFS2_SUMMARY_XREF_SIZE; break; @@ -584,7 +552,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras } } } - return 0; } @@ -594,7 +561,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb uint32_t *pseudo_random) { struct jffs2_unknown_node crcnode; - struct jffs2_raw_node_ref *cache_ref; int ret, ofs; uint32_t crc; int err; @@ -650,16 +616,8 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) return err; } else { - struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); - - if (!marker_ref) { - JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); - return -ENOMEM; - } - - marker_ref->flash_offset = jeb->offset | REF_NORMAL; - - jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr), NULL); + jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, + je32_to_cpu(summary->cln_mkr), NULL); } } @@ -672,16 +630,11 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb return ret; /* real error */ /* for PARANOIA_CHECK */ - cache_ref = alloc_ref_at(c, jeb, ofs); - - if (!cache_ref) { - JFFS2_NOTICE("Failed to allocate node ref for cache\n"); - return -ENOMEM; - } - - cache_ref->flash_offset |= REF_NORMAL; + ret = jffs2_prealloc_raw_node_refs(c, 1); + if (ret) + return ret; - jffs2_link_node_ref(c, jeb, cache_ref, sumsize, NULL); + jffs2_link_node_ref(c, jeb, (jeb->offset + ofs) | REF_NORMAL, sumsize, NULL); if (unlikely(jeb->free_size)) { JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n", @@ -709,6 +662,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock union jffs2_sum_mem *temp; struct jffs2_sum_marker *sm; struct kvec vecs[2]; + uint32_t sum_ofs; void *wpage; int ret; size_t retlen; @@ -821,36 +775,31 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock vecs[1].iov_base = c->summary->sum_buf; vecs[1].iov_len = datasize; + sum_ofs = jeb->offset + c->sector_size - jeb->free_size; + dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", - jeb->offset + c->sector_size - jeb->free_size); + sum_ofs); - spin_unlock(&c->erase_completion_lock); - ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - - jeb->free_size, &retlen, 0); + ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0); if (ret || (retlen != infosize)) { - struct jffs2_raw_node_ref *ref; JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", - infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); + infosize, sum_ofs, ret, retlen); /* Waste remaining space */ - ref = jffs2_alloc_raw_node_ref(); - if (ref) { - spin_lock(&c->erase_completion_lock); - - ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; - ref->flash_offset |= REF_OBSOLETE; - - jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size, NULL); - } + spin_lock(&c->erase_completion_lock); + jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL); + spin_unlock(&c->erase_completion_lock); c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; - return 1; + return 0; } spin_lock(&c->erase_completion_lock); + jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL); + spin_unlock(&c->erase_completion_lock); return 0; } @@ -859,12 +808,15 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) { - struct jffs2_raw_node_ref *summary_ref; - int datasize, infosize, padsize, ret; + int datasize, infosize, padsize; struct jffs2_eraseblock *jeb; + int ret; dbg_summary("called\n"); + spin_unlock(&c->erase_completion_lock); + jffs2_prealloc_raw_node_refs(c, 1); + jeb = c->nextblock; if (!c->summary->sum_num || !c->summary->sum_list_head) { @@ -888,22 +840,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) } ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); - if (ret) - return 0; /* can't write out summary, block is marked as NOSUM_SIZE */ - - /* for ACCT_PARANOIA_CHECK */ - spin_unlock(&c->erase_completion_lock); - summary_ref = jffs2_alloc_raw_node_ref(); - - if (!summary_ref) { - JFFS2_NOTICE("Failed to allocate node ref for summary\n"); - return -ENOMEM; - } - - summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; - spin_lock(&c->erase_completion_lock); - jffs2_link_node_ref(c, jeb, summary_ref, infosize, NULL); - - return 0; + return ret; } diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 916c87d3393b..0d7abb260489 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -179,6 +179,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) unsigned char *buf; uint32_t start, end, ofs, len; + if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1)) + return; + spin_lock(&c->erase_completion_lock); jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; @@ -306,17 +309,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); kfree(buf); - if (retlen) { - struct jffs2_raw_node_ref *raw2; - - raw2 = jffs2_alloc_raw_node_ref(); - if (!raw2) - return; - - raw2->flash_offset = ofs | REF_OBSOLETE; + if (retlen) + jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, *first_raw), NULL); - jffs2_add_physical_node_ref(c, raw2, ref_totlen(c, jeb, *first_raw), NULL); - } return; } printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs); @@ -428,6 +423,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) if (!c->wbuf_len) /* already checked c->wbuf above */ return 0; + if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1)) + return -ENOMEM; + /* claim remaining space on the page this happens, if we have a change to a new block, or if fsync forces us to flush the writebuffer. @@ -485,7 +483,6 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) /* Adjust free size of the block if we padded. */ if (pad) { struct jffs2_eraseblock *jeb; - struct jffs2_raw_node_ref *ref; uint32_t waste = c->wbuf_pagesize - c->wbuf_len; jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; @@ -503,15 +500,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) jeb->offset, jeb->free_size); BUG(); } - ref = jffs2_alloc_raw_node_ref(); - if (!ref) - return -ENOMEM; - ref->flash_offset = c->wbuf_ofs + c->wbuf_len; - ref->flash_offset |= REF_OBSOLETE; spin_lock(&c->erase_completion_lock); - jffs2_link_node_ref(c, jeb, ref, waste, NULL); + jffs2_link_node_ref(c, jeb, (c->wbuf_ofs + c->wbuf_len) | REF_OBSOLETE, waste, NULL); /* FIXME: that made it count as dirty. Convert to wasted */ jeb->dirty_size -= waste; c->dirty_size -= waste; diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 0e12b7561b71..67176792e138 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -61,7 +61,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 uint32_t datalen, int alloc_mode) { - struct jffs2_raw_node_ref *raw; struct jffs2_full_dnode *fn; size_t retlen; uint32_t flash_ofs; @@ -83,27 +82,16 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); } - raw = jffs2_alloc_raw_node_ref(); - if (!raw) - return ERR_PTR(-ENOMEM); fn = jffs2_alloc_full_dnode(); - if (!fn) { - jffs2_free_raw_node_ref(raw); + if (!fn) return ERR_PTR(-ENOMEM); - } - - fn->ofs = je32_to_cpu(ri->offset); - fn->size = je32_to_cpu(ri->dsize); - fn->frags = 0; /* check number of valid vecs */ if (!datalen || !data) cnt = 1; retry: - fn->raw = raw; - - raw->flash_offset = flash_ofs = write_ofs(c); + flash_ofs = write_ofs(c); jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); @@ -130,14 +118,11 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 seem corrupted, in which case the scan would skip over any node we write before the original intended end of this node */ - raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), NULL); - jffs2_mark_node_obsolete(c, raw); + jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL); } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); - jffs2_free_raw_node_ref(raw); + printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs); } - if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { + if (!retried && alloc_mode != ALLOC_NORETRY) { /* Try to reallocate space and retry */ uint32_t dummy; struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; @@ -172,7 +157,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 goto retry; } D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); - jffs2_free_raw_node_ref(raw); } /* Release the full_dnode which is now useless, and return */ jffs2_free_full_dnode(fn); @@ -186,14 +170,17 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { - raw->flash_offset |= REF_PRISTINE; + flash_ofs |= REF_PRISTINE; } else { - raw->flash_offset |= REF_NORMAL; + flash_ofs |= REF_NORMAL; } - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), f->inocache); + fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache); + fn->ofs = je32_to_cpu(ri->offset); + fn->size = je32_to_cpu(ri->dsize); + fn->frags = 0; D1(printk(KERN_DEBUG "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", - flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), + flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); @@ -208,11 +195,10 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, int alloc_mode) { - struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; size_t retlen; struct kvec vecs[2]; - uint32_t flash_ofs = write_ofs(c); + uint32_t flash_ofs; int retried = 0; int ret; @@ -223,26 +209,16 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); BUG(); - } - ); + }); vecs[0].iov_base = rd; vecs[0].iov_len = sizeof(*rd); vecs[1].iov_base = (unsigned char *)name; vecs[1].iov_len = namelen; - jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); - - raw = jffs2_alloc_raw_node_ref(); - - if (!raw) - return ERR_PTR(-ENOMEM); - fd = jffs2_alloc_full_dirent(namelen+1); - if (!fd) { - jffs2_free_raw_node_ref(raw); + if (!fd) return ERR_PTR(-ENOMEM); - } fd->version = je32_to_cpu(rd->version); fd->ino = je32_to_cpu(rd->ino); @@ -252,9 +228,9 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff fd->name[namelen]=0; retry: - fd->raw = raw; + flash_ofs = write_ofs(c); - raw->flash_offset = flash_ofs; + jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { BUG_ON(!retried); @@ -273,14 +249,11 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff sizeof(*rd)+namelen, flash_ofs, ret, retlen); /* Mark the space as dirtied */ if (retlen) { - raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), NULL); - jffs2_mark_node_obsolete(c, raw); + jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL); } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); - jffs2_free_raw_node_ref(raw); + printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs); } - if (!retried && (raw = jffs2_alloc_raw_node_ref())) { + if (!retried) { /* Try to reallocate space and retry */ uint32_t dummy; struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; @@ -313,15 +286,13 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff goto retry; } D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); - jffs2_free_raw_node_ref(raw); } /* Release the full_dnode which is now useless, and return */ jffs2_free_full_dirent(fd); return ERR_PTR(ret?ret:-EIO); } /* Mark the space used */ - raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), f->inocache); + fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache); if (retried) { jffs2_dbg_acct_sanity_check(c,NULL); diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 008f91b1c171..2255f1367bd5 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -304,8 +304,8 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) { /* must be called under down_write(xattr_sem) */ - struct jffs2_raw_xattr rx; struct jffs2_raw_node_ref *raw; + struct jffs2_raw_xattr rx; struct kvec vecs[2]; uint32_t length; int rc, totlen; @@ -319,11 +319,6 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x vecs[1].iov_len = xd->name_len + 1 + xd->value_len; totlen = vecs[0].iov_len + vecs[1].iov_len; - raw = jffs2_alloc_raw_node_ref(); - if (!raw) - return -ENOMEM; - raw->flash_offset = phys_ofs; - /* Setup raw-xattr */ rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); @@ -343,19 +338,14 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n", rc, totlen, length, phys_ofs); rc = rc ? rc : -EIO; - if (length) { - raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL); - jffs2_mark_node_obsolete(c, raw); - } else { - jffs2_free_raw_node_ref(raw); - } + if (length) + jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL); + return rc; } /* success */ - raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL); + raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL); /* FIXME */ raw->next_in_ino = (void *)xd; if (xd->node) @@ -563,11 +553,6 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) uint32_t phys_ofs = write_ofs(c); int ret; - raw = jffs2_alloc_raw_node_ref(); - if (!raw) - return -ENOMEM; - raw->flash_offset = phys_ofs; - rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); rr.totlen = cpu_to_je32(PAD(sizeof(rr))); @@ -582,18 +567,13 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n", ret, sizeof(rr), length, phys_ofs); ret = ret ? ret : -EIO; - if (length) { - raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL); - jffs2_mark_node_obsolete(c, raw); - } else { - jffs2_free_raw_node_ref(raw); - } + if (length) + jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL); + return ret; } - raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL); + raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL); /* FIXME */ raw->next_in_ino = (void *)ref; if (ref->node) delete_xattr_ref_node(c, ref); -- cgit v1.2.3-59-g8ed1b From 89291a9d5b70778e49e2563247c6c7e3efac9b14 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 25 May 2006 13:30:24 +0100 Subject: [JFFS2] Fix 64-bit size_t problems in XATTR code. Signed-off-by: David Woodhouse --- fs/jffs2/scan.c | 2 +- fs/jffs2/xattr.c | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'fs/jffs2/xattr.c') diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 404ba6e48581..3fb0e7e82cf2 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -379,7 +379,7 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock } if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) { - JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", + JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%zd\n", ofs, je32_to_cpu(rr->totlen), PAD(sizeof(struct jffs2_raw_xref))); if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen)))) diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 2255f1367bd5..2d82e250be34 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -111,7 +111,7 @@ static void delete_xattr_datum_node(struct jffs2_sb_info *c, struct jffs2_xattr_ { /* must be called under down_write(xattr_sem) */ struct jffs2_raw_xattr rx; - uint32_t length; + size_t length; int rc; if (!xd->node) { @@ -124,14 +124,14 @@ static void delete_xattr_datum_node(struct jffs2_sb_info *c, struct jffs2_xattr_ sizeof(struct jffs2_unknown_node), &length, (char *)&rx); if (rc || length != sizeof(struct jffs2_unknown_node)) { - JFFS2_ERROR("jffs2_flash_read()=%d, req=%u, read=%u at %#08x\n", + JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", rc, sizeof(struct jffs2_unknown_node), length, ref_offset(xd->node)); } rc = jffs2_flash_write(c, ref_offset(xd->node), sizeof(rx), &length, (char *)&rx); if (rc || length != sizeof(struct jffs2_raw_xattr)) { - JFFS2_ERROR("jffs2_flash_write()=%d, req=%u, wrote=%u ar %#08x\n", + JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu ar %#08x\n", rc, sizeof(rx), length, ref_offset(xd->node)); } } @@ -169,7 +169,7 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx); if (rc || readlen != sizeof(rx)) { - JFFS2_WARNING("jffs2_flash_read()=%d, req=%u, read=%u at %#08x\n", + JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", rc, sizeof(rx), readlen, ref_offset(xd->node)); return rc ? rc : -EIO; } @@ -240,7 +240,7 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum length, &readlen, data); if (ret || length!=readlen) { - JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%d, at %#08x\n", + JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%zu, at %#08x\n", ret, length, readlen, ref_offset(xd->node)); kfree(data); return ret ? ret : -EIO; @@ -307,7 +307,7 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x struct jffs2_raw_node_ref *raw; struct jffs2_raw_xattr rx; struct kvec vecs[2]; - uint32_t length; + size_t length; int rc, totlen; uint32_t phys_ofs = write_ofs(c); @@ -335,7 +335,7 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0); if (rc || totlen != length) { - JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n", + JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n", rc, totlen, length, phys_ofs); rc = rc ? rc : -EIO; if (length) @@ -459,7 +459,7 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr); if (rc || sizeof(rr) != readlen) { - JFFS2_WARNING("jffs2_flash_read()=%d, req=%u, read=%u, at %#08x\n", + JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n", rc, sizeof(rr), readlen, ref_offset(ref->node)); return rc ? rc : -EIO; } @@ -475,7 +475,7 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) { JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, " - "nodetype=%#04x/%#04x, totlen=%u/%u\n", + "nodetype=%#04x/%#04x, totlen=%u/%zu\n", ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, je32_to_cpu(rr.totlen), PAD(sizeof(rr))); @@ -502,7 +502,7 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) { struct jffs2_raw_xref rr; - uint32_t length; + size_t length; int rc; if (jffs2_sum_active()) { @@ -511,14 +511,14 @@ static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_re sizeof(struct jffs2_unknown_node), &length, (char *)&rr); if (rc || length != sizeof(struct jffs2_unknown_node)) { - JFFS2_ERROR("jffs2_flash_read()=%d, req=%u, read=%u at %#08x\n", + JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", rc, sizeof(struct jffs2_unknown_node), length, ref_offset(ref->node)); } rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr), &length, (char *)&rr); if (rc || length != sizeof(struct jffs2_raw_xref)) { - JFFS2_ERROR("jffs2_flash_write()=%d, req=%u, wrote=%u at %#08x\n", + JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu at %#08x\n", rc, sizeof(rr), length, ref_offset(ref->node)); } } @@ -549,7 +549,7 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) /* must be called under down_write(xattr_sem) */ struct jffs2_raw_node_ref *raw; struct jffs2_raw_xref rr; - uint32_t length; + size_t length; uint32_t phys_ofs = write_ofs(c); int ret; @@ -564,7 +564,7 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr); if (ret || sizeof(rr) != length) { - JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n", + JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n", ret, sizeof(rr), length, phys_ofs); ret = ret ? ret : -EIO; if (length) -- cgit v1.2.3-59-g8ed1b