diff options
author | Amir Goldstein <amir73il@gmail.com> | 2024-10-07 15:22:29 +0200 |
---|---|---|
committer | Amir Goldstein <amir73il@gmail.com> | 2024-11-15 08:56:48 +0100 |
commit | 87a8a76c34a2ae6f667cc33249dc99705e363d1f (patch) | |
tree | 7b027644d0b4f252aa90e3b468eba00845de8e7b /fs/overlayfs | |
parent | c2c54b5f34f6341f24d06689d4b986bd75b4b41c (diff) |
ovl: allocate a container struct ovl_file for ovl private context
Instead of using ->private_data to point at realfile directly, so
that we can add more context per ovl open file.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Diffstat (limited to 'fs/overlayfs')
-rw-r--r-- | fs/overlayfs/dir.c | 14 | ||||
-rw-r--r-- | fs/overlayfs/file.c | 40 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 3 |
3 files changed, 48 insertions, 9 deletions
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 5cf529482a8a..08e683917d12 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -1323,6 +1323,7 @@ static int ovl_create_tmpfile(struct file *file, struct dentry *dentry, const struct cred *old_cred, *new_cred = NULL; struct path realparentpath; struct file *realfile; + struct ovl_file *of; struct dentry *newdentry; /* It's okay to set O_NOATIME, since the owner will be current fsuid */ int flags = file->f_flags | OVL_OPEN_FLAGS; @@ -1344,14 +1345,21 @@ static int ovl_create_tmpfile(struct file *file, struct dentry *dentry, if (err) goto out_revert_creds; + of = ovl_file_alloc(realfile); + if (!of) { + fput(realfile); + err = -ENOMEM; + goto out_revert_creds; + } + /* ovl_instantiate() consumes the newdentry reference on success */ newdentry = dget(realfile->f_path.dentry); err = ovl_instantiate(dentry, inode, newdentry, false, file); if (!err) { - file->private_data = realfile; + file->private_data = of; } else { dput(newdentry); - fput(realfile); + ovl_file_free(of); } out_revert_creds: ovl_revert_creds(old_cred); @@ -1407,7 +1415,7 @@ static int ovl_tmpfile(struct mnt_idmap *idmap, struct inode *dir, put_realfile: /* Without FMODE_OPENED ->release() won't be called on @file */ if (!(file->f_mode & FMODE_OPENED)) - fput(file->private_data); + ovl_file_free(file->private_data); put_inode: iput(inode); drop_write: diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 4a1cf45e3fa1..0fa0795d335f 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -89,10 +89,32 @@ static int ovl_change_flags(struct file *file, unsigned int flags) return 0; } +struct ovl_file { + struct file *realfile; +}; + +struct ovl_file *ovl_file_alloc(struct file *realfile) +{ + struct ovl_file *of = kzalloc(sizeof(struct ovl_file), GFP_KERNEL); + + if (unlikely(!of)) + return NULL; + + of->realfile = realfile; + return of; +} + +void ovl_file_free(struct ovl_file *of) +{ + fput(of->realfile); + kfree(of); +} + static int ovl_real_fdget_path(const struct file *file, struct fd *real, struct path *realpath) { - struct file *realfile = file->private_data; + struct ovl_file *of = file->private_data; + struct file *realfile = of->realfile; real->word = (unsigned long)realfile; @@ -144,6 +166,7 @@ static int ovl_open(struct inode *inode, struct file *file) struct dentry *dentry = file_dentry(file); struct file *realfile; struct path realpath; + struct ovl_file *of; int err; /* lazy lookup and verify lowerdata */ @@ -166,15 +189,20 @@ static int ovl_open(struct inode *inode, struct file *file) if (IS_ERR(realfile)) return PTR_ERR(realfile); - file->private_data = realfile; + of = ovl_file_alloc(realfile); + if (!of) { + fput(realfile); + return -ENOMEM; + } + + file->private_data = of; return 0; } static int ovl_release(struct inode *inode, struct file *file) { - fput(file->private_data); - + ovl_file_free(file->private_data); return 0; } @@ -426,13 +454,13 @@ static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync) static int ovl_mmap(struct file *file, struct vm_area_struct *vma) { - struct file *realfile = file->private_data; + struct ovl_file *of = file->private_data; struct backing_file_ctx ctx = { .cred = ovl_creds(file_inode(file)->i_sb), .accessed = ovl_file_accessed, }; - return backing_file_mmap(realfile, vma, &ctx); + return backing_file_mmap(of->realfile, vma, &ctx); } static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len) diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 7b7a6e3a43e2..6e32eb9cd1b6 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -863,6 +863,9 @@ int ovl_real_fileattr_set(const struct path *realpath, struct fileattr *fa); int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa); int ovl_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, struct fileattr *fa); +struct ovl_file; +struct ovl_file *ovl_file_alloc(struct file *realfile); +void ovl_file_free(struct ovl_file *of); /* copy_up.c */ int ovl_copy_up(struct dentry *dentry); |