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"
53 # define _(String) dgettext (PACKAGE, String)
55 # define _(String) (String)
56 #endif /* ENABLE_NLS */
58 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
61 #define __NR__llseek 140
64 #ifndef SCSI_IOCTL_SEND_COMMAND
65 #define SCSI_IOCTL_SEND_COMMAND 1
68 /* from <linux/hdreg.h> */
69 #define HDIO_GETGEO 0x0301 /* get device geometry */
70 #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
72 #define RD_MODE (O_RDONLY)
73 #define WR_MODE (O_WRONLY)
74 #define RW_MODE (O_RDWR)
78 unsigned char sectors;
79 unsigned short cylinders;
83 struct ata7_sectinfo {
90 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
92 unsigned short config; /* lots of obsolete bit flags */
93 unsigned short cyls; /* "physical" cyls */
94 unsigned short reserved2; /* reserved (word 2) */
95 unsigned short heads; /* "physical" heads */
96 unsigned short track_bytes; /* unformatted bytes per track */
97 unsigned short sector_bytes; /* unformatted bytes per sector */
98 unsigned short sectors; /* "physical" sectors per track */
99 unsigned short vendor0; /* vendor unique */
100 unsigned short vendor1; /* vendor unique */
101 unsigned short vendor2; /* vendor unique */
102 unsigned char serial_no[20]; /* 0 = not_specified */
103 unsigned short buf_type;
104 unsigned short buf_size; /* 512 byte increments;
106 unsigned short ecc_bytes; /* for r/w long cmds;
108 unsigned char fw_rev[8]; /* 0 = not_specified */
109 char model[40]; /* 0 = not_specified */
110 unsigned char max_multsect; /* 0=not_implemented */
111 unsigned char vendor3; /* vendor unique */
112 unsigned short dword_io; /* 0=not_implemented; 1=implemented */
113 unsigned char vendor4; /* vendor unique */
114 unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
116 unsigned short reserved50; /* reserved (word 50) */
117 unsigned char vendor5; /* vendor unique */
118 unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
119 unsigned char vendor6; /* vendor unique */
120 unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
121 unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
122 unsigned short cur_cyls; /* logical cylinders */
123 unsigned short cur_heads; /* logical heads */
124 unsigned short cur_sectors; /* logical sectors per track */
125 unsigned short cur_capacity0; /* logical total sectors on drive */
126 unsigned short cur_capacity1; /* (2 words, misaligned int) */
127 unsigned char multsect; /* current multiple sector count */
128 unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
129 unsigned int lba_capacity; /* total number of sectors */
130 unsigned short dma_1word; /* single-word dma info */
131 unsigned short dma_mword; /* multiple-word dma info */
132 unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
133 unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
134 unsigned short eide_dma_time; /* recommended mword dma cycle
136 unsigned short eide_pio; /* min cycle time (ns), no IORDY */
137 unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
138 unsigned short words69_70[2]; /* reserved words 69-70 */
139 /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
140 unsigned short words71_74[4]; /* reserved words 71-74 */
141 unsigned short queue_depth; /* */
142 unsigned short words76_79[4]; /* reserved words 76-79 */
143 unsigned short major_rev_num; /* */
144 unsigned short minor_rev_num; /* */
145 unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
147 unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
148 unsigned short cfsse; /* command set-feature supported
150 unsigned short cfs_enable_1; /* command set-feature enabled */
151 unsigned short cfs_enable_2; /* command set-feature enabled */
152 unsigned short csf_default; /* command set-feature default */
153 unsigned short dma_ultra; /* */
154 unsigned short word89; /* reserved (word 89) */
155 unsigned short word90; /* reserved (word 90) */
156 unsigned short CurAPMvalues; /* current APM values */
157 unsigned short word92; /* reserved (word 92) */
158 unsigned short hw_config; /* hardware config */
159 unsigned short words94_105[12];/* reserved words 94-105 */
160 struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
162 unsigned short words107_116[10];/* reserved words 107-116 */
163 unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
164 unsigned short words119_125[7];/* reserved words 119-125 */
165 unsigned short last_lun; /* reserved (word 126) */
166 unsigned short word127; /* reserved (word 127) */
167 unsigned short dlf; /* device lock function
169 * 8 security level 1:max 0:high
178 unsigned short csfo; /* current set features options
185 unsigned short words130_155[26];/* reserved vendor words 130-155 */
186 unsigned short word156;
187 unsigned short words157_159[3]; /* reserved vendor words 157-159 */
188 unsigned short words160_255[95];/* reserved words 160-255 */
191 /* from <linux/fs.h> */
192 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
193 #define BLKGETSIZE _IO(0x12,96) /* return device size */
194 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
195 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
196 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
197 #define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
199 /* return device size in bytes (u64 *arg) */
200 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
202 struct blkdev_ioctl_param {
204 size_t content_length;
205 char * block_contents;
208 /* from <linux/major.h> */
210 #define IDE1_MAJOR 22
211 #define IDE2_MAJOR 33
212 #define IDE3_MAJOR 34
213 #define IDE4_MAJOR 56
214 #define IDE5_MAJOR 57
215 #define SCSI_CDROM_MAJOR 11
216 #define SCSI_DISK0_MAJOR 8
217 #define SCSI_DISK1_MAJOR 65
218 #define SCSI_DISK2_MAJOR 66
219 #define SCSI_DISK3_MAJOR 67
220 #define SCSI_DISK4_MAJOR 68
221 #define SCSI_DISK5_MAJOR 69
222 #define SCSI_DISK6_MAJOR 70
223 #define SCSI_DISK7_MAJOR 71
224 #define SCSI_DISK8_MAJOR 128
225 #define SCSI_DISK9_MAJOR 129
226 #define SCSI_DISK10_MAJOR 130
227 #define SCSI_DISK11_MAJOR 131
228 #define SCSI_DISK12_MAJOR 132
229 #define SCSI_DISK13_MAJOR 133
230 #define SCSI_DISK14_MAJOR 134
231 #define SCSI_DISK15_MAJOR 135
232 #define COMPAQ_SMART2_MAJOR 72
233 #define COMPAQ_SMART2_MAJOR1 73
234 #define COMPAQ_SMART2_MAJOR2 74
235 #define COMPAQ_SMART2_MAJOR3 75
236 #define COMPAQ_SMART2_MAJOR4 76
237 #define COMPAQ_SMART2_MAJOR5 77
238 #define COMPAQ_SMART2_MAJOR6 78
239 #define COMPAQ_SMART2_MAJOR7 79
240 #define COMPAQ_SMART_MAJOR 104
241 #define COMPAQ_SMART_MAJOR1 105
242 #define COMPAQ_SMART_MAJOR2 106
243 #define COMPAQ_SMART_MAJOR3 107
244 #define COMPAQ_SMART_MAJOR4 108
245 #define COMPAQ_SMART_MAJOR5 109
246 #define COMPAQ_SMART_MAJOR6 110
247 #define COMPAQ_SMART_MAJOR7 111
248 #define DAC960_MAJOR 48
249 #define ATARAID_MAJOR 114
250 #define I2O_MAJOR1 80
251 #define I2O_MAJOR2 81
252 #define I2O_MAJOR3 82
253 #define I2O_MAJOR4 83
254 #define I2O_MAJOR5 84
255 #define I2O_MAJOR6 85
256 #define I2O_MAJOR7 86
257 #define I2O_MAJOR8 87
259 #define DASD_MAJOR 94
260 #define VIODASD_MAJOR 112
261 #define AOE_MAJOR 152
262 #define SX8_MAJOR1 160
263 #define SX8_MAJOR2 161
264 #define XVD_MAJOR 202
265 #define SDMMC_MAJOR 179
269 #define SCSI_BLK_MAJOR(M) ( \
270 (M) == SCSI_DISK0_MAJOR \
271 || (M) == SCSI_CDROM_MAJOR \
272 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) \
273 || ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
275 /* Maximum number of partitions supported by linux. */
276 #define MAX_NUM_PARTS 64
278 static char* _device_get_part_path (PedDevice* dev, int num);
279 static int _partition_is_mounted_by_path (const char* path);
282 _read_fd (int fd, char **buf)
285 size_t size = PROC_DEVICES_BUFSIZ;
288 *buf = malloc (size * sizeof (char));
294 p = &(*buf) [filesize];
295 s = read (fd, p, PROC_DEVICES_BUFSIZ);
296 /* exit if there is an error or EOF is reached */
301 char *new_buf = realloc (*buf, size);
302 if (new_buf == NULL) {
303 int saved_errno = errno;
311 if (filesize == 0 && s < 0) {
316 char *new_buf = realloc (*buf, filesize + 1);
317 if (new_buf == NULL) {
318 int saved_errno = errno;
324 (*buf)[filesize] = '\0';
331 _major_type_in_devices (int major, const char* type)
340 fd = open ("/proc/devices", O_RDONLY);
344 if (_read_fd(fd, &buf) < 0) {
350 end = strchr(line, '\n');
359 if (!strncmp(line, "Block devices:", 14))
364 name = strrchr(line, ' ');
365 if (!name || strcmp(name+1, type))
368 maj = strtol(line, &name, 10);
378 end = strchr(line, '\n');
386 _is_ide_major (int major)
403 _is_cpqarray_major (int major)
405 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
406 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
410 _is_i2o_major (int major)
412 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
416 _is_sx8_major (int major)
418 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
422 _is_virtblk_major (int major)
424 return _major_type_in_devices (major, "virtblk");
427 #ifdef ENABLE_DEVICE_MAPPER
429 _is_dm_major (int major)
431 return _major_type_in_devices (major, "device-mapper");
435 _dm_maptype (PedDevice *dev)
437 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
439 uint64_t start, length;
440 char *target_type = NULL;
443 const char* dev_dir = getenv ("DM_DEV_DIR");
445 if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
448 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
451 if (!dm_task_set_major_minor(dmt, arch_specific->major,
452 arch_specific->minor, 0))
455 dm_task_no_open_count(dmt);
457 if (!dm_task_run(dmt))
460 dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms);
462 arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
463 if (arch_specific->dmtype == NULL)
467 dm_task_destroy(dmt);
477 char buf [512]; /* readdir(3) claims d_name[256] */
480 mapper_dir = opendir ("/dev/mapper");
484 /* Search the /dev/mapper directory for devices w/ the same major
485 * number that was returned from _probe_lvm_major().
487 while ((dent = readdir (mapper_dir))) {
488 if (strcmp (dent->d_name, ".") == 0 ||
489 strcmp (dent->d_name, "..") == 0)
492 snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
494 if (stat (buf, &st) != 0)
497 if (_is_dm_major(major(st.st_rdev)))
498 _ped_device_probe (buf);
500 closedir (mapper_dir);
507 _device_stat (PedDevice* dev, struct stat * dev_stat)
509 PED_ASSERT (dev != NULL, return 0);
510 PED_ASSERT (!dev->external_mode, return 0);
513 if (!stat (dev->path, dev_stat)) {
516 if (ped_exception_throw (
518 PED_EXCEPTION_RETRY_CANCEL,
519 _("Could not stat device %s - %s."),
522 != PED_EXCEPTION_RETRY)
529 _device_probe_type (PedDevice* dev)
531 struct stat dev_stat;
534 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
536 if (!_device_stat (dev, &dev_stat))
539 if (!S_ISBLK(dev_stat.st_mode)) {
540 dev->type = PED_DEVICE_FILE;
544 arch_specific->major = dev_major = major (dev_stat.st_rdev);
545 arch_specific->minor = dev_minor = minor (dev_stat.st_rdev);
547 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
548 dev->type = PED_DEVICE_SCSI;
549 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
550 dev->type = PED_DEVICE_IDE;
551 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
552 dev->type = PED_DEVICE_DAC960;
553 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
554 dev->type = PED_DEVICE_ATARAID;
555 } else if (dev_major == AOE_MAJOR && (dev_minor % 0x10 == 0)) {
556 dev->type = PED_DEVICE_AOE;
557 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
558 dev->type = PED_DEVICE_DASD;
559 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
560 dev->type = PED_DEVICE_VIODASD;
561 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
562 dev->type = PED_DEVICE_SX8;
563 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
564 dev->type = PED_DEVICE_I2O;
565 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
566 dev->type = PED_DEVICE_CPQARRAY;
567 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
568 dev->type = PED_DEVICE_UBD;
569 #ifdef ENABLE_DEVICE_MAPPER
570 } else if (_is_dm_major(dev_major)) {
571 dev->type = PED_DEVICE_DM;
572 if (_dm_maptype(dev)) {
573 ped_exception_throw (
575 PED_EXCEPTION_CANCEL,
576 _("Unable to determine the dm type of %s."),
580 } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
581 dev->type = PED_DEVICE_XVD;
582 } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
583 dev->type = PED_DEVICE_SDMMC;
584 } else if (_is_virtblk_major(dev_major)) {
585 dev->type = PED_DEVICE_VIRTBLK;
586 } else if (dev_major == LOOP_MAJOR) {
587 dev->type = PED_DEVICE_FILE;
588 } else if (dev_major == MD_MAJOR) {
589 dev->type = PED_DEVICE_MD;
591 dev->type = PED_DEVICE_UNKNOWN;
598 _get_linux_version ()
600 static int kver = -1;
612 if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
615 return kver = KERNEL_VERSION (major, minor, teeny);
621 static int have_kern26 = -1;
624 if (have_kern26 != -1)
627 kver = _get_linux_version();
628 return have_kern26 = kver >= KERNEL_VERSION (2,6,0) ? 1 : 0;
633 get_blkid_topology (LinuxSpecific *arch_specific)
635 arch_specific->probe = blkid_new_probe ();
636 if (!arch_specific->probe)
639 if (blkid_probe_set_device(arch_specific->probe,
640 arch_specific->fd, 0, 0))
643 arch_specific->topology =
644 blkid_probe_get_topology(arch_specific->probe);
649 _device_set_sector_size (PedDevice* dev)
651 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
654 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
655 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
657 PED_ASSERT (dev->open_count, return);
659 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
660 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
664 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
665 ped_exception_throw (
666 PED_EXCEPTION_WARNING,
668 _("Could not determine sector size for %s: %s.\n"
669 "Using the default sector size (%lld)."),
670 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
672 dev->sector_size = (long long)sector_size;
673 dev->phys_sector_size = dev->sector_size;
677 get_blkid_topology(arch_specific);
678 if (!arch_specific->topology) {
679 dev->phys_sector_size = 0;
681 dev->phys_sector_size =
682 blkid_topology_get_physical_sector_size(
683 arch_specific->topology);
685 if (dev->phys_sector_size == 0) {
686 ped_exception_throw (
687 PED_EXCEPTION_WARNING,
689 _("Could not determine physical sector size for %s.\n"
690 "Using the logical sector size (%lld)."),
691 dev->path, dev->sector_size);
692 dev->phys_sector_size = dev->sector_size;
696 #if defined __s390__ || defined __s390x__
697 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
698 if (dev->type == PED_DEVICE_DASD) {
699 arch_specific->real_sector_size = dev->sector_size;
700 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
706 _kernel_has_blkgetsize64(void)
708 int version = _get_linux_version();
710 if (version >= KERNEL_VERSION (2,5,4)) return 1;
711 if (version < KERNEL_VERSION (2,5,0) &&
712 version >= KERNEL_VERSION (2,4,18)) return 1;
716 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
718 _device_get_length (PedDevice* dev)
721 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
723 const char* test_str;
727 PED_ASSERT (dev->open_count > 0, return 0);
728 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
730 test_str = getenv ("PARTED_TEST_DEVICE_LENGTH");
732 && xstrtoll (test_str, NULL, 10, &test_size, NULL) == LONGINT_OK)
735 if (_kernel_has_blkgetsize64()) {
736 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
737 return bytes / dev->sector_size;
741 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
742 ped_exception_throw (
744 PED_EXCEPTION_CANCEL,
745 _("Unable to determine the size of %s (%s)."),
755 _device_probe_geometry (PedDevice* dev)
757 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
758 struct stat dev_stat;
759 struct hd_geometry geometry;
761 if (!_device_stat (dev, &dev_stat))
763 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
765 _device_set_sector_size (dev);
767 dev->length = _device_get_length (dev);
771 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
772 * still use it in 2.4.x, but this is contentious. Perhaps we should
774 dev->bios_geom.sectors = 63;
775 dev->bios_geom.heads = 255;
776 dev->bios_geom.cylinders
777 = dev->length / (63 * 255);
779 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
780 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
781 && geometry.sectors && geometry.heads) {
782 dev->hw_geom.sectors = geometry.sectors;
783 dev->hw_geom.heads = geometry.heads;
784 dev->hw_geom.cylinders
785 = dev->length / (dev->hw_geom.heads
786 * dev->hw_geom.sectors);
788 dev->hw_geom = dev->bios_geom;
795 strip_name(char* str)
800 for (i = 0; str[i] != 0; i++) {
801 if (!isspace (str[i])
802 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
812 init_ide (PedDevice* dev)
814 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
815 struct stat dev_stat;
816 struct hd_driveid hdi;
817 PedExceptionOption ex_status;
819 int sector_multiplier = 0;
821 if (!_device_stat (dev, &dev_stat))
824 if (!ped_device_open (dev))
827 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
828 ex_status = ped_exception_throw (
829 PED_EXCEPTION_WARNING,
830 PED_EXCEPTION_IGNORE_CANCEL,
831 _("Could not get identity of device %s - %s"),
832 dev->path, strerror (errno));
834 case PED_EXCEPTION_CANCEL:
835 goto error_close_dev;
837 case PED_EXCEPTION_UNHANDLED:
838 ped_exception_catch ();
839 case PED_EXCEPTION_IGNORE:
840 dev->model = strdup(_("Generic IDE"));
843 PED_ASSERT (0, (void) 0);
847 /* hdi.model is not guaranteed to be NULL terminated */
848 memcpy (hdi_buf, hdi.model, 40);
850 dev->model = strip_name (hdi_buf);
852 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
853 sector_multiplier = hdi.ata7_sectinfo.multiplier;
855 sector_multiplier = 1;
857 if (sector_multiplier != 1) {
858 ex_status = ped_exception_throw (
859 PED_EXCEPTION_WARNING,
860 PED_EXCEPTION_IGNORE_CANCEL,
861 _("Device %s has multiple (%d) logical sectors "
862 "per physical sector.\n"
863 "GNU Parted supports this EXPERIMENTALLY for "
864 "some special disk label/file system "
865 "combinations, e.g. GPT and ext2/3.\n"
866 "Please consult the web site for up-to-date "
868 dev->path, sector_multiplier);
871 case PED_EXCEPTION_CANCEL:
872 goto error_close_dev;
874 case PED_EXCEPTION_UNHANDLED:
875 ped_exception_catch ();
876 case PED_EXCEPTION_IGNORE:
879 PED_ASSERT (0, (void) 0);
884 /* XXX sector_size has not been set yet! */
885 /* dev->phys_sector_size = dev->sector_size
886 * sector_multiplier;*/
887 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
890 if (!_device_probe_geometry (dev))
891 goto error_close_dev;
893 ped_device_close (dev);
897 ped_device_close (dev);
902 /* This function reads the /sys entry named "file" for device "dev". */
904 read_device_sysfs_file (PedDevice *dev, const char *file)
910 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
911 last_component (dev->path), file);
913 if ((f = fopen (name_buf, "r")) == NULL)
916 if (fgets (buf, 255, f) == NULL)
920 return strip_name (buf);
923 /* This function sends a query to a SCSI device for vendor and product
924 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
928 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
930 /* The following are defined by the SCSI-2 specification. */
931 typedef struct _scsi_inquiry_cmd
934 uint8_t lun; /* bits 5-7 denote the LUN */
937 uint8_t alloc_length;
939 } __attribute__((packed)) scsi_inquiry_cmd_t;
941 typedef struct _scsi_inquiry_data
943 uint8_t peripheral_info;
945 uint8_t version_info;
947 uint8_t additional_length;
951 uint8_t vendor_id[8];
952 uint8_t product_id[16];
953 uint8_t product_revision[4];
954 uint8_t vendor_specific[20];
955 uint8_t _reserved3[40];
956 } __attribute__((packed)) scsi_inquiry_data_t;
965 scsi_inquiry_data_t out;
966 scsi_inquiry_cmd_t in;
970 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
976 memset (&arg, 0x00, sizeof(struct scsi_arg));
978 arg.outlen = sizeof(scsi_inquiry_data_t);
979 arg.data.in.op = INQUIRY;
980 arg.data.in.lun = dev->host << 5;
981 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
982 arg.data.in.page_code = 0;
983 arg.data.in.reserved = 0;
984 arg.data.in.control = 0;
986 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
989 memcpy (buf, arg.data.out.vendor_id, 8);
991 *vendor = strip_name (buf);
993 memcpy (buf, arg.data.out.product_id, 16);
995 *product = strip_name (buf);
1000 /* This function provides the vendor and product name for a SCSI device.
1001 * It supports both the modern /sys interface and direct queries
1002 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
1005 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
1007 *vendor = read_device_sysfs_file (dev, "vendor");
1008 *product = read_device_sysfs_file (dev, "model");
1009 if (*vendor && *product)
1012 return scsi_query_product_info (dev, vendor, product);
1016 init_scsi (PedDevice* dev)
1021 uint32_t host_unique_id;
1024 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1028 if (!ped_device_open (dev))
1031 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
1034 if (ped_exception_throw (
1035 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
1036 _("Error initialising SCSI device %s - %s"),
1037 dev->path, strerror (errno))
1038 != PED_EXCEPTION_IGNORE)
1039 goto error_close_dev;
1040 if (!_device_probe_geometry (dev))
1041 goto error_close_dev;
1042 ped_device_close (dev);
1046 dev->host = idlun.host_unique_id;
1047 dev->did = idlun.dev_id;
1049 dev->model = (char*) ped_malloc (8 + 16 + 2);
1051 goto error_close_dev;
1053 if (scsi_get_product_info (dev, &vendor, &product)) {
1054 sprintf (dev->model, "%.8s %.16s", vendor, product);
1058 strcpy (dev->model, "Generic SCSI");
1061 if (!_device_probe_geometry (dev))
1062 goto error_close_dev;
1064 ped_device_close (dev);
1068 ped_device_close (dev);
1074 init_file (PedDevice* dev)
1076 struct stat dev_stat;
1078 if (!_device_stat (dev, &dev_stat))
1080 if (!ped_device_open (dev))
1083 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1084 char *p = getenv ("PARTED_SECTOR_SIZE");
1087 if (0 < s && s % 512 == 0)
1088 dev->sector_size = s;
1090 dev->phys_sector_size = dev->sector_size;
1092 if (S_ISBLK(dev_stat.st_mode))
1093 dev->length = _device_get_length (dev);
1095 dev->length = dev_stat.st_size / dev->sector_size;
1096 if (dev->length <= 0) {
1097 ped_exception_throw (
1098 PED_EXCEPTION_ERROR,
1099 PED_EXCEPTION_CANCEL,
1100 _("The device %s has zero length, and can't possibly "
1101 "store a file system or partition table. Perhaps "
1102 "you selected the wrong device?"),
1104 goto error_close_dev;
1107 ped_device_close (dev);
1109 dev->bios_geom.cylinders = dev->length / 4 / 32;
1110 dev->bios_geom.heads = 4;
1111 dev->bios_geom.sectors = 32;
1112 dev->hw_geom = dev->bios_geom;
1113 dev->model = strdup ("");
1118 ped_device_close (dev);
1123 #if defined __s390__ || defined __s390x__
1125 init_dasd (PedDevice* dev, const char* model_name)
1127 struct stat dev_stat;
1128 struct hd_geometry geo;
1129 dasd_information_t dasd_info;
1131 if (!_device_stat (dev, &dev_stat))
1134 if (!ped_device_open (dev))
1137 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1139 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
1141 _device_set_sector_size (dev);
1142 if (!dev->sector_size)
1143 goto error_close_dev;
1145 dev->length = _device_get_length (dev);
1147 goto error_close_dev;
1149 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1150 dev->hw_geom.sectors = geo.sectors;
1151 dev->hw_geom.heads = geo.heads;
1152 dev->hw_geom.cylinders = dev->length
1153 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1154 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1155 dev->bios_geom = dev->hw_geom;
1157 dev->bios_geom.sectors = 12;
1158 dev->bios_geom.heads = 15;
1159 dev->bios_geom.cylinders = dev->length
1160 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1161 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1162 dev->hw_geom = dev->bios_geom;
1165 if (!ioctl(arch_specific->fd, BIODASDINFO, &dasd_info)) {
1166 arch_specific->devno = dasd_info.devno;
1168 arch_specific->devno = arch_specific->major * 256 +
1169 arch_specific->minor;
1172 dev->model = strdup (model_name);
1174 ped_device_close (dev);
1178 ped_device_close (dev);
1185 init_generic (PedDevice* dev, const char* model_name)
1187 struct stat dev_stat;
1188 PedExceptionOption ex_status;
1190 if (!_device_stat (dev, &dev_stat))
1193 if (!ped_device_open (dev))
1196 ped_exception_fetch_all ();
1197 if (_device_probe_geometry (dev)) {
1198 ped_exception_leave_all ();
1200 if (!_device_get_length (dev)) {
1201 ped_exception_catch ();
1202 ped_exception_leave_all ();
1203 goto error_close_dev;
1206 /* hack to allow use of files, for testing */
1207 ped_exception_catch ();
1208 ped_exception_leave_all ();
1210 ex_status = ped_exception_throw (
1211 PED_EXCEPTION_WARNING,
1212 PED_EXCEPTION_IGNORE_CANCEL,
1213 _("Unable to determine geometry of "
1214 "file/device %s. You should not use Parted "
1215 "unless you REALLY know what you're doing!"),
1217 switch (ex_status) {
1218 case PED_EXCEPTION_CANCEL:
1219 goto error_close_dev;
1221 case PED_EXCEPTION_UNHANDLED:
1222 ped_exception_catch ();
1223 case PED_EXCEPTION_IGNORE:
1226 PED_ASSERT (0, (void) 0);
1230 /* what should we stick in here? */
1231 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1232 dev->bios_geom.cylinders = dev->length / 4 / 32;
1233 dev->bios_geom.heads = 4;
1234 dev->bios_geom.sectors = 32;
1235 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1236 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1239 dev->model = strdup (model_name);
1241 ped_device_close (dev);
1245 ped_device_close (dev);
1251 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1253 *type = read_device_sysfs_file (dev, "type");
1254 *name = read_device_sysfs_file (dev, "name");
1262 init_sdmmc (PedDevice* dev)
1267 if (sdmmc_get_product_info (dev, &type, &name)) {
1268 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1272 snprintf (id, sizeof(id) - 1, "%s",
1273 _("Generic SD/MMC Storage Card"));
1275 return init_generic(dev, id);
1279 linux_new (const char* path)
1282 LinuxSpecific* arch_specific;
1284 PED_ASSERT (path != NULL, return NULL);
1286 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1290 dev->path = strdup (path);
1292 goto error_free_dev;
1295 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1296 if (!dev->arch_specific)
1297 goto error_free_path;
1298 arch_specific = LINUX_SPECIFIC (dev);
1299 arch_specific->dmtype = NULL;
1301 arch_specific->probe = NULL;
1302 arch_specific->topology = NULL;
1305 dev->open_count = 0;
1307 dev->external_mode = 0;
1309 dev->boot_dirty = 0;
1311 if (!_device_probe_type (dev))
1312 goto error_free_arch_specific;
1314 switch (dev->type) {
1315 case PED_DEVICE_IDE:
1316 if (!init_ide (dev))
1317 goto error_free_arch_specific;
1320 case PED_DEVICE_SCSI:
1321 if (!init_scsi (dev))
1322 goto error_free_arch_specific;
1325 case PED_DEVICE_DAC960:
1326 if (!init_generic (dev, _("DAC960 RAID controller")))
1327 goto error_free_arch_specific;
1330 case PED_DEVICE_SX8:
1331 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1332 goto error_free_arch_specific;
1335 case PED_DEVICE_AOE:
1336 if (!init_generic (dev, _("ATA over Ethernet Device")))
1337 goto error_free_arch_specific;
1340 #if defined __s390__ || defined __s390x__
1341 case PED_DEVICE_DASD:
1342 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1343 goto error_free_arch_specific;
1347 case PED_DEVICE_VIODASD:
1348 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1349 goto error_free_arch_specific;
1352 case PED_DEVICE_CPQARRAY:
1353 if (!init_generic (dev, _("Compaq Smart Array")))
1354 goto error_free_arch_specific;
1357 case PED_DEVICE_ATARAID:
1358 if (!init_generic (dev, _("ATARAID Controller")))
1359 goto error_free_arch_specific;
1362 case PED_DEVICE_I2O:
1363 if (!init_generic (dev, _("I2O Controller")))
1364 goto error_free_arch_specific;
1367 case PED_DEVICE_UBD:
1368 if (!init_generic (dev, _("User-Mode Linux UBD")))
1369 goto error_free_arch_specific;
1372 case PED_DEVICE_FILE:
1373 if (!init_file (dev))
1374 goto error_free_arch_specific;
1380 if (arch_specific->dmtype == NULL
1381 || asprintf(&type, _("Linux device-mapper (%s)"),
1382 arch_specific->dmtype) == -1)
1383 goto error_free_arch_specific;
1384 bool ok = init_generic (dev, type);
1387 goto error_free_arch_specific;
1391 case PED_DEVICE_XVD:
1392 if (!init_generic (dev, _("Xen Virtual Block Device")))
1393 goto error_free_arch_specific;
1396 case PED_DEVICE_UNKNOWN:
1397 if (!init_generic (dev, _("Unknown")))
1398 goto error_free_arch_specific;
1401 case PED_DEVICE_SDMMC:
1402 if (!init_sdmmc (dev))
1403 goto error_free_arch_specific;
1405 case PED_DEVICE_VIRTBLK:
1406 if (!init_generic(dev, _("Virtio Block Device")))
1407 goto error_free_arch_specific;
1411 if (!init_generic(dev, _("Linux Software RAID Array")))
1412 goto error_free_arch_specific;
1416 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1417 PED_EXCEPTION_CANCEL,
1418 _("ped_device_new() Unsupported device type"));
1419 goto error_free_arch_specific;
1423 error_free_arch_specific:
1424 free (dev->arch_specific);
1434 linux_destroy (PedDevice* dev)
1436 LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
1437 void *p = arch_specific->dmtype;
1440 if (arch_specific->probe)
1441 blkid_free_probe(arch_specific->probe);
1444 free (dev->arch_specific);
1451 linux_is_busy (PedDevice* dev)
1456 if (_partition_is_mounted_by_path (dev->path))
1459 for (i = 0; i < 32; i++) {
1462 part_name = _device_get_part_path (dev, i);
1465 status = _partition_is_mounted_by_path (part_name);
1475 /* we need to flush the master device, and with kernel < 2.6 all the partition
1476 * devices, because there is no coherency between the caches with old kernels.
1477 * We should only flush unmounted partition devices, because:
1478 * - there is never a need to flush them (we're not doing IO there)
1479 * - flushing a device that is mounted causes unnecessary IO, and can
1480 * even screw journaling & friends up. Even cause oopsen!
1483 _flush_cache (PedDevice* dev)
1485 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1492 ioctl (arch_specific->fd, BLKFLSBUF);
1494 /* With linux-2.6.0 and newer, we're done. */
1498 for (i = 1; i < 16; i++) {
1502 name = _device_get_part_path (dev, i);
1505 if (!_partition_is_mounted_by_path (name)) {
1506 fd = open (name, WR_MODE, 0);
1508 ioctl (fd, BLKFLSBUF);
1510 if (fsync (fd) < 0 || close (fd) < 0)
1511 if (ped_exception_throw (
1512 PED_EXCEPTION_WARNING,
1513 PED_EXCEPTION_RETRY +
1514 PED_EXCEPTION_IGNORE,
1515 _("Error fsyncing/closing %s: %s"),
1516 name, strerror (errno))
1517 == PED_EXCEPTION_RETRY)
1526 linux_open (PedDevice* dev)
1528 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1531 arch_specific->fd = open (dev->path, RW_MODE);
1533 if (arch_specific->fd == -1) {
1534 char* rw_error_msg = strerror (errno);
1536 arch_specific->fd = open (dev->path, RD_MODE);
1538 if (arch_specific->fd == -1) {
1539 if (ped_exception_throw (
1540 PED_EXCEPTION_ERROR,
1541 PED_EXCEPTION_RETRY_CANCEL,
1542 _("Error opening %s: %s"),
1543 dev->path, strerror (errno))
1544 != PED_EXCEPTION_RETRY) {
1550 ped_exception_throw (
1551 PED_EXCEPTION_WARNING,
1553 _("Unable to open %s read-write (%s). %s has "
1554 "been opened read-only."),
1555 dev->path, rw_error_msg, dev->path);
1562 /* With kernels < 2.6 flush cache for cache coherence issues */
1563 if (!_have_kern26())
1570 linux_refresh_open (PedDevice* dev)
1576 linux_close (PedDevice* dev)
1578 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1583 if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
1584 if (ped_exception_throw (
1585 PED_EXCEPTION_WARNING,
1586 PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
1587 _("Error fsyncing/closing %s: %s"),
1588 dev->path, strerror (errno))
1589 == PED_EXCEPTION_RETRY)
1595 linux_refresh_close (PedDevice* dev)
1602 #if SIZEOF_OFF_T < 8
1604 static _syscall5(int,_llseek,
1606 unsigned long, offset_high,
1607 unsigned long, offset_low,
1609 unsigned int, origin)
1612 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1617 retval = _llseek(fd,
1618 ((unsigned long long)offset) >> 32,
1619 ((unsigned long long)offset) & 0xffffffff,
1622 return (retval==-1 ? (loff_t) retval : result);
1625 #endif /* SIZEOF_OFF_T < 8 */
1628 _device_seek (const PedDevice* dev, PedSector sector)
1630 LinuxSpecific* arch_specific;
1632 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1633 PED_ASSERT (dev != NULL, return 0);
1634 PED_ASSERT (!dev->external_mode, return 0);
1636 arch_specific = LINUX_SPECIFIC (dev);
1638 #if SIZEOF_OFF_T < 8
1639 if (sizeof (off_t) < 8) {
1640 loff_t pos = (loff_t)(sector * dev->sector_size);
1641 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1645 off_t pos = sector * dev->sector_size;
1646 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1651 _read_lastoddsector (const PedDevice* dev, void* buffer)
1653 LinuxSpecific* arch_specific;
1654 struct blkdev_ioctl_param ioctl_param;
1656 PED_ASSERT(dev != NULL, return 0);
1657 PED_ASSERT(buffer != NULL, return 0);
1659 arch_specific = LINUX_SPECIFIC (dev);
1662 ioctl_param.block = 0; /* read the last sector */
1663 ioctl_param.content_length = dev->sector_size;
1664 ioctl_param.block_contents = buffer;
1666 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1667 PedExceptionOption opt;
1668 opt = ped_exception_throw (
1669 PED_EXCEPTION_ERROR,
1670 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1671 _("%s during read on %s"),
1672 strerror (errno), dev->path);
1674 if (opt == PED_EXCEPTION_CANCEL)
1676 if (opt == PED_EXCEPTION_RETRY)
1684 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1687 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1688 PedExceptionOption ex_status;
1689 void* diobuf = NULL;
1691 PED_ASSERT (dev != NULL, return 0);
1692 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1694 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1695 /* Kludge. This is necessary to read/write the last
1696 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1698 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1699 && start + count - 1 == dev->length - 1)
1700 return ped_device_read (dev, buffer, start, count - 1)
1701 && _read_lastoddsector (
1702 dev, (char *) buffer + (count-1) * 512);
1705 if (_device_seek (dev, start))
1708 ex_status = ped_exception_throw (
1709 PED_EXCEPTION_ERROR,
1710 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1711 _("%s during seek for read on %s"),
1712 strerror (errno), dev->path);
1714 switch (ex_status) {
1715 case PED_EXCEPTION_IGNORE:
1718 case PED_EXCEPTION_RETRY:
1721 case PED_EXCEPTION_UNHANDLED:
1722 ped_exception_catch ();
1723 case PED_EXCEPTION_CANCEL:
1726 PED_ASSERT (0, (void) 0);
1731 size_t read_length = count * dev->sector_size;
1732 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1736 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1738 memcpy(buffer, diobuf, status);
1739 if (status == (ssize_t) read_length)
1742 read_length -= status;
1743 buffer = (char *) buffer + status;
1747 ex_status = ped_exception_throw (
1748 PED_EXCEPTION_ERROR,
1749 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1751 ? _("end of file while reading %s")
1752 : _("%s during read on %s")),
1756 switch (ex_status) {
1757 case PED_EXCEPTION_IGNORE:
1761 case PED_EXCEPTION_RETRY:
1764 case PED_EXCEPTION_UNHANDLED:
1765 ped_exception_catch ();
1766 case PED_EXCEPTION_CANCEL:
1770 PED_ASSERT (0, (void) 0);
1781 _write_lastoddsector (PedDevice* dev, const void* buffer)
1783 LinuxSpecific* arch_specific;
1784 struct blkdev_ioctl_param ioctl_param;
1786 PED_ASSERT(dev != NULL, return 0);
1787 PED_ASSERT(buffer != NULL, return 0);
1789 arch_specific = LINUX_SPECIFIC (dev);
1792 ioctl_param.block = 0; /* write the last sector */
1793 ioctl_param.content_length = dev->sector_size;
1794 ioctl_param.block_contents = (void*) buffer;
1796 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1797 PedExceptionOption opt;
1798 opt = ped_exception_throw (
1799 PED_EXCEPTION_ERROR,
1800 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1801 _("%s during write on %s"),
1802 strerror (errno), dev->path);
1804 if (opt == PED_EXCEPTION_CANCEL)
1806 if (opt == PED_EXCEPTION_RETRY)
1814 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1817 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1818 PedExceptionOption ex_status;
1822 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1824 if (dev->read_only) {
1825 if (ped_exception_throw (
1826 PED_EXCEPTION_ERROR,
1827 PED_EXCEPTION_IGNORE_CANCEL,
1828 _("Can't write to %s, because it is opened read-only."),
1830 != PED_EXCEPTION_IGNORE)
1836 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1837 /* Kludge. This is necessary to read/write the last
1838 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1840 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1841 && start + count - 1 == dev->length - 1)
1842 return ped_device_write (dev, buffer, start, count - 1)
1843 && _write_lastoddsector (
1844 dev, ((char*) buffer
1845 + (count-1) * dev->sector_size));
1848 if (_device_seek (dev, start))
1851 ex_status = ped_exception_throw (
1852 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1853 _("%s during seek for write on %s"),
1854 strerror (errno), dev->path);
1856 switch (ex_status) {
1857 case PED_EXCEPTION_IGNORE:
1860 case PED_EXCEPTION_RETRY:
1863 case PED_EXCEPTION_UNHANDLED:
1864 ped_exception_catch ();
1865 case PED_EXCEPTION_CANCEL:
1868 PED_ASSERT (0, (void) 0);
1874 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1875 dev->path, buffer, (int) start, (int) count);
1877 size_t write_length = count * dev->sector_size;
1879 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1881 memcpy(diobuf, buffer, write_length);
1882 diobuf_start = diobuf;
1884 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1885 if (status == write_length) break;
1887 write_length -= status;
1888 diobuf = (char *) diobuf + status;
1892 ex_status = ped_exception_throw (
1893 PED_EXCEPTION_ERROR,
1894 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1895 _("%s during write on %s"),
1896 strerror (errno), dev->path);
1898 switch (ex_status) {
1899 case PED_EXCEPTION_IGNORE:
1903 case PED_EXCEPTION_RETRY:
1906 case PED_EXCEPTION_UNHANDLED:
1907 ped_exception_catch ();
1908 case PED_EXCEPTION_CANCEL:
1912 PED_ASSERT (0, (void) 0);
1917 #endif /* !READ_ONLY */
1921 /* returns the number of sectors that are ok.
1924 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1926 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1931 PED_ASSERT(dev != NULL, return 0);
1933 if (!_device_seek (dev, start))
1936 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1937 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1940 for (done = 0; done < count; done += status / dev->sector_size) {
1941 status = read (arch_specific->fd, diobuf,
1942 (size_t) ((count-done) * dev->sector_size));
1944 memcpy(buffer, diobuf, status);
1954 _do_fsync (PedDevice* dev)
1956 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1958 PedExceptionOption ex_status;
1961 status = fsync (arch_specific->fd);
1962 if (status >= 0) break;
1964 ex_status = ped_exception_throw (
1965 PED_EXCEPTION_ERROR,
1966 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1967 _("%s during write on %s"),
1968 strerror (errno), dev->path);
1970 switch (ex_status) {
1971 case PED_EXCEPTION_IGNORE:
1974 case PED_EXCEPTION_RETRY:
1977 case PED_EXCEPTION_UNHANDLED:
1978 ped_exception_catch ();
1979 case PED_EXCEPTION_CANCEL:
1982 PED_ASSERT (0, (void) 0);
1990 linux_sync (PedDevice* dev)
1992 PED_ASSERT (dev != NULL, return 0);
1993 PED_ASSERT (!dev->external_mode, return 0);
1997 if (!_do_fsync (dev))
2004 linux_sync_fast (PedDevice* dev)
2006 PED_ASSERT (dev != NULL, return 0);
2007 PED_ASSERT (!dev->external_mode, return 0);
2011 if (!_do_fsync (dev))
2013 /* no cache flush... */
2018 _compare_digit_state (char ch, int need_digit)
2020 return !!isdigit (ch) == need_digit;
2023 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
2024 * Motivation: accept devices looking like /dev/rd/c0d0, but
2025 * not looking like /dev/hda1 and /dev/rd/c0d0p1
2028 _match_rd_device (const char* name)
2033 /* exclude directory names from test */
2034 pos = strrchr(name, '/') ?: name;
2042 for (state = 0; state < 4; state++) {
2043 int want_digits = (state % 2 == 1);
2047 if (!_compare_digit_state (*pos, want_digits))
2050 } while (_compare_digit_state (*pos, want_digits));
2057 _probe_proc_partitions ()
2059 FILE* proc_part_file;
2060 int major, minor, size;
2062 char part_name [256];
2063 char dev_name [256];
2065 proc_part_file = fopen ("/proc/partitions", "r");
2066 if (!proc_part_file)
2069 if (fgets (buf, 256, proc_part_file) == NULL)
2072 if (fgets (buf, 256, proc_part_file) == NULL)
2075 while (fgets (buf, 512, proc_part_file)
2076 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
2078 /* Heuristic for telling partitions and devices apart
2079 * Probably needs to be improved
2081 if (!_match_rd_device (part_name)
2082 && isdigit (part_name [strlen (part_name) - 1]))
2085 strcpy (dev_name, "/dev/");
2086 strcat (dev_name, part_name);
2087 _ped_device_probe (dev_name);
2090 fclose (proc_part_file);
2100 _skip_entry (const char *name)
2103 static struct _entry entries[] = {
2104 { ".", sizeof (".") - 1 },
2105 { "..", sizeof ("..") - 1 },
2106 { "dm-", sizeof ("dm-") - 1 },
2107 { "loop", sizeof ("loop") - 1 },
2108 { "ram", sizeof ("ram") - 1 },
2112 for (i = entries; i->name != 0; i++) {
2113 if (strncmp (name, i->name, i->len) == 0)
2124 struct dirent *dirent;
2125 char dev_name [256];
2128 if (!(blockdir = opendir ("/sys/block")))
2130 while ((dirent = readdir (blockdir))) {
2131 if (_skip_entry (dirent->d_name))
2134 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2135 continue; /* device name too long! */
2137 strcpy (dev_name, "/dev/");
2138 strcat (dev_name, dirent->d_name);
2139 /* in /sys/block, '/'s are replaced with '!' or '.' */
2140 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2141 if (*ptr == '!' || *ptr == '.')
2144 _ped_device_probe (dev_name);
2147 closedir (blockdir);
2152 _probe_standard_devices ()
2154 _ped_device_probe ("/dev/hda");
2155 _ped_device_probe ("/dev/hdb");
2156 _ped_device_probe ("/dev/hdc");
2157 _ped_device_probe ("/dev/hdd");
2158 _ped_device_probe ("/dev/hde");
2159 _ped_device_probe ("/dev/hdf");
2160 _ped_device_probe ("/dev/hdg");
2161 _ped_device_probe ("/dev/hdh");
2163 _ped_device_probe ("/dev/sda");
2164 _ped_device_probe ("/dev/sdb");
2165 _ped_device_probe ("/dev/sdc");
2166 _ped_device_probe ("/dev/sdd");
2167 _ped_device_probe ("/dev/sde");
2168 _ped_device_probe ("/dev/sdf");
2176 /* we should probe the standard devs too, even with /proc/partitions,
2177 * because /proc/partitions might return devfs stuff, and we might not
2178 * have devfs available
2180 _probe_standard_devices ();
2182 #ifdef ENABLE_DEVICE_MAPPER
2183 /* device-mapper devices aren't listed in /proc/partitions; or, if
2184 * they are, they're listed as dm-X. So, instead of relying on that,
2185 * we do our own checks.
2187 _probe_dm_devices ();
2190 /* /sys/block is more reliable and consistent; fall back to using
2191 * /proc/partitions if the former is unavailable, however.
2193 if (!_probe_sys_block ())
2194 _probe_proc_partitions ();
2198 _device_get_part_path (PedDevice* dev, int num)
2200 int path_len = strlen (dev->path);
2201 int result_len = path_len + 16;
2204 result = (char*) ped_malloc (result_len);
2208 /* Check for devfs-style /disc => /partN transformation
2209 unconditionally; the system might be using udev with devfs rules,
2210 and if not the test is harmless. */
2211 if (!strcmp (dev->path + path_len - 5, "/disc")) {
2212 /* replace /disc with /path%d */
2213 strcpy (result, dev->path);
2214 snprintf (result + path_len - 5, 16, "/part%d", num);
2215 } else if (dev->type == PED_DEVICE_DAC960
2216 || dev->type == PED_DEVICE_CPQARRAY
2217 || dev->type == PED_DEVICE_ATARAID
2218 || dev->type == PED_DEVICE_DM
2219 || isdigit (dev->path[path_len - 1]))
2220 snprintf (result, result_len, "%sp%d", dev->path, num);
2222 snprintf (result, result_len, "%s%d", dev->path, num);
2228 linux_partition_get_path (const PedPartition* part)
2230 return _device_get_part_path (part->disk->dev, part->num);
2234 _partition_get_part_dev (const PedPartition* part)
2236 struct stat dev_stat;
2237 int dev_major, dev_minor;
2239 if (stat (part->disk->dev->path, &dev_stat))
2241 dev_major = major (dev_stat.st_rdev);
2242 dev_minor = minor (dev_stat.st_rdev);
2243 return (dev_t)makedev (dev_major, dev_minor + part->num);
2247 _mount_table_search (const char* file_name, dev_t dev)
2249 struct stat part_stat;
2251 char part_name[512];
2254 file = fopen (file_name, "r");
2257 while (fgets (line, 512, file)) {
2258 if (sscanf (line, "%s", part_name) == 1
2259 && stat (part_name, &part_stat) == 0) {
2260 if (part_stat.st_rdev == dev) {
2271 _partition_is_mounted_by_dev (dev_t dev)
2273 return _mount_table_search( "/proc/mounts", dev)
2274 || _mount_table_search( "/proc/swaps", dev)
2275 || _mount_table_search( "/etc/mtab", dev);
2279 _partition_is_mounted_by_path (const char *path)
2281 struct stat part_stat;
2282 if (stat (path, &part_stat) != 0)
2284 if (!S_ISBLK(part_stat.st_mode))
2286 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2290 _partition_is_mounted (const PedPartition *part)
2293 if (!ped_partition_is_active (part))
2295 dev = _partition_get_part_dev (part);
2298 return _partition_is_mounted_by_dev (dev);
2302 _has_partitions (const PedDisk* disk)
2304 PED_ASSERT(disk != NULL, return 0);
2306 /* Some devices can't be partitioned. */
2307 if (!strcmp (disk->type->name, "loop"))
2314 linux_partition_is_busy (const PedPartition* part)
2318 PED_ASSERT (part != NULL, return 0);
2320 if (_partition_is_mounted (part))
2322 if (part->type == PED_PARTITION_EXTENDED) {
2323 for (walk = part->part_list; walk; walk = walk->next) {
2324 if (linux_partition_is_busy (walk))
2332 _blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
2334 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2335 struct blkpg_ioctl_arg ioctl_arg;
2338 ioctl_arg.flags = 0;
2339 ioctl_arg.datalen = sizeof (struct blkpg_partition);
2340 ioctl_arg.data = (void*) part;
2342 return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
2346 _blkpg_add_partition (PedDisk* disk, const PedPartition *part)
2348 struct blkpg_partition linux_part;
2349 const char* vol_name;
2352 PED_ASSERT(disk != NULL, return 0);
2353 PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0,
2356 if (!_has_partitions (disk))
2359 if (ped_disk_type_check_feature (disk->type,
2360 PED_DISK_TYPE_PARTITION_NAME))
2361 vol_name = ped_partition_get_name (part);
2365 dev_name = _device_get_part_path (disk->dev, part->num);
2369 memset (&linux_part, 0, sizeof (linux_part));
2370 linux_part.start = part->geom.start * disk->dev->sector_size;
2371 /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
2372 if (part->type & PED_PARTITION_EXTENDED)
2373 linux_part.length = part->geom.length == 1 ? 512 : 1024;
2375 linux_part.length = part->geom.length * disk->dev->sector_size;
2376 linux_part.pno = part->num;
2377 strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
2379 strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
2383 if (!_blkpg_part_command (disk->dev, &linux_part,
2384 BLKPG_ADD_PARTITION)) {
2385 return ped_exception_throw (
2386 PED_EXCEPTION_ERROR,
2387 PED_EXCEPTION_IGNORE_CANCEL,
2388 _("Error informing the kernel about modifications to "
2389 "partition %s -- %s. This means Linux won't know "
2390 "about any changes you made to %s until you reboot "
2391 "-- so you shouldn't mount it or use it in any way "
2392 "before rebooting."),
2396 == PED_EXCEPTION_IGNORE;
2403 _blkpg_remove_partition (PedDisk* disk, int n)
2405 struct blkpg_partition linux_part;
2407 if (!_has_partitions (disk))
2410 memset (&linux_part, 0, sizeof (linux_part));
2412 return _blkpg_part_command (disk->dev, &linux_part,
2413 BLKPG_DEL_PARTITION);
2417 * The number of partitions that a device can have depends on the kernel.
2418 * If we don't find this value in /sys/block/DEV/range, we will use our own
2422 _device_get_partition_range(PedDevice* dev)
2429 r = snprintf(path, sizeof(path), "/sys/block/%s/range",
2430 last_component(dev->path));
2431 if (r < 0 || r >= sizeof(path))
2432 return MAX_NUM_PARTS;
2434 fp = fopen(path, "r");
2436 return MAX_NUM_PARTS;
2438 ok = fscanf(fp, "%d", &range) == 1;
2441 /* (range <= 0) is none sense.*/
2442 return ok && range > 0 ? range : MAX_NUM_PARTS;
2446 * Sync the partition table in two step process:
2447 * 1. Remove all of the partitions from the kernel's tables, but do not attempt
2448 * removal of any partition for which the corresponding ioctl call fails.
2449 * 2. Add all the partitions that we hold in disk, throwing a warning
2450 * if we cannot because step 1 failed to remove it and it is not being
2451 * added back with the same start and length.
2453 * To achieve this two step process we must calculate the minimum number of
2454 * maximum possible partitions between what linux supports and what the label
2455 * type supports. EX:
2457 * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables)
2460 _disk_sync_part_table (PedDisk* disk)
2462 PED_ASSERT(disk != NULL, return 0);
2463 PED_ASSERT(disk->dev != NULL, return 0);
2466 /* lpn = largest partition number. */
2467 if (ped_disk_get_max_supported_partition_count(disk, &lpn))
2468 lpn = PED_MIN(lpn, _device_get_partition_range(disk->dev));
2470 lpn = _device_get_partition_range(disk->dev);
2472 /* Its not possible to support largest_partnum < 0.
2473 * largest_partnum == 0 would mean does not support partitions.
2478 int *ok = calloc (lpn, sizeof *ok);
2481 int *errnums = ped_malloc(sizeof(int) * lpn);
2485 /* Attempt to remove each and every partition, retrying for
2486 up to max_sleep_seconds upon any failure due to EBUSY. */
2487 unsigned int sleep_microseconds = 10000;
2488 unsigned int max_sleep_seconds = 1;
2489 unsigned int n_sleep = (max_sleep_seconds
2490 * 1000000 / sleep_microseconds);
2492 for (i = 0; i < n_sleep; i++) {
2494 usleep (sleep_microseconds);
2497 for (j = 0; j < lpn; j++) {
2499 ok[j] = _blkpg_remove_partition (disk, j + 1);
2501 if (!ok[j] && errnums[j] == EBUSY)
2509 for (i = 1; i <= lpn; i++) {
2510 const PedPartition *part = ped_disk_get_partition (disk, i);
2512 if (!ok[i - 1] && errnums[i - 1] == EBUSY) {
2513 struct hd_geometry geom;
2514 unsigned long long length = 0;
2515 /* get start and length of existing partition */
2516 char *dev_name = _device_get_part_path (disk->dev, i);
2519 int fd = open (dev_name, O_RDONLY);
2521 || ioctl (fd, HDIO_GETGEO, &geom)
2522 || ioctl (fd, BLKGETSIZE64, &length)) {
2523 ped_exception_throw (
2525 PED_EXCEPTION_CANCEL,
2526 _("Unable to determine the size and length of %s."),
2534 length /= disk->dev->sector_size;
2536 if (geom.start == part->geom.start
2537 && length == part->geom.length)
2539 /* If the new partition is unchanged and the
2540 existing one was not removed because it was
2541 in use, then reset the error flag and do not
2542 try to add it since it is already there. */
2546 /* add the (possibly modified or new) partition */
2547 if (!_blkpg_add_partition (disk, part)) {
2548 ped_exception_throw (
2549 PED_EXCEPTION_ERROR,
2550 PED_EXCEPTION_RETRY_CANCEL,
2551 _("Failed to add partition %d (%s)"),
2552 i, strerror (errno));
2558 char *bad_part_list = NULL;
2559 /* now warn about any errors */
2560 for (i = 1; i <= lpn; i++) {
2561 if (ok[i - 1] || errnums[i - 1] == ENXIO)
2563 if (bad_part_list == NULL) {
2564 bad_part_list = malloc (lpn * 5);
2567 bad_part_list[0] = 0;
2569 sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i);
2571 if (bad_part_list == NULL)
2574 bad_part_list[strlen (bad_part_list) - 2] = 0;
2575 if (ped_exception_throw (
2576 PED_EXCEPTION_ERROR,
2577 PED_EXCEPTION_IGNORE_CANCEL,
2578 _("Partition(s) %s on %s have been written, but we have "
2579 "been unable to inform the kernel of the change, "
2580 "probably because it/they are in use. As a result, "
2581 "the old partition(s) will remain in use. You "
2582 "should reboot now before making further changes."),
2583 bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE)
2585 free (bad_part_list);
2593 #ifdef ENABLE_DEVICE_MAPPER
2595 _dm_remove_map_name(char *name)
2597 struct dm_task *task = NULL;
2600 task = dm_task_create(DM_DEVICE_REMOVE);
2604 dm_task_set_name (task, name);
2606 rc = dm_task_run(task);
2607 dm_task_update_nodes();
2608 dm_task_destroy(task);
2616 _dm_is_part (struct dm_info *this, char *name)
2618 struct dm_task* task = NULL;
2619 struct dm_info* info = alloca(sizeof *info);
2620 struct dm_deps* deps = NULL;
2624 task = dm_task_create(DM_DEVICE_DEPS);
2628 dm_task_set_name(task, name);
2629 if (!dm_task_run(task))
2632 memset(info, '\0', sizeof *info);
2633 dm_task_get_info(task, info);
2637 deps = dm_task_get_deps(task);
2641 for (i = 0; i < deps->count; i++) {
2642 unsigned int ma = major(deps->device[i]),
2643 mi = minor(deps->device[i]);
2645 if (ma == this->major && mi == this->minor)
2650 dm_task_destroy(task);
2655 _dm_remove_parts (PedDevice* dev)
2657 struct dm_task* task = NULL;
2658 struct dm_info* info = alloca(sizeof *info);
2659 struct dm_names* names = NULL;
2660 unsigned int next = 0;
2662 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2664 task = dm_task_create(DM_DEVICE_LIST);
2668 if (!dm_task_set_major_minor (task, arch_specific->major,
2669 arch_specific->minor, 0))
2672 if (!dm_task_run(task))
2675 memset(info, '\0', sizeof *info);
2676 dm_task_get_info(task, info);
2680 names = dm_task_get_names(task);
2686 names = (void *) ((char *) names + next);
2688 if (_dm_is_part(info, names->name))
2689 rc += _dm_remove_map_name(names->name);
2694 dm_task_update_nodes();
2695 dm_task_destroy(task);
2702 dm_task_destroy(task);
2703 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2704 _("parted was unable to re-read the partition "
2705 "table on %s (%s). This means Linux won't know "
2706 "anything about the modifications you made. "),
2707 dev->path, strerror (errno));
2712 _dm_add_partition (PedDisk* disk, PedPartition* part)
2714 char* vol_name = NULL;
2715 const char* dev_name = NULL;
2716 char* params = NULL;
2717 LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
2719 if (!_has_partitions(disk))
2722 /* Get map name from devicemapper */
2723 struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
2727 if (!dm_task_set_major_minor (task, arch_specific->major,
2728 arch_specific->minor, 0))
2731 if (!dm_task_run(task))
2734 dev_name = dm_task_get_name (task);
2736 if (asprintf (&vol_name, "%sp%d", dev_name, part->num) == -1)
2739 /* Caution: dm_task_destroy frees dev_name. */
2740 dm_task_destroy (task);
2743 if (asprintf (¶ms, "%d:%d %lld", arch_specific->major,
2744 arch_specific->minor, part->geom.start) == -1)
2747 task = dm_task_create (DM_DEVICE_CREATE);
2751 dm_task_set_name (task, vol_name);
2752 dm_task_add_target (task, 0, part->geom.length,
2754 if (dm_task_run (task)) {
2755 //printf("0 %ld linear %s\n", part->geom.length, params);
2756 dm_task_update_nodes();
2757 dm_task_destroy(task);
2762 _dm_remove_map_name(vol_name);
2765 dm_task_update_nodes();
2767 dm_task_destroy (task);
2774 _dm_reread_part_table (PedDisk* disk)
2776 int largest_partnum = ped_disk_get_last_partition_num (disk);
2777 if (largest_partnum <= 0)
2781 int last = PED_MIN (largest_partnum, 16);
2785 if (!_dm_remove_parts(disk->dev))
2788 for (i = 1; i <= last; i++) {
2791 part = ped_disk_get_partition (disk, i);
2795 if (!_dm_add_partition (disk, part))
2805 static int have_blkpg = -1;
2808 if (have_blkpg != -1)
2811 kver = _get_linux_version();
2812 return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
2815 /* Return nonzero upon success, 0 if something fails. */
2817 linux_disk_commit (PedDisk* disk)
2819 if (!_has_partitions (disk))
2822 #ifdef ENABLE_DEVICE_MAPPER
2823 if (disk->dev->type == PED_DEVICE_DM)
2824 return _dm_reread_part_table (disk);
2826 if (disk->dev->type != PED_DEVICE_FILE) {
2827 /* The ioctl() command BLKPG_ADD_PARTITION does not notify
2828 * the devfs system; consequently, /proc/partitions will not
2829 * be up to date, and the proper links in /dev are not
2830 * created. Therefore, if using DevFS, we must get the kernel
2831 * to re-read and grok the partition table.
2833 /* Work around kernel dasd problem so we really do BLKRRPART */
2835 if (disk->dev->type != PED_DEVICE_DASD && _have_blkpg ()) {
2836 if (!_disk_sync_part_table (disk))
2847 static PedAlignment*
2848 linux_get_minimum_alignment(const PedDevice *dev)
2850 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2854 if (blkid_topology_get_minimum_io_size(tp) == 0)
2855 return ped_alignment_new(
2856 blkid_topology_get_alignment_offset(tp) /
2858 dev->phys_sector_size / dev->sector_size);
2860 return ped_alignment_new(
2861 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2862 blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
2865 static PedAlignment*
2866 linux_get_optimum_alignment(const PedDevice *dev)
2868 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2872 /* If optimal_io_size is 0 _and_ alignment_offset is 0 _and_
2873 minimum_io_size is a power of 2 then go with the device.c default */
2874 unsigned long minimum_io_size = blkid_topology_get_minimum_io_size(tp);
2875 if (blkid_topology_get_optimal_io_size(tp) == 0 &&
2876 blkid_topology_get_alignment_offset(tp) == 0 &&
2877 (minimum_io_size & (minimum_io_size - 1)) == 0)
2880 /* If optimal_io_size is 0 and we don't meet the other criteria
2881 for using the device.c default, return the minimum alignment. */
2882 if (blkid_topology_get_optimal_io_size(tp) == 0)
2883 return linux_get_minimum_alignment(dev);
2885 return ped_alignment_new(
2886 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2887 blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
2891 static PedDeviceArchOps linux_dev_ops = {
2893 destroy: linux_destroy,
2894 is_busy: linux_is_busy,
2896 refresh_open: linux_refresh_open,
2898 refresh_close: linux_refresh_close,
2903 sync_fast: linux_sync_fast,
2904 probe_all: linux_probe_all,
2906 get_minimum_alignment: linux_get_minimum_alignment,
2907 get_optimum_alignment: linux_get_optimum_alignment,
2911 PedDiskArchOps linux_disk_ops = {
2912 partition_get_path: linux_partition_get_path,
2913 partition_is_busy: linux_partition_is_busy,
2914 disk_commit: linux_disk_commit
2917 PedArchitecture ped_linux_arch = {
2918 dev_ops: &linux_dev_ops,
2919 disk_ops: &linux_disk_ops