mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-18 13:16:34 +00:00
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:
@@ -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> */
|
||||
|
||||
/*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user