diff options
Diffstat (limited to 'fs/jffs2')
-rw-r--r-- | fs/jffs2/acl.c | 2 | ||||
-rw-r--r-- | fs/jffs2/background.c | 9 | ||||
-rw-r--r-- | fs/jffs2/file.c | 2 | ||||
-rw-r--r-- | fs/jffs2/fs.c | 2 | ||||
-rw-r--r-- | fs/jffs2/malloc.c | 18 | ||||
-rw-r--r-- | fs/jffs2/nodelist.h | 5 | ||||
-rw-r--r-- | fs/jffs2/readinode.c | 4 | ||||
-rw-r--r-- | fs/jffs2/scan.c | 3 | ||||
-rw-r--r-- | fs/jffs2/super.c | 2 | ||||
-rw-r--r-- | fs/jffs2/write.c | 15 |
10 files changed, 41 insertions, 21 deletions
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index a46101ee867a..65b3a1b5b88d 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -435,7 +435,7 @@ static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, struct posix_acl *acl; int rc; - if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) + if (!is_owner_or_cap(inode)) return -EPERM; if (value) { diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 0c82dfcfd246..504643f2e98b 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -81,9 +81,10 @@ static int jffs2_garbage_collect_thread(void *_c) set_user_nice(current, 10); + set_freezable(); for (;;) { allow_signal(SIGHUP); - + again: if (!jffs2_thread_should_wake(c)) { set_current_state (TASK_INTERRUPTIBLE); D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); @@ -94,9 +95,6 @@ static int jffs2_garbage_collect_thread(void *_c) schedule(); } - if (try_to_freeze()) - continue; - /* This thread is purely an optimisation. But if it runs when other things could be running, it actually makes things a lot worse. Use yield() and put it at the back of the runqueue @@ -111,6 +109,9 @@ static int jffs2_garbage_collect_thread(void *_c) siginfo_t info; unsigned long signr; + if (try_to_freeze()) + goto again; + signr = dequeue_signal_lock(current, ¤t->blocked, &info); switch(signr) { diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 99871279a1ed..c2530197be0c 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -47,7 +47,7 @@ const struct file_operations jffs2_file_operations = .ioctl = jffs2_ioctl, .mmap = generic_file_readonly_mmap, .fsync = jffs2_fsync, - .sendfile = generic_file_sendfile + .splice_read = generic_file_splice_read, }; /* jffs2_file_inode_operations */ diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 1d3b7a9fc828..8bc727b71696 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -627,7 +627,7 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, struct inode *inode = OFNI_EDONI_2SFFJ(f); struct page *pg; - pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, + pg = read_cache_page_async(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, (void *)jffs2_do_readpage_unlock, inode); if (IS_ERR(pg)) return (void *)pg; diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 35c1a5e30ba1..f9211252b5f1 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -33,56 +33,56 @@ int __init jffs2_create_slab_caches(void) { full_dnode_slab = kmem_cache_create("jffs2_full_dnode", sizeof(struct jffs2_full_dnode), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!full_dnode_slab) goto err; raw_dirent_slab = kmem_cache_create("jffs2_raw_dirent", sizeof(struct jffs2_raw_dirent), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!raw_dirent_slab) goto err; raw_inode_slab = kmem_cache_create("jffs2_raw_inode", sizeof(struct jffs2_raw_inode), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!raw_inode_slab) goto err; tmp_dnode_info_slab = kmem_cache_create("jffs2_tmp_dnode", sizeof(struct jffs2_tmp_dnode_info), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!tmp_dnode_info_slab) goto err; raw_node_ref_slab = kmem_cache_create("jffs2_refblock", sizeof(struct jffs2_raw_node_ref) * (REFS_PER_BLOCK + 1), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!raw_node_ref_slab) goto err; node_frag_slab = kmem_cache_create("jffs2_node_frag", sizeof(struct jffs2_node_frag), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!node_frag_slab) goto err; inode_cache_slab = kmem_cache_create("jffs2_inode_cache", sizeof(struct jffs2_inode_cache), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!inode_cache_slab) goto err; #ifdef CONFIG_JFFS2_FS_XATTR xattr_datum_cache = kmem_cache_create("jffs2_xattr_datum", sizeof(struct jffs2_xattr_datum), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!xattr_datum_cache) goto err; xattr_ref_cache = kmem_cache_create("jffs2_xattr_ref", sizeof(struct jffs2_xattr_ref), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!xattr_ref_cache) goto err; #endif diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 25126a062cae..bc5509fe577b 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -139,6 +139,11 @@ static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_nod #define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) #define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) +/* Dirent nodes should be REF_PRISTINE only if they are not a deletion + dirent. Deletion dirents should be REF_NORMAL so that GC gets to + throw them away when appropriate */ +#define dirent_node_state(rd) ( (je32_to_cpu((rd)->ino)?REF_PRISTINE:REF_NORMAL) ) + /* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get copied. If you need to do anything different to GC inode-less nodes, then diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 7b363786c2d2..b5baa356fed2 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -104,7 +104,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info 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); + ref_offset(ref), tn->data_crc, crc); return 1; } @@ -613,7 +613,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r jeb->unchecked_size -= len; c->used_size += len; c->unchecked_size -= len; - ref->flash_offset = ref_offset(ref) | REF_PRISTINE; + ref->flash_offset = ref_offset(ref) | dirent_node_state(rd); spin_unlock(&c->erase_completion_lock); } diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 2a1c976c7924..6c75cd433342 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -1049,7 +1049,8 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo return -ENOMEM; } - fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic); + fd->raw = jffs2_link_node_ref(c, jeb, ofs | dirent_node_state(rd), + PAD(je32_to_cpu(rd->totlen)), ic); fd->next = NULL; fd->version = je32_to_cpu(rd->version); diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index e220d3bd610d..be2b70c2ec16 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -192,7 +192,7 @@ static int __init init_jffs2_fs(void) sizeof(struct jffs2_inode_info), 0, (SLAB_RECLAIM_ACCOUNT| SLAB_MEM_SPREAD), - jffs2_i_init_once, NULL); + jffs2_i_init_once); if (!jffs2_inode_cachep) { printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n"); return -ENOMEM; diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 1b68a521acfc..664c164aa67c 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -173,6 +173,12 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 flash_ofs |= REF_NORMAL; } fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache); + if (IS_ERR(fn->raw)) { + void *hold_err = fn->raw; + /* Release the full_dnode which is now useless, and return */ + jffs2_free_full_dnode(fn); + return ERR_PTR(PTR_ERR(hold_err)); + } fn->ofs = je32_to_cpu(ri->offset); fn->size = je32_to_cpu(ri->dsize); fn->frags = 0; @@ -290,7 +296,14 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff return ERR_PTR(ret?ret:-EIO); } /* Mark the space used */ - fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache); + fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | dirent_node_state(rd), + PAD(sizeof(*rd)+namelen), f->inocache); + if (IS_ERR(fd->raw)) { + void *hold_err = fd->raw; + /* Release the full_dirent which is now useless, and return */ + jffs2_free_full_dirent(fd); + return ERR_PTR(PTR_ERR(hold_err)); + } if (retried) { jffs2_dbg_acct_sanity_check(c,NULL); |