181 lines
4.9 KiB
Diff
181 lines
4.9 KiB
Diff
--- 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 <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
|