1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
5*6a54128fSAndroid Build Coastguard Worker *
6*6a54128fSAndroid Build Coastguard Worker * %Begin-Header%
7*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the GNU Library
8*6a54128fSAndroid Build Coastguard Worker * General Public License, version 2.
9*6a54128fSAndroid Build Coastguard Worker * %End-Header%
10*6a54128fSAndroid Build Coastguard Worker */
11*6a54128fSAndroid Build Coastguard Worker
12*6a54128fSAndroid Build Coastguard Worker #include "config.h"
13*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
14*6a54128fSAndroid Build Coastguard Worker #include <string.h>
15*6a54128fSAndroid Build Coastguard Worker #if HAVE_UNISTD_H
16*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
17*6a54128fSAndroid Build Coastguard Worker #endif
18*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
19*6a54128fSAndroid Build Coastguard Worker #include <time.h>
20*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_STAT_H
21*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
22*6a54128fSAndroid Build Coastguard Worker #endif
23*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_TYPES_H
24*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
25*6a54128fSAndroid Build Coastguard Worker #endif
26*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD_H
27*6a54128fSAndroid Build Coastguard Worker #include <pthread.h>
28*6a54128fSAndroid Build Coastguard Worker #endif
29*6a54128fSAndroid Build Coastguard Worker
30*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
31*6a54128fSAndroid Build Coastguard Worker #include "ext2fs.h"
32*6a54128fSAndroid Build Coastguard Worker #include "e2image.h"
33*6a54128fSAndroid Build Coastguard Worker
34*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD
35*6a54128fSAndroid Build Coastguard Worker typedef pthread_mutex_t mutex_t;
36*6a54128fSAndroid Build Coastguard Worker
unix_pthread_mutex_lock(mutex_t * mutex)37*6a54128fSAndroid Build Coastguard Worker static void unix_pthread_mutex_lock(mutex_t *mutex)
38*6a54128fSAndroid Build Coastguard Worker {
39*6a54128fSAndroid Build Coastguard Worker if (mutex)
40*6a54128fSAndroid Build Coastguard Worker pthread_mutex_lock(mutex);
41*6a54128fSAndroid Build Coastguard Worker }
unix_pthread_mutex_unlock(mutex_t * mutex)42*6a54128fSAndroid Build Coastguard Worker static void unix_pthread_mutex_unlock(mutex_t *mutex)
43*6a54128fSAndroid Build Coastguard Worker {
44*6a54128fSAndroid Build Coastguard Worker if (mutex)
45*6a54128fSAndroid Build Coastguard Worker pthread_mutex_unlock(mutex);
46*6a54128fSAndroid Build Coastguard Worker }
47*6a54128fSAndroid Build Coastguard Worker #else
48*6a54128fSAndroid Build Coastguard Worker typedef int mutex_t;
49*6a54128fSAndroid Build Coastguard Worker #define unix_pthread_mutex_lock(mutex_t) do {} while (0)
50*6a54128fSAndroid Build Coastguard Worker #define unix_pthread_mutex_unlock(mutex_t) do {} while (0)
51*6a54128fSAndroid Build Coastguard Worker #endif
52*6a54128fSAndroid Build Coastguard Worker
write_bitmaps(ext2_filsys fs,int do_inode,int do_block)53*6a54128fSAndroid Build Coastguard Worker static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
54*6a54128fSAndroid Build Coastguard Worker {
55*6a54128fSAndroid Build Coastguard Worker dgrp_t i;
56*6a54128fSAndroid Build Coastguard Worker unsigned int j;
57*6a54128fSAndroid Build Coastguard Worker int block_nbytes, inode_nbytes;
58*6a54128fSAndroid Build Coastguard Worker unsigned int nbits;
59*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
60*6a54128fSAndroid Build Coastguard Worker char *block_buf = NULL, *inode_buf = NULL;
61*6a54128fSAndroid Build Coastguard Worker int csum_flag;
62*6a54128fSAndroid Build Coastguard Worker blk64_t blk;
63*6a54128fSAndroid Build Coastguard Worker blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
64*6a54128fSAndroid Build Coastguard Worker ext2_ino_t ino_itr = 1;
65*6a54128fSAndroid Build Coastguard Worker
66*6a54128fSAndroid Build Coastguard Worker EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
67*6a54128fSAndroid Build Coastguard Worker
68*6a54128fSAndroid Build Coastguard Worker if (!(fs->flags & EXT2_FLAG_RW))
69*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_RO_FILSYS;
70*6a54128fSAndroid Build Coastguard Worker
71*6a54128fSAndroid Build Coastguard Worker csum_flag = ext2fs_has_group_desc_csum(fs);
72*6a54128fSAndroid Build Coastguard Worker
73*6a54128fSAndroid Build Coastguard Worker inode_nbytes = block_nbytes = 0;
74*6a54128fSAndroid Build Coastguard Worker if (do_block) {
75*6a54128fSAndroid Build Coastguard Worker block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
76*6a54128fSAndroid Build Coastguard Worker retval = io_channel_alloc_buf(fs->io, 0, &block_buf);
77*6a54128fSAndroid Build Coastguard Worker if (retval)
78*6a54128fSAndroid Build Coastguard Worker goto errout;
79*6a54128fSAndroid Build Coastguard Worker memset(block_buf, 0xff, fs->blocksize);
80*6a54128fSAndroid Build Coastguard Worker }
81*6a54128fSAndroid Build Coastguard Worker if (do_inode) {
82*6a54128fSAndroid Build Coastguard Worker inode_nbytes = (size_t)
83*6a54128fSAndroid Build Coastguard Worker ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
84*6a54128fSAndroid Build Coastguard Worker retval = io_channel_alloc_buf(fs->io, 0, &inode_buf);
85*6a54128fSAndroid Build Coastguard Worker if (retval)
86*6a54128fSAndroid Build Coastguard Worker goto errout;
87*6a54128fSAndroid Build Coastguard Worker memset(inode_buf, 0xff, fs->blocksize);
88*6a54128fSAndroid Build Coastguard Worker }
89*6a54128fSAndroid Build Coastguard Worker
90*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < fs->group_desc_count; i++) {
91*6a54128fSAndroid Build Coastguard Worker if (!do_block)
92*6a54128fSAndroid Build Coastguard Worker goto skip_block_bitmap;
93*6a54128fSAndroid Build Coastguard Worker
94*6a54128fSAndroid Build Coastguard Worker if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT)
95*6a54128fSAndroid Build Coastguard Worker )
96*6a54128fSAndroid Build Coastguard Worker goto skip_this_block_bitmap;
97*6a54128fSAndroid Build Coastguard Worker
98*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_block_bitmap_range2(fs->block_map,
99*6a54128fSAndroid Build Coastguard Worker blk_itr, block_nbytes << 3, block_buf);
100*6a54128fSAndroid Build Coastguard Worker if (retval)
101*6a54128fSAndroid Build Coastguard Worker goto errout;
102*6a54128fSAndroid Build Coastguard Worker
103*6a54128fSAndroid Build Coastguard Worker if (i == fs->group_desc_count - 1) {
104*6a54128fSAndroid Build Coastguard Worker /* Force bitmap padding for the last group */
105*6a54128fSAndroid Build Coastguard Worker nbits = EXT2FS_NUM_B2C(fs,
106*6a54128fSAndroid Build Coastguard Worker ((ext2fs_blocks_count(fs->super)
107*6a54128fSAndroid Build Coastguard Worker - (__u64) fs->super->s_first_data_block)
108*6a54128fSAndroid Build Coastguard Worker % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super)));
109*6a54128fSAndroid Build Coastguard Worker if (nbits)
110*6a54128fSAndroid Build Coastguard Worker for (j = nbits; j < fs->blocksize * 8; j++)
111*6a54128fSAndroid Build Coastguard Worker ext2fs_set_bit(j, block_buf);
112*6a54128fSAndroid Build Coastguard Worker }
113*6a54128fSAndroid Build Coastguard Worker
114*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_block_bitmap_csum_set(fs, i, block_buf,
115*6a54128fSAndroid Build Coastguard Worker block_nbytes);
116*6a54128fSAndroid Build Coastguard Worker if (retval)
117*6a54128fSAndroid Build Coastguard Worker return retval;
118*6a54128fSAndroid Build Coastguard Worker ext2fs_group_desc_csum_set(fs, i);
119*6a54128fSAndroid Build Coastguard Worker fs->flags |= EXT2_FLAG_DIRTY;
120*6a54128fSAndroid Build Coastguard Worker
121*6a54128fSAndroid Build Coastguard Worker blk = ext2fs_block_bitmap_loc(fs, i);
122*6a54128fSAndroid Build Coastguard Worker if (blk && blk < ext2fs_blocks_count(fs->super)) {
123*6a54128fSAndroid Build Coastguard Worker retval = io_channel_write_blk64(fs->io, blk, 1,
124*6a54128fSAndroid Build Coastguard Worker block_buf);
125*6a54128fSAndroid Build Coastguard Worker if (retval) {
126*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_BLOCK_BITMAP_WRITE;
127*6a54128fSAndroid Build Coastguard Worker goto errout;
128*6a54128fSAndroid Build Coastguard Worker }
129*6a54128fSAndroid Build Coastguard Worker }
130*6a54128fSAndroid Build Coastguard Worker skip_this_block_bitmap:
131*6a54128fSAndroid Build Coastguard Worker blk_itr += block_nbytes << 3;
132*6a54128fSAndroid Build Coastguard Worker skip_block_bitmap:
133*6a54128fSAndroid Build Coastguard Worker
134*6a54128fSAndroid Build Coastguard Worker if (!do_inode)
135*6a54128fSAndroid Build Coastguard Worker continue;
136*6a54128fSAndroid Build Coastguard Worker
137*6a54128fSAndroid Build Coastguard Worker if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT)
138*6a54128fSAndroid Build Coastguard Worker )
139*6a54128fSAndroid Build Coastguard Worker goto skip_this_inode_bitmap;
140*6a54128fSAndroid Build Coastguard Worker
141*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_inode_bitmap_range2(fs->inode_map,
142*6a54128fSAndroid Build Coastguard Worker ino_itr, inode_nbytes << 3, inode_buf);
143*6a54128fSAndroid Build Coastguard Worker if (retval)
144*6a54128fSAndroid Build Coastguard Worker goto errout;
145*6a54128fSAndroid Build Coastguard Worker
146*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_inode_bitmap_csum_set(fs, i, inode_buf,
147*6a54128fSAndroid Build Coastguard Worker inode_nbytes);
148*6a54128fSAndroid Build Coastguard Worker if (retval)
149*6a54128fSAndroid Build Coastguard Worker goto errout;
150*6a54128fSAndroid Build Coastguard Worker ext2fs_group_desc_csum_set(fs, i);
151*6a54128fSAndroid Build Coastguard Worker fs->flags |= EXT2_FLAG_DIRTY;
152*6a54128fSAndroid Build Coastguard Worker
153*6a54128fSAndroid Build Coastguard Worker blk = ext2fs_inode_bitmap_loc(fs, i);
154*6a54128fSAndroid Build Coastguard Worker if (blk && blk < ext2fs_blocks_count(fs->super)) {
155*6a54128fSAndroid Build Coastguard Worker retval = io_channel_write_blk64(fs->io, blk, 1,
156*6a54128fSAndroid Build Coastguard Worker inode_buf);
157*6a54128fSAndroid Build Coastguard Worker if (retval) {
158*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_INODE_BITMAP_WRITE;
159*6a54128fSAndroid Build Coastguard Worker goto errout;
160*6a54128fSAndroid Build Coastguard Worker }
161*6a54128fSAndroid Build Coastguard Worker }
162*6a54128fSAndroid Build Coastguard Worker skip_this_inode_bitmap:
163*6a54128fSAndroid Build Coastguard Worker ino_itr += inode_nbytes << 3;
164*6a54128fSAndroid Build Coastguard Worker
165*6a54128fSAndroid Build Coastguard Worker }
166*6a54128fSAndroid Build Coastguard Worker if (do_block) {
167*6a54128fSAndroid Build Coastguard Worker fs->flags &= ~EXT2_FLAG_BB_DIRTY;
168*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&block_buf);
169*6a54128fSAndroid Build Coastguard Worker }
170*6a54128fSAndroid Build Coastguard Worker if (do_inode) {
171*6a54128fSAndroid Build Coastguard Worker fs->flags &= ~EXT2_FLAG_IB_DIRTY;
172*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&inode_buf);
173*6a54128fSAndroid Build Coastguard Worker }
174*6a54128fSAndroid Build Coastguard Worker return 0;
175*6a54128fSAndroid Build Coastguard Worker errout:
176*6a54128fSAndroid Build Coastguard Worker if (inode_buf)
177*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&inode_buf);
178*6a54128fSAndroid Build Coastguard Worker if (block_buf)
179*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&block_buf);
180*6a54128fSAndroid Build Coastguard Worker return retval;
181*6a54128fSAndroid Build Coastguard Worker }
182*6a54128fSAndroid Build Coastguard Worker
mark_uninit_bg_group_blocks(ext2_filsys fs)183*6a54128fSAndroid Build Coastguard Worker static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs)
184*6a54128fSAndroid Build Coastguard Worker {
185*6a54128fSAndroid Build Coastguard Worker dgrp_t i;
186*6a54128fSAndroid Build Coastguard Worker blk64_t blk;
187*6a54128fSAndroid Build Coastguard Worker ext2fs_block_bitmap bmap = fs->block_map;
188*6a54128fSAndroid Build Coastguard Worker
189*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < fs->group_desc_count; i++) {
190*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT))
191*6a54128fSAndroid Build Coastguard Worker continue;
192*6a54128fSAndroid Build Coastguard Worker
193*6a54128fSAndroid Build Coastguard Worker ext2fs_reserve_super_and_bgd(fs, i, bmap);
194*6a54128fSAndroid Build Coastguard Worker
195*6a54128fSAndroid Build Coastguard Worker /*
196*6a54128fSAndroid Build Coastguard Worker * Mark the blocks used for the inode table
197*6a54128fSAndroid Build Coastguard Worker */
198*6a54128fSAndroid Build Coastguard Worker blk = ext2fs_inode_table_loc(fs, i);
199*6a54128fSAndroid Build Coastguard Worker if (blk)
200*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_block_bitmap_range2(bmap, blk,
201*6a54128fSAndroid Build Coastguard Worker fs->inode_blocks_per_group);
202*6a54128fSAndroid Build Coastguard Worker
203*6a54128fSAndroid Build Coastguard Worker /*
204*6a54128fSAndroid Build Coastguard Worker * Mark block used for the block bitmap
205*6a54128fSAndroid Build Coastguard Worker */
206*6a54128fSAndroid Build Coastguard Worker blk = ext2fs_block_bitmap_loc(fs, i);
207*6a54128fSAndroid Build Coastguard Worker if (blk && blk < ext2fs_blocks_count(fs->super))
208*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_block_bitmap2(bmap, blk);
209*6a54128fSAndroid Build Coastguard Worker
210*6a54128fSAndroid Build Coastguard Worker /*
211*6a54128fSAndroid Build Coastguard Worker * Mark block used for the inode bitmap
212*6a54128fSAndroid Build Coastguard Worker */
213*6a54128fSAndroid Build Coastguard Worker blk = ext2fs_inode_bitmap_loc(fs, i);
214*6a54128fSAndroid Build Coastguard Worker if (blk && blk < ext2fs_blocks_count(fs->super))
215*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_block_bitmap2(bmap, blk);
216*6a54128fSAndroid Build Coastguard Worker }
217*6a54128fSAndroid Build Coastguard Worker return 0;
218*6a54128fSAndroid Build Coastguard Worker }
219*6a54128fSAndroid Build Coastguard Worker
bitmap_tail_verify(unsigned char * bitmap,int first,int last)220*6a54128fSAndroid Build Coastguard Worker static int bitmap_tail_verify(unsigned char *bitmap, int first, int last)
221*6a54128fSAndroid Build Coastguard Worker {
222*6a54128fSAndroid Build Coastguard Worker int i;
223*6a54128fSAndroid Build Coastguard Worker
224*6a54128fSAndroid Build Coastguard Worker for (i = first; i <= last; i++)
225*6a54128fSAndroid Build Coastguard Worker if (bitmap[i] != 0xff)
226*6a54128fSAndroid Build Coastguard Worker return 0;
227*6a54128fSAndroid Build Coastguard Worker return 1;
228*6a54128fSAndroid Build Coastguard Worker }
229*6a54128fSAndroid Build Coastguard Worker
read_bitmaps_range_prepare(ext2_filsys fs,int flags)230*6a54128fSAndroid Build Coastguard Worker static errcode_t read_bitmaps_range_prepare(ext2_filsys fs, int flags)
231*6a54128fSAndroid Build Coastguard Worker {
232*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
233*6a54128fSAndroid Build Coastguard Worker int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
234*6a54128fSAndroid Build Coastguard Worker int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
235*6a54128fSAndroid Build Coastguard Worker char *buf;
236*6a54128fSAndroid Build Coastguard Worker
237*6a54128fSAndroid Build Coastguard Worker EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
238*6a54128fSAndroid Build Coastguard Worker
239*6a54128fSAndroid Build Coastguard Worker if ((block_nbytes > (int) fs->blocksize) ||
240*6a54128fSAndroid Build Coastguard Worker (inode_nbytes > (int) fs->blocksize))
241*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_CORRUPT_SUPERBLOCK;
242*6a54128fSAndroid Build Coastguard Worker
243*6a54128fSAndroid Build Coastguard Worker fs->write_bitmaps = ext2fs_write_bitmaps;
244*6a54128fSAndroid Build Coastguard Worker
245*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
246*6a54128fSAndroid Build Coastguard Worker if (retval)
247*6a54128fSAndroid Build Coastguard Worker return retval;
248*6a54128fSAndroid Build Coastguard Worker
249*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_BLOCK) {
250*6a54128fSAndroid Build Coastguard Worker if (fs->block_map)
251*6a54128fSAndroid Build Coastguard Worker ext2fs_free_block_bitmap(fs->block_map);
252*6a54128fSAndroid Build Coastguard Worker strcpy(buf, "block bitmap for ");
253*6a54128fSAndroid Build Coastguard Worker strcat(buf, fs->device_name);
254*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
255*6a54128fSAndroid Build Coastguard Worker if (retval)
256*6a54128fSAndroid Build Coastguard Worker goto cleanup;
257*6a54128fSAndroid Build Coastguard Worker }
258*6a54128fSAndroid Build Coastguard Worker
259*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_INODE) {
260*6a54128fSAndroid Build Coastguard Worker if (fs->inode_map)
261*6a54128fSAndroid Build Coastguard Worker ext2fs_free_inode_bitmap(fs->inode_map);
262*6a54128fSAndroid Build Coastguard Worker strcpy(buf, "inode bitmap for ");
263*6a54128fSAndroid Build Coastguard Worker strcat(buf, fs->device_name);
264*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
265*6a54128fSAndroid Build Coastguard Worker if (retval)
266*6a54128fSAndroid Build Coastguard Worker goto cleanup;
267*6a54128fSAndroid Build Coastguard Worker }
268*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&buf);
269*6a54128fSAndroid Build Coastguard Worker return retval;
270*6a54128fSAndroid Build Coastguard Worker
271*6a54128fSAndroid Build Coastguard Worker cleanup:
272*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_BLOCK) {
273*6a54128fSAndroid Build Coastguard Worker ext2fs_free_block_bitmap(fs->block_map);
274*6a54128fSAndroid Build Coastguard Worker fs->block_map = 0;
275*6a54128fSAndroid Build Coastguard Worker }
276*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_INODE) {
277*6a54128fSAndroid Build Coastguard Worker ext2fs_free_inode_bitmap(fs->inode_map);
278*6a54128fSAndroid Build Coastguard Worker fs->inode_map = 0;
279*6a54128fSAndroid Build Coastguard Worker }
280*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&buf);
281*6a54128fSAndroid Build Coastguard Worker return retval;
282*6a54128fSAndroid Build Coastguard Worker }
283*6a54128fSAndroid Build Coastguard Worker
read_bitmaps_range_start(ext2_filsys fs,int flags,dgrp_t start,dgrp_t end,mutex_t * mutex,int * tail_flags)284*6a54128fSAndroid Build Coastguard Worker static errcode_t read_bitmaps_range_start(ext2_filsys fs, int flags,
285*6a54128fSAndroid Build Coastguard Worker dgrp_t start, dgrp_t end,
286*6a54128fSAndroid Build Coastguard Worker mutex_t *mutex,
287*6a54128fSAndroid Build Coastguard Worker int *tail_flags)
288*6a54128fSAndroid Build Coastguard Worker {
289*6a54128fSAndroid Build Coastguard Worker dgrp_t i;
290*6a54128fSAndroid Build Coastguard Worker char *block_bitmap = 0, *inode_bitmap = 0;
291*6a54128fSAndroid Build Coastguard Worker errcode_t retval = 0;
292*6a54128fSAndroid Build Coastguard Worker int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
293*6a54128fSAndroid Build Coastguard Worker int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
294*6a54128fSAndroid Build Coastguard Worker int csum_flag;
295*6a54128fSAndroid Build Coastguard Worker unsigned int cnt;
296*6a54128fSAndroid Build Coastguard Worker blk64_t blk;
297*6a54128fSAndroid Build Coastguard Worker blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
298*6a54128fSAndroid Build Coastguard Worker blk64_t blk_cnt;
299*6a54128fSAndroid Build Coastguard Worker ext2_ino_t ino_itr = 1;
300*6a54128fSAndroid Build Coastguard Worker ext2_ino_t ino_cnt;
301*6a54128fSAndroid Build Coastguard Worker
302*6a54128fSAndroid Build Coastguard Worker csum_flag = ext2fs_has_group_desc_csum(fs);
303*6a54128fSAndroid Build Coastguard Worker
304*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_BLOCK) {
305*6a54128fSAndroid Build Coastguard Worker retval = io_channel_alloc_buf(fs->io, 0, &block_bitmap);
306*6a54128fSAndroid Build Coastguard Worker if (retval)
307*6a54128fSAndroid Build Coastguard Worker goto cleanup;
308*6a54128fSAndroid Build Coastguard Worker } else {
309*6a54128fSAndroid Build Coastguard Worker block_nbytes = 0;
310*6a54128fSAndroid Build Coastguard Worker }
311*6a54128fSAndroid Build Coastguard Worker
312*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_INODE) {
313*6a54128fSAndroid Build Coastguard Worker retval = io_channel_alloc_buf(fs->io, 0, &inode_bitmap);
314*6a54128fSAndroid Build Coastguard Worker if (retval)
315*6a54128fSAndroid Build Coastguard Worker goto cleanup;
316*6a54128fSAndroid Build Coastguard Worker } else {
317*6a54128fSAndroid Build Coastguard Worker inode_nbytes = 0;
318*6a54128fSAndroid Build Coastguard Worker }
319*6a54128fSAndroid Build Coastguard Worker
320*6a54128fSAndroid Build Coastguard Worker /* io should be null */
321*6a54128fSAndroid Build Coastguard Worker if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
322*6a54128fSAndroid Build Coastguard Worker blk = (ext2fs_le32_to_cpu(fs->image_header->offset_inodemap) / fs->blocksize);
323*6a54128fSAndroid Build Coastguard Worker ino_cnt = fs->super->s_inodes_count;
324*6a54128fSAndroid Build Coastguard Worker while (inode_bitmap && ino_cnt > 0) {
325*6a54128fSAndroid Build Coastguard Worker retval = io_channel_read_blk64(fs->image_io, blk++,
326*6a54128fSAndroid Build Coastguard Worker 1, inode_bitmap);
327*6a54128fSAndroid Build Coastguard Worker if (retval)
328*6a54128fSAndroid Build Coastguard Worker goto cleanup;
329*6a54128fSAndroid Build Coastguard Worker cnt = fs->blocksize << 3;
330*6a54128fSAndroid Build Coastguard Worker if (cnt > ino_cnt)
331*6a54128fSAndroid Build Coastguard Worker cnt = ino_cnt;
332*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_set_inode_bitmap_range2(fs->inode_map,
333*6a54128fSAndroid Build Coastguard Worker ino_itr, cnt, inode_bitmap);
334*6a54128fSAndroid Build Coastguard Worker if (retval)
335*6a54128fSAndroid Build Coastguard Worker goto cleanup;
336*6a54128fSAndroid Build Coastguard Worker ino_itr += cnt;
337*6a54128fSAndroid Build Coastguard Worker ino_cnt -= cnt;
338*6a54128fSAndroid Build Coastguard Worker }
339*6a54128fSAndroid Build Coastguard Worker blk = (ext2fs_le32_to_cpu(fs->image_header->offset_blockmap) /
340*6a54128fSAndroid Build Coastguard Worker fs->blocksize);
341*6a54128fSAndroid Build Coastguard Worker blk_cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super,
342*6a54128fSAndroid Build Coastguard Worker fs->group_desc_count);
343*6a54128fSAndroid Build Coastguard Worker while (block_bitmap && blk_cnt > 0) {
344*6a54128fSAndroid Build Coastguard Worker retval = io_channel_read_blk64(fs->image_io, blk++,
345*6a54128fSAndroid Build Coastguard Worker 1, block_bitmap);
346*6a54128fSAndroid Build Coastguard Worker if (retval)
347*6a54128fSAndroid Build Coastguard Worker goto cleanup;
348*6a54128fSAndroid Build Coastguard Worker cnt = fs->blocksize << 3;
349*6a54128fSAndroid Build Coastguard Worker if (cnt > blk_cnt)
350*6a54128fSAndroid Build Coastguard Worker cnt = blk_cnt;
351*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_set_block_bitmap_range2(fs->block_map,
352*6a54128fSAndroid Build Coastguard Worker blk_itr, cnt, block_bitmap);
353*6a54128fSAndroid Build Coastguard Worker if (retval)
354*6a54128fSAndroid Build Coastguard Worker goto cleanup;
355*6a54128fSAndroid Build Coastguard Worker blk_itr += cnt;
356*6a54128fSAndroid Build Coastguard Worker blk_cnt -= cnt;
357*6a54128fSAndroid Build Coastguard Worker }
358*6a54128fSAndroid Build Coastguard Worker goto cleanup;
359*6a54128fSAndroid Build Coastguard Worker }
360*6a54128fSAndroid Build Coastguard Worker
361*6a54128fSAndroid Build Coastguard Worker blk_itr += ((blk64_t)start * (block_nbytes << 3));
362*6a54128fSAndroid Build Coastguard Worker ino_itr += ((blk64_t)start * (inode_nbytes << 3));
363*6a54128fSAndroid Build Coastguard Worker for (i = start; i <= end; i++) {
364*6a54128fSAndroid Build Coastguard Worker if (block_bitmap) {
365*6a54128fSAndroid Build Coastguard Worker blk = ext2fs_block_bitmap_loc(fs, i);
366*6a54128fSAndroid Build Coastguard Worker if ((csum_flag &&
367*6a54128fSAndroid Build Coastguard Worker ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) &&
368*6a54128fSAndroid Build Coastguard Worker ext2fs_group_desc_csum_verify(fs, i)) ||
369*6a54128fSAndroid Build Coastguard Worker (blk >= ext2fs_blocks_count(fs->super)))
370*6a54128fSAndroid Build Coastguard Worker blk = 0;
371*6a54128fSAndroid Build Coastguard Worker if (blk) {
372*6a54128fSAndroid Build Coastguard Worker retval = io_channel_read_blk64(fs->io, blk,
373*6a54128fSAndroid Build Coastguard Worker 1, block_bitmap);
374*6a54128fSAndroid Build Coastguard Worker if (retval) {
375*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_BLOCK_BITMAP_READ;
376*6a54128fSAndroid Build Coastguard Worker goto cleanup;
377*6a54128fSAndroid Build Coastguard Worker }
378*6a54128fSAndroid Build Coastguard Worker /* verify block bitmap checksum */
379*6a54128fSAndroid Build Coastguard Worker if (!(fs->flags &
380*6a54128fSAndroid Build Coastguard Worker EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
381*6a54128fSAndroid Build Coastguard Worker !ext2fs_block_bitmap_csum_verify(fs, i,
382*6a54128fSAndroid Build Coastguard Worker block_bitmap, block_nbytes)) {
383*6a54128fSAndroid Build Coastguard Worker retval =
384*6a54128fSAndroid Build Coastguard Worker EXT2_ET_BLOCK_BITMAP_CSUM_INVALID;
385*6a54128fSAndroid Build Coastguard Worker goto cleanup;
386*6a54128fSAndroid Build Coastguard Worker }
387*6a54128fSAndroid Build Coastguard Worker if (!bitmap_tail_verify((unsigned char *) block_bitmap,
388*6a54128fSAndroid Build Coastguard Worker block_nbytes, fs->blocksize - 1))
389*6a54128fSAndroid Build Coastguard Worker *tail_flags |= EXT2_FLAG_BBITMAP_TAIL_PROBLEM;
390*6a54128fSAndroid Build Coastguard Worker } else
391*6a54128fSAndroid Build Coastguard Worker memset(block_bitmap, 0, block_nbytes);
392*6a54128fSAndroid Build Coastguard Worker cnt = block_nbytes << 3;
393*6a54128fSAndroid Build Coastguard Worker unix_pthread_mutex_lock(mutex);
394*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_set_block_bitmap_range2(fs->block_map,
395*6a54128fSAndroid Build Coastguard Worker blk_itr, cnt, block_bitmap);
396*6a54128fSAndroid Build Coastguard Worker unix_pthread_mutex_unlock(mutex);
397*6a54128fSAndroid Build Coastguard Worker if (retval)
398*6a54128fSAndroid Build Coastguard Worker goto cleanup;
399*6a54128fSAndroid Build Coastguard Worker blk_itr += block_nbytes << 3;
400*6a54128fSAndroid Build Coastguard Worker }
401*6a54128fSAndroid Build Coastguard Worker if (inode_bitmap) {
402*6a54128fSAndroid Build Coastguard Worker blk = ext2fs_inode_bitmap_loc(fs, i);
403*6a54128fSAndroid Build Coastguard Worker if ((csum_flag &&
404*6a54128fSAndroid Build Coastguard Worker ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) &&
405*6a54128fSAndroid Build Coastguard Worker ext2fs_group_desc_csum_verify(fs, i)) ||
406*6a54128fSAndroid Build Coastguard Worker (blk >= ext2fs_blocks_count(fs->super)))
407*6a54128fSAndroid Build Coastguard Worker blk = 0;
408*6a54128fSAndroid Build Coastguard Worker if (blk) {
409*6a54128fSAndroid Build Coastguard Worker retval = io_channel_read_blk64(fs->io, blk,
410*6a54128fSAndroid Build Coastguard Worker 1, inode_bitmap);
411*6a54128fSAndroid Build Coastguard Worker if (retval) {
412*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_INODE_BITMAP_READ;
413*6a54128fSAndroid Build Coastguard Worker goto cleanup;
414*6a54128fSAndroid Build Coastguard Worker }
415*6a54128fSAndroid Build Coastguard Worker
416*6a54128fSAndroid Build Coastguard Worker /* verify inode bitmap checksum */
417*6a54128fSAndroid Build Coastguard Worker if (!(fs->flags &
418*6a54128fSAndroid Build Coastguard Worker EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
419*6a54128fSAndroid Build Coastguard Worker !ext2fs_inode_bitmap_csum_verify(fs, i,
420*6a54128fSAndroid Build Coastguard Worker inode_bitmap, inode_nbytes)) {
421*6a54128fSAndroid Build Coastguard Worker retval =
422*6a54128fSAndroid Build Coastguard Worker EXT2_ET_INODE_BITMAP_CSUM_INVALID;
423*6a54128fSAndroid Build Coastguard Worker goto cleanup;
424*6a54128fSAndroid Build Coastguard Worker }
425*6a54128fSAndroid Build Coastguard Worker if (!bitmap_tail_verify((unsigned char *) inode_bitmap,
426*6a54128fSAndroid Build Coastguard Worker inode_nbytes, fs->blocksize - 1))
427*6a54128fSAndroid Build Coastguard Worker *tail_flags |= EXT2_FLAG_IBITMAP_TAIL_PROBLEM;
428*6a54128fSAndroid Build Coastguard Worker } else
429*6a54128fSAndroid Build Coastguard Worker memset(inode_bitmap, 0, inode_nbytes);
430*6a54128fSAndroid Build Coastguard Worker cnt = inode_nbytes << 3;
431*6a54128fSAndroid Build Coastguard Worker unix_pthread_mutex_lock(mutex);
432*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_set_inode_bitmap_range2(fs->inode_map,
433*6a54128fSAndroid Build Coastguard Worker ino_itr, cnt, inode_bitmap);
434*6a54128fSAndroid Build Coastguard Worker unix_pthread_mutex_unlock(mutex);
435*6a54128fSAndroid Build Coastguard Worker if (retval)
436*6a54128fSAndroid Build Coastguard Worker goto cleanup;
437*6a54128fSAndroid Build Coastguard Worker ino_itr += inode_nbytes << 3;
438*6a54128fSAndroid Build Coastguard Worker }
439*6a54128fSAndroid Build Coastguard Worker }
440*6a54128fSAndroid Build Coastguard Worker
441*6a54128fSAndroid Build Coastguard Worker cleanup:
442*6a54128fSAndroid Build Coastguard Worker if (inode_bitmap)
443*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&inode_bitmap);
444*6a54128fSAndroid Build Coastguard Worker if (block_bitmap)
445*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&block_bitmap);
446*6a54128fSAndroid Build Coastguard Worker return retval;
447*6a54128fSAndroid Build Coastguard Worker }
448*6a54128fSAndroid Build Coastguard Worker
read_bitmaps_range_end(ext2_filsys fs,int flags,int tail_flags)449*6a54128fSAndroid Build Coastguard Worker static errcode_t read_bitmaps_range_end(ext2_filsys fs, int flags,
450*6a54128fSAndroid Build Coastguard Worker int tail_flags)
451*6a54128fSAndroid Build Coastguard Worker {
452*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
453*6a54128fSAndroid Build Coastguard Worker
454*6a54128fSAndroid Build Coastguard Worker /* Mark group blocks for any BLOCK_UNINIT groups */
455*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_BLOCK) {
456*6a54128fSAndroid Build Coastguard Worker retval = mark_uninit_bg_group_blocks(fs);
457*6a54128fSAndroid Build Coastguard Worker if (retval)
458*6a54128fSAndroid Build Coastguard Worker return retval;
459*6a54128fSAndroid Build Coastguard Worker fs->flags &= ~EXT2_FLAG_BBITMAP_TAIL_PROBLEM;
460*6a54128fSAndroid Build Coastguard Worker }
461*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_INODE)
462*6a54128fSAndroid Build Coastguard Worker fs->flags &= ~EXT2_FLAG_IBITMAP_TAIL_PROBLEM;
463*6a54128fSAndroid Build Coastguard Worker fs->flags |= tail_flags;
464*6a54128fSAndroid Build Coastguard Worker
465*6a54128fSAndroid Build Coastguard Worker return 0;
466*6a54128fSAndroid Build Coastguard Worker }
467*6a54128fSAndroid Build Coastguard Worker
read_bitmaps_cleanup_on_error(ext2_filsys fs,int flags)468*6a54128fSAndroid Build Coastguard Worker static void read_bitmaps_cleanup_on_error(ext2_filsys fs, int flags)
469*6a54128fSAndroid Build Coastguard Worker {
470*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_BLOCK) {
471*6a54128fSAndroid Build Coastguard Worker ext2fs_free_block_bitmap(fs->block_map);
472*6a54128fSAndroid Build Coastguard Worker fs->block_map = 0;
473*6a54128fSAndroid Build Coastguard Worker }
474*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_INODE) {
475*6a54128fSAndroid Build Coastguard Worker ext2fs_free_inode_bitmap(fs->inode_map);
476*6a54128fSAndroid Build Coastguard Worker fs->inode_map = 0;
477*6a54128fSAndroid Build Coastguard Worker }
478*6a54128fSAndroid Build Coastguard Worker }
479*6a54128fSAndroid Build Coastguard Worker
read_bitmaps_range(ext2_filsys fs,int flags,dgrp_t start,dgrp_t end)480*6a54128fSAndroid Build Coastguard Worker static errcode_t read_bitmaps_range(ext2_filsys fs, int flags,
481*6a54128fSAndroid Build Coastguard Worker dgrp_t start, dgrp_t end)
482*6a54128fSAndroid Build Coastguard Worker {
483*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
484*6a54128fSAndroid Build Coastguard Worker int tail_flags = 0;
485*6a54128fSAndroid Build Coastguard Worker
486*6a54128fSAndroid Build Coastguard Worker retval = read_bitmaps_range_prepare(fs, flags);
487*6a54128fSAndroid Build Coastguard Worker if (retval)
488*6a54128fSAndroid Build Coastguard Worker return retval;
489*6a54128fSAndroid Build Coastguard Worker
490*6a54128fSAndroid Build Coastguard Worker retval = read_bitmaps_range_start(fs, flags, start, end,
491*6a54128fSAndroid Build Coastguard Worker NULL, &tail_flags);
492*6a54128fSAndroid Build Coastguard Worker if (retval == 0)
493*6a54128fSAndroid Build Coastguard Worker retval = read_bitmaps_range_end(fs, flags, tail_flags);
494*6a54128fSAndroid Build Coastguard Worker if (retval)
495*6a54128fSAndroid Build Coastguard Worker read_bitmaps_cleanup_on_error(fs, flags);
496*6a54128fSAndroid Build Coastguard Worker return retval;
497*6a54128fSAndroid Build Coastguard Worker }
498*6a54128fSAndroid Build Coastguard Worker
499*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD
500*6a54128fSAndroid Build Coastguard Worker struct read_bitmaps_thread_info {
501*6a54128fSAndroid Build Coastguard Worker ext2_filsys rbt_fs;
502*6a54128fSAndroid Build Coastguard Worker int rbt_flags;
503*6a54128fSAndroid Build Coastguard Worker dgrp_t rbt_grp_start;
504*6a54128fSAndroid Build Coastguard Worker dgrp_t rbt_grp_end;
505*6a54128fSAndroid Build Coastguard Worker errcode_t rbt_retval;
506*6a54128fSAndroid Build Coastguard Worker pthread_mutex_t *rbt_mutex;
507*6a54128fSAndroid Build Coastguard Worker int rbt_tail_flags;
508*6a54128fSAndroid Build Coastguard Worker };
509*6a54128fSAndroid Build Coastguard Worker
read_bitmaps_thread(void * data)510*6a54128fSAndroid Build Coastguard Worker static void *read_bitmaps_thread(void *data)
511*6a54128fSAndroid Build Coastguard Worker {
512*6a54128fSAndroid Build Coastguard Worker struct read_bitmaps_thread_info *rbt = data;
513*6a54128fSAndroid Build Coastguard Worker
514*6a54128fSAndroid Build Coastguard Worker rbt->rbt_retval = read_bitmaps_range_start(rbt->rbt_fs, rbt->rbt_flags,
515*6a54128fSAndroid Build Coastguard Worker rbt->rbt_grp_start, rbt->rbt_grp_end,
516*6a54128fSAndroid Build Coastguard Worker rbt->rbt_mutex, &rbt->rbt_tail_flags);
517*6a54128fSAndroid Build Coastguard Worker return NULL;
518*6a54128fSAndroid Build Coastguard Worker }
519*6a54128fSAndroid Build Coastguard Worker #endif
520*6a54128fSAndroid Build Coastguard Worker
ext2fs_rw_bitmaps(ext2_filsys fs,int flags,int num_threads)521*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_rw_bitmaps(ext2_filsys fs, int flags, int num_threads)
522*6a54128fSAndroid Build Coastguard Worker {
523*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD
524*6a54128fSAndroid Build Coastguard Worker pthread_attr_t attr;
525*6a54128fSAndroid Build Coastguard Worker pthread_t *thread_ids = NULL;
526*6a54128fSAndroid Build Coastguard Worker struct read_bitmaps_thread_info *thread_infos = NULL;
527*6a54128fSAndroid Build Coastguard Worker pthread_mutex_t rbt_mutex = PTHREAD_MUTEX_INITIALIZER;
528*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
529*6a54128fSAndroid Build Coastguard Worker errcode_t rc;
530*6a54128fSAndroid Build Coastguard Worker unsigned flexbg_size = 1U << fs->super->s_log_groups_per_flex;
531*6a54128fSAndroid Build Coastguard Worker dgrp_t average_group;
532*6a54128fSAndroid Build Coastguard Worker int i, tail_flags = 0;
533*6a54128fSAndroid Build Coastguard Worker #endif
534*6a54128fSAndroid Build Coastguard Worker
535*6a54128fSAndroid Build Coastguard Worker if (flags & ~EXT2FS_BITMAPS_VALID_FLAGS)
536*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_INVALID_ARGUMENT;
537*6a54128fSAndroid Build Coastguard Worker
538*6a54128fSAndroid Build Coastguard Worker if (ext2fs_has_feature_journal_dev(fs->super))
539*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP;
540*6a54128fSAndroid Build Coastguard Worker
541*6a54128fSAndroid Build Coastguard Worker if (flags & EXT2FS_BITMAPS_WRITE)
542*6a54128fSAndroid Build Coastguard Worker return write_bitmaps(fs, flags & EXT2FS_BITMAPS_INODE,
543*6a54128fSAndroid Build Coastguard Worker flags & EXT2FS_BITMAPS_BLOCK);
544*6a54128fSAndroid Build Coastguard Worker
545*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD
546*6a54128fSAndroid Build Coastguard Worker if (((fs->io->flags & CHANNEL_FLAGS_THREADS) == 0) ||
547*6a54128fSAndroid Build Coastguard Worker (num_threads == 1) || (fs->flags & EXT2_FLAG_IMAGE_FILE))
548*6a54128fSAndroid Build Coastguard Worker goto fallback;
549*6a54128fSAndroid Build Coastguard Worker
550*6a54128fSAndroid Build Coastguard Worker #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
551*6a54128fSAndroid Build Coastguard Worker if (num_threads < 0)
552*6a54128fSAndroid Build Coastguard Worker num_threads = sysconf(_SC_NPROCESSORS_CONF);
553*6a54128fSAndroid Build Coastguard Worker #endif
554*6a54128fSAndroid Build Coastguard Worker /*
555*6a54128fSAndroid Build Coastguard Worker * Guess for now; eventually we should probably define
556*6a54128fSAndroid Build Coastguard Worker * ext2fs_get_num_cpus() and teach it how to get this info on
557*6a54128fSAndroid Build Coastguard Worker * MacOS, FreeBSD, etc.
558*6a54128fSAndroid Build Coastguard Worker * ref: https://stackoverflow.com/questions/150355
559*6a54128fSAndroid Build Coastguard Worker */
560*6a54128fSAndroid Build Coastguard Worker if (num_threads < 0)
561*6a54128fSAndroid Build Coastguard Worker num_threads = 4;
562*6a54128fSAndroid Build Coastguard Worker
563*6a54128fSAndroid Build Coastguard Worker if ((unsigned) num_threads > fs->group_desc_count)
564*6a54128fSAndroid Build Coastguard Worker num_threads = fs->group_desc_count;
565*6a54128fSAndroid Build Coastguard Worker average_group = fs->group_desc_count / num_threads;
566*6a54128fSAndroid Build Coastguard Worker if (ext2fs_has_feature_flex_bg(fs->super)) {
567*6a54128fSAndroid Build Coastguard Worker average_group = (average_group / flexbg_size) * flexbg_size;
568*6a54128fSAndroid Build Coastguard Worker }
569*6a54128fSAndroid Build Coastguard Worker if ((num_threads <= 1) || (average_group == 0))
570*6a54128fSAndroid Build Coastguard Worker goto fallback;
571*6a54128fSAndroid Build Coastguard Worker
572*6a54128fSAndroid Build Coastguard Worker io_channel_set_options(fs->io, "cache=off");
573*6a54128fSAndroid Build Coastguard Worker retval = pthread_attr_init(&attr);
574*6a54128fSAndroid Build Coastguard Worker if (retval)
575*6a54128fSAndroid Build Coastguard Worker return retval;
576*6a54128fSAndroid Build Coastguard Worker
577*6a54128fSAndroid Build Coastguard Worker thread_ids = calloc(sizeof(pthread_t), num_threads);
578*6a54128fSAndroid Build Coastguard Worker if (!thread_ids)
579*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
580*6a54128fSAndroid Build Coastguard Worker
581*6a54128fSAndroid Build Coastguard Worker thread_infos = calloc(sizeof(struct read_bitmaps_thread_info),
582*6a54128fSAndroid Build Coastguard Worker num_threads);
583*6a54128fSAndroid Build Coastguard Worker if (!thread_infos)
584*6a54128fSAndroid Build Coastguard Worker goto out;
585*6a54128fSAndroid Build Coastguard Worker
586*6a54128fSAndroid Build Coastguard Worker retval = read_bitmaps_range_prepare(fs, flags);
587*6a54128fSAndroid Build Coastguard Worker if (retval)
588*6a54128fSAndroid Build Coastguard Worker goto out;
589*6a54128fSAndroid Build Coastguard Worker
590*6a54128fSAndroid Build Coastguard Worker // fprintf(stdout, "Multiple threads triggered to read bitmaps\n");
591*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < num_threads; i++) {
592*6a54128fSAndroid Build Coastguard Worker thread_infos[i].rbt_fs = fs;
593*6a54128fSAndroid Build Coastguard Worker thread_infos[i].rbt_flags = flags;
594*6a54128fSAndroid Build Coastguard Worker thread_infos[i].rbt_mutex = &rbt_mutex;
595*6a54128fSAndroid Build Coastguard Worker thread_infos[i].rbt_tail_flags = 0;
596*6a54128fSAndroid Build Coastguard Worker if (i == 0)
597*6a54128fSAndroid Build Coastguard Worker thread_infos[i].rbt_grp_start = 0;
598*6a54128fSAndroid Build Coastguard Worker else
599*6a54128fSAndroid Build Coastguard Worker thread_infos[i].rbt_grp_start = average_group * i + 1;
600*6a54128fSAndroid Build Coastguard Worker
601*6a54128fSAndroid Build Coastguard Worker if (i == num_threads - 1)
602*6a54128fSAndroid Build Coastguard Worker thread_infos[i].rbt_grp_end = fs->group_desc_count - 1;
603*6a54128fSAndroid Build Coastguard Worker else
604*6a54128fSAndroid Build Coastguard Worker thread_infos[i].rbt_grp_end = average_group * (i + 1);
605*6a54128fSAndroid Build Coastguard Worker retval = pthread_create(&thread_ids[i], &attr,
606*6a54128fSAndroid Build Coastguard Worker &read_bitmaps_thread, &thread_infos[i]);
607*6a54128fSAndroid Build Coastguard Worker if (retval)
608*6a54128fSAndroid Build Coastguard Worker break;
609*6a54128fSAndroid Build Coastguard Worker }
610*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < num_threads; i++) {
611*6a54128fSAndroid Build Coastguard Worker if (!thread_ids[i])
612*6a54128fSAndroid Build Coastguard Worker break;
613*6a54128fSAndroid Build Coastguard Worker rc = pthread_join(thread_ids[i], NULL);
614*6a54128fSAndroid Build Coastguard Worker if (rc && !retval)
615*6a54128fSAndroid Build Coastguard Worker retval = rc;
616*6a54128fSAndroid Build Coastguard Worker rc = thread_infos[i].rbt_retval;
617*6a54128fSAndroid Build Coastguard Worker if (rc && !retval)
618*6a54128fSAndroid Build Coastguard Worker retval = rc;
619*6a54128fSAndroid Build Coastguard Worker tail_flags |= thread_infos[i].rbt_tail_flags;
620*6a54128fSAndroid Build Coastguard Worker }
621*6a54128fSAndroid Build Coastguard Worker out:
622*6a54128fSAndroid Build Coastguard Worker rc = pthread_attr_destroy(&attr);
623*6a54128fSAndroid Build Coastguard Worker if (rc && !retval)
624*6a54128fSAndroid Build Coastguard Worker retval = rc;
625*6a54128fSAndroid Build Coastguard Worker free(thread_infos);
626*6a54128fSAndroid Build Coastguard Worker free(thread_ids);
627*6a54128fSAndroid Build Coastguard Worker
628*6a54128fSAndroid Build Coastguard Worker if (retval == 0)
629*6a54128fSAndroid Build Coastguard Worker retval = read_bitmaps_range_end(fs, flags, tail_flags);
630*6a54128fSAndroid Build Coastguard Worker if (retval)
631*6a54128fSAndroid Build Coastguard Worker read_bitmaps_cleanup_on_error(fs, flags);
632*6a54128fSAndroid Build Coastguard Worker /* XXX should save and restore cache setting */
633*6a54128fSAndroid Build Coastguard Worker io_channel_set_options(fs->io, "cache=on");
634*6a54128fSAndroid Build Coastguard Worker return retval;
635*6a54128fSAndroid Build Coastguard Worker fallback:
636*6a54128fSAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD */
637*6a54128fSAndroid Build Coastguard Worker return read_bitmaps_range(fs, flags, 0, fs->group_desc_count - 1);
638*6a54128fSAndroid Build Coastguard Worker }
639*6a54128fSAndroid Build Coastguard Worker
ext2fs_read_inode_bitmap(ext2_filsys fs)640*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs)
641*6a54128fSAndroid Build Coastguard Worker {
642*6a54128fSAndroid Build Coastguard Worker return ext2fs_rw_bitmaps(fs, EXT2FS_BITMAPS_INODE, -1);
643*6a54128fSAndroid Build Coastguard Worker }
644*6a54128fSAndroid Build Coastguard Worker
ext2fs_read_block_bitmap(ext2_filsys fs)645*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
646*6a54128fSAndroid Build Coastguard Worker {
647*6a54128fSAndroid Build Coastguard Worker return ext2fs_rw_bitmaps(fs, EXT2FS_BITMAPS_BLOCK, -1);
648*6a54128fSAndroid Build Coastguard Worker }
649*6a54128fSAndroid Build Coastguard Worker
ext2fs_write_inode_bitmap(ext2_filsys fs)650*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
651*6a54128fSAndroid Build Coastguard Worker {
652*6a54128fSAndroid Build Coastguard Worker return write_bitmaps(fs, 1, 0);
653*6a54128fSAndroid Build Coastguard Worker }
654*6a54128fSAndroid Build Coastguard Worker
ext2fs_write_block_bitmap(ext2_filsys fs)655*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
656*6a54128fSAndroid Build Coastguard Worker {
657*6a54128fSAndroid Build Coastguard Worker return write_bitmaps(fs, 0, 1);
658*6a54128fSAndroid Build Coastguard Worker }
659*6a54128fSAndroid Build Coastguard Worker
ext2fs_read_bitmaps(ext2_filsys fs)660*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
661*6a54128fSAndroid Build Coastguard Worker {
662*6a54128fSAndroid Build Coastguard Worker int flags = 0;
663*6a54128fSAndroid Build Coastguard Worker
664*6a54128fSAndroid Build Coastguard Worker if (!fs->inode_map)
665*6a54128fSAndroid Build Coastguard Worker flags |= EXT2FS_BITMAPS_INODE;
666*6a54128fSAndroid Build Coastguard Worker if (!fs->block_map)
667*6a54128fSAndroid Build Coastguard Worker flags |= EXT2FS_BITMAPS_BLOCK;
668*6a54128fSAndroid Build Coastguard Worker if (flags == 0)
669*6a54128fSAndroid Build Coastguard Worker return 0;
670*6a54128fSAndroid Build Coastguard Worker return ext2fs_rw_bitmaps(fs, flags, -1);
671*6a54128fSAndroid Build Coastguard Worker }
672*6a54128fSAndroid Build Coastguard Worker
ext2fs_write_bitmaps(ext2_filsys fs)673*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
674*6a54128fSAndroid Build Coastguard Worker {
675*6a54128fSAndroid Build Coastguard Worker int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs);
676*6a54128fSAndroid Build Coastguard Worker int do_block = fs->block_map && ext2fs_test_bb_dirty(fs);
677*6a54128fSAndroid Build Coastguard Worker
678*6a54128fSAndroid Build Coastguard Worker if (!do_inode && !do_block)
679*6a54128fSAndroid Build Coastguard Worker return 0;
680*6a54128fSAndroid Build Coastguard Worker
681*6a54128fSAndroid Build Coastguard Worker return write_bitmaps(fs, do_inode, do_block);
682*6a54128fSAndroid Build Coastguard Worker }
683