2 * linux/fs/affs/bitmap.c
4 * (c) 1996 Hans-Joachim Widmaier
6 * bitmap.c contains the code that handles all bitmap related stuff -
7 * block allocation, deallocation, calculation of free space.
11 #include <linux/sched.h>
12 #include <linux/affs_fs.h>
13 #include <linux/stat.h>
14 #include <linux/kernel.h>
15 #include <linux/string.h>
16 #include <linux/locks.h>
17 #include <linux/amigaffs.h>
19 #include <asm/bitops.h>
21 /* This is, of course, shamelessly stolen from fs/minix */
23 static int nibblemap
[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
26 affs_count_free_bits(int blocksize
, const char *data
)
32 for (i
= 0; i
< blocksize
; i
++) {
33 free
+= nibblemap
[data
[i
] & 0xF] + nibblemap
[(data
[i
]>>4) & 0xF];
40 affs_count_free_blocks(struct super_block
*s
)
45 pr_debug("AFFS: count_free_blocks()\n");
48 if (s
->u
.affs_sb
.s_flags
& SF_BM_VALID
) {
49 for (i
= 0; i
< s
->u
.affs_sb
.s_num_az
; i
++) {
50 free
+= s
->u
.affs_sb
.s_alloc
[i
].az_free
;
57 affs_free_block(struct super_block
*sb
, s32 block
)
63 struct affs_bm_info
*bm
;
65 pr_debug("AFFS: free_block(%d)\n",block
);
67 blk
= block
- sb
->u
.affs_sb
.s_reserved
;
68 bmap
= blk
/ (sb
->s_blocksize
* 8 - 32);
69 bit
= blk
% (sb
->s_blocksize
* 8 - 32);
70 zone_no
= (bmap
<< (sb
->s_blocksize_bits
- 7)) + bit
/ 1024;
71 bm
= &sb
->u
.affs_sb
.s_bitmap
[bmap
];
72 if (bmap
>= sb
->u
.affs_sb
.s_bm_count
) {
73 affs_error(sb
,"affs_free_block","Block %d outside partition",block
);
77 set_bit(bit
& 31,&blk
);
82 bm
->bm_bh
= affs_bread(sb
->s_dev
,bm
->bm_key
,sb
->s_blocksize
);
86 affs_error(sb
,"affs_free_block","Cannot read bitmap block %d",bm
->bm_key
);
90 if (test_and_set_bit(bit
^ BO_EXBITS
,bm
->bm_bh
->b_data
+ 4))
91 affs_warning(sb
,"affs_free_block","Trying to free block %d which is already free",
94 sb
->u
.affs_sb
.s_alloc
[zone_no
].az_free
++;
95 ((u32
*)bm
->bm_bh
->b_data
)[0] = cpu_to_be32(be32_to_cpu(((u32
*)bm
->bm_bh
->b_data
)[0]) - blk
);
96 mark_buffer_dirty(bm
->bm_bh
);
99 if (--bm
->bm_count
== 0) {
100 affs_brelse(bm
->bm_bh
);
107 * Allocate a block in the given allocation zone.
108 * Since we have to byte-swap the bitmap on little-endian
109 * machines, this is rather expensive. Therefor we will
110 * preallocate up to 16 blocks from the same word, if
111 * possible. We are not doing preallocations in the
112 * header zone, though.
116 affs_balloc(struct inode
*inode
, int zone_no
)
124 struct affs_zone
*zone
;
125 struct affs_alloc_zone
*az
;
126 struct super_block
*sb
;
129 zone
= &sb
->u
.affs_sb
.s_zones
[zone_no
];
131 if (!zone
->z_bm
|| !zone
->z_bm
->bm_bh
)
134 pr_debug("AFFS: balloc(inode=%lu,zone=%d)\n",inode
->i_ino
,zone_no
);
136 az
= &sb
->u
.affs_sb
.s_alloc
[zone
->z_az_no
];
137 bm
= (u32
*)zone
->z_bm
->bm_bh
->b_data
;
139 for (i
= zone
->z_start
; i
< zone
->z_end
; i
++) {
146 fwb
= zone
->z_bm
->bm_firstblk
+ (i
- 1) * 32;
149 w
= ~be32_to_cpu(bm
[i
]);
150 fb
= find_first_zero_bit(&w
,32);
151 if (fb
> 31 || !test_and_clear_bit(fb
^ BO_EXBITS
,&bm
[i
])) {
153 affs_warning(sb
,"balloc","Empty block disappeared somehow");
159 /* prealloc as much as possible within this word, but not in header zone */
162 while (inode
->u
.affs_i
.i_pa_cnt
< AFFS_MAX_PREALLOC
&& ++fb
< 32) {
163 fb
= find_next_zero_bit(&w
,32,fb
);
166 if (!test_and_clear_bit(fb
^ BO_EXBITS
,&bm
[i
])) {
167 affs_warning(sb
,"balloc","Empty block disappeared somehow");
170 inode
->u
.affs_i
.i_data
[inode
->u
.affs_i
.i_pa_last
++] = fwb
+ fb
;
171 inode
->u
.affs_i
.i_pa_last
&= AFFS_MAX_PREALLOC
- 1;
172 inode
->u
.affs_i
.i_pa_cnt
++;
176 w
= ~w
- be32_to_cpu(bm
[i
]);
177 bm
[0] = cpu_to_be32(be32_to_cpu(bm
[0]) + w
);
179 mark_buffer_dirty(zone
->z_bm
->bm_bh
);
181 zone
->z_lru_time
= jiffies
;
186 /* Find a new allocation zone, starting at zone_no. */
189 affs_find_new_zone(struct super_block
*sb
, int zone_no
)
191 struct affs_bm_info
*bm
;
192 struct affs_zone
*zone
;
193 struct affs_alloc_zone
*az
;
201 pr_debug("AFFS: find_new_zone(zone_no=%d)\n",zone_no
);
207 min
= zone_no
? AFFS_DATA_MIN_FREE
: AFFS_HDR_MIN_FREE
;
209 zone
= &sb
->u
.affs_sb
.s_zones
[zone_no
];
211 az
= &sb
->u
.affs_sb
.s_alloc
[i
];
212 if (zone
->z_bm
&& zone
->z_bm
->bm_count
) {
213 if (--zone
->z_bm
->bm_count
== 0) {
214 affs_brelse(zone
->z_bm
->bm_bh
);
215 zone
->z_bm
->bm_bh
= NULL
;
220 affs_error(sb
,"find_new_zone","az_count=0, but bm used");
224 az
= &sb
->u
.affs_sb
.s_alloc
[i
];
226 if (az
->az_free
> min
) {
229 if (az
->az_free
> bestfree
) {
230 bestfree
= az
->az_free
;
233 } else if (az
->az_free
&& az
->az_count
< lusers
) {
234 lusers
= az
->az_count
;
237 if (++i
>= sb
->u
.affs_sb
.s_num_az
)
239 if (i
== zone
->z_az_no
) { /* Seen all */
249 /* Didn't find a single free block anywhere. */
253 az
= &sb
->u
.affs_sb
.s_alloc
[i
];
255 bm
= &sb
->u
.affs_sb
.s_bitmap
[i
>> (sb
->s_blocksize_bits
- 7)];
258 bm
->bm_bh
= affs_bread(sb
->s_dev
,bm
->bm_key
,sb
->s_blocksize
);
263 affs_error(sb
,"find_new_zone","Cannot read bitmap");
267 zone
->z_start
= (i
& ((sb
->s_blocksize
/ 128) - 1)) * 32 + 1;
268 zone
->z_end
= zone
->z_start
+ az
->az_size
;
270 zone
->z_lru_time
= jiffies
;
271 pr_debug("AFFS: found zone (%d) in bm %d at lw offset %d with %d free blocks\n",
272 i
,(i
>> (sb
->s_blocksize_bits
- 7)),zone
->z_start
,az
->az_free
);
277 /* Allocate a new header block. */
280 affs_new_header(struct inode
*inode
)
284 pr_debug("AFFS: new_header(ino=%lu)\n",inode
->i_ino
);
286 if (!(block
= affs_balloc(inode
,0))) {
287 while (affs_find_new_zone(inode
->i_sb
,0)) {
288 if ((block
= affs_balloc(inode
,0)))
297 /* Allocate a new data block. */
300 affs_new_data(struct inode
*inode
)
303 unsigned long oldest
;
304 struct affs_zone
*zone
;
305 struct super_block
*sb
;
309 pr_debug("AFFS: new_data(ino=%lu)\n",inode
->i_ino
);
313 if (inode
->u
.affs_i
.i_pa_cnt
) {
314 inode
->u
.affs_i
.i_pa_cnt
--;
316 block
= inode
->u
.affs_i
.i_data
[inode
->u
.affs_i
.i_pa_next
++];
317 inode
->u
.affs_i
.i_pa_next
&= AFFS_MAX_PREALLOC
- 1;
324 zone
= &sb
->u
.affs_sb
.s_zones
[inode
->u
.affs_i
.i_zone
];
325 if (zone
->z_ino
== inode
->i_ino
) {
326 i
= inode
->u
.affs_i
.i_zone
;
329 for (i
= 1; i
< MAX_ZONES
; i
++) {
330 zone
= &sb
->u
.affs_sb
.s_zones
[i
];
331 if (!empty
&& zone
->z_bm
&& !zone
->z_ino
)
333 if (zone
->z_bm
&& zone
->z_lru_time
< oldest
) {
335 oldest
= zone
->z_lru_time
;
343 inode
->u
.affs_i
.i_zone
= 0;
344 return affs_new_header(inode
);
347 inode
->u
.affs_i
.i_zone
= i
;
348 zone
->z_ino
= inode
->i_ino
;
351 zone
= &sb
->u
.affs_sb
.s_zones
[i
];
352 if (!(block
= affs_balloc(inode
,i
))) { /* No data zones left */
353 while (affs_find_new_zone(sb
,i
)) {
354 if ((block
= affs_balloc(inode
,i
)))
358 inode
->u
.affs_i
.i_zone
= 0;
366 affs_make_zones(struct super_block
*sb
)
370 pr_debug("AFFS: make_zones(): num_zones=%d\n",sb
->u
.affs_sb
.s_num_az
);
372 mid
= (sb
->u
.affs_sb
.s_num_az
+ 1) / 2;
373 for (i
= 0; i
< MAX_ZONES
; i
++) {
374 sb
->u
.affs_sb
.s_zones
[i
].z_az_no
= mid
;
375 affs_find_new_zone(sb
,i
);