Commit | Line | Data |
---|---|---|
00a9ab8c BM |
1 | #include "sdfat.h" |
2 | ||
3 | #define SDFAT_VF_CLUS_MAX 7 /* 512 Byte ~ 32 KByte */ | |
4 | #define SDFAT_EF_CLUS_MAX 17 /* 512 Byte ~ 32 MByte */ | |
5 | ||
6 | enum { | |
7 | SDFAT_MNT_FAT12, | |
8 | SDFAT_MNT_FAT16, | |
9 | SDFAT_MNT_FAT32, | |
10 | SDFAT_MNT_EXFAT, | |
11 | SDFAT_MNT_RO, | |
12 | SDFAT_MNT_MAX | |
13 | }; | |
14 | ||
15 | enum { | |
16 | SDFAT_OP_EXFAT_MNT, | |
17 | SDFAT_OP_MKDIR, | |
18 | SDFAT_OP_CREATE, | |
19 | SDFAT_OP_READ, | |
20 | SDFAT_OP_WRITE, | |
21 | SDFAT_OP_TRUNC, | |
22 | SDFAT_OP_MAX | |
23 | }; | |
24 | ||
25 | enum { | |
26 | SDFAT_VOL_4G, | |
27 | SDFAT_VOL_8G, | |
28 | SDFAT_VOL_16G, | |
29 | SDFAT_VOL_32G, | |
30 | SDFAT_VOL_64G, | |
31 | SDFAT_VOL_128G, | |
32 | SDFAT_VOL_256G, | |
33 | SDFAT_VOL_512G, | |
34 | SDFAT_VOL_XTB, | |
35 | SDFAT_VOL_MAX | |
36 | }; | |
37 | ||
38 | static struct sdfat_statistics { | |
39 | u32 clus_vfat[SDFAT_VF_CLUS_MAX]; | |
40 | u32 clus_exfat[SDFAT_EF_CLUS_MAX]; | |
41 | u32 mnt_cnt[SDFAT_MNT_MAX]; | |
42 | u32 nofat_op[SDFAT_OP_MAX]; | |
43 | u32 vol_size[SDFAT_VOL_MAX]; | |
44 | } statistics; | |
45 | ||
46 | static struct kset *sdfat_statistics_kset; | |
47 | ||
48 | static ssize_t vfat_cl_show(struct kobject *kobj, | |
49 | struct kobj_attribute *attr, char *buff) | |
50 | { | |
51 | return snprintf(buff, PAGE_SIZE, "\"VCL_512B_I\":\"%u\"," | |
52 | "\"VCL_1K_I\":\"%u\",\"VCL_2K_I\":\"%u\"," | |
53 | "\"VCL_4K_I\":\"%u\",\"VCL_8K_I\":\"%u\"," | |
54 | "\"VCL_16K_I\":\"%u\",\"VCL_32K_I\":\"%u\"\n", | |
55 | statistics.clus_vfat[0], statistics.clus_vfat[1], | |
56 | statistics.clus_vfat[2], statistics.clus_vfat[3], | |
57 | statistics.clus_vfat[4], statistics.clus_vfat[5], | |
58 | statistics.clus_vfat[6]); | |
59 | } | |
60 | ||
61 | static ssize_t exfat_cl_show(struct kobject *kobj, | |
62 | struct kobj_attribute *attr, char *buff) | |
63 | { | |
64 | return snprintf(buff, PAGE_SIZE, "\"ECL_512B_I\":\"%u\"," | |
65 | "\"ECL_1K_I\":\"%u\",\"ECL_2K_I\":\"%u\"," | |
66 | "\"ECL_4K_I\":\"%u\",\"ECL_8K_I\":\"%u\"," | |
67 | "\"ECL_16K_I\":\"%u\",\"ECL_32K_I\":\"%u\"," | |
68 | "\"ECL_64K_I\":\"%u\",\"ECL_128K_I\":\"%u\"," | |
69 | "\"ECL_256K_I\":\"%u\",\"ECL_512K_I\":\"%u\"," | |
70 | "\"ECL_1M_I\":\"%u\",\"ECL_2M_I\":\"%u\"," | |
71 | "\"ECL_4M_I\":\"%u\",\"ECL_8M_I\":\"%u\"," | |
72 | "\"ECL_16M_I\":\"%u\",\"ECL_32M_I\":\"%u\"\n", | |
73 | statistics.clus_exfat[0], statistics.clus_exfat[1], | |
74 | statistics.clus_exfat[2], statistics.clus_exfat[3], | |
75 | statistics.clus_exfat[4], statistics.clus_exfat[5], | |
76 | statistics.clus_exfat[6], statistics.clus_exfat[7], | |
77 | statistics.clus_exfat[8], statistics.clus_exfat[9], | |
78 | statistics.clus_exfat[10], statistics.clus_exfat[11], | |
79 | statistics.clus_exfat[12], statistics.clus_exfat[13], | |
80 | statistics.clus_exfat[14], statistics.clus_exfat[15], | |
81 | statistics.clus_exfat[16]); | |
82 | } | |
83 | ||
84 | static ssize_t mount_show(struct kobject *kobj, | |
85 | struct kobj_attribute *attr, char *buff) | |
86 | { | |
87 | return snprintf(buff, PAGE_SIZE, "\"FAT12_MNT_I\":\"%u\"," | |
88 | "\"FAT16_MNT_I\":\"%u\",\"FAT32_MNT_I\":\"%u\"," | |
89 | "\"EXFAT_MNT_I\":\"%u\",\"RO_MNT_I\":\"%u\"\n", | |
90 | statistics.mnt_cnt[SDFAT_MNT_FAT12], | |
91 | statistics.mnt_cnt[SDFAT_MNT_FAT16], | |
92 | statistics.mnt_cnt[SDFAT_MNT_FAT32], | |
93 | statistics.mnt_cnt[SDFAT_MNT_EXFAT], | |
94 | statistics.mnt_cnt[SDFAT_MNT_RO]); | |
95 | } | |
96 | ||
97 | static ssize_t nofat_op_show(struct kobject *kobj, | |
98 | struct kobj_attribute *attr, char *buff) | |
99 | { | |
100 | return snprintf(buff, PAGE_SIZE, "\"NOFAT_MOUNT_I\":\"%u\"," | |
101 | "\"NOFAT_MKDIR_I\":\"%u\",\"NOFAT_CREATE_I\":\"%u\"," | |
102 | "\"NOFAT_READ_I\":\"%u\",\"NOFAT_WRITE_I\":\"%u\"," | |
103 | "\"NOFAT_TRUNC_I\":\"%u\"\n", | |
104 | statistics.nofat_op[SDFAT_OP_EXFAT_MNT], | |
105 | statistics.nofat_op[SDFAT_OP_MKDIR], | |
106 | statistics.nofat_op[SDFAT_OP_CREATE], | |
107 | statistics.nofat_op[SDFAT_OP_READ], | |
108 | statistics.nofat_op[SDFAT_OP_WRITE], | |
109 | statistics.nofat_op[SDFAT_OP_TRUNC]); | |
110 | } | |
111 | ||
112 | static ssize_t vol_size_show(struct kobject *kobj, | |
113 | struct kobj_attribute *attr, char *buff) | |
114 | { | |
115 | return snprintf(buff, PAGE_SIZE, "\"VOL_4G_I\":\"%u\"," | |
116 | "\"VOL_8G_I\":\"%u\",\"VOL_16G_I\":\"%u\"," | |
117 | "\"VOL_32G_I\":\"%u\",\"VOL_64G_I\":\"%u\"," | |
118 | "\"VOL_128G_I\":\"%u\",\"VOL_256G_I\":\"%u\"," | |
119 | "\"VOL_512G_I\":\"%u\",\"VOL_XTB_I\":\"%u\"\n", | |
120 | statistics.vol_size[SDFAT_VOL_4G], | |
121 | statistics.vol_size[SDFAT_VOL_8G], | |
122 | statistics.vol_size[SDFAT_VOL_16G], | |
123 | statistics.vol_size[SDFAT_VOL_32G], | |
124 | statistics.vol_size[SDFAT_VOL_64G], | |
125 | statistics.vol_size[SDFAT_VOL_128G], | |
126 | statistics.vol_size[SDFAT_VOL_256G], | |
127 | statistics.vol_size[SDFAT_VOL_512G], | |
128 | statistics.vol_size[SDFAT_VOL_XTB]); | |
129 | } | |
130 | ||
131 | static struct kobj_attribute vfat_cl_attr = __ATTR_RO(vfat_cl); | |
132 | static struct kobj_attribute exfat_cl_attr = __ATTR_RO(exfat_cl); | |
133 | static struct kobj_attribute mount_attr = __ATTR_RO(mount); | |
134 | static struct kobj_attribute nofat_op_attr = __ATTR_RO(nofat_op); | |
135 | static struct kobj_attribute vol_size_attr = __ATTR_RO(vol_size); | |
136 | ||
137 | static struct attribute *attributes_statistics[] = { | |
138 | &vfat_cl_attr.attr, | |
139 | &exfat_cl_attr.attr, | |
140 | &mount_attr.attr, | |
141 | &nofat_op_attr.attr, | |
142 | &vol_size_attr.attr, | |
143 | NULL, | |
144 | }; | |
145 | ||
146 | static struct attribute_group attr_group_statistics = { | |
147 | .attrs = attributes_statistics, | |
148 | }; | |
149 | ||
150 | int sdfat_statistics_init(struct kset *sdfat_kset) | |
151 | { | |
152 | int err; | |
153 | ||
154 | sdfat_statistics_kset = kset_create_and_add("statistics", NULL, &sdfat_kset->kobj); | |
155 | if (!sdfat_statistics_kset) { | |
156 | pr_err("[SDFAT] failed to create sdfat statistics kobj\n"); | |
157 | return -ENOMEM; | |
158 | } | |
159 | ||
160 | err = sysfs_create_group(&sdfat_statistics_kset->kobj, &attr_group_statistics); | |
161 | if (err) { | |
162 | pr_err("[SDFAT] failed to create sdfat statistics attributes\n"); | |
163 | kset_unregister(sdfat_statistics_kset); | |
164 | sdfat_statistics_kset = NULL; | |
165 | return err; | |
166 | } | |
167 | ||
168 | return 0; | |
169 | } | |
170 | ||
171 | void sdfat_statistics_uninit(void) | |
172 | { | |
173 | if (sdfat_statistics_kset) { | |
174 | sysfs_remove_group(&sdfat_statistics_kset->kobj, &attr_group_statistics); | |
175 | kset_unregister(sdfat_statistics_kset); | |
176 | sdfat_statistics_kset = NULL; | |
177 | } | |
178 | memset(&statistics, 0, sizeof(struct sdfat_statistics)); | |
179 | } | |
180 | ||
181 | void sdfat_statistics_set_mnt(FS_INFO_T *fsi) | |
182 | { | |
183 | if (fsi->vol_type == EXFAT) { | |
184 | statistics.mnt_cnt[SDFAT_MNT_EXFAT]++; | |
185 | statistics.nofat_op[SDFAT_OP_EXFAT_MNT] = 1; | |
186 | if (fsi->sect_per_clus_bits < SDFAT_EF_CLUS_MAX) | |
187 | statistics.clus_exfat[fsi->sect_per_clus_bits]++; | |
188 | else | |
189 | statistics.clus_exfat[SDFAT_EF_CLUS_MAX - 1]++; | |
190 | return; | |
191 | } | |
192 | ||
193 | if (fsi->vol_type == FAT32) | |
194 | statistics.mnt_cnt[SDFAT_MNT_FAT32]++; | |
195 | else if (fsi->vol_type == FAT16) | |
196 | statistics.mnt_cnt[SDFAT_MNT_FAT16]++; | |
197 | else if (fsi->vol_type == FAT12) | |
198 | statistics.mnt_cnt[SDFAT_MNT_FAT12]++; | |
199 | ||
200 | if (fsi->sect_per_clus_bits < SDFAT_VF_CLUS_MAX) | |
201 | statistics.clus_vfat[fsi->sect_per_clus_bits]++; | |
202 | else | |
203 | statistics.clus_vfat[SDFAT_VF_CLUS_MAX - 1]++; | |
204 | } | |
205 | ||
206 | void sdfat_statistics_set_mnt_ro(void) | |
207 | { | |
208 | statistics.mnt_cnt[SDFAT_MNT_RO]++; | |
209 | } | |
210 | ||
211 | void sdfat_statistics_set_mkdir(u8 flags) | |
212 | { | |
213 | if (flags != 0x03) | |
214 | return; | |
215 | statistics.nofat_op[SDFAT_OP_MKDIR] = 1; | |
216 | } | |
217 | ||
218 | void sdfat_statistics_set_create(u8 flags) | |
219 | { | |
220 | if (flags != 0x03) | |
221 | return; | |
222 | statistics.nofat_op[SDFAT_OP_CREATE] = 1; | |
223 | } | |
224 | ||
225 | /* flags : file or dir flgas, 0x03 means no fat-chain. | |
226 | * clu_offset : file or dir logical cluster offset | |
227 | * create : BMAP_ADD_CLUSTER or not | |
228 | * | |
229 | * File or dir have BMAP_ADD_CLUSTER is no fat-chain write | |
230 | * when they have 0x03 flag and two or more clusters. | |
231 | * And don`t have BMAP_ADD_CLUSTER is no fat-chain read | |
232 | * when above same condition. | |
233 | */ | |
234 | void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create) | |
235 | { | |
236 | if ((flags == 0x03) && (clu_offset > 1)) { | |
237 | if (create) | |
238 | statistics.nofat_op[SDFAT_OP_WRITE] = 1; | |
239 | else | |
240 | statistics.nofat_op[SDFAT_OP_READ] = 1; | |
241 | } | |
242 | } | |
243 | ||
244 | /* flags : file or dir flgas, 0x03 means no fat-chain. | |
245 | * clu : cluster chain | |
246 | * | |
247 | * Set no fat-chain trunc when file or dir have 0x03 flag | |
248 | * and two or more clusters. | |
249 | */ | |
250 | void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu) | |
251 | { | |
252 | if ((flags == 0x03) && (clu->size > 1)) | |
253 | statistics.nofat_op[SDFAT_OP_TRUNC] = 1; | |
254 | } | |
255 | ||
256 | void sdfat_statistics_set_vol_size(struct super_block *sb) | |
257 | { | |
258 | u64 vol_size; | |
259 | FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); | |
260 | ||
261 | vol_size = (u64)fsi->num_sectors << sb->s_blocksize_bits; | |
262 | ||
263 | if (vol_size <= ((u64)1 << 32)) | |
264 | statistics.vol_size[SDFAT_VOL_4G]++; | |
265 | else if (vol_size <= ((u64)1 << 33)) | |
266 | statistics.vol_size[SDFAT_VOL_8G]++; | |
267 | else if (vol_size <= ((u64)1 << 34)) | |
268 | statistics.vol_size[SDFAT_VOL_16G]++; | |
269 | else if (vol_size <= ((u64)1 << 35)) | |
270 | statistics.vol_size[SDFAT_VOL_32G]++; | |
271 | else if (vol_size <= ((u64)1 << 36)) | |
272 | statistics.vol_size[SDFAT_VOL_64G]++; | |
273 | else if (vol_size <= ((u64)1 << 37)) | |
274 | statistics.vol_size[SDFAT_VOL_128G]++; | |
275 | else if (vol_size <= ((u64)1 << 38)) | |
276 | statistics.vol_size[SDFAT_VOL_256G]++; | |
277 | else if (vol_size <= ((u64)1 << 39)) | |
278 | statistics.vol_size[SDFAT_VOL_512G]++; | |
279 | else | |
280 | statistics.vol_size[SDFAT_VOL_XTB]++; | |
281 | } |