-
Notifications
You must be signed in to change notification settings - Fork 2
/
libext2fs-add-a-unit-test-for-inline-data
353 lines (346 loc) · 9.25 KB
/
libext2fs-add-a-unit-test-for-inline-data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
libext2fs: add a unit test for inline data
From: Zheng Liu <[email protected]>
In this unit test, we will test manipulation of regular file and dir
for inline data to make sure all tests pass.
Signed-off-by: Zheng Liu <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>
---
lib/ext2fs/Makefile.in | 8 +-
lib/ext2fs/inline_data.c | 295 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 302 insertions(+), 1 deletion(-)
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 001c222..6b188b8 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -390,6 +390,11 @@ tst_inline: $(srcdir)/inline.c $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
$(Q) $(CC) -o tst_inline $(srcdir)/inline.c $(ALL_CFLAGS) -DDEBUG \
$(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
+tst_inline_data: inline_data.c $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_inline_data $(srcdir)/inline_data.c $(ALL_CFLAGS) \
+ -DDEBUG $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
+
tst_csum: csum.c $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR) $(STATIC_LIBE2P) \
$(top_srcdir)/lib/e2p/e2p.h
$(E) " LD $@"
@@ -407,7 +412,7 @@ mkjournal: mkjournal.c $(STATIC_LIBEXT2FS) $(DEPLIBCOM_ERR)
check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount \
tst_super_size tst_types tst_inode_size tst_csum tst_crc32c tst_bitmaps \
- tst_inline
+ tst_inline tst_inline_data
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_bitops
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_badblocks
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_iscan
@@ -417,6 +422,7 @@ check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount \
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_inode_size
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_csum
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_inline
+ LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_inline_data
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_crc32c
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) \
./tst_bitmaps -f $(srcdir)/tst_bitmaps_cmds > tst_bitmaps_out
diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c
index e9892e6..ea3736c 100644
--- a/lib/ext2fs/inline_data.c
+++ b/lib/ext2fs/inline_data.c
@@ -900,3 +900,298 @@ out:
ext2fs_free_mem(&inode);
return retval;
}
+
+#ifdef DEBUG
+#include "e2p/e2p.h"
+
+/*
+ * The length of buffer is set to 64 because in inode's i_block member it only
+ * can save 60 bytes. Thus this value can let the data being saved in extra
+ * space.
+ */
+#define BUF_LEN (64)
+
+/*
+ * Test manipulation of regular file.
+ *
+ * In this test case, the following operations are tested:
+ * - regular file creation with inline_data flag
+ * - try to write data into inode while the size of data is fit for saving in
+ * inode
+ * - read data from inode
+ * - write data without changing the size of inline data
+ * - get the size of inline data
+ * - truncate
+ * - check header
+ */
+static errcode_t test_file(ext2_filsys fs)
+{
+ ext2_ino_t newfile;
+ errcode_t retval;
+ unsigned int written;
+ struct ext2_inode_large inode;
+ char *buf, *cmpbuf;
+ int inline_size;
+
+ retval = ext2fs_new_inode(fs, 2, 010755, 0, &newfile);
+ if (retval) {
+ com_err("test_file", retval,
+ "While creating a new file");
+ return 1;
+ }
+
+ retval = ext2fs_write_new_inode(fs, newfile, (void *)&inode);
+ if (retval) {
+ com_err("test_file", retval,
+ "While writting a new inode");
+ return 1;
+ }
+
+ retval = ext2fs_get_arrayzero(BUF_LEN, sizeof(char), &buf);
+ if (retval) {
+ com_err("test_file", retval, "While creating buffer");
+ return 1;
+ }
+ memset(buf, 'a', BUF_LEN);
+ retval = ext2fs_try_to_write_inline_data(fs, newfile, buf,
+ BUF_LEN, &written);
+ if (retval) {
+ com_err("test_file", retval,
+ "While trying to write a regular file");
+ return 1;
+ }
+
+ if (written != BUF_LEN) {
+ printf("inline_data: write a regular file error, written %d "
+ "should be %d.\n", written, BUF_LEN);
+ return 1;
+ }
+
+ inline_size = ext2fs_get_inline_data_size(fs, newfile);
+ if (inline_size != BUF_LEN) {
+ printf("inline_data: the size of inline data is incorrect\n");
+ return 1;
+ }
+
+ retval = ext2fs_get_arrayzero(BUF_LEN, sizeof(char), &cmpbuf);
+ if (retval) {
+ com_err("test_file", retval, "While creating buffer");
+ return 1;
+ }
+ retval = ext2fs_read_inline_data(fs, newfile, cmpbuf);
+ if (retval) {
+ com_err("test_file", retval, "While reading");
+ return 1;
+ }
+
+ if (memcmp(buf, cmpbuf, BUF_LEN)) {
+ printf("inline_data: read a regular file error\n");
+ return 1;
+ }
+
+ retval = ext2fs_write_inline_data(fs, newfile, buf);
+ if (retval) {
+ printf("inline_data: write a regular file error\n");
+ return 1;
+ }
+
+ retval = ext2fs_punch(fs, newfile, 0, 0, 0, ~0U);
+ if (retval) {
+ printf("inline_data: truncate failed\n");
+ return 1;
+ }
+
+ retval = ext2fs_inline_data_header_check(fs, newfile);
+ if (retval != 1) {
+ printf("inline_data: header check failed\n");
+ return 1;
+ }
+
+ ext2fs_free_mem(&buf);
+ ext2fs_free_mem(&cmpbuf);
+
+ printf("tst_inline_data(REG): OK\n");
+
+ return 0;
+}
+
+static errcode_t test_create_parent_dir(ext2_filsys fs, ext2_ino_t *ino)
+{
+ const char *dot = ".";
+ errcode_t retval;
+ ext2_ino_t dir, tmp;
+
+ retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, LINUX_S_IFDIR | 0755,
+ 0, &dir);
+ if (retval) {
+ com_err("test_create_parent_dir", retval,
+ "while allocating a inode");
+ return 1;
+ }
+
+ retval = ext2fs_inline_data_mkdir(fs, EXT2_ROOT_INO, dir);
+ if (retval) {
+ com_err("test_create_parent_dir", retval,
+ "while making test dir");
+ return 1;
+ }
+
+ ext2fs_inode_alloc_stats2(fs, dir, +1, 1);
+
+ retval = ext2fs_lookup(fs, dir, dot, strlen(dot), 0, &tmp);
+ if (retval) {
+ com_err("test_create_parent_dir", retval,
+ "while looking up test dir");
+ return 1;
+ }
+
+ if (tmp != dir) {
+ printf("inline_data: looking up '.' error\n");
+ return 1;
+ }
+
+ *ino = dir;
+ return 0;
+}
+
+static errcode_t test_manipulate_dirs(ext2_filsys fs, ext2_ino_t parent)
+{
+ errcode_t retval;
+ ext2_ino_t dir = 12, tmp;
+ char name[PATH_MAX];
+ int i;
+
+ /*
+ * Here we only try to create 4 dirs:
+ * 4 bytes (parent inode) + 56 bytes
+ * In ext4 a dir at least need to take 12 bytes. So it only can
+ * save 4 dirs in inode's i_block.
+ */
+ for (i = 0; i < 4; i++) {
+ tmp = 0;
+ snprintf(name, PATH_MAX, "%d", i);
+ retval = ext2fs_mkdir(fs, parent, 0, name);
+ if (retval) {
+ com_err("test_manipulate_dirs", retval,
+ "while making dir %s", name);
+ return 1;
+ }
+
+ retval = ext2fs_lookup(fs, parent, name,
+ strlen(name), 0, &tmp);
+ if (retval) {
+ com_err("test_manipulate_dirs", retval,
+ "while looking up test dir");
+ return 1;
+ }
+
+ if (tmp != dir) {
+ printf("inline_data: create subdirs failed, "
+ "dir inode is %d, but now is %d\n", dir, tmp);
+ return 1;
+ }
+
+ retval = ext2fs_inline_data_dirsearch(fs, parent, name,
+ strlen(name));
+ if (retval != 1) {
+ printf("inline_data: dirsearch %s failed\n", name);
+ return 1;
+ }
+
+ dir++;
+ }
+
+ /*
+ * XXX: In e2fsprogs the size of inline data doesn't expand from i_block
+ * space to extra space while making a new dir. If extra space has been
+ * used while creating a new dir, extra space will be used. So here
+ * ext2fs_mkdir() will return EXT2_ET_DIR_NO_SPACE.
+ */
+ snprintf(name, PATH_MAX, "%d", i);
+ retval = ext2fs_mkdir(fs, parent, 0, name);
+ if (retval != EXT2_ET_DIR_NO_SPACE) {
+ com_err("test_manipulate_dirs", retval,
+ "while making dir %s", name);
+ return 1;
+ }
+
+ retval = ext2fs_expand_dir(fs, parent);
+ if (retval) {
+ com_err("test_manipulate_dirs", retval,
+ "while expanding test dir");
+ return 1;
+ }
+
+ retval = ext2fs_inline_data_header_check(fs, parent);
+ if (retval != 1) {
+ printf("inline_data: header check failed\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Test manipulation of directory.
+ *
+ * In this test case, we first try to create a test dir. Then we will try to
+ * create, lookup, expand this dir and make sure all tests pass.
+ */
+static errcode_t test_dir(ext2_filsys fs)
+{
+ errcode_t retval;
+ ext2_ino_t dir;
+
+ retval = test_create_parent_dir(fs, &dir);
+ if (retval)
+ return 1;
+
+ retval = test_manipulate_dirs(fs, dir);
+ if (retval)
+ return 1;
+
+ printf("tst_inline_data(DIR): OK\n");
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ struct ext2_super_block param;
+ errcode_t retval;
+ ext2_filsys fs;
+ int i;
+
+ memset(¶m, 0, sizeof(param));
+ ext2fs_blocks_count_set(¶m, 32768);
+
+ retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m,
+ test_io_manager, &fs);
+ if (retval) {
+ com_err("setup", retval,
+ "While initializing filesystem");
+ exit(1);
+ }
+
+ fs->super->s_feature_ro_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
+ fs->super->s_feature_incompat |= EXT4_FEATURE_INCOMPAT_INLINE_DATA;
+ fs->super->s_rev_level = EXT2_DYNAMIC_REV;
+ fs->super->s_inode_size = 256;
+
+ retval = ext2fs_allocate_tables(fs);
+ if (retval) {
+ com_err("setup", retval,
+ "while allocating tables for test filesysmte");
+ exit(1);
+ }
+
+ retval = test_file(fs);
+ if (retval)
+ return retval;
+
+ retval = test_dir(fs);
+ if (retval)
+ return retval;
+
+ return 0;
+}
+#endif
--
1.7.12.rc0.22.gcdd159b