xref: /openbmc/linux/fs/udf/balloc.c (revision 5ce34554)
1*5ce34554SBagas Sanjaya // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * balloc.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * PURPOSE
61da177e4SLinus Torvalds  *	Block allocation handling routines for the OSTA-UDF(tm) filesystem.
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * COPYRIGHT
91da177e4SLinus Torvalds  *  (C) 1999-2001 Ben Fennema
101da177e4SLinus Torvalds  *  (C) 1999 Stelias Computing Inc
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  * HISTORY
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  02/24/99 blf  Created.
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  */
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds #include "udfdecl.h"
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds #include <linux/bitops.h>
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds #include "udf_i.h"
231da177e4SLinus Torvalds #include "udf_sb.h"
241da177e4SLinus Torvalds 
259ad1e1e4SAkinobu Mita #define udf_clear_bit	__test_and_clear_bit_le
269ad1e1e4SAkinobu Mita #define udf_set_bit	__test_and_set_bit_le
279ad1e1e4SAkinobu Mita #define udf_test_bit	test_bit_le
289ad1e1e4SAkinobu Mita #define udf_find_next_one_bit	find_next_bit_le
291da177e4SLinus Torvalds 
read_block_bitmap(struct super_block * sb,struct udf_bitmap * bitmap,unsigned int block,unsigned long bitmap_nr)301da177e4SLinus Torvalds static int read_block_bitmap(struct super_block *sb,
31cb00ea35SCyrill Gorcunov 			     struct udf_bitmap *bitmap, unsigned int block,
32cb00ea35SCyrill Gorcunov 			     unsigned long bitmap_nr)
331da177e4SLinus Torvalds {
341da177e4SLinus Torvalds 	struct buffer_head *bh = NULL;
351e0d4adfSVladislav Efanov 	int i;
361e0d4adfSVladislav Efanov 	int max_bits, off, count;
375ca4e4beSPekka Enberg 	struct kernel_lb_addr loc;
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds 	loc.logicalBlockNum = bitmap->s_extPosition;
406c79e987SMarcin Slusarz 	loc.partitionReferenceNum = UDF_SB(sb)->s_partition;
411da177e4SLinus Torvalds 
42101ee137SJan Kara 	bh = sb_bread(sb, udf_get_lb_pblock(sb, &loc, block));
431da177e4SLinus Torvalds 	bitmap->s_block_bitmap[bitmap_nr] = bh;
441e0d4adfSVladislav Efanov 	if (!bh)
451e0d4adfSVladislav Efanov 		return -EIO;
461e0d4adfSVladislav Efanov 
471e0d4adfSVladislav Efanov 	/* Check consistency of Space Bitmap buffer. */
481e0d4adfSVladislav Efanov 	max_bits = sb->s_blocksize * 8;
491e0d4adfSVladislav Efanov 	if (!bitmap_nr) {
501e0d4adfSVladislav Efanov 		off = sizeof(struct spaceBitmapDesc) << 3;
511e0d4adfSVladislav Efanov 		count = min(max_bits - off, bitmap->s_nr_groups);
521e0d4adfSVladislav Efanov 	} else {
531e0d4adfSVladislav Efanov 		/*
541e0d4adfSVladislav Efanov 		 * Rough check if bitmap number is too big to have any bitmap
551e0d4adfSVladislav Efanov  		 * blocks reserved.
561e0d4adfSVladislav Efanov 		 */
571e0d4adfSVladislav Efanov 		if (bitmap_nr >
581e0d4adfSVladislav Efanov 		    (bitmap->s_nr_groups >> (sb->s_blocksize_bits + 3)) + 2)
591e0d4adfSVladislav Efanov 			return 0;
601e0d4adfSVladislav Efanov 		off = 0;
611e0d4adfSVladislav Efanov 		count = bitmap->s_nr_groups - bitmap_nr * max_bits +
621e0d4adfSVladislav Efanov 				(sizeof(struct spaceBitmapDesc) << 3);
631e0d4adfSVladislav Efanov 		count = min(count, max_bits);
641e0d4adfSVladislav Efanov 	}
651e0d4adfSVladislav Efanov 
661e0d4adfSVladislav Efanov 	for (i = 0; i < count; i++)
671e0d4adfSVladislav Efanov 		if (udf_test_bit(i + off, bh->b_data))
681e0d4adfSVladislav Efanov 			return -EFSCORRUPTED;
691e0d4adfSVladislav Efanov 	return 0;
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds 
__load_block_bitmap(struct super_block * sb,struct udf_bitmap * bitmap,unsigned int block_group)721da177e4SLinus Torvalds static int __load_block_bitmap(struct super_block *sb,
73cb00ea35SCyrill Gorcunov 			       struct udf_bitmap *bitmap,
74cb00ea35SCyrill Gorcunov 			       unsigned int block_group)
751da177e4SLinus Torvalds {
761da177e4SLinus Torvalds 	int retval = 0;
771da177e4SLinus Torvalds 	int nr_groups = bitmap->s_nr_groups;
781da177e4SLinus Torvalds 
79cb00ea35SCyrill Gorcunov 	if (block_group >= nr_groups) {
80fcbf7637SSteve Magnani 		udf_debug("block_group (%u) > nr_groups (%d)\n",
81a983f368SJoe Perches 			  block_group, nr_groups);
821da177e4SLinus Torvalds 	}
831da177e4SLinus Torvalds 
846fbaad87SFabian Frederick 	if (bitmap->s_block_bitmap[block_group])
851da177e4SLinus Torvalds 		return block_group;
866fbaad87SFabian Frederick 
876fbaad87SFabian Frederick 	retval = read_block_bitmap(sb, bitmap, block_group, block_group);
881da177e4SLinus Torvalds 	if (retval < 0)
891da177e4SLinus Torvalds 		return retval;
906fbaad87SFabian Frederick 
911da177e4SLinus Torvalds 	return block_group;
921da177e4SLinus Torvalds }
931da177e4SLinus Torvalds 
load_block_bitmap(struct super_block * sb,struct udf_bitmap * bitmap,unsigned int block_group)941da177e4SLinus Torvalds static inline int load_block_bitmap(struct super_block *sb,
95cb00ea35SCyrill Gorcunov 				    struct udf_bitmap *bitmap,
96cb00ea35SCyrill Gorcunov 				    unsigned int block_group)
971da177e4SLinus Torvalds {
981da177e4SLinus Torvalds 	int slot;
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds 	slot = __load_block_bitmap(sb, bitmap, block_group);
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds 	if (slot < 0)
1031da177e4SLinus Torvalds 		return slot;
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds 	if (!bitmap->s_block_bitmap[slot])
1061da177e4SLinus Torvalds 		return -EIO;
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds 	return slot;
1091da177e4SLinus Torvalds }
1101da177e4SLinus Torvalds 
udf_add_free_space(struct super_block * sb,u16 partition,u32 cnt)111146bca72SJan Kara static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt)
112742ba02aSMarcin Slusarz {
113146bca72SJan Kara 	struct udf_sb_info *sbi = UDF_SB(sb);
114742ba02aSMarcin Slusarz 	struct logicalVolIntegrityDesc *lvid;
115742ba02aSMarcin Slusarz 
116146bca72SJan Kara 	if (!sbi->s_lvid_bh)
117146bca72SJan Kara 		return;
118742ba02aSMarcin Slusarz 
119742ba02aSMarcin Slusarz 	lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
120c2104fdaSmarcin.slusarz@gmail.com 	le32_add_cpu(&lvid->freeSpaceTable[partition], cnt);
121146bca72SJan Kara 	udf_updated_lvid(sb);
122742ba02aSMarcin Slusarz }
123742ba02aSMarcin Slusarz 
udf_bitmap_free_blocks(struct super_block * sb,struct udf_bitmap * bitmap,struct kernel_lb_addr * bloc,uint32_t offset,uint32_t count)1241da177e4SLinus Torvalds static void udf_bitmap_free_blocks(struct super_block *sb,
1251da177e4SLinus Torvalds 				   struct udf_bitmap *bitmap,
12697e961fdSPekka Enberg 				   struct kernel_lb_addr *bloc,
12797e961fdSPekka Enberg 				   uint32_t offset,
128cb00ea35SCyrill Gorcunov 				   uint32_t count)
1291da177e4SLinus Torvalds {
1301da177e4SLinus Torvalds 	struct udf_sb_info *sbi = UDF_SB(sb);
1311da177e4SLinus Torvalds 	struct buffer_head *bh = NULL;
13297e961fdSPekka Enberg 	struct udf_part_map *partmap;
1331da177e4SLinus Torvalds 	unsigned long block;
1341da177e4SLinus Torvalds 	unsigned long block_group;
1351da177e4SLinus Torvalds 	unsigned long bit;
1361da177e4SLinus Torvalds 	unsigned long i;
1371da177e4SLinus Torvalds 	int bitmap_nr;
1381da177e4SLinus Torvalds 	unsigned long overflow;
1391da177e4SLinus Torvalds 
1401e7933deSIngo Molnar 	mutex_lock(&sbi->s_alloc_mutex);
14197e961fdSPekka Enberg 	partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
14269ecbbedSDan Carpenter 	if (bloc->logicalBlockNum + count < count ||
14369ecbbedSDan Carpenter 	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
144fcbf7637SSteve Magnani 		udf_debug("%u < %d || %u + %u > %u\n",
145a983f368SJoe Perches 			  bloc->logicalBlockNum, 0,
146a983f368SJoe Perches 			  bloc->logicalBlockNum, count,
147a983f368SJoe Perches 			  partmap->s_partition_len);
1481da177e4SLinus Torvalds 		goto error_return;
1491da177e4SLinus Torvalds 	}
1501da177e4SLinus Torvalds 
15197e961fdSPekka Enberg 	block = bloc->logicalBlockNum + offset +
1524b11111aSMarcin Slusarz 		(sizeof(struct spaceBitmapDesc) << 3);
1531da177e4SLinus Torvalds 
1544daa1b87SMarcin Slusarz 	do {
1551da177e4SLinus Torvalds 		overflow = 0;
1561da177e4SLinus Torvalds 		block_group = block >> (sb->s_blocksize_bits + 3);
1571da177e4SLinus Torvalds 		bit = block % (sb->s_blocksize << 3);
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds 		/*
1601da177e4SLinus Torvalds 		* Check to see if we are freeing blocks across a group boundary.
1611da177e4SLinus Torvalds 		*/
162cb00ea35SCyrill Gorcunov 		if (bit + count > (sb->s_blocksize << 3)) {
1631da177e4SLinus Torvalds 			overflow = bit + count - (sb->s_blocksize << 3);
1641da177e4SLinus Torvalds 			count -= overflow;
1651da177e4SLinus Torvalds 		}
1661da177e4SLinus Torvalds 		bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
1671da177e4SLinus Torvalds 		if (bitmap_nr < 0)
1681da177e4SLinus Torvalds 			goto error_return;
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds 		bh = bitmap->s_block_bitmap[bitmap_nr];
171cb00ea35SCyrill Gorcunov 		for (i = 0; i < count; i++) {
172cb00ea35SCyrill Gorcunov 			if (udf_set_bit(bit + i, bh->b_data)) {
173fcbf7637SSteve Magnani 				udf_debug("bit %lu already set\n", bit + i);
1744b11111aSMarcin Slusarz 				udf_debug("byte=%2x\n",
175fcbf7637SSteve Magnani 					  ((__u8 *)bh->b_data)[(bit + i) >> 3]);
1761da177e4SLinus Torvalds 			}
1771da177e4SLinus Torvalds 		}
1787abc2e45SJan Kara 		udf_add_free_space(sb, sbi->s_partition, count);
1791da177e4SLinus Torvalds 		mark_buffer_dirty(bh);
180cb00ea35SCyrill Gorcunov 		if (overflow) {
1811da177e4SLinus Torvalds 			block += count;
1821da177e4SLinus Torvalds 			count = overflow;
1831da177e4SLinus Torvalds 		}
1844daa1b87SMarcin Slusarz 	} while (overflow);
1854daa1b87SMarcin Slusarz 
1861da177e4SLinus Torvalds error_return:
1871e7933deSIngo Molnar 	mutex_unlock(&sbi->s_alloc_mutex);
1881da177e4SLinus Torvalds }
1891da177e4SLinus Torvalds 
udf_bitmap_prealloc_blocks(struct super_block * sb,struct udf_bitmap * bitmap,uint16_t partition,uint32_t first_block,uint32_t block_count)1901da177e4SLinus Torvalds static int udf_bitmap_prealloc_blocks(struct super_block *sb,
191cb00ea35SCyrill Gorcunov 				      struct udf_bitmap *bitmap,
192cb00ea35SCyrill Gorcunov 				      uint16_t partition, uint32_t first_block,
1931da177e4SLinus Torvalds 				      uint32_t block_count)
1941da177e4SLinus Torvalds {
1951da177e4SLinus Torvalds 	struct udf_sb_info *sbi = UDF_SB(sb);
1961da177e4SLinus Torvalds 	int alloc_count = 0;
197849fe89cSColin Ian King 	int bit, block, block_group;
198849fe89cSColin Ian King 	int bitmap_nr;
1991da177e4SLinus Torvalds 	struct buffer_head *bh;
2006c79e987SMarcin Slusarz 	__u32 part_len;
2011da177e4SLinus Torvalds 
2021e7933deSIngo Molnar 	mutex_lock(&sbi->s_alloc_mutex);
2036c79e987SMarcin Slusarz 	part_len = sbi->s_partmaps[partition].s_partition_len;
2043391faa4SRoel Kluin 	if (first_block >= part_len)
2051da177e4SLinus Torvalds 		goto out;
2061da177e4SLinus Torvalds 
2076c79e987SMarcin Slusarz 	if (first_block + block_count > part_len)
2086c79e987SMarcin Slusarz 		block_count = part_len - first_block;
2091da177e4SLinus Torvalds 
2104daa1b87SMarcin Slusarz 	do {
2111da177e4SLinus Torvalds 		block = first_block + (sizeof(struct spaceBitmapDesc) << 3);
2121da177e4SLinus Torvalds 		block_group = block >> (sb->s_blocksize_bits + 3);
2131da177e4SLinus Torvalds 
2141da177e4SLinus Torvalds 		bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
2151da177e4SLinus Torvalds 		if (bitmap_nr < 0)
2161da177e4SLinus Torvalds 			goto out;
2171da177e4SLinus Torvalds 		bh = bitmap->s_block_bitmap[bitmap_nr];
2181da177e4SLinus Torvalds 
2191da177e4SLinus Torvalds 		bit = block % (sb->s_blocksize << 3);
2201da177e4SLinus Torvalds 
221cb00ea35SCyrill Gorcunov 		while (bit < (sb->s_blocksize << 3) && block_count > 0) {
22236350462SJan Kara 			if (!udf_clear_bit(bit, bh->b_data))
2231da177e4SLinus Torvalds 				goto out;
2241da177e4SLinus Torvalds 			block_count--;
2251da177e4SLinus Torvalds 			alloc_count++;
2261da177e4SLinus Torvalds 			bit++;
2271da177e4SLinus Torvalds 			block++;
2281da177e4SLinus Torvalds 		}
2291da177e4SLinus Torvalds 		mark_buffer_dirty(bh);
2304daa1b87SMarcin Slusarz 	} while (block_count > 0);
2314daa1b87SMarcin Slusarz 
2321da177e4SLinus Torvalds out:
233146bca72SJan Kara 	udf_add_free_space(sb, partition, -alloc_count);
2341e7933deSIngo Molnar 	mutex_unlock(&sbi->s_alloc_mutex);
2351da177e4SLinus Torvalds 	return alloc_count;
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds 
udf_bitmap_new_block(struct super_block * sb,struct udf_bitmap * bitmap,uint16_t partition,uint32_t goal,int * err)238b490bdd6SSteve Magnani static udf_pblk_t udf_bitmap_new_block(struct super_block *sb,
239cb00ea35SCyrill Gorcunov 				struct udf_bitmap *bitmap, uint16_t partition,
240cb00ea35SCyrill Gorcunov 				uint32_t goal, int *err)
2411da177e4SLinus Torvalds {
2421da177e4SLinus Torvalds 	struct udf_sb_info *sbi = UDF_SB(sb);
243b490bdd6SSteve Magnani 	int newbit, bit = 0;
244b490bdd6SSteve Magnani 	udf_pblk_t block;
245b490bdd6SSteve Magnani 	int block_group, group_start;
2461da177e4SLinus Torvalds 	int end_goal, nr_groups, bitmap_nr, i;
2471da177e4SLinus Torvalds 	struct buffer_head *bh = NULL;
2481da177e4SLinus Torvalds 	char *ptr;
249b490bdd6SSteve Magnani 	udf_pblk_t newblock = 0;
2501da177e4SLinus Torvalds 
2511da177e4SLinus Torvalds 	*err = -ENOSPC;
2521e7933deSIngo Molnar 	mutex_lock(&sbi->s_alloc_mutex);
2531da177e4SLinus Torvalds 
2541da177e4SLinus Torvalds repeat:
2553391faa4SRoel Kluin 	if (goal >= sbi->s_partmaps[partition].s_partition_len)
2561da177e4SLinus Torvalds 		goal = 0;
2571da177e4SLinus Torvalds 
2581da177e4SLinus Torvalds 	nr_groups = bitmap->s_nr_groups;
2591da177e4SLinus Torvalds 	block = goal + (sizeof(struct spaceBitmapDesc) << 3);
2601da177e4SLinus Torvalds 	block_group = block >> (sb->s_blocksize_bits + 3);
2611da177e4SLinus Torvalds 	group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc);
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
2641da177e4SLinus Torvalds 	if (bitmap_nr < 0)
2651da177e4SLinus Torvalds 		goto error_return;
2661da177e4SLinus Torvalds 	bh = bitmap->s_block_bitmap[bitmap_nr];
26728de7948SCyrill Gorcunov 	ptr = memscan((char *)bh->b_data + group_start, 0xFF,
268cb00ea35SCyrill Gorcunov 		      sb->s_blocksize - group_start);
2691da177e4SLinus Torvalds 
270cb00ea35SCyrill Gorcunov 	if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) {
2711da177e4SLinus Torvalds 		bit = block % (sb->s_blocksize << 3);
27228de7948SCyrill Gorcunov 		if (udf_test_bit(bit, bh->b_data))
2731da177e4SLinus Torvalds 			goto got_block;
27428de7948SCyrill Gorcunov 
2751da177e4SLinus Torvalds 		end_goal = (bit + 63) & ~63;
2761da177e4SLinus Torvalds 		bit = udf_find_next_one_bit(bh->b_data, end_goal, bit);
2771da177e4SLinus Torvalds 		if (bit < end_goal)
2781da177e4SLinus Torvalds 			goto got_block;
27928de7948SCyrill Gorcunov 
2804b11111aSMarcin Slusarz 		ptr = memscan((char *)bh->b_data + (bit >> 3), 0xFF,
2814b11111aSMarcin Slusarz 			      sb->s_blocksize - ((bit + 7) >> 3));
2821da177e4SLinus Torvalds 		newbit = (ptr - ((char *)bh->b_data)) << 3;
283cb00ea35SCyrill Gorcunov 		if (newbit < sb->s_blocksize << 3) {
2841da177e4SLinus Torvalds 			bit = newbit;
2851da177e4SLinus Torvalds 			goto search_back;
2861da177e4SLinus Torvalds 		}
28728de7948SCyrill Gorcunov 
2884b11111aSMarcin Slusarz 		newbit = udf_find_next_one_bit(bh->b_data,
2894b11111aSMarcin Slusarz 					       sb->s_blocksize << 3, bit);
290cb00ea35SCyrill Gorcunov 		if (newbit < sb->s_blocksize << 3) {
2911da177e4SLinus Torvalds 			bit = newbit;
2921da177e4SLinus Torvalds 			goto got_block;
2931da177e4SLinus Torvalds 		}
2941da177e4SLinus Torvalds 	}
2951da177e4SLinus Torvalds 
296cb00ea35SCyrill Gorcunov 	for (i = 0; i < (nr_groups * 2); i++) {
2971da177e4SLinus Torvalds 		block_group++;
2981da177e4SLinus Torvalds 		if (block_group >= nr_groups)
2991da177e4SLinus Torvalds 			block_group = 0;
3001da177e4SLinus Torvalds 		group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc);
3011da177e4SLinus Torvalds 
3021da177e4SLinus Torvalds 		bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
3031da177e4SLinus Torvalds 		if (bitmap_nr < 0)
3041da177e4SLinus Torvalds 			goto error_return;
3051da177e4SLinus Torvalds 		bh = bitmap->s_block_bitmap[bitmap_nr];
306cb00ea35SCyrill Gorcunov 		if (i < nr_groups) {
30728de7948SCyrill Gorcunov 			ptr = memscan((char *)bh->b_data + group_start, 0xFF,
308cb00ea35SCyrill Gorcunov 				      sb->s_blocksize - group_start);
309cb00ea35SCyrill Gorcunov 			if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) {
3101da177e4SLinus Torvalds 				bit = (ptr - ((char *)bh->b_data)) << 3;
3111da177e4SLinus Torvalds 				break;
3121da177e4SLinus Torvalds 			}
313cb00ea35SCyrill Gorcunov 		} else {
3146f644e5fSDirk Behme 			bit = udf_find_next_one_bit(bh->b_data,
315cb00ea35SCyrill Gorcunov 						    sb->s_blocksize << 3,
316cb00ea35SCyrill Gorcunov 						    group_start << 3);
3171da177e4SLinus Torvalds 			if (bit < sb->s_blocksize << 3)
3181da177e4SLinus Torvalds 				break;
3191da177e4SLinus Torvalds 		}
3201da177e4SLinus Torvalds 	}
321cb00ea35SCyrill Gorcunov 	if (i >= (nr_groups * 2)) {
3221e7933deSIngo Molnar 		mutex_unlock(&sbi->s_alloc_mutex);
3231da177e4SLinus Torvalds 		return newblock;
3241da177e4SLinus Torvalds 	}
3251da177e4SLinus Torvalds 	if (bit < sb->s_blocksize << 3)
3261da177e4SLinus Torvalds 		goto search_back;
3271da177e4SLinus Torvalds 	else
3284b11111aSMarcin Slusarz 		bit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3,
3294b11111aSMarcin Slusarz 					    group_start << 3);
330cb00ea35SCyrill Gorcunov 	if (bit >= sb->s_blocksize << 3) {
3311e7933deSIngo Molnar 		mutex_unlock(&sbi->s_alloc_mutex);
3321da177e4SLinus Torvalds 		return 0;
3331da177e4SLinus Torvalds 	}
3341da177e4SLinus Torvalds 
3351da177e4SLinus Torvalds search_back:
3364b11111aSMarcin Slusarz 	i = 0;
3374b11111aSMarcin Slusarz 	while (i < 7 && bit > (group_start << 3) &&
3384b11111aSMarcin Slusarz 	       udf_test_bit(bit - 1, bh->b_data)) {
3394b11111aSMarcin Slusarz 		++i;
3404b11111aSMarcin Slusarz 		--bit;
3414b11111aSMarcin Slusarz 	}
3421da177e4SLinus Torvalds 
3431da177e4SLinus Torvalds got_block:
3441da177e4SLinus Torvalds 	newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) -
3451da177e4SLinus Torvalds 		(sizeof(struct spaceBitmapDesc) << 3);
3461da177e4SLinus Torvalds 
34756db1991SSteve Magnani 	if (newblock >= sbi->s_partmaps[partition].s_partition_len) {
34856db1991SSteve Magnani 		/*
34956db1991SSteve Magnani 		 * Ran off the end of the bitmap, and bits following are
35056db1991SSteve Magnani 		 * non-compliant (not all zero)
35156db1991SSteve Magnani 		 */
35256db1991SSteve Magnani 		udf_err(sb, "bitmap for partition %d corrupted (block %u marked"
35356db1991SSteve Magnani 			" as free, partition length is %u)\n", partition,
35456db1991SSteve Magnani 			newblock, sbi->s_partmaps[partition].s_partition_len);
35556db1991SSteve Magnani 		goto error_return;
35656db1991SSteve Magnani 	}
35756db1991SSteve Magnani 
358cb00ea35SCyrill Gorcunov 	if (!udf_clear_bit(bit, bh->b_data)) {
3591da177e4SLinus Torvalds 		udf_debug("bit already cleared for block %d\n", bit);
3601da177e4SLinus Torvalds 		goto repeat;
3611da177e4SLinus Torvalds 	}
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds 	mark_buffer_dirty(bh);
3641da177e4SLinus Torvalds 
365146bca72SJan Kara 	udf_add_free_space(sb, partition, -1);
3661e7933deSIngo Molnar 	mutex_unlock(&sbi->s_alloc_mutex);
3671da177e4SLinus Torvalds 	*err = 0;
3681da177e4SLinus Torvalds 	return newblock;
3691da177e4SLinus Torvalds 
3701da177e4SLinus Torvalds error_return:
3711da177e4SLinus Torvalds 	*err = -EIO;
3721e7933deSIngo Molnar 	mutex_unlock(&sbi->s_alloc_mutex);
3731da177e4SLinus Torvalds 	return 0;
3741da177e4SLinus Torvalds }
3751da177e4SLinus Torvalds 
udf_table_free_blocks(struct super_block * sb,struct inode * table,struct kernel_lb_addr * bloc,uint32_t offset,uint32_t count)3761da177e4SLinus Torvalds static void udf_table_free_blocks(struct super_block *sb,
3771da177e4SLinus Torvalds 				  struct inode *table,
37897e961fdSPekka Enberg 				  struct kernel_lb_addr *bloc,
37997e961fdSPekka Enberg 				  uint32_t offset,
380cb00ea35SCyrill Gorcunov 				  uint32_t count)
3811da177e4SLinus Torvalds {
3821da177e4SLinus Torvalds 	struct udf_sb_info *sbi = UDF_SB(sb);
38397e961fdSPekka Enberg 	struct udf_part_map *partmap;
3841da177e4SLinus Torvalds 	uint32_t start, end;
385ff116fc8SJan Kara 	uint32_t elen;
3865ca4e4beSPekka Enberg 	struct kernel_lb_addr eloc;
387ff116fc8SJan Kara 	struct extent_position oepos, epos;
3881da177e4SLinus Torvalds 	int8_t etype;
38948d6d8ffSMarcin Slusarz 	struct udf_inode_info *iinfo;
3901da177e4SLinus Torvalds 
3911e7933deSIngo Molnar 	mutex_lock(&sbi->s_alloc_mutex);
39297e961fdSPekka Enberg 	partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
39369ecbbedSDan Carpenter 	if (bloc->logicalBlockNum + count < count ||
39469ecbbedSDan Carpenter 	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
395fcbf7637SSteve Magnani 		udf_debug("%u < %d || %u + %u > %u\n",
396a983f368SJoe Perches 			  bloc->logicalBlockNum, 0,
397a983f368SJoe Perches 			  bloc->logicalBlockNum, count,
39897e961fdSPekka Enberg 			  partmap->s_partition_len);
3991da177e4SLinus Torvalds 		goto error_return;
4001da177e4SLinus Torvalds 	}
4011da177e4SLinus Torvalds 
40248d6d8ffSMarcin Slusarz 	iinfo = UDF_I(table);
403146bca72SJan Kara 	udf_add_free_space(sb, sbi->s_partition, count);
4041da177e4SLinus Torvalds 
40597e961fdSPekka Enberg 	start = bloc->logicalBlockNum + offset;
40697e961fdSPekka Enberg 	end = bloc->logicalBlockNum + offset + count - 1;
4071da177e4SLinus Torvalds 
408ff116fc8SJan Kara 	epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry);
4091da177e4SLinus Torvalds 	elen = 0;
41048d6d8ffSMarcin Slusarz 	epos.block = oepos.block = iinfo->i_location;
411ff116fc8SJan Kara 	epos.bh = oepos.bh = NULL;
4121da177e4SLinus Torvalds 
41328de7948SCyrill Gorcunov 	while (count &&
41428de7948SCyrill Gorcunov 	       (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
4154b11111aSMarcin Slusarz 		if (((eloc.logicalBlockNum +
4164b11111aSMarcin Slusarz 			(elen >> sb->s_blocksize_bits)) == start)) {
4174b11111aSMarcin Slusarz 			if ((0x3FFFFFFF - elen) <
4184b11111aSMarcin Slusarz 					(count << sb->s_blocksize_bits)) {
4194b11111aSMarcin Slusarz 				uint32_t tmp = ((0x3FFFFFFF - elen) >>
4204b11111aSMarcin Slusarz 							sb->s_blocksize_bits);
4214b11111aSMarcin Slusarz 				count -= tmp;
4224b11111aSMarcin Slusarz 				start += tmp;
4234b11111aSMarcin Slusarz 				elen = (etype << 30) |
4244b11111aSMarcin Slusarz 					(0x40000000 - sb->s_blocksize);
425cb00ea35SCyrill Gorcunov 			} else {
4264b11111aSMarcin Slusarz 				elen = (etype << 30) |
4274b11111aSMarcin Slusarz 					(elen +
4284b11111aSMarcin Slusarz 					(count << sb->s_blocksize_bits));
4291da177e4SLinus Torvalds 				start += count;
4301da177e4SLinus Torvalds 				count = 0;
4311da177e4SLinus Torvalds 			}
43297e961fdSPekka Enberg 			udf_write_aext(table, &oepos, &eloc, elen, 1);
433cb00ea35SCyrill Gorcunov 		} else if (eloc.logicalBlockNum == (end + 1)) {
4344b11111aSMarcin Slusarz 			if ((0x3FFFFFFF - elen) <
4354b11111aSMarcin Slusarz 					(count << sb->s_blocksize_bits)) {
4364b11111aSMarcin Slusarz 				uint32_t tmp = ((0x3FFFFFFF - elen) >>
4374b11111aSMarcin Slusarz 						sb->s_blocksize_bits);
4384b11111aSMarcin Slusarz 				count -= tmp;
4394b11111aSMarcin Slusarz 				end -= tmp;
4404b11111aSMarcin Slusarz 				eloc.logicalBlockNum -= tmp;
4414b11111aSMarcin Slusarz 				elen = (etype << 30) |
4424b11111aSMarcin Slusarz 					(0x40000000 - sb->s_blocksize);
443cb00ea35SCyrill Gorcunov 			} else {
4441da177e4SLinus Torvalds 				eloc.logicalBlockNum = start;
4454b11111aSMarcin Slusarz 				elen = (etype << 30) |
4464b11111aSMarcin Slusarz 					(elen +
4474b11111aSMarcin Slusarz 					(count << sb->s_blocksize_bits));
4481da177e4SLinus Torvalds 				end -= count;
4491da177e4SLinus Torvalds 				count = 0;
4501da177e4SLinus Torvalds 			}
45197e961fdSPekka Enberg 			udf_write_aext(table, &oepos, &eloc, elen, 1);
4521da177e4SLinus Torvalds 		}
4531da177e4SLinus Torvalds 
454cb00ea35SCyrill Gorcunov 		if (epos.bh != oepos.bh) {
455ff116fc8SJan Kara 			oepos.block = epos.block;
4563bf25cb4SJan Kara 			brelse(oepos.bh);
4573bf25cb4SJan Kara 			get_bh(epos.bh);
458ff116fc8SJan Kara 			oepos.bh = epos.bh;
459ff116fc8SJan Kara 			oepos.offset = 0;
46028de7948SCyrill Gorcunov 		} else {
461ff116fc8SJan Kara 			oepos.offset = epos.offset;
4621da177e4SLinus Torvalds 		}
46328de7948SCyrill Gorcunov 	}
4641da177e4SLinus Torvalds 
465cb00ea35SCyrill Gorcunov 	if (count) {
46628de7948SCyrill Gorcunov 		/*
4674b11111aSMarcin Slusarz 		 * NOTE: we CANNOT use udf_add_aext here, as it can try to
4684b11111aSMarcin Slusarz 		 * allocate a new block, and since we hold the super block
4694b11111aSMarcin Slusarz 		 * lock already very bad things would happen :)
47028de7948SCyrill Gorcunov 		 *
47128de7948SCyrill Gorcunov 		 * We copy the behavior of udf_add_aext, but instead of
47228de7948SCyrill Gorcunov 		 * trying to allocate a new block close to the existing one,
47328de7948SCyrill Gorcunov 		 * we just steal a block from the extent we are trying to add.
47428de7948SCyrill Gorcunov 		 *
47528de7948SCyrill Gorcunov 		 * It would be nice if the blocks were close together, but it
47628de7948SCyrill Gorcunov 		 * isn't required.
4771da177e4SLinus Torvalds 		 */
4781da177e4SLinus Torvalds 
4791da177e4SLinus Torvalds 		int adsize;
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds 		eloc.logicalBlockNum = start;
48228de7948SCyrill Gorcunov 		elen = EXT_RECORDED_ALLOCATED |
48328de7948SCyrill Gorcunov 			(count << sb->s_blocksize_bits);
4841da177e4SLinus Torvalds 
48548d6d8ffSMarcin Slusarz 		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
4865ca4e4beSPekka Enberg 			adsize = sizeof(struct short_ad);
48748d6d8ffSMarcin Slusarz 		else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
4885ca4e4beSPekka Enberg 			adsize = sizeof(struct long_ad);
48948d6d8ffSMarcin Slusarz 		else {
4903bf25cb4SJan Kara 			brelse(oepos.bh);
4913bf25cb4SJan Kara 			brelse(epos.bh);
4921da177e4SLinus Torvalds 			goto error_return;
4931da177e4SLinus Torvalds 		}
4941da177e4SLinus Torvalds 
495cb00ea35SCyrill Gorcunov 		if (epos.offset + (2 * adsize) > sb->s_blocksize) {
4961da177e4SLinus Torvalds 			/* Steal a block from the extent being free'd */
497fcea62baSJan Kara 			udf_setup_indirect_aext(table, eloc.logicalBlockNum,
498fcea62baSJan Kara 						&epos);
499fcea62baSJan Kara 
5001da177e4SLinus Torvalds 			eloc.logicalBlockNum++;
5011da177e4SLinus Torvalds 			elen -= sb->s_blocksize;
50228de7948SCyrill Gorcunov 		}
5031da177e4SLinus Torvalds 
5044b11111aSMarcin Slusarz 		/* It's possible that stealing the block emptied the extent */
505fcea62baSJan Kara 		if (elen)
506fcea62baSJan Kara 			__udf_add_aext(table, &epos, &eloc, elen, 1);
5071da177e4SLinus Torvalds 	}
5081da177e4SLinus Torvalds 
5093bf25cb4SJan Kara 	brelse(epos.bh);
5103bf25cb4SJan Kara 	brelse(oepos.bh);
5111da177e4SLinus Torvalds 
5121da177e4SLinus Torvalds error_return:
5131e7933deSIngo Molnar 	mutex_unlock(&sbi->s_alloc_mutex);
5141da177e4SLinus Torvalds 	return;
5151da177e4SLinus Torvalds }
5161da177e4SLinus Torvalds 
udf_table_prealloc_blocks(struct super_block * sb,struct inode * table,uint16_t partition,uint32_t first_block,uint32_t block_count)5171da177e4SLinus Torvalds static int udf_table_prealloc_blocks(struct super_block *sb,
518cb00ea35SCyrill Gorcunov 				     struct inode *table, uint16_t partition,
519cb00ea35SCyrill Gorcunov 				     uint32_t first_block, uint32_t block_count)
5201da177e4SLinus Torvalds {
5211da177e4SLinus Torvalds 	struct udf_sb_info *sbi = UDF_SB(sb);
5221da177e4SLinus Torvalds 	int alloc_count = 0;
523ff116fc8SJan Kara 	uint32_t elen, adsize;
5245ca4e4beSPekka Enberg 	struct kernel_lb_addr eloc;
525ff116fc8SJan Kara 	struct extent_position epos;
5261da177e4SLinus Torvalds 	int8_t etype = -1;
52748d6d8ffSMarcin Slusarz 	struct udf_inode_info *iinfo;
5281da177e4SLinus Torvalds 
5293391faa4SRoel Kluin 	if (first_block >= sbi->s_partmaps[partition].s_partition_len)
5301da177e4SLinus Torvalds 		return 0;
5311da177e4SLinus Torvalds 
53248d6d8ffSMarcin Slusarz 	iinfo = UDF_I(table);
53348d6d8ffSMarcin Slusarz 	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5345ca4e4beSPekka Enberg 		adsize = sizeof(struct short_ad);
53548d6d8ffSMarcin Slusarz 	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5365ca4e4beSPekka Enberg 		adsize = sizeof(struct long_ad);
5371da177e4SLinus Torvalds 	else
5381da177e4SLinus Torvalds 		return 0;
5391da177e4SLinus Torvalds 
5401e7933deSIngo Molnar 	mutex_lock(&sbi->s_alloc_mutex);
541ff116fc8SJan Kara 	epos.offset = sizeof(struct unallocSpaceEntry);
54248d6d8ffSMarcin Slusarz 	epos.block = iinfo->i_location;
543ff116fc8SJan Kara 	epos.bh = NULL;
5441da177e4SLinus Torvalds 	eloc.logicalBlockNum = 0xFFFFFFFF;
5451da177e4SLinus Torvalds 
54628de7948SCyrill Gorcunov 	while (first_block != eloc.logicalBlockNum &&
54728de7948SCyrill Gorcunov 	       (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
548fcbf7637SSteve Magnani 		udf_debug("eloc=%u, elen=%u, first_block=%u\n",
5491da177e4SLinus Torvalds 			  eloc.logicalBlockNum, elen, first_block);
5501da177e4SLinus Torvalds 		; /* empty loop body */
5511da177e4SLinus Torvalds 	}
5521da177e4SLinus Torvalds 
553cb00ea35SCyrill Gorcunov 	if (first_block == eloc.logicalBlockNum) {
554ff116fc8SJan Kara 		epos.offset -= adsize;
5551da177e4SLinus Torvalds 
5561da177e4SLinus Torvalds 		alloc_count = (elen >> sb->s_blocksize_bits);
55736350462SJan Kara 		if (alloc_count > block_count) {
5581da177e4SLinus Torvalds 			alloc_count = block_count;
5591da177e4SLinus Torvalds 			eloc.logicalBlockNum += alloc_count;
5601da177e4SLinus Torvalds 			elen -= (alloc_count << sb->s_blocksize_bits);
56197e961fdSPekka Enberg 			udf_write_aext(table, &epos, &eloc,
5624b11111aSMarcin Slusarz 					(etype << 30) | elen, 1);
5634b11111aSMarcin Slusarz 		} else
5646c1e4d06SJan Kara 			udf_delete_aext(table, epos);
56528de7948SCyrill Gorcunov 	} else {
5661da177e4SLinus Torvalds 		alloc_count = 0;
56728de7948SCyrill Gorcunov 	}
5681da177e4SLinus Torvalds 
5693bf25cb4SJan Kara 	brelse(epos.bh);
5701da177e4SLinus Torvalds 
571146bca72SJan Kara 	if (alloc_count)
572146bca72SJan Kara 		udf_add_free_space(sb, partition, -alloc_count);
5731e7933deSIngo Molnar 	mutex_unlock(&sbi->s_alloc_mutex);
5741da177e4SLinus Torvalds 	return alloc_count;
5751da177e4SLinus Torvalds }
5761da177e4SLinus Torvalds 
udf_table_new_block(struct super_block * sb,struct inode * table,uint16_t partition,uint32_t goal,int * err)577b490bdd6SSteve Magnani static udf_pblk_t udf_table_new_block(struct super_block *sb,
578cb00ea35SCyrill Gorcunov 			       struct inode *table, uint16_t partition,
579cb00ea35SCyrill Gorcunov 			       uint32_t goal, int *err)
5801da177e4SLinus Torvalds {
5811da177e4SLinus Torvalds 	struct udf_sb_info *sbi = UDF_SB(sb);
5821da177e4SLinus Torvalds 	uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
583b490bdd6SSteve Magnani 	udf_pblk_t newblock = 0;
584b490bdd6SSteve Magnani 	uint32_t adsize;
585ff116fc8SJan Kara 	uint32_t elen, goal_elen = 0;
5863f649ab7SKees Cook 	struct kernel_lb_addr eloc, goal_eloc;
587ff116fc8SJan Kara 	struct extent_position epos, goal_epos;
5881da177e4SLinus Torvalds 	int8_t etype;
58948d6d8ffSMarcin Slusarz 	struct udf_inode_info *iinfo = UDF_I(table);
5901da177e4SLinus Torvalds 
5911da177e4SLinus Torvalds 	*err = -ENOSPC;
5921da177e4SLinus Torvalds 
59348d6d8ffSMarcin Slusarz 	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5945ca4e4beSPekka Enberg 		adsize = sizeof(struct short_ad);
59548d6d8ffSMarcin Slusarz 	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5965ca4e4beSPekka Enberg 		adsize = sizeof(struct long_ad);
5971da177e4SLinus Torvalds 	else
5981da177e4SLinus Torvalds 		return newblock;
5991da177e4SLinus Torvalds 
6001e7933deSIngo Molnar 	mutex_lock(&sbi->s_alloc_mutex);
6013391faa4SRoel Kluin 	if (goal >= sbi->s_partmaps[partition].s_partition_len)
6021da177e4SLinus Torvalds 		goal = 0;
6031da177e4SLinus Torvalds 
6044b11111aSMarcin Slusarz 	/* We search for the closest matching block to goal. If we find
6054b11111aSMarcin Slusarz 	   a exact hit, we stop. Otherwise we keep going till we run out
6064b11111aSMarcin Slusarz 	   of extents. We store the buffer_head, bloc, and extoffset
6074b11111aSMarcin Slusarz 	   of the current closest match and use that when we are done.
6081da177e4SLinus Torvalds 	 */
609ff116fc8SJan Kara 	epos.offset = sizeof(struct unallocSpaceEntry);
61048d6d8ffSMarcin Slusarz 	epos.block = iinfo->i_location;
611ff116fc8SJan Kara 	epos.bh = goal_epos.bh = NULL;
6121da177e4SLinus Torvalds 
61328de7948SCyrill Gorcunov 	while (spread &&
61428de7948SCyrill Gorcunov 	       (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
615cb00ea35SCyrill Gorcunov 		if (goal >= eloc.logicalBlockNum) {
6164b11111aSMarcin Slusarz 			if (goal < eloc.logicalBlockNum +
6174b11111aSMarcin Slusarz 					(elen >> sb->s_blocksize_bits))
6181da177e4SLinus Torvalds 				nspread = 0;
6191da177e4SLinus Torvalds 			else
6201da177e4SLinus Torvalds 				nspread = goal - eloc.logicalBlockNum -
6211da177e4SLinus Torvalds 					(elen >> sb->s_blocksize_bits);
62228de7948SCyrill Gorcunov 		} else {
6231da177e4SLinus Torvalds 			nspread = eloc.logicalBlockNum - goal;
62428de7948SCyrill Gorcunov 		}
6251da177e4SLinus Torvalds 
626cb00ea35SCyrill Gorcunov 		if (nspread < spread) {
6271da177e4SLinus Torvalds 			spread = nspread;
628cb00ea35SCyrill Gorcunov 			if (goal_epos.bh != epos.bh) {
6293bf25cb4SJan Kara 				brelse(goal_epos.bh);
630ff116fc8SJan Kara 				goal_epos.bh = epos.bh;
6313bf25cb4SJan Kara 				get_bh(goal_epos.bh);
6321da177e4SLinus Torvalds 			}
633ff116fc8SJan Kara 			goal_epos.block = epos.block;
634ff116fc8SJan Kara 			goal_epos.offset = epos.offset - adsize;
6351da177e4SLinus Torvalds 			goal_eloc = eloc;
6361da177e4SLinus Torvalds 			goal_elen = (etype << 30) | elen;
6371da177e4SLinus Torvalds 		}
6381da177e4SLinus Torvalds 	}
6391da177e4SLinus Torvalds 
6403bf25cb4SJan Kara 	brelse(epos.bh);
6411da177e4SLinus Torvalds 
642cb00ea35SCyrill Gorcunov 	if (spread == 0xFFFFFFFF) {
6433bf25cb4SJan Kara 		brelse(goal_epos.bh);
6441e7933deSIngo Molnar 		mutex_unlock(&sbi->s_alloc_mutex);
6451da177e4SLinus Torvalds 		return 0;
6461da177e4SLinus Torvalds 	}
6471da177e4SLinus Torvalds 
6481da177e4SLinus Torvalds 	/* Only allocate blocks from the beginning of the extent.
6491da177e4SLinus Torvalds 	   That way, we only delete (empty) extents, never have to insert an
6501da177e4SLinus Torvalds 	   extent because of splitting */
6511da177e4SLinus Torvalds 	/* This works, but very poorly.... */
6521da177e4SLinus Torvalds 
6531da177e4SLinus Torvalds 	newblock = goal_eloc.logicalBlockNum;
6541da177e4SLinus Torvalds 	goal_eloc.logicalBlockNum++;
6551da177e4SLinus Torvalds 	goal_elen -= sb->s_blocksize;
6561da177e4SLinus Torvalds 
6571da177e4SLinus Torvalds 	if (goal_elen)
65897e961fdSPekka Enberg 		udf_write_aext(table, &goal_epos, &goal_eloc, goal_elen, 1);
6591da177e4SLinus Torvalds 	else
6606c1e4d06SJan Kara 		udf_delete_aext(table, goal_epos);
6613bf25cb4SJan Kara 	brelse(goal_epos.bh);
6621da177e4SLinus Torvalds 
663146bca72SJan Kara 	udf_add_free_space(sb, partition, -1);
6641da177e4SLinus Torvalds 
6651e7933deSIngo Molnar 	mutex_unlock(&sbi->s_alloc_mutex);
6661da177e4SLinus Torvalds 	*err = 0;
6671da177e4SLinus Torvalds 	return newblock;
6681da177e4SLinus Torvalds }
6691da177e4SLinus Torvalds 
udf_free_blocks(struct super_block * sb,struct inode * inode,struct kernel_lb_addr * bloc,uint32_t offset,uint32_t count)67097e961fdSPekka Enberg void udf_free_blocks(struct super_block *sb, struct inode *inode,
67197e961fdSPekka Enberg 		     struct kernel_lb_addr *bloc, uint32_t offset,
672cb00ea35SCyrill Gorcunov 		     uint32_t count)
6731da177e4SLinus Torvalds {
67497e961fdSPekka Enberg 	uint16_t partition = bloc->partitionReferenceNum;
6756c79e987SMarcin Slusarz 	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
6761da177e4SLinus Torvalds 
6776c79e987SMarcin Slusarz 	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) {
678fd4287dbSJan Kara 		udf_bitmap_free_blocks(sb, map->s_uspace.s_bitmap,
67928de7948SCyrill Gorcunov 				       bloc, offset, count);
6806c79e987SMarcin Slusarz 	} else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) {
681fd4287dbSJan Kara 		udf_table_free_blocks(sb, map->s_uspace.s_table,
68228de7948SCyrill Gorcunov 				      bloc, offset, count);
6831da177e4SLinus Torvalds 	}
684fd4287dbSJan Kara 
685fd4287dbSJan Kara 	if (inode) {
686fd4287dbSJan Kara 		inode_sub_bytes(inode,
687fd4287dbSJan Kara 				((sector_t)count) << sb->s_blocksize_bits);
688fd4287dbSJan Kara 	}
68928de7948SCyrill Gorcunov }
6901da177e4SLinus Torvalds 
udf_prealloc_blocks(struct super_block * sb,struct inode * inode,uint16_t partition,uint32_t first_block,uint32_t block_count)6911da177e4SLinus Torvalds inline int udf_prealloc_blocks(struct super_block *sb,
6921da177e4SLinus Torvalds 			       struct inode *inode,
693cb00ea35SCyrill Gorcunov 			       uint16_t partition, uint32_t first_block,
694cb00ea35SCyrill Gorcunov 			       uint32_t block_count)
6951da177e4SLinus Torvalds {
6966c79e987SMarcin Slusarz 	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
6971be440deSFabian Frederick 	int allocated;
6986c79e987SMarcin Slusarz 
6994b11111aSMarcin Slusarz 	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
700fd4287dbSJan Kara 		allocated = udf_bitmap_prealloc_blocks(sb,
7016c79e987SMarcin Slusarz 						       map->s_uspace.s_bitmap,
7024b11111aSMarcin Slusarz 						       partition, first_block,
7034b11111aSMarcin Slusarz 						       block_count);
7044b11111aSMarcin Slusarz 	else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
705fd4287dbSJan Kara 		allocated = udf_table_prealloc_blocks(sb,
7066c79e987SMarcin Slusarz 						      map->s_uspace.s_table,
7074b11111aSMarcin Slusarz 						      partition, first_block,
7084b11111aSMarcin Slusarz 						      block_count);
7094b11111aSMarcin Slusarz 	else
7101da177e4SLinus Torvalds 		return 0;
711fd4287dbSJan Kara 
712fd4287dbSJan Kara 	if (inode && allocated > 0)
713fd4287dbSJan Kara 		inode_add_bytes(inode, allocated << sb->s_blocksize_bits);
714fd4287dbSJan Kara 	return allocated;
7151da177e4SLinus Torvalds }
7161da177e4SLinus Torvalds 
udf_new_block(struct super_block * sb,struct inode * inode,uint16_t partition,uint32_t goal,int * err)717b490bdd6SSteve Magnani inline udf_pblk_t udf_new_block(struct super_block *sb,
7181da177e4SLinus Torvalds 			 struct inode *inode,
7191da177e4SLinus Torvalds 			 uint16_t partition, uint32_t goal, int *err)
7201da177e4SLinus Torvalds {
7216c79e987SMarcin Slusarz 	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
722b490bdd6SSteve Magnani 	udf_pblk_t block;
7233bf25cb4SJan Kara 
7244b11111aSMarcin Slusarz 	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
725fd4287dbSJan Kara 		block = udf_bitmap_new_block(sb,
7266c79e987SMarcin Slusarz 					     map->s_uspace.s_bitmap,
72728de7948SCyrill Gorcunov 					     partition, goal, err);
7284b11111aSMarcin Slusarz 	else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
729fd4287dbSJan Kara 		block = udf_table_new_block(sb,
7306c79e987SMarcin Slusarz 					    map->s_uspace.s_table,
73128de7948SCyrill Gorcunov 					    partition, goal, err);
7324b11111aSMarcin Slusarz 	else {
7331da177e4SLinus Torvalds 		*err = -EIO;
7341da177e4SLinus Torvalds 		return 0;
7351da177e4SLinus Torvalds 	}
736fd4287dbSJan Kara 	if (inode && block)
737fd4287dbSJan Kara 		inode_add_bytes(inode, sb->s_blocksize);
738fd4287dbSJan Kara 	return block;
7391da177e4SLinus Torvalds }
740