summaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-3.7/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/patches-3.7/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch')
-rw-r--r--target/linux/generic/patches-3.7/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch180
1 files changed, 180 insertions, 0 deletions
diff --git a/target/linux/generic/patches-3.7/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch b/target/linux/generic/patches-3.7/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch
new file mode 100644
index 000000000..579932c69
--- /dev/null
+++ b/target/linux/generic/patches-3.7/513-yaffs-3.6-use-delayed-work-instead-of-write_super.patch
@@ -0,0 +1,180 @@
+--- a/fs/yaffs2/yaffs_vfs_glue.c
++++ b/fs/yaffs2/yaffs_vfs_glue.c
+@@ -394,6 +394,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,
+@@ -527,7 +605,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
+ };
+
+
+@@ -2314,7 +2394,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" : "" ));
+
+@@ -2323,9 +2403,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;
+ }
+@@ -2601,6 +2681,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);
+
+@@ -2639,7 +2721,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 {
+@@ -2965,6 +3047,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))
+@@ -3151,7 +3235,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 <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/xattr.h>
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
++#include <linux/workqueue.h>
++#endif
+
+ #define YCHAR char
+ #define YUCHAR unsigned char