Skip to content

Commit d1d04ef

Browse files
author
Miklos Szeredi
committed
ovl: stack file ops
Implement file operations on a regular overlay file. The underlying file is opened separately and cached in ->private_data. It might be worth making an exception for such files when accounting in nr_file to confirm to userspace expectations. We are only adding a small overhead (248bytes for the struct file) since the real inode and dentry are pinned by overlayfs anyway. This patch doesn't have any effect, since the vfs will use d_real() to find the real underlying file to open. The patch at the end of the series will actually enable this functionality. AV: make it use open_with_fake_path(), don't mess with override_creds SzM: still need to mess with override_creds() until no fs uses current_cred() in their open method. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent e8c985b commit d1d04ef

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

fs/overlayfs/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
obj-$(CONFIG_OVERLAY_FS) += overlay.o
66

7-
overlay-objs := super.o namei.o util.o inode.o dir.o readdir.o copy_up.o \
8-
export.o
7+
overlay-objs := super.o namei.o util.o inode.o file.o dir.o readdir.o \
8+
copy_up.o export.o

fs/overlayfs/file.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (C) 2017 Red Hat, Inc.
3+
*
4+
* This program is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 as published by
6+
* the Free Software Foundation.
7+
*/
8+
9+
#include <linux/cred.h>
10+
#include <linux/file.h>
11+
#include <linux/xattr.h>
12+
#include "overlayfs.h"
13+
14+
static struct file *ovl_open_realfile(const struct file *file)
15+
{
16+
struct inode *inode = file_inode(file);
17+
struct inode *upperinode = ovl_inode_upper(inode);
18+
struct inode *realinode = upperinode ?: ovl_inode_lower(inode);
19+
struct file *realfile;
20+
const struct cred *old_cred;
21+
22+
old_cred = ovl_override_creds(inode->i_sb);
23+
realfile = open_with_fake_path(&file->f_path, file->f_flags | O_NOATIME,
24+
realinode, current_cred());
25+
revert_creds(old_cred);
26+
27+
pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
28+
file, file, upperinode ? 'u' : 'l', file->f_flags,
29+
realfile, IS_ERR(realfile) ? 0 : realfile->f_flags);
30+
31+
return realfile;
32+
}
33+
34+
static int ovl_open(struct inode *inode, struct file *file)
35+
{
36+
struct dentry *dentry = file_dentry(file);
37+
struct file *realfile;
38+
int err;
39+
40+
err = ovl_open_maybe_copy_up(dentry, file->f_flags);
41+
if (err)
42+
return err;
43+
44+
/* No longer need these flags, so don't pass them on to underlying fs */
45+
file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
46+
47+
realfile = ovl_open_realfile(file);
48+
if (IS_ERR(realfile))
49+
return PTR_ERR(realfile);
50+
51+
file->private_data = realfile;
52+
53+
return 0;
54+
}
55+
56+
static int ovl_release(struct inode *inode, struct file *file)
57+
{
58+
fput(file->private_data);
59+
60+
return 0;
61+
}
62+
63+
static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)
64+
{
65+
struct inode *realinode = ovl_inode_real(file_inode(file));
66+
67+
return generic_file_llseek_size(file, offset, whence,
68+
realinode->i_sb->s_maxbytes,
69+
i_size_read(realinode));
70+
}
71+
72+
const struct file_operations ovl_file_operations = {
73+
.open = ovl_open,
74+
.release = ovl_release,
75+
.llseek = ovl_llseek,
76+
};

fs/overlayfs/inode.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev,
535535
switch (mode & S_IFMT) {
536536
case S_IFREG:
537537
inode->i_op = &ovl_file_inode_operations;
538+
inode->i_fop = &ovl_file_operations;
538539
break;
539540

540541
case S_IFDIR:

fs/overlayfs/overlayfs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,9 @@ struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
377377
int ovl_cleanup(struct inode *dir, struct dentry *dentry);
378378
struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr);
379379

380+
/* file.c */
381+
extern const struct file_operations ovl_file_operations;
382+
380383
/* copy_up.c */
381384
int ovl_copy_up(struct dentry *dentry);
382385
int ovl_copy_up_flags(struct dentry *dentry, int flags);

0 commit comments

Comments
 (0)