patch-2.3.17 linux/fs/udf/partition.c
Next file: linux/fs/udf/super.c
Previous file: linux/fs/udf/namei.c
Back to the patch index
Back to the overall index
- Lines: 191
- Date:
Sat Sep 4 12:42:30 1999
- Orig file:
v2.3.16/linux/fs/udf/partition.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.16/linux/fs/udf/partition.c linux/fs/udf/partition.c
@@ -0,0 +1,190 @@
+/*
+ * partition.c
+ *
+ * PURPOSE
+ * Partition handling routines for the OSTA-UDF(tm) filesystem.
+ *
+ * CONTACTS
+ * E-mail regarding any portion of the Linux UDF file system should be
+ * directed to the development team mailing list (run by majordomo):
+ * linux_udf@hootie.lvld.hp.com
+ *
+ * COPYRIGHT
+ * This file is distributed under the terms of the GNU General Public
+ * License (GPL). Copies of the GPL can be obtained from:
+ * ftp://prep.ai.mit.edu/pub/gnu/GPL
+ * Each contributing author retains all rights to their own work.
+ *
+ * (C) 1998-1999 Ben Fennema
+ *
+ * HISTORY
+ *
+ * 12/06/98 blf Created file.
+ *
+ */
+
+#include "udfdecl.h"
+#include "udf_sb.h"
+#include "udf_i.h"
+
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/udf_fs.h>
+
+extern Uint32 udf_get_pblock(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
+{
+ Uint16 ident;
+
+ if (partition >= UDF_SB_NUMPARTS(sb))
+ {
+ udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n",
+ block, partition, offset);
+ return 0xFFFFFFFF;
+ }
+ switch (UDF_SB_PARTTYPE(sb, partition))
+ {
+ case UDF_TYPE1_MAP15:
+ {
+ return UDF_SB_PARTROOT(sb, partition) + block + offset;
+ }
+ case UDF_VIRTUAL_MAP15:
+ case UDF_VIRTUAL_MAP20:
+ {
+ struct buffer_head *bh = NULL;
+ Uint32 newblock;
+ Uint32 index;
+ Uint32 loc;
+
+ index = (sb->s_blocksize - UDF_SB_TYPEVIRT(sb,partition).s_start_offset) / sizeof(Uint32);
+
+
+ if (block > UDF_SB_TYPEVIRT(sb,partition).s_num_entries)
+ {
+ udf_debug("Trying to access block beyond end of VAT (%d max %d)\n",
+ block, UDF_SB_TYPEVIRT(sb,partition).s_num_entries);
+ return 0xFFFFFFFF;
+ }
+
+ if (block >= index)
+ {
+ block -= index;
+ newblock = 1 + (block / (sb->s_blocksize / sizeof(Uint32)));
+ index = block % (sb->s_blocksize / sizeof(Uint32));
+ }
+ else
+ {
+ newblock = 0;
+ index = UDF_SB_TYPEVIRT(sb,partition).s_start_offset / sizeof(Uint32) + block;
+ }
+
+ loc = udf_locked_block_map(UDF_SB_VAT(sb), newblock);
+
+ if (!(bh = bread(sb->s_dev, loc, sb->s_blocksize)))
+ {
+ udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n",
+ sb, block, partition, loc, index);
+ return 0xFFFFFFFF;
+ }
+
+ loc = le32_to_cpu(((Uint32 *)bh->b_data)[index]);
+
+ udf_release_data(bh);
+
+ if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition)
+ {
+ udf_debug("recursive call to udf_get_pblock!\n");
+ return 0xFFFFFFFF;
+ }
+
+ return udf_get_pblock(sb, loc, UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum, offset);
+ }
+ case UDF_SPARABLE_MAP15:
+ {
+ Uint32 newblock = UDF_SB_PARTROOT(sb, partition) + block + offset;
+ Uint32 spartable = UDF_SB_TYPESPAR(sb, partition).s_spar_loc;
+ Uint32 plength = UDF_SB_TYPESPAR(sb,partition).s_spar_plen;
+ Uint32 packet = (block + offset) & (~(plength-1));
+ struct buffer_head *bh = NULL;
+ struct SparingTable *st;
+ SparingEntry *se;
+
+ bh = udf_read_tagged(sb, spartable, spartable, &ident);
+
+ if (!bh)
+ {
+ printk(KERN_ERR "udf: udf_read_tagged(%p,%d,%d)\n",
+ sb, spartable, spartable);
+ return 0xFFFFFFFF;
+ }
+
+ st = (struct SparingTable *)bh->b_data;
+ if (ident == 0)
+ {
+ if (!strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING)))
+ {
+ Uint16 rtl = le16_to_cpu(st->reallocationTableLen);
+ Uint16 index;
+
+ /* If the sparing table span multiple blocks, find out which block we are on */
+
+ se = &(st->mapEntry[0]);
+
+ if (rtl * sizeof(SparingEntry) + sizeof(struct SparingTable) > sb->s_blocksize)
+ {
+ index = (sb->s_blocksize - sizeof(struct SparingTable)) / sizeof(SparingEntry);
+ if (le32_to_cpu(se[index-1].origLocation) == packet)
+ {
+ udf_release_data(bh);
+ return le32_to_cpu(se[index].mappedLocation) | (newblock & (plength-1));
+ }
+ else if (le32_to_cpu(se[index-1].origLocation) < packet)
+ {
+ do
+ {
+ udf_release_data(bh);
+ bh = udf_tread(sb, spartable, sb->s_blocksize);
+ if (!bh)
+ return 0xFFFFFFFF;
+ se = (SparingEntry *)bh->b_data;
+ spartable ++;
+ rtl -= index;
+ index = sb->s_blocksize / sizeof(SparingEntry);
+
+ if (le32_to_cpu(se[index].origLocation) == packet)
+ {
+ udf_release_data(bh);
+ return le32_to_cpu(se[index].mappedLocation) | (newblock & (plength-1));
+ }
+ } while (rtl * sizeof(SparingEntry) > sb->s_blocksize &&
+ le32_to_cpu(se[index-1].origLocation) < packet);
+ }
+ }
+
+ for (index=0; index<rtl; index++)
+ {
+ if (le32_to_cpu(se[index].origLocation) == packet)
+ {
+ udf_release_data(bh);
+ return le32_to_cpu(se[index].mappedLocation) | (newblock & (plength-1));
+ }
+ else if (le32_to_cpu(se[index].origLocation) > packet)
+ {
+ udf_release_data(bh);
+ return newblock;
+ }
+ }
+
+ udf_release_data(bh);
+ return newblock;
+ }
+ }
+ udf_release_data(bh);
+ }
+ }
+ return 0xFFFFFFFF;
+}
+
+extern Uint32 udf_get_lb_pblock(struct super_block *sb, lb_addr loc, Uint32 offset)
+{
+ return udf_get_pblock(sb, loc.logicalBlockNum, loc.partitionReferenceNum, offset);
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)