lib,loopdev: add missing functions
- improve loop_info usage (don't call ioctl more than once) - add functions to get devno and inode of the backing file - add function for compare any file with backing file by devno + inode or by filename Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
7eac65fcf6
commit
6c224de18b
|
@ -96,6 +96,7 @@ struct loopdev_cxt {
|
|||
unsigned int has_info:1; /* .info contains data */
|
||||
unsigned int extra_check:1; /* unusual stuff for iterator */
|
||||
unsigned int debug:1; /* debug mode ON/OFF */
|
||||
unsigned int info_failed:1; /* LOOP_GET_STATUS ioctl failed */
|
||||
|
||||
struct sysfs_cxt sysfs; /* pointer to /sys/dev/block/<maj:min>/ */
|
||||
struct loop_info64 info; /* for GET/SET ioctl */
|
||||
|
@ -120,6 +121,7 @@ enum {
|
|||
*/
|
||||
extern int is_loopdev(const char *device);
|
||||
extern int loopdev_is_autoclear(const char *device);
|
||||
|
||||
extern char *loopdev_get_backing_file(const char *device);
|
||||
extern int loopdev_is_used(const char *device, const char *filename,
|
||||
uint64_t offset, int flags);
|
||||
|
@ -161,12 +163,22 @@ int loopcxt_set_encryption(struct loopdev_cxt *lc,
|
|||
const char *password);
|
||||
|
||||
extern char *loopcxt_get_backing_file(struct loopdev_cxt *lc);
|
||||
extern int loopcxt_get_backing_devno(struct loopdev_cxt *lc, dev_t *devno);
|
||||
extern int loopcxt_get_backing_inode(struct loopdev_cxt *lc, ino_t *ino);
|
||||
extern int loopcxt_get_offset(struct loopdev_cxt *lc, uint64_t *offset);
|
||||
extern int loopcxt_get_sizelimit(struct loopdev_cxt *lc, uint64_t *size);
|
||||
extern int loopcxt_get_encrypt_type(struct loopdev_cxt *lc, uint32_t *type);
|
||||
extern const char *loopcxt_get_crypt_name(struct loopdev_cxt *lc);
|
||||
extern int loopcxt_is_autoclear(struct loopdev_cxt *lc);
|
||||
extern int loopcxt_is_readonly(struct loopdev_cxt *lc);
|
||||
extern int loopcxt_find_by_backing_file(struct loopdev_cxt *lc,
|
||||
const char *filename,
|
||||
uint64_t offset, int flags);
|
||||
|
||||
extern int loopcxt_is_used(struct loopdev_cxt *lc,
|
||||
struct stat *st,
|
||||
const char *backing_file,
|
||||
uint64_t offset,
|
||||
int flags);
|
||||
|
||||
#endif /* UTIL_LINUX_LOOPDEV_H */
|
||||
|
|
207
lib/loopdev.c
207
lib/loopdev.c
|
@ -88,6 +88,7 @@ int loopcxt_set_device(struct loopdev_cxt *lc, const char *device)
|
|||
lc->fd = -1;
|
||||
lc->mode = 0;
|
||||
lc->has_info = 0;
|
||||
lc->info_failed = 0;
|
||||
*lc->device = '\0';
|
||||
memset(&lc->info, 0, sizeof(lc->info));
|
||||
|
||||
|
@ -236,7 +237,6 @@ struct sysfs_cxt *loopcxt_get_sysfs(struct loopdev_cxt *lc)
|
|||
}
|
||||
}
|
||||
|
||||
DBG(lc, loopdev_debug("sysfs: returns context"));
|
||||
return &lc->sysfs;
|
||||
}
|
||||
|
||||
|
@ -540,20 +540,23 @@ struct loop_info64 *loopcxt_get_info(struct loopdev_cxt *lc)
|
|||
{
|
||||
int fd;
|
||||
|
||||
if (!lc)
|
||||
if (!lc || lc->info_failed)
|
||||
return NULL;
|
||||
if (lc->has_info)
|
||||
return &lc->info;
|
||||
|
||||
DBG(lc, loopdev_debug("reading loop_info64"));
|
||||
|
||||
fd = loopcxt_get_fd(lc);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
if (ioctl(fd, LOOP_GET_STATUS64, &lc->info) == 0) {
|
||||
lc->has_info = 1;
|
||||
lc->info_failed = 0;
|
||||
DBG(lc, loopdev_debug("reading loop_info64 OK"));
|
||||
return &lc->info;
|
||||
} else {
|
||||
lc->info_failed = 1;
|
||||
DBG(lc, loopdev_debug("reading loop_info64 FAILED"));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -587,7 +590,7 @@ char *loopcxt_get_backing_file(struct loopdev_cxt *lc)
|
|||
}
|
||||
}
|
||||
|
||||
DBG(lc, loopdev_debug("return backing file: %s", res));
|
||||
DBG(lc, loopdev_debug("get_backing_file [%s]", res));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -610,10 +613,11 @@ int loopcxt_get_offset(struct loopdev_cxt *lc, uint64_t *offset)
|
|||
if (lo) {
|
||||
if (offset)
|
||||
*offset = lo->lo_offset;
|
||||
return 0;
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DBG(lc, loopdev_debug("get_offset [rc=%d]", rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -636,10 +640,92 @@ int loopcxt_get_sizelimit(struct loopdev_cxt *lc, uint64_t *size)
|
|||
if (lo) {
|
||||
if (size)
|
||||
*size = lo->lo_sizelimit;
|
||||
return 0;
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DBG(lc, loopdev_debug("get_sizelimit [rc=%d]", rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* @lc: context
|
||||
* @devno: returns encryption type
|
||||
*
|
||||
* Cryptoloop is DEPRECATED!
|
||||
*
|
||||
* Returns: <0 on error, 0 on success
|
||||
*/
|
||||
int loopcxt_get_encrypt_type(struct loopdev_cxt *lc, uint32_t *type)
|
||||
{
|
||||
struct loop_info64 *lo = loopcxt_get_info(lc);
|
||||
int rc = -EINVAL;
|
||||
|
||||
if (lo) {
|
||||
if (type)
|
||||
*type = lo->lo_encrypt_type;
|
||||
rc = 0;
|
||||
}
|
||||
DBG(lc, loopdev_debug("get_encrypt_type [rc=%d]", rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* @lc: context
|
||||
* @devno: returns crypt name
|
||||
*
|
||||
* Cryptoloop is DEPRECATED!
|
||||
*
|
||||
* Returns: <0 on error, 0 on success
|
||||
*/
|
||||
const char *loopcxt_get_crypt_name(struct loopdev_cxt *lc)
|
||||
{
|
||||
struct loop_info64 *lo = loopcxt_get_info(lc);
|
||||
|
||||
if (lo)
|
||||
return (char *) lo->lo_crypt_name;
|
||||
|
||||
DBG(lc, loopdev_debug("get_crypt_name failed"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* @lc: context
|
||||
* @devno: returns backing file devno
|
||||
*
|
||||
* Returns: <0 on error, 0 on success
|
||||
*/
|
||||
int loopcxt_get_backing_devno(struct loopdev_cxt *lc, dev_t *devno)
|
||||
{
|
||||
struct loop_info64 *lo = loopcxt_get_info(lc);
|
||||
int rc = -EINVAL;
|
||||
|
||||
if (lo) {
|
||||
if (devno)
|
||||
*devno = lo->lo_device;
|
||||
rc = 0;
|
||||
}
|
||||
DBG(lc, loopdev_debug("get_backing_devno [rc=%d]", rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* @lc: context
|
||||
* @ino: returns backing file inode
|
||||
*
|
||||
* Returns: <0 on error, 0 on success
|
||||
*/
|
||||
int loopcxt_get_backing_inode(struct loopdev_cxt *lc, ino_t *ino)
|
||||
{
|
||||
struct loop_info64 *lo = loopcxt_get_info(lc);
|
||||
int rc = -EINVAL;
|
||||
|
||||
if (lo) {
|
||||
if (ino)
|
||||
*ino = lo->lo_inode;
|
||||
rc = 0;
|
||||
}
|
||||
DBG(lc, loopdev_debug("get_backing_inode [rc=%d]", rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -689,6 +775,67 @@ int loopcxt_is_readonly(struct loopdev_cxt *lc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @lc: context
|
||||
* @st: backing file stat or NULL
|
||||
* @backing_file: filename
|
||||
* @offset: offset
|
||||
* @flags: LOOPDEV_FL_OFFSET if @offset should not be ignored
|
||||
*
|
||||
* Returns 1 if the current @lc loopdev is associated with the given backing
|
||||
* file. Note that the preferred way is to use devno and inode number rather
|
||||
* than filename. The @backing_file filename is poor solution usable in case
|
||||
* that you don't have rights to call stat().
|
||||
*
|
||||
* Don't forget that old kernels provide very restricted (in size) backing
|
||||
* filename by LOOP_GET_STAT64 ioctl only.
|
||||
*/
|
||||
int loopcxt_is_used(struct loopdev_cxt *lc,
|
||||
struct stat *st,
|
||||
const char *backing_file,
|
||||
uint64_t offset,
|
||||
int flags)
|
||||
{
|
||||
ino_t ino;
|
||||
dev_t dev;
|
||||
|
||||
if (!lc)
|
||||
return 0;
|
||||
|
||||
DBG(lc, loopdev_debug("checking %s vs. %s",
|
||||
loopcxt_get_device(lc),
|
||||
backing_file));
|
||||
|
||||
if (st && loopcxt_get_backing_inode(lc, &ino) == 0 &&
|
||||
loopcxt_get_backing_devno(lc, &dev) == 0) {
|
||||
|
||||
if (ino == st->st_ino && dev == st->st_dev)
|
||||
goto found;
|
||||
|
||||
/* don't use filename if we have devno and inode */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* poor man's solution */
|
||||
if (backing_file) {
|
||||
char *name = loopcxt_get_backing_file(lc);
|
||||
int rc = name && strcmp(name, backing_file) == 0;
|
||||
|
||||
free(name);
|
||||
if (rc)
|
||||
goto found;
|
||||
}
|
||||
|
||||
return 0;
|
||||
found:
|
||||
if (flags & LOOPDEV_FL_OFFSET) {
|
||||
uint64_t off;
|
||||
|
||||
return loopcxt_get_offset(lc, &off) == 0 && off == offset;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The setting is removed by loopcxt_set_device() loopcxt_next()!
|
||||
*/
|
||||
|
@ -891,6 +1038,7 @@ int loopcxt_setup_device(struct loopdev_cxt *lc)
|
|||
}
|
||||
memset(&lc->info, 0, sizeof(lc->info));
|
||||
lc->has_info = 0;
|
||||
lc->info_failed = 0;
|
||||
|
||||
DBG(lc, loopdev_debug("setup success [rc=0]"));
|
||||
return 0;
|
||||
|
@ -998,7 +1146,7 @@ int loopdev_is_used(const char *device, const char *filename,
|
|||
uint64_t offset, int flags)
|
||||
{
|
||||
struct loopdev_cxt lc;
|
||||
char *backing = NULL;
|
||||
struct stat st;
|
||||
int rc = 0;
|
||||
|
||||
if (!device)
|
||||
|
@ -1007,23 +1155,10 @@ int loopdev_is_used(const char *device, const char *filename,
|
|||
loopcxt_init(&lc, 0);
|
||||
loopcxt_set_device(&lc, device);
|
||||
|
||||
backing = loopcxt_get_backing_file(&lc);
|
||||
if (!backing)
|
||||
goto done;
|
||||
if (filename && strcmp(filename, backing) != 0)
|
||||
goto done;
|
||||
if (flags & LOOPDEV_FL_OFFSET) {
|
||||
uint64_t off;
|
||||
rc = !stat(filename, &st);
|
||||
rc = loopcxt_is_used(&lc, rc ? &st : NULL, filename, offset, flags);
|
||||
|
||||
if (loopcxt_get_offset(&lc, &off) != 0 || off != offset)
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
done:
|
||||
free(backing);
|
||||
loopcxt_deinit(&lc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1046,33 +1181,23 @@ int loopdev_delete(const char *device)
|
|||
int loopcxt_find_by_backing_file(struct loopdev_cxt *lc, const char *filename,
|
||||
uint64_t offset, int flags)
|
||||
{
|
||||
int rc;
|
||||
int rc, hasst;
|
||||
struct stat st;
|
||||
|
||||
if (!filename)
|
||||
return -EINVAL;
|
||||
|
||||
hasst = !stat(filename, &st);
|
||||
|
||||
rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
while((rc = loopcxt_next(lc)) == 0) {
|
||||
char *backing = loopcxt_get_backing_file(lc);
|
||||
while ((rc = loopcxt_next(lc)) == 0) {
|
||||
|
||||
if (!backing || strcmp(backing, filename)) {
|
||||
free(backing);
|
||||
continue;
|
||||
}
|
||||
|
||||
free(backing);
|
||||
|
||||
if (flags & LOOPDEV_FL_OFFSET) {
|
||||
uint64_t off;
|
||||
if (loopcxt_get_offset(lc, &off) != 0 || offset != off)
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
break;
|
||||
if (loopcxt_is_used(lc, hasst ? &st : NULL,
|
||||
filename, offset, flags))
|
||||
break;
|
||||
}
|
||||
|
||||
loopcxt_deinit_iterator(lc);
|
||||
|
|
Loading…
Reference in New Issue