scst: Rework vdisk_get_file_size()

Linux kernel commit 4e7b5671c6a8 ("block: remove i_bdev"; v5.11-rc1) removes
the i_bdev member of struct inode. Hence use blkdev_get_by_path() to open
block devices when the struct block_device pointer is needed instead of using
filp_open().



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@9316 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2021-01-03 02:51:31 +00:00
parent 1c3d35bdab
commit 616730270b
5 changed files with 114 additions and 80 deletions
+23
View File
@@ -161,6 +161,29 @@ static inline int bdev_io_opt(struct block_device *bdev)
}
#endif
/*
* See also commit d4d77629953e ("block: clean up blkdev_get() wrappers and
* their users") # v2.6.38.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
static inline struct block_device *
blkdev_get_by_path(const char *path, fmode_t mode, void *holder)
{
struct block_device *bdev;
int err;
bdev = lookup_bdev(path);
if (IS_ERR(bdev))
return bdev;
err = blkdev_get(bdev, mode);
if (err)
return ERR_PTR(err);
return bdev;
}
#endif
/* <linux/bsg-lib.h> */
/*
+3
View File
@@ -5543,6 +5543,9 @@ struct scst_data_descriptor {
uint64_t sdd_blocks;
};
loff_t scst_file_size(const char *path, umode_t *mode);
loff_t scst_bdev_size(const char *path);
loff_t scst_file_or_bdev_size(const char *path);
ssize_t scst_readv(struct file *file, const struct kvec *vec,
unsigned long vlen, loff_t *pos);
ssize_t scst_writev(struct file *file, const struct kvec *vec,
+10 -36
View File
@@ -679,9 +679,7 @@ check:
static int vdisk_get_file_size(const struct scst_vdisk_dev *virt_dev,
loff_t *file_size)
{
struct inode *inode;
int res = 0;
struct file *fd;
loff_t res;
TRACE_ENTRY();
@@ -694,42 +692,18 @@ static int vdisk_get_file_size(const struct scst_vdisk_dev *virt_dev,
goto out;
}
*file_size = 0;
fd = filp_open(virt_dev->filename, O_LARGEFILE | O_RDONLY, 0600);
if (IS_ERR(fd)) {
res = PTR_ERR(fd);
if ((res == -EMEDIUMTYPE) && virt_dev->blockio)
TRACE(TRACE_MINOR, "Unable to open %s with EMEDIUMTYPE, "
"DRBD passive?", virt_dev->filename);
else
PRINT_ERROR("filp_open(%s) failed: %d", virt_dev->filename, res);
res = scst_file_or_bdev_size(virt_dev->filename);
if (res == -EMEDIUMTYPE && virt_dev->blockio) {
TRACE(TRACE_MINOR,
"Unable to open %s with EMEDIUMTYPE, DRBD passive?",
virt_dev->filename);
goto out;
}
inode = file_inode(fd);
if (virt_dev->blockio && !S_ISBLK(inode->i_mode)) {
PRINT_ERROR("File %s is NOT a block device", virt_dev->filename);
res = -EINVAL;
goto out_close;
if (res < 0) {
PRINT_ERROR("opening %s failed: %lld", virt_dev->filename, res);
goto out;
}
if (S_ISREG(inode->i_mode)) {
/* Nothing to do */
} else if (S_ISBLK(inode->i_mode)) {
inode = inode->i_bdev->bd_inode;
} else {
PRINT_ERROR("File %s unsupported mode: mode=0%o\n",
virt_dev->filename, inode->i_mode);
res = -EINVAL;
goto out_close;
}
*file_size = inode->i_size;
out_close:
filp_close(fd, NULL);
*file_size = res;
out:
TRACE_EXIT_RES(res);
+72 -30
View File
@@ -6015,6 +6015,66 @@ ssize_t kernel_write(struct file *file, const void *buf, size_t count,
EXPORT_SYMBOL(kernel_write);
#endif
/**
* scst_file_size - returns the size of a regular file
* @path: Path of the file.
* @mode: If not NULL, the file mode will be stored in *@mode.
*
* Returns the file size or an error code.
*/
loff_t scst_file_size(const char *path, umode_t *mode)
{
struct file *filp;
struct inode *inode;
loff_t res;
filp = filp_open(path, O_LARGEFILE | O_RDONLY, 0600);
if (IS_ERR(filp))
return PTR_ERR(filp);
inode = file_inode(filp);
if (mode)
*mode = inode->i_mode;
res = S_ISREG(inode->i_mode) ? i_size_read(file_inode(filp)) : -ENOTTY;
filp_close(filp, NULL);
return res;
}
EXPORT_SYMBOL(scst_file_size);
/**
* scst_bdev_size - returns the size of a block device
* @path: Path of the block device.
*
* Returns the block device size or an error code.
*/
loff_t scst_bdev_size(const char *path)
{
struct block_device *bdev;
loff_t res;
bdev = blkdev_get_by_path(path, FMODE_READ, (void *)__func__);
if (IS_ERR(bdev))
return PTR_ERR(bdev);
res = i_size_read(bdev->bd_inode);
blkdev_put(bdev, FMODE_READ);
return res;
}
EXPORT_SYMBOL(scst_bdev_size);
loff_t scst_file_or_bdev_size(const char *path)
{
enum { INVALID_FILE_MODE = 0 };
umode_t mode = INVALID_FILE_MODE;
loff_t res;
res = scst_file_size(path, &mode);
if (S_ISREG(mode))
return res;
if (mode != INVALID_FILE_MODE && !S_ISBLK(mode))
return -EINVAL;
return scst_bdev_size(path);
}
EXPORT_SYMBOL(scst_file_or_bdev_size);
/**
* scst_readv - read data from a file into a kernel buffer
* @file: File to read from.
@@ -15133,7 +15193,6 @@ EXPORT_SYMBOL(scst_path_put);
int scst_copy_file(const char *src, const char *dest)
{
int res = 0;
struct inode *inode;
loff_t file_size, pos;
uint8_t *buf = NULL;
struct file *file_src = NULL, *file_dest = NULL;
@@ -15149,6 +15208,12 @@ int scst_copy_file(const char *src, const char *dest)
TRACE_DBG("Copying '%s' into '%s'", src, dest);
file_size = scst_file_or_bdev_size(src);
if (file_size < 0) {
res = file_size;
goto out;
}
file_src = filp_open(src, O_RDONLY, 0);
if (IS_ERR(file_src)) {
res = PTR_ERR(file_src);
@@ -15164,20 +15229,6 @@ int scst_copy_file(const char *src, const char *dest)
goto out_close;
}
inode = file_inode(file_src);
if (S_ISREG(inode->i_mode)) {
/* Nothing to do */
} else if (S_ISBLK(inode->i_mode)) {
inode = inode->i_bdev->bd_inode;
} else {
PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
res = -EINVAL;
goto out_skip;
}
file_size = inode->i_size;
buf = vmalloc(file_size);
if (buf == NULL) {
res = -ENOMEM;
@@ -15332,13 +15383,18 @@ static int __scst_read_file_transactional(const char *file_name,
{
int res;
struct file *file = NULL;
struct inode *inode;
loff_t file_size, pos;
TRACE_ENTRY();
TRACE_DBG("Loading file '%s'", file_name);
file_size = scst_file_or_bdev_size(file_name);
if (file_size < 0) {
res = file_size;
goto out;
}
file = filp_open(file_name, O_RDONLY, 0);
if (IS_ERR(file)) {
res = PTR_ERR(file);
@@ -15346,20 +15402,6 @@ static int __scst_read_file_transactional(const char *file_name,
goto out;
}
inode = file_inode(file);
if (S_ISREG(inode->i_mode)) {
/* Nothing to do */
} else if (S_ISBLK(inode->i_mode)) {
inode = inode->i_bdev->bd_inode;
} else {
PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
res = -EINVAL;
goto out_close;
}
file_size = inode->i_size;
if (file_size > size) {
PRINT_ERROR("Supplied buffer (%d) too small (need %d)", size,
(int)file_size);
+6 -14
View File
@@ -660,7 +660,6 @@ static int scst_pr_do_load_device_file(struct scst_device *dev,
{
int res = 0, rc;
struct file *file = NULL;
struct inode *inode;
char *buf = NULL;
loff_t file_size, pos, data_size;
uint64_t sign, version;
@@ -676,6 +675,12 @@ static int scst_pr_do_load_device_file(struct scst_device *dev,
TRACE_PR("Loading persistent file '%s'", file_name);
file_size = scst_file_or_bdev_size(file_name);
if (file_size < 0) {
res = file_size;
goto out;
}
file = filp_open(file_name, O_RDONLY, 0);
if (IS_ERR(file)) {
res = PTR_ERR(file);
@@ -683,19 +688,6 @@ static int scst_pr_do_load_device_file(struct scst_device *dev,
goto out;
}
inode = file_inode(file);
if (S_ISREG(inode->i_mode)) {
/* Nothing to do */
} else if (S_ISBLK(inode->i_mode)) {
inode = inode->i_bdev->bd_inode;
} else {
PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
goto out_close;
}
file_size = inode->i_size;
/* Let's limit the file size by some reasonable number */
if ((file_size == 0) || (file_size >= 15*1024*1024)) {
PRINT_ERROR("Invalid PR file size %d", (int)file_size);