]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/blkdev.cc
2 * Ceph - scalable distributed file system
4 * Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
6 * This is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2.1, as published by the Free Software
9 * Foundation. See file COPYING.
14 #include <sys/ioctl.h>
17 #include "include/uuid.h"
21 #include <blkid/blkid.h>
25 static const char *sandbox_dir
= "";
27 void set_block_device_sandbox_dir(const char *dir
)
35 int get_block_device_size(int fd
, int64_t *psize
)
38 int ret
= ::ioctl(fd
, BLKGETSIZE64
, psize
);
39 #elif defined(BLKGETSIZE)
40 unsigned long sectors
= 0;
41 int ret
= ::ioctl(fd
, BLKGETSIZE
, §ors
);
42 *psize
= sectors
* 512ULL;
44 // cppcheck-suppress preprocessorErrorDirective
45 # error "Linux configuration error (get_block_device_size)"
53 * get the base device (strip off partition suffix and /dev/ prefix)
56 * /dev/cciss/c0d1p2 -> cciss/c0d1
57 * dev can a symbolic link.
59 int get_block_device_base(const char *dev
, char *out
, size_t out_len
)
64 char devname
[PATH_MAX
] = {0}, fn
[PATH_MAX
] = {0};
66 char realname
[PATH_MAX
] = {0};
68 if (strncmp(dev
, "/dev/", 5) != 0) {
69 if (realpath(dev
, realname
) == NULL
|| (strncmp(realname
, "/dev/", 5) != 0)) {
75 strncpy(devname
, realname
+ 5, PATH_MAX
- 5);
77 strncpy(devname
, dev
+ 5, strlen(dev
) - 5);
79 devname
[PATH_MAX
- 1] = '\0';
81 for (p
= devname
; *p
; ++p
)
85 snprintf(fn
, sizeof(fn
), "%s/sys/block/%s", sandbox_dir
, devname
);
86 if (stat(fn
, &st
) == 0) {
87 if (strlen(devname
) + 1 > out_len
) {
90 strncpy(out
, devname
, out_len
);
94 snprintf(fn
, sizeof(fn
), "%s/sys/block", sandbox_dir
);
99 struct dirent
*de
= nullptr;
100 while ((de
= ::readdir(dir
))) {
101 if (de
->d_name
[0] == '.')
103 snprintf(fn
, sizeof(fn
), "%s/sys/block/%s/%s", sandbox_dir
, de
->d_name
,
106 if (stat(fn
, &st
) == 0) {
108 if (strlen(de
->d_name
) + 1 > out_len
) {
112 strncpy(out
, de
->d_name
, out_len
);
125 * get a block device property as a string
127 * store property in *val, up to maxlen chars
128 * return 0 on success
129 * return negative error on error
131 int64_t get_block_device_string_property(const char *devname
,
132 const char *property
,
133 char *val
, size_t maxlen
)
135 char filename
[PATH_MAX
];
136 snprintf(filename
, sizeof(filename
),
137 "%s/sys/block/%s/%s", sandbox_dir
, devname
, property
);
139 FILE *fp
= fopen(filename
, "r");
145 if (fgets(val
, maxlen
- 1, fp
)) {
146 // truncate at newline
148 while (*p
&& *p
!= '\n')
159 * get a block device property
161 * return the value (we assume it is positive)
162 * return negative error on error
164 int64_t get_block_device_int_property(const char *devname
, const char *property
)
166 char buff
[256] = {0};
167 int r
= get_block_device_string_property(devname
, property
, buff
, sizeof(buff
));
171 for (char *p
= buff
; *p
; ++p
) {
178 r
= strtoll(buff
, &endptr
, 10);
179 if (endptr
!= buff
+ strlen(buff
))
184 bool block_device_support_discard(const char *devname
)
186 return get_block_device_int_property(devname
, "queue/discard_granularity") > 0;
189 int block_device_discard(int fd
, int64_t offset
, int64_t len
)
191 uint64_t range
[2] = {(uint64_t)offset
, (uint64_t)len
};
192 return ioctl(fd
, BLKDISCARD
, range
);
195 bool block_device_is_rotational(const char *devname
)
197 return get_block_device_int_property(devname
, "queue/rotational") > 0;
200 int block_device_model(const char *devname
, char *model
, size_t max
)
202 return get_block_device_string_property(devname
, "device/model", model
, max
);
205 int get_device_by_uuid(uuid_d dev_uuid
, const char* label
, char* partition
,
208 char uuid_str
[UUID_LEN
+1];
209 char basename
[PATH_MAX
];
210 const char* temp_partition_ptr
= NULL
;
211 blkid_cache cache
= NULL
;
212 blkid_dev dev
= NULL
;
215 dev_uuid
.print(uuid_str
);
217 if (blkid_get_cache(&cache
, NULL
) >= 0)
218 dev
= blkid_find_dev_with_tag(cache
, label
, (const char*)uuid_str
);
223 temp_partition_ptr
= blkid_dev_devname(dev
);
224 strncpy(partition
, temp_partition_ptr
, PATH_MAX
);
225 rc
= get_block_device_base(partition
, basename
,
228 strncpy(device
, basename
, sizeof(basename
));
237 /* From what I can tell, blkid_put_cache cleans up dev, which
238 * appears to be a pointer into cache, as well */
240 blkid_put_cache(cache
);
244 int get_device_by_fd(int fd
, char *partition
, char *device
, size_t max
)
247 int r
= fstat(fd
, &st
);
249 return -EINVAL
; // hrm.
251 dev_t devid
= S_ISBLK(st
.st_mode
) ? st
.st_rdev
: st
.st_dev
;
252 char *t
= blkid_devno_to_devname(devid
);
256 strncpy(partition
, t
, max
);
259 r
= blkid_devno_to_wholedisk(devid
, device
, max
, &diskdev
);
266 #elif defined(__APPLE__)
267 #include <sys/disk.h>
269 int get_block_device_size(int fd
, int64_t *psize
)
271 unsigned long blocksize
= 0;
272 int ret
= ::ioctl(fd
, DKIOCGETBLOCKSIZE
, &blocksize
);
274 unsigned long nblocks
;
275 ret
= ::ioctl(fd
, DKIOCGETBLOCKCOUNT
, &nblocks
);
277 *psize
= (int64_t)nblocks
* blocksize
;
284 bool block_device_support_discard(const char *devname
)
289 int block_device_discard(int fd
, int64_t offset
, int64_t len
)
294 bool block_device_is_rotational(const char *devname
)
299 int get_device_by_uuid(uuid_d dev_uuid
, const char* label
, char* partition
,
304 #elif defined(__FreeBSD__)
305 #include <sys/disk.h>
307 int get_block_device_size(int fd
, int64_t *psize
)
309 int ret
= ::ioctl(fd
, DIOCGMEDIASIZE
, psize
);
315 bool block_device_support_discard(const char *devname
)
320 int block_device_discard(int fd
, int64_t offset
, int64_t len
)
325 bool block_device_is_rotational(const char *devname
)
330 int get_device_by_uuid(uuid_d dev_uuid
, const char* label
, char* partition
,
335 int get_device_by_fd(int fd
, char *partition
, char *device
, size_t max
)
340 int get_block_device_size(int fd
, int64_t *psize
)
345 bool block_device_support_discard(const char *devname
)
350 int block_device_discard(int fd
, int64_t offset
, int64_t len
)
355 bool block_device_is_rotational(const char *devname
)
360 int get_device_by_uuid(uuid_d dev_uuid
, const char* label
, char* partition
,
366 int get_device_by_fd(int fd
, char *partition
, char *device
, size_t max
)