1
/* libparted - a library for manipulating disk partitions
2
Copyright (C) 1999-2010 Free Software Foundation, Inc.
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 3 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program. If not, see <http://www.gnu.org/licenses/>.
18
#define PROC_DEVICES_BUFSIZ 16384
21
#include <arch/linux.h>
22
#include <linux/blkpg.h>
23
#include <parted/parted.h>
24
#include <parted/debug.h>
25
#if defined __s390__ || defined __s390x__
26
#include <parted/fdasd.h>
38
#include <sys/ioctl.h>
40
#include <sys/types.h>
41
#include <sys/utsname.h> /* for uname() */
42
#include <scsi/scsi.h>
43
#ifdef ENABLE_DEVICE_MAPPER
44
#include <libdevmapper.h>
47
#include "../architecture.h"
52
# define _(String) dgettext (PACKAGE, String)
54
# define _(String) (String)
55
#endif /* ENABLE_NLS */
57
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
60
#define __NR__llseek 140
63
#ifndef SCSI_IOCTL_SEND_COMMAND
64
#define SCSI_IOCTL_SEND_COMMAND 1
67
/* from <linux/hdreg.h> */
68
#define HDIO_GETGEO 0x0301 /* get device geometry */
69
#define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
71
#define RD_MODE (O_RDONLY)
72
#define WR_MODE (O_WRONLY)
73
#define RW_MODE (O_RDWR)
77
unsigned char sectors;
78
unsigned short cylinders;
82
struct ata7_sectinfo {
89
/* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
91
unsigned short config; /* lots of obsolete bit flags */
92
unsigned short cyls; /* "physical" cyls */
93
unsigned short reserved2; /* reserved (word 2) */
94
unsigned short heads; /* "physical" heads */
95
unsigned short track_bytes; /* unformatted bytes per track */
96
unsigned short sector_bytes; /* unformatted bytes per sector */
97
unsigned short sectors; /* "physical" sectors per track */
98
unsigned short vendor0; /* vendor unique */
99
unsigned short vendor1; /* vendor unique */
100
unsigned short vendor2; /* vendor unique */
101
unsigned char serial_no[20]; /* 0 = not_specified */
102
unsigned short buf_type;
103
unsigned short buf_size; /* 512 byte increments;
105
unsigned short ecc_bytes; /* for r/w long cmds;
107
unsigned char fw_rev[8]; /* 0 = not_specified */
108
char model[40]; /* 0 = not_specified */
109
unsigned char max_multsect; /* 0=not_implemented */
110
unsigned char vendor3; /* vendor unique */
111
unsigned short dword_io; /* 0=not_implemented; 1=implemented */
112
unsigned char vendor4; /* vendor unique */
113
unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
115
unsigned short reserved50; /* reserved (word 50) */
116
unsigned char vendor5; /* vendor unique */
117
unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
118
unsigned char vendor6; /* vendor unique */
119
unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
120
unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
121
unsigned short cur_cyls; /* logical cylinders */
122
unsigned short cur_heads; /* logical heads */
123
unsigned short cur_sectors; /* logical sectors per track */
124
unsigned short cur_capacity0; /* logical total sectors on drive */
125
unsigned short cur_capacity1; /* (2 words, misaligned int) */
126
unsigned char multsect; /* current multiple sector count */
127
unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
128
unsigned int lba_capacity; /* total number of sectors */
129
unsigned short dma_1word; /* single-word dma info */
130
unsigned short dma_mword; /* multiple-word dma info */
131
unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
132
unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
133
unsigned short eide_dma_time; /* recommended mword dma cycle
135
unsigned short eide_pio; /* min cycle time (ns), no IORDY */
136
unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
137
unsigned short words69_70[2]; /* reserved words 69-70 */
138
/* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
139
unsigned short words71_74[4]; /* reserved words 71-74 */
140
unsigned short queue_depth; /* */
141
unsigned short words76_79[4]; /* reserved words 76-79 */
142
unsigned short major_rev_num; /* */
143
unsigned short minor_rev_num; /* */
144
unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
146
unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
147
unsigned short cfsse; /* command set-feature supported
149
unsigned short cfs_enable_1; /* command set-feature enabled */
150
unsigned short cfs_enable_2; /* command set-feature enabled */
151
unsigned short csf_default; /* command set-feature default */
152
unsigned short dma_ultra; /* */
153
unsigned short word89; /* reserved (word 89) */
154
unsigned short word90; /* reserved (word 90) */
155
unsigned short CurAPMvalues; /* current APM values */
156
unsigned short word92; /* reserved (word 92) */
157
unsigned short hw_config; /* hardware config */
158
unsigned short words94_105[12];/* reserved words 94-105 */
159
struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
161
unsigned short words107_116[10];/* reserved words 107-116 */
162
unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
163
unsigned short words119_125[7];/* reserved words 119-125 */
164
unsigned short last_lun; /* reserved (word 126) */
165
unsigned short word127; /* reserved (word 127) */
166
unsigned short dlf; /* device lock function
168
* 8 security level 1:max 0:high
177
unsigned short csfo; /* current set features options
184
unsigned short words130_155[26];/* reserved vendor words 130-155 */
185
unsigned short word156;
186
unsigned short words157_159[3]; /* reserved vendor words 157-159 */
187
unsigned short words160_255[95];/* reserved words 160-255 */
190
/* from <linux/fs.h> */
191
#define BLKRRPART _IO(0x12,95) /* re-read partition table */
192
#define BLKGETSIZE _IO(0x12,96) /* return device size */
193
#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
194
#define BLKSSZGET _IO(0x12,104) /* get block device sector size */
195
#define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
196
#define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
198
/* return device size in bytes (u64 *arg) */
199
#define BLKGETSIZE64 _IOR(0x12,114,size_t)
201
struct blkdev_ioctl_param {
203
size_t content_length;
204
char * block_contents;
207
/* from <linux/major.h> */
209
#define IDE1_MAJOR 22
210
#define IDE2_MAJOR 33
211
#define IDE3_MAJOR 34
212
#define IDE4_MAJOR 56
213
#define IDE5_MAJOR 57
214
#define SCSI_CDROM_MAJOR 11
215
#define SCSI_DISK0_MAJOR 8
216
#define SCSI_DISK1_MAJOR 65
217
#define SCSI_DISK2_MAJOR 66
218
#define SCSI_DISK3_MAJOR 67
219
#define SCSI_DISK4_MAJOR 68
220
#define SCSI_DISK5_MAJOR 69
221
#define SCSI_DISK6_MAJOR 70
222
#define SCSI_DISK7_MAJOR 71
223
#define COMPAQ_SMART2_MAJOR 72
224
#define COMPAQ_SMART2_MAJOR1 73
225
#define COMPAQ_SMART2_MAJOR2 74
226
#define COMPAQ_SMART2_MAJOR3 75
227
#define COMPAQ_SMART2_MAJOR4 76
228
#define COMPAQ_SMART2_MAJOR5 77
229
#define COMPAQ_SMART2_MAJOR6 78
230
#define COMPAQ_SMART2_MAJOR7 79
231
#define COMPAQ_SMART_MAJOR 104
232
#define COMPAQ_SMART_MAJOR1 105
233
#define COMPAQ_SMART_MAJOR2 106
234
#define COMPAQ_SMART_MAJOR3 107
235
#define COMPAQ_SMART_MAJOR4 108
236
#define COMPAQ_SMART_MAJOR5 109
237
#define COMPAQ_SMART_MAJOR6 110
238
#define COMPAQ_SMART_MAJOR7 111
239
#define DAC960_MAJOR 48
240
#define ATARAID_MAJOR 114
241
#define I2O_MAJOR1 80
242
#define I2O_MAJOR2 81
243
#define I2O_MAJOR3 82
244
#define I2O_MAJOR4 83
245
#define I2O_MAJOR5 84
246
#define I2O_MAJOR6 85
247
#define I2O_MAJOR7 86
248
#define I2O_MAJOR8 87
250
#define DASD_MAJOR 94
251
#define VIODASD_MAJOR 112
252
#define AOE_MAJOR 152
253
#define SX8_MAJOR1 160
254
#define SX8_MAJOR2 161
255
#define XVD_MAJOR 202
256
#define SDMMC_MAJOR 179
260
#define SCSI_BLK_MAJOR(M) ( \
261
(M) == SCSI_DISK0_MAJOR \
262
|| (M) == SCSI_CDROM_MAJOR \
263
|| ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
265
/* Maximum number of partitions supported by linux. */
266
#define MAX_NUM_PARTS 64
268
static char* _device_get_part_path (PedDevice* dev, int num);
269
static int _partition_is_mounted_by_path (const char* path);
272
_read_fd (int fd, char **buf)
275
size_t size = PROC_DEVICES_BUFSIZ;
278
*buf = malloc (size * sizeof (char));
284
p = &(*buf) [filesize];
285
s = read (fd, p, PROC_DEVICES_BUFSIZ);
286
/* exit if there is an error or EOF is reached */
291
char *new_buf = realloc (*buf, size);
292
if (new_buf == NULL) {
293
int saved_errno = errno;
301
if (filesize == 0 && s < 0) {
306
char *new_buf = realloc (*buf, filesize + 1);
307
if (new_buf == NULL) {
308
int saved_errno = errno;
314
(*buf)[filesize] = '\0';
321
_major_type_in_devices (int major, const char* type)
330
fd = open ("/proc/devices", O_RDONLY);
334
if (_read_fd(fd, &buf) < 0) {
340
end = strchr(line, '\n');
349
if (!strncmp(line, "Block devices:", 14))
354
name = strrchr(line, ' ');
355
if (!name || strcmp(name+1, type))
358
maj = strtol(line, &name, 10);
368
end = strchr(line, '\n');
376
_is_ide_major (int major)
393
_is_cpqarray_major (int major)
395
return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
396
|| (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
400
_is_i2o_major (int major)
402
return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
406
_is_sx8_major (int major)
408
return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
412
_is_virtblk_major (int major)
414
return _major_type_in_devices (major, "virtblk");
417
#ifdef ENABLE_DEVICE_MAPPER
419
_is_dm_major (int major)
421
return _major_type_in_devices (major, "device-mapper");
425
_dm_maptype (PedDevice *dev)
427
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
429
uint64_t start, length;
430
char *target_type = NULL;
433
const char* dev_dir = getenv ("DM_DEV_DIR");
435
if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
438
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
441
if (!dm_task_set_major_minor(dmt, arch_specific->major,
442
arch_specific->minor, 0))
445
dm_task_no_open_count(dmt);
447
if (!dm_task_run(dmt))
450
dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms);
452
arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
453
if (arch_specific->dmtype == NULL)
457
dm_task_destroy(dmt);
467
char buf [512]; /* readdir(3) claims d_name[256] */
470
mapper_dir = opendir ("/dev/mapper");
474
/* Search the /dev/mapper directory for devices w/ the same major
475
* number that was returned from _probe_lvm_major().
477
while ((dent = readdir (mapper_dir))) {
478
if (strcmp (dent->d_name, ".") == 0 ||
479
strcmp (dent->d_name, "..") == 0)
482
snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
484
if (stat (buf, &st) != 0)
487
if (_is_dm_major(major(st.st_rdev)))
488
_ped_device_probe (buf);
490
closedir (mapper_dir);
497
_device_stat (PedDevice* dev, struct stat * dev_stat)
499
PED_ASSERT (dev != NULL, return 0);
500
PED_ASSERT (!dev->external_mode, return 0);
503
if (!stat (dev->path, dev_stat)) {
506
if (ped_exception_throw (
508
PED_EXCEPTION_RETRY_CANCEL,
509
_("Could not stat device %s - %s."),
512
!= PED_EXCEPTION_RETRY)
519
_device_probe_type (PedDevice* dev)
521
struct stat dev_stat;
524
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
526
if (!_device_stat (dev, &dev_stat))
529
if (!S_ISBLK(dev_stat.st_mode)) {
530
dev->type = PED_DEVICE_FILE;
534
arch_specific->major = dev_major = major (dev_stat.st_rdev);
535
arch_specific->minor = dev_minor = minor (dev_stat.st_rdev);
537
if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
538
dev->type = PED_DEVICE_SCSI;
539
} else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
540
dev->type = PED_DEVICE_IDE;
541
} else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
542
dev->type = PED_DEVICE_DAC960;
543
} else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
544
dev->type = PED_DEVICE_ATARAID;
545
} else if (dev_major == AOE_MAJOR && (dev_minor % 0x10 == 0)) {
546
dev->type = PED_DEVICE_AOE;
547
} else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
548
dev->type = PED_DEVICE_DASD;
549
} else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
550
dev->type = PED_DEVICE_VIODASD;
551
} else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
552
dev->type = PED_DEVICE_SX8;
553
} else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
554
dev->type = PED_DEVICE_I2O;
555
} else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
556
dev->type = PED_DEVICE_CPQARRAY;
557
} else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
558
dev->type = PED_DEVICE_UBD;
559
#ifdef ENABLE_DEVICE_MAPPER
560
} else if (_is_dm_major(dev_major)) {
561
dev->type = PED_DEVICE_DM;
562
if (_dm_maptype(dev)) {
563
ped_exception_throw (
565
PED_EXCEPTION_CANCEL,
566
_("Unable to determine the dm type of %s."),
570
} else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
571
dev->type = PED_DEVICE_XVD;
572
} else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
573
dev->type = PED_DEVICE_SDMMC;
574
} else if (_is_virtblk_major(dev_major)) {
575
dev->type = PED_DEVICE_VIRTBLK;
576
} else if (dev_major == LOOP_MAJOR) {
577
dev->type = PED_DEVICE_FILE;
578
} else if (dev_major == MD_MAJOR) {
579
dev->type = PED_DEVICE_MD;
581
dev->type = PED_DEVICE_UNKNOWN;
588
_get_linux_version ()
590
static int kver = -1;
602
if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
605
return kver = KERNEL_VERSION (major, minor, teeny);
611
static int have_kern26 = -1;
614
if (have_kern26 != -1)
617
kver = _get_linux_version();
618
return have_kern26 = kver >= KERNEL_VERSION (2,6,0) ? 1 : 0;
623
get_blkid_topology (LinuxSpecific *arch_specific)
625
arch_specific->probe = blkid_new_probe ();
626
if (!arch_specific->probe)
629
if (blkid_probe_set_device(arch_specific->probe,
630
arch_specific->fd, 0, 0))
633
arch_specific->topology =
634
blkid_probe_get_topology(arch_specific->probe);
639
_device_set_sector_size (PedDevice* dev)
641
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
644
dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
645
dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
647
PED_ASSERT (dev->open_count, return);
649
if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
650
dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
654
if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
655
ped_exception_throw (
656
PED_EXCEPTION_WARNING,
658
_("Could not determine sector size for %s: %s.\n"
659
"Using the default sector size (%lld)."),
660
dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
662
dev->sector_size = (long long)sector_size;
663
dev->phys_sector_size = dev->sector_size;
667
get_blkid_topology(arch_specific);
668
if (!arch_specific->topology) {
669
dev->phys_sector_size = 0;
671
dev->phys_sector_size =
672
blkid_topology_get_physical_sector_size(
673
arch_specific->topology);
675
if (dev->phys_sector_size == 0) {
676
ped_exception_throw (
677
PED_EXCEPTION_WARNING,
679
_("Could not determine physical sector size for %s.\n"
680
"Using the logical sector size (%lld)."),
681
dev->path, dev->sector_size);
682
dev->phys_sector_size = dev->sector_size;
686
#if defined __s390__ || defined __s390x__
687
/* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
688
if (dev->type == PED_DEVICE_DASD) {
689
arch_specific->real_sector_size = dev->sector_size;
690
dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
696
_kernel_has_blkgetsize64(void)
698
int version = _get_linux_version();
700
if (version >= KERNEL_VERSION (2,5,4)) return 1;
701
if (version < KERNEL_VERSION (2,5,0) &&
702
version >= KERNEL_VERSION (2,4,18)) return 1;
706
/* TODO: do a binary search if BLKGETSIZE doesn't work?! */
708
_device_get_length (PedDevice* dev)
711
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
715
PED_ASSERT (dev->open_count > 0, return 0);
716
PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
718
if (_kernel_has_blkgetsize64()) {
719
if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
720
return bytes / dev->sector_size;
724
if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
725
ped_exception_throw (
727
PED_EXCEPTION_CANCEL,
728
_("Unable to determine the size of %s (%s)."),
738
_device_probe_geometry (PedDevice* dev)
740
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
741
struct stat dev_stat;
742
struct hd_geometry geometry;
744
if (!_device_stat (dev, &dev_stat))
746
PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
748
_device_set_sector_size (dev);
750
dev->length = _device_get_length (dev);
754
/* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
755
* still use it in 2.4.x, but this is contentious. Perhaps we should
757
dev->bios_geom.sectors = 63;
758
dev->bios_geom.heads = 255;
759
dev->bios_geom.cylinders
760
= dev->length / (63 * 255);
762
/* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
763
if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
764
&& geometry.sectors && geometry.heads) {
765
dev->hw_geom.sectors = geometry.sectors;
766
dev->hw_geom.heads = geometry.heads;
767
dev->hw_geom.cylinders
768
= dev->length / (dev->hw_geom.heads
769
* dev->hw_geom.sectors);
771
dev->hw_geom = dev->bios_geom;
778
strip_name(char* str)
783
for (i = 0; str[i] != 0; i++) {
784
if (!isspace (str[i])
785
|| (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
795
init_ide (PedDevice* dev)
797
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
798
struct stat dev_stat;
799
struct hd_driveid hdi;
800
PedExceptionOption ex_status;
802
int sector_multiplier = 0;
804
if (!_device_stat (dev, &dev_stat))
807
if (!ped_device_open (dev))
810
if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
811
ex_status = ped_exception_throw (
812
PED_EXCEPTION_WARNING,
813
PED_EXCEPTION_IGNORE_CANCEL,
814
_("Could not get identity of device %s - %s"),
815
dev->path, strerror (errno));
817
case PED_EXCEPTION_CANCEL:
818
goto error_close_dev;
820
case PED_EXCEPTION_UNHANDLED:
821
ped_exception_catch ();
822
case PED_EXCEPTION_IGNORE:
823
dev->model = strdup(_("Generic IDE"));
826
PED_ASSERT (0, (void) 0);
830
/* hdi.model is not guaranteed to be NULL terminated */
831
memcpy (hdi_buf, hdi.model, 40);
833
dev->model = strip_name (hdi_buf);
835
if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
836
sector_multiplier = hdi.ata7_sectinfo.multiplier;
838
sector_multiplier = 1;
840
if (sector_multiplier != 1) {
841
ex_status = ped_exception_throw (
842
PED_EXCEPTION_WARNING,
843
PED_EXCEPTION_IGNORE_CANCEL,
844
_("Device %s has multiple (%d) logical sectors "
845
"per physical sector.\n"
846
"GNU Parted supports this EXPERIMENTALLY for "
847
"some special disk label/file system "
848
"combinations, e.g. GPT and ext2/3.\n"
849
"Please consult the web site for up-to-date "
851
dev->path, sector_multiplier);
854
case PED_EXCEPTION_CANCEL:
855
goto error_close_dev;
857
case PED_EXCEPTION_UNHANDLED:
858
ped_exception_catch ();
859
case PED_EXCEPTION_IGNORE:
862
PED_ASSERT (0, (void) 0);
867
/* XXX sector_size has not been set yet! */
868
/* dev->phys_sector_size = dev->sector_size
869
* sector_multiplier;*/
870
dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
873
if (!_device_probe_geometry (dev))
874
goto error_close_dev;
876
ped_device_close (dev);
880
ped_device_close (dev);
885
/* This function reads the /sys entry named "file" for device "dev". */
887
read_device_sysfs_file (PedDevice *dev, const char *file)
893
snprintf (name_buf, 127, "/sys/block/%s/device/%s",
894
last_component (dev->path), file);
896
if ((f = fopen (name_buf, "r")) == NULL)
899
if (fgets (buf, 255, f) == NULL)
903
return strip_name (buf);
906
/* This function sends a query to a SCSI device for vendor and product
907
* information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
911
scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
913
/* The following are defined by the SCSI-2 specification. */
914
typedef struct _scsi_inquiry_cmd
917
uint8_t lun; /* bits 5-7 denote the LUN */
920
uint8_t alloc_length;
922
} __attribute__((packed)) scsi_inquiry_cmd_t;
924
typedef struct _scsi_inquiry_data
926
uint8_t peripheral_info;
928
uint8_t version_info;
930
uint8_t additional_length;
934
uint8_t vendor_id[8];
935
uint8_t product_id[16];
936
uint8_t product_revision[4];
937
uint8_t vendor_specific[20];
938
uint8_t _reserved3[40];
939
} __attribute__((packed)) scsi_inquiry_data_t;
948
scsi_inquiry_data_t out;
949
scsi_inquiry_cmd_t in;
953
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
959
memset (&arg, 0x00, sizeof(struct scsi_arg));
961
arg.outlen = sizeof(scsi_inquiry_data_t);
962
arg.data.in.op = INQUIRY;
963
arg.data.in.lun = dev->host << 5;
964
arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
965
arg.data.in.page_code = 0;
966
arg.data.in.reserved = 0;
967
arg.data.in.control = 0;
969
if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
972
memcpy (buf, arg.data.out.vendor_id, 8);
974
*vendor = strip_name (buf);
976
memcpy (buf, arg.data.out.product_id, 16);
978
*product = strip_name (buf);
983
/* This function provides the vendor and product name for a SCSI device.
984
* It supports both the modern /sys interface and direct queries
985
* via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
988
scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
990
*vendor = read_device_sysfs_file (dev, "vendor");
991
*product = read_device_sysfs_file (dev, "model");
992
if (*vendor && *product)
995
return scsi_query_product_info (dev, vendor, product);
999
init_scsi (PedDevice* dev)
1004
uint32_t host_unique_id;
1007
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1011
if (!ped_device_open (dev))
1014
if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
1017
if (ped_exception_throw (
1018
PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
1019
_("Error initialising SCSI device %s - %s"),
1020
dev->path, strerror (errno))
1021
!= PED_EXCEPTION_IGNORE)
1022
goto error_close_dev;
1023
if (!_device_probe_geometry (dev))
1024
goto error_close_dev;
1025
ped_device_close (dev);
1029
dev->host = idlun.host_unique_id;
1030
dev->did = idlun.dev_id;
1032
dev->model = (char*) ped_malloc (8 + 16 + 2);
1034
goto error_close_dev;
1036
if (scsi_get_product_info (dev, &vendor, &product)) {
1037
sprintf (dev->model, "%.8s %.16s", vendor, product);
1041
strcpy (dev->model, "Generic SCSI");
1044
if (!_device_probe_geometry (dev))
1045
goto error_close_dev;
1047
ped_device_close (dev);
1051
ped_device_close (dev);
1057
init_file (PedDevice* dev)
1059
struct stat dev_stat;
1061
if (!_device_stat (dev, &dev_stat))
1063
if (!ped_device_open (dev))
1066
dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1067
char *p = getenv ("PARTED_SECTOR_SIZE");
1070
if (0 < s && s % 512 == 0)
1071
dev->sector_size = s;
1073
dev->phys_sector_size = dev->sector_size;
1075
if (S_ISBLK(dev_stat.st_mode))
1076
dev->length = _device_get_length (dev);
1078
dev->length = dev_stat.st_size / dev->sector_size;
1079
if (dev->length <= 0) {
1080
ped_exception_throw (
1081
PED_EXCEPTION_ERROR,
1082
PED_EXCEPTION_CANCEL,
1083
_("The device %s has zero length, and can't possibly "
1084
"store a file system or partition table. Perhaps "
1085
"you selected the wrong device?"),
1087
goto error_close_dev;
1090
ped_device_close (dev);
1092
dev->bios_geom.cylinders = dev->length / 4 / 32;
1093
dev->bios_geom.heads = 4;
1094
dev->bios_geom.sectors = 32;
1095
dev->hw_geom = dev->bios_geom;
1096
dev->model = strdup ("");
1101
ped_device_close (dev);
1106
#if defined __s390__ || defined __s390x__
1108
init_dasd (PedDevice* dev, const char* model_name)
1110
struct stat dev_stat;
1111
struct hd_geometry geo;
1112
dasd_information_t dasd_info;
1114
if (!_device_stat (dev, &dev_stat))
1117
if (!ped_device_open (dev))
1120
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1122
PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
1124
_device_set_sector_size (dev);
1125
if (!dev->sector_size)
1126
goto error_close_dev;
1128
dev->length = _device_get_length (dev);
1130
goto error_close_dev;
1132
if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1133
dev->hw_geom.sectors = geo.sectors;
1134
dev->hw_geom.heads = geo.heads;
1135
dev->hw_geom.cylinders = dev->length
1136
/ (dev->hw_geom.heads * dev->hw_geom.sectors)
1137
/ (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1138
dev->bios_geom = dev->hw_geom;
1140
dev->bios_geom.sectors = 12;
1141
dev->bios_geom.heads = 15;
1142
dev->bios_geom.cylinders = dev->length
1143
/ (dev->hw_geom.heads * dev->hw_geom.sectors)
1144
/ (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1145
dev->hw_geom = dev->bios_geom;
1148
if (!ioctl(arch_specific->fd, BIODASDINFO, &dasd_info)) {
1149
arch_specific->devno = dasd_info.devno;
1151
arch_specific->devno = arch_specific->major * 256 +
1152
arch_specific->minor;
1155
dev->model = strdup (model_name);
1157
ped_device_close (dev);
1161
ped_device_close (dev);
1168
init_generic (PedDevice* dev, const char* model_name)
1170
struct stat dev_stat;
1171
PedExceptionOption ex_status;
1173
if (!_device_stat (dev, &dev_stat))
1176
if (!ped_device_open (dev))
1179
ped_exception_fetch_all ();
1180
if (_device_probe_geometry (dev)) {
1181
ped_exception_leave_all ();
1183
if (!_device_get_length (dev)) {
1184
ped_exception_catch ();
1185
ped_exception_leave_all ();
1186
goto error_close_dev;
1189
/* hack to allow use of files, for testing */
1190
ped_exception_catch ();
1191
ped_exception_leave_all ();
1193
ex_status = ped_exception_throw (
1194
PED_EXCEPTION_WARNING,
1195
PED_EXCEPTION_IGNORE_CANCEL,
1196
_("Unable to determine geometry of "
1197
"file/device %s. You should not use Parted "
1198
"unless you REALLY know what you're doing!"),
1200
switch (ex_status) {
1201
case PED_EXCEPTION_CANCEL:
1202
goto error_close_dev;
1204
case PED_EXCEPTION_UNHANDLED:
1205
ped_exception_catch ();
1206
case PED_EXCEPTION_IGNORE:
1209
PED_ASSERT (0, (void) 0);
1213
/* what should we stick in here? */
1214
dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1215
dev->bios_geom.cylinders = dev->length / 4 / 32;
1216
dev->bios_geom.heads = 4;
1217
dev->bios_geom.sectors = 32;
1218
dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1219
dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1222
dev->model = strdup (model_name);
1224
ped_device_close (dev);
1228
ped_device_close (dev);
1234
sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1236
*type = read_device_sysfs_file (dev, "type");
1237
*name = read_device_sysfs_file (dev, "name");
1245
init_sdmmc (PedDevice* dev)
1250
if (sdmmc_get_product_info (dev, &type, &name)) {
1251
snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1255
snprintf (id, sizeof(id) - 1, "%s",
1256
_("Generic SD/MMC Storage Card"));
1258
return init_generic(dev, id);
1262
linux_new (const char* path)
1265
LinuxSpecific* arch_specific;
1267
PED_ASSERT (path != NULL, return NULL);
1269
dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1273
dev->path = strdup (path);
1275
goto error_free_dev;
1278
= (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1279
if (!dev->arch_specific)
1280
goto error_free_path;
1281
arch_specific = LINUX_SPECIFIC (dev);
1282
arch_specific->dmtype = NULL;
1284
arch_specific->probe = NULL;
1285
arch_specific->topology = NULL;
1288
dev->open_count = 0;
1290
dev->external_mode = 0;
1292
dev->boot_dirty = 0;
1294
if (!_device_probe_type (dev))
1295
goto error_free_arch_specific;
1297
switch (dev->type) {
1298
case PED_DEVICE_IDE:
1299
if (!init_ide (dev))
1300
goto error_free_arch_specific;
1303
case PED_DEVICE_SCSI:
1304
if (!init_scsi (dev))
1305
goto error_free_arch_specific;
1308
case PED_DEVICE_DAC960:
1309
if (!init_generic (dev, _("DAC960 RAID controller")))
1310
goto error_free_arch_specific;
1313
case PED_DEVICE_SX8:
1314
if (!init_generic (dev, _("Promise SX8 SATA Device")))
1315
goto error_free_arch_specific;
1318
case PED_DEVICE_AOE:
1319
if (!init_generic (dev, _("ATA over Ethernet Device")))
1320
goto error_free_arch_specific;
1323
#if defined __s390__ || defined __s390x__
1324
case PED_DEVICE_DASD:
1325
if (!init_dasd (dev, _("IBM S390 DASD drive")))
1326
goto error_free_arch_specific;
1330
case PED_DEVICE_VIODASD:
1331
if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1332
goto error_free_arch_specific;
1335
case PED_DEVICE_CPQARRAY:
1336
if (!init_generic (dev, _("Compaq Smart Array")))
1337
goto error_free_arch_specific;
1340
case PED_DEVICE_ATARAID:
1341
if (!init_generic (dev, _("ATARAID Controller")))
1342
goto error_free_arch_specific;
1345
case PED_DEVICE_I2O:
1346
if (!init_generic (dev, _("I2O Controller")))
1347
goto error_free_arch_specific;
1350
case PED_DEVICE_UBD:
1351
if (!init_generic (dev, _("User-Mode Linux UBD")))
1352
goto error_free_arch_specific;
1355
case PED_DEVICE_FILE:
1356
if (!init_file (dev))
1357
goto error_free_arch_specific;
1363
if (arch_specific->dmtype == NULL
1364
|| asprintf(&type, _("Linux device-mapper (%s)"),
1365
arch_specific->dmtype) == -1)
1366
goto error_free_arch_specific;
1367
bool ok = init_generic (dev, type);
1370
goto error_free_arch_specific;
1374
case PED_DEVICE_XVD:
1375
if (!init_generic (dev, _("Xen Virtual Block Device")))
1376
goto error_free_arch_specific;
1379
case PED_DEVICE_UNKNOWN:
1380
if (!init_generic (dev, _("Unknown")))
1381
goto error_free_arch_specific;
1384
case PED_DEVICE_SDMMC:
1385
if (!init_sdmmc (dev))
1386
goto error_free_arch_specific;
1388
case PED_DEVICE_VIRTBLK:
1389
if (!init_generic(dev, _("Virtio Block Device")))
1390
goto error_free_arch_specific;
1394
if (!init_generic(dev, _("Linux Software RAID Array")))
1395
goto error_free_arch_specific;
1399
ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1400
PED_EXCEPTION_CANCEL,
1401
_("ped_device_new() Unsupported device type"));
1402
goto error_free_arch_specific;
1406
error_free_arch_specific:
1407
free (dev->arch_specific);
1417
linux_destroy (PedDevice* dev)
1419
LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
1420
void *p = arch_specific->dmtype;
1423
if (arch_specific->probe)
1424
blkid_free_probe(arch_specific->probe);
1427
free (dev->arch_specific);
1434
linux_is_busy (PedDevice* dev)
1439
if (_partition_is_mounted_by_path (dev->path))
1442
for (i = 0; i < 32; i++) {
1445
part_name = _device_get_part_path (dev, i);
1448
status = _partition_is_mounted_by_path (part_name);
1458
/* we need to flush the master device, and with kernel < 2.6 all the partition
1459
* devices, because there is no coherency between the caches with old kernels.
1460
* We should only flush unmounted partition devices, because:
1461
* - there is never a need to flush them (we're not doing IO there)
1462
* - flushing a device that is mounted causes unnecessary IO, and can
1463
* even screw journaling & friends up. Even cause oopsen!
1466
_flush_cache (PedDevice* dev)
1468
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1475
ioctl (arch_specific->fd, BLKFLSBUF);
1477
/* With linux-2.6.0 and newer, we're done. */
1481
for (i = 1; i < 16; i++) {
1485
name = _device_get_part_path (dev, i);
1488
if (!_partition_is_mounted_by_path (name)) {
1489
fd = open (name, WR_MODE, 0);
1491
ioctl (fd, BLKFLSBUF);
1493
if (fsync (fd) < 0 || close (fd) < 0)
1494
if (ped_exception_throw (
1495
PED_EXCEPTION_WARNING,
1496
PED_EXCEPTION_RETRY +
1497
PED_EXCEPTION_IGNORE,
1498
_("Error fsyncing/closing %s: %s"),
1499
name, strerror (errno))
1500
== PED_EXCEPTION_RETRY)
1509
linux_open (PedDevice* dev)
1511
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1514
arch_specific->fd = open (dev->path, RW_MODE);
1516
if (arch_specific->fd == -1) {
1517
char* rw_error_msg = strerror (errno);
1519
arch_specific->fd = open (dev->path, RD_MODE);
1521
if (arch_specific->fd == -1) {
1522
if (ped_exception_throw (
1523
PED_EXCEPTION_ERROR,
1524
PED_EXCEPTION_RETRY_CANCEL,
1525
_("Error opening %s: %s"),
1526
dev->path, strerror (errno))
1527
!= PED_EXCEPTION_RETRY) {
1533
ped_exception_throw (
1534
PED_EXCEPTION_WARNING,
1536
_("Unable to open %s read-write (%s). %s has "
1537
"been opened read-only."),
1538
dev->path, rw_error_msg, dev->path);
1545
/* With kernels < 2.6 flush cache for cache coherence issues */
1546
if (!_have_kern26())
1553
linux_refresh_open (PedDevice* dev)
1559
linux_close (PedDevice* dev)
1561
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1566
if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
1567
if (ped_exception_throw (
1568
PED_EXCEPTION_WARNING,
1569
PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
1570
_("Error fsyncing/closing %s: %s"),
1571
dev->path, strerror (errno))
1572
== PED_EXCEPTION_RETRY)
1578
linux_refresh_close (PedDevice* dev)
1585
#if SIZEOF_OFF_T < 8
1587
static _syscall5(int,_llseek,
1589
unsigned long, offset_high,
1590
unsigned long, offset_low,
1592
unsigned int, origin)
1595
llseek (unsigned int fd, loff_t offset, unsigned int whence)
1600
retval = _llseek(fd,
1601
((unsigned long long)offset) >> 32,
1602
((unsigned long long)offset) & 0xffffffff,
1605
return (retval==-1 ? (loff_t) retval : result);
1608
#endif /* SIZEOF_OFF_T < 8 */
1611
_device_seek (const PedDevice* dev, PedSector sector)
1613
LinuxSpecific* arch_specific;
1615
PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1616
PED_ASSERT (dev != NULL, return 0);
1617
PED_ASSERT (!dev->external_mode, return 0);
1619
arch_specific = LINUX_SPECIFIC (dev);
1621
#if SIZEOF_OFF_T < 8
1622
if (sizeof (off_t) < 8) {
1623
loff_t pos = (loff_t)(sector * dev->sector_size);
1624
return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1628
off_t pos = sector * dev->sector_size;
1629
return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1634
_read_lastoddsector (const PedDevice* dev, void* buffer)
1636
LinuxSpecific* arch_specific;
1637
struct blkdev_ioctl_param ioctl_param;
1639
PED_ASSERT(dev != NULL, return 0);
1640
PED_ASSERT(buffer != NULL, return 0);
1642
arch_specific = LINUX_SPECIFIC (dev);
1645
ioctl_param.block = 0; /* read the last sector */
1646
ioctl_param.content_length = dev->sector_size;
1647
ioctl_param.block_contents = buffer;
1649
if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1650
PedExceptionOption opt;
1651
opt = ped_exception_throw (
1652
PED_EXCEPTION_ERROR,
1653
PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1654
_("%s during read on %s"),
1655
strerror (errno), dev->path);
1657
if (opt == PED_EXCEPTION_CANCEL)
1659
if (opt == PED_EXCEPTION_RETRY)
1667
linux_read (const PedDevice* dev, void* buffer, PedSector start,
1670
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1671
PedExceptionOption ex_status;
1672
void* diobuf = NULL;
1674
PED_ASSERT (dev != NULL, return 0);
1675
PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1677
if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1678
/* Kludge. This is necessary to read/write the last
1679
block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1681
if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1682
&& start + count - 1 == dev->length - 1)
1683
return ped_device_read (dev, buffer, start, count - 1)
1684
&& _read_lastoddsector (
1685
dev, (char *) buffer + (count-1) * 512);
1688
if (_device_seek (dev, start))
1691
ex_status = ped_exception_throw (
1692
PED_EXCEPTION_ERROR,
1693
PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1694
_("%s during seek for read on %s"),
1695
strerror (errno), dev->path);
1697
switch (ex_status) {
1698
case PED_EXCEPTION_IGNORE:
1701
case PED_EXCEPTION_RETRY:
1704
case PED_EXCEPTION_UNHANDLED:
1705
ped_exception_catch ();
1706
case PED_EXCEPTION_CANCEL:
1709
PED_ASSERT (0, (void) 0);
1714
size_t read_length = count * dev->sector_size;
1715
if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1719
ssize_t status = read (arch_specific->fd, diobuf, read_length);
1721
memcpy(buffer, diobuf, status);
1722
if (status == (ssize_t) read_length)
1725
read_length -= status;
1726
buffer = (char *) buffer + status;
1730
ex_status = ped_exception_throw (
1731
PED_EXCEPTION_ERROR,
1732
PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1734
? _("end of file while reading %s")
1735
: _("%s during read on %s")),
1739
switch (ex_status) {
1740
case PED_EXCEPTION_IGNORE:
1744
case PED_EXCEPTION_RETRY:
1747
case PED_EXCEPTION_UNHANDLED:
1748
ped_exception_catch ();
1749
case PED_EXCEPTION_CANCEL:
1753
PED_ASSERT (0, (void) 0);
1764
_write_lastoddsector (PedDevice* dev, const void* buffer)
1766
LinuxSpecific* arch_specific;
1767
struct blkdev_ioctl_param ioctl_param;
1769
PED_ASSERT(dev != NULL, return 0);
1770
PED_ASSERT(buffer != NULL, return 0);
1772
arch_specific = LINUX_SPECIFIC (dev);
1775
ioctl_param.block = 0; /* write the last sector */
1776
ioctl_param.content_length = dev->sector_size;
1777
ioctl_param.block_contents = (void*) buffer;
1779
if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1780
PedExceptionOption opt;
1781
opt = ped_exception_throw (
1782
PED_EXCEPTION_ERROR,
1783
PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1784
_("%s during write on %s"),
1785
strerror (errno), dev->path);
1787
if (opt == PED_EXCEPTION_CANCEL)
1789
if (opt == PED_EXCEPTION_RETRY)
1797
linux_write (PedDevice* dev, const void* buffer, PedSector start,
1800
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1801
PedExceptionOption ex_status;
1805
PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1807
if (dev->read_only) {
1808
if (ped_exception_throw (
1809
PED_EXCEPTION_ERROR,
1810
PED_EXCEPTION_IGNORE_CANCEL,
1811
_("Can't write to %s, because it is opened read-only."),
1813
!= PED_EXCEPTION_IGNORE)
1819
if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1820
/* Kludge. This is necessary to read/write the last
1821
block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1823
if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1824
&& start + count - 1 == dev->length - 1)
1825
return ped_device_write (dev, buffer, start, count - 1)
1826
&& _write_lastoddsector (
1827
dev, ((char*) buffer
1828
+ (count-1) * dev->sector_size));
1831
if (_device_seek (dev, start))
1834
ex_status = ped_exception_throw (
1835
PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1836
_("%s during seek for write on %s"),
1837
strerror (errno), dev->path);
1839
switch (ex_status) {
1840
case PED_EXCEPTION_IGNORE:
1843
case PED_EXCEPTION_RETRY:
1846
case PED_EXCEPTION_UNHANDLED:
1847
ped_exception_catch ();
1848
case PED_EXCEPTION_CANCEL:
1851
PED_ASSERT (0, (void) 0);
1857
printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1858
dev->path, buffer, (int) start, (int) count);
1860
size_t write_length = count * dev->sector_size;
1862
if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1864
memcpy(diobuf, buffer, write_length);
1865
diobuf_start = diobuf;
1867
ssize_t status = write (arch_specific->fd, diobuf, write_length);
1868
if (status == write_length) break;
1870
write_length -= status;
1871
diobuf = (char *) diobuf + status;
1875
ex_status = ped_exception_throw (
1876
PED_EXCEPTION_ERROR,
1877
PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1878
_("%s during write on %s"),
1879
strerror (errno), dev->path);
1881
switch (ex_status) {
1882
case PED_EXCEPTION_IGNORE:
1886
case PED_EXCEPTION_RETRY:
1889
case PED_EXCEPTION_UNHANDLED:
1890
ped_exception_catch ();
1891
case PED_EXCEPTION_CANCEL:
1895
PED_ASSERT (0, (void) 0);
1900
#endif /* !READ_ONLY */
1904
/* returns the number of sectors that are ok.
1907
linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1909
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1914
PED_ASSERT(dev != NULL, return 0);
1916
if (!_device_seek (dev, start))
1919
if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1920
count * PED_SECTOR_SIZE_DEFAULT) != 0)
1923
for (done = 0; done < count; done += status / dev->sector_size) {
1924
status = read (arch_specific->fd, diobuf,
1925
(size_t) ((count-done) * dev->sector_size));
1927
memcpy(buffer, diobuf, status);
1937
_do_fsync (PedDevice* dev)
1939
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1941
PedExceptionOption ex_status;
1944
status = fsync (arch_specific->fd);
1945
if (status >= 0) break;
1947
ex_status = ped_exception_throw (
1948
PED_EXCEPTION_ERROR,
1949
PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1950
_("%s during write on %s"),
1951
strerror (errno), dev->path);
1953
switch (ex_status) {
1954
case PED_EXCEPTION_IGNORE:
1957
case PED_EXCEPTION_RETRY:
1960
case PED_EXCEPTION_UNHANDLED:
1961
ped_exception_catch ();
1962
case PED_EXCEPTION_CANCEL:
1965
PED_ASSERT (0, (void) 0);
1973
linux_sync (PedDevice* dev)
1975
PED_ASSERT (dev != NULL, return 0);
1976
PED_ASSERT (!dev->external_mode, return 0);
1980
if (!_do_fsync (dev))
1987
linux_sync_fast (PedDevice* dev)
1989
PED_ASSERT (dev != NULL, return 0);
1990
PED_ASSERT (!dev->external_mode, return 0);
1994
if (!_do_fsync (dev))
1996
/* no cache flush... */
2001
_compare_digit_state (char ch, int need_digit)
2003
return !!isdigit (ch) == need_digit;
2006
/* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
2007
* Motivation: accept devices looking like /dev/rd/c0d0, but
2008
* not looking like /dev/hda1 and /dev/rd/c0d0p1
2011
_match_rd_device (const char* name)
2016
/* exclude directory names from test */
2017
pos = strrchr(name, '/') ?: name;
2025
for (state = 0; state < 4; state++) {
2026
int want_digits = (state % 2 == 1);
2030
if (!_compare_digit_state (*pos, want_digits))
2033
} while (_compare_digit_state (*pos, want_digits));
2040
_probe_proc_partitions ()
2042
FILE* proc_part_file;
2043
int major, minor, size;
2045
char part_name [256];
2046
char dev_name [256];
2048
proc_part_file = fopen ("/proc/partitions", "r");
2049
if (!proc_part_file)
2052
if (fgets (buf, 256, proc_part_file) == NULL)
2055
if (fgets (buf, 256, proc_part_file) == NULL)
2058
while (fgets (buf, 512, proc_part_file)
2059
&& sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
2061
/* Heuristic for telling partitions and devices apart
2062
* Probably needs to be improved
2064
if (!_match_rd_device (part_name)
2065
&& isdigit (part_name [strlen (part_name) - 1]))
2068
strcpy (dev_name, "/dev/");
2069
strcat (dev_name, part_name);
2070
_ped_device_probe (dev_name);
2073
fclose (proc_part_file);
2083
_skip_entry (const char *name)
2086
static struct _entry entries[] = {
2087
{ ".", sizeof (".") - 1 },
2088
{ "..", sizeof ("..") - 1 },
2089
{ "dm-", sizeof ("dm-") - 1 },
2090
{ "loop", sizeof ("loop") - 1 },
2091
{ "ram", sizeof ("ram") - 1 },
2095
for (i = entries; i->name != 0; i++) {
2096
if (strncmp (name, i->name, i->len) == 0)
2107
struct dirent *dirent;
2108
char dev_name [256];
2111
if (!(blockdir = opendir ("/sys/block")))
2113
while ((dirent = readdir (blockdir))) {
2114
if (_skip_entry (dirent->d_name))
2117
if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2118
continue; /* device name too long! */
2120
strcpy (dev_name, "/dev/");
2121
strcat (dev_name, dirent->d_name);
2122
/* in /sys/block, '/'s are replaced with '!' or '.' */
2123
for (ptr = dev_name; *ptr != '\0'; ptr++) {
2124
if (*ptr == '!' || *ptr == '.')
2127
_ped_device_probe (dev_name);
2130
closedir (blockdir);
2135
_probe_standard_devices ()
2137
_ped_device_probe ("/dev/hda");
2138
_ped_device_probe ("/dev/hdb");
2139
_ped_device_probe ("/dev/hdc");
2140
_ped_device_probe ("/dev/hdd");
2141
_ped_device_probe ("/dev/hde");
2142
_ped_device_probe ("/dev/hdf");
2143
_ped_device_probe ("/dev/hdg");
2144
_ped_device_probe ("/dev/hdh");
2146
_ped_device_probe ("/dev/sda");
2147
_ped_device_probe ("/dev/sdb");
2148
_ped_device_probe ("/dev/sdc");
2149
_ped_device_probe ("/dev/sdd");
2150
_ped_device_probe ("/dev/sde");
2151
_ped_device_probe ("/dev/sdf");
2159
/* we should probe the standard devs too, even with /proc/partitions,
2160
* because /proc/partitions might return devfs stuff, and we might not
2161
* have devfs available
2163
_probe_standard_devices ();
2165
#ifdef ENABLE_DEVICE_MAPPER
2166
/* device-mapper devices aren't listed in /proc/partitions; or, if
2167
* they are, they're listed as dm-X. So, instead of relying on that,
2168
* we do our own checks.
2170
_probe_dm_devices ();
2173
/* /sys/block is more reliable and consistent; fall back to using
2174
* /proc/partitions if the former is unavailable, however.
2176
if (!_probe_sys_block ())
2177
_probe_proc_partitions ();
2181
_device_get_part_path (PedDevice* dev, int num)
2183
int path_len = strlen (dev->path);
2184
int result_len = path_len + 16;
2187
result = (char*) ped_malloc (result_len);
2191
/* Check for devfs-style /disc => /partN transformation
2192
unconditionally; the system might be using udev with devfs rules,
2193
and if not the test is harmless. */
2194
if (!strcmp (dev->path + path_len - 5, "/disc")) {
2195
/* replace /disc with /path%d */
2196
strcpy (result, dev->path);
2197
snprintf (result + path_len - 5, 16, "/part%d", num);
2198
} else if (dev->type == PED_DEVICE_DAC960
2199
|| dev->type == PED_DEVICE_CPQARRAY
2200
|| dev->type == PED_DEVICE_ATARAID
2201
|| isdigit (dev->path[path_len - 1]))
2202
snprintf (result, result_len, "%sp%d", dev->path, num);
2204
snprintf (result, result_len, "%s%d", dev->path, num);
2210
linux_partition_get_path (const PedPartition* part)
2212
return _device_get_part_path (part->disk->dev, part->num);
2216
_mount_table_search (const char* file_name, dev_t dev)
2218
struct stat part_stat;
2220
char part_name[512];
2223
file = fopen (file_name, "r");
2226
while (fgets (line, 512, file)) {
2227
if (sscanf (line, "%s", part_name) == 1
2228
&& stat (part_name, &part_stat) == 0) {
2229
if (part_stat.st_rdev == dev) {
2240
_partition_is_mounted_by_dev (dev_t dev)
2242
return _mount_table_search( "/proc/mounts", dev)
2243
|| _mount_table_search( "/proc/swaps", dev)
2244
|| _mount_table_search( "/etc/mtab", dev);
2248
_partition_is_mounted_by_path (const char *path)
2250
struct stat part_stat;
2251
if (stat (path, &part_stat) != 0)
2253
if (!S_ISBLK(part_stat.st_mode))
2255
return _partition_is_mounted_by_dev (part_stat.st_rdev);
2259
_partition_is_mounted (const PedPartition *part)
2263
if (!ped_partition_is_active (part))
2265
part_name = _device_get_part_path (part->disk->dev, part->num);
2268
status = _partition_is_mounted_by_path (part_name);
2276
_has_partitions (const PedDisk* disk)
2278
PED_ASSERT(disk != NULL, return 0);
2280
/* Some devices can't be partitioned. */
2281
if (!strcmp (disk->type->name, "loop"))
2288
linux_partition_is_busy (const PedPartition* part)
2292
PED_ASSERT (part != NULL, return 0);
2294
if (_partition_is_mounted (part))
2296
if (part->type == PED_PARTITION_EXTENDED) {
2297
for (walk = part->part_list; walk; walk = walk->next) {
2298
if (linux_partition_is_busy (walk))
2306
_blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
2308
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2309
struct blkpg_ioctl_arg ioctl_arg;
2312
ioctl_arg.flags = 0;
2313
ioctl_arg.datalen = sizeof (struct blkpg_partition);
2314
ioctl_arg.data = (void*) part;
2316
return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
2320
_blkpg_add_partition (PedDisk* disk, const PedPartition *part)
2322
struct blkpg_partition linux_part;
2323
const char* vol_name;
2326
PED_ASSERT(disk != NULL, return 0);
2327
PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0,
2330
if (!_has_partitions (disk))
2333
if (ped_disk_type_check_feature (disk->type,
2334
PED_DISK_TYPE_PARTITION_NAME))
2335
vol_name = ped_partition_get_name (part);
2339
dev_name = _device_get_part_path (disk->dev, part->num);
2343
memset (&linux_part, 0, sizeof (linux_part));
2344
linux_part.start = part->geom.start * disk->dev->sector_size;
2345
/* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
2346
if (part->type & PED_PARTITION_EXTENDED)
2347
linux_part.length = part->geom.length == 1 ? 512 : 1024;
2349
linux_part.length = part->geom.length * disk->dev->sector_size;
2350
linux_part.pno = part->num;
2351
strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
2353
strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
2357
if (!_blkpg_part_command (disk->dev, &linux_part,
2358
BLKPG_ADD_PARTITION)) {
2359
return ped_exception_throw (
2360
PED_EXCEPTION_ERROR,
2361
PED_EXCEPTION_IGNORE_CANCEL,
2362
_("Error informing the kernel about modifications to "
2363
"partition %s -- %s. This means Linux won't know "
2364
"about any changes you made to %s until you reboot "
2365
"-- so you shouldn't mount it or use it in any way "
2366
"before rebooting."),
2370
== PED_EXCEPTION_IGNORE;
2377
_blkpg_remove_partition (PedDisk* disk, int n)
2379
struct blkpg_partition linux_part;
2381
if (!_has_partitions (disk))
2384
memset (&linux_part, 0, sizeof (linux_part));
2386
return _blkpg_part_command (disk->dev, &linux_part,
2387
BLKPG_DEL_PARTITION);
2391
* The number of partitions that a device can have depends on the kernel.
2392
* If we don't find this value in /sys/block/DEV/range, we will use our own
2396
_device_get_partition_range(PedDevice* dev)
2403
r = snprintf(path, sizeof(path), "/sys/block/%s/range",
2404
last_component(dev->path));
2405
if (r < 0 || r >= sizeof(path))
2406
return MAX_NUM_PARTS;
2408
fp = fopen(path, "r");
2410
return MAX_NUM_PARTS;
2412
ok = fscanf(fp, "%d", &range) == 1;
2415
/* (range <= 0) is none sense.*/
2416
return ok && range > 0 ? range : MAX_NUM_PARTS;
2420
* Sync the partition table in two step process:
2421
* 1. Remove all of the partitions from the kernel's tables, but do not attempt
2422
* removal of any partition for which the corresponding ioctl call fails.
2423
* 2. Add all the partitions that we hold in disk, throwing a warning
2424
* if we cannot because step 1 failed to remove it and it is not being
2425
* added back with the same start and length.
2427
* To achieve this two step process we must calculate the minimum number of
2428
* maximum possible partitions between what linux supports and what the label
2429
* type supports. EX:
2431
* number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables)
2434
_disk_sync_part_table (PedDisk* disk)
2436
PED_ASSERT(disk != NULL, return 0);
2437
PED_ASSERT(disk->dev != NULL, return 0);
2440
/* lpn = largest partition number. */
2441
if (ped_disk_get_max_supported_partition_count(disk, &lpn))
2442
lpn = PED_MIN(lpn, _device_get_partition_range(disk->dev));
2444
lpn = _device_get_partition_range(disk->dev);
2446
/* Its not possible to support largest_partnum < 0.
2447
* largest_partnum == 0 would mean does not support partitions.
2452
int *ok = calloc (lpn, sizeof *ok);
2455
int *errnums = ped_malloc(sizeof(int) * lpn);
2459
/* Attempt to remove each and every partition, retrying for
2460
up to max_sleep_seconds upon any failure due to EBUSY. */
2461
unsigned int sleep_microseconds = 10000;
2462
unsigned int max_sleep_seconds = 1;
2463
unsigned int n_sleep = (max_sleep_seconds
2464
* 1000000 / sleep_microseconds);
2466
for (i = 0; i < n_sleep; i++) {
2468
usleep (sleep_microseconds);
2471
for (j = 0; j < lpn; j++) {
2473
ok[j] = _blkpg_remove_partition (disk, j + 1);
2475
if (!ok[j] && errnums[j] == EBUSY)
2483
for (i = 1; i <= lpn; i++) {
2484
const PedPartition *part = ped_disk_get_partition (disk, i);
2486
if (!ok[i - 1] && errnums[i - 1] == EBUSY) {
2487
struct hd_geometry geom;
2488
unsigned long long length = 0;
2489
/* get start and length of existing partition */
2490
char *dev_name = _device_get_part_path (disk->dev, i);
2493
int fd = open (dev_name, O_RDONLY);
2495
|| ioctl (fd, HDIO_GETGEO, &geom)
2496
|| ioctl (fd, BLKGETSIZE64, &length)) {
2497
ped_exception_throw (
2499
PED_EXCEPTION_CANCEL,
2500
_("Unable to determine the size and length of %s."),
2508
length /= disk->dev->sector_size;
2510
if (geom.start == part->geom.start
2511
&& length == part->geom.length)
2513
/* If the new partition is unchanged and the
2514
existing one was not removed because it was
2515
in use, then reset the error flag and do not
2516
try to add it since it is already there. */
2520
/* add the (possibly modified or new) partition */
2521
if (!_blkpg_add_partition (disk, part)) {
2522
ped_exception_throw (
2523
PED_EXCEPTION_ERROR,
2524
PED_EXCEPTION_RETRY_CANCEL,
2525
_("Failed to add partition %d (%s)"),
2526
i, strerror (errno));
2532
char *bad_part_list = NULL;
2533
/* now warn about any errors */
2534
for (i = 1; i <= lpn; i++) {
2535
if (ok[i - 1] || errnums[i - 1] == ENXIO)
2537
if (bad_part_list == NULL) {
2538
bad_part_list = malloc (lpn * 5);
2541
bad_part_list[0] = 0;
2543
sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i);
2545
if (bad_part_list == NULL)
2548
bad_part_list[strlen (bad_part_list) - 2] = 0;
2549
if (ped_exception_throw (
2550
PED_EXCEPTION_ERROR,
2551
PED_EXCEPTION_IGNORE_CANCEL,
2552
_("Partition(s) %s on %s have been written, but we have "
2553
"been unable to inform the kernel of the change, "
2554
"probably because it/they are in use. As a result, "
2555
"the old partition(s) will remain in use. You "
2556
"should reboot now before making further changes."),
2557
bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE)
2559
free (bad_part_list);
2567
#ifdef ENABLE_DEVICE_MAPPER
2569
_dm_remove_map_name(char *name)
2571
struct dm_task *task = NULL;
2574
task = dm_task_create(DM_DEVICE_REMOVE);
2578
dm_task_set_name (task, name);
2580
rc = dm_task_run(task);
2581
dm_task_update_nodes();
2582
dm_task_destroy(task);
2590
_dm_is_part (struct dm_info *this, char *name)
2592
struct dm_task* task = NULL;
2593
struct dm_info* info = alloca(sizeof *info);
2594
struct dm_deps* deps = NULL;
2598
task = dm_task_create(DM_DEVICE_DEPS);
2602
dm_task_set_name(task, name);
2603
if (!dm_task_run(task))
2606
memset(info, '\0', sizeof *info);
2607
dm_task_get_info(task, info);
2611
deps = dm_task_get_deps(task);
2615
for (i = 0; i < deps->count; i++) {
2616
unsigned int ma = major(deps->device[i]),
2617
mi = minor(deps->device[i]);
2619
if (ma == this->major && mi == this->minor)
2624
dm_task_destroy(task);
2629
_dm_remove_parts (PedDevice* dev)
2631
struct dm_task* task = NULL;
2632
struct dm_info* info = alloca(sizeof *info);
2633
struct dm_names* names = NULL;
2634
unsigned int next = 0;
2636
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2638
task = dm_task_create(DM_DEVICE_LIST);
2642
if (!dm_task_set_major_minor (task, arch_specific->major,
2643
arch_specific->minor, 0))
2646
if (!dm_task_run(task))
2649
memset(info, '\0', sizeof *info);
2650
dm_task_get_info(task, info);
2654
names = dm_task_get_names(task);
2660
names = (void *) ((char *) names + next);
2662
if (_dm_is_part(info, names->name))
2663
rc += _dm_remove_map_name(names->name);
2668
dm_task_update_nodes();
2669
dm_task_destroy(task);
2676
dm_task_destroy(task);
2677
ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2678
_("parted was unable to re-read the partition "
2679
"table on %s (%s). This means Linux won't know "
2680
"anything about the modifications you made. "),
2681
dev->path, strerror (errno));
2686
_dm_add_partition (PedDisk* disk, PedPartition* part)
2688
char* vol_name = NULL;
2689
const char* dev_name = NULL;
2690
char* params = NULL;
2691
LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
2693
if (!_has_partitions(disk))
2696
/* Get map name from devicemapper */
2697
struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
2701
if (!dm_task_set_major_minor (task, arch_specific->major,
2702
arch_specific->minor, 0))
2705
if (!dm_task_run(task))
2708
dev_name = dm_task_get_name (task);
2710
if (isdigit (dev_name[strlen (dev_name) - 1])) {
2711
if (asprintf (&vol_name, "%sp%d", dev_name, part->num) == -1)
2713
} else if (asprintf (&vol_name, "%s%d", dev_name, part->num) == -1)
2716
/* Caution: dm_task_destroy frees dev_name. */
2717
dm_task_destroy (task);
2720
if (asprintf (¶ms, "%d:%d %lld", arch_specific->major,
2721
arch_specific->minor, part->geom.start) == -1)
2724
task = dm_task_create (DM_DEVICE_CREATE);
2728
dm_task_set_name (task, vol_name);
2729
dm_task_add_target (task, 0, part->geom.length,
2731
if (dm_task_run (task)) {
2732
//printf("0 %ld linear %s\n", part->geom.length, params);
2733
dm_task_update_nodes();
2734
dm_task_destroy(task);
2739
_dm_remove_map_name(vol_name);
2742
dm_task_update_nodes();
2744
dm_task_destroy (task);
2751
_dm_reread_part_table (PedDisk* disk)
2753
int largest_partnum = ped_disk_get_last_partition_num (disk);
2754
if (largest_partnum <= 0)
2758
int last = PED_MIN (largest_partnum, 16);
2762
if (!_dm_remove_parts(disk->dev))
2765
for (i = 1; i <= last; i++) {
2768
part = ped_disk_get_partition (disk, i);
2772
if (!_dm_add_partition (disk, part))
2782
static int have_blkpg = -1;
2785
if (have_blkpg != -1)
2788
kver = _get_linux_version();
2789
return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
2792
/* Return nonzero upon success, 0 if something fails. */
2794
linux_disk_commit (PedDisk* disk)
2796
if (!_has_partitions (disk))
2799
#ifdef ENABLE_DEVICE_MAPPER
2800
if (disk->dev->type == PED_DEVICE_DM)
2801
return _dm_reread_part_table (disk);
2803
if (disk->dev->type != PED_DEVICE_FILE) {
2804
/* The ioctl() command BLKPG_ADD_PARTITION does not notify
2805
* the devfs system; consequently, /proc/partitions will not
2806
* be up to date, and the proper links in /dev are not
2807
* created. Therefore, if using DevFS, we must get the kernel
2808
* to re-read and grok the partition table.
2810
/* Work around kernel dasd problem so we really do BLKRRPART */
2812
if (disk->dev->type != PED_DEVICE_DASD && _have_blkpg ()) {
2813
if (!_disk_sync_part_table (disk))
2824
static PedAlignment*
2825
linux_get_minimum_alignment(const PedDevice *dev)
2827
blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2831
if (blkid_topology_get_minimum_io_size(tp) == 0)
2832
return ped_alignment_new(
2833
blkid_topology_get_alignment_offset(tp) /
2835
dev->phys_sector_size / dev->sector_size);
2837
return ped_alignment_new(
2838
blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2839
blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
2842
static PedAlignment*
2843
linux_get_optimum_alignment(const PedDevice *dev)
2845
blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2849
/* If optimal_io_size is 0 _and_ alignment_offset is 0 _and_
2850
minimum_io_size is a power of 2 then go with the device.c default */
2851
unsigned long minimum_io_size = blkid_topology_get_minimum_io_size(tp);
2852
if (blkid_topology_get_optimal_io_size(tp) == 0 &&
2853
blkid_topology_get_alignment_offset(tp) == 0 &&
2854
(minimum_io_size & (minimum_io_size - 1)) == 0)
2857
/* If optimal_io_size is 0 and we don't meet the other criteria
2858
for using the device.c default, return the minimum alignment. */
2859
if (blkid_topology_get_optimal_io_size(tp) == 0)
2860
return linux_get_minimum_alignment(dev);
2862
return ped_alignment_new(
2863
blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2864
blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
2868
static PedDeviceArchOps linux_dev_ops = {
2870
destroy: linux_destroy,
2871
is_busy: linux_is_busy,
2873
refresh_open: linux_refresh_open,
2875
refresh_close: linux_refresh_close,
2880
sync_fast: linux_sync_fast,
2881
probe_all: linux_probe_all,
2883
get_minimum_alignment: linux_get_minimum_alignment,
2884
get_optimum_alignment: linux_get_optimum_alignment,
2888
PedDiskArchOps linux_disk_ops = {
2889
partition_get_path: linux_partition_get_path,
2890
partition_is_busy: linux_partition_is_busy,
2891
disk_commit: linux_disk_commit
2894
PedArchitecture ped_linux_arch = {
2895
dev_ops: &linux_dev_ops,
2896
disk_ops: &linux_disk_ops