*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: readinode.c,v 1.135 2005/08/01 12:05:19 dedekind Exp $
+ * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $
*
*/
while (ref && ref->next_in_ino) {
if (!ref_obsolete(ref))
return ref;
- JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref));
+ dbg_noderef("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref));
ref = ref->next_in_ino;
}
return NULL;
* negative error code on failure.
*/
static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
- struct jffs2_raw_dirent *rd, uint32_t read, struct jffs2_full_dirent **fdp,
+ struct jffs2_raw_dirent *rd, size_t read, struct jffs2_full_dirent **fdp,
uint32_t *latest_mctime, uint32_t *mctime_ver)
{
struct jffs2_full_dirent *fd;
-
+
/* The direntry nodes are checked during the flash scanning */
BUG_ON(ref_flags(ref) == REF_UNCHECKED);
/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
BUG_ON(ref_obsolete(ref));
-
+
/* Sanity check */
if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
return 1;
}
-
+
fd = jffs2_alloc_full_dirent(rd->nsize + 1);
if (unlikely(!fd))
return -ENOMEM;
fd->type = rd->type;
/* Pick out the mctime of the latest dirent */
- if(fd->version > *mctime_ver) {
+ if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) {
*mctime_ver = fd->version;
*latest_mctime = je32_to_cpu(rd->mctime);
}
- /*
+ /*
* Copy as much of the name as possible from the raw
* dirent we've already read from the flash.
*/
if (read > sizeof(*rd))
memcpy(&fd->name[0], &rd->name[0],
min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) ));
-
+
/* Do we need to copy any more of the name directly from the flash? */
if (rd->nsize + sizeof(*rd) > read) {
/* FIXME: point() */
int err;
int already = read - sizeof(*rd);
-
- err = jffs2_flash_read(c, (ref_offset(ref)) + read,
+
+ err = jffs2_flash_read(c, (ref_offset(ref)) + read,
rd->nsize - already, &read, &fd->name[already]);
if (unlikely(read != rd->nsize - already) && likely(!err))
return -EIO;
-
+
if (unlikely(err)) {
JFFS2_ERROR("read remainder of name: error %d\n", err);
jffs2_free_full_dirent(fd);
return -EIO;
}
}
-
+
fd->nhash = full_name_hash(fd->name, rd->nsize);
fd->next = NULL;
fd->name[rd->nsize] = '\0';
-
+
/*
* Wheee. We now have a complete jffs2_full_dirent structure, with
- * the name in it and everything. Link it into the list
+ * the name in it and everything. Link it into the list
*/
jffs2_add_fd_to_list(c, fd, fdp);
struct jffs2_tmp_dnode_info *tn;
uint32_t len, csize;
int ret = 1;
-
+
/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
BUG_ON(ref_obsolete(ref));
tn->partial_crc = 0;
csize = je32_to_cpu(rd->csize);
-
+
/* If we've never checked the CRCs on this node, check them now */
if (ref_flags(ref) == REF_UNCHECKED) {
uint32_t crc;
ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
goto free_out;
}
-
+
/* Sanity checks */
if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
buf = (unsigned char *)rd + sizeof(*rd);
/* len will be the read data length */
len = min_t(uint32_t, rdlen - sizeof(*rd), csize);
-
- if (len)
- tn->partial_crc = crc = crc32(0, buf, len);
+ tn->partial_crc = crc32(0, buf, len);
+
+ dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize);
/* If we actually calculated the whole data CRC
* and it is wrong, drop the node. */
- if (unlikely(tn->partial_crc
- != je32_to_cpu(rd->data_crc)) &&
- len == csize)
+ if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
+ JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
+ ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc));
goto free_out;
+ }
} else if (csize == 0) {
/*
*/
struct jffs2_eraseblock *jeb;
- JFFS2_DBG_READINODE("the node has no data.\n");
+ dbg_readinode("the node has no data.\n");
jeb = &c->blocks[ref->flash_offset / c->sector_size];
len = ref_totlen(c, jeb, ref);
ret = -ENOMEM;
goto free_out;
}
-
+
tn->version = je32_to_cpu(rd->version);
tn->fn->ofs = je32_to_cpu(rd->offset);
tn->data_crc = je32_to_cpu(rd->data_crc);
tn->csize = csize;
tn->fn->raw = ref;
-
+
/* There was a bug where we wrote hole nodes out with
csize/dsize swapped. Deal with it */
if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize)
else // normal case...
tn->fn->size = je32_to_cpu(rd->dsize);
- JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x\n",
- ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize));
-
+ dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
+ ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
+
jffs2_add_tn_to_tree(tn, tnp);
return 0;
{
/* We don't mark unknown nodes as REF_UNCHECKED */
BUG_ON(ref_flags(ref) == REF_UNCHECKED);
-
+
un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) {
bufstart = buf + *rdlen;
len = right_size - *rdlen;
}
-
- JFFS2_DBG_READINODE("read more %d bytes.", len);
+
+ dbg_readinode("read more %d bytes\n", len);
err = jffs2_flash_read(c, offs, len, &retlen, bufstart);
if (err) {
"error code: %d.\n", len, offs, err);
return err;
}
-
+
if (retlen < len) {
JFFS2_ERROR("short read at %#08x: %d instead of %d.\n",
offs, retlen, len);
int len, err;
*mctime_ver = 0;
-
- JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino);
+
+ dbg_readinode("ino #%u\n", f->inocache->ino);
if (jffs2_is_writebuffered(c)) {
/*
buf = kmalloc(len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
-
+
spin_lock(&c->erase_completion_lock);
valid_ref = jffs2_first_valid_node(f->inocache->nodes);
if (!valid_ref && f->inocache->ino != 1)
* size = JFFS2_MIN_NODE_HEADER.
*/
if (jffs2_is_writebuffered(c)) {
- /*
+ /*
* We treat 'buf' as 2 adjacent wbufs. We want to
* adjust bufstart such as it points to the
* beginning of the node within this wbuf.
bufstart = buf + (ref_offset(ref) % c->wbuf_pagesize);
/* We will read either one wbuf or 2 wbufs. */
len = c->wbuf_pagesize - (bufstart - buf);
- if (JFFS2_MIN_NODE_HEADER +
- (int)(bufstart - buf) > c->wbuf_pagesize) {
- /* The header spans the border of the
- * first wbuf */
+ if (JFFS2_MIN_NODE_HEADER + (int)(bufstart - buf) > c->wbuf_pagesize) {
+ /* The header spans the border of the first wbuf */
len += c->wbuf_pagesize;
}
} else {
len = JFFS2_MIN_NODE_HEADER;
}
- JFFS2_DBG_READINODE("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref));
+ dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref));
/* FIXME: point() */
err = jffs2_flash_read(c, ref_offset(ref), len,
JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err);
goto free_out;
}
-
+
if (retlen < len) {
JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len);
err = -EIO;
goto free_out;
}
-
+
node = (union jffs2_node_union *)bufstart;
-
+
switch (je16_to_cpu(node->u.nodetype)) {
-
+
case JFFS2_NODETYPE_DIRENT:
if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) {
if (unlikely(err))
goto free_out;
}
-
+
err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver);
if (err == 1) {
jffs2_mark_node_obsolete(c, ref);
break;
} else if (unlikely(err))
goto free_out;
-
+
if (je32_to_cpu(node->d.version) > *highest_version)
*highest_version = je32_to_cpu(node->d.version);
break;
case JFFS2_NODETYPE_INODE:
-
+
if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) {
err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart);
if (unlikely(err))
if (je32_to_cpu(node->i.version) > *highest_version)
*highest_version = je32_to_cpu(node->i.version);
-
+
break;
default:
if (unlikely(err))
goto free_out;
}
-
+
err = read_unknown(c, ref, &node->u);
if (err == 1) {
jffs2_mark_node_obsolete(c, ref);
*fdp = ret_fd;
kfree(buf);
- JFFS2_DBG_READINODE("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n",
+ dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n",
f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver);
return 0;
return err;
}
-static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
struct jffs2_inode_info *f,
struct jffs2_raw_inode *latest_node)
{
size_t retlen;
int ret;
- JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
+ dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
/* Grab all nodes relevant to this ino */
ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);
fn = tn->fn;
ret = 1;
- JFFS2_DBG_READINODE("consider node ver %u, phys offset "
+ dbg_readinode("consider node ver %u, phys offset "
"%#08x(%d), range %u-%u.\n", tn->version,
ref_offset(fn->raw), ref_flags(fn->raw),
fn->ofs, fn->ofs + fn->size);
ret = 0; /* Prevent freeing the metadata update node */
} else
jffs2_mark_node_obsolete(c, fn->raw);
-
+
BUG_ON(rb->rb_left);
if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
/* We were then left-hand child of our parent. We need
jffs2_free_tmp_dnode_info(tn);
if (ret) {
- JFFS2_DBG_READINODE("delete dnode %u-%u.\n",
+ dbg_readinode("delete dnode %u-%u.\n",
fn->ofs, fn->ofs + fn->size);
jffs2_free_full_dnode(fn);
}
}
break;
-
+
case S_IFREG:
/* If it was a regular file, truncate it to the latest node's isize */
jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
jffs2_do_clear_inode(c, f);
return -ENOMEM;
}
-
+
ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),
je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);
-
+
if (ret || retlen != je32_to_cpu(latest_node->csize)) {
if (retlen != je32_to_cpu(latest_node->csize))
ret = -EIO;
}
f->target[je32_to_cpu(latest_node->csize)] = '\0';
- JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target);
+ dbg_readinode("symlink's target '%s' cached\n", f->target);
}
-
+
/* fall through... */
case S_IFBLK:
}
/* Scan the list of all nodes present for this ino, build map of versions, etc. */
-int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
uint32_t ino, struct jffs2_raw_inode *latest_node)
{
- JFFS2_DBG_READINODE("read inode #%u\n", ino);
+ dbg_readinode("read inode #%u\n", ino);
retry_inocache:
spin_lock(&c->inocache_lock);
case INO_STATE_CHECKEDABSENT:
f->inocache->state = INO_STATE_READING;
break;
-
+
case INO_STATE_CHECKING:
case INO_STATE_GC:
/* If it's in either of these states, we need
to wait for whoever's got it to finish and
put it back. */
- JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state);
+ dbg_readinode("waiting for ino #%u in state %d\n", ino, f->inocache->state);
sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
goto retry_inocache;
JFFS2_ERROR("cannot allocate inocache for root inode\n");
return -ENOMEM;
}
- JFFS2_DBG_READINODE("creating inocache for root inode\n");
+ dbg_readinode("creating inocache for root inode\n");
memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
f->inocache->ino = f->inocache->nlink = 1;
f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
kfree(f->target);
f->target = NULL;
}
-
+
fds = f->dents;
while(fds) {
fd = fds;