c6ecddf0b2d91f3f029d926b50314265b4426f87
[openwrt.git] / target / linux / generic / patches-3.9 / 514-yaffs-3.6-use-delayed-work-instead-of-write_super.patch
1 --- a/fs/yaffs2/yaffs_vfs_glue.c
2 +++ b/fs/yaffs2/yaffs_vfs_glue.c
3 @@ -393,6 +393,84 @@ static void yaffs_touch_super(yaffs_dev_
4  static int yaffs_vfs_setattr(struct inode *, struct iattr *);
5  
6  
7 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8 +
9 +#define yaffs_super_to_dev(sb)    ((struct yaffs_dev_s *)sb->s_fs_info)
10 +
11 +static inline struct yaffs_LinuxContext *
12 +yaffs_sb_to_ylc(struct super_block *sb)
13 +{
14 +       struct yaffs_dev_s *ydev;
15 +       struct yaffs_LinuxContext *ylc;
16 +
17 +       ydev = yaffs_super_to_dev(sb);
18 +       ylc = yaffs_dev_to_lc(ydev);
19 +       return ylc;
20 +}
21 +
22 +static inline struct super_block *yaffs_work_to_sb(struct work_struct *work)
23 +{
24 +       struct delayed_work *dwork;
25 +       struct yaffs_LinuxContext *ylc;
26 +
27 +       dwork = container_of(work, struct delayed_work, work);
28 +       ylc = container_of(dwork, struct yaffs_LinuxContext, sb_sync_dwork);
29 +       return ylc->superBlock;
30 +}
31 +
32 +static void yaffs_sb_sync_dwork_func(struct work_struct *work)
33 +{
34 +       struct super_block *sb = yaffs_work_to_sb(work);
35 +
36 +       yaffs_write_super(sb);
37 +}
38 +
39 +static void yaffs_init_sb_sync_dwork(struct yaffs_LinuxContext *ylc)
40 +{
41 +       INIT_DELAYED_WORK(&ylc->sb_sync_dwork, yaffs_sb_sync_dwork_func);
42 +}
43 +
44 +static void yaffs_cancel_sb_sync_dwork(struct super_block *sb)
45 +{
46 +       struct yaffs_LinuxContext *ylc = yaffs_sb_to_ylc(sb);
47 +
48 +       cancel_delayed_work_sync(&ylc->sb_sync_dwork);
49 +}
50 +
51 +static inline bool yaffs_sb_is_dirty(struct super_block *sb)
52 +{
53 +       struct yaffs_LinuxContext *ylc = yaffs_sb_to_ylc(sb);
54 +
55 +       return !!ylc->sb_dirty;
56 +}
57 +
58 +static inline void yaffs_sb_set_dirty(struct super_block *sb, int dirty)
59 +{
60 +       struct yaffs_LinuxContext *ylc = yaffs_sb_to_ylc(sb);
61 +
62 +       if (ylc->sb_dirty == dirty)
63 +               return;
64 +
65 +       ylc->sb_dirty = dirty;
66 +       if (dirty)
67 +               queue_delayed_work(system_long_wq, &ylc->sb_sync_dwork,
68 +                                  msecs_to_jiffies(5000));
69 +}
70 +#else
71 +static inline bool yaffs_sb_is_dirty(struct super_block *sb)
72 +{
73 +       return !!sb->s_dirt;
74 +}
75 +
76 +static inline void yaffs_sb_set_dirty(struct super_block *sb, int dirty)
77 +{
78 +       sb->s_dirt = dirty;
79 +}
80 +
81 +static inline void yaffs_init_sb_sync_dwork(struct yaffs_LinuxContext *ylc) {}
82 +static inline void yaffs_cancel_sb_sync_dwork(struct super_block *sb) {}
83 +#endif /* >= 3.6.0 */
84 +
85  static struct address_space_operations yaffs_file_address_operations = {
86         .readpage = yaffs_readpage,
87         .writepage = yaffs_writepage,
88 @@ -553,7 +631,9 @@ static const struct super_operations yaf
89         .clear_inode = yaffs_clear_inode,
90  #endif
91         .sync_fs = yaffs_sync_fs,
92 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
93         .write_super = yaffs_write_super,
94 +#endif
95  };
96  
97  
98 @@ -2340,7 +2420,7 @@ static int yaffs_do_sync_fs(struct super
99         T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
100                 (TSTR("yaffs_do_sync_fs: gc-urgency %d %s %s%s\n"),
101                 gc_urgent,
102 -               sb->s_dirt ? "dirty" : "clean",
103 +               yaffs_sb_is_dirty(sb) ? "dirty" : "clean",
104                 request_checkpoint ? "checkpoint requested" : "no checkpoint",
105                 oneshot_checkpoint ? " one-shot" : "" ));
106  
107 @@ -2349,9 +2429,9 @@ static int yaffs_do_sync_fs(struct super
108                         oneshot_checkpoint) &&
109                         !dev->is_checkpointed;
110  
111 -       if (sb->s_dirt || do_checkpoint) {
112 +       if (yaffs_sb_is_dirty(sb) || do_checkpoint) {
113                 yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint);
114 -               sb->s_dirt = 0;
115 +               yaffs_sb_set_dirty(sb, 0);
116                 if(oneshot_checkpoint)
117                         yaffs_auto_checkpoint &= ~4;
118         }
119 @@ -2627,6 +2707,8 @@ static void yaffs_put_super(struct super
120  
121         yaffs_flush_super(sb,1);
122  
123 +       yaffs_cancel_sb_sync_dwork(sb);
124 +
125         if (yaffs_dev_to_lc(dev)->putSuperFunc)
126                 yaffs_dev_to_lc(dev)->putSuperFunc(sb);
127  
128 @@ -2665,7 +2747,7 @@ static void yaffs_touch_super(yaffs_dev_
129  
130         T(YAFFS_TRACE_OS, (TSTR("yaffs_touch_super() sb = %p\n"), sb));
131         if (sb)
132 -               sb->s_dirt = 1;
133 +               yaffs_sb_set_dirty(sb, 1);
134  }
135  
136  typedef struct {
137 @@ -2991,6 +3073,8 @@ static struct super_block *yaffs_interna
138         context->dev = dev;
139         context->superBlock = sb;
140  
141 +       yaffs_init_sb_sync_dwork(context);
142 +
143         dev->read_only = read_only;
144  
145  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
146 @@ -3177,7 +3261,7 @@ static struct super_block *yaffs_interna
147                 return NULL;
148         }
149         sb->s_root = root;
150 -       sb->s_dirt = !dev->is_checkpointed;
151 +       yaffs_sb_set_dirty(sb, !dev->is_checkpointed);
152         T(YAFFS_TRACE_ALWAYS,
153                 (TSTR("yaffs_read_super: is_checkpointed %d\n"),
154                 dev->is_checkpointed));
155 --- a/fs/yaffs2/yaffs_linux.h
156 +++ b/fs/yaffs2/yaffs_linux.h
157 @@ -34,6 +34,11 @@ struct yaffs_LinuxContext {
158  
159         struct task_struct *readdirProcess;
160         unsigned mount_id;
161 +
162 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
163 +       struct delayed_work sb_sync_dwork;      /* superblock write-out work */
164 +       int sb_dirty;                           /* superblock is dirty */
165 +#endif
166  };
167  
168  #define yaffs_dev_to_lc(dev) ((struct yaffs_LinuxContext *)((dev)->os_context))
169 --- a/fs/yaffs2/yportenv.h
170 +++ b/fs/yaffs2/yportenv.h
171 @@ -49,6 +49,9 @@
172  #include <linux/slab.h>
173  #include <linux/vmalloc.h>
174  #include <linux/xattr.h>
175 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
176 +#include <linux/workqueue.h>
177 +#endif
178  
179  #define YCHAR char
180  #define YUCHAR unsigned char