Revision b50c8289 snf-image-helper/disklabel.py

b/snf-image-helper/disklabel.py
98 98
        def pack_chs(cylinder, head, sector):
99 99
            """Packs a CHS tuple to an address string."""
100 100

  
101
            assert 1 <= sector <= 63
102
            assert 0 <= head <= 255
103
            assert 0 <= cylinder
104

  
105
            # If the cylinders overflow then put the value (1023, 254, 63) to
106
            # the tuple. At least this is what OpenBSD does.
107
            if cylinder > 1023:
108
                cylinder = 1023
109
                head = 254
110
                sector = 63
101
            assert 1 <= sector < 2**6, "Invalid sector value"
102
            assert 0 <= head < 2**8, "Invalid head value"
103
            assert 0 <= cylinder < 2**10, "Invalid cylinder value"
111 104

  
112 105
            byte0 = head
113 106
            byte1 = (cylinder >> 2) & 0xC0 | sector
......
209 202
        start = self.mbr.part[self.part_num].first_sector
210 203
        self.mbr.part[self.part_num].sector_count = end - start + 1
211 204

  
212
        ntracks = self.disklabel.field['ntracks']
213
        nsectors = self.disklabel.field['nsectors']
205
        # There are cases where the CHS address changes although the LBA
206
        # address remains the same. For example when the bios is configured
207
        # to use a disk in LBA-Assisted translation mode, the CHS
208
        # representation depends on the size of the disk. When we enlarge the
209
        # size of the disk we may have to update the starting sector's CHS
210
        # address too.
211
        start_chs = MBR.Partition.pack_chs(*self.disklabel.lba2chs(start))
212
        self.mbr.part[self.part_num].start = start_chs
214 213

  
215
        cylinder = end // (ntracks * nsectors)
216
        header = (end // nsectors) % ntracks
217
        sector = (end % nsectors) + 1
218
        chs = MBR.Partition.pack_chs(cylinder, header, sector)
219
        self.mbr.part[self.part_num].end = chs
214
        end_chs = MBR.Partition.pack_chs(*self.disklabel.lba2chs(end))
215
        self.mbr.part[self.part_num].end = end_chs
220 216

  
221 217
    def enlarge_last_partition(self):
222 218
        """Enlarge the last partition to cover up all the free space"""
......
277 273

  
278 274
        return checksum
279 275

  
280
    @abc.abstractmethod
281
    def enlarge(self, new_size):
282
        """Enlarge the disk and return the last usable sector"""
283
        pass
284

  
285 276
    def write_to(self, device):
286 277
        """Write the disklabel to a device"""
287 278

  
......
289 280
        device.seek(BLOCKSIZE, os.SEEK_CUR)
290 281
        device.write(self.pack())
291 282

  
283
    def lba2chs(self, lba, hpc=None, spt=None):
284
        """Returns the CHS address for a given LBA address"""
285

  
286
        assert hpc is None or hpc > 0, "Invalid heads per cylinder value"
287
        assert spt is None or spt > 0, "Invalid sectors per track value"
288

  
289
        if hpc is None:
290
            hpc = self.field['ntracks']
291

  
292
        if spt is None:
293
            spt = self.field['nsectors']
294

  
295
        # See:
296
        # http://en.wikipedia.org/wiki/Logical_Block_Addressing#CHS_conversion
297
        #
298

  
299
        cylinder = lba // (spt * hpc)
300
        header = (lba // spt) % hpc
301
        sector = (lba % spt) + 1
302

  
303
        return (cylinder, header, sector)
304

  
305
    @abc.abstractmethod
306
    def enlarge(self, new_size):
307
        """Enlarge the disk and return the last usable sector"""
308
        pass
309

  
292 310
    @abc.abstractmethod
293 311
    def enlarge_last_partition(self):
294 312
        """Enlarge the last partition to consume all the usable space"""
......
484 502

  
485 503
        @property
486 504
        def fields(self):
487
            return [    # Offset  Length Contents
505
            return [        # Offset  Length Contents
488 506
                'size',     # 0       4      Number of sectors in the partition
489 507
                'offset',   # 4       4      Starting sector of the partition
490 508
                'offseth',  # 8       2      Starting sector (high part)
......
655 673

  
656 674
        self.field['checksum'] = self.compute_checksum()
657 675

  
676
    def lba2chs(self, lba, hpc=None, spt=None):
677
        """Returns the CHS address for a given LBA address"""
678

  
679
        chs = super(OpenBSDDisklabel, self).lba2chs(lba, hpc, spt)
680

  
681
        # If the cylinders overflow, then OpenBSD will put the value
682
        #(1023, 254, 63) to the tuple.
683
        if chs[0] > 1023:
684
            return (1023, 254, 63)
685

  
686
        return chs
687

  
658 688
    def __str__(self):
659 689
        """Print the Disklabel"""
660 690

  

Also available in: Unified diff