5 * Partition handling routines for the OSTA-UDF(tm) filesystem.
8 * E-mail regarding any portion of the Linux UDF file system should be
9 * directed to the development team mailing list (run by majordomo):
10 * linux_udf@hpesjro.fc.hp.com
13 * This file is distributed under the terms of the GNU General Public
14 * License (GPL). Copies of the GPL can be obtained from:
15 * ftp://prep.ai.mit.edu/pub/gnu/GPL
16 * Each contributing author retains all rights to their own work.
18 * (C) 1998-2001 Ben Fennema
22 * 12/06/98 blf Created file.
31 #include <linux/string.h>
32 #include <linux/udf_fs.h>
33 #include <linux/slab.h>
34 #include <linux/buffer_head.h>
36 inline uint32_t udf_get_pblock(struct super_block
*sb
, uint32_t block
, uint16_t partition
, uint32_t offset
)
38 if (partition
>= UDF_SB_NUMPARTS(sb
))
40 udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n",
41 block
, partition
, offset
);
44 if (UDF_SB_PARTFUNC(sb
, partition
))
45 return UDF_SB_PARTFUNC(sb
, partition
)(sb
, block
, partition
, offset
);
47 return UDF_SB_PARTROOT(sb
, partition
) + block
+ offset
;
50 uint32_t udf_get_pblock_virt15(struct super_block
*sb
, uint32_t block
, uint16_t partition
, uint32_t offset
)
52 struct buffer_head
*bh
= NULL
;
57 index
= (sb
->s_blocksize
- UDF_SB_TYPEVIRT(sb
,partition
).s_start_offset
) / sizeof(uint32_t);
59 if (block
> UDF_SB_TYPEVIRT(sb
,partition
).s_num_entries
)
61 udf_debug("Trying to access block beyond end of VAT (%d max %d)\n",
62 block
, UDF_SB_TYPEVIRT(sb
,partition
).s_num_entries
);
69 newblock
= 1 + (block
/ (sb
->s_blocksize
/ sizeof(uint32_t)));
70 index
= block
% (sb
->s_blocksize
/ sizeof(uint32_t));
75 index
= UDF_SB_TYPEVIRT(sb
,partition
).s_start_offset
/ sizeof(uint32_t) + block
;
78 loc
= udf_block_map(UDF_SB_VAT(sb
), newblock
);
80 if (!(bh
= sb_bread(sb
, loc
)))
82 udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n",
83 sb
, block
, partition
, loc
, index
);
87 loc
= le32_to_cpu(((__le32
*)bh
->b_data
)[index
]);
91 if (UDF_I_LOCATION(UDF_SB_VAT(sb
)).partitionReferenceNum
== partition
)
93 udf_debug("recursive call to udf_get_pblock!\n");
97 return udf_get_pblock(sb
, loc
, UDF_I_LOCATION(UDF_SB_VAT(sb
)).partitionReferenceNum
, offset
);
100 inline uint32_t udf_get_pblock_virt20(struct super_block
*sb
, uint32_t block
, uint16_t partition
, uint32_t offset
)
102 return udf_get_pblock_virt15(sb
, block
, partition
, offset
);
105 uint32_t udf_get_pblock_spar15(struct super_block
*sb
, uint32_t block
, uint16_t partition
, uint32_t offset
)
108 struct sparingTable
*st
= NULL
;
109 uint32_t packet
= (block
+ offset
) & ~(UDF_SB_TYPESPAR(sb
,partition
).s_packet_len
- 1);
113 if (UDF_SB_TYPESPAR(sb
,partition
).s_spar_map
[i
] != NULL
)
115 st
= (struct sparingTable
*)UDF_SB_TYPESPAR(sb
,partition
).s_spar_map
[i
]->b_data
;
122 for (i
=0; i
<le16_to_cpu(st
->reallocationTableLen
); i
++)
124 if (le32_to_cpu(st
->mapEntry
[i
].origLocation
) >= 0xFFFFFFF0)
126 else if (le32_to_cpu(st
->mapEntry
[i
].origLocation
) == packet
)
128 return le32_to_cpu(st
->mapEntry
[i
].mappedLocation
) +
129 ((block
+ offset
) & (UDF_SB_TYPESPAR(sb
,partition
).s_packet_len
- 1));
131 else if (le32_to_cpu(st
->mapEntry
[i
].origLocation
) > packet
)
135 return UDF_SB_PARTROOT(sb
,partition
) + block
+ offset
;
138 int udf_relocate_blocks(struct super_block
*sb
, long old_block
, long *new_block
)
140 struct udf_sparing_data
*sdata
;
141 struct sparingTable
*st
= NULL
;
142 struct sparingEntry mapEntry
;
146 for (i
=0; i
<UDF_SB_NUMPARTS(sb
); i
++)
148 if (old_block
> UDF_SB_PARTROOT(sb
,i
) &&
149 old_block
< UDF_SB_PARTROOT(sb
,i
) + UDF_SB_PARTLEN(sb
,i
))
151 sdata
= &UDF_SB_TYPESPAR(sb
,i
);
152 packet
= (old_block
- UDF_SB_PARTROOT(sb
,i
)) & ~(sdata
->s_packet_len
- 1);
156 if (UDF_SB_TYPESPAR(sb
,i
).s_spar_map
[j
] != NULL
)
158 st
= (struct sparingTable
*)sdata
->s_spar_map
[j
]->b_data
;
166 for (k
=0; k
<le16_to_cpu(st
->reallocationTableLen
); k
++)
168 if (le32_to_cpu(st
->mapEntry
[k
].origLocation
) == 0xFFFFFFFF)
172 if (sdata
->s_spar_map
[j
])
174 st
= (struct sparingTable
*)sdata
->s_spar_map
[j
]->b_data
;
175 st
->mapEntry
[k
].origLocation
= cpu_to_le32(packet
);
176 udf_update_tag((char *)st
, sizeof(struct sparingTable
) + le16_to_cpu(st
->reallocationTableLen
) * sizeof(struct sparingEntry
));
177 mark_buffer_dirty(sdata
->s_spar_map
[j
]);
180 *new_block
= le32_to_cpu(st
->mapEntry
[k
].mappedLocation
) +
181 ((old_block
- UDF_SB_PARTROOT(sb
,i
)) & (sdata
->s_packet_len
- 1));
184 else if (le32_to_cpu(st
->mapEntry
[k
].origLocation
) == packet
)
186 *new_block
= le32_to_cpu(st
->mapEntry
[k
].mappedLocation
) +
187 ((old_block
- UDF_SB_PARTROOT(sb
,i
)) & (sdata
->s_packet_len
- 1));
190 else if (le32_to_cpu(st
->mapEntry
[k
].origLocation
) > packet
)
193 for (l
=k
; l
<le16_to_cpu(st
->reallocationTableLen
); l
++)
195 if (le32_to_cpu(st
->mapEntry
[l
].origLocation
) == 0xFFFFFFFF)
199 if (sdata
->s_spar_map
[j
])
201 st
= (struct sparingTable
*)sdata
->s_spar_map
[j
]->b_data
;
202 mapEntry
= st
->mapEntry
[l
];
203 mapEntry
.origLocation
= cpu_to_le32(packet
);
204 memmove(&st
->mapEntry
[k
+1], &st
->mapEntry
[k
], (l
-k
)*sizeof(struct sparingEntry
));
205 st
->mapEntry
[k
] = mapEntry
;
206 udf_update_tag((char *)st
, sizeof(struct sparingTable
) + le16_to_cpu(st
->reallocationTableLen
) * sizeof(struct sparingEntry
));
207 mark_buffer_dirty(sdata
->s_spar_map
[j
]);
210 *new_block
= le32_to_cpu(st
->mapEntry
[k
].mappedLocation
) +
211 ((old_block
- UDF_SB_PARTROOT(sb
,i
)) & (sdata
->s_packet_len
- 1));
218 if (i
== UDF_SB_NUMPARTS(sb
))
220 /* outside of partitions */
221 /* for now, fail =) */