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