The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/udf/partition.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * partition.c
    3  *
    4  * PURPOSE
    5  *      Partition handling routines for the OSTA-UDF(tm) filesystem.
    6  *
    7  * COPYRIGHT
    8  *      This file is distributed under the terms of the GNU General Public
    9  *      License (GPL). Copies of the GPL can be obtained from:
   10  *              ftp://prep.ai.mit.edu/pub/gnu/GPL
   11  *      Each contributing author retains all rights to their own work.
   12  *
   13  *  (C) 1998-2001 Ben Fennema
   14  *
   15  * HISTORY
   16  *
   17  * 12/06/98 blf  Created file.
   18  *
   19  */
   20 
   21 #include "udfdecl.h"
   22 #include "udf_sb.h"
   23 #include "udf_i.h"
   24 
   25 #include <linux/fs.h>
   26 #include <linux/string.h>
   27 #include <linux/buffer_head.h>
   28 #include <linux/mutex.h>
   29 
   30 uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
   31                         uint16_t partition, uint32_t offset)
   32 {
   33         struct udf_sb_info *sbi = UDF_SB(sb);
   34         struct udf_part_map *map;
   35         if (partition >= sbi->s_partitions) {
   36                 udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n",
   37                           block, partition, offset);
   38                 return 0xFFFFFFFF;
   39         }
   40         map = &sbi->s_partmaps[partition];
   41         if (map->s_partition_func)
   42                 return map->s_partition_func(sb, block, partition, offset);
   43         else
   44                 return map->s_partition_root + block + offset;
   45 }
   46 
   47 uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
   48                                uint16_t partition, uint32_t offset)
   49 {
   50         struct buffer_head *bh = NULL;
   51         uint32_t newblock;
   52         uint32_t index;
   53         uint32_t loc;
   54         struct udf_sb_info *sbi = UDF_SB(sb);
   55         struct udf_part_map *map;
   56         struct udf_virtual_data *vdata;
   57         struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode);
   58 
   59         map = &sbi->s_partmaps[partition];
   60         vdata = &map->s_type_specific.s_virtual;
   61 
   62         if (block > vdata->s_num_entries) {
   63                 udf_debug("Trying to access block beyond end of VAT (%d max %d)\n",
   64                           block, vdata->s_num_entries);
   65                 return 0xFFFFFFFF;
   66         }
   67 
   68         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
   69                 loc = le32_to_cpu(((__le32 *)(iinfo->i_ext.i_data +
   70                         vdata->s_start_offset))[block]);
   71                 goto translate;
   72         }
   73         index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
   74         if (block >= index) {
   75                 block -= index;
   76                 newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t)));
   77                 index = block % (sb->s_blocksize / sizeof(uint32_t));
   78         } else {
   79                 newblock = 0;
   80                 index = vdata->s_start_offset / sizeof(uint32_t) + block;
   81         }
   82 
   83         loc = udf_block_map(sbi->s_vat_inode, newblock);
   84 
   85         bh = sb_bread(sb, loc);
   86         if (!bh) {
   87                 udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n",
   88                           sb, block, partition, loc, index);
   89                 return 0xFFFFFFFF;
   90         }
   91 
   92         loc = le32_to_cpu(((__le32 *)bh->b_data)[index]);
   93 
   94         brelse(bh);
   95 
   96 translate:
   97         if (iinfo->i_location.partitionReferenceNum == partition) {
   98                 udf_debug("recursive call to udf_get_pblock!\n");
   99                 return 0xFFFFFFFF;
  100         }
  101 
  102         return udf_get_pblock(sb, loc,
  103                               iinfo->i_location.partitionReferenceNum,
  104                               offset);
  105 }
  106 
  107 inline uint32_t udf_get_pblock_virt20(struct super_block *sb, uint32_t block,
  108                                       uint16_t partition, uint32_t offset)
  109 {
  110         return udf_get_pblock_virt15(sb, block, partition, offset);
  111 }
  112 
  113 uint32_t udf_get_pblock_spar15(struct super_block *sb, uint32_t block,
  114                                uint16_t partition, uint32_t offset)
  115 {
  116         int i;
  117         struct sparingTable *st = NULL;
  118         struct udf_sb_info *sbi = UDF_SB(sb);
  119         struct udf_part_map *map;
  120         uint32_t packet;
  121         struct udf_sparing_data *sdata;
  122 
  123         map = &sbi->s_partmaps[partition];
  124         sdata = &map->s_type_specific.s_sparing;
  125         packet = (block + offset) & ~(sdata->s_packet_len - 1);
  126 
  127         for (i = 0; i < 4; i++) {
  128                 if (sdata->s_spar_map[i] != NULL) {
  129                         st = (struct sparingTable *)
  130                                         sdata->s_spar_map[i]->b_data;
  131                         break;
  132                 }
  133         }
  134 
  135         if (st) {
  136                 for (i = 0; i < le16_to_cpu(st->reallocationTableLen); i++) {
  137                         struct sparingEntry *entry = &st->mapEntry[i];
  138                         u32 origLoc = le32_to_cpu(entry->origLocation);
  139                         if (origLoc >= 0xFFFFFFF0)
  140                                 break;
  141                         else if (origLoc == packet)
  142                                 return le32_to_cpu(entry->mappedLocation) +
  143                                         ((block + offset) &
  144                                                 (sdata->s_packet_len - 1));
  145                         else if (origLoc > packet)
  146                                 break;
  147                 }
  148         }
  149 
  150         return map->s_partition_root + block + offset;
  151 }
  152 
  153 int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
  154 {
  155         struct udf_sparing_data *sdata;
  156         struct sparingTable *st = NULL;
  157         struct sparingEntry mapEntry;
  158         uint32_t packet;
  159         int i, j, k, l;
  160         struct udf_sb_info *sbi = UDF_SB(sb);
  161         u16 reallocationTableLen;
  162         struct buffer_head *bh;
  163         int ret = 0;
  164 
  165         mutex_lock(&sbi->s_alloc_mutex);
  166         for (i = 0; i < sbi->s_partitions; i++) {
  167                 struct udf_part_map *map = &sbi->s_partmaps[i];
  168                 if (old_block > map->s_partition_root &&
  169                     old_block < map->s_partition_root + map->s_partition_len) {
  170                         sdata = &map->s_type_specific.s_sparing;
  171                         packet = (old_block - map->s_partition_root) &
  172                                                 ~(sdata->s_packet_len - 1);
  173 
  174                         for (j = 0; j < 4; j++)
  175                                 if (sdata->s_spar_map[j] != NULL) {
  176                                         st = (struct sparingTable *)
  177                                                 sdata->s_spar_map[j]->b_data;
  178                                         break;
  179                                 }
  180 
  181                         if (!st) {
  182                                 ret = 1;
  183                                 goto out;
  184                         }
  185 
  186                         reallocationTableLen =
  187                                         le16_to_cpu(st->reallocationTableLen);
  188                         for (k = 0; k < reallocationTableLen; k++) {
  189                                 struct sparingEntry *entry = &st->mapEntry[k];
  190                                 u32 origLoc = le32_to_cpu(entry->origLocation);
  191 
  192                                 if (origLoc == 0xFFFFFFFF) {
  193                                         for (; j < 4; j++) {
  194                                                 int len;
  195                                                 bh = sdata->s_spar_map[j];
  196                                                 if (!bh)
  197                                                         continue;
  198 
  199                                                 st = (struct sparingTable *)
  200                                                                 bh->b_data;
  201                                                 entry->origLocation =
  202                                                         cpu_to_le32(packet);
  203                                                 len =
  204                                                   sizeof(struct sparingTable) +
  205                                                   reallocationTableLen *
  206                                                   sizeof(struct sparingEntry);
  207                                                 udf_update_tag((char *)st, len);
  208                                                 mark_buffer_dirty(bh);
  209                                         }
  210                                         *new_block = le32_to_cpu(
  211                                                         entry->mappedLocation) +
  212                                                      ((old_block -
  213                                                         map->s_partition_root) &
  214                                                      (sdata->s_packet_len - 1));
  215                                         ret = 0;
  216                                         goto out;
  217                                 } else if (origLoc == packet) {
  218                                         *new_block = le32_to_cpu(
  219                                                         entry->mappedLocation) +
  220                                                      ((old_block -
  221                                                         map->s_partition_root) &
  222                                                      (sdata->s_packet_len - 1));
  223                                         ret = 0;
  224                                         goto out;
  225                                 } else if (origLoc > packet)
  226                                         break;
  227                         }
  228 
  229                         for (l = k; l < reallocationTableLen; l++) {
  230                                 struct sparingEntry *entry = &st->mapEntry[l];
  231                                 u32 origLoc = le32_to_cpu(entry->origLocation);
  232 
  233                                 if (origLoc != 0xFFFFFFFF)
  234                                         continue;
  235 
  236                                 for (; j < 4; j++) {
  237                                         bh = sdata->s_spar_map[j];
  238                                         if (!bh)
  239                                                 continue;
  240 
  241                                         st = (struct sparingTable *)bh->b_data;
  242                                         mapEntry = st->mapEntry[l];
  243                                         mapEntry.origLocation =
  244                                                         cpu_to_le32(packet);
  245                                         memmove(&st->mapEntry[k + 1],
  246                                                 &st->mapEntry[k],
  247                                                 (l - k) *
  248                                                 sizeof(struct sparingEntry));
  249                                         st->mapEntry[k] = mapEntry;
  250                                         udf_update_tag((char *)st,
  251                                                 sizeof(struct sparingTable) +
  252                                                 reallocationTableLen *
  253                                                 sizeof(struct sparingEntry));
  254                                         mark_buffer_dirty(bh);
  255                                 }
  256                                 *new_block =
  257                                         le32_to_cpu(
  258                                               st->mapEntry[k].mappedLocation) +
  259                                         ((old_block - map->s_partition_root) &
  260                                          (sdata->s_packet_len - 1));
  261                                 ret = 0;
  262                                 goto out;
  263                         }
  264 
  265                         ret = 1;
  266                         goto out;
  267                 } /* if old_block */
  268         }
  269 
  270         if (i == sbi->s_partitions) {
  271                 /* outside of partitions */
  272                 /* for now, fail =) */
  273                 ret = 1;
  274         }
  275 
  276 out:
  277         mutex_unlock(&sbi->s_alloc_mutex);
  278         return ret;
  279 }
  280 
  281 static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
  282                                         uint16_t partition, uint32_t offset)
  283 {
  284         struct super_block *sb = inode->i_sb;
  285         struct udf_part_map *map;
  286         struct kernel_lb_addr eloc;
  287         uint32_t elen;
  288         sector_t ext_offset;
  289         struct extent_position epos = {};
  290         uint32_t phyblock;
  291 
  292         if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) !=
  293                                                 (EXT_RECORDED_ALLOCATED >> 30))
  294                 phyblock = 0xFFFFFFFF;
  295         else {
  296                 map = &UDF_SB(sb)->s_partmaps[partition];
  297                 /* map to sparable/physical partition desc */
  298                 phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
  299                         map->s_partition_num, ext_offset + offset);
  300         }
  301 
  302         brelse(epos.bh);
  303         return phyblock;
  304 }
  305 
  306 uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
  307                                 uint16_t partition, uint32_t offset)
  308 {
  309         struct udf_sb_info *sbi = UDF_SB(sb);
  310         struct udf_part_map *map;
  311         struct udf_meta_data *mdata;
  312         uint32_t retblk;
  313         struct inode *inode;
  314 
  315         udf_debug("READING from METADATA\n");
  316 
  317         map = &sbi->s_partmaps[partition];
  318         mdata = &map->s_type_specific.s_metadata;
  319         inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe;
  320 
  321         /* We shouldn't mount such media... */
  322         BUG_ON(!inode);
  323         retblk = udf_try_read_meta(inode, block, partition, offset);
  324         if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) {
  325                 udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n");
  326                 if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) {
  327                         mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
  328                                 mdata->s_mirror_file_loc, map->s_partition_num);
  329                         mdata->s_flags |= MF_MIRROR_FE_LOADED;
  330                 }
  331 
  332                 inode = mdata->s_mirror_fe;
  333                 if (!inode)
  334                         return 0xFFFFFFFF;
  335                 retblk = udf_try_read_meta(inode, block, partition, offset);
  336         }
  337 
  338         return retblk;
  339 }

Cache object: e290d139346d036efe1c1b37e620379f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.