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 /* The __attribute__ feature is available in gcc versions 2.5 and later.
60 The __-protected variants of the attributes 'format' and 'printf' are
61 accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
62 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
63 # define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
65 # define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
68 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
71 #define __NR__llseek 140
74 #ifndef SCSI_IOCTL_SEND_COMMAND
75 #define SCSI_IOCTL_SEND_COMMAND 1
78 /* from <linux/hdreg.h> */
79 #define HDIO_GETGEO 0x0301 /* get device geometry */
80 #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
82 #define RD_MODE (O_RDONLY)
83 #define WR_MODE (O_WRONLY)
84 #define RW_MODE (O_RDWR)
88 unsigned char sectors;
89 unsigned short cylinders;
93 struct ata7_sectinfo {
100 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
102 unsigned short config; /* lots of obsolete bit flags */
103 unsigned short cyls; /* "physical" cyls */
104 unsigned short reserved2; /* reserved (word 2) */
105 unsigned short heads; /* "physical" heads */
106 unsigned short track_bytes; /* unformatted bytes per track */
107 unsigned short sector_bytes; /* unformatted bytes per sector */
108 unsigned short sectors; /* "physical" sectors per track */
109 unsigned short vendor0; /* vendor unique */
110 unsigned short vendor1; /* vendor unique */
111 unsigned short vendor2; /* vendor unique */
112 unsigned char serial_no[20]; /* 0 = not_specified */
113 unsigned short buf_type;
114 unsigned short buf_size; /* 512 byte increments;
116 unsigned short ecc_bytes; /* for r/w long cmds;
118 unsigned char fw_rev[8]; /* 0 = not_specified */
119 char model[40]; /* 0 = not_specified */
120 unsigned char max_multsect; /* 0=not_implemented */
121 unsigned char vendor3; /* vendor unique */
122 unsigned short dword_io; /* 0=not_implemented; 1=implemented */
123 unsigned char vendor4; /* vendor unique */
124 unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
126 unsigned short reserved50; /* reserved (word 50) */
127 unsigned char vendor5; /* vendor unique */
128 unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
129 unsigned char vendor6; /* vendor unique */
130 unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
131 unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
132 unsigned short cur_cyls; /* logical cylinders */
133 unsigned short cur_heads; /* logical heads */
134 unsigned short cur_sectors; /* logical sectors per track */
135 unsigned short cur_capacity0; /* logical total sectors on drive */
136 unsigned short cur_capacity1; /* (2 words, misaligned int) */
137 unsigned char multsect; /* current multiple sector count */
138 unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
139 unsigned int lba_capacity; /* total number of sectors */
140 unsigned short dma_1word; /* single-word dma info */
141 unsigned short dma_mword; /* multiple-word dma info */
142 unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
143 unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
144 unsigned short eide_dma_time; /* recommended mword dma cycle
146 unsigned short eide_pio; /* min cycle time (ns), no IORDY */
147 unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
148 unsigned short words69_70[2]; /* reserved words 69-70 */
149 /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
150 unsigned short words71_74[4]; /* reserved words 71-74 */
151 unsigned short queue_depth; /* */
152 unsigned short words76_79[4]; /* reserved words 76-79 */
153 unsigned short major_rev_num; /* */
154 unsigned short minor_rev_num; /* */
155 unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
157 unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
158 unsigned short cfsse; /* command set-feature supported
160 unsigned short cfs_enable_1; /* command set-feature enabled */
161 unsigned short cfs_enable_2; /* command set-feature enabled */
162 unsigned short csf_default; /* command set-feature default */
163 unsigned short dma_ultra; /* */
164 unsigned short word89; /* reserved (word 89) */
165 unsigned short word90; /* reserved (word 90) */
166 unsigned short CurAPMvalues; /* current APM values */
167 unsigned short word92; /* reserved (word 92) */
168 unsigned short hw_config; /* hardware config */
169 unsigned short words94_105[12];/* reserved words 94-105 */
170 struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
172 unsigned short words107_116[10];/* reserved words 107-116 */
173 unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
174 unsigned short words119_125[7];/* reserved words 119-125 */
175 unsigned short last_lun; /* reserved (word 126) */
176 unsigned short word127; /* reserved (word 127) */
177 unsigned short dlf; /* device lock function
179 * 8 security level 1:max 0:high
188 unsigned short csfo; /* current set features options
195 unsigned short words130_155[26];/* reserved vendor words 130-155 */
196 unsigned short word156;
197 unsigned short words157_159[3]; /* reserved vendor words 157-159 */
198 unsigned short words160_255[95];/* reserved words 160-255 */
201 /* from <linux/fs.h> */
202 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
203 #define BLKGETSIZE _IO(0x12,96) /* return device size */
204 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
205 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
206 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
207 #define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
209 /* return device size in bytes (u64 *arg) */
210 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
212 struct blkdev_ioctl_param {
214 size_t content_length;
215 char * block_contents;
218 /* from <linux/major.h> */
220 #define IDE1_MAJOR 22
221 #define IDE2_MAJOR 33
222 #define IDE3_MAJOR 34
223 #define IDE4_MAJOR 56
224 #define IDE5_MAJOR 57
225 #define SCSI_CDROM_MAJOR 11
226 #define SCSI_DISK0_MAJOR 8
227 #define SCSI_DISK1_MAJOR 65
228 #define SCSI_DISK2_MAJOR 66
229 #define SCSI_DISK3_MAJOR 67
230 #define SCSI_DISK4_MAJOR 68
231 #define SCSI_DISK5_MAJOR 69
232 #define SCSI_DISK6_MAJOR 70
233 #define SCSI_DISK7_MAJOR 71
234 #define SCSI_DISK8_MAJOR 128
235 #define SCSI_DISK9_MAJOR 129
236 #define SCSI_DISK10_MAJOR 130
237 #define SCSI_DISK11_MAJOR 131
238 #define SCSI_DISK12_MAJOR 132
239 #define SCSI_DISK13_MAJOR 133
240 #define SCSI_DISK14_MAJOR 134
241 #define SCSI_DISK15_MAJOR 135
242 #define COMPAQ_SMART2_MAJOR 72
243 #define COMPAQ_SMART2_MAJOR1 73
244 #define COMPAQ_SMART2_MAJOR2 74
245 #define COMPAQ_SMART2_MAJOR3 75
246 #define COMPAQ_SMART2_MAJOR4 76
247 #define COMPAQ_SMART2_MAJOR5 77
248 #define COMPAQ_SMART2_MAJOR6 78
249 #define COMPAQ_SMART2_MAJOR7 79
250 #define COMPAQ_SMART_MAJOR 104
251 #define COMPAQ_SMART_MAJOR1 105
252 #define COMPAQ_SMART_MAJOR2 106
253 #define COMPAQ_SMART_MAJOR3 107
254 #define COMPAQ_SMART_MAJOR4 108
255 #define COMPAQ_SMART_MAJOR5 109
256 #define COMPAQ_SMART_MAJOR6 110
257 #define COMPAQ_SMART_MAJOR7 111
258 #define DAC960_MAJOR 48
259 #define ATARAID_MAJOR 114
260 #define I2O_MAJOR1 80
261 #define I2O_MAJOR2 81
262 #define I2O_MAJOR3 82
263 #define I2O_MAJOR4 83
264 #define I2O_MAJOR5 84
265 #define I2O_MAJOR6 85
266 #define I2O_MAJOR7 86
267 #define I2O_MAJOR8 87
269 #define DASD_MAJOR 94
270 #define VIODASD_MAJOR 112
271 #define AOE_MAJOR 152
272 #define SX8_MAJOR1 160
273 #define SX8_MAJOR2 161
274 #define XVD_MAJOR 202
275 #define SDMMC_MAJOR 179
279 #define SCSI_BLK_MAJOR(M) ( \
280 (M) == SCSI_DISK0_MAJOR \
281 || (M) == SCSI_CDROM_MAJOR \
282 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) \
283 || ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
285 /* Maximum number of partitions supported by linux. */
286 #define MAX_NUM_PARTS 64
288 static char* _device_get_part_path (PedDevice* dev, int num);
289 static int _partition_is_mounted_by_path (const char* path);
292 _read_fd (int fd, char **buf)
295 size_t size = PROC_DEVICES_BUFSIZ;
298 *buf = malloc (size * sizeof (char));
304 p = &(*buf) [filesize];
305 s = read (fd, p, PROC_DEVICES_BUFSIZ);
306 /* exit if there is an error or EOF is reached */
311 char *new_buf = realloc (*buf, size);
312 if (new_buf == NULL) {
313 int saved_errno = errno;
321 if (filesize == 0 && s < 0) {
326 char *new_buf = realloc (*buf, filesize + 1);
327 if (new_buf == NULL) {
328 int saved_errno = errno;
334 (*buf)[filesize] = '\0';
341 _major_type_in_devices (int major, const char* type)
350 fd = open ("/proc/devices", O_RDONLY);
354 if (_read_fd(fd, &buf) < 0) {
360 end = strchr(line, '\n');
369 if (!strncmp(line, "Block devices:", 14))
374 name = strrchr(line, ' ');
375 if (!name || strcmp(name+1, type))
378 maj = strtol(line, &name, 10);
388 end = strchr(line, '\n');
396 _is_ide_major (int major)
413 _is_cpqarray_major (int major)
415 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
416 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
420 _is_i2o_major (int major)
422 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
426 _is_sx8_major (int major)
428 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
432 _is_virtblk_major (int major)
434 return _major_type_in_devices (major, "virtblk");
437 #ifdef ENABLE_DEVICE_MAPPER
439 _is_dm_major (int major)
441 return _major_type_in_devices (major, "device-mapper");
445 _dm_maptype (PedDevice *dev)
447 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
449 uint64_t start, length;
450 char *target_type = NULL;
453 const char* dev_dir = getenv ("DM_DEV_DIR");
455 if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
458 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
461 if (!dm_task_set_major_minor(dmt, arch_specific->major,
462 arch_specific->minor, 0))
465 dm_task_no_open_count(dmt);
467 if (!dm_task_run(dmt))
470 dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms);
472 arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
473 if (arch_specific->dmtype == NULL)
477 dm_task_destroy(dmt);
487 char buf [512]; /* readdir(3) claims d_name[256] */
490 mapper_dir = opendir ("/dev/mapper");
494 /* Search the /dev/mapper directory for devices w/ the same major
495 * number that was returned from _probe_lvm_major().
497 while ((dent = readdir (mapper_dir))) {
498 if (strcmp (dent->d_name, ".") == 0 ||
499 strcmp (dent->d_name, "..") == 0)
502 snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
504 if (stat (buf, &st) != 0)
507 if (_is_dm_major(major(st.st_rdev)))
508 _ped_device_probe (buf);
510 closedir (mapper_dir);
517 _device_stat (PedDevice* dev, struct stat * dev_stat)
519 PED_ASSERT (dev != NULL);
520 PED_ASSERT (!dev->external_mode);
523 if (!stat (dev->path, dev_stat)) {
526 if (ped_exception_throw (
528 PED_EXCEPTION_RETRY_CANCEL,
529 _("Could not stat device %s - %s."),
532 != PED_EXCEPTION_RETRY)
539 _device_probe_type (PedDevice* dev)
541 struct stat dev_stat;
544 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
546 if (!_device_stat (dev, &dev_stat))
549 if (!S_ISBLK(dev_stat.st_mode)) {
550 dev->type = PED_DEVICE_FILE;
554 arch_specific->major = dev_major = major (dev_stat.st_rdev);
555 arch_specific->minor = dev_minor = minor (dev_stat.st_rdev);
557 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
558 dev->type = PED_DEVICE_SCSI;
559 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
560 dev->type = PED_DEVICE_IDE;
561 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
562 dev->type = PED_DEVICE_DAC960;
563 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
564 dev->type = PED_DEVICE_ATARAID;
565 } else if (dev_major == AOE_MAJOR && (dev_minor % 0x10 == 0)) {
566 dev->type = PED_DEVICE_AOE;
567 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
568 dev->type = PED_DEVICE_DASD;
569 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
570 dev->type = PED_DEVICE_VIODASD;
571 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
572 dev->type = PED_DEVICE_SX8;
573 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
574 dev->type = PED_DEVICE_I2O;
575 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
576 dev->type = PED_DEVICE_CPQARRAY;
577 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
578 dev->type = PED_DEVICE_UBD;
579 #ifdef ENABLE_DEVICE_MAPPER
580 } else if (_is_dm_major(dev_major)) {
581 dev->type = PED_DEVICE_DM;
582 if (_dm_maptype(dev)) {
583 ped_exception_throw (
585 PED_EXCEPTION_CANCEL,
586 _("Unable to determine the dm type of %s."),
590 } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
591 dev->type = PED_DEVICE_XVD;
592 } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
593 dev->type = PED_DEVICE_SDMMC;
594 } else if (_is_virtblk_major(dev_major)) {
595 dev->type = PED_DEVICE_VIRTBLK;
596 } else if (dev_major == LOOP_MAJOR) {
597 dev->type = PED_DEVICE_LOOP;
598 } else if (dev_major == MD_MAJOR) {
599 dev->type = PED_DEVICE_MD;
601 dev->type = PED_DEVICE_UNKNOWN;
608 _get_linux_version ()
610 static int kver = -1;
622 int n = sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny);
623 assert (n == 2 || n == 3);
624 return kver = KERNEL_VERSION (major, minor, teeny);
630 static int have_kern26 = -1;
633 if (have_kern26 != -1)
636 kver = _get_linux_version();
637 return have_kern26 = kver >= KERNEL_VERSION (2,6,0) ? 1 : 0;
642 get_blkid_topology (LinuxSpecific *arch_specific)
644 arch_specific->probe = blkid_new_probe ();
645 if (!arch_specific->probe)
648 if (blkid_probe_set_device(arch_specific->probe,
649 arch_specific->fd, 0, 0))
652 arch_specific->topology =
653 blkid_probe_get_topology(arch_specific->probe);
658 _device_set_sector_size (PedDevice* dev)
660 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
663 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
664 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
666 PED_ASSERT (dev->open_count);
668 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
669 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
673 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
674 ped_exception_throw (
675 PED_EXCEPTION_WARNING,
677 _("Could not determine sector size for %s: %s.\n"
678 "Using the default sector size (%lld)."),
679 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
681 dev->sector_size = (long long)sector_size;
682 dev->phys_sector_size = dev->sector_size;
686 get_blkid_topology(arch_specific);
687 if (!arch_specific->topology) {
688 dev->phys_sector_size = 0;
690 dev->phys_sector_size =
691 blkid_topology_get_physical_sector_size(
692 arch_specific->topology);
694 if (dev->phys_sector_size == 0) {
695 ped_exception_throw (
696 PED_EXCEPTION_WARNING,
698 _("Could not determine physical sector size for %s.\n"
699 "Using the logical sector size (%lld)."),
700 dev->path, dev->sector_size);
701 dev->phys_sector_size = dev->sector_size;
705 #if defined __s390__ || defined __s390x__
706 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
707 if (dev->type == PED_DEVICE_DASD) {
708 arch_specific->real_sector_size = dev->sector_size;
709 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
715 _kernel_has_blkgetsize64(void)
717 int version = _get_linux_version();
719 if (version >= KERNEL_VERSION (2,5,4)) return 1;
720 if (version < KERNEL_VERSION (2,5,0) &&
721 version >= KERNEL_VERSION (2,4,18)) return 1;
725 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
727 _device_get_length (PedDevice* dev)
730 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
732 const char* test_str;
736 PED_ASSERT (dev->open_count > 0);
737 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
739 test_str = getenv ("PARTED_TEST_DEVICE_LENGTH");
741 && xstrtoll (test_str, NULL, 10, &test_size, NULL) == LONGINT_OK)
744 if (_kernel_has_blkgetsize64()) {
745 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
746 return bytes / dev->sector_size;
750 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
751 ped_exception_throw (
753 PED_EXCEPTION_CANCEL,
754 _("Unable to determine the size of %s (%s)."),
764 _device_probe_geometry (PedDevice* dev)
766 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
767 struct stat dev_stat;
768 struct hd_geometry geometry;
770 if (!_device_stat (dev, &dev_stat))
772 PED_ASSERT (S_ISBLK (dev_stat.st_mode));
774 _device_set_sector_size (dev);
776 dev->length = _device_get_length (dev);
780 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
781 * still use it in 2.4.x, but this is contentious. Perhaps we should
783 dev->bios_geom.sectors = 63;
784 dev->bios_geom.heads = 255;
785 dev->bios_geom.cylinders
786 = dev->length / (63 * 255);
788 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
789 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
790 && geometry.sectors && geometry.heads) {
791 dev->hw_geom.sectors = geometry.sectors;
792 dev->hw_geom.heads = geometry.heads;
793 dev->hw_geom.cylinders
794 = dev->length / (dev->hw_geom.heads
795 * dev->hw_geom.sectors);
797 dev->hw_geom = dev->bios_geom;
804 strip_name(char* str)
809 for (i = 0; str[i] != 0; i++) {
810 if (!isspace (str[i])
811 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
821 init_ide (PedDevice* dev)
823 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
824 struct stat dev_stat;
825 struct hd_driveid hdi;
826 PedExceptionOption ex_status;
828 int sector_multiplier = 0;
830 if (!_device_stat (dev, &dev_stat))
833 if (!ped_device_open (dev))
836 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
837 ex_status = ped_exception_throw (
838 PED_EXCEPTION_WARNING,
839 PED_EXCEPTION_IGNORE_CANCEL,
840 _("Could not get identity of device %s - %s"),
841 dev->path, strerror (errno));
843 case PED_EXCEPTION_CANCEL:
844 goto error_close_dev;
846 case PED_EXCEPTION_UNHANDLED:
847 ped_exception_catch ();
848 case PED_EXCEPTION_IGNORE:
849 dev->model = strdup(_("Generic IDE"));
856 /* hdi.model is not guaranteed to be NULL terminated */
857 memcpy (hdi_buf, hdi.model, 40);
859 dev->model = strip_name (hdi_buf);
861 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
862 sector_multiplier = hdi.ata7_sectinfo.multiplier;
864 sector_multiplier = 1;
866 if (sector_multiplier != 1) {
867 ex_status = ped_exception_throw (
868 PED_EXCEPTION_WARNING,
869 PED_EXCEPTION_IGNORE_CANCEL,
870 _("Device %s has multiple (%d) logical sectors "
871 "per physical sector.\n"
872 "GNU Parted supports this EXPERIMENTALLY for "
873 "some special disk label/file system "
874 "combinations, e.g. GPT and ext2/3.\n"
875 "Please consult the web site for up-to-date "
877 dev->path, sector_multiplier);
880 case PED_EXCEPTION_CANCEL:
881 goto error_close_dev;
883 case PED_EXCEPTION_UNHANDLED:
884 ped_exception_catch ();
885 case PED_EXCEPTION_IGNORE:
893 /* XXX sector_size has not been set yet! */
894 /* dev->phys_sector_size = dev->sector_size
895 * sector_multiplier;*/
896 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
899 if (!_device_probe_geometry (dev))
900 goto error_close_dev;
902 ped_device_close (dev);
906 ped_device_close (dev);
911 /* This function reads the /sys entry named "file" for device "dev". */
913 read_device_sysfs_file (PedDevice *dev, const char *file)
919 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
920 last_component (dev->path), file);
922 if ((f = fopen (name_buf, "r")) == NULL)
925 if (fgets (buf, 255, f) == NULL) {
931 return strip_name (buf);
934 /* This function sends a query to a SCSI device for vendor and product
935 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
939 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
941 /* The following are defined by the SCSI-2 specification. */
942 typedef struct _scsi_inquiry_cmd
945 uint8_t lun; /* bits 5-7 denote the LUN */
948 uint8_t alloc_length;
950 } __attribute__((packed)) scsi_inquiry_cmd_t;
952 typedef struct _scsi_inquiry_data
954 uint8_t peripheral_info;
956 uint8_t version_info;
958 uint8_t additional_length;
962 uint8_t vendor_id[8];
963 uint8_t product_id[16];
964 uint8_t product_revision[4];
965 uint8_t vendor_specific[20];
966 uint8_t _reserved3[40];
967 } __attribute__((packed)) scsi_inquiry_data_t;
976 scsi_inquiry_data_t out;
977 scsi_inquiry_cmd_t in;
981 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
987 memset (&arg, 0x00, sizeof(struct scsi_arg));
989 arg.outlen = sizeof(scsi_inquiry_data_t);
990 arg.data.in.op = INQUIRY;
991 arg.data.in.lun = dev->host << 5;
992 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
993 arg.data.in.page_code = 0;
994 arg.data.in.reserved = 0;
995 arg.data.in.control = 0;
997 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
1000 memcpy (buf, arg.data.out.vendor_id, 8);
1002 *vendor = strip_name (buf);
1004 memcpy (buf, arg.data.out.product_id, 16);
1006 *product = strip_name (buf);
1011 /* This function provides the vendor and product name for a SCSI device.
1012 * It supports both the modern /sys interface and direct queries
1013 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
1016 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
1018 *vendor = read_device_sysfs_file (dev, "vendor");
1019 *product = read_device_sysfs_file (dev, "model");
1020 if (*vendor && *product)
1023 return scsi_query_product_info (dev, vendor, product);
1027 init_scsi (PedDevice* dev)
1032 uint32_t host_unique_id;
1035 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1039 if (!ped_device_open (dev))
1042 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
1045 if (ped_exception_throw (
1046 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
1047 _("Error initialising SCSI device %s - %s"),
1048 dev->path, strerror (errno))
1049 != PED_EXCEPTION_IGNORE)
1050 goto error_close_dev;
1051 if (!_device_probe_geometry (dev))
1052 goto error_close_dev;
1053 ped_device_close (dev);
1057 dev->host = idlun.host_unique_id;
1058 dev->did = idlun.dev_id;
1060 dev->model = (char*) ped_malloc (8 + 16 + 2);
1062 goto error_close_dev;
1064 if (scsi_get_product_info (dev, &vendor, &product)) {
1065 sprintf (dev->model, "%.8s %.16s", vendor, product);
1069 strcpy (dev->model, "Generic SCSI");
1072 if (!_device_probe_geometry (dev))
1073 goto error_close_dev;
1075 ped_device_close (dev);
1079 ped_device_close (dev);
1085 init_file (PedDevice* dev)
1087 struct stat dev_stat;
1089 if (!_device_stat (dev, &dev_stat))
1091 if (!ped_device_open (dev))
1094 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1095 char *p = getenv ("PARTED_SECTOR_SIZE");
1098 if (0 < s && s % 512 == 0)
1099 dev->sector_size = s;
1101 dev->phys_sector_size = dev->sector_size;
1103 if (S_ISBLK(dev_stat.st_mode))
1104 dev->length = _device_get_length (dev);
1106 dev->length = dev_stat.st_size / dev->sector_size;
1107 if (dev->length <= 0) {
1108 ped_exception_throw (
1109 PED_EXCEPTION_ERROR,
1110 PED_EXCEPTION_CANCEL,
1111 _("The device %s is so small that it cannot possibly "
1112 "store a file system or partition table. Perhaps "
1113 "you selected the wrong device?"),
1115 goto error_close_dev;
1118 ped_device_close (dev);
1120 dev->bios_geom.cylinders = dev->length / 4 / 32;
1121 dev->bios_geom.heads = 4;
1122 dev->bios_geom.sectors = 32;
1123 dev->hw_geom = dev->bios_geom;
1124 dev->model = strdup ("");
1129 ped_device_close (dev);
1134 #if defined __s390__ || defined __s390x__
1136 init_dasd (PedDevice* dev, const char* model_name)
1138 struct stat dev_stat;
1139 struct hd_geometry geo;
1140 dasd_information_t dasd_info;
1142 if (!_device_stat (dev, &dev_stat))
1145 if (!ped_device_open (dev))
1148 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1150 PED_ASSERT (S_ISBLK (dev_stat.st_mode));
1152 _device_set_sector_size (dev);
1153 if (!dev->sector_size)
1154 goto error_close_dev;
1156 dev->length = _device_get_length (dev);
1158 goto error_close_dev;
1160 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1161 dev->hw_geom.sectors = geo.sectors;
1162 dev->hw_geom.heads = geo.heads;
1163 dev->hw_geom.cylinders = dev->length
1164 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1165 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1166 dev->bios_geom = dev->hw_geom;
1168 dev->bios_geom.sectors = 12;
1169 dev->bios_geom.heads = 15;
1170 dev->bios_geom.cylinders = dev->length
1171 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1172 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1173 dev->hw_geom = dev->bios_geom;
1176 if (!ioctl(arch_specific->fd, BIODASDINFO, &dasd_info)) {
1177 arch_specific->devno = dasd_info.devno;
1179 arch_specific->devno = arch_specific->major * 256 +
1180 arch_specific->minor;
1183 dev->model = strdup (model_name);
1185 ped_device_close (dev);
1189 ped_device_close (dev);
1196 init_generic (PedDevice* dev, const char* model_name)
1198 struct stat dev_stat;
1199 PedExceptionOption ex_status;
1201 if (!_device_stat (dev, &dev_stat))
1204 if (!ped_device_open (dev))
1207 ped_exception_fetch_all ();
1208 if (_device_probe_geometry (dev)) {
1209 ped_exception_leave_all ();
1211 if (!_device_get_length (dev)) {
1212 ped_exception_catch ();
1213 ped_exception_leave_all ();
1214 goto error_close_dev;
1217 /* hack to allow use of files, for testing */
1218 ped_exception_catch ();
1219 ped_exception_leave_all ();
1221 ex_status = ped_exception_throw (
1222 PED_EXCEPTION_WARNING,
1223 PED_EXCEPTION_IGNORE_CANCEL,
1224 _("Unable to determine geometry of "
1225 "file/device %s. You should not use Parted "
1226 "unless you REALLY know what you're doing!"),
1228 switch (ex_status) {
1229 case PED_EXCEPTION_CANCEL:
1230 goto error_close_dev;
1232 case PED_EXCEPTION_UNHANDLED:
1233 ped_exception_catch ();
1234 case PED_EXCEPTION_IGNORE:
1241 /* what should we stick in here? */
1242 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1243 dev->bios_geom.cylinders = dev->length / 4 / 32;
1244 dev->bios_geom.heads = 4;
1245 dev->bios_geom.sectors = 32;
1246 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1247 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1250 dev->model = strdup (model_name);
1252 ped_device_close (dev);
1256 ped_device_close (dev);
1262 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1264 *type = read_device_sysfs_file (dev, "type");
1265 *name = read_device_sysfs_file (dev, "name");
1273 init_sdmmc (PedDevice* dev)
1278 if (sdmmc_get_product_info (dev, &type, &name)) {
1279 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1283 snprintf (id, sizeof(id) - 1, "%s",
1284 _("Generic SD/MMC Storage Card"));
1286 return init_generic(dev, id);
1290 linux_new (const char* path)
1293 LinuxSpecific* arch_specific;
1295 PED_ASSERT (path != NULL);
1297 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1301 dev->path = strdup (path);
1303 goto error_free_dev;
1306 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1307 if (!dev->arch_specific)
1308 goto error_free_path;
1309 arch_specific = LINUX_SPECIFIC (dev);
1310 arch_specific->dmtype = NULL;
1312 arch_specific->probe = NULL;
1313 arch_specific->topology = NULL;
1316 dev->open_count = 0;
1318 dev->external_mode = 0;
1320 dev->boot_dirty = 0;
1322 if (!_device_probe_type (dev))
1323 goto error_free_arch_specific;
1325 switch (dev->type) {
1326 case PED_DEVICE_IDE:
1327 if (!init_ide (dev))
1328 goto error_free_arch_specific;
1331 case PED_DEVICE_SCSI:
1332 if (!init_scsi (dev))
1333 goto error_free_arch_specific;
1336 case PED_DEVICE_DAC960:
1337 if (!init_generic (dev, _("DAC960 RAID controller")))
1338 goto error_free_arch_specific;
1341 case PED_DEVICE_SX8:
1342 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1343 goto error_free_arch_specific;
1346 case PED_DEVICE_AOE:
1347 if (!init_generic (dev, _("ATA over Ethernet Device")))
1348 goto error_free_arch_specific;
1351 #if defined __s390__ || defined __s390x__
1352 case PED_DEVICE_DASD:
1353 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1354 goto error_free_arch_specific;
1358 case PED_DEVICE_VIODASD:
1359 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1360 goto error_free_arch_specific;
1363 case PED_DEVICE_CPQARRAY:
1364 if (!init_generic (dev, _("Compaq Smart Array")))
1365 goto error_free_arch_specific;
1368 case PED_DEVICE_ATARAID:
1369 if (!init_generic (dev, _("ATARAID Controller")))
1370 goto error_free_arch_specific;
1373 case PED_DEVICE_I2O:
1374 if (!init_generic (dev, _("I2O Controller")))
1375 goto error_free_arch_specific;
1378 case PED_DEVICE_UBD:
1379 if (!init_generic (dev, _("User-Mode Linux UBD")))
1380 goto error_free_arch_specific;
1383 case PED_DEVICE_FILE:
1384 if (!init_file (dev))
1385 goto error_free_arch_specific;
1388 case PED_DEVICE_LOOP:
1389 if (!init_generic (dev, _("Loopback device")))
1390 goto error_free_arch_specific;
1396 if (arch_specific->dmtype == NULL
1397 || asprintf(&type, _("Linux device-mapper (%s)"),
1398 arch_specific->dmtype) == -1)
1399 goto error_free_arch_specific;
1400 bool ok = init_generic (dev, type);
1403 goto error_free_arch_specific;
1407 case PED_DEVICE_XVD:
1408 if (!init_generic (dev, _("Xen Virtual Block Device")))
1409 goto error_free_arch_specific;
1412 case PED_DEVICE_UNKNOWN:
1413 if (!init_generic (dev, _("Unknown")))
1414 goto error_free_arch_specific;
1417 case PED_DEVICE_SDMMC:
1418 if (!init_sdmmc (dev))
1419 goto error_free_arch_specific;
1421 case PED_DEVICE_VIRTBLK:
1422 if (!init_generic(dev, _("Virtio Block Device")))
1423 goto error_free_arch_specific;
1427 if (!init_generic(dev, _("Linux Software RAID Array")))
1428 goto error_free_arch_specific;
1432 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1433 PED_EXCEPTION_CANCEL,
1434 _("ped_device_new() Unsupported device type"));
1435 goto error_free_arch_specific;
1439 error_free_arch_specific:
1440 free (dev->arch_specific);
1450 linux_destroy (PedDevice* dev)
1452 LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
1453 void *p = arch_specific->dmtype;
1456 if (arch_specific->probe)
1457 blkid_free_probe(arch_specific->probe);
1460 free (dev->arch_specific);
1467 linux_is_busy (PedDevice* dev)
1472 if (_partition_is_mounted_by_path (dev->path))
1475 for (i = 0; i < 32; i++) {
1478 part_name = _device_get_part_path (dev, i);
1481 status = _partition_is_mounted_by_path (part_name);
1491 /* we need to flush the master device, and with kernel < 2.6 all the partition
1492 * devices, because there is no coherency between the caches with old kernels.
1493 * We should only flush unmounted partition devices, because:
1494 * - there is never a need to flush them (we're not doing IO there)
1495 * - flushing a device that is mounted causes unnecessary IO, and can
1496 * even screw journaling & friends up. Even cause oopsen!
1499 _flush_cache (PedDevice* dev)
1501 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1508 ioctl (arch_specific->fd, BLKFLSBUF);
1510 /* With linux-2.6.0 and newer, we're done. */
1514 for (i = 1; i < 16; i++) {
1518 name = _device_get_part_path (dev, i);
1521 if (!_partition_is_mounted_by_path (name)) {
1522 fd = open (name, WR_MODE, 0);
1524 ioctl (fd, BLKFLSBUF);
1526 if (fsync (fd) < 0 || close (fd) < 0)
1527 if (ped_exception_throw (
1528 PED_EXCEPTION_WARNING,
1529 PED_EXCEPTION_RETRY +
1530 PED_EXCEPTION_IGNORE,
1531 _("Error fsyncing/closing %s: %s"),
1532 name, strerror (errno))
1533 == PED_EXCEPTION_RETRY)
1542 linux_open (PedDevice* dev)
1544 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1547 arch_specific->fd = open (dev->path, RW_MODE);
1549 if (arch_specific->fd == -1) {
1550 char* rw_error_msg = strerror (errno);
1552 arch_specific->fd = open (dev->path, RD_MODE);
1554 if (arch_specific->fd == -1) {
1555 if (ped_exception_throw (
1556 PED_EXCEPTION_ERROR,
1557 PED_EXCEPTION_RETRY_CANCEL,
1558 _("Error opening %s: %s"),
1559 dev->path, strerror (errno))
1560 != PED_EXCEPTION_RETRY) {
1566 ped_exception_throw (
1567 PED_EXCEPTION_WARNING,
1569 _("Unable to open %s read-write (%s). %s has "
1570 "been opened read-only."),
1571 dev->path, rw_error_msg, dev->path);
1578 /* With kernels < 2.6 flush cache for cache coherence issues */
1579 if (!_have_kern26())
1586 linux_refresh_open (PedDevice* dev)
1592 linux_close (PedDevice* dev)
1594 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1599 if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
1600 if (ped_exception_throw (
1601 PED_EXCEPTION_WARNING,
1602 PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
1603 _("Error fsyncing/closing %s: %s"),
1604 dev->path, strerror (errno))
1605 == PED_EXCEPTION_RETRY)
1611 linux_refresh_close (PedDevice* dev)
1618 #if SIZEOF_OFF_T < 8
1620 static _syscall5(int,_llseek,
1622 unsigned long, offset_high,
1623 unsigned long, offset_low,
1625 unsigned int, origin)
1628 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1633 retval = _llseek(fd,
1634 ((unsigned long long)offset) >> 32,
1635 ((unsigned long long)offset) & 0xffffffff,
1638 return (retval==-1 ? (loff_t) retval : result);
1641 #endif /* SIZEOF_OFF_T < 8 */
1644 _device_seek (const PedDevice* dev, PedSector sector)
1646 LinuxSpecific* arch_specific;
1648 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
1649 PED_ASSERT (dev != NULL);
1650 PED_ASSERT (!dev->external_mode);
1652 arch_specific = LINUX_SPECIFIC (dev);
1654 #if SIZEOF_OFF_T < 8
1655 if (sizeof (off_t) < 8) {
1656 loff_t pos = (loff_t)(sector * dev->sector_size);
1657 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1661 off_t pos = sector * dev->sector_size;
1662 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1667 _read_lastoddsector (const PedDevice* dev, void* buffer)
1669 LinuxSpecific* arch_specific;
1670 struct blkdev_ioctl_param ioctl_param;
1672 PED_ASSERT(dev != NULL);
1673 PED_ASSERT(buffer != NULL);
1675 arch_specific = LINUX_SPECIFIC (dev);
1678 ioctl_param.block = 0; /* read the last sector */
1679 ioctl_param.content_length = dev->sector_size;
1680 ioctl_param.block_contents = buffer;
1682 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1683 PedExceptionOption opt;
1684 opt = ped_exception_throw (
1685 PED_EXCEPTION_ERROR,
1686 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1687 _("%s during read on %s"),
1688 strerror (errno), dev->path);
1690 if (opt == PED_EXCEPTION_CANCEL)
1692 if (opt == PED_EXCEPTION_RETRY)
1700 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1703 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1704 PedExceptionOption ex_status;
1705 void* diobuf = NULL;
1707 PED_ASSERT (dev != NULL);
1708 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
1710 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1711 /* Kludge. This is necessary to read/write the last
1712 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1714 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1715 && start + count - 1 == dev->length - 1)
1716 return ped_device_read (dev, buffer, start, count - 1)
1717 && _read_lastoddsector (
1718 dev, (char *) buffer + (count-1) * 512);
1721 if (_device_seek (dev, start))
1724 ex_status = ped_exception_throw (
1725 PED_EXCEPTION_ERROR,
1726 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1727 _("%s during seek for read on %s"),
1728 strerror (errno), dev->path);
1730 switch (ex_status) {
1731 case PED_EXCEPTION_IGNORE:
1734 case PED_EXCEPTION_RETRY:
1737 case PED_EXCEPTION_UNHANDLED:
1738 ped_exception_catch ();
1739 case PED_EXCEPTION_CANCEL:
1747 size_t read_length = count * dev->sector_size;
1748 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1752 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1754 memcpy(buffer, diobuf, status);
1755 if (status == (ssize_t) read_length)
1758 read_length -= status;
1759 buffer = (char *) buffer + status;
1763 ex_status = ped_exception_throw (
1764 PED_EXCEPTION_ERROR,
1765 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1767 ? _("%0.0send of file while reading %s")
1768 : _("%s during read on %s")),
1772 switch (ex_status) {
1773 case PED_EXCEPTION_IGNORE:
1777 case PED_EXCEPTION_RETRY:
1780 case PED_EXCEPTION_UNHANDLED:
1781 ped_exception_catch ();
1782 case PED_EXCEPTION_CANCEL:
1797 _write_lastoddsector (PedDevice* dev, const void* buffer)
1799 LinuxSpecific* arch_specific;
1800 struct blkdev_ioctl_param ioctl_param;
1802 PED_ASSERT(dev != NULL);
1803 PED_ASSERT(buffer != NULL);
1805 arch_specific = LINUX_SPECIFIC (dev);
1808 ioctl_param.block = 0; /* write the last sector */
1809 ioctl_param.content_length = dev->sector_size;
1810 ioctl_param.block_contents = (void*) buffer;
1812 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1813 PedExceptionOption opt;
1814 opt = ped_exception_throw (
1815 PED_EXCEPTION_ERROR,
1816 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1817 _("%s during write on %s"),
1818 strerror (errno), dev->path);
1820 if (opt == PED_EXCEPTION_CANCEL)
1822 if (opt == PED_EXCEPTION_RETRY)
1830 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1833 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1834 PedExceptionOption ex_status;
1838 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
1840 if (dev->read_only) {
1841 if (ped_exception_throw (
1842 PED_EXCEPTION_ERROR,
1843 PED_EXCEPTION_IGNORE_CANCEL,
1844 _("Can't write to %s, because it is opened read-only."),
1846 != PED_EXCEPTION_IGNORE)
1852 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1853 /* Kludge. This is necessary to read/write the last
1854 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1856 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1857 && start + count - 1 == dev->length - 1)
1858 return ped_device_write (dev, buffer, start, count - 1)
1859 && _write_lastoddsector (
1860 dev, ((char*) buffer
1861 + (count-1) * dev->sector_size));
1864 if (_device_seek (dev, start))
1867 ex_status = ped_exception_throw (
1868 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1869 _("%s during seek for write on %s"),
1870 strerror (errno), dev->path);
1872 switch (ex_status) {
1873 case PED_EXCEPTION_IGNORE:
1876 case PED_EXCEPTION_RETRY:
1879 case PED_EXCEPTION_UNHANDLED:
1880 ped_exception_catch ();
1881 case PED_EXCEPTION_CANCEL:
1890 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1891 dev->path, buffer, (int) start, (int) count);
1893 size_t write_length = count * dev->sector_size;
1895 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1897 memcpy(diobuf, buffer, write_length);
1898 diobuf_start = diobuf;
1900 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1901 if (status == write_length) break;
1903 write_length -= status;
1904 diobuf = (char *) diobuf + status;
1908 ex_status = ped_exception_throw (
1909 PED_EXCEPTION_ERROR,
1910 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1911 _("%s during write on %s"),
1912 strerror (errno), dev->path);
1914 switch (ex_status) {
1915 case PED_EXCEPTION_IGNORE:
1919 case PED_EXCEPTION_RETRY:
1922 case PED_EXCEPTION_UNHANDLED:
1923 ped_exception_catch ();
1924 case PED_EXCEPTION_CANCEL:
1933 #endif /* !READ_ONLY */
1937 /* returns the number of sectors that are ok.
1940 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1942 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1947 PED_ASSERT(dev != NULL);
1949 if (!_device_seek (dev, start))
1952 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1953 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1956 for (done = 0; done < count; done += status / dev->sector_size) {
1957 status = read (arch_specific->fd, diobuf,
1958 (size_t) ((count-done) * dev->sector_size));
1960 memcpy(buffer, diobuf, status);
1970 _do_fsync (PedDevice* dev)
1972 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1974 PedExceptionOption ex_status;
1977 status = fsync (arch_specific->fd);
1978 if (status >= 0) break;
1980 ex_status = ped_exception_throw (
1981 PED_EXCEPTION_ERROR,
1982 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1983 _("%s during write on %s"),
1984 strerror (errno), dev->path);
1986 switch (ex_status) {
1987 case PED_EXCEPTION_IGNORE:
1990 case PED_EXCEPTION_RETRY:
1993 case PED_EXCEPTION_UNHANDLED:
1994 ped_exception_catch ();
1995 case PED_EXCEPTION_CANCEL:
2006 linux_sync (PedDevice* dev)
2008 PED_ASSERT (dev != NULL);
2009 PED_ASSERT (!dev->external_mode);
2013 if (!_do_fsync (dev))
2020 linux_sync_fast (PedDevice* dev)
2022 PED_ASSERT (dev != NULL);
2023 PED_ASSERT (!dev->external_mode);
2027 if (!_do_fsync (dev))
2029 /* no cache flush... */
2034 _compare_digit_state (char ch, int need_digit)
2036 return !!isdigit (ch) == need_digit;
2039 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
2040 * Motivation: accept devices looking like /dev/rd/c0d0, but
2041 * not looking like /dev/hda1 and /dev/rd/c0d0p1
2044 _match_rd_device (const char* name)
2049 /* exclude directory names from test */
2050 pos = strrchr(name, '/') ?: name;
2058 for (state = 0; state < 4; state++) {
2059 int want_digits = (state % 2 == 1);
2063 if (!_compare_digit_state (*pos, want_digits))
2066 } while (_compare_digit_state (*pos, want_digits));
2073 _probe_proc_partitions ()
2075 FILE* proc_part_file;
2076 int major, minor, size;
2078 char part_name [256];
2079 char dev_name [256];
2082 proc_part_file = fopen ("/proc/partitions", "r");
2083 if (!proc_part_file)
2086 if (fgets (buf, 256, proc_part_file) == NULL)
2089 if (fgets (buf, 256, proc_part_file) == NULL)
2092 while (fgets (buf, 512, proc_part_file)
2093 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
2095 /* Heuristic for telling partitions and devices apart
2096 * Probably needs to be improved
2098 if (!_match_rd_device (part_name)
2099 && isdigit (part_name [strlen (part_name) - 1]))
2102 strcpy (dev_name, "/dev/");
2103 strcat (dev_name, part_name);
2104 _ped_device_probe (dev_name);
2109 fclose (proc_part_file);
2119 _skip_entry (const char *name)
2122 static struct _entry entries[] = {
2123 { ".", sizeof (".") - 1 },
2124 { "..", sizeof ("..") - 1 },
2125 { "dm-", sizeof ("dm-") - 1 },
2126 { "loop", sizeof ("loop") - 1 },
2127 { "ram", sizeof ("ram") - 1 },
2131 for (i = entries; i->name != 0; i++) {
2132 if (strncmp (name, i->name, i->len) == 0)
2143 struct dirent *dirent;
2144 char dev_name [256];
2147 if (!(blockdir = opendir ("/sys/block")))
2149 while ((dirent = readdir (blockdir))) {
2150 if (_skip_entry (dirent->d_name))
2153 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2154 continue; /* device name too long! */
2156 strcpy (dev_name, "/dev/");
2157 strcat (dev_name, dirent->d_name);
2158 /* in /sys/block, '/'s are replaced with '!' or '.' */
2159 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2160 if (*ptr == '!' || *ptr == '.')
2163 _ped_device_probe (dev_name);
2166 closedir (blockdir);
2171 _probe_standard_devices ()
2173 _ped_device_probe ("/dev/hda");
2174 _ped_device_probe ("/dev/hdb");
2175 _ped_device_probe ("/dev/hdc");
2176 _ped_device_probe ("/dev/hdd");
2177 _ped_device_probe ("/dev/hde");
2178 _ped_device_probe ("/dev/hdf");
2179 _ped_device_probe ("/dev/hdg");
2180 _ped_device_probe ("/dev/hdh");
2182 _ped_device_probe ("/dev/sda");
2183 _ped_device_probe ("/dev/sdb");
2184 _ped_device_probe ("/dev/sdc");
2185 _ped_device_probe ("/dev/sdd");
2186 _ped_device_probe ("/dev/sde");
2187 _ped_device_probe ("/dev/sdf");
2195 /* we should probe the standard devs too, even with /proc/partitions,
2196 * because /proc/partitions might return devfs stuff, and we might not
2197 * have devfs available
2199 _probe_standard_devices ();
2201 #ifdef ENABLE_DEVICE_MAPPER
2202 /* device-mapper devices aren't listed in /proc/partitions; or, if
2203 * they are, they're listed as dm-X. So, instead of relying on that,
2204 * we do our own checks.
2206 _probe_dm_devices ();
2209 /* /sys/block is more reliable and consistent; fall back to using
2210 * /proc/partitions if the former is unavailable, however.
2212 if (!_probe_sys_block ())
2213 _probe_proc_partitions ();
2216 static char * _GL_ATTRIBUTE_FORMAT ((__printf__, 1, 2))
2217 zasprintf (const char *format, ...)
2221 va_start (args, format);
2222 int r = vasprintf (&resultp, format, args);
2224 return r < 0 ? NULL : resultp;
2228 _device_get_part_path (PedDevice *dev, int num)
2230 size_t path_len = strlen (dev->path);
2233 /* Check for devfs-style /disc => /partN transformation
2234 unconditionally; the system might be using udev with devfs rules,
2235 and if not the test is harmless. */
2236 if (5 < path_len && !strcmp (dev->path + path_len - 5, "/disc")) {
2237 /* replace /disc with /part%d */
2238 result = zasprintf ("%.*s/part%d",
2239 (int) (path_len - 5), dev->path, num);
2241 char const *p = (dev->type == PED_DEVICE_DAC960
2242 || dev->type == PED_DEVICE_CPQARRAY
2243 || dev->type == PED_DEVICE_ATARAID
2244 || dev->type == PED_DEVICE_DM
2245 || isdigit (dev->path[path_len - 1])
2247 result = zasprintf ("%s%s%d", dev->path, p, num);
2254 linux_partition_get_path (const PedPartition* part)
2256 return _device_get_part_path (part->disk->dev, part->num);
2260 _mount_table_search (const char* file_name, dev_t dev)
2262 struct stat part_stat;
2264 char part_name[512];
2267 file = fopen (file_name, "r");
2270 while (fgets (line, 512, file)) {
2271 if (sscanf (line, "%s", part_name) == 1
2272 && stat (part_name, &part_stat) == 0) {
2273 if (part_stat.st_rdev == dev) {
2284 _partition_is_mounted_by_dev (dev_t dev)
2286 return _mount_table_search( "/proc/mounts", dev)
2287 || _mount_table_search( "/proc/swaps", dev)
2288 || _mount_table_search( "/etc/mtab", dev);
2292 _partition_is_mounted_by_path (const char *path)
2294 struct stat part_stat;
2295 if (stat (path, &part_stat) != 0)
2297 if (!S_ISBLK(part_stat.st_mode))
2299 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2302 /* If partition PART is mounted, or if we encounter an out-of-memory error
2303 while trying to determine its status, return 1. Otherwise, return 0. */
2305 _partition_is_mounted (const PedPartition *part)
2307 if (!ped_partition_is_active (part))
2309 char *part_name = _device_get_part_path (part->disk->dev, part->num);
2312 int status = _partition_is_mounted_by_path (part_name);
2318 _has_partitions (const PedDisk* disk)
2320 PED_ASSERT(disk != NULL);
2322 /* Some devices can't be partitioned. */
2323 if (!strcmp (disk->type->name, "loop"))
2330 linux_partition_is_busy (const PedPartition* part)
2334 PED_ASSERT (part != NULL);
2336 if (_partition_is_mounted (part))
2338 if (part->type == PED_PARTITION_EXTENDED) {
2339 for (walk = part->part_list; walk; walk = walk->next) {
2340 if (linux_partition_is_busy (walk))
2348 _blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
2350 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2351 struct blkpg_ioctl_arg ioctl_arg;
2354 ioctl_arg.flags = 0;
2355 ioctl_arg.datalen = sizeof (struct blkpg_partition);
2356 ioctl_arg.data = (void*) part;
2358 return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
2362 _blkpg_add_partition (PedDisk* disk, const PedPartition *part)
2364 struct blkpg_partition linux_part;
2365 const char* vol_name;
2368 PED_ASSERT(disk != NULL);
2369 PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
2371 if (!_has_partitions (disk))
2374 if (ped_disk_type_check_feature (disk->type,
2375 PED_DISK_TYPE_PARTITION_NAME))
2376 vol_name = ped_partition_get_name (part);
2380 dev_name = _device_get_part_path (disk->dev, part->num);
2384 memset (&linux_part, 0, sizeof (linux_part));
2385 linux_part.start = part->geom.start * disk->dev->sector_size;
2386 /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
2387 if (part->type & PED_PARTITION_EXTENDED)
2388 linux_part.length = part->geom.length == 1 ? 512 : 1024;
2390 linux_part.length = part->geom.length * disk->dev->sector_size;
2391 linux_part.pno = part->num;
2392 strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
2394 strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
2398 if (!_blkpg_part_command (disk->dev, &linux_part,
2399 BLKPG_ADD_PARTITION)) {
2400 return ped_exception_throw (
2401 PED_EXCEPTION_ERROR,
2402 PED_EXCEPTION_IGNORE_CANCEL,
2403 _("Error informing the kernel about modifications to "
2404 "partition %s -- %s. This means Linux won't know "
2405 "about any changes you made to %s until you reboot "
2406 "-- so you shouldn't mount it or use it in any way "
2407 "before rebooting."),
2411 == PED_EXCEPTION_IGNORE;
2418 _blkpg_remove_partition (PedDisk* disk, int n)
2420 struct blkpg_partition linux_part;
2422 if (!_has_partitions (disk))
2425 memset (&linux_part, 0, sizeof (linux_part));
2427 return _blkpg_part_command (disk->dev, &linux_part,
2428 BLKPG_DEL_PARTITION);
2432 * The number of partitions that a device can have depends on the kernel.
2433 * If we don't find this value in /sys/block/DEV/range, we will use our own
2437 _device_get_partition_range(PedDevice* dev)
2444 r = snprintf(path, sizeof(path), "/sys/block/%s/range",
2445 last_component(dev->path));
2446 if (r < 0 || r >= sizeof(path))
2447 return MAX_NUM_PARTS;
2449 fp = fopen(path, "r");
2451 return MAX_NUM_PARTS;
2453 ok = fscanf(fp, "%d", &range) == 1;
2456 /* (range <= 0) is none sense.*/
2457 return ok && range > 0 ? range : MAX_NUM_PARTS;
2461 * Sync the partition table in two step process:
2462 * 1. Remove all of the partitions from the kernel's tables, but do not attempt
2463 * removal of any partition for which the corresponding ioctl call fails.
2464 * 2. Add all the partitions that we hold in disk, throwing a warning
2465 * if we cannot because step 1 failed to remove it and it is not being
2466 * added back with the same start and length.
2468 * To achieve this two step process we must calculate the minimum number of
2469 * maximum possible partitions between what linux supports and what the label
2470 * type supports. EX:
2472 * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables)
2475 _disk_sync_part_table (PedDisk* disk)
2477 PED_ASSERT(disk != NULL);
2478 PED_ASSERT(disk->dev != NULL);
2481 /* lpn = largest partition number. */
2482 if (ped_disk_get_max_supported_partition_count(disk, &lpn))
2483 lpn = PED_MIN(lpn, _device_get_partition_range(disk->dev));
2485 lpn = _device_get_partition_range(disk->dev);
2487 /* Its not possible to support largest_partnum < 0.
2488 * largest_partnum == 0 would mean does not support partitions.
2493 int *ok = calloc (lpn, sizeof *ok);
2496 int *errnums = ped_malloc(sizeof(int) * lpn);
2500 /* Attempt to remove each and every partition, retrying for
2501 up to max_sleep_seconds upon any failure due to EBUSY. */
2502 unsigned int sleep_microseconds = 10000;
2503 unsigned int max_sleep_seconds = 1;
2504 unsigned int n_sleep = (max_sleep_seconds
2505 * 1000000 / sleep_microseconds);
2507 for (i = 0; i < n_sleep; i++) {
2509 usleep (sleep_microseconds);
2512 for (j = 0; j < lpn; j++) {
2514 ok[j] = _blkpg_remove_partition (disk, j + 1);
2516 if (!ok[j] && errnums[j] == EBUSY)
2524 for (i = 1; i <= lpn; i++) {
2525 const PedPartition *part = ped_disk_get_partition (disk, i);
2527 if (!ok[i - 1] && errnums[i - 1] == EBUSY) {
2528 struct hd_geometry geom;
2529 unsigned long long length = 0;
2530 /* get start and length of existing partition */
2531 char *dev_name = _device_get_part_path (disk->dev, i);
2534 int fd = open (dev_name, O_RDONLY);
2536 || ioctl (fd, HDIO_GETGEO, &geom)
2537 || ioctl (fd, BLKGETSIZE64, &length)) {
2538 ped_exception_throw (
2540 PED_EXCEPTION_CANCEL,
2541 _("Unable to determine the size and length of %s."),
2549 length /= disk->dev->sector_size;
2551 if (geom.start == part->geom.start
2552 && length == part->geom.length)
2554 /* If the new partition is unchanged and the
2555 existing one was not removed because it was
2556 in use, then reset the error flag and do not
2557 try to add it since it is already there. */
2561 /* add the (possibly modified or new) partition */
2562 if (!_blkpg_add_partition (disk, part)) {
2563 ped_exception_throw (
2564 PED_EXCEPTION_ERROR,
2565 PED_EXCEPTION_RETRY_CANCEL,
2566 _("Failed to add partition %d (%s)"),
2567 i, strerror (errno));
2573 char *bad_part_list = NULL;
2574 /* now warn about any errors */
2575 for (i = 1; i <= lpn; i++) {
2576 if (ok[i - 1] || errnums[i - 1] == ENXIO)
2578 if (bad_part_list == NULL) {
2579 bad_part_list = malloc (lpn * 5);
2582 bad_part_list[0] = 0;
2584 sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i);
2586 if (bad_part_list == NULL)
2589 bad_part_list[strlen (bad_part_list) - 2] = 0;
2590 if (ped_exception_throw (
2591 PED_EXCEPTION_ERROR,
2592 PED_EXCEPTION_IGNORE_CANCEL,
2593 _("Partition(s) %s on %s have been written, but we have "
2594 "been unable to inform the kernel of the change, "
2595 "probably because it/they are in use. As a result, "
2596 "the old partition(s) will remain in use. You "
2597 "should reboot now before making further changes."),
2598 bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE)
2600 free (bad_part_list);
2608 #ifdef ENABLE_DEVICE_MAPPER
2610 _dm_remove_map_name(char *name)
2612 struct dm_task *task = NULL;
2615 task = dm_task_create(DM_DEVICE_REMOVE);
2619 dm_task_set_name (task, name);
2621 rc = dm_task_run(task);
2622 dm_task_update_nodes();
2623 dm_task_destroy(task);
2631 _dm_is_part (struct dm_info *this, char *name)
2633 struct dm_task* task = NULL;
2634 struct dm_info* info = alloca(sizeof *info);
2635 struct dm_deps* deps = NULL;
2639 task = dm_task_create(DM_DEVICE_DEPS);
2643 dm_task_set_name(task, name);
2644 if (!dm_task_run(task))
2647 memset(info, '\0', sizeof *info);
2648 dm_task_get_info(task, info);
2652 deps = dm_task_get_deps(task);
2656 for (i = 0; i < deps->count; i++) {
2657 unsigned int ma = major(deps->device[i]),
2658 mi = minor(deps->device[i]);
2660 if (ma == this->major && mi == this->minor)
2665 dm_task_destroy(task);
2670 _dm_remove_parts (PedDevice* dev)
2672 struct dm_task* task = NULL;
2673 struct dm_info* info = alloca(sizeof *info);
2674 struct dm_names* names = NULL;
2675 unsigned int next = 0;
2677 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2679 task = dm_task_create(DM_DEVICE_LIST);
2683 if (!dm_task_set_major_minor (task, arch_specific->major,
2684 arch_specific->minor, 0))
2687 if (!dm_task_run(task))
2690 memset(info, '\0', sizeof *info);
2691 dm_task_get_info(task, info);
2695 names = dm_task_get_names(task);
2701 names = (void *) ((char *) names + next);
2703 if (_dm_is_part(info, names->name))
2704 rc += _dm_remove_map_name(names->name);
2709 dm_task_update_nodes();
2710 dm_task_destroy(task);
2717 dm_task_destroy(task);
2718 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2719 _("parted was unable to re-read the partition "
2720 "table on %s (%s). This means Linux won't know "
2721 "anything about the modifications you made. "),
2722 dev->path, strerror (errno));
2727 _dm_add_partition (PedDisk* disk, PedPartition* part)
2729 char* vol_name = NULL;
2730 const char* dev_name = NULL;
2731 char* params = NULL;
2732 LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
2734 if (!_has_partitions(disk))
2737 /* Get map name from devicemapper */
2738 struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
2742 if (!dm_task_set_major_minor (task, arch_specific->major,
2743 arch_specific->minor, 0))
2746 if (!dm_task_run(task))
2749 dev_name = dm_task_get_name (task);
2751 if ( ! (vol_name = zasprintf ("%sp%d", dev_name, part->num)))
2754 /* Caution: dm_task_destroy frees dev_name. */
2755 dm_task_destroy (task);
2758 if ( ! (params = zasprintf ("%d:%d %lld", arch_specific->major,
2759 arch_specific->minor, part->geom.start)))
2762 task = dm_task_create (DM_DEVICE_CREATE);
2766 dm_task_set_name (task, vol_name);
2767 dm_task_add_target (task, 0, part->geom.length,
2769 if (dm_task_run (task)) {
2770 //printf("0 %ld linear %s\n", part->geom.length, params);
2771 dm_task_update_nodes();
2772 dm_task_destroy(task);
2777 _dm_remove_map_name(vol_name);
2780 dm_task_update_nodes();
2782 dm_task_destroy (task);
2789 _dm_reread_part_table (PedDisk* disk)
2791 int largest_partnum = ped_disk_get_last_partition_num (disk);
2792 if (largest_partnum <= 0)
2796 int last = PED_MIN (largest_partnum, 16);
2800 if (!_dm_remove_parts(disk->dev))
2803 for (i = 1; i <= last; i++) {
2806 part = ped_disk_get_partition (disk, i);
2810 if (!_dm_add_partition (disk, part))
2820 static int have_blkpg = -1;
2823 if (have_blkpg != -1)
2826 kver = _get_linux_version();
2827 return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
2830 /* Return nonzero upon success, 0 if something fails. */
2832 linux_disk_commit (PedDisk* disk)
2834 if (!_has_partitions (disk))
2837 #ifdef ENABLE_DEVICE_MAPPER
2838 if (disk->dev->type == PED_DEVICE_DM)
2839 return _dm_reread_part_table (disk);
2841 if (disk->dev->type != PED_DEVICE_FILE) {
2843 /* We now require BLKPG support. If this assertion fails,
2844 please write to the mailing list describing your system.
2845 Assuming it's never triggered, ...
2846 FIXME: remove this assertion in 2012. */
2847 assert (_have_blkpg ());
2849 if (!_disk_sync_part_table (disk))
2857 static PedAlignment*
2858 linux_get_minimum_alignment(const PedDevice *dev)
2860 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2864 if (blkid_topology_get_minimum_io_size(tp) == 0)
2865 return ped_alignment_new(
2866 blkid_topology_get_alignment_offset(tp) /
2868 dev->phys_sector_size / dev->sector_size);
2870 return ped_alignment_new(
2871 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2872 blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
2875 static PedAlignment*
2876 linux_get_optimum_alignment(const PedDevice *dev)
2878 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2882 /* When PED_DEFAULT_ALIGNMENT is divisible by the *_io_size or
2883 there are no *_io_size values, use the PED_DEFAULT_ALIGNMENT
2884 If one or the other will not divide evenly, fall through to
2886 unsigned long optimal_io = blkid_topology_get_optimal_io_size(tp);
2887 unsigned long minimum_io = blkid_topology_get_minimum_io_size(tp);
2889 (!optimal_io && !minimum_io)
2890 || (optimal_io && PED_DEFAULT_ALIGNMENT % optimal_io == 0
2891 && minimum_io && PED_DEFAULT_ALIGNMENT % minimum_io == 0)
2892 || (!minimum_io && optimal_io
2893 && PED_DEFAULT_ALIGNMENT % optimal_io == 0)
2894 || (!optimal_io && minimum_io
2895 && PED_DEFAULT_ALIGNMENT % minimum_io == 0)
2897 /* DASD needs to use minimum alignment */
2898 if (dev->type == PED_DEVICE_DASD)
2899 return linux_get_minimum_alignment(dev);
2901 return ped_alignment_new(
2902 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2903 PED_DEFAULT_ALIGNMENT / dev->sector_size);
2906 /* If optimal_io_size is 0 and we don't meet the other criteria
2907 for using the device.c default, return the minimum alignment. */
2908 if (blkid_topology_get_optimal_io_size(tp) == 0)
2909 return linux_get_minimum_alignment(dev);
2911 return ped_alignment_new(
2912 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2913 blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
2917 static PedDeviceArchOps linux_dev_ops = {
2919 destroy: linux_destroy,
2920 is_busy: linux_is_busy,
2922 refresh_open: linux_refresh_open,
2924 refresh_close: linux_refresh_close,
2929 sync_fast: linux_sync_fast,
2930 probe_all: linux_probe_all,
2932 get_minimum_alignment: linux_get_minimum_alignment,
2933 get_optimum_alignment: linux_get_optimum_alignment,
2937 PedDiskArchOps linux_disk_ops = {
2938 partition_get_path: linux_partition_get_path,
2939 partition_is_busy: linux_partition_is_busy,
2940 disk_commit: linux_disk_commit
2943 PedArchitecture ped_linux_arch = {
2944 dev_ops: &linux_dev_ops,
2945 disk_ops: &linux_disk_ops