--- a/fs/yaffs2/yaffs_vfs_glue.c +++ b/fs/yaffs2/yaffs_vfs_glue.c @@ -393,6 +393,84 @@ static void yaffs_touch_super(yaffs_dev_ static int yaffs_vfs_setattr(struct inode *, struct iattr *); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + +#define yaffs_super_to_dev(sb) ((struct yaffs_dev_s *)sb->s_fs_info) + +static inline struct yaffs_LinuxContext * +yaffs_sb_to_ylc(struct super_block *sb) +{ + struct yaffs_dev_s *ydev; + struct yaffs_LinuxContext *ylc; + + ydev = yaffs_super_to_dev(sb); + ylc = yaffs_dev_to_lc(ydev); + return ylc; +} + +static inline struct super_block *yaffs_work_to_sb(struct work_struct *work) +{ + struct delayed_work *dwork; + struct yaffs_LinuxContext *ylc; + + dwork = container_of(work, struct delayed_work, work); + ylc = container_of(dwork, struct yaffs_LinuxContext, sb_sync_dwork); + return ylc->superBlock; +} + +static void yaffs_sb_sync_dwork_func(struct work_struct *work) +{ + struct super_block *sb = yaffs_work_to_sb(work); + + yaffs_write_super(sb); +} + +static void yaffs_init_sb_sync_dwork(struct yaffs_LinuxContext *ylc) +{ + INIT_DELAYED_WORK(&ylc->sb_sync_dwork, yaffs_sb_sync_dwork_func); +} + +static void yaffs_cancel_sb_sync_dwork(struct super_block *sb) +{ + struct yaffs_LinuxContext *ylc = yaffs_sb_to_ylc(sb); + + cancel_delayed_work_sync(&ylc->sb_sync_dwork); +} + +static inline bool yaffs_sb_is_dirty(struct super_block *sb) +{ + struct yaffs_LinuxContext *ylc = yaffs_sb_to_ylc(sb); + + return !!ylc->sb_dirty; +} + +static inline void yaffs_sb_set_dirty(struct super_block *sb, int dirty) +{ + struct yaffs_LinuxContext *ylc = yaffs_sb_to_ylc(sb); + + if (ylc->sb_dirty == dirty) + return; + + ylc->sb_dirty = dirty; + if (dirty) + queue_delayed_work(system_long_wq, &ylc->sb_sync_dwork, + msecs_to_jiffies(5000)); +} +#else +static inline bool yaffs_sb_is_dirty(struct super_block *sb) +{ + return !!sb->s_dirt; +} + +static inline void yaffs_sb_set_dirty(struct super_block *sb, int dirty) +{ + sb->s_dirt = dirty; +} + +static inline void yaffs_init_sb_sync_dwork(struct yaffs_LinuxContext *ylc) {} +static inline void yaffs_cancel_sb_sync_dwork(struct super_block *sb) {} +#endif /* >= 3.6.0 */ + static struct address_space_operations yaffs_file_address_operations = { .readpage = yaffs_readpage, .writepage = yaffs_writepage, @@ -553,7 +631,9 @@ static const struct super_operations yaf .clear_inode = yaffs_clear_inode, #endif .sync_fs = yaffs_sync_fs, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) .write_super = yaffs_write_super, +#endif }; @@ -2340,7 +2420,7 @@ static int yaffs_do_sync_fs(struct super T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND, (TSTR("yaffs_do_sync_fs: gc-urgency %d %s %s%s\n"), gc_urgent, - sb->s_dirt ? "dirty" : "clean", + yaffs_sb_is_dirty(sb) ? "dirty" : "clean", request_checkpoint ? "checkpoint requested" : "no checkpoint", oneshot_checkpoint ? " one-shot" : "" )); @@ -2349,9 +2429,9 @@ static int yaffs_do_sync_fs(struct super oneshot_checkpoint) && !dev->is_checkpointed; - if (sb->s_dirt || do_checkpoint) { + if (yaffs_sb_is_dirty(sb) || do_checkpoint) { yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint); - sb->s_dirt = 0; + yaffs_sb_set_dirty(sb, 0); if(oneshot_checkpoint) yaffs_auto_checkpoint &= ~4; } @@ -2627,6 +2707,8 @@ static void yaffs_put_super(struct super yaffs_flush_super(sb,1); + yaffs_cancel_sb_sync_dwork(sb); + if (yaffs_dev_to_lc(dev)->putSuperFunc) yaffs_dev_to_lc(dev)->putSuperFunc(sb); @@ -2665,7 +2747,7 @@ static void yaffs_touch_super(yaffs_dev_ T(YAFFS_TRACE_OS, (TSTR("yaffs_touch_super() sb = %p\n"), sb)); if (sb) - sb->s_dirt = 1; + yaffs_sb_set_dirty(sb, 1); } typedef struct { @@ -2991,6 +3073,8 @@ static struct super_block *yaffs_interna context->dev = dev; context->superBlock = sb; + yaffs_init_sb_sync_dwork(context); + dev->read_only = read_only; #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) @@ -3177,7 +3261,7 @@ static struct super_block *yaffs_interna return NULL; } sb->s_root = root; - sb->s_dirt = !dev->is_checkpointed; + yaffs_sb_set_dirty(sb, !dev->is_checkpointed); T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs_read_super: is_checkpointed %d\n"), dev->is_checkpointed)); --- a/fs/yaffs2/yaffs_linux.h +++ b/fs/yaffs2/yaffs_linux.h @@ -34,6 +34,11 @@ struct yaffs_LinuxContext { struct task_struct *readdirProcess; unsigned mount_id; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct delayed_work sb_sync_dwork; /* superblock write-out work */ + int sb_dirty; /* superblock is dirty */ +#endif }; #define yaffs_dev_to_lc(dev) ((struct yaffs_LinuxContext *)((dev)->os_context)) --- a/fs/yaffs2/yportenv.h +++ b/fs/yaffs2/yportenv.h @@ -49,6 +49,9 @@ #include #include #include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) +#include +#endif #define YCHAR char #define YUCHAR unsigned char