Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
1b91dbdd
Commit
1b91dbdd
authored
Jul 27, 2016
by
Miklos Szeredi
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'd_real' into overlayfs-next
parents
523d939e
0cac643c
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
80 additions
and
78 deletions
+80
-78
Documentation/filesystems/Locking
Documentation/filesystems/Locking
+3
-2
Documentation/filesystems/vfs.txt
Documentation/filesystems/vfs.txt
+26
-14
fs/dcache.c
fs/dcache.c
+0
-3
fs/namei.c
fs/namei.c
+1
-1
fs/open.c
fs/open.c
+4
-4
fs/overlayfs/inode.c
fs/overlayfs/inode.c
+10
-21
fs/overlayfs/overlayfs.h
fs/overlayfs/overlayfs.h
+1
-1
fs/overlayfs/super.c
fs/overlayfs/super.c
+14
-6
include/linux/dcache.h
include/linux/dcache.h
+20
-20
include/linux/fs.h
include/linux/fs.h
+1
-6
No files found.
Documentation/filesystems/Locking
View file @
1b91dbdd
...
...
@@ -20,6 +20,8 @@ prototypes:
char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
struct vfsmount *(*d_automount)(struct path *path);
int (*d_manage)(struct dentry *, bool);
struct dentry *(*d_real)(struct dentry *, const struct inode *,
unsigned int);
locking rules:
rename_lock ->d_lock may block rcu-walk
...
...
@@ -34,6 +36,7 @@ d_iput: no no yes no
d_dname: no no no no
d_automount: no no yes no
d_manage: no no yes (ref-walk) maybe
d_real no no yes no
--------------------------- inode_operations ---------------------------
prototypes:
...
...
@@ -66,7 +69,6 @@ prototypes:
struct file *, unsigned open_flag,
umode_t create_mode, int *opened);
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
locking rules:
all may block
...
...
@@ -95,7 +97,6 @@ fiemap: no
update_time: no
atomic_open: yes
tmpfile: no
dentry_open: no
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim.
...
...
Documentation/filesystems/vfs.txt
View file @
1b91dbdd
...
...
@@ -364,7 +364,6 @@ struct inode_operations {
int (*atomic_open)(struct inode *, struct dentry *, struct file *,
unsigned open_flag, umode_t create_mode, int *opened);
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
};
Again, all methods are called without any locks being held, unless
...
...
@@ -696,13 +695,6 @@ struct address_space_operations {
but instead uses bmap to find out where the blocks in the file
are and uses those addresses directly.
dentry_open: *WARNING: probably going away soon, do not use!* This is an
alternative to f_op->open(), the difference is that this method may open
a file not necessarily originating from the same filesystem as the one
i_op->open() was called on. It may be useful for stacking filesystems
which want to allow native I/O directly on underlying files.
invalidatepage: If a page has PagePrivate set, then invalidatepage
will be called when part or all of the page is to be removed
from the address space. This generally corresponds to either a
...
...
@@ -938,6 +930,8 @@ struct dentry_operations {
char *(*d_dname)(struct dentry *, char *, int);
struct vfsmount *(*d_automount)(struct path *);
int (*d_manage)(struct dentry *, bool);
struct dentry *(*d_real)(struct dentry *, const struct inode *,
unsigned int);
};
d_revalidate: called when the VFS needs to revalidate a dentry. This
...
...
@@ -1022,6 +1016,14 @@ struct dentry_operations {
at the end of the buffer, and returns a pointer to the first char.
dynamic_dname() helper function is provided to take care of this.
Example :
static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen)
{
return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]",
dentry->d_inode->i_ino);
}
d_automount: called when an automount dentry is to be traversed (optional).
This should create a new VFS mount record and return the record to the
caller. The caller is supplied with a path parameter giving the
...
...
@@ -1060,13 +1062,23 @@ struct dentry_operations {
This function is only used if DCACHE_MANAGE_TRANSIT is set on the
dentry being transited from.
Example :
d_real: overlay/union type filesystems implement this method to return one of
the underlying dentries hidden by the overlay. It is used in three
different modes:
static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen)
{
return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]",
dentry->d_inode->i_ino);
}
Called from open it may need to copy-up the file depending on the
supplied open flags. This mode is selected with a non-zero flags
argument. In this mode the d_real method can return an error.
Called from file_dentry() it returns the real dentry matching the inode
argument. The real dentry may be from a lower layer already copied up,
but still referenced from the file. This mode is selected with a
non-NULL inode argument. This will always succeed.
With NULL inode and zero flags the topmost real underlying dentry is
returned. This will always succeed.
This method is never called with both non-NULL inode and non-zero flags.
Each dentry has a pointer to its parent dentry, as well as a hash list
of child dentries. Child dentries are basically like files in a
...
...
fs/dcache.c
View file @
1b91dbdd
...
...
@@ -1729,7 +1729,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
DCACHE_OP_REVALIDATE
|
DCACHE_OP_WEAK_REVALIDATE
|
DCACHE_OP_DELETE
|
DCACHE_OP_SELECT_INODE
|
DCACHE_OP_REAL
));
dentry
->
d_op
=
op
;
if
(
!
op
)
...
...
@@ -1746,8 +1745,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
dentry
->
d_flags
|=
DCACHE_OP_DELETE
;
if
(
op
->
d_prune
)
dentry
->
d_flags
|=
DCACHE_OP_PRUNE
;
if
(
op
->
d_select_inode
)
dentry
->
d_flags
|=
DCACHE_OP_SELECT_INODE
;
if
(
op
->
d_real
)
dentry
->
d_flags
|=
DCACHE_OP_REAL
;
...
...
fs/namei.c
View file @
1b91dbdd
...
...
@@ -4328,7 +4328,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
* Check source == target.
* On overlayfs need to look at underlying inodes.
*/
if
(
vfs_select_inode
(
old_dentry
,
0
)
==
vfs_select_inode
(
new_dentry
,
0
))
if
(
d_real_inode
(
old_dentry
)
==
d_real_inode
(
new_dentry
))
return
0
;
error
=
may_delete
(
old_dir
,
old_dentry
,
is_dir
);
...
...
fs/open.c
View file @
1b91dbdd
...
...
@@ -840,13 +840,13 @@ EXPORT_SYMBOL(file_path);
int
vfs_open
(
const
struct
path
*
path
,
struct
file
*
file
,
const
struct
cred
*
cred
)
{
struct
inode
*
inode
=
vfs_select_inode
(
path
->
dentry
,
file
->
f_flags
);
struct
dentry
*
dentry
=
d_real
(
path
->
dentry
,
NULL
,
file
->
f_flags
);
if
(
IS_ERR
(
inode
))
return
PTR_ERR
(
inode
);
if
(
IS_ERR
(
dentry
))
return
PTR_ERR
(
dentry
);
file
->
f_path
=
*
path
;
return
do_dentry_open
(
file
,
inode
,
NULL
,
cred
);
return
do_dentry_open
(
file
,
d_backing_inode
(
dentry
)
,
NULL
,
cred
);
}
struct
file
*
dentry_open
(
const
struct
path
*
path
,
int
flags
,
...
...
fs/overlayfs/inode.c
View file @
1b91dbdd
...
...
@@ -351,36 +351,25 @@ static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
return
true
;
}
struct
inode
*
ovl_d_select_inode
(
struct
dentry
*
dentry
,
unsigned
file_flags
)
int
ovl_open_maybe_copy_up
(
struct
dentry
*
dentry
,
unsigned
int
file_flags
)
{
int
err
;
int
err
=
0
;
struct
path
realpath
;
enum
ovl_path_type
type
;
if
(
d_is_dir
(
dentry
))
return
d_backing_inode
(
dentry
);
type
=
ovl_path_real
(
dentry
,
&
realpath
);
if
(
ovl_open_need_copy_up
(
file_flags
,
type
,
realpath
.
dentry
))
{
err
=
ovl_want_write
(
dentry
);
if
(
err
)
return
ERR_PTR
(
err
);
if
(
!
err
)
{
if
(
file_flags
&
O_TRUNC
)
err
=
ovl_copy_up_truncate
(
dentry
);
else
err
=
ovl_copy_up
(
dentry
);
ovl_drop_write
(
dentry
);
if
(
err
)
return
ERR_PTR
(
err
);
ovl_path_upper
(
dentry
,
&
realpath
);
}
}
if
(
realpath
.
dentry
->
d_flags
&
DCACHE_OP_SELECT_INODE
)
return
realpath
.
dentry
->
d_op
->
d_select_inode
(
realpath
.
dentry
,
file_flags
);
return
d_backing_inode
(
realpath
.
dentry
);
return
err
;
}
static
const
struct
inode_operations
ovl_file_inode_operations
=
{
...
...
fs/overlayfs/overlayfs.h
View file @
1b91dbdd
...
...
@@ -179,7 +179,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
const
char
*
name
,
void
*
value
,
size_t
size
);
ssize_t
ovl_listxattr
(
struct
dentry
*
dentry
,
char
*
list
,
size_t
size
);
int
ovl_removexattr
(
struct
dentry
*
dentry
,
const
char
*
name
);
struct
inode
*
ovl_d_select_inode
(
struct
dentry
*
dentry
,
unsigned
file_flags
);
int
ovl_open_maybe_copy_up
(
struct
dentry
*
dentry
,
unsigned
int
file_flags
);
struct
inode
*
ovl_new_inode
(
struct
super_block
*
sb
,
umode_t
mode
,
struct
ovl_entry
*
oe
);
...
...
fs/overlayfs/super.c
View file @
1b91dbdd
...
...
@@ -304,7 +304,9 @@ static void ovl_dentry_release(struct dentry *dentry)
}
}
static
struct
dentry
*
ovl_d_real
(
struct
dentry
*
dentry
,
struct
inode
*
inode
)
static
struct
dentry
*
ovl_d_real
(
struct
dentry
*
dentry
,
const
struct
inode
*
inode
,
unsigned
int
open_flags
)
{
struct
dentry
*
real
;
...
...
@@ -314,6 +316,16 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
goto
bug
;
}
if
(
d_is_negative
(
dentry
))
return
dentry
;
if
(
open_flags
)
{
int
err
=
ovl_open_maybe_copy_up
(
dentry
,
open_flags
);
if
(
err
)
return
ERR_PTR
(
err
);
}
real
=
ovl_dentry_upper
(
dentry
);
if
(
real
&&
(
!
inode
||
inode
==
d_inode
(
real
)))
return
real
;
...
...
@@ -326,9 +338,7 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
return
real
;
/* Handle recursion */
if
(
real
->
d_flags
&
DCACHE_OP_REAL
)
return
real
->
d_op
->
d_real
(
real
,
inode
);
return
d_real
(
real
,
inode
,
open_flags
);
bug:
WARN
(
1
,
"ovl_d_real(%pd4, %s:%lu
\n
): real dentry not found
\n
"
,
dentry
,
inode
?
inode
->
i_sb
->
s_id
:
"NULL"
,
inode
?
inode
->
i_ino
:
0
);
...
...
@@ -378,13 +388,11 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
static
const
struct
dentry_operations
ovl_dentry_operations
=
{
.
d_release
=
ovl_dentry_release
,
.
d_select_inode
=
ovl_d_select_inode
,
.
d_real
=
ovl_d_real
,
};
static
const
struct
dentry_operations
ovl_reval_dentry_operations
=
{
.
d_release
=
ovl_dentry_release
,
.
d_select_inode
=
ovl_d_select_inode
,
.
d_real
=
ovl_d_real
,
.
d_revalidate
=
ovl_dentry_revalidate
,
.
d_weak_revalidate
=
ovl_dentry_weak_revalidate
,
...
...
include/linux/dcache.h
View file @
1b91dbdd
...
...
@@ -139,8 +139,8 @@ struct dentry_operations {
char
*
(
*
d_dname
)(
struct
dentry
*
,
char
*
,
int
);
struct
vfsmount
*
(
*
d_automount
)(
struct
path
*
);
int
(
*
d_manage
)(
struct
dentry
*
,
bool
);
struct
inode
*
(
*
d_select_inode
)(
struct
dentry
*
,
unsigned
);
struct
dentry
*
(
*
d_real
)(
struct
dentry
*
,
struct
inode
*
);
struct
dentry
*
(
*
d_real
)(
struct
dentry
*
,
const
struct
inode
*
,
unsigned
int
);
}
____cacheline_aligned
;
/*
...
...
@@ -206,10 +206,8 @@ struct dentry_operations {
#define DCACHE_MAY_FREE 0x00800000
#define DCACHE_FALLTHRU 0x01000000
/* Fall through to lower layer */
#define DCACHE_OP_SELECT_INODE 0x02000000
/* Unioned entry: dcache op selects inode */
#define DCACHE_ENCRYPTED_WITH_KEY 0x04000000
/* dir is encrypted with a valid key */
#define DCACHE_OP_REAL 0x08000000
#define DCACHE_ENCRYPTED_WITH_KEY 0x02000000
/* dir is encrypted with a valid key */
#define DCACHE_OP_REAL 0x04000000
#define DCACHE_PAR_LOOKUP 0x10000000
/* being looked up (with parent locked shared) */
#define DCACHE_DENTRY_CURSOR 0x20000000
...
...
@@ -557,25 +555,27 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper)
return
upper
;
}
static
inline
struct
dentry
*
d_real
(
struct
dentry
*
dentry
)
/**
* d_real - Return the real dentry
* @dentry: the dentry to query
* @inode: inode to select the dentry from multiple layers (can be NULL)
* @flags: open flags to control copy-up behavior
*
* If dentry is on an union/overlay, then return the underlying, real dentry.
* Otherwise return the dentry itself.
*
* See also: Documentation/filesystems/vfs.txt
*/
static
inline
struct
dentry
*
d_real
(
struct
dentry
*
dentry
,
const
struct
inode
*
inode
,
unsigned
int
flags
)
{
if
(
unlikely
(
dentry
->
d_flags
&
DCACHE_OP_REAL
))
return
dentry
->
d_op
->
d_real
(
dentry
,
NULL
);
return
dentry
->
d_op
->
d_real
(
dentry
,
inode
,
flags
);
else
return
dentry
;
}
static
inline
struct
inode
*
vfs_select_inode
(
struct
dentry
*
dentry
,
unsigned
open_flags
)
{
struct
inode
*
inode
=
d_inode
(
dentry
);
if
(
inode
&&
unlikely
(
dentry
->
d_flags
&
DCACHE_OP_SELECT_INODE
))
inode
=
dentry
->
d_op
->
d_select_inode
(
dentry
,
open_flags
);
return
inode
;
}
/**
* d_real_inode - Return the real inode
* @dentry: The dentry to query
...
...
@@ -585,7 +585,7 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry,
*/
static
inline
struct
inode
*
d_real_inode
(
struct
dentry
*
dentry
)
{
return
d_backing_inode
(
d_real
(
dentry
));
return
d_backing_inode
(
d_real
(
dentry
,
NULL
,
0
));
}
...
...
include/linux/fs.h
View file @
1b91dbdd
...
...
@@ -1272,12 +1272,7 @@ static inline struct inode *file_inode(const struct file *f)
static
inline
struct
dentry
*
file_dentry
(
const
struct
file
*
file
)
{
struct
dentry
*
dentry
=
file
->
f_path
.
dentry
;
if
(
unlikely
(
dentry
->
d_flags
&
DCACHE_OP_REAL
))
return
dentry
->
d_op
->
d_real
(
dentry
,
file_inode
(
file
));
else
return
dentry
;
return
d_real
(
file
->
f_path
.
dentry
,
file_inode
(
file
),
0
);
}
static
inline
int
locks_lock_file_wait
(
struct
file
*
filp
,
struct
file_lock
*
fl
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment