fs: Add sdfat
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / fs / sdfat / dfr.h
1 /*
2 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifndef _SDFAT_DEFRAG_H
19 #define _SDFAT_DEFRAG_H
20
21 #ifdef CONFIG_SDFAT_DFR
22
23 /* Tuning parameters */
24 #define DFR_MIN_TIMEOUT (1 * HZ) // Minimum timeout for forced-sync
25 #define DFR_DEFAULT_TIMEOUT (10 * HZ) // Default timeout for forced-sync
26
27 #define DFR_DEFAULT_CLEAN_RATIO (50) // Wake-up daemon when clean AU ratio under 50%
28 #define DFR_DEFAULT_WAKEUP_RATIO (10) // Wake-up daemon when clean AU ratio under 10%, regardless of frag_ratio
29
30 #define DFR_DEFAULT_FRAG_RATIO (130) // Wake-up daemon when frag_ratio over 130%
31
32 #define DFR_DEFAULT_PACKING_RATIO (10) // Call allocator with PACKING flag, when clean AU ratio under 10%
33
34 #define DFR_DEFAULT_STOP_RATIO (98) // Stop defrag_daemon when disk used ratio over 98%
35 #define DFR_FULL_RATIO (100)
36
37 #define DFR_MAX_AU_MOVED (16) // Maximum # of AUs for a request
38
39
40 /* Debugging support*/
41 #define dfr_err(fmt, args...) pr_err("DFR: " fmt "\n", args)
42
43 #ifdef CONFIG_SDFAT_DFR_DEBUG
44 #define dfr_debug(fmt, args...) pr_debug("DFR: " fmt "\n", args)
45 #else
46 #define dfr_debug(fmt, args...)
47 #endif
48
49
50 /* Error handling */
51 #define ERR_HANDLE(err) { \
52 if (err) { \
53 dfr_debug("err %d", err); \
54 goto error; \
55 } \
56 }
57
58 #define ERR_HANDLE2(cond, err, val) { \
59 if (cond) { \
60 err = val; \
61 dfr_debug("err %d", err); \
62 goto error; \
63 } \
64 }
65
66
67 /* Arguments IN-OUT */
68 #define IN
69 #define OUT
70 #define INOUT
71
72
73 /* Macros */
74 #define GET64_HI(var64) ((unsigned int)((var64) >> 32))
75 #define GET64_LO(var64) ((unsigned int)(((var64) << 32) >> 32))
76 #define SET64_HI(dst64, var32) { (dst64) = ((loff_t)(var32) << 32) | ((dst64) & 0x00000000ffffffffLL); }
77 #define SET64_LO(dst64, var32) { (dst64) = ((dst64) & 0xffffffff00000000LL) | ((var32) & 0x00000000ffffffffLL); }
78
79 #define GET32_HI(var32) ((unsigned short)((var32) >> 16))
80 #define GET32_LO(var32) ((unsigned short)(((var32) << 16) >> 16))
81 #define SET32_HI(dst32, var16) { (dst32) = ((unsigned int)(var16) << 16) | ((dst32) & 0x0000ffff); }
82 #define SET32_LO(dst32, var16) { (dst32) = ((dst32) & 0xffff0000) | ((unsigned int)(var16) & 0x0000ffff); }
83
84
85 /* FAT32 related */
86 #define FAT32_EOF (0x0fffffff)
87 #define FAT32_RESERVED (0x0ffffff7)
88 #define FAT32_UNUSED_CLUS (2)
89
90 #define CLUS_PER_AU(sb) ( \
91 (SDFAT_SB(sb)->options.amap_opt.sect_per_au) >> (SDFAT_SB(sb)->fsi.sect_per_clus_bits) \
92 )
93 #define PAGES_PER_AU(sb) ( \
94 ((SDFAT_SB(sb)->options.amap_opt.sect_per_au) << ((sb)->s_blocksize_bits)) \
95 >> PAGE_SHIFT \
96 )
97 #define PAGES_PER_CLUS(sb) ((SDFAT_SB(sb)->fsi.cluster_size) >> PAGE_SHIFT)
98
99 #define FAT32_CHECK_CLUSTER(fsi, clus, err) \
100 { \
101 if (((clus) < FAT32_UNUSED_CLUS) || \
102 ((clus) > (fsi)->num_clusters) || \
103 ((clus) >= FAT32_RESERVED)) { \
104 dfr_err("clus %08x, fsi->num_clusters %08x", (clus), (fsi)->num_clusters); \
105 err = -EINVAL; \
106 } else { \
107 err = 0; \
108 } \
109 }
110
111
112 /* IOCTL_DFR_INFO */
113 struct defrag_info_arg {
114 /* PBS info */
115 unsigned int sec_sz;
116 unsigned int clus_sz;
117 unsigned int total_sec;
118 unsigned int fat_offset_sec;
119 unsigned int fat_sz_sec;
120 unsigned int n_fat;
121 unsigned int hidden_sectors;
122
123 /* AU info */
124 unsigned int sec_per_au;
125 };
126
127
128 /* IOC_DFR_TRAV */
129 #define DFR_TRAV_HEADER_IDX (0)
130
131 #define DFR_TRAV_TYPE_HEADER (0x0000000F)
132 #define DFR_TRAV_TYPE_DIR (1)
133 #define DFR_TRAV_TYPE_FILE (2)
134 #define DFR_TRAV_TYPE_TEST (DFR_TRAV_TYPE_HEADER | 0x10000000)
135
136 #define DFR_TRAV_ROOT_IPOS (0xFFFFFFFFFFFFFFFFLL)
137
138 struct defrag_trav_arg {
139 int type;
140 unsigned int start_clus;
141 loff_t i_pos;
142 char name[MAX_DOSNAME_BUF_SIZE];
143 char dummy1;
144 int dummy2;
145 };
146
147 #define DFR_TRAV_STAT_DONE (0x1)
148 #define DFR_TRAV_STAT_MORE (0x2)
149 #define DFR_TRAV_STAT_ERR (0xFF)
150
151 struct defrag_trav_header {
152 int type;
153 unsigned int start_clus;
154 loff_t i_pos;
155 char name[MAX_DOSNAME_BUF_SIZE];
156 char stat;
157 unsigned int nr_entries;
158 };
159
160
161 /* IOC_DFR_REQ */
162 #define REQ_HEADER_IDX (0)
163
164 #define DFR_CHUNK_STAT_ERR (0xFFFFFFFF)
165 #define DFR_CHUNK_STAT_REQ (0x1)
166 #define DFR_CHUNK_STAT_WB (0x2)
167 #define DFR_CHUNK_STAT_FAT (0x4)
168 #define DFR_CHUNK_STAT_PREP (DFR_CHUNK_STAT_REQ | DFR_CHUNK_STAT_WB | DFR_CHUNK_STAT_FAT)
169 #define DFR_CHUNK_STAT_PASS (0x0000000F)
170
171 struct defrag_chunk_header {
172 int mode;
173 unsigned int nr_chunks;
174 loff_t dummy1;
175 int dummy2[4];
176 union {
177 int *dummy3;
178 int dummy4;
179 };
180 int dummy5;
181 };
182
183 struct defrag_chunk_info {
184 int stat;
185 /* File related */
186 unsigned int f_clus;
187 loff_t i_pos;
188 /* Cluster related */
189 unsigned int d_clus;
190 unsigned int nr_clus;
191 unsigned int prev_clus;
192 unsigned int next_clus;
193 union {
194 void *dummy;
195 /* req status */
196 unsigned int new_idx;
197 };
198 /* AU related */
199 unsigned int au_clus;
200 };
201
202
203 /* Global info */
204 #define DFR_MODE_BACKGROUND (0x1)
205 #define DFR_MODE_FOREGROUND (0x2)
206 #define DFR_MODE_ONESHOT (0x4)
207 #define DFR_MODE_BATCHED (0x8)
208 #define DFR_MODE_TEST (DFR_MODE_BACKGROUND | 0x10000000)
209
210 #define DFR_SB_STAT_IDLE (0)
211 #define DFR_SB_STAT_REQ (1)
212 #define DFR_SB_STAT_VALID (2)
213
214 #define DFR_INO_STAT_IDLE (0)
215 #define DFR_INO_STAT_REQ (1)
216 struct defrag_info {
217 struct mutex lock;
218 atomic_t stat;
219 struct defrag_chunk_info *chunks;
220 unsigned int nr_chunks;
221 struct list_head entry;
222 };
223
224
225 /* SPO test flags */
226 #define DFR_SPO_NONE (0)
227 #define DFR_SPO_NORMAL (1)
228 #define DFR_SPO_DISCARD (2)
229 #define DFR_SPO_FAT_NEXT (3)
230 #define DFR_SPO_RANDOM (4)
231
232
233 /* Extern functions */
234 int defrag_get_info(struct super_block *sb, struct defrag_info_arg *arg);
235
236 int defrag_scan_dir(struct super_block *sb, struct defrag_trav_arg *arg);
237
238 int defrag_validate_cluster(struct inode *inode, struct defrag_chunk_info *chunk, int skip_prev);
239 int defrag_reserve_clusters(struct super_block *sb, int nr_clus);
240 int defrag_mark_ignore(struct super_block *sb, unsigned int clus);
241 void defrag_unmark_ignore_all(struct super_block *sb);
242
243 int defrag_map_cluster(struct inode *inode, unsigned int clu_offset, unsigned int *clu);
244 void defrag_writepage_end_io(struct page *page);
245
246 void defrag_update_fat_prev(struct super_block *sb, int force);
247 void defrag_update_fat_next(struct super_block *sb);
248 void defrag_check_discard(struct super_block *sb);
249 int defrag_free_cluster(struct super_block *sb, unsigned int clus);
250
251 int defrag_check_defrag_required(struct super_block *sb, int *totalau, int *cleanau, int *fullau);
252 int defrag_check_defrag_on(struct inode *inode, loff_t start, loff_t end, int cancel, const char *caller);
253
254 #ifdef CONFIG_SDFAT_DFR_DEBUG
255 void defrag_spo_test(struct super_block *sb, int flag, const char *caller);
256 #endif
257
258 #endif /* CONFIG_SDFAT_DFR */
259
260 #endif /* _SDFAT_DEFRAG_H */
261