[Devel] [PATCH VZ9 1/4] Add do_ftruncate that truncates a struct file
Vasileios Almpanis
vasileios.almpanis at virtuozzo.com
Thu Jan 29 14:15:04 MSK 2026
From: Tony Solomonik <tony.solomonik at gmail.com>
do_sys_ftruncate receives a file descriptor, fgets the struct file, and
finally actually truncates the file.
do_ftruncate allows for passing in a file directly, with the caller
already holding a reference to it.
Signed-off-by: Tony Solomonik <tony.solomonik at gmail.com>
Reviewed-by: Christian Brauner <brauner at kernel.org>
Link: https://lore.kernel.org/r/20240202121724.17461-2-tony.solomonik@gmail.com
Signed-off-by: Jens Axboe <axboe at kernel.dk>
(cherry picked from commit 5f0d594c602f870e3a3872f7ea42bf846a1d26cf)
https://virtuozzo.atlassian.net/browse/VSTOR-123292
Signed-off-by: Vasileios Almpanis <vasileios.almpanis at virtuozzo.com>
Feature: dm-ploop: ploop target driver
---
fs/internal.h | 1 +
fs/open.c | 53 +++++++++++++++++++++++++++------------------------
2 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/fs/internal.h b/fs/internal.h
index d4f05a3aa34a..2fbfd5863397 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -138,6 +138,7 @@ extern struct open_how build_open_how(int flags, umode_t mode);
extern int build_open_flags(const struct open_how *how, struct open_flags *op);
extern struct file *__close_fd_get_file(unsigned int fd);
+long do_ftruncate(struct file *file, loff_t length, int small);
long do_sys_ftruncate(unsigned int fd, loff_t length, int small);
int chmod_common(const struct path *path, umode_t mode);
int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
diff --git a/fs/open.c b/fs/open.c
index 8d30f25f3a59..b82f5fc333d7 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -153,49 +153,52 @@ COMPAT_SYSCALL_DEFINE2(truncate, const char __user *, path, compat_off_t, length
}
#endif
-long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
+long do_ftruncate(struct file *file, loff_t length, int small)
{
struct inode *inode;
struct dentry *dentry;
- struct fd f;
int error;
- error = -EINVAL;
- if (length < 0)
- goto out;
- error = -EBADF;
- f = fdget(fd);
- if (!f.file)
- goto out;
-
/* explicitly opened as large or we are on 64-bit box */
- if (f.file->f_flags & O_LARGEFILE)
+ if (file->f_flags & O_LARGEFILE)
small = 0;
- dentry = f.file->f_path.dentry;
+ dentry = file->f_path.dentry;
inode = dentry->d_inode;
- error = -EINVAL;
- if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
- goto out_putf;
+ if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
+ return -EINVAL;
- error = -EINVAL;
/* Cannot ftruncate over 2^31 bytes without large file support */
if (small && length > MAX_NON_LFS)
- goto out_putf;
+ return -EINVAL;
- error = -EPERM;
/* Check IS_APPEND on real upper inode */
- if (IS_APPEND(file_inode(f.file)))
- goto out_putf;
+ if (IS_APPEND(file_inode(file)))
+ return -EPERM;
sb_start_write(inode->i_sb);
- error = security_path_truncate(&f.file->f_path);
+ error = security_path_truncate(&file->f_path);
if (!error)
- error = do_truncate(file_mnt_user_ns(f.file), dentry, length,
- ATTR_MTIME | ATTR_CTIME, f.file);
+ error = do_truncate(file_mnt_user_ns(file), dentry, length,
+ ATTR_MTIME | ATTR_CTIME, file);
sb_end_write(inode->i_sb);
-out_putf:
+
+ return error;
+}
+
+long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
+{
+ struct fd f;
+ int error;
+
+ if (length < 0)
+ return -EINVAL;
+ f = fdget(fd);
+ if (!f.file)
+ return -EBADF;
+
+ error = do_ftruncate(f.file, length, small);
+
fdput(f);
-out:
return error;
}
--
2.43.0
More information about the Devel
mailing list