summaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/LICENCE7
-rw-r--r--fs/jffs2/Makefile1
-rw-r--r--fs/jffs2/README.Locking1
-rw-r--r--fs/jffs2/TODO3
-rw-r--r--fs/jffs2/acl.c3
-rw-r--r--fs/jffs2/acl.h3
-rw-r--r--fs/jffs2/background.c4
-rw-r--r--fs/jffs2/build.c4
-rw-r--r--fs/jffs2/compr.c144
-rw-r--r--fs/jffs2/compr.h17
-rw-r--r--fs/jffs2/compr_rtime.c3
-rw-r--r--fs/jffs2/compr_rubin.c81
-rw-r--r--fs/jffs2/compr_rubin.h21
-rw-r--r--fs/jffs2/compr_zlib.c4
-rw-r--r--fs/jffs2/comprtest.c307
-rw-r--r--fs/jffs2/debug.c5
-rw-r--r--fs/jffs2/debug.h5
-rw-r--r--fs/jffs2/dir.c4
-rw-r--r--fs/jffs2/erase.c6
-rw-r--r--fs/jffs2/file.c4
-rw-r--r--fs/jffs2/fs.c16
-rw-r--r--fs/jffs2/gc.c7
-rw-r--r--fs/jffs2/ioctl.c4
-rw-r--r--fs/jffs2/jffs2_fs_i.h11
-rw-r--r--fs/jffs2/jffs2_fs_sb.h11
-rw-r--r--fs/jffs2/malloc.c4
-rw-r--r--fs/jffs2/nodelist.c482
-rw-r--r--fs/jffs2/nodelist.h40
-rw-r--r--fs/jffs2/nodemgmt.c9
-rw-r--r--fs/jffs2/os-linux.h10
-rw-r--r--fs/jffs2/pushpull.h72
-rw-r--r--fs/jffs2/read.c4
-rw-r--r--fs/jffs2/readinode.c851
-rw-r--r--fs/jffs2/scan.c62
-rw-r--r--fs/jffs2/security.c3
-rw-r--r--fs/jffs2/summary.c12
-rw-r--r--fs/jffs2/summary.h10
-rw-r--r--fs/jffs2/super.c6
-rw-r--r--fs/jffs2/symlink.c5
-rw-r--r--fs/jffs2/wbuf.c39
-rw-r--r--fs/jffs2/write.c7
-rw-r--r--fs/jffs2/writev.c4
-rw-r--r--fs/jffs2/xattr.c3
-rw-r--r--fs/jffs2/xattr.h3
-rw-r--r--fs/jffs2/xattr_trusted.c3
-rw-r--r--fs/jffs2/xattr_user.c3
46 files changed, 922 insertions, 1386 deletions
diff --git a/fs/jffs2/LICENCE b/fs/jffs2/LICENCE
index cd81d83e4ad..56288590813 100644
--- a/fs/jffs2/LICENCE
+++ b/fs/jffs2/LICENCE
@@ -1,7 +1,7 @@
The files in this directory and elsewhere which refer to this LICENCE
file are part of JFFS2, the Journalling Flash File System v2.
- Copyright (C) 2001, 2002 Red Hat, Inc.
+ Copyright © 2001-2007 Red Hat, Inc. and others
JFFS2 is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
@@ -28,8 +28,3 @@ of the GNU General Public License.
This exception does not invalidate any other reasons why a work based on
this file might be covered by the GNU General Public License.
-For information on obtaining alternative licences for JFFS2, see
-http://sources.redhat.com/jffs2/jffs2-licence.html
-
-
- $Id: LICENCE,v 1.1 2002/05/20 14:56:37 dwmw2 Exp $
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index 7f28ee0bd13..c32b241e3d9 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -1,7 +1,6 @@
#
# Makefile for the Linux Journalling Flash File System v2 (JFFS2)
#
-# $Id: Makefile.common,v 1.11 2005/09/07 08:34:53 havasi Exp $
#
obj-$(CONFIG_JFFS2_FS) += jffs2.o
diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
index c8f0bd64e53..d14d5a4dc5a 100644
--- a/fs/jffs2/README.Locking
+++ b/fs/jffs2/README.Locking
@@ -1,4 +1,3 @@
- $Id: README.Locking,v 1.12 2005/04/13 13:22:35 dwmw2 Exp $
JFFS2 LOCKING DOCUMENTATION
---------------------------
diff --git a/fs/jffs2/TODO b/fs/jffs2/TODO
index d0e23b26fa5..5d3ea4070f0 100644
--- a/fs/jffs2/TODO
+++ b/fs/jffs2/TODO
@@ -1,4 +1,3 @@
-$Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $
- support asynchronous operation -- add a per-fs 'reserved_space' count,
let each outstanding write reserve the _maximum_ amount of physical
@@ -30,8 +29,6 @@ $Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $
the full dirent, we only need to go to the flash in lookup() when we think we've
got a match, and in readdir().
- Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately?
- - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into
- jffs2_mark_node_obsolete(). Can all callers work it out?
- Remove size from jffs2_raw_node_frag.
dedekind:
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 73f0d60f73a..a46101ee867 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -1,13 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2006 NEC Corporation
+ * Copyright © 2006 NEC Corporation
*
* Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
*/
+
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index fa327dbd317..c84378cee82 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -1,13 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2006 NEC Corporation
+ * Copyright © 2006 NEC Corporation
*
* Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* 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/background.c b/fs/jffs2/background.c
index 888f236e549..0c82dfcfd24 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: background.c,v 1.54 2005/05/20 21:37:12 gleixner Exp $
- *
*/
#include <linux/kernel.h>
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index 07119c42a86..0ca2fff2617 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: build.c,v 1.85 2005/11/07 11:14:38 gleixner Exp $
- *
*/
#include <linux/kernel.h>
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index 7001ba26c06..485d065de41 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -1,16 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
* Created by Arjan van de Ven <arjanv@redhat.com>
*
- * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
+ * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
* University of Szeged, Hungary
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: compr.c,v 1.46 2005/11/07 11:14:38 gleixner Exp $
- *
*/
#include "compr.h"
@@ -268,144 +266,6 @@ int jffs2_unregister_compressor(struct jffs2_compressor *comp)
return 0;
}
-#ifdef CONFIG_JFFS2_PROC
-
-#define JFFS2_STAT_BUF_SIZE 16000
-
-char *jffs2_list_compressors(void)
-{
- struct jffs2_compressor *this;
- char *buf, *act_buf;
-
- act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL);
- list_for_each_entry(this, &jffs2_compressor_list, list) {
- act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority);
- if ((this->disabled)||(!this->compress))
- act_buf += sprintf(act_buf,"disabled");
- else
- act_buf += sprintf(act_buf,"enabled");
- act_buf += sprintf(act_buf,"\n");
- }
- return buf;
-}
-
-char *jffs2_stats(void)
-{
- struct jffs2_compressor *this;
- char *buf, *act_buf;
-
- act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL);
-
- act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n");
- act_buf += sprintf(act_buf,"%10s ","none");
- act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks,
- none_stat_compr_size, none_stat_decompr_blocks);
- spin_lock(&jffs2_compressor_list_lock);
- list_for_each_entry(this, &jffs2_compressor_list, list) {
- act_buf += sprintf(act_buf,"%10s ",this->name);
- if ((this->disabled)||(!this->compress))
- act_buf += sprintf(act_buf,"- ");
- else
- act_buf += sprintf(act_buf,"+ ");
- act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks,
- this->stat_compr_new_size, this->stat_compr_orig_size,
- this->stat_decompr_blocks);
- act_buf += sprintf(act_buf,"\n");
- }
- spin_unlock(&jffs2_compressor_list_lock);
-
- return buf;
-}
-
-char *jffs2_get_compression_mode_name(void)
-{
- switch (jffs2_compression_mode) {
- case JFFS2_COMPR_MODE_NONE:
- return "none";
- case JFFS2_COMPR_MODE_PRIORITY:
- return "priority";
- case JFFS2_COMPR_MODE_SIZE:
- return "size";
- }
- return "unkown";
-}
-
-int jffs2_set_compression_mode_name(const char *name)
-{
- if (!strcmp("none",name)) {
- jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
- return 0;
- }
- if (!strcmp("priority",name)) {
- jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
- return 0;
- }
- if (!strcmp("size",name)) {
- jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
- return 0;
- }
- return 1;
-}
-
-static int jffs2_compressor_Xable(const char *name, int disabled)
-{
- struct jffs2_compressor *this;
- spin_lock(&jffs2_compressor_list_lock);
- list_for_each_entry(this, &jffs2_compressor_list, list) {
- if (!strcmp(this->name, name)) {
- this->disabled = disabled;
- spin_unlock(&jffs2_compressor_list_lock);
- return 0;
- }
- }
- spin_unlock(&jffs2_compressor_list_lock);
- printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name);
- return 1;
-}
-
-int jffs2_enable_compressor_name(const char *name)
-{
- return jffs2_compressor_Xable(name, 0);
-}
-
-int jffs2_disable_compressor_name(const char *name)
-{
- return jffs2_compressor_Xable(name, 1);
-}
-
-int jffs2_set_compressor_priority(const char *name, int priority)
-{
- struct jffs2_compressor *this,*comp;
- spin_lock(&jffs2_compressor_list_lock);
- list_for_each_entry(this, &jffs2_compressor_list, list) {
- if (!strcmp(this->name, name)) {
- this->priority = priority;
- comp = this;
- goto reinsert;
- }
- }
- spin_unlock(&jffs2_compressor_list_lock);
- printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name);
- return 1;
-reinsert:
- /* list is sorted in the order of priority, so if
- we change it we have to reinsert it into the
- good place */
- list_del(&comp->list);
- list_for_each_entry(this, &jffs2_compressor_list, list) {
- if (this->priority < comp->priority) {
- list_add(&comp->list, this->list.prev);
- spin_unlock(&jffs2_compressor_list_lock);
- return 0;
- }
- }
- list_add_tail(&comp->list, &jffs2_compressor_list);
- spin_unlock(&jffs2_compressor_list_lock);
- return 0;
-}
-
-#endif
-
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
{
if (orig != comprbuf)
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index 509b8b1c081..68cc7010dbd 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -1,13 +1,10 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
+ * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
* University of Szeged, Hungary
*
- * For licensing information, see the file 'LICENCE' in the
- * jffs2 directory.
- *
- * $Id: compr.h,v 1.9 2005/11/07 11:14:38 gleixner Exp $
+ * For licensing information, see the file 'LICENCE' in this directory.
*
*/
@@ -76,16 +73,6 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
-#ifdef CONFIG_JFFS2_PROC
-int jffs2_enable_compressor_name(const char *name);
-int jffs2_disable_compressor_name(const char *name);
-int jffs2_set_compression_mode_name(const char *mode_name);
-char *jffs2_get_compression_mode_name(void);
-int jffs2_set_compressor_priority(const char *mode_name, int priority);
-char *jffs2_list_compressors(void);
-char *jffs2_stats(void);
-#endif
-
/* Compressor modules */
/* These functions will be called by jffs2_compressors_init/exit */
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
index 2eb1b7428d1..0d0bfd2e4e0 100644
--- a/fs/jffs2/compr_rtime.c
+++ b/fs/jffs2/compr_rtime.c
@@ -1,13 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by Arjan van de Ven <arjanv@redhat.com>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: compr_rtime.c,v 1.14 2004/06/23 16:34:40 havasi Exp $
*
*
* Very simple lz77-ish encoder.
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
index e792e675d62..ea0431e047d 100644
--- a/fs/jffs2/compr_rubin.c
+++ b/fs/jffs2/compr_rubin.c
@@ -1,23 +1,94 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001, 2002 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by Arjan van de Ven <arjanv@redhat.com>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: compr_rubin.c,v 1.20 2004/06/23 16:34:40 havasi Exp $
- *
*/
#include <linux/string.h>
#include <linux/types.h>
#include <linux/jffs2.h>
-#include "compr_rubin.h"
-#include "histo_mips.h"
+#include <linux/errno.h>
#include "compr.h"
+
+#define RUBIN_REG_SIZE 16
+#define UPPER_BIT_RUBIN (((long) 1)<<(RUBIN_REG_SIZE-1))
+#define LOWER_BITS_RUBIN ((((long) 1)<<(RUBIN_REG_SIZE-1))-1)
+
+
+#define BIT_DIVIDER_MIPS 1043
+static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */
+
+#include <linux/errno.h>
+
+struct pushpull {
+ unsigned char *buf;
+ unsigned int buflen;
+ unsigned int ofs;
+ unsigned int reserve;
+};
+
+struct rubin_state {
+ unsigned long p;
+ unsigned long q;
+ unsigned long rec_q;
+ long bit_number;
+ struct pushpull pp;
+ int bit_divider;
+ int bits[8];
+};
+
+static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve)
+{
+ pp->buf = buf;
+ pp->buflen = buflen;
+ pp->ofs = ofs;
+ pp->reserve = reserve;
+}
+
+static inline int pushbit(struct pushpull *pp, int bit, int use_reserved)
+{
+ if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) {
+ return -ENOSPC;
+ }
+
+ if (bit) {
+ pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7)));
+ }
+ else {
+ pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7)));
+ }
+ pp->ofs++;
+
+ return 0;
+}
+
+static inline int pushedbits(struct pushpull *pp)
+{
+ return pp->ofs;
+}
+
+static inline int pullbit(struct pushpull *pp)
+{
+ int bit;
+
+ bit = (pp->buf[pp->ofs >> 3] >> (7-(pp->ofs & 7))) & 1;
+
+ pp->ofs++;
+ return bit;
+}
+
+static inline int pulledbits(struct pushpull *pp)
+{
+ return pp->ofs;
+}
+
+
static void init_rubin(struct rubin_state *rs, int div, int *bits)
{
int c;
diff --git a/fs/jffs2/compr_rubin.h b/fs/jffs2/compr_rubin.h
deleted file mode 100644
index bf1a9345162..00000000000
--- a/fs/jffs2/compr_rubin.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Rubin encoder/decoder header */
-/* work started at : aug 3, 1994 */
-/* last modification : aug 15, 1994 */
-/* $Id: compr_rubin.h,v 1.7 2005/11/07 11:14:38 gleixner Exp $ */
-
-#include "pushpull.h"
-
-#define RUBIN_REG_SIZE 16
-#define UPPER_BIT_RUBIN (((long) 1)<<(RUBIN_REG_SIZE-1))
-#define LOWER_BITS_RUBIN ((((long) 1)<<(RUBIN_REG_SIZE-1))-1)
-
-
-struct rubin_state {
- unsigned long p;
- unsigned long q;
- unsigned long rec_q;
- long bit_number;
- struct pushpull pp;
- int bit_divider;
- int bits[8];
-};
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index 0c1fc6e20b4..2b87fccc155 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: compr_zlib.c,v 1.32 2005/11/07 11:14:38 gleixner Exp $
- *
*/
#if !defined(__KERNEL__) && !defined(__ECOS)
diff --git a/fs/jffs2/comprtest.c b/fs/jffs2/comprtest.c
deleted file mode 100644
index f0fb8be7740..00000000000
--- a/fs/jffs2/comprtest.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/* $Id: comprtest.c,v 1.6 2005/11/07 11:14:38 gleixner Exp $ */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <asm/types.h>
-#if 0
-#define TESTDATA_LEN 512
-static unsigned char testdata[TESTDATA_LEN] = {
- 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x83, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00,
- 0xb0, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x06, 0x00, 0x28, 0x00,
- 0x1e, 0x00, 0x1b, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x80, 0x04, 0x08,
- 0x34, 0x80, 0x04, 0x08, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xf4, 0x80, 0x04, 0x08,
- 0xf4, 0x80, 0x04, 0x08, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x08,
- 0x00, 0x80, 0x04, 0x08, 0x0d, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x10, 0x95, 0x04, 0x08,
- 0x10, 0x95, 0x04, 0x08, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x58, 0x95, 0x04, 0x08,
- 0x58, 0x95, 0x04, 0x08, 0xa0, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x08, 0x81, 0x04, 0x08,
- 0x08, 0x81, 0x04, 0x08, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x6c, 0x64, 0x2d, 0x6c, 0x69, 0x6e, 0x75,
- 0x78, 0x2e, 0x73, 0x6f, 0x2e, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x47, 0x4e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
- 0x0c, 0x83, 0x04, 0x08, 0x81, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x1c, 0x83, 0x04, 0x08, 0xac, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
- 0x2c, 0x83, 0x04, 0x08, 0xdd, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
- 0x3c, 0x83, 0x04, 0x08, 0x2e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x4c, 0x83, 0x04, 0x08, 0x7d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
- 0x00, 0x85, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x67,
- 0x6d, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x5f, 0x00, 0x6c, 0x69, 0x62, 0x63,
- 0x2e, 0x73, 0x6f, 0x2e, 0x36, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x00, 0x5f, 0x5f, 0x63};
-#else
-#define TESTDATA_LEN 3481
-static unsigned char testdata[TESTDATA_LEN] = {
- 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x22, 0x64, 0x62, 0x65, 0x6e, 0x63, 0x68,
- 0x2e, 0x68, 0x22, 0x0a, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x4d, 0x41, 0x58,
- 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x20, 0x31, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x73, 0x74, 0x61,
- 0x74, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x62, 0x75, 0x66, 0x5b, 0x37, 0x30, 0x30,
- 0x30, 0x30, 0x5d, 0x3b, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x20,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x61,
- 0x74, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x7b, 0x0a, 0x09, 0x69, 0x6e,
- 0x74, 0x20, 0x66, 0x64, 0x3b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
- 0x65, 0x3b, 0x0a, 0x7d, 0x20, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x4d, 0x41, 0x58, 0x5f,
- 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5d, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f,
- 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e,
- 0x61, 0x6d, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72,
- 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x75,
- 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x20, 0x21, 0x3d, 0x20,
- 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28,
- 0x25, 0x64, 0x29, 0x20, 0x75, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x25, 0x73, 0x20, 0x66, 0x61,
- 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09,
- 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75,
- 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72,
- 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a,
- 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x66,
- 0x69, 0x6c, 0x65, 0x28, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20,
- 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x3b, 0x0a,
- 0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a,
- 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x4d, 0x49, 0x4e, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x6f, 0x66,
- 0x28, 0x62, 0x75, 0x66, 0x29, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x09,
- 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73,
- 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x2d, 0x3d, 0x20, 0x73, 0x3b, 0x0a,
- 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x6f, 0x70,
- 0x65, 0x6e, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20,
- 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20,
- 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x64, 0x2c,
- 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d,
- 0x20, 0x4f, 0x5f, 0x52, 0x44, 0x57, 0x52, 0x7c, 0x4f, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x3b,
- 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x20, 0x73, 0x74,
- 0x3b, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x63, 0x6f,
- 0x75, 0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28,
- 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69,
- 0x7a, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x7c,
- 0x3d, 0x20, 0x4f, 0x5f, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x3b, 0x0a, 0x0a, 0x09, 0x66, 0x64, 0x20,
- 0x3d, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x66, 0x6c,
- 0x61, 0x67, 0x73, 0x2c, 0x20, 0x30, 0x36, 0x30, 0x30, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20,
- 0x28, 0x66, 0x64, 0x20, 0x3d, 0x3d, 0x20, 0x2d, 0x31, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70,
- 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x6f, 0x70, 0x65, 0x6e,
- 0x20, 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68,
- 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22,
- 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65,
- 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x68,
- 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28,
- 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72,
- 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x66, 0x73, 0x74, 0x61, 0x74, 0x28, 0x66, 0x64, 0x2c,
- 0x20, 0x26, 0x73, 0x74, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65,
- 0x20, 0x3e, 0x20, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b,
- 0x0a, 0x23, 0x69, 0x66, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69,
- 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64,
- 0x69, 0x6e, 0x67, 0x20, 0x25, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x20, 0x66, 0x72, 0x6f,
- 0x6d, 0x20, 0x25, 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66,
- 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74,
- 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x23, 0x65,
- 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x09, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x66, 0x69,
- 0x6c, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x74,
- 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x20, 0x65, 0x6c,
- 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3c, 0x20, 0x73, 0x74,
- 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72,
- 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67,
- 0x20, 0x25, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x25,
- 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e,
- 0x74, 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09,
- 0x09, 0x66, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x73,
- 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69,
- 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b, 0x69,
- 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61, 0x62,
- 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d, 0x20,
- 0x30, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66,
- 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53,
- 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x66, 0x69,
- 0x6c, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x66, 0x6f,
- 0x72, 0x20, 0x25, 0x73, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b,
- 0x0a, 0x09, 0x09, 0x65, 0x78, 0x69, 0x74, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09,
- 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65,
- 0x20, 0x3d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x3b, 0x0a, 0x09, 0x66, 0x74, 0x61, 0x62,
- 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x64, 0x3b, 0x0a, 0x09,
- 0x69, 0x66, 0x20, 0x28, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2b, 0x2b, 0x20, 0x25, 0x20, 0x31, 0x30,
- 0x30, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e,
- 0x74, 0x66, 0x28, 0x22, 0x2e, 0x22, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76,
- 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x69, 0x6e, 0x74,
- 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a,
- 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x0a, 0x7b,
- 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x62,
- 0x75, 0x66, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x6d, 0x65, 0x6d, 0x73,
- 0x65, 0x74, 0x28, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x6f,
- 0x66, 0x28, 0x62, 0x75, 0x66, 0x29, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28,
- 0x69, 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b,
- 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61,
- 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d,
- 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a,
- 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58,
- 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x31, 0x0a,
- 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64,
- 0x6f, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x3a, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20,
- 0x25, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20,
- 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25, 0x64, 0x20, 0x6f, 0x66, 0x73, 0x3d, 0x25, 0x64, 0x5c, 0x6e,
- 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e,
- 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c,
- 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x3b, 0x0a,
- 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b,
- 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x6c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c,
- 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c,
- 0x20, 0x53, 0x45, 0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20,
- 0x28, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d,
- 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20,
- 0x21, 0x3d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69,
- 0x6e, 0x74, 0x66, 0x28, 0x22, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65,
- 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x5c, 0x6e,
- 0x22, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d,
- 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x28, 0x69,
- 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73,
- 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29,
- 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20,
- 0x28, 0x69, 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53,
- 0x3b, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74,
- 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d,
- 0x3d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b,
- 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41,
- 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69,
- 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x65, 0x61,
- 0x64, 0x3a, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x77, 0x61, 0x73,
- 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25,
- 0x64, 0x20, 0x6f, 0x66, 0x73, 0x3d, 0x25, 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
- 0x74, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c,
- 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75,
- 0x72, 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x6c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x66, 0x74,
- 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73,
- 0x65, 0x74, 0x2c, 0x20, 0x53, 0x45, 0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x29, 0x3b, 0x0a, 0x09,
- 0x72, 0x65, 0x61, 0x64, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66,
- 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x7d,
- 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28,
- 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69,
- 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69, 0x3d, 0x30, 0x3b,
- 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b, 0x69, 0x2b, 0x2b, 0x29,
- 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b,
- 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x68, 0x61, 0x6e,
- 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09,
- 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c,
- 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22,
- 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x68,
- 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74,
- 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20,
- 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72,
- 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, 0x66, 0x74, 0x61,
- 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x29, 0x3b, 0x0a, 0x09, 0x66, 0x74, 0x61,
- 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x20,
- 0x30, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x6d, 0x6b,
- 0x64, 0x69, 0x72, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29,
- 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61,
- 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x6d, 0x6b, 0x64, 0x69, 0x72,
- 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x30, 0x37, 0x30, 0x30, 0x29, 0x20, 0x21, 0x3d,
- 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0a,
- 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x20,
- 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e,
- 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6e, 0x61,
- 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72,
- 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x7d, 0x0a,
- 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x6d, 0x64, 0x69, 0x72,
- 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x0a, 0x7b, 0x0a,
- 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29,
- 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x6d, 0x64, 0x69, 0x72, 0x28, 0x66, 0x6e,
- 0x61, 0x6d, 0x65, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70,
- 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x72, 0x6d, 0x64, 0x69, 0x72, 0x20, 0x25, 0x73, 0x20,
- 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20,
- 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c,
- 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29,
- 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f,
- 0x5f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x6f, 0x6c,
- 0x64, 0x2c, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x6e, 0x65, 0x77, 0x29, 0x0a, 0x7b, 0x0a,
- 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x6f, 0x6c, 0x64, 0x29, 0x3b, 0x0a,
- 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x6e, 0x65, 0x77, 0x29, 0x3b, 0x0a,
- 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x6f, 0x6c, 0x64,
- 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09,
- 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20,
- 0x25, 0x73, 0x20, 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73,
- 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72,
- 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d,
- 0x0a, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x28,
- 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74,
- 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74,
- 0x20, 0x73, 0x74, 0x61, 0x74, 0x20, 0x73, 0x74, 0x3b, 0x0a, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75,
- 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69,
- 0x66, 0x20, 0x28, 0x73, 0x74, 0x61, 0x74, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x26,
- 0x73, 0x74, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72,
- 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74,
- 0x61, 0x74, 0x3a, 0x20, 0x25, 0x73, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25, 0x64, 0x20, 0x25,
- 0x73, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d,
- 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f,
- 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74,
- 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x53, 0x5f, 0x49,
- 0x53, 0x44, 0x49, 0x52, 0x28, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x29,
- 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28,
- 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x21, 0x3d, 0x20, 0x73, 0x69,
- 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22,
- 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x3a, 0x20, 0x25, 0x73,
- 0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25, 0x64, 0x20, 0x25,
- 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d,
- 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69,
- 0x7a, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a,
- 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x28,
- 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74,
- 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x64, 0x6f, 0x5f, 0x6f, 0x70, 0x65,
- 0x6e, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x35, 0x30, 0x30, 0x30, 0x2c, 0x20, 0x73,
- 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28,
- 0x35, 0x30, 0x30, 0x30, 0x29, 0x3b, 0x0a, 0x7d, 0x0a
-};
-#endif
-static unsigned char comprbuf[TESTDATA_LEN];
-static unsigned char decomprbuf[TESTDATA_LEN];
-
-int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in,
- unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
-unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out,
- uint32_t *datalen, uint32_t *cdatalen);
-
-int init_module(void ) {
- unsigned char comprtype;
- uint32_t c, d;
- int ret;
-
- printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
- testdata[0],testdata[1],testdata[2],testdata[3],
- testdata[4],testdata[5],testdata[6],testdata[7],
- testdata[8],testdata[9],testdata[10],testdata[11],
- testdata[12],testdata[13],testdata[14],testdata[15]);
- d = TESTDATA_LEN;
- c = TESTDATA_LEN;
- comprtype = jffs2_compress(testdata, comprbuf, &d, &c);
-
- printk("jffs2_compress used compression type %d. Compressed size %d, uncompressed size %d\n",
- comprtype, c, d);
- printk("Compressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
- comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3],
- comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7],
- comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11],
- comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]);
-
- ret = jffs2_decompress(comprtype, comprbuf, decomprbuf, c, d);
- printk("jffs2_decompress returned %d\n", ret);
- printk("Decompressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
- decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3],
- decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7],
- decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11],
- decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]);
- if (memcmp(decomprbuf, testdata, d))
- printk("Compression and decompression corrupted data\n");
- else
- printk("Compression good for %d bytes\n", d);
- return 1;
-}
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
index 4189e4a3605..3a32c64ed49 100644
--- a/fs/jffs2/debug.c
+++ b/fs/jffs2/debug.c
@@ -1,15 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: debug.c,v 1.12 2005/11/07 11:14:39 gleixner Exp $
- *
*/
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pagemap.h>
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index f89c85d5a3f..2a49f2c51a9 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -1,15 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: debug.h,v 1.21 2005/11/07 11:14:39 gleixner Exp $
- *
*/
+
#ifndef _JFFS2_DEBUG_H_
#define _JFFS2_DEBUG_H_
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 9fa2e27f064..c1dfca310dd 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: dir.c,v 1.90 2005/11/07 11:14:39 gleixner Exp $
- *
*/
#include <linux/kernel.h>
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index ad0121088dd..66e7c2f1e64 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: erase.c,v 1.85 2005/09/20 14:53:15 dedekind Exp $
- *
*/
#include <linux/kernel.h>
@@ -333,7 +331,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
*bad_offset = ofs;
- ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf);
+ ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf);
if (ret) {
printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret);
goto fail;
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index e82eeaf7590..99871279a1e 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: file.c,v 1.104 2005/10/18 23:29:35 tpoynor Exp $
- *
*/
#include <linux/kernel.h>
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index abb90c0c09c..1d3b7a9fc82 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: fs.c,v 1.66 2005/09/27 13:17:29 dedekind Exp $
- *
*/
#include <linux/capability.h>
@@ -672,6 +670,13 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) {
return ret;
}
+ /* and an UBI volume */
+ if (jffs2_ubivol(c)) {
+ ret = jffs2_ubivol_setup(c);
+ if (ret)
+ return ret;
+ }
+
return ret;
}
@@ -690,4 +695,9 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) {
if (jffs2_nor_wbuf_flash(c)) {
jffs2_nor_wbuf_flash_cleanup(c);
}
+
+ /* and an UBI volume */
+ if (jffs2_ubivol(c)) {
+ jffs2_ubivol_cleanup(c);
+ }
}
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 3a3cf225981..2d99e06ab22 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: gc.c,v 1.155 2005/11/07 11:14:39 gleixner Exp $
- *
*/
#include <linux/kernel.h>
@@ -144,7 +142,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
c->unchecked_size);
jffs2_dbg_dump_block_lists_nolock(c);
spin_unlock(&c->erase_completion_lock);
- BUG();
+ up(&c->alloc_sem);
+ return -ENOSPC;
}
spin_unlock(&c->erase_completion_lock);
diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c
index 69099835de1..f4d525b0ea5 100644
--- a/fs/jffs2/ioctl.c
+++ b/fs/jffs2/ioctl.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: ioctl.c,v 1.10 2005/11/07 11:14:40 gleixner Exp $
- *
*/
#include <linux/fs.h>
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h
index 3a566077ac9..0b78fdc9773 100644
--- a/fs/jffs2/jffs2_fs_i.h
+++ b/fs/jffs2/jffs2_fs_i.h
@@ -1,4 +1,13 @@
-/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright © 2001-2007 Red Hat, Inc.
+ *
+ * Created by David Woodhouse <dwmw2@infradead.org>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
#ifndef _JFFS2_FS_I
#define _JFFS2_FS_I
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index ea88f69af13..b13298a824e 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -1,4 +1,13 @@
-/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright © 2001-2007 Red Hat, Inc.
+ *
+ * Created by David Woodhouse <dwmw2@infradead.org>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
#ifndef _JFFS2_FS_SB
#define _JFFS2_FS_SB
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 83f9881ec4c..35c1a5e30ba 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: malloc.c,v 1.31 2005/11/07 11:14:40 gleixner Exp $
- *
*/
#include <linux/kernel.h>
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 5a6b4d64206..4bf86088b3a 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: nodelist.c,v 1.115 2005/11/07 11:14:40 gleixner Exp $
- *
*/
#include <linux/kernel.h>
@@ -54,7 +52,7 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new
*prev = new;
}
-void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
+uint32_t jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
{
struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);
@@ -76,18 +74,24 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint
}
if (size == 0)
- return;
+ return 0;
- /*
- * If the last fragment starts at the RAM page boundary, it is
- * REF_PRISTINE irrespective of its size.
- */
frag = frag_last(list);
+
+ /* Sanity check for truncation to longer than we started with... */
+ if (!frag)
+ return 0;
+ if (frag->ofs + frag->size < size)
+ return frag->ofs + frag->size;
+
+ /* If the last fragment starts at the RAM page boundary, it is
+ * REF_PRISTINE irrespective of its size. */
if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) {
dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n",
frag->ofs, frag->ofs + frag->size);
frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE;
}
+ return size;
}
static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c,
@@ -397,466 +401,6 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in
return 0;
}
-/*
- * Check the data CRC of the node.
- *
- * Returns: 0 if the data CRC is correct;
- * 1 - if incorrect;
- * error code if an error occured.
- */
-static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
-{
- struct jffs2_raw_node_ref *ref = tn->fn->raw;
- int err = 0, pointed = 0;
- struct jffs2_eraseblock *jeb;
- unsigned char *buffer;
- uint32_t crc, ofs, len;
- size_t retlen;
-
- BUG_ON(tn->csize == 0);
-
- if (!jffs2_is_writebuffered(c))
- goto adj_acc;
-
- /* Calculate how many bytes were already checked */
- ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode);
- len = ofs % c->wbuf_pagesize;
- if (likely(len))
- len = c->wbuf_pagesize - len;
-
- if (len >= tn->csize) {
- dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n",
- ref_offset(ref), tn->csize, ofs);
- goto adj_acc;
- }
-
- ofs += len;
- len = tn->csize - len;
-
- dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n",
- ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len);
-
-#ifndef __ECOS
- /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
- * adding and jffs2_flash_read_end() interface. */
- if (c->mtd->point) {
- err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
- if (!err && retlen < tn->csize) {
- JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
- c->mtd->unpoint(c->mtd, buffer, ofs, len);
- } else if (err)
- JFFS2_WARNING("MTD point failed: error code %d.\n", err);
- else
- pointed = 1; /* succefully pointed to device */
- }
-#endif
-
- if (!pointed) {
- buffer = kmalloc(len, GFP_KERNEL);
- if (unlikely(!buffer))
- return -ENOMEM;
-
- /* TODO: this is very frequent pattern, make it a separate
- * routine */
- err = jffs2_flash_read(c, ofs, len, &retlen, buffer);
- if (err) {
- JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err);
- goto free_out;
- }
-
- if (retlen != len) {
- JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len);
- err = -EIO;
- goto free_out;
- }
- }
-
- /* Continue calculating CRC */
- crc = crc32(tn->partial_crc, buffer, len);
- if(!pointed)
- kfree(buffer);
-#ifndef __ECOS
- else
- c->mtd->unpoint(c->mtd, buffer, ofs, len);
-#endif
-
- if (crc != tn->data_crc) {
- JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
- ofs, tn->data_crc, crc);
- return 1;
- }
-
-adj_acc:
- jeb = &c->blocks[ref->flash_offset / c->sector_size];
- len = ref_totlen(c, jeb, ref);
-
- /*
- * Mark the node as having been checked and fix the
- * accounting accordingly.
- */
- spin_lock(&c->erase_completion_lock);
- jeb->used_size += len;
- jeb->unchecked_size -= len;
- c->used_size += len;
- c->unchecked_size -= len;
- spin_unlock(&c->erase_completion_lock);
-
- return 0;
-
-free_out:
- if(!pointed)
- kfree(buffer);
-#ifndef __ECOS
- else
- c->mtd->unpoint(c->mtd, buffer, ofs, len);
-#endif
- return err;
-}
-
-/*
- * Helper function for jffs2_add_older_frag_to_fragtree().
- *
- * Checks the node if we are in the checking stage.
- */
-static int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn)
-{
- int ret;
-
- BUG_ON(ref_obsolete(tn->fn->raw));
-
- /* We only check the data CRC of unchecked nodes */
- if (ref_flags(tn->fn->raw) != REF_UNCHECKED)
- return 0;
-
- dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n",
- tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw));
-
- ret = check_node_data(c, tn);
- if (unlikely(ret < 0)) {
- JFFS2_ERROR("check_node_data() returned error: %d.\n",
- ret);
- } else if (unlikely(ret > 0)) {
- dbg_fragtree2("CRC error, mark it obsolete.\n");
- jffs2_mark_node_obsolete(c, tn->fn->raw);
- }
-
- return ret;
-}
-
-/*
- * Helper function for jffs2_add_older_frag_to_fragtree().
- *
- * Called when the new fragment that is being inserted
- * splits a hole fragment.
- */
-static int split_hole(struct jffs2_sb_info *c, struct rb_root *root,
- struct jffs2_node_frag *newfrag, struct jffs2_node_frag *hole)
-{
- dbg_fragtree2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n",
- newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size);
-
- if (hole->ofs == newfrag->ofs) {
- /*
- * Well, the new fragment actually starts at the same offset as
- * the hole.
- */
- if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) {
- /*
- * We replace the overlapped left part of the hole by
- * the new node.
- */
-
- dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n",
- newfrag->ofs, newfrag->ofs + newfrag->size);
- rb_replace_node(&hole->rb, &newfrag->rb, root);
-
- hole->ofs += newfrag->size;
- hole->size -= newfrag->size;
-
- /*
- * We know that 'hole' should be the right hand
- * fragment.
- */
- jffs2_fragtree_insert(hole, newfrag);
- rb_insert_color(&hole->rb, root);
- } else {
- /*
- * Ah, the new fragment is of the same size as the hole.
- * Relace the hole by it.
- */
- dbg_fragtree2("insert fragment %#04x-%#04x and overwrite hole\n",
- newfrag->ofs, newfrag->ofs + newfrag->size);
- rb_replace_node(&hole->rb, &newfrag->rb, root);
- jffs2_free_node_frag(hole);
- }
- } else {
- /* The new fragment lefts some hole space at the left */
-
- struct jffs2_node_frag * newfrag2 = NULL;
-
- if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) {
- /* The new frag also lefts some space at the right */
- newfrag2 = new_fragment(NULL, newfrag->ofs +
- newfrag->size, hole->ofs + hole->size
- - newfrag->ofs - newfrag->size);
- if (unlikely(!newfrag2)) {
- jffs2_free_node_frag(newfrag);
- return -ENOMEM;
- }
- }
-
- hole->size = newfrag->ofs - hole->ofs;
- dbg_fragtree2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n",
- hole->ofs, hole->ofs + hole->size, newfrag->ofs, newfrag->ofs + newfrag->size);
-
- jffs2_fragtree_insert(newfrag, hole);
- rb_insert_color(&newfrag->rb, root);
-
- if (newfrag2) {
- dbg_fragtree2("left the hole %#04x-%#04x at the right\n",
- newfrag2->ofs, newfrag2->ofs + newfrag2->size);
- jffs2_fragtree_insert(newfrag2, newfrag);
- rb_insert_color(&newfrag2->rb, root);
- }
- }
-
- return 0;
-}
-
-/*
- * This function is used when we build inode. It expects the nodes are passed
- * in the decreasing version order. The whole point of this is to improve the
- * inodes checking on NAND: we check the nodes' data CRC only when they are not
- * obsoleted. Previously, add_frag_to_fragtree() function was used and
- * nodes were passed to it in the increasing version ordes and CRCs of all
- * nodes were checked.
- *
- * Note: tn->fn->size shouldn't be zero.
- *
- * Returns 0 if the node was inserted
- * 1 if it wasn't inserted (since it is obsolete)
- * < 0 an if error occured
- */
-int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
- struct jffs2_tmp_dnode_info *tn)
-{
- struct jffs2_node_frag *this, *newfrag;
- uint32_t lastend;
- struct jffs2_full_dnode *fn = tn->fn;
- struct rb_root *root = &f->fragtree;
- uint32_t fn_size = fn->size, fn_ofs = fn->ofs;
- int err, checked = 0;
- int ref_flag;
-
- dbg_fragtree("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version);
-
- /* Skip all the nodes which are completed before this one starts */
- this = jffs2_lookup_node_frag(root, fn_ofs);
- if (this)
- dbg_fragtree2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole");
-
- if (this)
- lastend = this->ofs + this->size;
- else
- lastend = 0;
-
- /* Detect the preliminary type of node */
- if (fn->size >= PAGE_CACHE_SIZE)
- ref_flag = REF_PRISTINE;
- else
- ref_flag = REF_NORMAL;
-
- /* See if we ran off the end of the root */
- if (lastend <= fn_ofs) {
- /* We did */
-
- /*
- * We are going to insert the new node into the
- * fragment tree, so check it.
- */
- err = check_node(c, f, tn);
- if (err != 0)
- return err;
-
- fn->frags = 1;
-
- newfrag = new_fragment(fn, fn_ofs, fn_size);
- if (unlikely(!newfrag))
- return -ENOMEM;
-
- err = no_overlapping_node(c, root, newfrag, this, lastend);
- if (unlikely(err != 0)) {
- jffs2_free_node_frag(newfrag);
- return err;
- }
-
- goto out_ok;
- }
-
- fn->frags = 0;
-
- while (1) {
- /*
- * Here we have:
- * fn_ofs < this->ofs + this->size && fn_ofs >= this->ofs.
- *
- * Remember, 'this' has higher version, any non-hole node
- * which is already in the fragtree is newer then the newly
- * inserted.
- */
- if (!this->node) {
- /*
- * 'this' is the hole fragment, so at least the
- * beginning of the new fragment is valid.
- */
-
- /*
- * We are going to insert the new node into the
- * fragment tree, so check it.
- */
- if (!checked) {
- err = check_node(c, f, tn);
- if (unlikely(err != 0))
- return err;
- checked = 1;
- }
-
- if (this->ofs + this->size >= fn_ofs + fn_size) {
- /* We split the hole on two parts */
-
- fn->frags += 1;
- newfrag = new_fragment(fn, fn_ofs, fn_size);
- if (unlikely(!newfrag))
- return -ENOMEM;
-
- err = split_hole(c, root, newfrag, this);
- if (unlikely(err))
- return err;
- goto out_ok;
- }
-
- /*
- * The beginning of the new fragment is valid since it
- * overlaps the hole node.
- */
-
- ref_flag = REF_NORMAL;
-
- fn->frags += 1;
- newfrag = new_fragment(fn, fn_ofs,
- this->ofs + this->size - fn_ofs);
- if (unlikely(!newfrag))
- return -ENOMEM;
-
- if (fn_ofs == this->ofs) {
- /*
- * The new node starts at the same offset as
- * the hole and supersieds the hole.
- */
- dbg_fragtree2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n",
- fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags);
-
- rb_replace_node(&this->rb, &newfrag->rb, root);
- jffs2_free_node_frag(this);
- } else {
- /*
- * The hole becomes shorter as its right part
- * is supersieded by the new fragment.
- */
- dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n",
- this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size);
-
- dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs,
- fn_ofs + this->ofs + this->size - fn_ofs, fn->frags);
-
- this->size -= newfrag->size;
- jffs2_fragtree_insert(newfrag, this);
- rb_insert_color(&newfrag->rb, root);
- }
-
- fn_ofs += newfrag->size;
- fn_size -= newfrag->size;
- this = rb_entry(rb_next(&newfrag->rb),
- struct jffs2_node_frag, rb);
-
- dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n",
- this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)");
- }
-
- /*
- * 'This' node is not the hole so it obsoletes the new fragment
- * either fully or partially.
- */
- if (this->ofs + this->size >= fn_ofs + fn_size) {
- /* The new node is obsolete, drop it */
- if (fn->frags == 0) {
- dbg_fragtree2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size);
- ref_flag = REF_OBSOLETE;
- }
- goto out_ok;
- } else {
- struct jffs2_node_frag *new_this;
-
- /* 'This' node obsoletes the beginning of the new node */
- dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size);
-
- ref_flag = REF_NORMAL;
-
- fn_size -= this->ofs + this->size - fn_ofs;
- fn_ofs = this->ofs + this->size;
- dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size);
-
- new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb);
- if (!new_this) {
- /*
- * There is no next fragment. Add the rest of
- * the new node as the right-hand child.
- */
- if (!checked) {
- err = check_node(c, f, tn);
- if (unlikely(err != 0))
- return err;
- checked = 1;
- }
-
- fn->frags += 1;
- newfrag = new_fragment(fn, fn_ofs, fn_size);
- if (unlikely(!newfrag))
- return -ENOMEM;
-
- dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n",
- newfrag->ofs, newfrag->ofs + newfrag->size);
- rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right);
- rb_insert_color(&newfrag->rb, root);
- goto out_ok;
- } else {
- this = new_this;
- dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n",
- this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)");
- }
- }
- }
-
-out_ok:
- BUG_ON(fn->size < PAGE_CACHE_SIZE && ref_flag == REF_PRISTINE);
-
- if (ref_flag == REF_OBSOLETE) {
- dbg_fragtree2("the node is obsolete now\n");
- /* jffs2_mark_node_obsolete() will adjust space accounting */
- jffs2_mark_node_obsolete(c, fn->raw);
- return 1;
- }
-
- dbg_fragtree2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE");
-
- /* Space accounting was adjusted at check_node_data() */
- spin_lock(&c->erase_completion_lock);
- fn->raw->flash_offset = ref_offset(fn->raw) | ref_flag;
- spin_unlock(&c->erase_completion_lock);
-
- return 0;
-}
-
void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state)
{
spin_lock(&c->inocache_lock);
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 4178b4b5594..25126a062ca 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: nodelist.h,v 1.140 2005/09/07 08:34:54 havasi Exp $
- *
*/
#ifndef __JFFS2_NODELIST_H__
@@ -40,6 +38,9 @@
#define cpu_to_je32(x) ((jint32_t){x})
#define cpu_to_jemode(x) ((jmode_t){os_to_jffs2_mode(x)})
+#define constant_cpu_to_je16(x) ((jint16_t){x})
+#define constant_cpu_to_je32(x) ((jint32_t){x})
+
#define je16_to_cpu(x) ((x).v16)
#define je32_to_cpu(x) ((x).v32)
#define jemode_to_cpu(x) (jffs2_to_os_mode((x).m))
@@ -48,6 +49,9 @@
#define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)})
#define cpu_to_jemode(x) ((jmode_t){cpu_to_be32(os_to_jffs2_mode(x))})
+#define constant_cpu_to_je16(x) ((jint16_t){__constant_cpu_to_be16(x)})
+#define constant_cpu_to_je32(x) ((jint32_t){__constant_cpu_to_be32(x)})
+
#define je16_to_cpu(x) (be16_to_cpu(x.v16))
#define je32_to_cpu(x) (be32_to_cpu(x.v32))
#define jemode_to_cpu(x) (be32_to_cpu(jffs2_to_os_mode((x).m)))
@@ -56,6 +60,9 @@
#define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)})
#define cpu_to_jemode(x) ((jmode_t){cpu_to_le32(os_to_jffs2_mode(x))})
+#define constant_cpu_to_je16(x) ((jint16_t){__constant_cpu_to_le16(x)})
+#define constant_cpu_to_je32(x) ((jint32_t){__constant_cpu_to_le32(x)})
+
#define je16_to_cpu(x) (le16_to_cpu(x.v16))
#define je32_to_cpu(x) (le32_to_cpu(x.v32))
#define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m)))
@@ -216,7 +223,20 @@ struct jffs2_tmp_dnode_info
uint32_t version;
uint32_t data_crc;
uint32_t partial_crc;
- uint32_t csize;
+ uint16_t csize;
+ uint16_t overlapped;
+};
+
+/* Temporary data structure used during readinode. */
+struct jffs2_readinode_info
+{
+ struct rb_root tn_root;
+ struct jffs2_tmp_dnode_info *mdata_tn;
+ uint32_t highest_version;
+ uint32_t latest_mctime;
+ uint32_t mctime_ver;
+ struct jffs2_full_dirent *fds;
+ struct jffs2_raw_node_ref *latest_ref;
};
struct jffs2_full_dirent
@@ -319,6 +339,15 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
#define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb)
#define frag_erase(frag, list) rb_erase(&frag->rb, list);
+#define tn_next(tn) rb_entry(rb_next(&(tn)->rb), struct jffs2_tmp_dnode_info, rb)
+#define tn_prev(tn) rb_entry(rb_prev(&(tn)->rb), struct jffs2_tmp_dnode_info, rb)
+#define tn_parent(tn) rb_entry(rb_parent(&(tn)->rb), struct jffs2_tmp_dnode_info, rb)
+#define tn_left(tn) rb_entry((tn)->rb.rb_left, struct jffs2_tmp_dnode_info, rb)
+#define tn_right(tn) rb_entry((tn)->rb.rb_right, struct jffs2_tmp_dnode_info, rb)
+#define tn_erase(tn, list) rb_erase(&tn->rb, list);
+#define tn_last(list) rb_entry(rb_last(list), struct jffs2_tmp_dnode_info, rb)
+#define tn_first(list) rb_entry(rb_first(list), struct jffs2_tmp_dnode_info, rb)
+
/* nodelist.c */
void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list);
void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state);
@@ -333,8 +362,7 @@ struct rb_node *rb_next(struct rb_node *);
struct rb_node *rb_prev(struct rb_node *);
void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root);
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);
+uint32_t jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
struct jffs2_eraseblock *jeb,
uint32_t ofs, uint32_t len,
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index d88376992ed..dbc908ad622 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: nodemgmt.c,v 1.127 2005/09/20 15:49:12 dedekind Exp $
- *
*/
#include <linux/kernel.h>
@@ -172,6 +170,11 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
{
+ if (c->nextblock == NULL) {
+ D1(printk(KERN_DEBUG "jffs2_close_nextblock: Erase block at 0x%08x has already been placed in a list\n",
+ jeb->offset));
+ return;
+ }
/* Check, if we have a dirty block now, or if it was dirty already */
if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) {
c->dirty_size += jeb->wasted_size;
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index e07a0edcdb4..80daea96bbc 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2002-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: os-linux.h,v 1.64 2005/09/30 13:59:13 dedekind Exp $
- *
*/
#ifndef __JFFS2_OS_LINUX_H__
@@ -98,6 +96,9 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
#define jffs2_nor_wbuf_flash(c) (0)
#define jffs2_nor_wbuf_flash_setup(c) (0)
#define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0)
+#define jffs2_ubivol(c) (0)
+#define jffs2_ubivol_setup(c) (0)
+#define jffs2_ubivol_cleanup(c) do {} while (0)
#else /* NAND and/or ECC'd NOR support present */
@@ -133,6 +134,9 @@ void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c);
#define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH)
int jffs2_dataflash_setup(struct jffs2_sb_info *c);
void jffs2_dataflash_cleanup(struct jffs2_sb_info *c);
+#define jffs2_ubivol(c) (c->mtd->type == MTD_UBIVOLUME)
+int jffs2_ubivol_setup(struct jffs2_sb_info *c);
+void jffs2_ubivol_cleanup(struct jffs2_sb_info *c);
#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && ! (c->mtd->flags & MTD_BIT_WRITEABLE))
int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c);
diff --git a/fs/jffs2/pushpull.h b/fs/jffs2/pushpull.h
deleted file mode 100644
index c0c2a9158df..00000000000
--- a/fs/jffs2/pushpull.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * JFFS2 -- Journalling Flash File System, Version 2.
- *
- * Copyright (C) 2001, 2002 Red Hat, Inc.
- *
- * Created by David Woodhouse <dwmw2@infradead.org>
- *
- * For licensing information, see the file 'LICENCE' in this directory.
- *
- * $Id: pushpull.h,v 1.10 2004/11/16 20:36:11 dwmw2 Exp $
- *
- */
-
-#ifndef __PUSHPULL_H__
-#define __PUSHPULL_H__
-
-#include <linux/errno.h>
-
-struct pushpull {
- unsigned char *buf;
- unsigned int buflen;
- unsigned int ofs;
- unsigned int reserve;
-};
-
-
-static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve)
-{
- pp->buf = buf;
- pp->buflen = buflen;
- pp->ofs = ofs;
- pp->reserve = reserve;
-}
-
-static inline int pushbit(struct pushpull *pp, int bit, int use_reserved)
-{
- if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) {
- return -ENOSPC;
- }
-
- if (bit) {
- pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7)));
- }
- else {
- pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7)));
- }
- pp->ofs++;
-
- return 0;
-}
-
-static inline int pushedbits(struct pushpull *pp)
-{
- return pp->ofs;
-}
-
-static inline int pullbit(struct pushpull *pp)
-{
- int bit;
-
- bit = (pp->buf[pp->ofs >> 3] >> (7-(pp->ofs & 7))) & 1;
-
- pp->ofs++;
- return bit;
-}
-
-static inline int pulledbits(struct pushpull *pp)
-{
- return pp->ofs;
-}
-
-#endif /* __PUSHPULL_H__ */
diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c
index f3b86da833b..cfe05c1966a 100644
--- a/fs/jffs2/read.c
+++ b/fs/jffs2/read.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: read.c,v 1.42 2005/11/07 11:14:41 gleixner Exp $
- *
*/
#include <linux/kernel.h>
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 717a48cf7df..6aff38930b5 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $
- *
*/
#include <linux/kernel.h>
@@ -22,30 +20,510 @@
#include "nodelist.h"
/*
- * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in
- * order of increasing version.
+ * Check the data CRC of the node.
+ *
+ * Returns: 0 if the data CRC is correct;
+ * 1 - if incorrect;
+ * error code if an error occured.
*/
-static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list)
+static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
{
- struct rb_node **p = &list->rb_node;
- struct rb_node * parent = NULL;
- struct jffs2_tmp_dnode_info *this;
-
- while (*p) {
- parent = *p;
- this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
-
- /* There may actually be a collision here, but it doesn't
- actually matter. As long as the two nodes with the same
- version are together, it's all fine. */
- if (tn->version > this->version)
- p = &(*p)->rb_left;
+ struct jffs2_raw_node_ref *ref = tn->fn->raw;
+ int err = 0, pointed = 0;
+ struct jffs2_eraseblock *jeb;
+ unsigned char *buffer;
+ uint32_t crc, ofs, len;
+ size_t retlen;
+
+ BUG_ON(tn->csize == 0);
+
+ if (!jffs2_is_writebuffered(c))
+ goto adj_acc;
+
+ /* Calculate how many bytes were already checked */
+ ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode);
+ len = ofs % c->wbuf_pagesize;
+ if (likely(len))
+ len = c->wbuf_pagesize - len;
+
+ if (len >= tn->csize) {
+ dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n",
+ ref_offset(ref), tn->csize, ofs);
+ goto adj_acc;
+ }
+
+ ofs += len;
+ len = tn->csize - len;
+
+ dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n",
+ ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len);
+
+#ifndef __ECOS
+ /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
+ * adding and jffs2_flash_read_end() interface. */
+ if (c->mtd->point) {
+ err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
+ if (!err && retlen < tn->csize) {
+ JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
+ c->mtd->unpoint(c->mtd, buffer, ofs, len);
+ } else if (err)
+ JFFS2_WARNING("MTD point failed: error code %d.\n", err);
else
- p = &(*p)->rb_right;
+ pointed = 1; /* succefully pointed to device */
+ }
+#endif
+
+ if (!pointed) {
+ buffer = kmalloc(len, GFP_KERNEL);
+ if (unlikely(!buffer))
+ return -ENOMEM;
+
+ /* TODO: this is very frequent pattern, make it a separate
+ * routine */
+ err = jffs2_flash_read(c, ofs, len, &retlen, buffer);
+ if (err) {
+ JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err);
+ goto free_out;
+ }
+
+ if (retlen != len) {
+ JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len);
+ err = -EIO;
+ goto free_out;
+ }
+ }
+
+ /* Continue calculating CRC */
+ crc = crc32(tn->partial_crc, buffer, len);
+ if(!pointed)
+ kfree(buffer);
+#ifndef __ECOS
+ else
+ c->mtd->unpoint(c->mtd, buffer, ofs, len);
+#endif
+
+ if (crc != tn->data_crc) {
+ JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
+ ofs, tn->data_crc, crc);
+ return 1;
}
- rb_link_node(&tn->rb, parent, p);
- rb_insert_color(&tn->rb, list);
+adj_acc:
+ jeb = &c->blocks[ref->flash_offset / c->sector_size];
+ len = ref_totlen(c, jeb, ref);
+ /* If it should be REF_NORMAL, it'll get marked as such when
+ we build the fragtree, shortly. No need to worry about GC
+ moving it while it's marked REF_PRISTINE -- GC won't happen
+ till we've finished checking every inode anyway. */
+ ref->flash_offset |= REF_PRISTINE;
+ /*
+ * Mark the node as having been checked and fix the
+ * accounting accordingly.
+ */
+ spin_lock(&c->erase_completion_lock);
+ jeb->used_size += len;
+ jeb->unchecked_size -= len;
+ c->used_size += len;
+ c->unchecked_size -= len;
+ jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
+ spin_unlock(&c->erase_completion_lock);
+
+ return 0;
+
+free_out:
+ if(!pointed)
+ kfree(buffer);
+#ifndef __ECOS
+ else
+ c->mtd->unpoint(c->mtd, buffer, ofs, len);
+#endif
+ return err;
+}
+
+/*
+ * Helper function for jffs2_add_older_frag_to_fragtree().
+ *
+ * Checks the node if we are in the checking stage.
+ */
+static int check_tn_node(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
+{
+ int ret;
+
+ BUG_ON(ref_obsolete(tn->fn->raw));
+
+ /* We only check the data CRC of unchecked nodes */
+ if (ref_flags(tn->fn->raw) != REF_UNCHECKED)
+ return 0;
+
+ dbg_readinode("check node %#04x-%#04x, phys offs %#08x\n",
+ tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw));
+
+ ret = check_node_data(c, tn);
+ if (unlikely(ret < 0)) {
+ JFFS2_ERROR("check_node_data() returned error: %d.\n",
+ ret);
+ } else if (unlikely(ret > 0)) {
+ dbg_readinode("CRC error, mark it obsolete.\n");
+ jffs2_mark_node_obsolete(c, tn->fn->raw);
+ }
+
+ return ret;
+}
+
+static struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uint32_t offset)
+{
+ struct rb_node *next;
+ struct jffs2_tmp_dnode_info *tn = NULL;
+
+ dbg_readinode("root %p, offset %d\n", tn_root, offset);
+
+ next = tn_root->rb_node;
+
+ while (next) {
+ tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb);
+
+ if (tn->fn->ofs < offset)
+ next = tn->rb.rb_right;
+ else if (tn->fn->ofs >= offset)
+ next = tn->rb.rb_left;
+ else
+ break;
+ }
+
+ return tn;
+}
+
+
+static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
+{
+ jffs2_mark_node_obsolete(c, tn->fn->raw);
+ jffs2_free_full_dnode(tn->fn);
+ jffs2_free_tmp_dnode_info(tn);
+}
+/*
+ * This function is used when we read an inode. Data nodes arrive in
+ * arbitrary order -- they may be older or newer than the nodes which
+ * are already in the tree. Where overlaps occur, the older node can
+ * be discarded as long as the newer passes the CRC check. We don't
+ * bother to keep track of holes in this rbtree, and neither do we deal
+ * with frags -- we can have multiple entries starting at the same
+ * offset, and the one with the smallest length will come first in the
+ * ordering.
+ *
+ * Returns 0 if the node was inserted
+ * 1 if the node is obsolete (because we can't mark it so yet)
+ * < 0 an if error occurred
+ */
+static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
+ struct jffs2_readinode_info *rii,
+ struct jffs2_tmp_dnode_info *tn)
+{
+ uint32_t fn_end = tn->fn->ofs + tn->fn->size;
+ struct jffs2_tmp_dnode_info *insert_point = NULL, *this;
+
+ dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version);
+
+ /* If a node has zero dsize, we only have to keep if it if it might be the
+ node with highest version -- i.e. the one which will end up as f->metadata.
+ Note that such nodes won't be REF_UNCHECKED since there are no data to
+ check anyway. */
+ if (!tn->fn->size) {
+ if (rii->mdata_tn) {
+ /* We had a candidate mdata node already */
+ dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version);
+ jffs2_kill_tn(c, rii->mdata_tn);
+ }
+ rii->mdata_tn = tn;
+ dbg_readinode("keep new mdata with ver %d\n", tn->version);
+ return 0;
+ }
+
+ /* Find the earliest node which _may_ be relevant to this one */
+ this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs);
+ if (!this) {
+ /* First addition to empty tree. $DEITY how I love the easy cases */
+ rb_link_node(&tn->rb, NULL, &rii->tn_root.rb_node);
+ rb_insert_color(&tn->rb, &rii->tn_root);
+ dbg_readinode("keep new frag\n");
+ return 0;
+ }
+
+ /* If we add a new node it'll be somewhere under here. */
+ insert_point = this;
+
+ /* If the node is coincident with another at a lower address,
+ back up until the other node is found. It may be relevant */
+ while (tn->overlapped)
+ tn = tn_prev(tn);
+
+ dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
+
+ while (this) {
+ if (this->fn->ofs > fn_end)
+ break;
+ dbg_readinode("Ponder this ver %d, 0x%x-0x%x\n",
+ this->version, this->fn->ofs, this->fn->size);
+
+ if (this->version == tn->version) {
+ /* Version number collision means REF_PRISTINE GC. Accept either of them
+ as long as the CRC is correct. Check the one we have already... */
+ if (!check_tn_node(c, this)) {
+ /* The one we already had was OK. Keep it and throw away the new one */
+ dbg_readinode("Like old node. Throw away new\n");
+ jffs2_kill_tn(c, tn);
+ return 0;
+ } else {
+ /* Who cares if the new one is good; keep it for now anyway. */
+ rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
+ /* Same overlapping from in front and behind */
+ tn->overlapped = this->overlapped;
+ jffs2_kill_tn(c, this);
+ dbg_readinode("Like new node. Throw away old\n");
+ return 0;
+ }
+ }
+ if (this->version < tn->version &&
+ this->fn->ofs >= tn->fn->ofs &&
+ this->fn->ofs + this->fn->size <= fn_end) {
+ /* New node entirely overlaps 'this' */
+ if (check_tn_node(c, tn)) {
+ dbg_readinode("new node bad CRC\n");
+ jffs2_kill_tn(c, tn);
+ return 0;
+ }
+ /* ... and is good. Kill 'this'... */
+ rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
+ tn->overlapped = this->overlapped;
+ jffs2_kill_tn(c, this);
+ /* ... and any subsequent nodes which are also overlapped */
+ this = tn_next(tn);
+ while (this && this->fn->ofs + this->fn->size < fn_end) {
+ struct jffs2_tmp_dnode_info *next = tn_next(this);
+ if (this->version < tn->version) {
+ tn_erase(this, &rii->tn_root);
+ dbg_readinode("Kill overlapped ver %d, 0x%x-0x%x\n",
+ this->version, this->fn->ofs,
+ this->fn->ofs+this->fn->size);
+ jffs2_kill_tn(c, this);
+ }
+ this = next;
+ }
+ dbg_readinode("Done inserting new\n");
+ return 0;
+ }
+ if (this->version > tn->version &&
+ this->fn->ofs <= tn->fn->ofs &&
+ this->fn->ofs+this->fn->size >= fn_end) {
+ /* New node entirely overlapped by 'this' */
+ if (!check_tn_node(c, this)) {
+ dbg_readinode("Good CRC on old node. Kill new\n");
+ jffs2_kill_tn(c, tn);
+ return 0;
+ }
+ /* ... but 'this' was bad. Replace it... */
+ rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
+ dbg_readinode("Bad CRC on old overlapping node. Kill it\n");
+ jffs2_kill_tn(c, this);
+ return 0;
+ }
+ /* We want to be inserted under the last node which is
+ either at a lower offset _or_ has a smaller range */
+ if (this->fn->ofs < tn->fn->ofs ||
+ (this->fn->ofs == tn->fn->ofs &&
+ this->fn->size <= tn->fn->size))
+ insert_point = this;
+
+ this = tn_next(this);
+ }
+ dbg_readinode("insert_point %p, ver %d, 0x%x-0x%x, ov %d\n",
+ insert_point, insert_point->version, insert_point->fn->ofs,
+ insert_point->fn->ofs+insert_point->fn->size,
+ insert_point->overlapped);
+ /* We neither completely obsoleted nor were completely
+ obsoleted by an earlier node. Insert under insert_point */
+ {
+ struct rb_node *parent = &insert_point->rb;
+ struct rb_node **link = &parent;
+
+ while (*link) {
+ parent = *link;
+ insert_point = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
+ if (tn->fn->ofs > insert_point->fn->ofs)
+ link = &insert_point->rb.rb_right;
+ else if (tn->fn->ofs < insert_point->fn->ofs ||
+ tn->fn->size < insert_point->fn->size)
+ link = &insert_point->rb.rb_left;
+ else
+ link = &insert_point->rb.rb_right;
+ }
+ rb_link_node(&tn->rb, &insert_point->rb, link);
+ rb_insert_color(&tn->rb, &rii->tn_root);
+ }
+ /* If there's anything behind that overlaps us, note it */
+ this = tn_prev(tn);
+ if (this) {
+ while (1) {
+ if (this->fn->ofs + this->fn->size > tn->fn->ofs) {
+ dbg_readinode("Node is overlapped by %p (v %d, 0x%x-0x%x)\n",
+ this, this->version, this->fn->ofs,
+ this->fn->ofs+this->fn->size);
+ tn->overlapped = 1;
+ break;
+ }
+ if (!this->overlapped)
+ break;
+ this = tn_prev(this);
+ }
+ }
+
+ /* If the new node overlaps anything ahead, note it */
+ this = tn_next(tn);
+ while (this && this->fn->ofs < fn_end) {
+ this->overlapped = 1;
+ dbg_readinode("Node ver %d, 0x%x-0x%x is overlapped\n",
+ this->version, this->fn->ofs,
+ this->fn->ofs+this->fn->size);
+ this = tn_next(this);
+ }
+ return 0;
+}
+
+/* Trivial function to remove the last node in the tree. Which by definition
+ has no right-hand -- so can be removed just by making its only child (if
+ any) take its place under its parent. */
+static void eat_last(struct rb_root *root, struct rb_node *node)
+{
+ struct rb_node *parent = rb_parent(node);
+ struct rb_node **link;
+
+ /* LAST! */
+ BUG_ON(node->rb_right);
+
+ if (!parent)
+ link = &root->rb_node;
+ else if (node == parent->rb_left)
+ link = &parent->rb_left;
+ else
+ link = &parent->rb_right;
+
+ *link = node->rb_left;
+ /* Colour doesn't matter now. Only the parent pointer. */
+ if (node->rb_left)
+ node->rb_left->rb_parent_color = node->rb_parent_color;
+}
+
+/* We put this in reverse order, so we can just use eat_last */
+static void ver_insert(struct rb_root *ver_root, struct jffs2_tmp_dnode_info *tn)
+{
+ struct rb_node **link = &ver_root->rb_node;
+ struct rb_node *parent = NULL;
+ struct jffs2_tmp_dnode_info *this_tn;
+
+ while (*link) {
+ parent = *link;
+ this_tn = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
+
+ if (tn->version > this_tn->version)
+ link = &parent->rb_left;
+ else
+ link = &parent->rb_right;
+ }
+ dbg_readinode("Link new node at %p (root is %p)\n", link, ver_root);
+ rb_link_node(&tn->rb, parent, link);
+ rb_insert_color(&tn->rb, ver_root);
+}
+
+/* Build final, normal fragtree from tn tree. It doesn't matter which order
+ we add nodes to the real fragtree, as long as they don't overlap. And
+ having thrown away the majority of overlapped nodes as we went, there
+ really shouldn't be many sets of nodes which do overlap. If we start at
+ the end, we can use the overlap markers -- we can just eat nodes which
+ aren't overlapped, and when we encounter nodes which _do_ overlap we
+ sort them all into a temporary tree in version order before replaying them. */
+static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
+ struct jffs2_inode_info *f,
+ struct jffs2_readinode_info *rii)
+{
+ struct jffs2_tmp_dnode_info *pen, *last, *this;
+ struct rb_root ver_root = RB_ROOT;
+ uint32_t high_ver = 0;
+
+ if (rii->mdata_tn) {
+ dbg_readinode("potential mdata is ver %d at %p\n", rii->mdata_tn->version, rii->mdata_tn);
+ high_ver = rii->mdata_tn->version;
+ rii->latest_ref = rii->mdata_tn->fn->raw;
+ }
+#ifdef JFFS2_DBG_READINODE_MESSAGES
+ this = tn_last(&rii->tn_root);
+ while (this) {
+ dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs,
+ this->fn->ofs+this->fn->size, this->overlapped);
+ this = tn_prev(this);
+ }
+#endif
+ pen = tn_last(&rii->tn_root);
+ while ((last = pen)) {
+ pen = tn_prev(last);
+
+ eat_last(&rii->tn_root, &last->rb);
+ ver_insert(&ver_root, last);
+
+ if (unlikely(last->overlapped))
+ continue;
+
+ /* Now we have a bunch of nodes in reverse version
+ order, in the tree at ver_root. Most of the time,
+ there'll actually be only one node in the 'tree',
+ in fact. */
+ this = tn_last(&ver_root);
+
+ while (this) {
+ struct jffs2_tmp_dnode_info *vers_next;
+ int ret;
+ vers_next = tn_prev(this);
+ eat_last(&ver_root, &this->rb);
+ if (check_tn_node(c, this)) {
+ dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n",
+ this->version, this->fn->ofs,
+ this->fn->ofs+this->fn->size);
+ jffs2_kill_tn(c, this);
+ } else {
+ if (this->version > high_ver) {
+ /* Note that this is different from the other
+ highest_version, because this one is only
+ counting _valid_ nodes which could give the
+ latest inode metadata */
+ high_ver = this->version;
+ rii->latest_ref = this->fn->raw;
+ }
+ dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n",
+ this, this->version, this->fn->ofs,
+ this->fn->ofs+this->fn->size, this->overlapped);
+
+ ret = jffs2_add_full_dnode_to_inode(c, f, this->fn);
+ if (ret) {
+ /* Free the nodes in vers_root; let the caller
+ deal with the rest */
+ JFFS2_ERROR("Add node to tree failed %d\n", ret);
+ while (1) {
+ vers_next = tn_prev(this);
+ if (check_tn_node(c, this))
+ jffs2_mark_node_obsolete(c, this->fn->raw);
+ jffs2_free_full_dnode(this->fn);
+ jffs2_free_tmp_dnode_info(this);
+ this = vers_next;
+ if (!this)
+ break;
+ eat_last(&ver_root, &vers_next->rb);
+ }
+ return ret;
+ }
+ jffs2_free_tmp_dnode_info(this);
+ }
+ this = vers_next;
+ }
+ }
+ return 0;
}
static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
@@ -112,8 +590,8 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r
* 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, size_t read, struct jffs2_full_dirent **fdp,
- uint32_t *latest_mctime, uint32_t *mctime_ver)
+ struct jffs2_raw_dirent *rd, size_t read,
+ struct jffs2_readinode_info *rii)
{
struct jffs2_full_dirent *fd;
uint32_t crc;
@@ -125,7 +603,8 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
- return 1;
+ jffs2_mark_node_obsolete(c, ref);
+ return 0;
}
/* If we've never checked the CRCs on this node, check them now */
@@ -137,7 +616,8 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
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;
+ jffs2_mark_node_obsolete(c, ref);
+ return 0;
}
jeb = &c->blocks[ref->flash_offset / c->sector_size];
@@ -161,10 +641,13 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
fd->ino = je32_to_cpu(rd->ino);
fd->type = rd->type;
+ if (fd->version > rii->highest_version)
+ rii->highest_version = fd->version;
+
/* Pick out the mctime of the latest dirent */
- if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) {
- *mctime_ver = fd->version;
- *latest_mctime = je32_to_cpu(rd->mctime);
+ if(fd->version > rii->mctime_ver && je32_to_cpu(rd->mctime)) {
+ rii->mctime_ver = fd->version;
+ rii->latest_mctime = je32_to_cpu(rd->mctime);
}
/*
@@ -201,7 +684,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
* Wheee. We now have a complete jffs2_full_dirent structure, with
* the name in it and everything. Link it into the list
*/
- jffs2_add_fd_to_list(c, fd, fdp);
+ jffs2_add_fd_to_list(c, fd, &rii->fds);
return 0;
}
@@ -210,13 +693,13 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
* Helper function for jffs2_get_inode_nodes().
* It is called every time an inode node is found.
*
- * Returns: 0 on succes;
+ * Returns: 0 on success;
* 1 if the node should be marked obsolete;
* negative error code on failure.
*/
static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
- struct jffs2_raw_inode *rd, struct rb_root *tnp, int rdlen,
- uint32_t *latest_mctime, uint32_t *mctime_ver)
+ struct jffs2_raw_inode *rd, int rdlen,
+ struct jffs2_readinode_info *rii)
{
struct jffs2_tmp_dnode_info *tn;
uint32_t len, csize;
@@ -230,7 +713,8 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
- return 1;
+ jffs2_mark_node_obsolete(c, ref);
+ return 0;
}
tn = jffs2_alloc_tmp_dnode_info();
@@ -342,6 +826,10 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
tn->data_crc = je32_to_cpu(rd->data_crc);
tn->csize = csize;
tn->fn->raw = ref;
+ tn->overlapped = 0;
+
+ if (tn->version > rii->highest_version)
+ rii->highest_version = tn->version;
/* There was a bug where we wrote hole nodes out with
csize/dsize swapped. Deal with it */
@@ -353,13 +841,25 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
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);
+ ret = jffs2_add_tn_to_tree(c, rii, tn);
+ if (ret) {
+ jffs2_free_full_dnode(tn->fn);
+ free_out:
+ jffs2_free_tmp_dnode_info(tn);
+ return ret;
+ }
+#ifdef JFFS2_DBG_READINODE_MESSAGES
+ dbg_readinode("After adding ver %d:\n", tn->version);
+ tn = tn_first(&rii->tn_root);
+ while (tn) {
+ dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n",
+ tn, tn->version, tn->fn->ofs,
+ tn->fn->ofs+tn->fn->size, tn->overlapped);
+ tn = tn_next(tn);
+ }
+#endif
return 0;
-
-free_out:
- jffs2_free_tmp_dnode_info(tn);
- return ret;
}
/*
@@ -379,7 +879,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
- return 1;
+ jffs2_mark_node_obsolete(c, ref);
+ return 0;
}
un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
@@ -407,7 +908,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
case JFFS2_FEATURE_RWCOMPAT_DELETE:
JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
je16_to_cpu(un->nodetype), ref_offset(ref));
- return 1;
+ jffs2_mark_node_obsolete(c, ref);
+ return 0;
}
return 0;
@@ -421,92 +923,62 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
* negative error code on failure.
*/
static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
- int right_size, int *rdlen, unsigned char *buf, unsigned char *bufstart)
+ int needed_len, int *rdlen, unsigned char *buf)
{
- int right_len, err, len;
+ int err, to_read = needed_len - *rdlen;
size_t retlen;
uint32_t offs;
if (jffs2_is_writebuffered(c)) {
- right_len = c->wbuf_pagesize - (bufstart - buf);
- if (right_size + (int)(bufstart - buf) > c->wbuf_pagesize)
- right_len += c->wbuf_pagesize;
- } else
- right_len = right_size;
+ int rem = to_read % c->wbuf_pagesize;
- if (*rdlen == right_len)
- return 0;
+ if (rem)
+ to_read += c->wbuf_pagesize - rem;
+ }
/* We need to read more data */
offs = ref_offset(ref) + *rdlen;
- if (jffs2_is_writebuffered(c)) {
- bufstart = buf + c->wbuf_pagesize;
- len = c->wbuf_pagesize;
- } else {
- bufstart = buf + *rdlen;
- len = right_size - *rdlen;
- }
- dbg_readinode("read more %d bytes\n", len);
+ dbg_readinode("read more %d bytes\n", to_read);
- err = jffs2_flash_read(c, offs, len, &retlen, bufstart);
+ err = jffs2_flash_read(c, offs, to_read, &retlen, buf + *rdlen);
if (err) {
JFFS2_ERROR("can not read %d bytes from 0x%08x, "
- "error code: %d.\n", len, offs, err);
+ "error code: %d.\n", to_read, offs, err);
return err;
}
- if (retlen < len) {
+ if (retlen < to_read) {
JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
- offs, retlen, len);
+ offs, retlen, to_read);
return -EIO;
}
- *rdlen = right_len;
-
+ *rdlen += to_read;
return 0;
}
/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
- with this ino, returning the former in order of version */
+ with this ino. Perform a preliminary ordering on data nodes, throwing away
+ those which are completely obsoleted by newer ones. The naïve approach we
+ use to take of just returning them _all_ in version order will cause us to
+ run out of memory in certain degenerate cases. */
static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
- struct rb_root *tnp, struct jffs2_full_dirent **fdp,
- uint32_t *highest_version, uint32_t *latest_mctime,
- uint32_t *mctime_ver)
+ struct jffs2_readinode_info *rii)
{
struct jffs2_raw_node_ref *ref, *valid_ref;
- struct rb_root ret_tn = RB_ROOT;
- struct jffs2_full_dirent *ret_fd = NULL;
unsigned char *buf = NULL;
union jffs2_node_union *node;
size_t retlen;
int len, err;
- *mctime_ver = 0;
+ rii->mctime_ver = 0;
dbg_readinode("ino #%u\n", f->inocache->ino);
- if (jffs2_is_writebuffered(c)) {
- /*
- * If we have the write buffer, we assume the minimal I/O unit
- * is c->wbuf_pagesize. We implement some optimizations which in
- * this case and we need a temporary buffer of size =
- * 2*c->wbuf_pagesize bytes (see comments in read_dnode()).
- * Basically, we want to read not only the node header, but the
- * whole wbuf (NAND page in case of NAND) or 2, if the node
- * header overlaps the border between the 2 wbufs.
- */
- len = 2*c->wbuf_pagesize;
- } else {
- /*
- * When there is no write buffer, the size of the temporary
- * buffer is the size of the larges node header.
- */
- len = sizeof(union jffs2_node_union);
- }
-
/* FIXME: in case of NOR and available ->point() this
* needs to be fixed. */
+ len = sizeof(union jffs2_node_union) + c->wbuf_pagesize;
buf = kmalloc(len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -516,8 +988,6 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
if (!valid_ref && f->inocache->ino != 1)
JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino);
while (valid_ref) {
- unsigned char *bufstart;
-
/* We can hold a pointer to a non-obsolete node without the spinlock,
but _obsolete_ nodes may disappear at any time, if the block
they're in gets erased. So if we mark 'ref' obsolete while we're
@@ -533,32 +1003,31 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
/*
* At this point we don't know the type of the node we're going
* to read, so we do not know the size of its header. In order
- * to minimize the amount of flash IO we assume the node has
- * size = JFFS2_MIN_NODE_HEADER.
+ * to minimize the amount of flash IO we assume the header is
+ * of size = JFFS2_MIN_NODE_HEADER.
*/
+ len = JFFS2_MIN_NODE_HEADER;
if (jffs2_is_writebuffered(c)) {
+ int end, rem;
+
/*
- * 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.
+ * We are about to read JFFS2_MIN_NODE_HEADER bytes,
+ * but this flash has some minimal I/O unit. It is
+ * possible that we'll need to read more soon, so read
+ * up to the next min. I/O unit, in order not to
+ * re-read the same min. I/O unit twice.
*/
- 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 */
- len += c->wbuf_pagesize;
- }
- } else {
- bufstart = buf;
- len = JFFS2_MIN_NODE_HEADER;
+ end = ref_offset(ref) + len;
+ rem = end % c->wbuf_pagesize;
+ if (rem)
+ end += c->wbuf_pagesize - rem;
+ len = end - ref_offset(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,
- &retlen, bufstart);
+ err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf);
if (err) {
JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err);
goto free_out;
@@ -570,7 +1039,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
goto free_out;
}
- node = (union jffs2_node_union *)bufstart;
+ node = (union jffs2_node_union *)buf;
/* No need to mask in the valid bit; it shouldn't be invalid */
if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
@@ -583,10 +1052,10 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
jffs2_mark_node_obsolete(c, ref);
goto cont;
}
- /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */
- if (!je32_to_cpu(node->u.hdr_crc) && !je16_to_cpu(node->u.nodetype) &&
- !je16_to_cpu(node->u.magic) && !je32_to_cpu(node->u.totlen)) {
- JFFS2_NOTICE("All zero node header at %#08x.\n", ref_offset(ref));
+ if (je16_to_cpu(node->u.magic) != JFFS2_MAGIC_BITMASK) {
+ /* Not a JFFS2 node, whinge and move on */
+ JFFS2_NOTICE("Wrong magic bitmask 0x%04x in node header at %#08x.\n",
+ je16_to_cpu(node->u.magic), ref_offset(ref));
jffs2_mark_node_obsolete(c, ref);
goto cont;
}
@@ -596,46 +1065,34 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
case JFFS2_NODETYPE_DIRENT:
if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) {
- err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf, bufstart);
+ err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf);
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))
+ err = read_direntry(c, ref, &node->d, retlen, rii);
+ 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);
+ err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf);
if (unlikely(err))
goto free_out;
}
- err = read_dnode(c, ref, &node->i, &ret_tn, len, latest_mctime, mctime_ver);
- if (err == 1) {
- jffs2_mark_node_obsolete(c, ref);
- break;
- } else if (unlikely(err))
+ err = read_dnode(c, ref, &node->i, len, rii);
+ if (unlikely(err))
goto free_out;
- if (je32_to_cpu(node->i.version) > *highest_version)
- *highest_version = je32_to_cpu(node->i.version);
-
break;
default:
if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) {
- err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf, bufstart);
+ err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf);
if (unlikely(err))
goto free_out;
}
@@ -653,17 +1110,19 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
}
spin_unlock(&c->erase_completion_lock);
- *tnp = ret_tn;
- *fdp = ret_fd;
kfree(buf);
+ f->highest_version = rii->highest_version;
+
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);
+ f->inocache->ino, rii->highest_version, rii->latest_mctime,
+ rii->mctime_ver);
return 0;
free_out:
- jffs2_free_tmp_dnode_info_list(&ret_tn);
- jffs2_free_full_dirent_list(ret_fd);
+ jffs2_free_tmp_dnode_info_list(&rii->tn_root);
+ jffs2_free_full_dirent_list(rii->fds);
+ rii->fds = NULL;
kfree(buf);
return err;
}
@@ -672,20 +1131,17 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
struct jffs2_inode_info *f,
struct jffs2_raw_inode *latest_node)
{
- struct jffs2_tmp_dnode_info *tn;
- struct rb_root tn_list;
- struct rb_node *rb, *repl_rb;
- struct jffs2_full_dirent *fd_list;
- struct jffs2_full_dnode *fn, *first_fn = NULL;
- uint32_t crc;
- uint32_t latest_mctime, mctime_ver;
+ struct jffs2_readinode_info rii;
+ uint32_t crc, new_size;
size_t retlen;
int ret;
dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
+ memset(&rii, 0, sizeof(rii));
+
/* 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);
+ ret = jffs2_get_inode_nodes(c, f, &rii);
if (ret) {
JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret);
@@ -693,74 +1149,42 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
return ret;
}
- f->dents = fd_list;
-
- rb = rb_first(&tn_list);
- while (rb) {
- cond_resched();
- tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);
- fn = tn->fn;
- ret = 1;
- 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);
-
- if (fn->size) {
- ret = jffs2_add_older_frag_to_fragtree(c, f, tn);
- /* TODO: the error code isn't checked, check it */
- jffs2_dbg_fragtree_paranoia_check_nolock(f);
- BUG_ON(ret < 0);
- if (!first_fn && ret == 0)
- first_fn = fn;
- } else if (!first_fn) {
- first_fn = fn;
- f->metadata = fn;
- ret = 0; /* Prevent freeing the metadata update node */
- } else
- jffs2_mark_node_obsolete(c, fn->raw);
-
- BUG_ON(rb->rb_left);
- if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) {
- /* We were then left-hand child of our parent. We need
- * to move our own right-hand child into our place. */
- repl_rb = rb->rb_right;
- if (repl_rb)
- rb_set_parent(repl_rb, rb_parent(rb));
- } else
- repl_rb = NULL;
-
- rb = rb_next(rb);
-
- /* Remove the spent tn from the tree; don't bother rebalancing
- * but put our right-hand child in our own place. */
- if (rb_parent(&tn->rb)) {
- if (rb_parent(&tn->rb)->rb_left == &tn->rb)
- rb_parent(&tn->rb)->rb_left = repl_rb;
- else if (rb_parent(&tn->rb)->rb_right == &tn->rb)
- rb_parent(&tn->rb)->rb_right = repl_rb;
- else BUG();
- } else if (tn->rb.rb_right)
- rb_set_parent(tn->rb.rb_right, NULL);
+ ret = jffs2_build_inode_fragtree(c, f, &rii);
+ if (ret) {
+ JFFS2_ERROR("Failed to build final fragtree for inode #%u: error %d\n",
+ f->inocache->ino, ret);
+ if (f->inocache->state == INO_STATE_READING)
+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
+ jffs2_free_tmp_dnode_info_list(&rii.tn_root);
+ /* FIXME: We could at least crc-check them all */
+ if (rii.mdata_tn) {
+ jffs2_free_full_dnode(rii.mdata_tn->fn);
+ jffs2_free_tmp_dnode_info(rii.mdata_tn);
+ rii.mdata_tn = NULL;
+ }
+ return ret;
+ }
- jffs2_free_tmp_dnode_info(tn);
- if (ret) {
- dbg_readinode("delete dnode %u-%u.\n",
- fn->ofs, fn->ofs + fn->size);
- jffs2_free_full_dnode(fn);
+ if (rii.mdata_tn) {
+ if (rii.mdata_tn->fn->raw == rii.latest_ref) {
+ f->metadata = rii.mdata_tn->fn;
+ jffs2_free_tmp_dnode_info(rii.mdata_tn);
+ } else {
+ jffs2_kill_tn(c, rii.mdata_tn);
}
+ rii.mdata_tn = NULL;
}
- jffs2_dbg_fragtree_paranoia_check_nolock(f);
- BUG_ON(first_fn && ref_obsolete(first_fn->raw));
+ f->dents = rii.fds;
- fn = first_fn;
- if (unlikely(!first_fn)) {
+ jffs2_dbg_fragtree_paranoia_check_nolock(f);
+
+ if (unlikely(!rii.latest_ref)) {
/* No data nodes for this inode. */
if (f->inocache->ino != 1) {
JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino);
- if (!fd_list) {
+ if (!rii.fds) {
if (f->inocache->state == INO_STATE_READING)
jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
return -EIO;
@@ -778,7 +1202,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
return 0;
}
- ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node);
+ ret = jffs2_flash_read(c, ref_offset(rii.latest_ref), sizeof(*latest_node), &retlen, (void *)latest_node);
if (ret || retlen != sizeof(*latest_node)) {
JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
ret, retlen, sizeof(*latest_node));
@@ -791,7 +1215,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
crc = crc32(0, latest_node, sizeof(*latest_node)-8);
if (crc != je32_to_cpu(latest_node->node_crc)) {
JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
- f->inocache->ino, ref_offset(fn->raw));
+ f->inocache->ino, ref_offset(rii.latest_ref));
up(&f->sem);
jffs2_do_clear_inode(c, f);
return -EIO;
@@ -799,17 +1223,22 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
case S_IFDIR:
- if (mctime_ver > je32_to_cpu(latest_node->version)) {
+ if (rii.mctime_ver > je32_to_cpu(latest_node->version)) {
/* The times in the latest_node are actually older than
mctime in the latest dirent. Cheat. */
- latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime);
+ latest_node->ctime = latest_node->mtime = cpu_to_je32(rii.latest_mctime);
}
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));
+ new_size = jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
+ if (new_size != je32_to_cpu(latest_node->isize)) {
+ JFFS2_WARNING("Truncating ino #%u to %d bytes failed because it only had %d bytes to start with!\n",
+ f->inocache->ino, je32_to_cpu(latest_node->isize), new_size);
+ latest_node->isize = cpu_to_je32(new_size);
+ }
break;
case S_IFLNK:
@@ -832,7 +1261,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
return -ENOMEM;
}
- ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),
+ ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node),
je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);
if (ret || retlen != je32_to_cpu(latest_node->csize)) {
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 7fb45bd4915..2a1c976c792 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -1,15 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: scan.c,v 1.125 2005/09/30 13:59:13 dedekind Exp $
- *
*/
+
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -636,16 +635,17 @@ scan_more:
if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) {
uint32_t inbuf_ofs;
- uint32_t empty_start;
+ uint32_t empty_start, scan_end;
empty_start = ofs;
ofs += 4;
+ scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE(c->sector_size)/8, buf_len);
D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs));
more_empty:
inbuf_ofs = ofs - buf_ofs;
- while (inbuf_ofs < buf_len) {
- if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) {
+ while (inbuf_ofs < scan_end) {
+ if (unlikely(*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)) {
printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
empty_start, ofs);
if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
@@ -666,7 +666,11 @@ scan_more:
D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));
return BLK_STATE_CLEANMARKER;
}
-
+ if (!buf_size && (scan_end != buf_len)) {/* XIP/point case */
+ scan_end = buf_len;
+ goto more_empty;
+ }
+
/* See how much more there is to read in this eraseblock... */
buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
if (!buf_len) {
@@ -676,6 +680,8 @@ scan_more:
empty_start));
break;
}
+ /* point never reaches here */
+ scan_end = buf_len;
D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x\n", buf_len, ofs));
err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
if (err)
@@ -734,18 +740,8 @@ scan_more:
ofs += 4;
continue;
}
- /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */
- if (!je32_to_cpu(node->hdr_crc) && !je16_to_cpu(node->nodetype) &&
- !je16_to_cpu(node->magic) && !je32_to_cpu(node->totlen)) {
- noisy_printk(&noise, "jffs2_scan_eraseblock(): All zero node header at 0x%08x.\n", ofs);
- if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
- return err;
- ofs += 4;
- continue;
- }
- if (ofs + je32_to_cpu(node->totlen) >
- jeb->offset + c->sector_size) {
+ if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) {
/* Eep. Node goes over the end of the erase block. */
printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
ofs, je32_to_cpu(node->totlen));
@@ -952,8 +948,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
{
struct jffs2_inode_cache *ic;
- uint32_t ino = je32_to_cpu(ri->ino);
- int err;
+ uint32_t crc, ino = je32_to_cpu(ri->ino);
D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));
@@ -966,21 +961,22 @@ 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. */
+ /* Check the node CRC in any case. */
+ crc = crc32(0, ri, sizeof(*ri)-8);
+ if (crc != je32_to_cpu(ri->node_crc)) {
+ printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on "
+ "node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+ ofs, je32_to_cpu(ri->node_crc), crc);
+ /*
+ * We believe totlen because the CRC on the node
+ * _header_ was OK, just the node itself failed.
+ */
+ return jffs2_scan_dirty_space(c, jeb,
+ PAD(je32_to_cpu(ri->totlen)));
+ }
+
ic = jffs2_get_ino_cache(c, ino);
if (!ic) {
- /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
- first node we found for this inode. Do a CRC check to protect against the former
- case */
- uint32_t crc = crc32(0, ri, sizeof(*ri)-8);
-
- if (crc != je32_to_cpu(ri->node_crc)) {
- printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
- ofs, je32_to_cpu(ri->node_crc), crc);
- /* 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;
- return 0;
- }
ic = jffs2_scan_make_ino_cache(c, ino);
if (!ic)
return -ENOMEM;
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index 52a9894a636..bc9f6ba1082 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -1,13 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2006 NEC Corporation
+ * Copyright © 2006 NEC Corporation
*
* Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
*/
+
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 30f888414ce..d828b296392 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -1,16 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
- * Zoltan Sogor <weth@inf.u-szeged.hu>,
- * Patrik Kluba <pajko@halom.u-szeged.hu>,
- * University of Szeged, Hungary
- * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
+ * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
+ * Zoltan Sogor <weth@inf.u-szeged.hu>,
+ * Patrik Kluba <pajko@halom.u-szeged.hu>,
+ * University of Szeged, Hungary
+ * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: summary.c,v 1.4 2005/09/26 11:37:21 havasi Exp $
- *
*/
#include <linux/kernel.h>
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
index 6bf1f6aa455..0c6669e2139 100644
--- a/fs/jffs2/summary.h
+++ b/fs/jffs2/summary.h
@@ -1,15 +1,13 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
- * Zoltan Sogor <weth@inf.u-szeged.hu>,
- * Patrik Kluba <pajko@halom.u-szeged.hu>,
- * University of Szeged, Hungary
+ * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
+ * Zoltan Sogor <weth@inf.u-szeged.hu>,
+ * Patrik Kluba <pajko@halom.u-szeged.hu>,
+ * University of Szeged, Hungary
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: summary.h,v 1.2 2005/09/26 11:37:21 havasi Exp $
- *
*/
#ifndef JFFS2_SUMMARY_H
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index cc7e8e71ad4..e51164a8a8d 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: super.c,v 1.110 2005/11/07 11:14:42 gleixner Exp $
- *
*/
#include <linux/kernel.h>
@@ -347,7 +345,7 @@ static int __init init_jffs2_fs(void)
#ifdef CONFIG_JFFS2_SUMMARY
" (SUMMARY) "
#endif
- " (C) 2001-2006 Red Hat, Inc.\n");
+ " © 2001-2006 Red Hat, Inc.\n");
jffs2_inode_cachep = kmem_cache_create("jffs2_i",
sizeof(struct jffs2_inode_info),
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index 7e4882c8a7e..b7339c3b6ad 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -1,17 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001, 2002 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: symlink.c,v 1.19 2005/11/07 11:14:42 gleixner Exp $
- *
*/
-
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 4fac6dd5395..c556e85a565 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -1,16 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
- * Copyright (C) 2004 Thomas Gleixner <tglx@linutronix.de>
+ * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004 Thomas Gleixner <tglx@linutronix.de>
*
* Created by David Woodhouse <dwmw2@infradead.org>
* Modified debugged and enhanced by Thomas Gleixner <tglx@linutronix.de>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: wbuf.c,v 1.100 2005/09/30 13:59:13 dedekind Exp $
- *
*/
#include <linux/kernel.h>
@@ -345,6 +343,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
return;
}
+ /* The summary is not recovered, so it must be disabled for this erase block */
+ jffs2_sum_disable_collecting(c->summary);
+
ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, nr_refile);
if (ret) {
printk(KERN_WARNING "Failed to allocate node refs for wbuf recovery. Data loss ensues.\n");
@@ -967,9 +968,9 @@ exit:
static const struct jffs2_unknown_node oob_cleanmarker =
{
- .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK),
- .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
- .totlen = cpu_to_je32(8)
+ .magic = constant_cpu_to_je16(JFFS2_MAGIC_BITMASK),
+ .nodetype = constant_cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
+ .totlen = constant_cpu_to_je32(8)
};
/*
@@ -1208,3 +1209,27 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) {
kfree(c->wbuf);
}
+
+int jffs2_ubivol_setup(struct jffs2_sb_info *c) {
+ c->cleanmarker_size = 0;
+
+ if (c->mtd->writesize == 1)
+ /* We do not need write-buffer */
+ return 0;
+
+ init_rwsem(&c->wbuf_sem);
+
+ c->wbuf_pagesize = c->mtd->writesize;
+ c->wbuf_ofs = 0xFFFFFFFF;
+ c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
+ if (!c->wbuf)
+ return -ENOMEM;
+
+ printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size);
+
+ return 0;
+}
+
+void jffs2_ubivol_cleanup(struct jffs2_sb_info *c) {
+ kfree(c->wbuf);
+}
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 67176792e13..c9fe0ab3a32 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: write.c,v 1.97 2005/11/07 11:14:42 gleixner Exp $
- *
*/
#include <linux/kernel.h>
@@ -507,8 +505,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
uint32_t alloclen;
int ret;
- if (1 /* alternative branch needs testing */ ||
- !jffs2_can_mark_obsolete(c)) {
+ if (!jffs2_can_mark_obsolete(c)) {
/* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */
rd = jffs2_alloc_raw_dirent();
diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c
index c638ae1008d..b9276b11bac 100644
--- a/fs/jffs2/writev.c
+++ b/fs/jffs2/writev.c
@@ -1,14 +1,12 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2001, 2002 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: writev.c,v 1.8 2005/09/09 15:11:58 havasi Exp $
- *
*/
#include <linux/kernel.h>
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 4bb3f189733..78fc08893a6 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -1,13 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2006 NEC Corporation
+ * Copyright © 2006 NEC Corporation
*
* Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
*/
+
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 06a5c69dcf8..3b0ff292593 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -1,13 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2006 NEC Corporation
+ * Copyright © 2006 NEC Corporation
*
* Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* 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 ed046e19dbf..8ec5765ef34 100644
--- a/fs/jffs2/xattr_trusted.c
+++ b/fs/jffs2/xattr_trusted.c
@@ -1,13 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2006 NEC Corporation
+ * Copyright © 2006 NEC Corporation
*
* Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
*/
+
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/jffs2.h>
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
index 2f8e9aa01ea..40942bc516b 100644
--- a/fs/jffs2/xattr_user.c
+++ b/fs/jffs2/xattr_user.c
@@ -1,13 +1,14 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
- * Copyright (C) 2006 NEC Corporation
+ * Copyright © 2006 NEC Corporation
*
* Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
*/
+
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/jffs2.h>