static void udf_bitmap_free_blocks(const struct inode * inode, struct udf_bitmap *bitmap, lb_addr bloc, Uint32 offset, Uint32 count) { struct buffer_head * bh = NULL; unsigned long block; unsigned long block_group; unsigned long bit; unsigned long i; int bitmap_nr; unsigned long overflow; struct super_block * sb; sb = inode->i_sb; if (!sb) { udf_debug("nonexistent device"); return; } lock_super(sb); if (bloc.logicalBlockNum < 0 || (bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum)) { udf_debug("%d < %d || %d + %d > %d\n", bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum)); goto error_return; } block = bloc.logicalBlockNum + offset + (sizeof(struct SpaceBitmapDesc) << 3); do_more: overflow = 0; block_group = block >> (sb->s_blocksize_bits + 3); bit = block % (sb->s_blocksize << 3); /* * Check to see if we are freeing blocks across a group boundary. */ if (bit + count > (sb->s_blocksize << 3)) { overflow = bit + count - (sb->s_blocksize << 3); count -= overflow; } bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto error_return; bh = bitmap->s_block_bitmap[bitmap_nr]; for (i=0; i < count; i++) { if (udf_set_bit(bit + i, bh->b_data)) { udf_debug("bit %ld already set\n", bit + i); udf_debug("byte=%2x\n", ((char *)bh->b_data)[(bit + i) >> 3]); } else {
int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block) { struct udf_sparing_data *sdata; struct sparingTable *st = NULL; struct sparingEntry mapEntry; uint32_t packet; int i, j, k, l; for (i = 0; i < UDF_SB_NUMPARTS(sb); i++) { if (old_block > UDF_SB_PARTROOT(sb,i) && old_block < UDF_SB_PARTROOT(sb,i) + UDF_SB_PARTLEN(sb,i)) { sdata = &UDF_SB_TYPESPAR(sb,i); packet = (old_block - UDF_SB_PARTROOT(sb,i)) & ~(sdata->s_packet_len - 1); for (j = 0; j < 4; j++) { if (UDF_SB_TYPESPAR(sb,i).s_spar_map[j] != NULL) { st = (struct sparingTable *)sdata->s_spar_map[j]->b_data; break; } } if (!st) return 1; for (k = 0; k < le16_to_cpu(st->reallocationTableLen); k++) { if (le32_to_cpu(st->mapEntry[k].origLocation) == 0xFFFFFFFF) { for (; j < 4; j++) { if (sdata->s_spar_map[j]) { st = (struct sparingTable *)sdata->s_spar_map[j]->b_data; st->mapEntry[k].origLocation = cpu_to_le32(packet); udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry)); mark_buffer_dirty(sdata->s_spar_map[j]); } } *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) + ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1)); return 0; } else if (le32_to_cpu(st->mapEntry[k].origLocation) == packet) { *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) + ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1)); return 0; } else if (le32_to_cpu(st->mapEntry[k].origLocation) > packet) { break; } } for (l = k; l < le16_to_cpu(st->reallocationTableLen); l++) { if (le32_to_cpu(st->mapEntry[l].origLocation) == 0xFFFFFFFF) { for (; j < 4; j++) { if (sdata->s_spar_map[j]) { st = (struct sparingTable *)sdata->s_spar_map[j]->b_data; mapEntry = st->mapEntry[l]; mapEntry.origLocation = cpu_to_le32(packet); memmove(&st->mapEntry[k + 1], &st->mapEntry[k], (l - k) * sizeof(struct sparingEntry)); st->mapEntry[k] = mapEntry; udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry)); mark_buffer_dirty(sdata->s_spar_map[j]); } } *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) + ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1)); return 0; } } return 1; } /* if old_block */ } if (i == UDF_SB_NUMPARTS(sb)) { /* outside of partitions */ /* for now, fail =) */ return 1; } return 0; }
static int udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root) { struct buffer_head *bh = NULL; long lastblock; Uint16 ident; if (fileset->logicalBlockNum != 0xFFFFFFFF || fileset->partitionReferenceNum != 0xFFFF) { bh = udf_read_ptagged(sb, *fileset, 0, &ident); if (!bh) return 1; else if (ident != TID_FILE_SET_DESC) { udf_release_data(bh); return 1; } } if (!bh) /* Search backwards through the partitions */ { lb_addr newfileset; return 1; for (newfileset.partitionReferenceNum=UDF_SB_NUMPARTS(sb)-1; (newfileset.partitionReferenceNum != 0xFFFF && fileset->logicalBlockNum == 0xFFFFFFFF && fileset->partitionReferenceNum == 0xFFFF); newfileset.partitionReferenceNum--) { lastblock = UDF_SB_PARTLEN(sb, newfileset.partitionReferenceNum); newfileset.logicalBlockNum = 0; do { bh = udf_read_ptagged(sb, newfileset, 0, &ident); if (!bh) { newfileset.logicalBlockNum ++; continue; } switch (ident) { case TID_SPACE_BITMAP_DESC: { struct SpaceBitmapDesc *sp; sp = (struct SpaceBitmapDesc *)bh->b_data; newfileset.logicalBlockNum += 1 + ((le32_to_cpu(sp->numOfBytes) + sizeof(struct SpaceBitmapDesc) - 1) >> sb->s_blocksize_bits); udf_release_data(bh); break; } case TID_FILE_SET_DESC: { *fileset = newfileset; break; } default: { newfileset.logicalBlockNum ++; udf_release_data(bh); bh = NULL; break; } } } while (newfileset.logicalBlockNum < lastblock && fileset->logicalBlockNum == 0xFFFFFFFF && fileset->partitionReferenceNum == 0xFFFF); } }