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 /* hack to allow use of files, for testing */
1184 ped_exception_catch ();
1185 ped_exception_leave_all ();
1187 ex_status = ped_exception_throw (
1188 PED_EXCEPTION_WARNING,
1189 PED_EXCEPTION_IGNORE_CANCEL,
1190 _("Unable to determine geometry of "
1191 "file/device %s. You should not use Parted "
1192 "unless you REALLY know what you're doing!"),
1194 switch (ex_status) {
1195 case PED_EXCEPTION_CANCEL:
1196 goto error_close_dev;
1198 case PED_EXCEPTION_UNHANDLED:
1199 ped_exception_catch ();
1200 case PED_EXCEPTION_IGNORE:
1203 PED_ASSERT (0, (void) 0);
1207 /* what should we stick in here? */
1208 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1209 dev->bios_geom.cylinders = dev->length / 4 / 32;
1210 dev->bios_geom.heads = 4;
1211 dev->bios_geom.sectors = 32;
1212 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1213 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1216 dev->model = strdup (model_name);
1218 ped_device_close (dev);
1222 ped_device_close (dev);
1228 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1230 *type = read_device_sysfs_file (dev, "type");
1231 *name = read_device_sysfs_file (dev, "name");
1239 init_sdmmc (PedDevice* dev)
1244 if (sdmmc_get_product_info (dev, &type, &name)) {
1245 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1249 snprintf (id, sizeof(id) - 1, "%s",
1250 _("Generic SD/MMC Storage Card"));
1252 return init_generic(dev, id);
1256 linux_new (const char* path)
1259 LinuxSpecific* arch_specific;
1261 PED_ASSERT (path != NULL, return NULL);
1263 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1267 dev->path = strdup (path);
1269 goto error_free_dev;
1272 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1273 if (!dev->arch_specific)
1274 goto error_free_path;
1275 arch_specific = LINUX_SPECIFIC (dev);
1276 arch_specific->dmtype = NULL;
1278 arch_specific->probe = NULL;
1279 arch_specific->topology = NULL;
1282 dev->open_count = 0;
1284 dev->external_mode = 0;
1286 dev->boot_dirty = 0;
1288 if (!_device_probe_type (dev))
1289 goto error_free_arch_specific;
1291 switch (dev->type) {
1292 case PED_DEVICE_IDE:
1293 if (!init_ide (dev))
1294 goto error_free_arch_specific;
1297 case PED_DEVICE_SCSI:
1298 if (!init_scsi (dev))
1299 goto error_free_arch_specific;
1302 case PED_DEVICE_DAC960:
1303 if (!init_generic (dev, _("DAC960 RAID controller")))
1304 goto error_free_arch_specific;
1307 case PED_DEVICE_SX8:
1308 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1309 goto error_free_arch_specific;
1312 case PED_DEVICE_AOE:
1313 if (!init_generic (dev, _("ATA over Ethernet Device")))
1314 goto error_free_arch_specific;
1317 #if defined __s390__ || defined __s390x__
1318 case PED_DEVICE_DASD:
1319 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1320 goto error_free_arch_specific;
1324 case PED_DEVICE_VIODASD:
1325 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1326 goto error_free_arch_specific;
1329 case PED_DEVICE_CPQARRAY:
1330 if (!init_generic (dev, _("Compaq Smart Array")))
1331 goto error_free_arch_specific;
1334 case PED_DEVICE_ATARAID:
1335 if (!init_generic (dev, _("ATARAID Controller")))
1336 goto error_free_arch_specific;
1339 case PED_DEVICE_I2O:
1340 if (!init_generic (dev, _("I2O Controller")))
1341 goto error_free_arch_specific;
1344 case PED_DEVICE_UBD:
1345 if (!init_generic (dev, _("User-Mode Linux UBD")))
1346 goto error_free_arch_specific;
1349 case PED_DEVICE_FILE:
1350 if (!init_file (dev))
1351 goto error_free_arch_specific;
1357 if (arch_specific->dmtype == NULL
1358 || asprintf(&type, _("Linux device-mapper (%s)"),
1359 arch_specific->dmtype) == -1)
1360 goto error_free_arch_specific;
1361 bool ok = init_generic (dev, type);
1364 goto error_free_arch_specific;
1368 case PED_DEVICE_XVD:
1369 if (!init_generic (dev, _("Xen Virtual Block Device")))
1370 goto error_free_arch_specific;
1373 case PED_DEVICE_UNKNOWN:
1374 if (!init_generic (dev, _("Unknown")))
1375 goto error_free_arch_specific;
1378 case PED_DEVICE_SDMMC:
1379 if (!init_sdmmc (dev))
1380 goto error_free_arch_specific;
1382 case PED_DEVICE_VIRTBLK:
1383 if (!init_generic(dev, _("Virtio Block Device")))
1384 goto error_free_arch_specific;
1388 if (!init_generic(dev, _("Linux Software RAID Array")))
1389 goto error_free_arch_specific;
1393 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1394 PED_EXCEPTION_CANCEL,
1395 _("ped_device_new() Unsupported device type"));
1396 goto error_free_arch_specific;
1400 error_free_arch_specific:
1401 free (dev->arch_specific);
1411 linux_destroy (PedDevice* dev)
1413 LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
1414 void *p = arch_specific->dmtype;
1417 if (arch_specific->probe)
1418 blkid_free_probe(arch_specific->probe);
1421 free (dev->arch_specific);
1428 linux_is_busy (PedDevice* dev)
1433 if (_partition_is_mounted_by_path (dev->path))
1436 for (i = 0; i < 32; i++) {
1439 part_name = _device_get_part_path (dev, i);
1442 status = _partition_is_mounted_by_path (part_name);
1452 /* we need to flush the master device, and with kernel < 2.6 all the partition
1453 * devices, because there is no coherency between the caches with old kernels.
1454 * We should only flush unmounted partition devices, because:
1455 * - there is never a need to flush them (we're not doing IO there)
1456 * - flushing a device that is mounted causes unnecessary IO, and can
1457 * even screw journaling & friends up. Even cause oopsen!
1460 _flush_cache (PedDevice* dev)
1462 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1469 ioctl (arch_specific->fd, BLKFLSBUF);
1471 /* With linux-2.6.0 and newer, we're done. */
1475 for (i = 1; i < 16; i++) {
1479 name = _device_get_part_path (dev, i);
1482 if (!_partition_is_mounted_by_path (name)) {
1483 fd = open (name, WR_MODE, 0);
1485 ioctl (fd, BLKFLSBUF);
1487 if (fsync (fd) < 0 || close (fd) < 0)
1488 if (ped_exception_throw (
1489 PED_EXCEPTION_WARNING,
1490 PED_EXCEPTION_RETRY +
1491 PED_EXCEPTION_IGNORE,
1492 _("Error fsyncing/closing %s: %s"),
1493 name, strerror (errno))
1494 == PED_EXCEPTION_RETRY)
1503 linux_open (PedDevice* dev)
1505 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1508 arch_specific->fd = open (dev->path, RW_MODE);
1510 if (arch_specific->fd == -1) {
1511 char* rw_error_msg = strerror (errno);
1513 arch_specific->fd = open (dev->path, RD_MODE);
1515 if (arch_specific->fd == -1) {
1516 if (ped_exception_throw (
1517 PED_EXCEPTION_ERROR,
1518 PED_EXCEPTION_RETRY_CANCEL,
1519 _("Error opening %s: %s"),
1520 dev->path, strerror (errno))
1521 != PED_EXCEPTION_RETRY) {
1527 ped_exception_throw (
1528 PED_EXCEPTION_WARNING,
1530 _("Unable to open %s read-write (%s). %s has "
1531 "been opened read-only."),
1532 dev->path, rw_error_msg, dev->path);
1539 /* With kernels < 2.6 flush cache for cache coherence issues */
1540 if (!_have_kern26())
1547 linux_refresh_open (PedDevice* dev)
1553 linux_close (PedDevice* dev)
1555 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1560 if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
1561 if (ped_exception_throw (
1562 PED_EXCEPTION_WARNING,
1563 PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
1564 _("Error fsyncing/closing %s: %s"),
1565 dev->path, strerror (errno))
1566 == PED_EXCEPTION_RETRY)
1572 linux_refresh_close (PedDevice* dev)
1579 #if SIZEOF_OFF_T < 8
1581 static _syscall5(int,_llseek,
1583 unsigned long, offset_high,
1584 unsigned long, offset_low,
1586 unsigned int, origin)
1589 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1594 retval = _llseek(fd,
1595 ((unsigned long long)offset) >> 32,
1596 ((unsigned long long)offset) & 0xffffffff,
1599 return (retval==-1 ? (loff_t) retval : result);
1602 #endif /* SIZEOF_OFF_T < 8 */
1605 _device_seek (const PedDevice* dev, PedSector sector)
1607 LinuxSpecific* arch_specific;
1609 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1610 PED_ASSERT (dev != NULL, return 0);
1611 PED_ASSERT (!dev->external_mode, return 0);
1613 arch_specific = LINUX_SPECIFIC (dev);
1615 #if SIZEOF_OFF_T < 8
1616 if (sizeof (off_t) < 8) {
1617 loff_t pos = (loff_t)(sector * dev->sector_size);
1618 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1622 off_t pos = sector * dev->sector_size;
1623 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1628 _read_lastoddsector (const PedDevice* dev, void* buffer)
1630 LinuxSpecific* arch_specific;
1631 struct blkdev_ioctl_param ioctl_param;
1633 PED_ASSERT(dev != NULL, return 0);
1634 PED_ASSERT(buffer != NULL, return 0);
1636 arch_specific = LINUX_SPECIFIC (dev);
1639 ioctl_param.block = 0; /* read the last sector */
1640 ioctl_param.content_length = dev->sector_size;
1641 ioctl_param.block_contents = buffer;
1643 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1644 PedExceptionOption opt;
1645 opt = ped_exception_throw (
1646 PED_EXCEPTION_ERROR,
1647 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1648 _("%s during read on %s"),
1649 strerror (errno), dev->path);
1651 if (opt == PED_EXCEPTION_CANCEL)
1653 if (opt == PED_EXCEPTION_RETRY)
1661 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1664 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1665 PedExceptionOption ex_status;
1666 void* diobuf = NULL;
1668 PED_ASSERT (dev != NULL, return 0);
1669 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1671 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1672 /* Kludge. This is necessary to read/write the last
1673 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1675 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1676 && start + count - 1 == dev->length - 1)
1677 return ped_device_read (dev, buffer, start, count - 1)
1678 && _read_lastoddsector (
1679 dev, (char *) buffer + (count-1) * 512);
1682 if (_device_seek (dev, start))
1685 ex_status = ped_exception_throw (
1686 PED_EXCEPTION_ERROR,
1687 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1688 _("%s during seek for read on %s"),
1689 strerror (errno), dev->path);
1691 switch (ex_status) {
1692 case PED_EXCEPTION_IGNORE:
1695 case PED_EXCEPTION_RETRY:
1698 case PED_EXCEPTION_UNHANDLED:
1699 ped_exception_catch ();
1700 case PED_EXCEPTION_CANCEL:
1703 PED_ASSERT (0, (void) 0);
1708 size_t read_length = count * dev->sector_size;
1709 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1713 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1715 memcpy(buffer, diobuf, status);
1716 if (status == (ssize_t) read_length)
1719 read_length -= status;
1720 buffer = (char *) buffer + status;
1724 ex_status = ped_exception_throw (
1725 PED_EXCEPTION_ERROR,
1726 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1728 ? _("end of file while reading %s")
1729 : _("%s during read on %s")),
1733 switch (ex_status) {
1734 case PED_EXCEPTION_IGNORE:
1738 case PED_EXCEPTION_RETRY:
1741 case PED_EXCEPTION_UNHANDLED:
1742 ped_exception_catch ();
1743 case PED_EXCEPTION_CANCEL:
1747 PED_ASSERT (0, (void) 0);
1758 _write_lastoddsector (PedDevice* dev, const void* buffer)
1760 LinuxSpecific* arch_specific;
1761 struct blkdev_ioctl_param ioctl_param;
1763 PED_ASSERT(dev != NULL, return 0);
1764 PED_ASSERT(buffer != NULL, return 0);
1766 arch_specific = LINUX_SPECIFIC (dev);
1769 ioctl_param.block = 0; /* write the last sector */
1770 ioctl_param.content_length = dev->sector_size;
1771 ioctl_param.block_contents = (void*) buffer;
1773 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1774 PedExceptionOption opt;
1775 opt = ped_exception_throw (
1776 PED_EXCEPTION_ERROR,
1777 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1778 _("%s during write on %s"),
1779 strerror (errno), dev->path);
1781 if (opt == PED_EXCEPTION_CANCEL)
1783 if (opt == PED_EXCEPTION_RETRY)
1791 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1794 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1795 PedExceptionOption ex_status;
1799 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1801 if (dev->read_only) {
1802 if (ped_exception_throw (
1803 PED_EXCEPTION_ERROR,
1804 PED_EXCEPTION_IGNORE_CANCEL,
1805 _("Can't write to %s, because it is opened read-only."),
1807 != PED_EXCEPTION_IGNORE)
1813 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1814 /* Kludge. This is necessary to read/write the last
1815 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1817 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1818 && start + count - 1 == dev->length - 1)
1819 return ped_device_write (dev, buffer, start, count - 1)
1820 && _write_lastoddsector (
1821 dev, ((char*) buffer
1822 + (count-1) * dev->sector_size));
1825 if (_device_seek (dev, start))
1828 ex_status = ped_exception_throw (
1829 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1830 _("%s during seek for write on %s"),
1831 strerror (errno), dev->path);
1833 switch (ex_status) {
1834 case PED_EXCEPTION_IGNORE:
1837 case PED_EXCEPTION_RETRY:
1840 case PED_EXCEPTION_UNHANDLED:
1841 ped_exception_catch ();
1842 case PED_EXCEPTION_CANCEL:
1845 PED_ASSERT (0, (void) 0);
1851 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1852 dev->path, buffer, (int) start, (int) count);
1854 size_t write_length = count * dev->sector_size;
1856 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1858 memcpy(diobuf, buffer, write_length);
1859 diobuf_start = diobuf;
1861 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1862 if (status == write_length) break;
1864 write_length -= status;
1865 diobuf = (char *) diobuf + status;
1869 ex_status = ped_exception_throw (
1870 PED_EXCEPTION_ERROR,
1871 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1872 _("%s during write on %s"),
1873 strerror (errno), dev->path);
1875 switch (ex_status) {
1876 case PED_EXCEPTION_IGNORE:
1880 case PED_EXCEPTION_RETRY:
1883 case PED_EXCEPTION_UNHANDLED:
1884 ped_exception_catch ();
1885 case PED_EXCEPTION_CANCEL:
1889 PED_ASSERT (0, (void) 0);
1894 #endif /* !READ_ONLY */
1898 /* returns the number of sectors that are ok.
1901 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1903 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1908 PED_ASSERT(dev != NULL, return 0);
1910 if (!_device_seek (dev, start))
1913 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1914 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1917 for (done = 0; done < count; done += status / dev->sector_size) {
1918 status = read (arch_specific->fd, diobuf,
1919 (size_t) ((count-done) * dev->sector_size));
1921 memcpy(buffer, diobuf, status);
1931 _do_fsync (PedDevice* dev)
1933 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1935 PedExceptionOption ex_status;
1938 status = fsync (arch_specific->fd);
1939 if (status >= 0) break;
1941 ex_status = ped_exception_throw (
1942 PED_EXCEPTION_ERROR,
1943 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1944 _("%s during write on %s"),
1945 strerror (errno), dev->path);
1947 switch (ex_status) {
1948 case PED_EXCEPTION_IGNORE:
1951 case PED_EXCEPTION_RETRY:
1954 case PED_EXCEPTION_UNHANDLED:
1955 ped_exception_catch ();
1956 case PED_EXCEPTION_CANCEL:
1959 PED_ASSERT (0, (void) 0);
1967 linux_sync (PedDevice* dev)
1969 PED_ASSERT (dev != NULL, return 0);
1970 PED_ASSERT (!dev->external_mode, return 0);
1974 if (!_do_fsync (dev))
1981 linux_sync_fast (PedDevice* dev)
1983 PED_ASSERT (dev != NULL, return 0);
1984 PED_ASSERT (!dev->external_mode, return 0);
1988 if (!_do_fsync (dev))
1990 /* no cache flush... */
1995 _compare_digit_state (char ch, int need_digit)
1997 return !!isdigit (ch) == need_digit;
2000 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
2001 * Motivation: accept devices looking like /dev/rd/c0d0, but
2002 * not looking like /dev/hda1 and /dev/rd/c0d0p1
2005 _match_rd_device (const char* name)
2010 /* exclude directory names from test */
2011 pos = strrchr(name, '/') ?: name;
2019 for (state = 0; state < 4; state++) {
2020 int want_digits = (state % 2 == 1);
2024 if (!_compare_digit_state (*pos, want_digits))
2027 } while (_compare_digit_state (*pos, want_digits));
2034 _probe_proc_partitions ()
2036 FILE* proc_part_file;
2037 int major, minor, size;
2039 char part_name [256];
2040 char dev_name [256];
2042 proc_part_file = fopen ("/proc/partitions", "r");
2043 if (!proc_part_file)
2046 if (fgets (buf, 256, proc_part_file) == NULL)
2049 if (fgets (buf, 256, proc_part_file) == NULL)
2052 while (fgets (buf, 512, proc_part_file)
2053 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
2055 /* Heuristic for telling partitions and devices apart
2056 * Probably needs to be improved
2058 if (!_match_rd_device (part_name)
2059 && isdigit (part_name [strlen (part_name) - 1]))
2062 strcpy (dev_name, "/dev/");
2063 strcat (dev_name, part_name);
2064 _ped_device_probe (dev_name);
2067 fclose (proc_part_file);
2077 _skip_entry (const char *name)
2080 static struct _entry entries[] = {
2081 { ".", sizeof (".") - 1 },
2082 { "..", sizeof ("..") - 1 },
2083 { "dm-", sizeof ("dm-") - 1 },
2084 { "loop", sizeof ("loop") - 1 },
2085 { "ram", sizeof ("ram") - 1 },
2089 for (i = entries; i->name != 0; i++) {
2090 if (strncmp (name, i->name, i->len) == 0)
2101 struct dirent *dirent;
2102 char dev_name [256];
2105 if (!(blockdir = opendir ("/sys/block")))
2107 while ((dirent = readdir (blockdir))) {
2108 if (_skip_entry (dirent->d_name))
2111 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2112 continue; /* device name too long! */
2114 strcpy (dev_name, "/dev/");
2115 strcat (dev_name, dirent->d_name);
2116 /* in /sys/block, '/'s are replaced with '!' or '.' */
2117 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2118 if (*ptr == '!' || *ptr == '.')
2121 _ped_device_probe (dev_name);
2124 closedir (blockdir);
2129 _probe_standard_devices ()
2131 _ped_device_probe ("/dev/hda");
2132 _ped_device_probe ("/dev/hdb");
2133 _ped_device_probe ("/dev/hdc");
2134 _ped_device_probe ("/dev/hdd");
2135 _ped_device_probe ("/dev/hde");
2136 _ped_device_probe ("/dev/hdf");
2137 _ped_device_probe ("/dev/hdg");
2138 _ped_device_probe ("/dev/hdh");
2140 _ped_device_probe ("/dev/sda");
2141 _ped_device_probe ("/dev/sdb");
2142 _ped_device_probe ("/dev/sdc");
2143 _ped_device_probe ("/dev/sdd");
2144 _ped_device_probe ("/dev/sde");
2145 _ped_device_probe ("/dev/sdf");
2153 /* we should probe the standard devs too, even with /proc/partitions,
2154 * because /proc/partitions might return devfs stuff, and we might not
2155 * have devfs available
2157 _probe_standard_devices ();
2159 #ifdef ENABLE_DEVICE_MAPPER
2160 /* device-mapper devices aren't listed in /proc/partitions; or, if
2161 * they are, they're listed as dm-X. So, instead of relying on that,
2162 * we do our own checks.
2164 _probe_dm_devices ();
2167 /* /sys/block is more reliable and consistent; fall back to using
2168 * /proc/partitions if the former is unavailable, however.
2170 if (!_probe_sys_block ())
2171 _probe_proc_partitions ();
2175 _device_get_part_path (PedDevice* dev, int num)
2177 int path_len = strlen (dev->path);
2178 int result_len = path_len + 16;
2181 result = (char*) ped_malloc (result_len);
2185 /* Check for devfs-style /disc => /partN transformation
2186 unconditionally; the system might be using udev with devfs rules,
2187 and if not the test is harmless. */
2188 if (!strcmp (dev->path + path_len - 5, "/disc")) {
2189 /* replace /disc with /path%d */
2190 strcpy (result, dev->path);
2191 snprintf (result + path_len - 5, 16, "/part%d", num);
2192 } else if (dev->type == PED_DEVICE_DAC960
2193 || dev->type == PED_DEVICE_CPQARRAY
2194 || dev->type == PED_DEVICE_ATARAID
2195 || dev->type == PED_DEVICE_DM
2196 || isdigit (dev->path[path_len - 1]))
2197 snprintf (result, result_len, "%sp%d", dev->path, num);
2199 snprintf (result, result_len, "%s%d", dev->path, num);
2205 linux_partition_get_path (const PedPartition* part)
2207 return _device_get_part_path (part->disk->dev, part->num);
2211 _partition_get_part_dev (const PedPartition* part)
2213 struct stat dev_stat;
2214 int dev_major, dev_minor;
2216 if (stat (part->disk->dev->path, &dev_stat))
2218 dev_major = major (dev_stat.st_rdev);
2219 dev_minor = minor (dev_stat.st_rdev);
2220 return (dev_t)makedev (dev_major, dev_minor + part->num);
2224 _mount_table_search (const char* file_name, dev_t dev)
2226 struct stat part_stat;
2228 char part_name[512];
2231 file = fopen (file_name, "r");
2234 while (fgets (line, 512, file)) {
2235 if (sscanf (line, "%s", part_name) == 1
2236 && stat (part_name, &part_stat) == 0) {
2237 if (part_stat.st_rdev == dev) {
2248 _partition_is_mounted_by_dev (dev_t dev)
2250 return _mount_table_search( "/proc/mounts", dev)
2251 || _mount_table_search( "/proc/swaps", dev)
2252 || _mount_table_search( "/etc/mtab", dev);
2256 _partition_is_mounted_by_path (const char *path)
2258 struct stat part_stat;
2259 if (stat (path, &part_stat) != 0)
2261 if (!S_ISBLK(part_stat.st_mode))
2263 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2267 _partition_is_mounted (const PedPartition *part)
2270 if (!ped_partition_is_active (part))
2272 dev = _partition_get_part_dev (part);
2275 return _partition_is_mounted_by_dev (dev);
2279 _has_partitions (const PedDisk* disk)
2281 PED_ASSERT(disk != NULL, return 0);
2283 /* Some devices can't be partitioned. */
2284 if (!strcmp (disk->type->name, "loop"))
2291 linux_partition_is_busy (const PedPartition* part)
2295 PED_ASSERT (part != NULL, return 0);
2297 if (_partition_is_mounted (part))
2299 if (part->type == PED_PARTITION_EXTENDED) {
2300 for (walk = part->part_list; walk; walk = walk->next) {
2301 if (linux_partition_is_busy (walk))
2309 _blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
2311 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2312 struct blkpg_ioctl_arg ioctl_arg;
2315 ioctl_arg.flags = 0;
2316 ioctl_arg.datalen = sizeof (struct blkpg_partition);
2317 ioctl_arg.data = (void*) part;
2319 return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
2323 _blkpg_add_partition (PedDisk* disk, const PedPartition *part)
2325 struct blkpg_partition linux_part;
2326 const char* vol_name;
2329 PED_ASSERT(disk != NULL, return 0);
2330 PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0,
2333 if (!_has_partitions (disk))
2336 if (ped_disk_type_check_feature (disk->type,
2337 PED_DISK_TYPE_PARTITION_NAME))
2338 vol_name = ped_partition_get_name (part);
2342 dev_name = _device_get_part_path (disk->dev, part->num);
2346 memset (&linux_part, 0, sizeof (linux_part));
2347 linux_part.start = part->geom.start * disk->dev->sector_size;
2348 /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
2349 if (part->type & PED_PARTITION_EXTENDED)
2350 linux_part.length = part->geom.length == 1 ? 512 : 1024;
2352 linux_part.length = part->geom.length * disk->dev->sector_size;
2353 linux_part.pno = part->num;
2354 strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
2356 strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
2360 if (!_blkpg_part_command (disk->dev, &linux_part,
2361 BLKPG_ADD_PARTITION)) {
2362 return ped_exception_throw (
2363 PED_EXCEPTION_ERROR,
2364 PED_EXCEPTION_IGNORE_CANCEL,
2365 _("Error informing the kernel about modifications to "
2366 "partition %s -- %s. This means Linux won't know "
2367 "about any changes you made to %s until you reboot "
2368 "-- so you shouldn't mount it or use it in any way "
2369 "before rebooting."),
2373 == PED_EXCEPTION_IGNORE;
2380 _blkpg_remove_partition (PedDisk* disk, int n)
2382 struct blkpg_partition linux_part;
2384 if (!_has_partitions (disk))
2387 memset (&linux_part, 0, sizeof (linux_part));
2389 return _blkpg_part_command (disk->dev, &linux_part,
2390 BLKPG_DEL_PARTITION);
2394 * The number of partitions that a device can have depends on the kernel.
2395 * If we don't find this value in /sys/block/DEV/range, we will use our own
2399 _device_get_partition_range(PedDevice* dev)
2406 r = snprintf(path, sizeof(path), "/sys/block/%s/range",
2407 last_component(dev->path));
2408 if (r < 0 || r >= sizeof(path))
2409 return MAX_NUM_PARTS;
2411 fp = fopen(path, "r");
2413 return MAX_NUM_PARTS;
2415 ok = fscanf(fp, "%d", &range) == 1;
2418 /* (range <= 0) is none sense.*/
2419 return ok && range > 0 ? range : MAX_NUM_PARTS;
2423 * Sync the partition table in two step process:
2424 * 1. Remove all of the partitions from the kernel's tables, but do not attempt
2425 * removal of any partition for which the corresponding ioctl call fails.
2426 * 2. Add all the partitions that we hold in disk, throwing a warning
2427 * if we cannot because step 1 failed to remove it and it is not being
2428 * added back with the same start and length.
2430 * To achieve this two step process we must calculate the minimum number of
2431 * maximum possible partitions between what linux supports and what the label
2432 * type supports. EX:
2434 * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables)
2437 _disk_sync_part_table (PedDisk* disk)
2439 PED_ASSERT(disk != NULL, return 0);
2440 PED_ASSERT(disk->dev != NULL, return 0);
2443 /* lpn = largest partition number. */
2444 if (ped_disk_get_max_supported_partition_count(disk, &lpn))
2445 lpn = PED_MIN(lpn, _device_get_partition_range(disk->dev));
2447 lpn = _device_get_partition_range(disk->dev);
2449 /* Its not possible to support largest_partnum < 0.
2450 * largest_partnum == 0 would mean does not support partitions.
2455 int *rets = ped_malloc(sizeof(int) * lpn);
2458 int *errnums = ped_malloc(sizeof(int) * lpn);
2463 for (i = 1; i <= lpn; i++) {
2464 rets[i - 1] = _blkpg_remove_partition (disk, i);
2465 errnums[i - 1] = errno;
2468 for (i = 1; i <= lpn; i++) {
2469 const PedPartition *part = ped_disk_get_partition (disk, i);
2471 if (!rets[i - 1] && errnums[i - 1] == EBUSY) {
2472 struct hd_geometry geom;
2473 unsigned long long length = 0;
2474 /* get start and length of existing partition */
2475 char *dev_name = _device_get_part_path (disk->dev, i);
2478 int fd = open (dev_name, O_RDONLY);
2480 || ioctl (fd, HDIO_GETGEO, &geom)
2481 || ioctl (fd, BLKGETSIZE64, &length)) {
2482 ped_exception_throw (
2484 PED_EXCEPTION_CANCEL,
2485 _("Unable to determine the size and length of %s."),
2493 length /= disk->dev->sector_size;
2495 if (geom.start == part->geom.start
2496 && length == part->geom.length)
2498 /* If the new partition is unchanged and the
2499 existing one was not removed because it was
2500 in use, then reset the error flag and do not
2501 try to add it since it is already there. */
2505 /* add the (possibly modified or new) partition */
2506 if (!_blkpg_add_partition (disk, part)) {
2507 ped_exception_throw (
2508 PED_EXCEPTION_ERROR,
2509 PED_EXCEPTION_RETRY_CANCEL,
2510 _("Failed to add partition %d (%s)"),
2511 i, strerror (errno));
2517 char *bad_part_list = NULL;
2518 /* now warn about any errors */
2519 for (i = 1; i <= lpn; i++) {
2520 if (rets[i - 1] || errnums[i - 1] == ENXIO)
2522 if (bad_part_list == NULL) {
2523 bad_part_list = malloc (lpn * 5);
2526 bad_part_list[0] = 0;
2528 sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i);
2530 if (bad_part_list == NULL)
2533 bad_part_list[strlen (bad_part_list) - 2] = 0;
2534 if (ped_exception_throw (
2535 PED_EXCEPTION_WARNING,
2536 PED_EXCEPTION_IGNORE_CANCEL,
2537 _("Partition(s) %s on %s have been written, but we have "
2538 "been unable to inform the kernel of the change, "
2539 "probably because it/they are in use. As a result, "
2540 "the old partition(s) will remain in use. You "
2541 "should reboot now before making further changes."),
2542 bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE)
2544 free (bad_part_list);
2553 #ifdef ENABLE_DEVICE_MAPPER
2555 _dm_remove_map_name(char *name)
2557 struct dm_task *task = NULL;
2560 task = dm_task_create(DM_DEVICE_REMOVE);
2564 dm_task_set_name (task, name);
2566 rc = dm_task_run(task);
2567 dm_task_update_nodes();
2568 dm_task_destroy(task);
2576 _dm_is_part (struct dm_info *this, char *name)
2578 struct dm_task* task = NULL;
2579 struct dm_info* info = alloca(sizeof *info);
2580 struct dm_deps* deps = NULL;
2584 task = dm_task_create(DM_DEVICE_DEPS);
2588 dm_task_set_name(task, name);
2589 if (!dm_task_run(task))
2592 memset(info, '\0', sizeof *info);
2593 dm_task_get_info(task, info);
2597 deps = dm_task_get_deps(task);
2601 for (i = 0; i < deps->count; i++) {
2602 unsigned int ma = major(deps->device[i]),
2603 mi = minor(deps->device[i]);
2605 if (ma == this->major && mi == this->minor)
2610 dm_task_destroy(task);
2615 _dm_remove_parts (PedDevice* dev)
2617 struct dm_task* task = NULL;
2618 struct dm_info* info = alloca(sizeof *info);
2619 struct dm_names* names = NULL;
2620 unsigned int next = 0;
2622 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2624 task = dm_task_create(DM_DEVICE_LIST);
2628 if (!dm_task_set_major_minor (task, arch_specific->major,
2629 arch_specific->minor, 0))
2632 if (!dm_task_run(task))
2635 memset(info, '\0', sizeof *info);
2636 dm_task_get_info(task, info);
2640 names = dm_task_get_names(task);
2646 names = (void *) ((char *) names + next);
2648 if (_dm_is_part(info, names->name))
2649 rc += _dm_remove_map_name(names->name);
2654 dm_task_update_nodes();
2655 dm_task_destroy(task);
2662 dm_task_destroy(task);
2663 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2664 _("parted was unable to re-read the partition "
2665 "table on %s (%s). This means Linux won't know "
2666 "anything about the modifications you made. "),
2667 dev->path, strerror (errno));
2672 _dm_add_partition (PedDisk* disk, PedPartition* part)
2674 char* vol_name = NULL;
2675 const char* dev_name = NULL;
2676 char* params = NULL;
2677 LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
2679 if (!_has_partitions(disk))
2682 /* Get map name from devicemapper */
2683 struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
2687 if (!dm_task_set_major_minor (task, arch_specific->major,
2688 arch_specific->minor, 0))
2691 if (!dm_task_run(task))
2694 dev_name = dm_task_get_name (task);
2696 if (asprintf (&vol_name, "%sp%d", dev_name, part->num) == -1)
2699 /* Caution: dm_task_destroy frees dev_name. */
2700 dm_task_destroy (task);
2703 if (asprintf (¶ms, "%d:%d %lld", arch_specific->major,
2704 arch_specific->minor, part->geom.start) == -1)
2707 task = dm_task_create (DM_DEVICE_CREATE);
2711 dm_task_set_name (task, vol_name);
2712 dm_task_add_target (task, 0, part->geom.length,
2714 if (dm_task_run (task)) {
2715 //printf("0 %ld linear %s\n", part->geom.length, params);
2716 dm_task_update_nodes();
2717 dm_task_destroy(task);
2722 _dm_remove_map_name(vol_name);
2725 dm_task_update_nodes();
2727 dm_task_destroy (task);
2734 _dm_reread_part_table (PedDisk* disk)
2736 int largest_partnum = ped_disk_get_last_partition_num (disk);
2737 if (largest_partnum <= 0)
2741 int last = PED_MIN (largest_partnum, 16);
2745 if (!_dm_remove_parts(disk->dev))
2748 for (i = 1; i <= last; i++) {
2751 part = ped_disk_get_partition (disk, i);
2755 if (!_dm_add_partition (disk, part))
2763 _kernel_reread_part_table (PedDevice* dev)
2765 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2766 int retry_count = 9;
2769 while (ioctl (arch_specific->fd, BLKRRPART)) {
2772 if (retry_count == 3)
2773 sleep(1); /* Pause to allow system to settle */
2776 ped_exception_throw (
2777 PED_EXCEPTION_WARNING,
2778 PED_EXCEPTION_IGNORE,
2779 _("WARNING: the kernel failed to re-read the partition "
2780 "table on %s (%s). As a result, it may not "
2781 "reflect all of your changes until after reboot."),
2782 dev->path, strerror (errno));
2793 static int have_blkpg = -1;
2796 if (have_blkpg != -1)
2799 kver = _get_linux_version();
2800 return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
2803 /* Return nonzero upon success, 0 if something fails. */
2805 linux_disk_commit (PedDisk* disk)
2807 if (!_has_partitions (disk))
2810 #ifdef ENABLE_DEVICE_MAPPER
2811 if (disk->dev->type == PED_DEVICE_DM)
2812 return _dm_reread_part_table (disk);
2814 if (disk->dev->type != PED_DEVICE_FILE) {
2815 /* The ioctl() command BLKPG_ADD_PARTITION does not notify
2816 * the devfs system; consequently, /proc/partitions will not
2817 * be up to date, and the proper links in /dev are not
2818 * created. Therefore, if using DevFS, we must get the kernel
2819 * to re-read and grok the partition table.
2821 /* Work around kernel dasd problem so we really do BLKRRPART */
2823 if (disk->dev->type != PED_DEVICE_DASD && _have_blkpg ()) {
2824 if (!_disk_sync_part_table (disk))
2828 if (!_kernel_reread_part_table (disk->dev))
2837 static PedAlignment*
2838 linux_get_minimum_alignment(const PedDevice *dev)
2840 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2844 if (blkid_topology_get_minimum_io_size(tp) == 0)
2845 return ped_alignment_new(
2846 blkid_topology_get_alignment_offset(tp) /
2848 dev->phys_sector_size / dev->sector_size);
2850 return ped_alignment_new(
2851 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2852 blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
2855 static PedAlignment*
2856 linux_get_optimum_alignment(const PedDevice *dev)
2858 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2862 /* If optimal_io_size is 0 _and_ alignment_offset is 0 _and_
2863 minimum_io_size is a power of 2 then go with the device.c default */
2864 unsigned long minimum_io_size = blkid_topology_get_minimum_io_size(tp);
2865 if (blkid_topology_get_optimal_io_size(tp) == 0 &&
2866 blkid_topology_get_alignment_offset(tp) == 0 &&
2867 (minimum_io_size & (minimum_io_size - 1)) == 0)
2870 /* If optimal_io_size is 0 and we don't meet the other criteria
2871 for using the device.c default, return the minimum alignment. */
2872 if (blkid_topology_get_optimal_io_size(tp) == 0)
2873 return linux_get_minimum_alignment(dev);
2875 return ped_alignment_new(
2876 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2877 blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
2881 static PedDeviceArchOps linux_dev_ops = {
2883 destroy: linux_destroy,
2884 is_busy: linux_is_busy,
2886 refresh_open: linux_refresh_open,
2888 refresh_close: linux_refresh_close,
2893 sync_fast: linux_sync_fast,
2894 probe_all: linux_probe_all,
2896 get_minimum_alignment: linux_get_minimum_alignment,
2897 get_optimum_alignment: linux_get_optimum_alignment,
2901 PedDiskArchOps linux_disk_ops = {
2902 partition_get_path: linux_partition_get_path,
2903 partition_is_busy: linux_partition_is_busy,
2904 disk_commit: linux_disk_commit
2907 PedArchitecture ped_linux_arch = {
2908 dev_ops: &linux_dev_ops,
2909 disk_ops: &linux_disk_ops