1 /* libparted - a library for manipulating disk partitions
2 Copyright (C) 1999-2011 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>
44 #ifdef ENABLE_DEVICE_MAPPER
45 #include <libdevmapper.h>
48 #include "../architecture.h"
54 # define _(String) dgettext (PACKAGE, String)
56 # define _(String) (String)
57 #endif /* ENABLE_NLS */
59 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
62 #define __NR__llseek 140
65 #ifndef SCSI_IOCTL_SEND_COMMAND
66 #define SCSI_IOCTL_SEND_COMMAND 1
69 /* from <linux/hdreg.h> */
70 #define HDIO_GETGEO 0x0301 /* get device geometry */
71 #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
73 #define RD_MODE (O_RDONLY)
74 #define WR_MODE (O_WRONLY)
75 #define RW_MODE (O_RDWR)
79 unsigned char sectors;
80 unsigned short cylinders;
84 struct ata7_sectinfo {
91 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
93 unsigned short config; /* lots of obsolete bit flags */
94 unsigned short cyls; /* "physical" cyls */
95 unsigned short reserved2; /* reserved (word 2) */
96 unsigned short heads; /* "physical" heads */
97 unsigned short track_bytes; /* unformatted bytes per track */
98 unsigned short sector_bytes; /* unformatted bytes per sector */
99 unsigned short sectors; /* "physical" sectors per track */
100 unsigned short vendor0; /* vendor unique */
101 unsigned short vendor1; /* vendor unique */
102 unsigned short vendor2; /* vendor unique */
103 unsigned char serial_no[20]; /* 0 = not_specified */
104 unsigned short buf_type;
105 unsigned short buf_size; /* 512 byte increments;
107 unsigned short ecc_bytes; /* for r/w long cmds;
109 unsigned char fw_rev[8]; /* 0 = not_specified */
110 char model[40]; /* 0 = not_specified */
111 unsigned char max_multsect; /* 0=not_implemented */
112 unsigned char vendor3; /* vendor unique */
113 unsigned short dword_io; /* 0=not_implemented; 1=implemented */
114 unsigned char vendor4; /* vendor unique */
115 unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
117 unsigned short reserved50; /* reserved (word 50) */
118 unsigned char vendor5; /* vendor unique */
119 unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
120 unsigned char vendor6; /* vendor unique */
121 unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
122 unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
123 unsigned short cur_cyls; /* logical cylinders */
124 unsigned short cur_heads; /* logical heads */
125 unsigned short cur_sectors; /* logical sectors per track */
126 unsigned short cur_capacity0; /* logical total sectors on drive */
127 unsigned short cur_capacity1; /* (2 words, misaligned int) */
128 unsigned char multsect; /* current multiple sector count */
129 unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
130 unsigned int lba_capacity; /* total number of sectors */
131 unsigned short dma_1word; /* single-word dma info */
132 unsigned short dma_mword; /* multiple-word dma info */
133 unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
134 unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
135 unsigned short eide_dma_time; /* recommended mword dma cycle
137 unsigned short eide_pio; /* min cycle time (ns), no IORDY */
138 unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
139 unsigned short words69_70[2]; /* reserved words 69-70 */
140 /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
141 unsigned short words71_74[4]; /* reserved words 71-74 */
142 unsigned short queue_depth; /* */
143 unsigned short words76_79[4]; /* reserved words 76-79 */
144 unsigned short major_rev_num; /* */
145 unsigned short minor_rev_num; /* */
146 unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
148 unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
149 unsigned short cfsse; /* command set-feature supported
151 unsigned short cfs_enable_1; /* command set-feature enabled */
152 unsigned short cfs_enable_2; /* command set-feature enabled */
153 unsigned short csf_default; /* command set-feature default */
154 unsigned short dma_ultra; /* */
155 unsigned short word89; /* reserved (word 89) */
156 unsigned short word90; /* reserved (word 90) */
157 unsigned short CurAPMvalues; /* current APM values */
158 unsigned short word92; /* reserved (word 92) */
159 unsigned short hw_config; /* hardware config */
160 unsigned short words94_105[12];/* reserved words 94-105 */
161 struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
163 unsigned short words107_116[10];/* reserved words 107-116 */
164 unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
165 unsigned short words119_125[7];/* reserved words 119-125 */
166 unsigned short last_lun; /* reserved (word 126) */
167 unsigned short word127; /* reserved (word 127) */
168 unsigned short dlf; /* device lock function
170 * 8 security level 1:max 0:high
179 unsigned short csfo; /* current set features options
186 unsigned short words130_155[26];/* reserved vendor words 130-155 */
187 unsigned short word156;
188 unsigned short words157_159[3]; /* reserved vendor words 157-159 */
189 unsigned short words160_255[95];/* reserved words 160-255 */
192 /* from <linux/fs.h> */
193 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
194 #define BLKGETSIZE _IO(0x12,96) /* return device size */
195 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
196 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
197 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
198 #define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
200 /* return device size in bytes (u64 *arg) */
201 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
203 struct blkdev_ioctl_param {
205 size_t content_length;
206 char * block_contents;
209 /* from <linux/major.h> */
211 #define IDE1_MAJOR 22
212 #define IDE2_MAJOR 33
213 #define IDE3_MAJOR 34
214 #define IDE4_MAJOR 56
215 #define IDE5_MAJOR 57
216 #define SCSI_CDROM_MAJOR 11
217 #define SCSI_DISK0_MAJOR 8
218 #define SCSI_DISK1_MAJOR 65
219 #define SCSI_DISK2_MAJOR 66
220 #define SCSI_DISK3_MAJOR 67
221 #define SCSI_DISK4_MAJOR 68
222 #define SCSI_DISK5_MAJOR 69
223 #define SCSI_DISK6_MAJOR 70
224 #define SCSI_DISK7_MAJOR 71
225 #define SCSI_DISK8_MAJOR 128
226 #define SCSI_DISK9_MAJOR 129
227 #define SCSI_DISK10_MAJOR 130
228 #define SCSI_DISK11_MAJOR 131
229 #define SCSI_DISK12_MAJOR 132
230 #define SCSI_DISK13_MAJOR 133
231 #define SCSI_DISK14_MAJOR 134
232 #define SCSI_DISK15_MAJOR 135
233 #define COMPAQ_SMART2_MAJOR 72
234 #define COMPAQ_SMART2_MAJOR1 73
235 #define COMPAQ_SMART2_MAJOR2 74
236 #define COMPAQ_SMART2_MAJOR3 75
237 #define COMPAQ_SMART2_MAJOR4 76
238 #define COMPAQ_SMART2_MAJOR5 77
239 #define COMPAQ_SMART2_MAJOR6 78
240 #define COMPAQ_SMART2_MAJOR7 79
241 #define COMPAQ_SMART_MAJOR 104
242 #define COMPAQ_SMART_MAJOR1 105
243 #define COMPAQ_SMART_MAJOR2 106
244 #define COMPAQ_SMART_MAJOR3 107
245 #define COMPAQ_SMART_MAJOR4 108
246 #define COMPAQ_SMART_MAJOR5 109
247 #define COMPAQ_SMART_MAJOR6 110
248 #define COMPAQ_SMART_MAJOR7 111
249 #define DAC960_MAJOR 48
250 #define ATARAID_MAJOR 114
251 #define I2O_MAJOR1 80
252 #define I2O_MAJOR2 81
253 #define I2O_MAJOR3 82
254 #define I2O_MAJOR4 83
255 #define I2O_MAJOR5 84
256 #define I2O_MAJOR6 85
257 #define I2O_MAJOR7 86
258 #define I2O_MAJOR8 87
260 #define DASD_MAJOR 94
261 #define VIODASD_MAJOR 112
262 #define AOE_MAJOR 152
263 #define SX8_MAJOR1 160
264 #define SX8_MAJOR2 161
265 #define XVD_MAJOR 202
266 #define SDMMC_MAJOR 179
270 #define SCSI_BLK_MAJOR(M) ( \
271 (M) == SCSI_DISK0_MAJOR \
272 || (M) == SCSI_CDROM_MAJOR \
273 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) \
274 || ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
276 /* Maximum number of partitions supported by linux. */
277 #define MAX_NUM_PARTS 64
279 static char* _device_get_part_path (PedDevice* dev, int num);
280 static int _partition_is_mounted_by_path (const char* path);
283 _read_fd (int fd, char **buf)
286 size_t size = PROC_DEVICES_BUFSIZ;
289 *buf = malloc (size * sizeof (char));
295 p = &(*buf) [filesize];
296 s = read (fd, p, PROC_DEVICES_BUFSIZ);
297 /* exit if there is an error or EOF is reached */
302 char *new_buf = realloc (*buf, size);
303 if (new_buf == NULL) {
304 int saved_errno = errno;
312 if (filesize == 0 && s < 0) {
317 char *new_buf = realloc (*buf, filesize + 1);
318 if (new_buf == NULL) {
319 int saved_errno = errno;
325 (*buf)[filesize] = '\0';
332 _major_type_in_devices (int major, const char* type)
341 fd = open ("/proc/devices", O_RDONLY);
345 if (_read_fd(fd, &buf) < 0) {
351 end = strchr(line, '\n');
360 if (!strncmp(line, "Block devices:", 14))
365 name = strrchr(line, ' ');
366 if (!name || strcmp(name+1, type))
369 maj = strtol(line, &name, 10);
379 end = strchr(line, '\n');
387 _is_ide_major (int major)
404 _is_cpqarray_major (int major)
406 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
407 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
411 _is_i2o_major (int major)
413 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
417 _is_sx8_major (int major)
419 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
423 _is_virtblk_major (int major)
425 return _major_type_in_devices (major, "virtblk");
428 #ifdef ENABLE_DEVICE_MAPPER
430 _is_dm_major (int major)
432 return _major_type_in_devices (major, "device-mapper");
436 _dm_maptype (PedDevice *dev)
438 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
440 uint64_t start, length;
441 char *target_type = NULL;
444 const char* dev_dir = getenv ("DM_DEV_DIR");
446 if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
449 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
452 if (!dm_task_set_major_minor(dmt, arch_specific->major,
453 arch_specific->minor, 0))
456 dm_task_no_open_count(dmt);
458 if (!dm_task_run(dmt))
461 dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms);
463 arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
464 if (arch_specific->dmtype == NULL)
468 dm_task_destroy(dmt);
478 char buf [512]; /* readdir(3) claims d_name[256] */
481 mapper_dir = opendir ("/dev/mapper");
485 /* Search the /dev/mapper directory for devices w/ the same major
486 * number that was returned from _probe_lvm_major().
488 while ((dent = readdir (mapper_dir))) {
489 if (strcmp (dent->d_name, ".") == 0 ||
490 strcmp (dent->d_name, "..") == 0)
493 snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
495 if (stat (buf, &st) != 0)
498 if (_is_dm_major(major(st.st_rdev)))
499 _ped_device_probe (buf);
501 closedir (mapper_dir);
508 _device_stat (PedDevice* dev, struct stat * dev_stat)
510 PED_ASSERT (dev != NULL);
511 PED_ASSERT (!dev->external_mode);
514 if (!stat (dev->path, dev_stat)) {
517 if (ped_exception_throw (
519 PED_EXCEPTION_RETRY_CANCEL,
520 _("Could not stat device %s - %s."),
523 != PED_EXCEPTION_RETRY)
530 _device_probe_type (PedDevice* dev)
532 struct stat dev_stat;
535 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
537 if (!_device_stat (dev, &dev_stat))
540 if (!S_ISBLK(dev_stat.st_mode)) {
541 dev->type = PED_DEVICE_FILE;
545 arch_specific->major = dev_major = major (dev_stat.st_rdev);
546 arch_specific->minor = dev_minor = minor (dev_stat.st_rdev);
548 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
549 dev->type = PED_DEVICE_SCSI;
550 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
551 dev->type = PED_DEVICE_IDE;
552 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
553 dev->type = PED_DEVICE_DAC960;
554 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
555 dev->type = PED_DEVICE_ATARAID;
556 } else if (dev_major == AOE_MAJOR && (dev_minor % 0x10 == 0)) {
557 dev->type = PED_DEVICE_AOE;
558 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
559 dev->type = PED_DEVICE_DASD;
560 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
561 dev->type = PED_DEVICE_VIODASD;
562 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
563 dev->type = PED_DEVICE_SX8;
564 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
565 dev->type = PED_DEVICE_I2O;
566 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
567 dev->type = PED_DEVICE_CPQARRAY;
568 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
569 dev->type = PED_DEVICE_UBD;
570 #ifdef ENABLE_DEVICE_MAPPER
571 } else if (_is_dm_major(dev_major)) {
572 dev->type = PED_DEVICE_DM;
573 if (_dm_maptype(dev)) {
574 ped_exception_throw (
576 PED_EXCEPTION_CANCEL,
577 _("Unable to determine the dm type of %s."),
581 } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
582 dev->type = PED_DEVICE_XVD;
583 } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
584 dev->type = PED_DEVICE_SDMMC;
585 } else if (_is_virtblk_major(dev_major)) {
586 dev->type = PED_DEVICE_VIRTBLK;
587 } else if (dev_major == LOOP_MAJOR) {
588 dev->type = PED_DEVICE_FILE;
589 } else if (dev_major == MD_MAJOR) {
590 dev->type = PED_DEVICE_MD;
592 dev->type = PED_DEVICE_UNKNOWN;
599 _get_linux_version ()
601 static int kver = -1;
613 if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
616 return kver = KERNEL_VERSION (major, minor, teeny);
622 static int have_kern26 = -1;
625 if (have_kern26 != -1)
628 kver = _get_linux_version();
629 return have_kern26 = kver >= KERNEL_VERSION (2,6,0) ? 1 : 0;
634 get_blkid_topology (LinuxSpecific *arch_specific)
636 arch_specific->probe = blkid_new_probe ();
637 if (!arch_specific->probe)
640 if (blkid_probe_set_device(arch_specific->probe,
641 arch_specific->fd, 0, 0))
644 arch_specific->topology =
645 blkid_probe_get_topology(arch_specific->probe);
650 _device_set_sector_size (PedDevice* dev)
652 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
655 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
656 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
658 PED_ASSERT (dev->open_count);
660 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
661 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
665 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
666 ped_exception_throw (
667 PED_EXCEPTION_WARNING,
669 _("Could not determine sector size for %s: %s.\n"
670 "Using the default sector size (%lld)."),
671 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
673 dev->sector_size = (long long)sector_size;
674 dev->phys_sector_size = dev->sector_size;
678 get_blkid_topology(arch_specific);
679 if (!arch_specific->topology) {
680 dev->phys_sector_size = 0;
682 dev->phys_sector_size =
683 blkid_topology_get_physical_sector_size(
684 arch_specific->topology);
686 if (dev->phys_sector_size == 0) {
687 ped_exception_throw (
688 PED_EXCEPTION_WARNING,
690 _("Could not determine physical sector size for %s.\n"
691 "Using the logical sector size (%lld)."),
692 dev->path, dev->sector_size);
693 dev->phys_sector_size = dev->sector_size;
697 #if defined __s390__ || defined __s390x__
698 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
699 if (dev->type == PED_DEVICE_DASD) {
700 arch_specific->real_sector_size = dev->sector_size;
701 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
707 _kernel_has_blkgetsize64(void)
709 int version = _get_linux_version();
711 if (version >= KERNEL_VERSION (2,5,4)) return 1;
712 if (version < KERNEL_VERSION (2,5,0) &&
713 version >= KERNEL_VERSION (2,4,18)) return 1;
717 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
719 _device_get_length (PedDevice* dev)
722 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
724 const char* test_str;
728 PED_ASSERT (dev->open_count > 0);
729 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
731 test_str = getenv ("PARTED_TEST_DEVICE_LENGTH");
733 && xstrtoll (test_str, NULL, 10, &test_size, NULL) == LONGINT_OK)
736 if (_kernel_has_blkgetsize64()) {
737 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
738 return bytes / dev->sector_size;
742 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
743 ped_exception_throw (
745 PED_EXCEPTION_CANCEL,
746 _("Unable to determine the size of %s (%s)."),
756 _device_probe_geometry (PedDevice* dev)
758 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
759 struct stat dev_stat;
760 struct hd_geometry geometry;
762 if (!_device_stat (dev, &dev_stat))
764 PED_ASSERT (S_ISBLK (dev_stat.st_mode));
766 _device_set_sector_size (dev);
768 dev->length = _device_get_length (dev);
772 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
773 * still use it in 2.4.x, but this is contentious. Perhaps we should
775 dev->bios_geom.sectors = 63;
776 dev->bios_geom.heads = 255;
777 dev->bios_geom.cylinders
778 = dev->length / (63 * 255);
780 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
781 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
782 && geometry.sectors && geometry.heads) {
783 dev->hw_geom.sectors = geometry.sectors;
784 dev->hw_geom.heads = geometry.heads;
785 dev->hw_geom.cylinders
786 = dev->length / (dev->hw_geom.heads
787 * dev->hw_geom.sectors);
789 dev->hw_geom = dev->bios_geom;
796 strip_name(char* str)
801 for (i = 0; str[i] != 0; i++) {
802 if (!isspace (str[i])
803 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
813 init_ide (PedDevice* dev)
815 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
816 struct stat dev_stat;
817 struct hd_driveid hdi;
818 PedExceptionOption ex_status;
820 int sector_multiplier = 0;
822 if (!_device_stat (dev, &dev_stat))
825 if (!ped_device_open (dev))
828 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
829 ex_status = ped_exception_throw (
830 PED_EXCEPTION_WARNING,
831 PED_EXCEPTION_IGNORE_CANCEL,
832 _("Could not get identity of device %s - %s"),
833 dev->path, strerror (errno));
835 case PED_EXCEPTION_CANCEL:
836 goto error_close_dev;
838 case PED_EXCEPTION_UNHANDLED:
839 ped_exception_catch ();
840 case PED_EXCEPTION_IGNORE:
841 dev->model = strdup(_("Generic IDE"));
848 /* hdi.model is not guaranteed to be NULL terminated */
849 memcpy (hdi_buf, hdi.model, 40);
851 dev->model = strip_name (hdi_buf);
853 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
854 sector_multiplier = hdi.ata7_sectinfo.multiplier;
856 sector_multiplier = 1;
858 if (sector_multiplier != 1) {
859 ex_status = ped_exception_throw (
860 PED_EXCEPTION_WARNING,
861 PED_EXCEPTION_IGNORE_CANCEL,
862 _("Device %s has multiple (%d) logical sectors "
863 "per physical sector.\n"
864 "GNU Parted supports this EXPERIMENTALLY for "
865 "some special disk label/file system "
866 "combinations, e.g. GPT and ext2/3.\n"
867 "Please consult the web site for up-to-date "
869 dev->path, sector_multiplier);
872 case PED_EXCEPTION_CANCEL:
873 goto error_close_dev;
875 case PED_EXCEPTION_UNHANDLED:
876 ped_exception_catch ();
877 case PED_EXCEPTION_IGNORE:
885 /* XXX sector_size has not been set yet! */
886 /* dev->phys_sector_size = dev->sector_size
887 * sector_multiplier;*/
888 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
891 if (!_device_probe_geometry (dev))
892 goto error_close_dev;
894 ped_device_close (dev);
898 ped_device_close (dev);
903 /* This function reads the /sys entry named "file" for device "dev". */
905 read_device_sysfs_file (PedDevice *dev, const char *file)
911 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
912 last_component (dev->path), file);
914 if ((f = fopen (name_buf, "r")) == NULL)
917 if (fgets (buf, 255, f) == NULL)
921 return strip_name (buf);
924 /* This function sends a query to a SCSI device for vendor and product
925 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
929 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
931 /* The following are defined by the SCSI-2 specification. */
932 typedef struct _scsi_inquiry_cmd
935 uint8_t lun; /* bits 5-7 denote the LUN */
938 uint8_t alloc_length;
940 } __attribute__((packed)) scsi_inquiry_cmd_t;
942 typedef struct _scsi_inquiry_data
944 uint8_t peripheral_info;
946 uint8_t version_info;
948 uint8_t additional_length;
952 uint8_t vendor_id[8];
953 uint8_t product_id[16];
954 uint8_t product_revision[4];
955 uint8_t vendor_specific[20];
956 uint8_t _reserved3[40];
957 } __attribute__((packed)) scsi_inquiry_data_t;
966 scsi_inquiry_data_t out;
967 scsi_inquiry_cmd_t in;
971 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
977 memset (&arg, 0x00, sizeof(struct scsi_arg));
979 arg.outlen = sizeof(scsi_inquiry_data_t);
980 arg.data.in.op = INQUIRY;
981 arg.data.in.lun = dev->host << 5;
982 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
983 arg.data.in.page_code = 0;
984 arg.data.in.reserved = 0;
985 arg.data.in.control = 0;
987 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
990 memcpy (buf, arg.data.out.vendor_id, 8);
992 *vendor = strip_name (buf);
994 memcpy (buf, arg.data.out.product_id, 16);
996 *product = strip_name (buf);
1001 /* This function provides the vendor and product name for a SCSI device.
1002 * It supports both the modern /sys interface and direct queries
1003 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
1006 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
1008 *vendor = read_device_sysfs_file (dev, "vendor");
1009 *product = read_device_sysfs_file (dev, "model");
1010 if (*vendor && *product)
1013 return scsi_query_product_info (dev, vendor, product);
1017 init_scsi (PedDevice* dev)
1022 uint32_t host_unique_id;
1025 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1029 if (!ped_device_open (dev))
1032 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
1035 if (ped_exception_throw (
1036 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
1037 _("Error initialising SCSI device %s - %s"),
1038 dev->path, strerror (errno))
1039 != PED_EXCEPTION_IGNORE)
1040 goto error_close_dev;
1041 if (!_device_probe_geometry (dev))
1042 goto error_close_dev;
1043 ped_device_close (dev);
1047 dev->host = idlun.host_unique_id;
1048 dev->did = idlun.dev_id;
1050 dev->model = (char*) ped_malloc (8 + 16 + 2);
1052 goto error_close_dev;
1054 if (scsi_get_product_info (dev, &vendor, &product)) {
1055 sprintf (dev->model, "%.8s %.16s", vendor, product);
1059 strcpy (dev->model, "Generic SCSI");
1062 if (!_device_probe_geometry (dev))
1063 goto error_close_dev;
1065 ped_device_close (dev);
1069 ped_device_close (dev);
1075 init_file (PedDevice* dev)
1077 struct stat dev_stat;
1079 if (!_device_stat (dev, &dev_stat))
1081 if (!ped_device_open (dev))
1084 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1085 char *p = getenv ("PARTED_SECTOR_SIZE");
1088 if (0 < s && s % 512 == 0)
1089 dev->sector_size = s;
1091 dev->phys_sector_size = dev->sector_size;
1093 if (S_ISBLK(dev_stat.st_mode))
1094 dev->length = _device_get_length (dev);
1096 dev->length = dev_stat.st_size / dev->sector_size;
1097 if (dev->length <= 0) {
1098 ped_exception_throw (
1099 PED_EXCEPTION_ERROR,
1100 PED_EXCEPTION_CANCEL,
1101 _("The device %s has zero length, and can't possibly "
1102 "store a file system or partition table. Perhaps "
1103 "you selected the wrong device?"),
1105 goto error_close_dev;
1108 ped_device_close (dev);
1110 dev->bios_geom.cylinders = dev->length / 4 / 32;
1111 dev->bios_geom.heads = 4;
1112 dev->bios_geom.sectors = 32;
1113 dev->hw_geom = dev->bios_geom;
1114 dev->model = strdup ("");
1119 ped_device_close (dev);
1124 #if defined __s390__ || defined __s390x__
1126 init_dasd (PedDevice* dev, const char* model_name)
1128 struct stat dev_stat;
1129 struct hd_geometry geo;
1130 dasd_information_t dasd_info;
1132 if (!_device_stat (dev, &dev_stat))
1135 if (!ped_device_open (dev))
1138 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1140 PED_ASSERT (S_ISBLK (dev_stat.st_mode));
1142 _device_set_sector_size (dev);
1143 if (!dev->sector_size)
1144 goto error_close_dev;
1146 dev->length = _device_get_length (dev);
1148 goto error_close_dev;
1150 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1151 dev->hw_geom.sectors = geo.sectors;
1152 dev->hw_geom.heads = geo.heads;
1153 dev->hw_geom.cylinders = dev->length
1154 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1155 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1156 dev->bios_geom = dev->hw_geom;
1158 dev->bios_geom.sectors = 12;
1159 dev->bios_geom.heads = 15;
1160 dev->bios_geom.cylinders = dev->length
1161 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1162 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1163 dev->hw_geom = dev->bios_geom;
1166 if (!ioctl(arch_specific->fd, BIODASDINFO, &dasd_info)) {
1167 arch_specific->devno = dasd_info.devno;
1169 arch_specific->devno = arch_specific->major * 256 +
1170 arch_specific->minor;
1173 dev->model = strdup (model_name);
1175 ped_device_close (dev);
1179 ped_device_close (dev);
1186 init_generic (PedDevice* dev, const char* model_name)
1188 struct stat dev_stat;
1189 PedExceptionOption ex_status;
1191 if (!_device_stat (dev, &dev_stat))
1194 if (!ped_device_open (dev))
1197 ped_exception_fetch_all ();
1198 if (_device_probe_geometry (dev)) {
1199 ped_exception_leave_all ();
1201 if (!_device_get_length (dev)) {
1202 ped_exception_catch ();
1203 ped_exception_leave_all ();
1204 goto error_close_dev;
1207 /* hack to allow use of files, for testing */
1208 ped_exception_catch ();
1209 ped_exception_leave_all ();
1211 ex_status = ped_exception_throw (
1212 PED_EXCEPTION_WARNING,
1213 PED_EXCEPTION_IGNORE_CANCEL,
1214 _("Unable to determine geometry of "
1215 "file/device %s. You should not use Parted "
1216 "unless you REALLY know what you're doing!"),
1218 switch (ex_status) {
1219 case PED_EXCEPTION_CANCEL:
1220 goto error_close_dev;
1222 case PED_EXCEPTION_UNHANDLED:
1223 ped_exception_catch ();
1224 case PED_EXCEPTION_IGNORE:
1231 /* what should we stick in here? */
1232 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1233 dev->bios_geom.cylinders = dev->length / 4 / 32;
1234 dev->bios_geom.heads = 4;
1235 dev->bios_geom.sectors = 32;
1236 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1237 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1240 dev->model = strdup (model_name);
1242 ped_device_close (dev);
1246 ped_device_close (dev);
1252 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1254 *type = read_device_sysfs_file (dev, "type");
1255 *name = read_device_sysfs_file (dev, "name");
1263 init_sdmmc (PedDevice* dev)
1268 if (sdmmc_get_product_info (dev, &type, &name)) {
1269 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1273 snprintf (id, sizeof(id) - 1, "%s",
1274 _("Generic SD/MMC Storage Card"));
1276 return init_generic(dev, id);
1280 linux_new (const char* path)
1283 LinuxSpecific* arch_specific;
1285 PED_ASSERT (path != NULL);
1287 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1291 dev->path = strdup (path);
1293 goto error_free_dev;
1296 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1297 if (!dev->arch_specific)
1298 goto error_free_path;
1299 arch_specific = LINUX_SPECIFIC (dev);
1300 arch_specific->dmtype = NULL;
1302 arch_specific->probe = NULL;
1303 arch_specific->topology = NULL;
1306 dev->open_count = 0;
1308 dev->external_mode = 0;
1310 dev->boot_dirty = 0;
1312 if (!_device_probe_type (dev))
1313 goto error_free_arch_specific;
1315 switch (dev->type) {
1316 case PED_DEVICE_IDE:
1317 if (!init_ide (dev))
1318 goto error_free_arch_specific;
1321 case PED_DEVICE_SCSI:
1322 if (!init_scsi (dev))
1323 goto error_free_arch_specific;
1326 case PED_DEVICE_DAC960:
1327 if (!init_generic (dev, _("DAC960 RAID controller")))
1328 goto error_free_arch_specific;
1331 case PED_DEVICE_SX8:
1332 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1333 goto error_free_arch_specific;
1336 case PED_DEVICE_AOE:
1337 if (!init_generic (dev, _("ATA over Ethernet Device")))
1338 goto error_free_arch_specific;
1341 #if defined __s390__ || defined __s390x__
1342 case PED_DEVICE_DASD:
1343 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1344 goto error_free_arch_specific;
1348 case PED_DEVICE_VIODASD:
1349 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1350 goto error_free_arch_specific;
1353 case PED_DEVICE_CPQARRAY:
1354 if (!init_generic (dev, _("Compaq Smart Array")))
1355 goto error_free_arch_specific;
1358 case PED_DEVICE_ATARAID:
1359 if (!init_generic (dev, _("ATARAID Controller")))
1360 goto error_free_arch_specific;
1363 case PED_DEVICE_I2O:
1364 if (!init_generic (dev, _("I2O Controller")))
1365 goto error_free_arch_specific;
1368 case PED_DEVICE_UBD:
1369 if (!init_generic (dev, _("User-Mode Linux UBD")))
1370 goto error_free_arch_specific;
1373 case PED_DEVICE_FILE:
1374 if (!init_file (dev))
1375 goto error_free_arch_specific;
1381 if (arch_specific->dmtype == NULL
1382 || asprintf(&type, _("Linux device-mapper (%s)"),
1383 arch_specific->dmtype) == -1)
1384 goto error_free_arch_specific;
1385 bool ok = init_generic (dev, type);
1388 goto error_free_arch_specific;
1392 case PED_DEVICE_XVD:
1393 if (!init_generic (dev, _("Xen Virtual Block Device")))
1394 goto error_free_arch_specific;
1397 case PED_DEVICE_UNKNOWN:
1398 if (!init_generic (dev, _("Unknown")))
1399 goto error_free_arch_specific;
1402 case PED_DEVICE_SDMMC:
1403 if (!init_sdmmc (dev))
1404 goto error_free_arch_specific;
1406 case PED_DEVICE_VIRTBLK:
1407 if (!init_generic(dev, _("Virtio Block Device")))
1408 goto error_free_arch_specific;
1412 if (!init_generic(dev, _("Linux Software RAID Array")))
1413 goto error_free_arch_specific;
1417 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1418 PED_EXCEPTION_CANCEL,
1419 _("ped_device_new() Unsupported device type"));
1420 goto error_free_arch_specific;
1424 error_free_arch_specific:
1425 free (dev->arch_specific);
1435 linux_destroy (PedDevice* dev)
1437 LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
1438 void *p = arch_specific->dmtype;
1441 if (arch_specific->probe)
1442 blkid_free_probe(arch_specific->probe);
1445 free (dev->arch_specific);
1452 linux_is_busy (PedDevice* dev)
1457 if (_partition_is_mounted_by_path (dev->path))
1460 for (i = 0; i < 32; i++) {
1463 part_name = _device_get_part_path (dev, i);
1466 status = _partition_is_mounted_by_path (part_name);
1476 /* we need to flush the master device, and with kernel < 2.6 all the partition
1477 * devices, because there is no coherency between the caches with old kernels.
1478 * We should only flush unmounted partition devices, because:
1479 * - there is never a need to flush them (we're not doing IO there)
1480 * - flushing a device that is mounted causes unnecessary IO, and can
1481 * even screw journaling & friends up. Even cause oopsen!
1484 _flush_cache (PedDevice* dev)
1486 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1493 ioctl (arch_specific->fd, BLKFLSBUF);
1495 /* With linux-2.6.0 and newer, we're done. */
1499 for (i = 1; i < 16; i++) {
1503 name = _device_get_part_path (dev, i);
1506 if (!_partition_is_mounted_by_path (name)) {
1507 fd = open (name, WR_MODE, 0);
1509 ioctl (fd, BLKFLSBUF);
1511 if (fsync (fd) < 0 || close (fd) < 0)
1512 if (ped_exception_throw (
1513 PED_EXCEPTION_WARNING,
1514 PED_EXCEPTION_RETRY +
1515 PED_EXCEPTION_IGNORE,
1516 _("Error fsyncing/closing %s: %s"),
1517 name, strerror (errno))
1518 == PED_EXCEPTION_RETRY)
1527 linux_open (PedDevice* dev)
1529 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1532 arch_specific->fd = open (dev->path, RW_MODE);
1534 if (arch_specific->fd == -1) {
1535 char* rw_error_msg = strerror (errno);
1537 arch_specific->fd = open (dev->path, RD_MODE);
1539 if (arch_specific->fd == -1) {
1540 if (ped_exception_throw (
1541 PED_EXCEPTION_ERROR,
1542 PED_EXCEPTION_RETRY_CANCEL,
1543 _("Error opening %s: %s"),
1544 dev->path, strerror (errno))
1545 != PED_EXCEPTION_RETRY) {
1551 ped_exception_throw (
1552 PED_EXCEPTION_WARNING,
1554 _("Unable to open %s read-write (%s). %s has "
1555 "been opened read-only."),
1556 dev->path, rw_error_msg, dev->path);
1563 /* With kernels < 2.6 flush cache for cache coherence issues */
1564 if (!_have_kern26())
1571 linux_refresh_open (PedDevice* dev)
1577 linux_close (PedDevice* dev)
1579 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1584 if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
1585 if (ped_exception_throw (
1586 PED_EXCEPTION_WARNING,
1587 PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
1588 _("Error fsyncing/closing %s: %s"),
1589 dev->path, strerror (errno))
1590 == PED_EXCEPTION_RETRY)
1596 linux_refresh_close (PedDevice* dev)
1603 #if SIZEOF_OFF_T < 8
1605 static _syscall5(int,_llseek,
1607 unsigned long, offset_high,
1608 unsigned long, offset_low,
1610 unsigned int, origin)
1613 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1618 retval = _llseek(fd,
1619 ((unsigned long long)offset) >> 32,
1620 ((unsigned long long)offset) & 0xffffffff,
1623 return (retval==-1 ? (loff_t) retval : result);
1626 #endif /* SIZEOF_OFF_T < 8 */
1629 _device_seek (const PedDevice* dev, PedSector sector)
1631 LinuxSpecific* arch_specific;
1633 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
1634 PED_ASSERT (dev != NULL);
1635 PED_ASSERT (!dev->external_mode);
1637 arch_specific = LINUX_SPECIFIC (dev);
1639 #if SIZEOF_OFF_T < 8
1640 if (sizeof (off_t) < 8) {
1641 loff_t pos = (loff_t)(sector * dev->sector_size);
1642 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1646 off_t pos = sector * dev->sector_size;
1647 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1652 _read_lastoddsector (const PedDevice* dev, void* buffer)
1654 LinuxSpecific* arch_specific;
1655 struct blkdev_ioctl_param ioctl_param;
1657 PED_ASSERT(dev != NULL);
1658 PED_ASSERT(buffer != NULL);
1660 arch_specific = LINUX_SPECIFIC (dev);
1663 ioctl_param.block = 0; /* read the last sector */
1664 ioctl_param.content_length = dev->sector_size;
1665 ioctl_param.block_contents = buffer;
1667 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1668 PedExceptionOption opt;
1669 opt = ped_exception_throw (
1670 PED_EXCEPTION_ERROR,
1671 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1672 _("%s during read on %s"),
1673 strerror (errno), dev->path);
1675 if (opt == PED_EXCEPTION_CANCEL)
1677 if (opt == PED_EXCEPTION_RETRY)
1685 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1688 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1689 PedExceptionOption ex_status;
1690 void* diobuf = NULL;
1692 PED_ASSERT (dev != NULL);
1693 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
1695 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1696 /* Kludge. This is necessary to read/write the last
1697 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1699 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1700 && start + count - 1 == dev->length - 1)
1701 return ped_device_read (dev, buffer, start, count - 1)
1702 && _read_lastoddsector (
1703 dev, (char *) buffer + (count-1) * 512);
1706 if (_device_seek (dev, start))
1709 ex_status = ped_exception_throw (
1710 PED_EXCEPTION_ERROR,
1711 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1712 _("%s during seek for read on %s"),
1713 strerror (errno), dev->path);
1715 switch (ex_status) {
1716 case PED_EXCEPTION_IGNORE:
1719 case PED_EXCEPTION_RETRY:
1722 case PED_EXCEPTION_UNHANDLED:
1723 ped_exception_catch ();
1724 case PED_EXCEPTION_CANCEL:
1732 size_t read_length = count * dev->sector_size;
1733 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1737 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1739 memcpy(buffer, diobuf, status);
1740 if (status == (ssize_t) read_length)
1743 read_length -= status;
1744 buffer = (char *) buffer + status;
1748 ex_status = ped_exception_throw (
1749 PED_EXCEPTION_ERROR,
1750 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1752 ? _("end of file while reading %s")
1753 : _("%s during read on %s")),
1757 switch (ex_status) {
1758 case PED_EXCEPTION_IGNORE:
1762 case PED_EXCEPTION_RETRY:
1765 case PED_EXCEPTION_UNHANDLED:
1766 ped_exception_catch ();
1767 case PED_EXCEPTION_CANCEL:
1782 _write_lastoddsector (PedDevice* dev, const void* buffer)
1784 LinuxSpecific* arch_specific;
1785 struct blkdev_ioctl_param ioctl_param;
1787 PED_ASSERT(dev != NULL);
1788 PED_ASSERT(buffer != NULL);
1790 arch_specific = LINUX_SPECIFIC (dev);
1793 ioctl_param.block = 0; /* write the last sector */
1794 ioctl_param.content_length = dev->sector_size;
1795 ioctl_param.block_contents = (void*) buffer;
1797 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1798 PedExceptionOption opt;
1799 opt = ped_exception_throw (
1800 PED_EXCEPTION_ERROR,
1801 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1802 _("%s during write on %s"),
1803 strerror (errno), dev->path);
1805 if (opt == PED_EXCEPTION_CANCEL)
1807 if (opt == PED_EXCEPTION_RETRY)
1815 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1818 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1819 PedExceptionOption ex_status;
1823 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
1825 if (dev->read_only) {
1826 if (ped_exception_throw (
1827 PED_EXCEPTION_ERROR,
1828 PED_EXCEPTION_IGNORE_CANCEL,
1829 _("Can't write to %s, because it is opened read-only."),
1831 != PED_EXCEPTION_IGNORE)
1837 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1838 /* Kludge. This is necessary to read/write the last
1839 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1841 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1842 && start + count - 1 == dev->length - 1)
1843 return ped_device_write (dev, buffer, start, count - 1)
1844 && _write_lastoddsector (
1845 dev, ((char*) buffer
1846 + (count-1) * dev->sector_size));
1849 if (_device_seek (dev, start))
1852 ex_status = ped_exception_throw (
1853 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1854 _("%s during seek for write on %s"),
1855 strerror (errno), dev->path);
1857 switch (ex_status) {
1858 case PED_EXCEPTION_IGNORE:
1861 case PED_EXCEPTION_RETRY:
1864 case PED_EXCEPTION_UNHANDLED:
1865 ped_exception_catch ();
1866 case PED_EXCEPTION_CANCEL:
1875 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1876 dev->path, buffer, (int) start, (int) count);
1878 size_t write_length = count * dev->sector_size;
1880 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1882 memcpy(diobuf, buffer, write_length);
1883 diobuf_start = diobuf;
1885 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1886 if (status == write_length) break;
1888 write_length -= status;
1889 diobuf = (char *) diobuf + status;
1893 ex_status = ped_exception_throw (
1894 PED_EXCEPTION_ERROR,
1895 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1896 _("%s during write on %s"),
1897 strerror (errno), dev->path);
1899 switch (ex_status) {
1900 case PED_EXCEPTION_IGNORE:
1904 case PED_EXCEPTION_RETRY:
1907 case PED_EXCEPTION_UNHANDLED:
1908 ped_exception_catch ();
1909 case PED_EXCEPTION_CANCEL:
1918 #endif /* !READ_ONLY */
1922 /* returns the number of sectors that are ok.
1925 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1927 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1932 PED_ASSERT(dev != NULL);
1934 if (!_device_seek (dev, start))
1937 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1938 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1941 for (done = 0; done < count; done += status / dev->sector_size) {
1942 status = read (arch_specific->fd, diobuf,
1943 (size_t) ((count-done) * dev->sector_size));
1945 memcpy(buffer, diobuf, status);
1955 _do_fsync (PedDevice* dev)
1957 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1959 PedExceptionOption ex_status;
1962 status = fsync (arch_specific->fd);
1963 if (status >= 0) break;
1965 ex_status = ped_exception_throw (
1966 PED_EXCEPTION_ERROR,
1967 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1968 _("%s during write on %s"),
1969 strerror (errno), dev->path);
1971 switch (ex_status) {
1972 case PED_EXCEPTION_IGNORE:
1975 case PED_EXCEPTION_RETRY:
1978 case PED_EXCEPTION_UNHANDLED:
1979 ped_exception_catch ();
1980 case PED_EXCEPTION_CANCEL:
1991 linux_sync (PedDevice* dev)
1993 PED_ASSERT (dev != NULL);
1994 PED_ASSERT (!dev->external_mode);
1998 if (!_do_fsync (dev))
2005 linux_sync_fast (PedDevice* dev)
2007 PED_ASSERT (dev != NULL);
2008 PED_ASSERT (!dev->external_mode);
2012 if (!_do_fsync (dev))
2014 /* no cache flush... */
2019 _compare_digit_state (char ch, int need_digit)
2021 return !!isdigit (ch) == need_digit;
2024 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
2025 * Motivation: accept devices looking like /dev/rd/c0d0, but
2026 * not looking like /dev/hda1 and /dev/rd/c0d0p1
2029 _match_rd_device (const char* name)
2034 /* exclude directory names from test */
2035 pos = strrchr(name, '/') ?: name;
2043 for (state = 0; state < 4; state++) {
2044 int want_digits = (state % 2 == 1);
2048 if (!_compare_digit_state (*pos, want_digits))
2051 } while (_compare_digit_state (*pos, want_digits));
2058 _probe_proc_partitions ()
2060 FILE* proc_part_file;
2061 int major, minor, size;
2063 char part_name [256];
2064 char dev_name [256];
2066 proc_part_file = fopen ("/proc/partitions", "r");
2067 if (!proc_part_file)
2070 if (fgets (buf, 256, proc_part_file) == NULL)
2073 if (fgets (buf, 256, proc_part_file) == NULL)
2076 while (fgets (buf, 512, proc_part_file)
2077 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
2079 /* Heuristic for telling partitions and devices apart
2080 * Probably needs to be improved
2082 if (!_match_rd_device (part_name)
2083 && isdigit (part_name [strlen (part_name) - 1]))
2086 strcpy (dev_name, "/dev/");
2087 strcat (dev_name, part_name);
2088 _ped_device_probe (dev_name);
2091 fclose (proc_part_file);
2101 _skip_entry (const char *name)
2104 static struct _entry entries[] = {
2105 { ".", sizeof (".") - 1 },
2106 { "..", sizeof ("..") - 1 },
2107 { "dm-", sizeof ("dm-") - 1 },
2108 { "loop", sizeof ("loop") - 1 },
2109 { "ram", sizeof ("ram") - 1 },
2113 for (i = entries; i->name != 0; i++) {
2114 if (strncmp (name, i->name, i->len) == 0)
2125 struct dirent *dirent;
2126 char dev_name [256];
2129 if (!(blockdir = opendir ("/sys/block")))
2131 while ((dirent = readdir (blockdir))) {
2132 if (_skip_entry (dirent->d_name))
2135 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2136 continue; /* device name too long! */
2138 strcpy (dev_name, "/dev/");
2139 strcat (dev_name, dirent->d_name);
2140 /* in /sys/block, '/'s are replaced with '!' or '.' */
2141 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2142 if (*ptr == '!' || *ptr == '.')
2145 _ped_device_probe (dev_name);
2148 closedir (blockdir);
2153 _probe_standard_devices ()
2155 _ped_device_probe ("/dev/hda");
2156 _ped_device_probe ("/dev/hdb");
2157 _ped_device_probe ("/dev/hdc");
2158 _ped_device_probe ("/dev/hdd");
2159 _ped_device_probe ("/dev/hde");
2160 _ped_device_probe ("/dev/hdf");
2161 _ped_device_probe ("/dev/hdg");
2162 _ped_device_probe ("/dev/hdh");
2164 _ped_device_probe ("/dev/sda");
2165 _ped_device_probe ("/dev/sdb");
2166 _ped_device_probe ("/dev/sdc");
2167 _ped_device_probe ("/dev/sdd");
2168 _ped_device_probe ("/dev/sde");
2169 _ped_device_probe ("/dev/sdf");
2177 /* we should probe the standard devs too, even with /proc/partitions,
2178 * because /proc/partitions might return devfs stuff, and we might not
2179 * have devfs available
2181 _probe_standard_devices ();
2183 #ifdef ENABLE_DEVICE_MAPPER
2184 /* device-mapper devices aren't listed in /proc/partitions; or, if
2185 * they are, they're listed as dm-X. So, instead of relying on that,
2186 * we do our own checks.
2188 _probe_dm_devices ();
2191 /* /sys/block is more reliable and consistent; fall back to using
2192 * /proc/partitions if the former is unavailable, however.
2194 if (!_probe_sys_block ())
2195 _probe_proc_partitions ();
2198 static char * _GL_ATTRIBUTE_FORMAT ((__printf__, 1, 2))
2199 zasprintf (const char *format, ...)
2203 va_start (args, format);
2204 int r = vasprintf (&resultp, format, args);
2206 return r < 0 ? NULL : resultp;
2210 _device_get_part_path (PedDevice *dev, int num)
2212 size_t path_len = strlen (dev->path);
2215 /* Check for devfs-style /disc => /partN transformation
2216 unconditionally; the system might be using udev with devfs rules,
2217 and if not the test is harmless. */
2218 if (5 < path_len && !strcmp (dev->path + path_len - 5, "/disc")) {
2219 /* replace /disc with /path%d */
2220 result = zasprintf ("%.*s/part%d",
2221 (int) (path_len - 5), dev->path, num);
2223 char const *p = (dev->type == PED_DEVICE_DAC960
2224 || dev->type == PED_DEVICE_CPQARRAY
2225 || dev->type == PED_DEVICE_ATARAID
2226 || dev->type == PED_DEVICE_DM
2227 || isdigit (dev->path[path_len - 1])
2229 result = zasprintf ("%s%s%d", dev->path, p, num);
2236 linux_partition_get_path (const PedPartition* part)
2238 return _device_get_part_path (part->disk->dev, part->num);
2242 _partition_get_part_dev (const PedPartition* part)
2244 struct stat dev_stat;
2245 int dev_major, dev_minor;
2247 if (stat (part->disk->dev->path, &dev_stat))
2249 dev_major = major (dev_stat.st_rdev);
2250 dev_minor = minor (dev_stat.st_rdev);
2251 return (dev_t)makedev (dev_major, dev_minor + part->num);
2255 _mount_table_search (const char* file_name, dev_t dev)
2257 struct stat part_stat;
2259 char part_name[512];
2262 file = fopen (file_name, "r");
2265 while (fgets (line, 512, file)) {
2266 if (sscanf (line, "%s", part_name) == 1
2267 && stat (part_name, &part_stat) == 0) {
2268 if (part_stat.st_rdev == dev) {
2279 _partition_is_mounted_by_dev (dev_t dev)
2281 return _mount_table_search( "/proc/mounts", dev)
2282 || _mount_table_search( "/proc/swaps", dev)
2283 || _mount_table_search( "/etc/mtab", dev);
2287 _partition_is_mounted_by_path (const char *path)
2289 struct stat part_stat;
2290 if (stat (path, &part_stat) != 0)
2292 if (!S_ISBLK(part_stat.st_mode))
2294 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2298 _partition_is_mounted (const PedPartition *part)
2301 if (!ped_partition_is_active (part))
2303 dev = _partition_get_part_dev (part);
2306 return _partition_is_mounted_by_dev (dev);
2310 _has_partitions (const PedDisk* disk)
2312 PED_ASSERT(disk != NULL);
2314 /* Some devices can't be partitioned. */
2315 if (!strcmp (disk->type->name, "loop"))
2322 linux_partition_is_busy (const PedPartition* part)
2326 PED_ASSERT (part != NULL);
2328 if (_partition_is_mounted (part))
2330 if (part->type == PED_PARTITION_EXTENDED) {
2331 for (walk = part->part_list; walk; walk = walk->next) {
2332 if (linux_partition_is_busy (walk))
2340 _blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
2342 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2343 struct blkpg_ioctl_arg ioctl_arg;
2346 ioctl_arg.flags = 0;
2347 ioctl_arg.datalen = sizeof (struct blkpg_partition);
2348 ioctl_arg.data = (void*) part;
2350 return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
2354 _blkpg_add_partition (PedDisk* disk, const PedPartition *part)
2356 struct blkpg_partition linux_part;
2357 const char* vol_name;
2360 PED_ASSERT(disk != NULL);
2361 PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
2363 if (!_has_partitions (disk))
2366 if (ped_disk_type_check_feature (disk->type,
2367 PED_DISK_TYPE_PARTITION_NAME))
2368 vol_name = ped_partition_get_name (part);
2372 dev_name = _device_get_part_path (disk->dev, part->num);
2376 memset (&linux_part, 0, sizeof (linux_part));
2377 linux_part.start = part->geom.start * disk->dev->sector_size;
2378 /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
2379 if (part->type & PED_PARTITION_EXTENDED)
2380 linux_part.length = part->geom.length == 1 ? 512 : 1024;
2382 linux_part.length = part->geom.length * disk->dev->sector_size;
2383 linux_part.pno = part->num;
2384 strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
2386 strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
2390 if (!_blkpg_part_command (disk->dev, &linux_part,
2391 BLKPG_ADD_PARTITION)) {
2392 return ped_exception_throw (
2393 PED_EXCEPTION_ERROR,
2394 PED_EXCEPTION_IGNORE_CANCEL,
2395 _("Error informing the kernel about modifications to "
2396 "partition %s -- %s. This means Linux won't know "
2397 "about any changes you made to %s until you reboot "
2398 "-- so you shouldn't mount it or use it in any way "
2399 "before rebooting."),
2403 == PED_EXCEPTION_IGNORE;
2410 _blkpg_remove_partition (PedDisk* disk, int n)
2412 struct blkpg_partition linux_part;
2414 if (!_has_partitions (disk))
2417 memset (&linux_part, 0, sizeof (linux_part));
2419 return _blkpg_part_command (disk->dev, &linux_part,
2420 BLKPG_DEL_PARTITION);
2424 * The number of partitions that a device can have depends on the kernel.
2425 * If we don't find this value in /sys/block/DEV/range, we will use our own
2429 _device_get_partition_range(PedDevice* dev)
2436 r = snprintf(path, sizeof(path), "/sys/block/%s/range",
2437 last_component(dev->path));
2438 if (r < 0 || r >= sizeof(path))
2439 return MAX_NUM_PARTS;
2441 fp = fopen(path, "r");
2443 return MAX_NUM_PARTS;
2445 ok = fscanf(fp, "%d", &range) == 1;
2448 /* (range <= 0) is none sense.*/
2449 return ok && range > 0 ? range : MAX_NUM_PARTS;
2453 * Sync the partition table in two step process:
2454 * 1. Remove all of the partitions from the kernel's tables, but do not attempt
2455 * removal of any partition for which the corresponding ioctl call fails.
2456 * 2. Add all the partitions that we hold in disk, throwing a warning
2457 * if we cannot because step 1 failed to remove it and it is not being
2458 * added back with the same start and length.
2460 * To achieve this two step process we must calculate the minimum number of
2461 * maximum possible partitions between what linux supports and what the label
2462 * type supports. EX:
2464 * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables)
2467 _disk_sync_part_table (PedDisk* disk)
2469 PED_ASSERT(disk != NULL);
2470 PED_ASSERT(disk->dev != NULL);
2473 /* lpn = largest partition number. */
2474 if (ped_disk_get_max_supported_partition_count(disk, &lpn))
2475 lpn = PED_MIN(lpn, _device_get_partition_range(disk->dev));
2477 lpn = _device_get_partition_range(disk->dev);
2479 /* Its not possible to support largest_partnum < 0.
2480 * largest_partnum == 0 would mean does not support partitions.
2485 int *ok = calloc (lpn, sizeof *ok);
2488 int *errnums = ped_malloc(sizeof(int) * lpn);
2492 /* Attempt to remove each and every partition, retrying for
2493 up to max_sleep_seconds upon any failure due to EBUSY. */
2494 unsigned int sleep_microseconds = 10000;
2495 unsigned int max_sleep_seconds = 1;
2496 unsigned int n_sleep = (max_sleep_seconds
2497 * 1000000 / sleep_microseconds);
2499 for (i = 0; i < n_sleep; i++) {
2501 usleep (sleep_microseconds);
2504 for (j = 0; j < lpn; j++) {
2506 ok[j] = _blkpg_remove_partition (disk, j + 1);
2508 if (!ok[j] && errnums[j] == EBUSY)
2516 for (i = 1; i <= lpn; i++) {
2517 const PedPartition *part = ped_disk_get_partition (disk, i);
2519 if (!ok[i - 1] && errnums[i - 1] == EBUSY) {
2520 struct hd_geometry geom;
2521 unsigned long long length = 0;
2522 /* get start and length of existing partition */
2523 char *dev_name = _device_get_part_path (disk->dev, i);
2526 int fd = open (dev_name, O_RDONLY);
2528 || ioctl (fd, HDIO_GETGEO, &geom)
2529 || ioctl (fd, BLKGETSIZE64, &length)) {
2530 ped_exception_throw (
2532 PED_EXCEPTION_CANCEL,
2533 _("Unable to determine the size and length of %s."),
2541 length /= disk->dev->sector_size;
2543 if (geom.start == part->geom.start
2544 && length == part->geom.length)
2546 /* If the new partition is unchanged and the
2547 existing one was not removed because it was
2548 in use, then reset the error flag and do not
2549 try to add it since it is already there. */
2553 /* add the (possibly modified or new) partition */
2554 if (!_blkpg_add_partition (disk, part)) {
2555 ped_exception_throw (
2556 PED_EXCEPTION_ERROR,
2557 PED_EXCEPTION_RETRY_CANCEL,
2558 _("Failed to add partition %d (%s)"),
2559 i, strerror (errno));
2565 char *bad_part_list = NULL;
2566 /* now warn about any errors */
2567 for (i = 1; i <= lpn; i++) {
2568 if (ok[i - 1] || errnums[i - 1] == ENXIO)
2570 if (bad_part_list == NULL) {
2571 bad_part_list = malloc (lpn * 5);
2574 bad_part_list[0] = 0;
2576 sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i);
2578 if (bad_part_list == NULL)
2581 bad_part_list[strlen (bad_part_list) - 2] = 0;
2582 if (ped_exception_throw (
2583 PED_EXCEPTION_ERROR,
2584 PED_EXCEPTION_IGNORE_CANCEL,
2585 _("Partition(s) %s on %s have been written, but we have "
2586 "been unable to inform the kernel of the change, "
2587 "probably because it/they are in use. As a result, "
2588 "the old partition(s) will remain in use. You "
2589 "should reboot now before making further changes."),
2590 bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE)
2592 free (bad_part_list);
2600 #ifdef ENABLE_DEVICE_MAPPER
2602 _dm_remove_map_name(char *name)
2604 struct dm_task *task = NULL;
2607 task = dm_task_create(DM_DEVICE_REMOVE);
2611 dm_task_set_name (task, name);
2613 rc = dm_task_run(task);
2614 dm_task_update_nodes();
2615 dm_task_destroy(task);
2623 _dm_is_part (struct dm_info *this, char *name)
2625 struct dm_task* task = NULL;
2626 struct dm_info* info = alloca(sizeof *info);
2627 struct dm_deps* deps = NULL;
2631 task = dm_task_create(DM_DEVICE_DEPS);
2635 dm_task_set_name(task, name);
2636 if (!dm_task_run(task))
2639 memset(info, '\0', sizeof *info);
2640 dm_task_get_info(task, info);
2644 deps = dm_task_get_deps(task);
2648 for (i = 0; i < deps->count; i++) {
2649 unsigned int ma = major(deps->device[i]),
2650 mi = minor(deps->device[i]);
2652 if (ma == this->major && mi == this->minor)
2657 dm_task_destroy(task);
2662 _dm_remove_parts (PedDevice* dev)
2664 struct dm_task* task = NULL;
2665 struct dm_info* info = alloca(sizeof *info);
2666 struct dm_names* names = NULL;
2667 unsigned int next = 0;
2669 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2671 task = dm_task_create(DM_DEVICE_LIST);
2675 if (!dm_task_set_major_minor (task, arch_specific->major,
2676 arch_specific->minor, 0))
2679 if (!dm_task_run(task))
2682 memset(info, '\0', sizeof *info);
2683 dm_task_get_info(task, info);
2687 names = dm_task_get_names(task);
2693 names = (void *) ((char *) names + next);
2695 if (_dm_is_part(info, names->name))
2696 rc += _dm_remove_map_name(names->name);
2701 dm_task_update_nodes();
2702 dm_task_destroy(task);
2709 dm_task_destroy(task);
2710 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2711 _("parted was unable to re-read the partition "
2712 "table on %s (%s). This means Linux won't know "
2713 "anything about the modifications you made. "),
2714 dev->path, strerror (errno));
2719 _dm_add_partition (PedDisk* disk, PedPartition* part)
2721 char* vol_name = NULL;
2722 const char* dev_name = NULL;
2723 char* params = NULL;
2724 LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
2726 if (!_has_partitions(disk))
2729 /* Get map name from devicemapper */
2730 struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
2734 if (!dm_task_set_major_minor (task, arch_specific->major,
2735 arch_specific->minor, 0))
2738 if (!dm_task_run(task))
2741 dev_name = dm_task_get_name (task);
2743 if (asprintf (&vol_name, "%sp%d", dev_name, part->num) == -1)
2746 /* Caution: dm_task_destroy frees dev_name. */
2747 dm_task_destroy (task);
2750 if (asprintf (¶ms, "%d:%d %lld", arch_specific->major,
2751 arch_specific->minor, part->geom.start) == -1)
2754 task = dm_task_create (DM_DEVICE_CREATE);
2758 dm_task_set_name (task, vol_name);
2759 dm_task_add_target (task, 0, part->geom.length,
2761 if (dm_task_run (task)) {
2762 //printf("0 %ld linear %s\n", part->geom.length, params);
2763 dm_task_update_nodes();
2764 dm_task_destroy(task);
2769 _dm_remove_map_name(vol_name);
2772 dm_task_update_nodes();
2774 dm_task_destroy (task);
2781 _dm_reread_part_table (PedDisk* disk)
2783 int largest_partnum = ped_disk_get_last_partition_num (disk);
2784 if (largest_partnum <= 0)
2788 int last = PED_MIN (largest_partnum, 16);
2792 if (!_dm_remove_parts(disk->dev))
2795 for (i = 1; i <= last; i++) {
2798 part = ped_disk_get_partition (disk, i);
2802 if (!_dm_add_partition (disk, part))
2812 static int have_blkpg = -1;
2815 if (have_blkpg != -1)
2818 kver = _get_linux_version();
2819 return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
2822 /* Return nonzero upon success, 0 if something fails. */
2824 linux_disk_commit (PedDisk* disk)
2826 if (!_has_partitions (disk))
2829 #ifdef ENABLE_DEVICE_MAPPER
2830 if (disk->dev->type == PED_DEVICE_DM)
2831 return _dm_reread_part_table (disk);
2833 if (disk->dev->type != PED_DEVICE_FILE) {
2835 /* We now require BLKPG support. If this assertion fails,
2836 please write to the mailing list describing your system.
2837 Assuming it's never triggered, ...
2838 FIXME: remove this assertion in 2012. */
2839 assert (_have_blkpg ());
2841 if (!_disk_sync_part_table (disk))
2849 static PedAlignment*
2850 linux_get_minimum_alignment(const PedDevice *dev)
2852 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2856 if (blkid_topology_get_minimum_io_size(tp) == 0)
2857 return ped_alignment_new(
2858 blkid_topology_get_alignment_offset(tp) /
2860 dev->phys_sector_size / dev->sector_size);
2862 return ped_alignment_new(
2863 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2864 blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
2867 static PedAlignment*
2868 linux_get_optimum_alignment(const PedDevice *dev)
2870 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2874 /* When PED_DEFAULT_ALIGNMENT is divisible by the *_io_size or
2875 there are no *_io_size values, use the PED_DEFAULT_ALIGNMENT
2876 If one or the other will not divide evenly, fall through to
2878 unsigned long optimal_io = blkid_topology_get_optimal_io_size(tp);
2879 unsigned long minimum_io = blkid_topology_get_minimum_io_size(tp);
2881 (!optimal_io && !minimum_io)
2882 || (optimal_io && PED_DEFAULT_ALIGNMENT % optimal_io == 0
2883 && minimum_io && PED_DEFAULT_ALIGNMENT % minimum_io == 0)
2884 || (!minimum_io && optimal_io
2885 && PED_DEFAULT_ALIGNMENT % optimal_io == 0)
2886 || (!optimal_io && minimum_io
2887 && PED_DEFAULT_ALIGNMENT % minimum_io == 0)
2889 /* DASD needs to use minimum alignment */
2890 if (dev->type == PED_DEVICE_DASD)
2891 return linux_get_minimum_alignment(dev);
2893 return ped_alignment_new(
2894 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2895 PED_DEFAULT_ALIGNMENT / dev->sector_size);
2898 /* If optimal_io_size is 0 and we don't meet the other criteria
2899 for using the device.c default, return the minimum alignment. */
2900 if (blkid_topology_get_optimal_io_size(tp) == 0)
2901 return linux_get_minimum_alignment(dev);
2903 return ped_alignment_new(
2904 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2905 blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
2909 static PedDeviceArchOps linux_dev_ops = {
2911 destroy: linux_destroy,
2912 is_busy: linux_is_busy,
2914 refresh_open: linux_refresh_open,
2916 refresh_close: linux_refresh_close,
2921 sync_fast: linux_sync_fast,
2922 probe_all: linux_probe_all,
2924 get_minimum_alignment: linux_get_minimum_alignment,
2925 get_optimum_alignment: linux_get_optimum_alignment,
2929 PedDiskArchOps linux_disk_ops = {
2930 partition_get_path: linux_partition_get_path,
2931 partition_is_busy: linux_partition_is_busy,
2932 disk_commit: linux_disk_commit
2935 PedArchitecture ped_linux_arch = {
2936 dev_ops: &linux_dev_ops,
2937 disk_ops: &linux_disk_ops