-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathvdfs4.h
1549 lines (1338 loc) · 45.1 KB
/
vdfs4.h
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
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* VDFS4 -- Vertically Deliberate improved performance File System
*
* Copyright 2012 by Samsung Electronics, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef _VDFS4_VDFS4_H_
#define _VDFS4_VDFS4_H_
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/rbtree.h>
#include <linux/fs.h>
#include <linux/aio.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/pagemap.h>
#include <linux/completion.h>
#include <linux/version.h>
#include <linux/list.h>
#include <linux/crypto.h>
#include <linux/xattr.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/kfifo.h>
#include <linux/delay.h>
#include "vdfs4_layout.h"
#include "btree.h"
#include "cattree.h"
#include "debug.h"
#include "lock_trace.h"
#ifdef CONFIG_VDFS4_AUTHENTICATION
#include <crypto/internal/hash.h>
#include <crypto/md5.h>
#include <linux/mpi.h>
#include <crypto/crypto_wrapper.h>
#endif
#define VDFS4_NAME "vdfs"
#define UUL_MAX_LEN 20
#define VDFS4_DEBUG_DUMP /* enable meta dump in memory */
/*
* Dump out the contents of some memory nicely...
*/
#if defined(CONFIG_SEPARATE_PRINTK_FROM_USER) && !defined(MODULE)
void _sep_printk_start(void);
void _sep_printk_end(void);
#else
#define _sep_printk_start() {}
#define _sep_printk_end() {}
#endif
struct vdfs4_packtree_meta_common {
__u64 packoffset; /* packtree first bnode offset in file */
__u64 nfs_offset; /* inode finder info for nfs callbacks */
__u64 xattr_off; /* xattr area offset in file (in pages) */
__u64 chtab_off; /* chunk index table offset */
__u32 chunk_cnt; /* chunk count in image */
__u16 squash_bss; /* squashfs image block size shift */
__u16 compr_type; /* squashfs image compression type */
__u32 inodes_cnt; /* number of inodes in the squashfs image */
};
struct vdfs4_ioc_file_info {
int open_count;
int compressed_status;
int compressed_type;
int authenticated_status;
int encryption_status; /* remain it for compatilbilty */
int extents_num;
unsigned long long size;
unsigned long long compressed_size; /* If compressed type */
int chunk_cnt; /* If compressed type */
int compressed_chunk_cnt; /* If compressed type */
int uncompressed_chunk_cnt; /* If compressed type */
};
#define VDFS4_Z_NEED_DICT_ERR -7
#define HW_DECOMPRESSOR_PAGES_NUM 32
#define SQUASHFS_COMPR_NR 6
/* INTERNAL CONSTANTS, do not export them via ioctl or disk format */
enum compr_type {
VDFS4_COMPR_UNDEF = 0, /* Undefined or uninitialized */
VDFS4_COMPR_NONE, /* No compression */
VDFS4_COMPR_ZLIB,
VDFS4_COMPR_LZO,
VDFS4_COMPR_XZ,
VDFS4_COMPR_LZMA,
VDFS4_COMPR_GZIP,
VDFS4_COMPR_NR,
};
enum hash_type {
VDFS4_HASH_UNDEF = 0,
VDFS4_HASH_SHA1,
VDFS4_HASH_SHA256,
VDFS4_HASH_MD5,
VDFS4_HASH_NR,
};
enum vdfs4_read_type {
VDFS4_META_READ = 0,
VDFS4_PACKTREE_READ,
VDFS4_FBASED_READ_M,
VDFS4_FBASED_READ_C, /* file based compressed contenes read */
VDFS4_FBASED_READ_UNC, /* file based un-compresed contents read */
VDFS4_READ_NR,
};
/* Enabels additional print at mount - how long mount is */
/* #define CONFIG_VDFS4_PRINT_MOUNT_TIME */
#define VDFS4_BUG(sbi) do { \
vdfs4_record_err_dump_disk((sbi), VDFS4_DEBUG_ERR_BUG, 0, 0, __func__, \
NULL, 0); \
BUG(); \
} while (0)
#define VDFS4_BUG_ON(cond, sbi) do { \
if ((cond)) { \
vdfs4_record_err_dump_disk((sbi), VDFS4_DEBUG_ERR_BUG_ON, \
0, 0, __func__, NULL, 0); \
BUG(); \
} \
} while (0)
#ifdef CONFIG_VDFS4_DEBUG
#define VDFS4_DEBUG_BUG_ON(cond) BUG_ON((cond))
#else
#define VDFS4_DEBUG_BUG_ON(cond) do { \
if (cond) \
VDFS4_ERR(#cond); \
} while (0)
#endif
#define VDFS4_IS_READONLY(sb) (sb->s_flags & MS_RDONLY)
extern unsigned int file_prealloc;
extern unsigned int cattree_prealloc;
#define VDFS4_LINK_MAX 32
#define VDFS4_INVALID_BLOCK (~((sector_t) 0xffff))
/* the block size if fixed in vdfs4 file system = 4K */
#define VDFS4_BLOCK_SIZE (1 << 12)
/** Maximal supported file size. Equal maximal file size supported by VFS */
#define VDFS4_MAX_FILE_SIZE_IN_BYTES MAX_LFS_FILESIZE
/* The eMMCFS runtime flags */
#define EXSB_DIRTY 0
#define IS_MOUNT_FINISHED 2
#define VDFS4_META_CRC 3
#define DO_NOT_CHECK_SIGN 4
#define VOLUME_AUTH 5
/** The VDFS4 inode flags */
#define HAS_BLOCKS_IN_EXTTREE 1
#define VDFS4_IMMUTABLE 2
#define HARD_LINK 10
#define ORPHAN_INODE 12
#define VDFS4_COMPRESSED_FILE 13
/* UNUSED: 14 */
#define VDFS4_AUTH_FILE 15
#define VDFS4_READ_ONLY_AUTH 16
/* UNUSED: 17 */
#define VDFS4_PROFILED_FILE 18
/* Macros for calculating catalog tree expand step size.
* x - total blocks count on volume
* right shift 7 - empirical value. For example, on 1G volume catalog tree will
* expands by 8M one step*/
#define TREE_EXPAND_STEP(x) (x >> 7)
/* Preallocation blocks amount */
#define FSM_PREALLOC_DELTA 0
/* Meta/Bnode re-read count
* Set -1 if you want to disable */
#define VDFS4_META_REREAD 2
#define VDFS4_META_REREAD_BNODE 2
/* Virtual Memory Api retry configurations */
#define VDFS4_VMEM_RETRY_CNT 2
#define VDFS4_VMEM_RETRY_INTERVAL 10 /* ms */
/**
* @brief Compare two 64 bit values
* @param [in] b first value
* @param [in] a second value
* @return Returns 0 if a == b, 1 if a > b, -1 if a < b
*/
static inline int cmp_2_le64(__le64 a, __le64 b)
{
if (le64_to_cpu(a) == le64_to_cpu(b))
return 0;
else
return (le64_to_cpu(a) > le64_to_cpu(b)) ? 1 : -1;
}
/* Flags that should be inherited by new inodes from their parent. */
#define VDFS4_FL_INHERITED 0
/* force read-only ioctl command */
#define VDFS4_IOC_FORCE_RO _IOR('A', 1, long)
/* ioctl command code for open_count fetch */
#define VDFS4_IOC_GET_OPEN_COUNT _IOR('C', 1, long)
#define VDFS4_IOC32_GET_OPEN_COUNT _IOR('C', 1, int)
/* File based compression commands */
#define VDFS4_IOC_SET_DECODE_STATUS _IOW('I', 1, int)
#define VDFS4_IOC_GET_DECODE_STATUS _IOR('I', 1, int)
#define VDFS4_IOC_GET_COMPR_TYPE _IOR('J', 1, int)
#define VDFS4_IOC_IS_AUTHENTICATED _IOR('K', 1, int)
#define VDFS4_IOC_GET_FILE_INFORMATION \
_IOR('M', 1, struct vdfs4_ioc_file_info *)
#define vdfs4_vmalloc(...) ({ \
unsigned noio_flags = memalloc_noio_save(); \
void *ret = vmalloc(__VA_ARGS__); \
int retry = VDFS4_VMEM_RETRY_CNT; \
while (unlikely(!ret) && retry--) { \
VDFS4_WARNING("NoMem(%s():%d, %d):vmalloc\n", \
__func__, __LINE__, retry); \
msleep(VDFS4_VMEM_RETRY_INTERVAL); \
ret = vmalloc(__VA_ARGS__); \
} \
memalloc_noio_restore(noio_flags); \
ret; \
})
#define vdfs4_vzalloc(...) ({ \
unsigned noio_flags = memalloc_noio_save(); \
void *ret = vzalloc(__VA_ARGS__); \
int retry = VDFS4_VMEM_RETRY_CNT; \
while (unlikely(!ret) && retry--) { \
VDFS4_WARNING("NoMem(%s():%d, %d):vzalloc\n", \
__func__, __LINE__, retry); \
msleep(VDFS4_VMEM_RETRY_INTERVAL); \
ret = vzalloc(__VA_ARGS__); \
} \
memalloc_noio_restore(noio_flags); \
ret; \
})
#define vdfs4_vmap(...) ({ \
unsigned noio_flags = memalloc_noio_save(); \
void *ret = vmap(__VA_ARGS__); \
int retry = VDFS4_VMEM_RETRY_CNT; \
while (unlikely(!ret) && retry--) { \
VDFS4_WARNING("NoMem(%s():%d, %d):vmap\n", \
__func__, __LINE__, retry); \
msleep(VDFS4_VMEM_RETRY_INTERVAL); \
ret = vmap(__VA_ARGS__); \
} \
memalloc_noio_restore(noio_flags); \
ret; \
})
#define vdfs4_vm_map_ram(...) ({ \
unsigned noio_flags = memalloc_noio_save(); \
void *ret = vm_map_ram(__VA_ARGS__); \
int retry = VDFS4_VMEM_RETRY_CNT; \
while (unlikely(!ret) && retry--) { \
VDFS4_WARNING("NoMem(%s():%d, %d):vm_map\n", \
__func__, __LINE__, retry); \
msleep(VDFS4_VMEM_RETRY_INTERVAL); \
ret = vm_map_ram(__VA_ARGS__); \
} \
memalloc_noio_restore(noio_flags); \
ret; \
})
struct packtrees_list {
/* pack tree multi-access protection */
struct mutex lock_pactree_list;
struct list_head list;
};
/** @brief Maintains private super block information.
*/
struct vdfs4_sb_info {
/** The VFS super block */
struct super_block *sb;
/** The page that contains superblocks */
struct page *superblocks;
/** The page that contains superblocks copy */
struct page *superblocks_copy;
/** The VDFS mapped raw superblock data */
void *raw_superblock;
/** The VDFS mapped raw superblock copy data */
void *raw_superblock_copy;
/** The VDFS mapped meta hashtable for R/O */
void *raw_meta_hashtable;
/** The page that contains debug area (not used)*/
struct page **debug_pages;
/** Mapped debug area (not used)*/
void *debug_area;
/** The eMMCFS flags */
unsigned long flags;
/** Allocated block size in bytes */
unsigned int block_size;
/** Allocated block size shift */
unsigned int block_size_shift;
/** Allocated block size mask for offset */
unsigned int offset_msk_inblock;
/** Size of LEB in blocks */
unsigned int log_blocks_in_leb;
/* log blocks in page */
unsigned int log_blocks_in_page;
/** Log sector per block */
unsigned int log_sectors_per_block;
/** The eMMCFS mount options */
unsigned int mount_options;
/** Volume size in blocks */
unsigned long long volume_blocks_count;
/** The current value of free block count on the whole eMMCFS volume */
unsigned long long free_blocks_count;
/* Reserved for delayed allocations, not in free_blocks_count */
unsigned long long reserved_blocks_count;
/** The files count on the whole eMMCFS volume */
unsigned long long files_count;
/** The folders count on the whole eMMCFS volume */
unsigned long long folders_count;
/** 64-bit uuid for volume */
u64 volume_uuid;
/** How many blocks in the bnode */
unsigned long btree_node_size_blks;
/** Catalog tree in memory */
struct vdfs4_btree *catalog_tree;
/** Maximum value of catalog tree height */
int max_cattree_height;
/** Extents overflow tree */
struct vdfs4_btree *extents_tree;
/** Xattr tree */
struct vdfs4_btree *xattr_tree;
/*Sysfs kobject structure*/
struct kobject s_kobj;
struct completion s_kobj_unregister;
u32 erase_block_size;
u32 erase_block_size_in_blocks;
u8 log_erase_block_size_in_blocks;
u8 log_erase_block_size;
u8 log_block_size;
char umount_time;
time_t mount_time;
atomic_t running_errcnt;
u32 *erase_blocks_counters;
u32 nr_erase_blocks_counters;
/** Free space bitmap information */
struct {
struct inode *inode;
atomic64_t last_used;
} free_inode_bitmap;
/** Free space management */
struct vdfs4_fsm_info *fsm_info;
/** Snapshot manager */
struct vdfs4_snapshot_info *snapshot_info;
/** pending transaction commit */
struct delayed_work delayed_commit;
/* fallback completion for metadata writeback */
wait_queue_head_t meta_bio_wait;
atomic_t meta_bio_count;
/** log flash superpage size */
unsigned int log_super_page_size;
int bugon_count;
/* opened packtree list */
struct packtrees_list packtree_images;
/* decompression type : hardware or software */
int use_hw_decompressor;
struct vdfs4_proc_dir_info *proc_info;
/* new files mode mask, filled if fmask mount option is specifided */
umode_t fmask;
/* new directory mode mask, filled if dmask mount option
* is specifided */
umode_t dmask;
int orig_ro;
/* under catalog_tree->rw_tree_lock */
struct list_head orphan_inodes;
#ifdef VDFS4_DEBUG_DUMP
struct mutex dump_meta;
#endif
#ifdef CONFIG_VDFS4_AUTHENTICATION
rsakey_t *rsa_key;
rsakey_t *rsa_key_legacy;
#endif
enum sign_type sign_type;
#ifdef CONFIG_VDFS4_SQUEEZE_PROFILING
struct file *prof_file;
struct kfifo prof_fifo;
spinlock_t prof_lock;
struct delayed_work prof_task;
#endif
/* For write statistics */
u64 sectors_written_start;
u64 kbytes_written;
#ifdef CONFIG_VDFS4_LOCK_TRACE
struct vdfs4_lock_info lock_info[VDFS4_LOCK_MAX];
#endif
};
/* For write statistics. Suppose sector size is 512 bytes,
* and the return value is in kbytes. s is of struct vdfs_sb_info.
*/
#define BD_PART_WRITTEN(s) \
(((u64)part_stat_read(s->sb->s_bdev->bd_part, sectors[1]) - \
s->sectors_written_start) >> 1)
#ifdef CONFIG_VDFS4_SQUEEZE_PROFILING
struct vdfs4_prof_data {
struct vdfs4_timespec stamp;
__u32 ino;
__u32 block;
__u32 count;
};
#endif
/** @brief Current extent information.
*/
struct vdfs4_extent_info {
/** physical start block of the extent */
u64 first_block;
/** logical start block of the extent */
sector_t iblock;
/** block count in the extent*/
u32 block_count;
};
struct vdfs4_runtime_extent_info {
/** logical start block of the extent */
sector_t iblock;
sector_t alloc_hint;
/** block count in the extent*/
u32 block_count;
struct list_head list;
};
/** @brief Current fork information.
*/
struct vdfs4_fork_info {
/**
* The total number of allocation blocks which are
* allocated for file system object described by this fork */
u32 total_block_count;
/**
* Number of blocks,which are preallocated by free space manager for
* file system object described by this fork */
__u32 prealloc_block_count;
/* Preallocated space first block physical number */
sector_t prealloc_start_block;
/**
* The set of extents which describe file system object's blocks
* placement */
struct vdfs4_extent_info extents[VDFS4_EXTENTS_COUNT_IN_FORK];
/** Used extents */
unsigned int used_extents;
};
/*
* Free space extents are hashed by log2(length) in
* VDFS4_FSM_MAX_ORDER + 1 buckets: 1..2^FSM_MAX_ORDER blocks
*/
#define VDFS4_FSM_MAX_ORDER 16
/*
* Upper limit of tracked free area extents
*/
# define VDFS4_FSM_MAX_FREE_NODES 20480
/** @brief Maintains free space management info.
*/
struct vdfs4_fsm_info {
/* Superblock info structure pointer */
struct vdfs4_sb_info *sbi;
/** Free space start (in blocks)*/
__u32 free_space_start;
/** LEB state bitmap pages */
struct page **pages;
/** TODO */
__u32 page_count;
/** Mapped pages (ptr to LEB bitmap)*/
void *data;
/** Lock for LEBs bitmap */
struct mutex lock;
/** Free space bitmap inode (VFS inode) */
struct inode *bitmap_inode;
/* free extents sorted by start block */
struct rb_root free_area;
/* free extents hashed by log2(length) */
struct list_head free_list[VDFS4_FSM_MAX_ORDER + 1];
/* extents will be freed after commit, sorted by start block */
struct rb_root next_free_area;
/* list of will-be-freed extents */
struct list_head next_free_list;
/* count of extents in free_area tree */
unsigned int free_area_nodes;
/* count of extents in next_free_area tree */
unsigned int next_free_nodes;
/* will be freed after metadata commit */
long long next_free_blocks;
/* free space not present in free_area for some reason */
long long untracked_blocks;
/* next free space not present in next_free_area */
long long untracked_next_free;
};
struct vdfs4_comp_extent_info {
pgoff_t start_block;
int offset;
int len_bytes;
int blocks_n;
__u16 flags;
#ifdef CONFIG_VDFS4_SQUEEZE
__u16 profiled_prio;
#endif
};
enum {
FORCE_NONE = 0,
FORCE_SW,
FORCE_HW,
};
/** @brief Maintains file-based decompression info
*/
struct vdfs4_file_based_info {
/* offset to chunks table */
loff_t comp_table_start_offset;
/* file compressed size */
loff_t comp_size;
/* log chunk size 12 ~ 17 */
size_t log_chunk_size;
/* compressed extents count */
__u32 comp_extents_n;
/* force readpage path (SW/HW) for this file */
int force_path;
/* compression type */
enum compr_type compr_type;
/* hash type */
enum hash_type hash_type;
/* signature type */
enum sign_type sign_type;
/* hash length */
size_t hash_len;
/* decompression function */
int (*decomp_fn)(void *src, void *dst, size_t offset, size_t len_bytes,
size_t chunk_size);
/* authentication function */
int (*hash_fn)(unsigned char *buffer, size_t length, char *hash);
/* hardware decompression / authentication function */
int (*hw_fn)(struct inode *inode, struct page *page);
/* debug auth */
int informed_about_fail_read;
};
#ifdef CONFIG_VDFS4_SQUEEZE
struct vdfs4_squeeze_chunk_info {
__u16 order;
struct list_head list;
};
#endif
/** @brief Maintains private inode info.
*/
struct vdfs4_inode_info {
/** VFS inode */
struct inode vfs_inode;
/* record type */
__u8 record_type;
/** The inode fork information */
struct vdfs4_fork_info fork;
/* file-based decompression info */
struct vdfs4_file_based_info *fbc;
/* runtime fork */
struct list_head runtime_extents;
/** Truncate_mutex is for serializing vdfs4_truncate_blocks() against
* vdfs4_getblock()
*/
struct mutex truncate_mutex;
/** Name information */
char *name;
/** Parent ID */
__u64 parent_id;
/** Inode flags */
unsigned long int flags;
/* for vdfs4_sb_info->orphan_inodes */
struct list_head orphan_list;
__u64 next_orphan_id;
/** difference between file_open() and file_release() calls */
atomic_t open_count;
#ifdef CONFIG_VDFS4_DEBUG_AUTHENTICAION
int informed_about_fail_read;
#endif
#ifdef CONFIG_VDFS4_SQUEEZE
struct list_head to_read_list;
spinlock_t to_read_lock;
struct vdfs4_squeeze_chunk_info *sci;
#endif
#ifdef CONFIG_VDFS4_TRACE
/* size of data that doesn't be written to disk */
unsigned int write_size;
#endif
};
struct vdfs4_snapshot_info {
/** Lock metadata update */
struct mutex insert_lock;
/** Transaction lock */
struct rw_semaphore transaction_lock;
struct rw_semaphore writeback_lock;
/* snapshot tables protections */
struct rw_semaphore tables_lock;
/* current snapshot state : describe current and next snapshot */
unsigned long *snapshot_bitmap;
/* next snapshot state */
unsigned long *next_snapshot_bitmap;
/* moved iblocks bitmap */
unsigned long *moved_iblock;
/* sizeof snapshot_bitmap & next_snapshot_bitmap in bits */
unsigned long bitmap_size_in_bits;
/* last allocation place for btree */
unsigned long int hint_btree;
/* last allocation place for bitmaps */
unsigned long int hint_bitmaps;
/* --------------------- */
/* base table */
struct vdfs4_base_table *base_t;
/* extended table page */
struct vdfs4_extended_table *extended_table;
/* first free block in tables area */
sector_t iblock;
__u32 sync_count;
/* dirty pages ammount */
unsigned int dirty_pages_count;
/* flag - use base table or expand table */
__u8 use_base_table;
__u8 exteneded_table_count;
};
enum snapshot_table_type {
SNAPSHOT_BASE_TABLE,
SNAPSHOT_EXT_TABLE
};
/** @brief struct for writeback function
*
*/
struct vdfs4_mpage_data {
sector_t last_block_in_bio;
struct bio *bio;
};
struct vdfs4_attr {
struct attribute attr;
ssize_t (*show)(struct vdfs4_sb_info *, char *);
ssize_t (*store)(struct vdfs4_sb_info *, const char *, size_t);
};
static inline int is_vdfs4(struct super_block *sb)
{
if (!sb->s_type)
return 0;
if (!sb->s_type->name)
return 0;
if (memcmp(sb->s_type->name, VDFS4_NAME, sizeof(VDFS4_NAME)))
return 0;
else
return 1;
}
/**
* @brief Get eMMCFS inode info structure from
* encapsulated inode.
* @param [in] inode VFS inode
* @return Returns pointer to eMMCFS inode info data structure
*/
static inline struct vdfs4_inode_info *VDFS4_I(struct inode *inode)
{
return container_of(inode, struct vdfs4_inode_info, vfs_inode);
}
/**
* @brief Get eMMCFS superblock from VFS superblock.
* @param [in] sb The VFS superblock
* @return Returns eMMCFS run-time superblock
*/
static inline struct vdfs4_sb_info *VDFS4_SB(struct super_block *sb)
{
return sb->s_fs_info;
}
static inline int vdfs4_produce_err(struct vdfs4_sb_info *sbi)
{
if (sbi->bugon_count <= 0) {
VDFS4_BUG_ON(sbi->bugon_count < 0, sbi);
sbi->bugon_count--;
return -ERANGE;
}
sbi->bugon_count--;
return 0;
}
/**
* @brief save function name and error code to oops area (first 1K of
* a volume).
*/
int vdfs4_log_error(struct vdfs4_sb_info *sbi, unsigned int,
const char *name, int err);
/**
* @brief wrapper : write function name and error code on disk in
* debug area
* @param [in] sbi Printf format string.
* @return void
*/
#define VDFS4_LOG_ERROR(sbi, err) vdfs4_log_error(sbi, __LINE__, __func__, err)
void __printf(4, 5)
vdfs4_fatal_error(struct vdfs4_sb_info *sbi, unsigned int err_type,
unsigned long i_ino, const char *fmt, ...);
void destroy_layout(struct vdfs4_sb_info *sbi);
/**
* @brief Validate fork.
* @param [in] fork Pointer to the fork for validation
* @return Returns 1 if fork is valid, 0 in case of wrong fork
* */
static inline int is_fork_valid(const struct vdfs4_fork *fork,
struct vdfs4_sb_info *sbi)
{
int ext;
if (!fork)
goto ERR;
if (fork->total_blocks_count > sbi->volume_blocks_count) {
VDFS4_ERR("total blks is invalid(%llu)\n",
fork->total_blocks_count);
goto ERR;
}
for (ext = 0; ext < VDFS4_EXTENTS_COUNT_IN_FORK; ext++) {
if ((fork->extents[ext].extent.begin +
fork->extents[ext].extent.length) >
sbi->volume_blocks_count) {
VDFS4_ERR("begin&length is invalid(%llu, %llu)\n",
fork->extents[ext].extent.begin,
fork->extents[ext].extent.length);
goto ERR;
}
}
return 1;
ERR:
VDFS4_ERR("%s(%llu) fork is invalid\n",
sbi->sb->s_id, sbi->volume_blocks_count);
return 0;
}
/**
* @brief Set flag in superblock.
* @param [in] sbi Superblock information
* @param [in] flag Value to be set
* @return void
*/
static inline void set_sbi_flag(struct vdfs4_sb_info *sbi, int flag)
{
set_bit(flag, &sbi->flags);
}
/**
* @brief Check flag in superblock.
* @param [in] sbi Superblock information
* @param [in] flag Flag to be checked
* @return Returns flag value
*/
static inline int is_sbi_flag_set(struct vdfs4_sb_info *sbi, int flag)
{
return test_bit(flag, &sbi->flags);
}
/**
* @brief Clear flag in superblock.
* @param [in] sbi Superblock information
* @param [in] flag Value to be clear
* @return void
*/
static inline void clear_sbi_flag(struct vdfs4_sb_info *sbi, int flag)
{
clear_bit(flag, &sbi->flags);
}
/**
* @brief Set flag in vdfs4 inode info
* @param [in] sbi VFS inode
* @param [in] flag flag to set
* @return Return previous flag value
*/
static inline int set_vdfs4_inode_flag(struct inode *inode, int flag)
{
struct vdfs4_inode_info *inode_info = VDFS4_I(inode);
return test_and_set_bit(flag, &inode_info->flags);
}
static inline struct inode *INODE(struct kiocb *iocb)
{
return iocb->ki_filp->f_path.dentry->d_inode;
}
/**
* @brief Set flag in vdfs4 inode info
* @param [in] sbi VFS inode
* @param [in] flag Flag to be checked
* @return Returns flag value
*/
static inline int is_vdfs4_inode_flag_set(struct inode *inode, int flag)
{
struct vdfs4_inode_info *inode_info = VDFS4_I(inode);
return test_bit(flag, &inode_info->flags);
}
/**
* @brief Clear flag in vdfs4 inode info
* @param [in] sbi VFS inode
* @param [in] flag Flag to be cleared
* @return Returns flag value
*/
static inline int clear_vdfs4_inode_flag(struct inode *inode, int flag)
{
struct vdfs4_inode_info *inode_info = VDFS4_I(inode);
return test_and_clear_bit(flag, &inode_info->flags);
}
/**
* @brief Copy layout fork into run time fork.
* @param [out] rfork Run time fork
* @param [in] lfork Layout fork
* @return void
*/
static inline void vdfs4_lfork_to_rfork(struct vdfs4_fork *lfork,
struct vdfs4_fork_info *rfork)
{
unsigned i;
/* Caller must check fork, call is_fork_valid(struct vdfs4_fork *) */
/* First blanked extent means - no any more valid extents */
rfork->used_extents = 0;
for (i = 0; i < VDFS4_EXTENTS_COUNT_IN_FORK; ++i) {
struct vdfs4_iextent *lextent;
lextent = &lfork->extents[i];
rfork->extents[i].first_block =
le64_to_cpu(lextent->extent.begin);
rfork->extents[i].block_count =
le32_to_cpu(lextent->extent.length);
rfork->extents[i].iblock = le64_to_cpu(lextent->iblock);
if (rfork->extents[i].first_block)
rfork->used_extents++;
}
}
/**
* @brief Get current time for inode.
* @param [in] inode The inode for which current time will be returned
* @return Time value for current inode
*/
static inline struct timespec vdfs4_current_time(struct inode *inode)
{
return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ?
current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
}
static inline int get_sign_length(enum sign_type type)
{
switch (type) {
case VDFS4_SIGN_RSA1024:
return 128;
case VDFS4_SIGN_RSA2048:
return 256;
case VDFS4_SIGN_NONE:
return 0;
default:
return -1;
}
}
#ifdef CONFIG_VDFS4_AUTHENTICATION
static inline rsakey_t *get_rsa_key_by_type(struct vdfs4_sb_info *sbi,
enum sign_type type)
{
switch (type) {
#ifdef CONFIG_VDFS4_ALLOW_LEGACY_SIGN
case VDFS4_SIGN_RSA1024:
return sbi->rsa_key_legacy;
#endif
case VDFS4_SIGN_RSA2048:
return sbi->rsa_key;
default:
return NULL;
}
}
#endif
static inline void *correct_addr_and_bit_unaligned(int *bit, void *addr)
{
#if BITS_PER_LONG == 64
*bit += ((unsigned long) addr & 7UL) << 3;
addr = (void *) ((unsigned long) addr & ~7UL);
#elif BITS_PER_LONG == 32
*bit += ((unsigned long) addr & 3UL) << 3;
addr = (void *) ((unsigned long) addr & ~3UL);
#else
#error "how many bits you are?!"
#endif
return addr;
}
static inline int vdfs4_test_and_set_bit(int bit, void *addr)
{
addr = correct_addr_and_bit_unaligned(&bit, addr);
return test_and_set_bit(bit, addr);
}
static inline int vdfs4_test_and_clear_bit(int bit, void *addr)
{
addr = correct_addr_and_bit_unaligned(&bit, addr);
return test_and_clear_bit(bit, addr);
}
/* super.c */
int vdfs4_sync_fs(struct super_block *sb, int wait);
int vdfs4_sync_exsb(struct vdfs4_sb_info *sbi, int no);
void vdfs4_dirty_super(struct vdfs4_sb_info *sbi);
void vdfs4_init_inode(struct vdfs4_inode_info *inode);
int vdfs4_remount_fs(struct super_block *sb, int *flags, char *data);
/** todo move to btree.c ?
* @brief The eMMCFS B-tree common constructor.
*/
int vdfs4_fill_btree(struct vdfs4_sb_info *sbi,
struct vdfs4_btree *btree, struct inode *inode);
/**