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