#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/pagemap.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <asm/byteorder.h>
#include <linux/smp_lock.h>
#include <linux/time.h>
#include "jffs_fm.h"
long no_jffs_node = 0;
-long no_jffs_file = 0;
+static long no_jffs_file = 0;
#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
long no_jffs_control = 0;
long no_jffs_raw_inode = 0;
static int jffs_scan_flash(struct jffs_control *c);
static int jffs_update_file(struct jffs_file *f, struct jffs_node *node);
+static int jffs_build_file(struct jffs_file *f);
+static int jffs_free_file(struct jffs_file *f);
+static int jffs_free_node_list(struct jffs_file *f);
+static int jffs_garbage_collect_now(struct jffs_control *c);
+static int jffs_insert_file_into_hash(struct jffs_file *f);
+static int jffs_remove_redundant_nodes(struct jffs_file *f);
+
+/* Is there enough space on the flash? */
+static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c, __u32 space)
+{
+ struct jffs_fmcontrol *fmc = c->fmc;
+
+ while (1) {
+ if ((fmc->flash_size - (fmc->used_size + fmc->dirty_size))
+ >= fmc->min_free_size + space) {
+ return 1;
+ }
+ if (fmc->dirty_size < fmc->sector_size)
+ return 0;
+
+ if (jffs_garbage_collect_now(c)) {
+ D1(printk("JFFS_ENOUGH_SPACE: jffs_garbage_collect_now() failed.\n"));
+ return 0;
+ }
+ }
+}
#if CONFIG_JFFS_FS_VERBOSE > 0
static __u8
}
}
+/* Print the contents of a node. */
+static void
+jffs_print_node(struct jffs_node *n)
+{
+ D(printk("jffs_node: 0x%p\n", n));
+ D(printk("{\n"));
+ D(printk(" 0x%08x, /* version */\n", n->version));
+ D(printk(" 0x%08x, /* data_offset */\n", n->data_offset));
+ D(printk(" 0x%08x, /* data_size */\n", n->data_size));
+ D(printk(" 0x%08x, /* removed_size */\n", n->removed_size));
+ D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset));
+ D(printk(" 0x%02x, /* name_size */\n", n->name_size));
+ D(printk(" 0x%p, /* fm, fm->offset: %u */\n",
+ n->fm, (n->fm ? n->fm->offset : 0)));
+ D(printk(" 0x%p, /* version_prev */\n", n->version_prev));
+ D(printk(" 0x%p, /* version_next */\n", n->version_next));
+ D(printk(" 0x%p, /* range_prev */\n", n->range_prev));
+ D(printk(" 0x%p, /* range_next */\n", n->range_next));
+ D(printk("}\n"));
+}
+
#endif
+/* Print the contents of a raw inode. */
+static void
+jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
+{
+ D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
+ D(printk("{\n"));
+ D(printk(" 0x%08x, /* magic */\n", raw_inode->magic));
+ D(printk(" 0x%08x, /* ino */\n", raw_inode->ino));
+ D(printk(" 0x%08x, /* pino */\n", raw_inode->pino));
+ D(printk(" 0x%08x, /* version */\n", raw_inode->version));
+ D(printk(" 0x%08x, /* mode */\n", raw_inode->mode));
+ D(printk(" 0x%04x, /* uid */\n", raw_inode->uid));
+ D(printk(" 0x%04x, /* gid */\n", raw_inode->gid));
+ D(printk(" 0x%08x, /* atime */\n", raw_inode->atime));
+ D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime));
+ D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime));
+ D(printk(" 0x%08x, /* offset */\n", raw_inode->offset));
+ D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize));
+ D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize));
+ D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize));
+ D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink));
+ D(printk(" 0x%02x, /* spare */\n",
+ raw_inode->spare));
+ D(printk(" %u, /* rename */\n",
+ raw_inode->rename));
+ D(printk(" %u, /* deleted */\n",
+ raw_inode->deleted));
+ D(printk(" 0x%02x, /* accurate */\n",
+ raw_inode->accurate));
+ D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum));
+ D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum));
+ D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum));
+ D(printk("}\n"));
+}
+
#define flash_safe_acquire(arg)
#define flash_safe_release(arg)
static int
-flash_safe_writev(struct mtd_info *mtd, const struct iovec *vecs,
+flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs,
unsigned long iovec_cnt, loff_t to)
{
size_t retlen, retlen_a;
}
/* This routine calculates checksums in JFFS. */
-__u32
+static __u32
jffs_checksum(const void *data, int size)
{
__u32 sum = 0;
}
-int
+static int
jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result)
{
__u32 sum = 0;
}
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
/* Return result */
D3(printk("checksum result: 0x%08x\n", sum));
if (!(f = (struct jffs_file *)kmalloc(sizeof(struct jffs_file),
GFP_KERNEL))) {
D(printk("jffs_create_file(): Failed!\n"));
- return 0;
+ return NULL;
}
no_jffs_file++;
memset(f, 0, sizeof(struct jffs_file));
goto fail_control;
}
DJM(no_jffs_control++);
- c->root = 0;
- c->gc_task = 0;
+ c->root = NULL;
+ c->gc_task = NULL;
c->hash_len = JFFS_HASH_SIZE;
s = sizeof(struct list_head) * c->hash_len;
if (!(c->hash = (struct list_head *)kmalloc(s, GFP_KERNEL))) {
a (even) higher degree of confidence in your mount process.
A higher number would of course slow down your mount.
*/
-int check_partly_erased_sectors(struct jffs_fmcontrol *fmc){
+static int check_partly_erased_sectors(struct jffs_fmcontrol *fmc){
#define NUM_REREADS 4 /* see note above */
#define READ_AHEAD_BYTES 4096 /* must be a multiple of 4,
{
char name[JFFS_MAX_NAME_LEN + 2];
struct jffs_raw_inode raw_inode;
- struct jffs_node *node = 0;
+ struct jffs_node *node = NULL;
struct jffs_fmcontrol *fmc = c->fmc;
__u32 checksum;
__u8 tmp_accurate;
D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n",
(unsigned int) start, (unsigned int) (pos - start)));
jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
+ (__u32) (pos - start), NULL);
}else{
/* "Flipping bits" detected. This means that our scan for them
did not catch this offset. See check_partly_erased_sectors() for
offset , fmc->sector_size);
flash_safe_release(fmc->mtd);
- kfree (read_buf);
+ kfree(read_buf);
return -1; /* bad, bad, bad! */
}
flash_safe_release(fmc->mtd);
- kfree (read_buf);
+ kfree(read_buf);
return -EAGAIN; /* erased offending sector. Try mount one more time please. */
}
D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n",
(unsigned int) start, (unsigned int) (pos - start)));
jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
+ (__u32) (pos - start), NULL);
}
}
D1(printk("jffs_scan_flash(): 0x00 ended at "
"pos 0x%lx.\n", (long)pos));
jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
+ (__u32) (pos - start), NULL);
continue;
case JFFS_MAGIC_BITMASK:
which really does contain crap. */
jffs_fmalloced(fmc, (__u32) start,
(__u32) (pos - start),
- 0);
+ NULL);
continue;
}/* switch */
if (!node) {
if (!(node = jffs_alloc_node())) {
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
/* Release the flash device */
flash_safe_release(fmc->mtd);
checksum, raw_inode.chksum));
pos += sizeof(struct jffs_raw_inode);
jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
+ (__u32) (pos - start), NULL);
/* Reuse this unused struct jffs_node. */
continue;
}
"raw_inode.nchksum = %u\n",
checksum, raw_inode.nchksum));
jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
+ (__u32) (pos - start), NULL);
/* Reuse this unused struct jffs_node. */
continue;
}
if (jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize, &checksum)) {
printk("jffs_checksum_flash() failed to calculate a checksum\n");
jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
+ (__u32) (pos - start), NULL);
/* Reuse this unused struct jffs_node. */
continue;
}
"raw_inode.dchksum = %u\n",
checksum, raw_inode.dchksum));
jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
+ (__u32) (pos - start), NULL);
/* Reuse this unused struct jffs_node. */
continue;
}
DJM(no_jffs_node--);
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
/* Release the flash device */
flash_safe_release(fmc->mtd);
return -ENOMEM;
}
- if ((err = jffs_insert_node(c, 0, &raw_inode,
+ if ((err = jffs_insert_node(c, NULL, &raw_inode,
name, node)) < 0) {
printk("JFFS: Failed to handle raw inode. "
"(err = %d)\n", err);
flash_safe_release(fmc->flash_part);
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
return -ENOMEM;
}
node->data_size = 0;
}
D3(jffs_print_node(node));
- node = 0; /* Don't free the node! */
+ node = NULL; /* Don't free the node! */
}
else {
jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
+ (__u32) (pos - start), NULL);
D3(printk("jffs_scan_flash(): Just found an obsolete "
"raw_inode. Continuing the scan...\n"));
/* Reuse this unused struct jffs_node. */
jffs_build_end(fmc);
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
if(!num_free_space){
printk(KERN_WARNING "jffs_scan_flash(): Did not find even a single "
/* This is the first node. */
f->version_head = node;
f->version_tail = node;
- node->version_prev = 0;
- node->version_next = 0;
+ node->version_prev = NULL;
+ node->version_next = NULL;
f->highest_version = node->version;
update_name = 1;
f->mode = raw_inode->mode;
/* Insert at the end of the list. I.e. this node is the
newest one so far. */
node->version_prev = f->version_tail;
- node->version_next = 0;
+ node->version_next = NULL;
f->version_tail->version_next = node;
f->version_tail = node;
f->highest_version = node->version;
}
else if (f->version_head->version > node->version) {
/* Insert at the bottom of the list. */
- node->version_prev = 0;
+ node->version_prev = NULL;
node->version_next = f->version_head;
f->version_head->version_prev = node;
f->version_head = node;
/* Remove redundant nodes from a file. Mark the on-flash memory
as dirty. */
-int
+static int
jffs_remove_redundant_nodes(struct jffs_file *f)
{
struct jffs_node *newest_node;
/* Insert a file into the hash table. */
-int
+static int
jffs_insert_file_into_hash(struct jffs_file *f)
{
int i = f->ino % f->c->hash_len;
if (!(parent = jffs_find_file(f->c, f->pino))) {
if (f->pino == 0) {
f->c->root = f;
- f->parent = 0;
- f->sibling_prev = 0;
- f->sibling_next = 0;
+ f->parent = NULL;
+ f->sibling_prev = NULL;
+ f->sibling_next = NULL;
return 0;
}
else {
if (f->sibling_next) {
f->sibling_next->sibling_prev = f;
}
- f->sibling_prev = 0;
+ f->sibling_prev = NULL;
parent->children = f;
return 0;
}
/* Remove a file from the hash table. */
-int
+static int
jffs_unlink_file_from_hash(struct jffs_file *f)
{
D3(printk("jffs_unlink_file_from_hash(): f: 0x%p, "
{
struct jffs_file *f;
int i = ino % c->hash_len;
- struct list_head *tmp;
D3(printk("jffs_find_file(): ino: %u\n", ino));
- for (tmp = c->hash[i].next; tmp != &c->hash[i]; tmp = tmp->next) {
- f = list_entry(tmp, struct jffs_file, hash);
+ list_for_each_entry(f, &c->hash[i], hash) {
if (ino != f->ino)
continue;
D3(printk("jffs_find_file(): Found file with ino "
}
printk("jffs_find_child(): Didn't find the file \"%s\".\n",
(copy ? copy : ""));
- if (copy) {
- kfree(copy);
- }
+ kfree(copy);
});
return f;
{
struct jffs_fmcontrol *fmc = c->fmc;
struct jffs_fm *fm;
- struct iovec node_iovec[4];
+ struct kvec node_iovec[4];
unsigned long iovec_cnt;
__u32 pos;
iovec_cnt++;
if (JFFS_GET_PAD_BYTES(raw_inode->nsize)) {
- static char allff[3]={255,255,255};
+ static unsigned char allff[3]={255,255,255};
/* Add some extra padding if necessary */
node_iovec[iovec_cnt].iov_base = allff;
node_iovec[iovec_cnt].iov_len =
int result = 0;
for (pos = 0; pos < c->hash_len; pos++) {
- struct list_head *p, *next;
- for (p = c->hash[pos].next; p != &c->hash[pos]; p = next) {
- /* We need a reference to the next file in the
- list because `func' might remove the current
- file `f'. */
- next = p->next;
- r = func(list_entry(p, struct jffs_file, hash));
+ struct jffs_file *f, *next;
+
+ /* We must do _safe, because 'func' might remove the
+ current file 'f' from the list. */
+ list_for_each_entry_safe(f, next, &c->hash[pos], hash) {
+ r = func(f);
if (r < 0)
return r;
result += r;
/* Free all nodes associated with a file. */
-int
+static int
jffs_free_node_list(struct jffs_file *f)
{
struct jffs_node *node;
/* Free a file and its name. */
-int
+static int
jffs_free_file(struct jffs_file *f)
{
D3(printk("jffs_free_file: f #%u, \"%s\"\n",
return 0;
}
-long
+static long
jffs_get_file_count(void)
{
return no_jffs_file;
/* Build up a file's range list from scratch by going through the
version list. */
-int
+static int
jffs_build_file(struct jffs_file *f)
{
struct jffs_node *n;
retry:
if (node->data_offset == f->size) {
/* A simple append. This is the most common operation. */
- node->range_next = 0;
+ node->range_next = NULL;
node->range_prev = f->range_tail;
if (node->range_prev) {
node->range_prev->range_next = node;
virtual_node->removed_size = 0;
virtual_node->fm_offset = 0;
virtual_node->name_size = 0;
- virtual_node->fm = 0; /* This is a virtual data holder. */
- virtual_node->version_prev = 0;
- virtual_node->version_next = 0;
- virtual_node->range_next = 0;
+ virtual_node->fm = NULL; /* This is a virtual data holder. */
+ virtual_node->version_prev = NULL;
+ virtual_node->version_next = NULL;
+ virtual_node->range_next = NULL;
/* Are there any data at all in the file yet? */
if (f->range_head) {
else {
virtual_node->data_offset = 0;
virtual_node->data_size = node->data_offset;
- virtual_node->range_prev = 0;
+ virtual_node->range_prev = NULL;
f->range_head = virtual_node;
}
return 0;
}
-
-/* Print the contents of a node. */
-void
-jffs_print_node(struct jffs_node *n)
-{
- D(printk("jffs_node: 0x%p\n", n));
- D(printk("{\n"));
- D(printk(" 0x%08x, /* version */\n", n->version));
- D(printk(" 0x%08x, /* data_offset */\n", n->data_offset));
- D(printk(" 0x%08x, /* data_size */\n", n->data_size));
- D(printk(" 0x%08x, /* removed_size */\n", n->removed_size));
- D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset));
- D(printk(" 0x%02x, /* name_size */\n", n->name_size));
- D(printk(" 0x%p, /* fm, fm->offset: %u */\n",
- n->fm, (n->fm ? n->fm->offset : 0)));
- D(printk(" 0x%p, /* version_prev */\n", n->version_prev));
- D(printk(" 0x%p, /* version_next */\n", n->version_next));
- D(printk(" 0x%p, /* range_prev */\n", n->range_prev));
- D(printk(" 0x%p, /* range_next */\n", n->range_next));
- D(printk("}\n"));
-}
-
-
-/* Print the contents of a raw inode. */
-void
-jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
-{
- D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
- D(printk("{\n"));
- D(printk(" 0x%08x, /* magic */\n", raw_inode->magic));
- D(printk(" 0x%08x, /* ino */\n", raw_inode->ino));
- D(printk(" 0x%08x, /* pino */\n", raw_inode->pino));
- D(printk(" 0x%08x, /* version */\n", raw_inode->version));
- D(printk(" 0x%08x, /* mode */\n", raw_inode->mode));
- D(printk(" 0x%04x, /* uid */\n", raw_inode->uid));
- D(printk(" 0x%04x, /* gid */\n", raw_inode->gid));
- D(printk(" 0x%08x, /* atime */\n", raw_inode->atime));
- D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime));
- D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime));
- D(printk(" 0x%08x, /* offset */\n", raw_inode->offset));
- D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize));
- D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize));
- D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize));
- D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink));
- D(printk(" 0x%02x, /* spare */\n",
- raw_inode->spare));
- D(printk(" %u, /* rename */\n",
- raw_inode->rename));
- D(printk(" %u, /* deleted */\n",
- raw_inode->deleted));
- D(printk(" 0x%02x, /* accurate */\n",
- raw_inode->accurate));
- D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum));
- D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum));
- D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum));
- D(printk("}\n"));
-}
-
-
/* Print the contents of a file. */
+#if 0
int
jffs_print_file(struct jffs_file *f)
{
D(printk("}\n"));
return 0;
}
-
+#endif /* 0 */
void
jffs_print_hash_table(struct jffs_control *c)
printk("JFFS: Dumping the file system's hash table...\n");
for (i = 0; i < c->hash_len; i++) {
- struct list_head *p;
- for (p = c->hash[i].next; p != &c->hash[i]; p = p->next) {
- struct jffs_file *f=list_entry(p,struct jffs_file,hash);
+ struct jffs_file *f;
+ list_for_each_entry(f, &c->hash[i], hash) {
printk("*** c->hash[%u]: \"%s\" "
"(ino: %u, pino: %u)\n",
i, (f->name ? f->name : ""),
/* Rewrite `size' bytes, and begin at `node'. */
-int
+static int
jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, __u32 size)
{
struct jffs_control *c = f->c;
process and is often called multiple times at each occasion of a
garbage collect. */
-int
+static int
jffs_garbage_collect_next(struct jffs_control *c)
{
struct jffs_fmcontrol *fmc = c->fmc;
} /* jffs_clear_end_of_node() */
/* Try to erase as much as possible of the dirt in the flash memory. */
-long
+static long
jffs_try_to_erase(struct jffs_control *c)
{
struct jffs_fmcontrol *fmc = c->fmc;
collection can be. */
-int
+static int
jffs_garbage_collect_now(struct jffs_control *c)
{
struct jffs_fmcontrol *fmc = c->fmc;
siginfo_t info;
unsigned long signr = 0;
+ if (try_to_freeze())
+ continue;
+
spin_lock_irq(¤t->sighand->siglock);
signr = dequeue_signal(current, ¤t->blocked, &info);
spin_unlock_irq(¤t->sighand->siglock);
D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): collecting.\n"));
D3(printk (KERN_NOTICE "g_c_thread(): down biglock\n"));
- down(&fmc->biglock);
+ mutex_lock(&fmc->biglock);
D1(printk("***jffs_garbage_collect_thread(): round #%u, "
"fmc->dirty_size = %u\n", i++, fmc->dirty_size));
gc_end:
D3(printk (KERN_NOTICE "g_c_thread(): up biglock\n"));
- up(&fmc->biglock);
+ mutex_unlock(&fmc->biglock);
} /* for (;;) */
} /* jffs_garbage_collect_thread() */