xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/jffs2/src/gcthread.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * JFFS2 -- Journalling Flash File System, Version 2.
3*10465441SEvalZero  *
4*10465441SEvalZero  * Copyright (C) 2001-2003 Red Hat, Inc.
5*10465441SEvalZero  *
6*10465441SEvalZero  * Created by David Woodhouse <[email protected]>
7*10465441SEvalZero  *
8*10465441SEvalZero  * For licensing information, see the file 'LICENCE' in this directory.
9*10465441SEvalZero  *
10*10465441SEvalZero  * $Id: gcthread.c,v 1.3 2005/01/22 16:01:12 lunn Exp $
11*10465441SEvalZero  *
12*10465441SEvalZero  */
13*10465441SEvalZero #include <linux/kernel.h>
14*10465441SEvalZero #include "nodelist.h"
15*10465441SEvalZero //#include <cyg/kernel/kapi.h> prife
16*10465441SEvalZero 
17*10465441SEvalZero #if defined(CYGOPT_FS_JFFS2_GCTHREAD)
18*10465441SEvalZero 
19*10465441SEvalZero #define GC_THREAD_FLAG_TRIG 1
20*10465441SEvalZero #define GC_THREAD_FLAG_STOP 2
21*10465441SEvalZero #define GC_THREAD_FLAG_HAS_EXIT 4
22*10465441SEvalZero 
23*10465441SEvalZero #if 0
24*10465441SEvalZero static cyg_thread_entry_t jffs2_garbage_collect_thread;
25*10465441SEvalZero 
26*10465441SEvalZero void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
27*10465441SEvalZero {
28*10465441SEvalZero      struct super_block *sb=OFNI_BS_2SFFJ(c);
29*10465441SEvalZero 
30*10465441SEvalZero      /* Wake up the thread */
31*10465441SEvalZero      D1(printk("jffs2_garbage_collect_trigger\n"));
32*10465441SEvalZero 
33*10465441SEvalZero      cyg_flag_setbits(&sb->s_gc_thread_flags,GC_THREAD_FLAG_TRIG);
34*10465441SEvalZero }
35*10465441SEvalZero 
36*10465441SEvalZero 
37*10465441SEvalZero void
38*10465441SEvalZero jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
39*10465441SEvalZero {
40*10465441SEvalZero      struct super_block *sb=OFNI_BS_2SFFJ(c);
41*10465441SEvalZero 
42*10465441SEvalZero      RT_ASSERT(c);
43*10465441SEvalZero      RT_ASSERT(!sb->s_gc_thread_handle);
44*10465441SEvalZero 
45*10465441SEvalZero      cyg_flag_init(&sb->s_gc_thread_flags);
46*10465441SEvalZero      cyg_mutex_init(&sb->s_lock);
47*10465441SEvalZero 
48*10465441SEvalZero      D1(printk("jffs2_start_garbage_collect_thread\n"));
49*10465441SEvalZero      /* Start the thread. Doesn't matter if it fails -- it's only an
50*10465441SEvalZero       * optimisation anyway */
51*10465441SEvalZero      cyg_thread_create(CYGNUM_JFFS2_GC_THREAD_PRIORITY,
52*10465441SEvalZero                        jffs2_garbage_collect_thread,
53*10465441SEvalZero                        (unsigned long)c,"jffs2 gc thread",
54*10465441SEvalZero                        (void*)sb->s_gc_thread_stack,
55*10465441SEvalZero                        sizeof(sb->s_gc_thread_stack),
56*10465441SEvalZero                        &sb->s_gc_thread_handle,
57*10465441SEvalZero                        &sb->s_gc_thread);
58*10465441SEvalZero 
59*10465441SEvalZero      cyg_thread_resume(sb->s_gc_thread_handle);
60*10465441SEvalZero }
61*10465441SEvalZero 
62*10465441SEvalZero void
63*10465441SEvalZero jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
64*10465441SEvalZero {
65*10465441SEvalZero      struct super_block *sb=OFNI_BS_2SFFJ(c);
66*10465441SEvalZero 
67*10465441SEvalZero      RT_ASSERT(sb->s_gc_thread_handle);
68*10465441SEvalZero 
69*10465441SEvalZero      D1(printk("jffs2_stop_garbage_collect_thread\n"));
70*10465441SEvalZero      /* Stop the thread and wait for it if necessary */
71*10465441SEvalZero 
72*10465441SEvalZero      cyg_flag_setbits(&sb->s_gc_thread_flags,GC_THREAD_FLAG_STOP);
73*10465441SEvalZero 
74*10465441SEvalZero      D1(printk("jffs2_stop_garbage_collect_thread wait\n"));
75*10465441SEvalZero 
76*10465441SEvalZero      cyg_flag_wait(&sb->s_gc_thread_flags,
77*10465441SEvalZero                    GC_THREAD_FLAG_HAS_EXIT,
78*10465441SEvalZero                    CYG_FLAG_WAITMODE_OR| CYG_FLAG_WAITMODE_CLR);
79*10465441SEvalZero 
80*10465441SEvalZero      // Kill and free the resources ...  this is safe due to the flag
81*10465441SEvalZero      // from the thread.
82*10465441SEvalZero      cyg_thread_kill(sb->s_gc_thread_handle);
83*10465441SEvalZero      cyg_thread_delete(sb->s_gc_thread_handle);
84*10465441SEvalZero 
85*10465441SEvalZero      cyg_mutex_destroy(&sb->s_lock);
86*10465441SEvalZero      cyg_flag_destroy(&sb->s_gc_thread_flags);
87*10465441SEvalZero }
88*10465441SEvalZero 
89*10465441SEvalZero 
90*10465441SEvalZero static void
91*10465441SEvalZero jffs2_garbage_collect_thread(unsigned long data)
92*10465441SEvalZero {
93*10465441SEvalZero      struct jffs2_sb_info *c=(struct jffs2_sb_info *)data;
94*10465441SEvalZero      struct super_block *sb=OFNI_BS_2SFFJ(c);
95*10465441SEvalZero      cyg_flag_value_t flag;
96*10465441SEvalZero      cyg_mtab_entry *mte;
97*10465441SEvalZero 
98*10465441SEvalZero      D1(printk("jffs2_garbage_collect_thread START\n"));
99*10465441SEvalZero 
100*10465441SEvalZero      while(1) {
101*10465441SEvalZero           flag=cyg_flag_timed_wait(&sb->s_gc_thread_flags,
102*10465441SEvalZero                                    GC_THREAD_FLAG_TRIG|GC_THREAD_FLAG_STOP,
103*10465441SEvalZero                                    CYG_FLAG_WAITMODE_OR| CYG_FLAG_WAITMODE_CLR,
104*10465441SEvalZero                                    cyg_current_time()+
105*10465441SEvalZero                                    CYGNUM_JFFS2_GS_THREAD_TICKS);
106*10465441SEvalZero 
107*10465441SEvalZero           if (flag & GC_THREAD_FLAG_STOP)
108*10465441SEvalZero                break;
109*10465441SEvalZero 
110*10465441SEvalZero           D1(printk("jffs2: GC THREAD GC BEGIN\n"));
111*10465441SEvalZero 
112*10465441SEvalZero           mte=cyg_fs_root_lookup((cyg_dir *) sb->s_root);
113*10465441SEvalZero           CYG_ASSERT(mte, "Bad mount point");
114*10465441SEvalZero           cyg_fs_lock(mte, mte->fs->syncmode);
115*10465441SEvalZero 
116*10465441SEvalZero           if (jffs2_garbage_collect_pass(c) == -ENOSPC) {
117*10465441SEvalZero                printf("No space for garbage collection. "
118*10465441SEvalZero                       "Aborting JFFS2 GC thread\n");
119*10465441SEvalZero                break;
120*10465441SEvalZero           }
121*10465441SEvalZero           cyg_fs_unlock(mte, mte->fs->syncmode);
122*10465441SEvalZero           D1(printk("jffs2: GC THREAD GC END\n"));
123*10465441SEvalZero      }
124*10465441SEvalZero 
125*10465441SEvalZero      D1(printk("jffs2_garbage_collect_thread EXIT\n"));
126*10465441SEvalZero      cyg_flag_setbits(&sb->s_gc_thread_flags,GC_THREAD_FLAG_HAS_EXIT);
127*10465441SEvalZero }
128*10465441SEvalZero #endif
129*10465441SEvalZero 
cyg_current_time(void)130*10465441SEvalZero rt_uint32_t cyg_current_time(void)
131*10465441SEvalZero {
132*10465441SEvalZero 	return 0;
133*10465441SEvalZero }
134*10465441SEvalZero 
135*10465441SEvalZero static void
136*10465441SEvalZero jffs2_garbage_collect_thread(unsigned long data);
137*10465441SEvalZero 
jffs2_garbage_collect_trigger(struct jffs2_sb_info * c)138*10465441SEvalZero void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
139*10465441SEvalZero {
140*10465441SEvalZero      struct super_block *sb=OFNI_BS_2SFFJ(c);
141*10465441SEvalZero 
142*10465441SEvalZero      /* Wake up the thread */
143*10465441SEvalZero      D1(printk("jffs2_garbage_collect_trigger\n"));
144*10465441SEvalZero 
145*10465441SEvalZero      rt_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_TRIG);
146*10465441SEvalZero }
147*10465441SEvalZero 
148*10465441SEvalZero static struct rt_thread gc_thread;
149*10465441SEvalZero void
jffs2_start_garbage_collect_thread(struct jffs2_sb_info * c)150*10465441SEvalZero jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
151*10465441SEvalZero {
152*10465441SEvalZero      struct super_block *sb=OFNI_BS_2SFFJ(c);
153*10465441SEvalZero      cyg_mtab_entry *mte;
154*10465441SEvalZero      int result;
155*10465441SEvalZero 
156*10465441SEvalZero      RT_ASSERT(c);
157*10465441SEvalZero      //RT_ASSERT(!sb->s_gc_thread_handle);
158*10465441SEvalZero 
159*10465441SEvalZero      mte=(cyg_dir *) sb->s_root;
160*10465441SEvalZero      RT_ASSERT(mte);
161*10465441SEvalZero 
162*10465441SEvalZero      rt_event_init(&sb->s_gc_thread_flags, "gc_event", RT_IPC_FLAG_FIFO);
163*10465441SEvalZero      rt_mutex_init(&sb->s_lock, "gc_mutex", RT_IPC_FLAG_FIFO);
164*10465441SEvalZero //     rt_mutex_init(&mte->fs->syncmode, "fs_lock", RT_IPC_FLAG_FIFO);
165*10465441SEvalZero 
166*10465441SEvalZero      D1(printk("jffs2_start_garbage_collect_thread\n"));
167*10465441SEvalZero      /* Start the thread. Doesn't matter if it fails -- it's only an
168*10465441SEvalZero       * optimisation anyway */
169*10465441SEvalZero      result =  rt_thread_init(&sb->s_gc_thread,
170*10465441SEvalZero 	                   "jffs2_gc_thread",
171*10465441SEvalZero                        jffs2_garbage_collect_thread,
172*10465441SEvalZero                        (void *)c,
173*10465441SEvalZero                        (void*)sb->s_gc_thread_stack,
174*10465441SEvalZero                        sizeof(sb->s_gc_thread_stack),
175*10465441SEvalZero 					   CYGNUM_JFFS2_GC_THREAD_PRIORITY,
176*10465441SEvalZero 					   CYGNUM_JFFS2_GC_THREAD_TICKS
177*10465441SEvalZero 					   );
178*10465441SEvalZero 	 if (result != RT_EOK) {
179*10465441SEvalZero 		 rt_thread_startup(&sb->s_gc_thread);
180*10465441SEvalZero 		 /* how to deal with the following filed? */
181*10465441SEvalZero 		 /* sb->s_gc_thread_handle; */
182*10465441SEvalZero 	 }
183*10465441SEvalZero }
184*10465441SEvalZero 
185*10465441SEvalZero void
jffs2_stop_garbage_collect_thread(struct jffs2_sb_info * c)186*10465441SEvalZero jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
187*10465441SEvalZero {
188*10465441SEvalZero      struct super_block *sb=OFNI_BS_2SFFJ(c);
189*10465441SEvalZero      cyg_mtab_entry *mte;
190*10465441SEvalZero 	 rt_uint32_t  e;
191*10465441SEvalZero 
192*10465441SEvalZero      //RT_ASSERT(sb->s_gc_thread_handle);
193*10465441SEvalZero 
194*10465441SEvalZero      D1(printk("jffs2_stop_garbage_collect_thread\n"));
195*10465441SEvalZero      /* Stop the thread and wait for it if necessary */
196*10465441SEvalZero 
197*10465441SEvalZero      rt_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_STOP);
198*10465441SEvalZero 
199*10465441SEvalZero      D1(printk("jffs2_stop_garbage_collect_thread wait\n"));
200*10465441SEvalZero 
201*10465441SEvalZero      rt_event_recv(&sb->s_gc_thread_flags,
202*10465441SEvalZero                    GC_THREAD_FLAG_HAS_EXIT,
203*10465441SEvalZero                    RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
204*10465441SEvalZero 				   RT_WAITING_FOREVER,  &e);
205*10465441SEvalZero 
206*10465441SEvalZero      // Kill and free the resources ...  this is safe due to the flag
207*10465441SEvalZero      // from the thread.
208*10465441SEvalZero      rt_thread_detach(&sb->s_gc_thread);
209*10465441SEvalZero      rt_sem_detach(&sb->s_lock);
210*10465441SEvalZero      rt_event_detach(&sb->s_gc_thread_flags);
211*10465441SEvalZero }
212*10465441SEvalZero 
213*10465441SEvalZero 
214*10465441SEvalZero static void
jffs2_garbage_collect_thread(unsigned long data)215*10465441SEvalZero jffs2_garbage_collect_thread(unsigned long data)
216*10465441SEvalZero {
217*10465441SEvalZero      struct jffs2_sb_info *c=(struct jffs2_sb_info *)data;
218*10465441SEvalZero      struct super_block *sb=OFNI_BS_2SFFJ(c);
219*10465441SEvalZero      cyg_mtab_entry *mte;
220*10465441SEvalZero      rt_uint32_t flag = 0;
221*10465441SEvalZero 
222*10465441SEvalZero      D1(printk("jffs2_garbage_collect_thread START\n"));
223*10465441SEvalZero 
224*10465441SEvalZero      while(1) {
225*10465441SEvalZero           rt_event_recv(&sb->s_gc_thread_flags,
226*10465441SEvalZero                         GC_THREAD_FLAG_TRIG | GC_THREAD_FLAG_STOP,
227*10465441SEvalZero                         RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
228*10465441SEvalZero 				        cyg_current_time() + CYGNUM_JFFS2_GS_THREAD_TICKS,
229*10465441SEvalZero 						&flag);
230*10465441SEvalZero 
231*10465441SEvalZero           if (flag & GC_THREAD_FLAG_STOP)
232*10465441SEvalZero                break;
233*10465441SEvalZero 
234*10465441SEvalZero           D1(printk("jffs2: GC THREAD GC BEGIN\n"));
235*10465441SEvalZero 
236*10465441SEvalZero           mte=(cyg_dir *) sb->s_root;
237*10465441SEvalZero           RT_ASSERT(mte != NULL);
238*10465441SEvalZero //          rt_mutex_take(&mte->fs->syncmode, RT_WAITING_FOREVER);
239*10465441SEvalZero 
240*10465441SEvalZero           if (jffs2_garbage_collect_pass(c) == -ENOSPC) {
241*10465441SEvalZero                printf("No space for garbage collection. "
242*10465441SEvalZero                       "Aborting JFFS2 GC thread\n");
243*10465441SEvalZero                break;
244*10465441SEvalZero           }
245*10465441SEvalZero //          rt_mutex_release(&mte->fs->syncmode);
246*10465441SEvalZero           D1(printk("jffs2: GC THREAD GC END\n"));
247*10465441SEvalZero      }
248*10465441SEvalZero 
249*10465441SEvalZero      D1(printk("jffs2_garbage_collect_thread EXIT\n"));
250*10465441SEvalZero      rt_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_HAS_EXIT);
251*10465441SEvalZero }
252*10465441SEvalZero #endif
253