mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 23:00:21 +00:00
jffs2: get rid of jffs2_sync_super
Currently JFFS2 file-system maps the VFS "superblock" abstraction to the write-buffer. Namely, it uses VFS services to synchronize the write-buffer periodically. The whole "superblock write-out" VFS infrastructure is served by the 'sync_supers()' kernel thread, which wakes up every 5 (by default) seconds and writes out all dirty superblock using the '->write_super()' call-back. But the problem with this thread is that it wastes power by waking up the system every 5 seconds no matter what. So we want to kill it completely and thus, we need to make file-systems to stop using the '->write_super' VFS service, and then remove it together with the kernel thread. This patch switches the JFFS2 write-buffer management from '->write_super()'/'->s_dirt' to a delayed work. Instead of setting the 's_dirt' flag we just schedule a delayed work for synchronizing the write-buffer. Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
e832579fd1
commit
208b14e507
@ -133,6 +133,10 @@ struct jffs2_sb_info {
|
|||||||
struct jffs2_inodirty *wbuf_inodes;
|
struct jffs2_inodirty *wbuf_inodes;
|
||||||
struct rw_semaphore wbuf_sem; /* Protects the write buffer */
|
struct rw_semaphore wbuf_sem; /* Protects the write buffer */
|
||||||
|
|
||||||
|
struct delayed_work wbuf_dwork; /* write-buffer write-out work */
|
||||||
|
int wbuf_queued; /* non-zero delayed work is queued */
|
||||||
|
spinlock_t wbuf_dwork_lock; /* protects wbuf_dwork and and wbuf_queued */
|
||||||
|
|
||||||
unsigned char *oobbuf;
|
unsigned char *oobbuf;
|
||||||
int oobavail; /* How many bytes are available for JFFS2 in OOB */
|
int oobavail; /* How many bytes are available for JFFS2 in OOB */
|
||||||
#endif
|
#endif
|
||||||
|
@ -95,6 +95,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
|
|||||||
#define jffs2_ubivol(c) (0)
|
#define jffs2_ubivol(c) (0)
|
||||||
#define jffs2_ubivol_setup(c) (0)
|
#define jffs2_ubivol_setup(c) (0)
|
||||||
#define jffs2_ubivol_cleanup(c) do {} while (0)
|
#define jffs2_ubivol_cleanup(c) do {} while (0)
|
||||||
|
#define jffs2_dirty_trigger(c) do {} while (0)
|
||||||
|
|
||||||
#else /* NAND and/or ECC'd NOR support present */
|
#else /* NAND and/or ECC'd NOR support present */
|
||||||
|
|
||||||
@ -135,14 +136,10 @@ 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))
|
#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);
|
int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c);
|
||||||
void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c);
|
void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c);
|
||||||
|
void jffs2_dirty_trigger(struct jffs2_sb_info *c);
|
||||||
|
|
||||||
#endif /* WRITEBUFFER */
|
#endif /* WRITEBUFFER */
|
||||||
|
|
||||||
static inline void jffs2_dirty_trigger(struct jffs2_sb_info *c)
|
|
||||||
{
|
|
||||||
OFNI_BS_2SFFJ(c)->s_dirt = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* background.c */
|
/* background.c */
|
||||||
int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
|
int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
|
||||||
void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);
|
void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);
|
||||||
|
@ -63,18 +63,6 @@ static void jffs2_i_init_once(void *foo)
|
|||||||
inode_init_once(&f->vfs_inode);
|
inode_init_once(&f->vfs_inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jffs2_write_super(struct super_block *sb)
|
|
||||||
{
|
|
||||||
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
|
|
||||||
|
|
||||||
sb->s_dirt = 0;
|
|
||||||
|
|
||||||
if (!(sb->s_flags & MS_RDONLY)) {
|
|
||||||
jffs2_dbg(1, "%s()\n", __func__);
|
|
||||||
jffs2_flush_wbuf_gc(c, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *jffs2_compr_name(unsigned int compr)
|
static const char *jffs2_compr_name(unsigned int compr)
|
||||||
{
|
{
|
||||||
switch (compr) {
|
switch (compr) {
|
||||||
@ -263,7 +251,6 @@ static const struct super_operations jffs2_super_operations =
|
|||||||
.alloc_inode = jffs2_alloc_inode,
|
.alloc_inode = jffs2_alloc_inode,
|
||||||
.destroy_inode =jffs2_destroy_inode,
|
.destroy_inode =jffs2_destroy_inode,
|
||||||
.put_super = jffs2_put_super,
|
.put_super = jffs2_put_super,
|
||||||
.write_super = jffs2_write_super,
|
|
||||||
.statfs = jffs2_statfs,
|
.statfs = jffs2_statfs,
|
||||||
.remount_fs = jffs2_remount_fs,
|
.remount_fs = jffs2_remount_fs,
|
||||||
.evict_inode = jffs2_evict_inode,
|
.evict_inode = jffs2_evict_inode,
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <linux/mtd/nand.h>
|
#include <linux/mtd/nand.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/writeback.h>
|
||||||
|
|
||||||
#include "nodelist.h"
|
#include "nodelist.h"
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ static void jffs2_wbuf_dirties_inode(struct jffs2_sb_info *c, uint32_t ino)
|
|||||||
{
|
{
|
||||||
struct jffs2_inodirty *new;
|
struct jffs2_inodirty *new;
|
||||||
|
|
||||||
/* Mark the superblock dirty so that kupdated will flush... */
|
/* Schedule delayed write-buffer write-out */
|
||||||
jffs2_dirty_trigger(c);
|
jffs2_dirty_trigger(c);
|
||||||
|
|
||||||
if (jffs2_wbuf_pending_for_ino(c, ino))
|
if (jffs2_wbuf_pending_for_ino(c, ino))
|
||||||
@ -1148,6 +1149,47 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct jffs2_sb_info *work_to_sb(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct delayed_work *dwork;
|
||||||
|
|
||||||
|
dwork = container_of(work, struct delayed_work, work);
|
||||||
|
return container_of(dwork, struct jffs2_sb_info, wbuf_dwork);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void delayed_wbuf_sync(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct jffs2_sb_info *c = work_to_sb(work);
|
||||||
|
struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||||
|
|
||||||
|
spin_lock(&c->wbuf_dwork_lock);
|
||||||
|
c->wbuf_queued = 0;
|
||||||
|
spin_unlock(&c->wbuf_dwork_lock);
|
||||||
|
|
||||||
|
if (!(sb->s_flags & MS_RDONLY)) {
|
||||||
|
jffs2_dbg(1, "%s()\n", __func__);
|
||||||
|
jffs2_flush_wbuf_gc(c, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jffs2_dirty_trigger(struct jffs2_sb_info *c)
|
||||||
|
{
|
||||||
|
struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||||
|
unsigned long delay;
|
||||||
|
|
||||||
|
if (sb->s_flags & MS_RDONLY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
spin_lock(&c->wbuf_dwork_lock);
|
||||||
|
if (!c->wbuf_queued) {
|
||||||
|
jffs2_dbg(1, "%s()\n", __func__);
|
||||||
|
delay = msecs_to_jiffies(dirty_writeback_interval * 10);
|
||||||
|
queue_delayed_work(system_long_wq, &c->wbuf_dwork, delay);
|
||||||
|
c->wbuf_queued = 1;
|
||||||
|
}
|
||||||
|
spin_unlock(&c->wbuf_dwork_lock);
|
||||||
|
}
|
||||||
|
|
||||||
int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
|
int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
|
||||||
{
|
{
|
||||||
struct nand_ecclayout *oinfo = c->mtd->ecclayout;
|
struct nand_ecclayout *oinfo = c->mtd->ecclayout;
|
||||||
@ -1169,6 +1211,8 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
|
|||||||
|
|
||||||
/* Initialise write buffer */
|
/* Initialise write buffer */
|
||||||
init_rwsem(&c->wbuf_sem);
|
init_rwsem(&c->wbuf_sem);
|
||||||
|
spin_lock_init(&c->wbuf_dwork_lock);
|
||||||
|
INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync);
|
||||||
c->wbuf_pagesize = c->mtd->writesize;
|
c->wbuf_pagesize = c->mtd->writesize;
|
||||||
c->wbuf_ofs = 0xFFFFFFFF;
|
c->wbuf_ofs = 0xFFFFFFFF;
|
||||||
|
|
||||||
@ -1207,8 +1251,8 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
|
|||||||
|
|
||||||
/* Initialize write buffer */
|
/* Initialize write buffer */
|
||||||
init_rwsem(&c->wbuf_sem);
|
init_rwsem(&c->wbuf_sem);
|
||||||
|
spin_lock_init(&c->wbuf_dwork_lock);
|
||||||
|
INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync);
|
||||||
c->wbuf_pagesize = c->mtd->erasesize;
|
c->wbuf_pagesize = c->mtd->erasesize;
|
||||||
|
|
||||||
/* Find a suitable c->sector_size
|
/* Find a suitable c->sector_size
|
||||||
@ -1267,6 +1311,9 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
|
|||||||
|
|
||||||
/* Initialize write buffer */
|
/* Initialize write buffer */
|
||||||
init_rwsem(&c->wbuf_sem);
|
init_rwsem(&c->wbuf_sem);
|
||||||
|
spin_lock_init(&c->wbuf_dwork_lock);
|
||||||
|
INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync);
|
||||||
|
|
||||||
c->wbuf_pagesize = c->mtd->writesize;
|
c->wbuf_pagesize = c->mtd->writesize;
|
||||||
c->wbuf_ofs = 0xFFFFFFFF;
|
c->wbuf_ofs = 0xFFFFFFFF;
|
||||||
|
|
||||||
@ -1299,6 +1346,8 @@ int jffs2_ubivol_setup(struct jffs2_sb_info *c) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
init_rwsem(&c->wbuf_sem);
|
init_rwsem(&c->wbuf_sem);
|
||||||
|
spin_lock_init(&c->wbuf_dwork_lock);
|
||||||
|
INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync);
|
||||||
|
|
||||||
c->wbuf_pagesize = c->mtd->writesize;
|
c->wbuf_pagesize = c->mtd->writesize;
|
||||||
c->wbuf_ofs = 0xFFFFFFFF;
|
c->wbuf_ofs = 0xFFFFFFFF;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user