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
Kirill Smelkov
linux
Commits
254cf582
Commit
254cf582
authored
May 05, 2015
by
Al Viro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
namei: don't mangle nd->seq in lookup_fast()
Signed-off-by:
Al Viro
<
viro@zeniv.linux.org.uk
>
parent
6e9918b7
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
23 additions
and
15 deletions
+23
-15
fs/namei.c
fs/namei.c
+23
-15
No files found.
fs/namei.c
View file @
254cf582
...
@@ -1134,7 +1134,7 @@ static inline int managed_dentry_rcu(struct dentry *dentry)
...
@@ -1134,7 +1134,7 @@ static inline int managed_dentry_rcu(struct dentry *dentry)
* we meet a managed dentry that would need blocking.
* we meet a managed dentry that would need blocking.
*/
*/
static
bool
__follow_mount_rcu
(
struct
nameidata
*
nd
,
struct
path
*
path
,
static
bool
__follow_mount_rcu
(
struct
nameidata
*
nd
,
struct
path
*
path
,
struct
inode
**
inode
)
struct
inode
**
inode
,
unsigned
*
seqp
)
{
{
for
(;;)
{
for
(;;)
{
struct
mount
*
mounted
;
struct
mount
*
mounted
;
...
@@ -1161,7 +1161,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
...
@@ -1161,7 +1161,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
path
->
mnt
=
&
mounted
->
mnt
;
path
->
mnt
=
&
mounted
->
mnt
;
path
->
dentry
=
mounted
->
mnt
.
mnt_root
;
path
->
dentry
=
mounted
->
mnt
.
mnt_root
;
nd
->
flags
|=
LOOKUP_JUMPED
;
nd
->
flags
|=
LOOKUP_JUMPED
;
nd
->
seq
=
read_seqcount_begin
(
&
path
->
dentry
->
d_seq
);
*
seqp
=
read_seqcount_begin
(
&
path
->
dentry
->
d_seq
);
/*
/*
* Update the inode too. We don't need to re-check the
* Update the inode too. We don't need to re-check the
* dentry sequence number here after this d_inode read,
* dentry sequence number here after this d_inode read,
...
@@ -1397,7 +1397,8 @@ static struct dentry *__lookup_hash(struct qstr *name,
...
@@ -1397,7 +1397,8 @@ static struct dentry *__lookup_hash(struct qstr *name,
* It _is_ time-critical.
* It _is_ time-critical.
*/
*/
static
int
lookup_fast
(
struct
nameidata
*
nd
,
static
int
lookup_fast
(
struct
nameidata
*
nd
,
struct
path
*
path
,
struct
inode
**
inode
)
struct
path
*
path
,
struct
inode
**
inode
,
unsigned
*
seqp
)
{
{
struct
vfsmount
*
mnt
=
nd
->
path
.
mnt
;
struct
vfsmount
*
mnt
=
nd
->
path
.
mnt
;
struct
dentry
*
dentry
,
*
parent
=
nd
->
path
.
dentry
;
struct
dentry
*
dentry
,
*
parent
=
nd
->
path
.
dentry
;
...
@@ -1437,8 +1438,8 @@ static int lookup_fast(struct nameidata *nd,
...
@@ -1437,8 +1438,8 @@ static int lookup_fast(struct nameidata *nd,
*/
*/
if
(
__read_seqcount_retry
(
&
parent
->
d_seq
,
nd
->
seq
))
if
(
__read_seqcount_retry
(
&
parent
->
d_seq
,
nd
->
seq
))
return
-
ECHILD
;
return
-
ECHILD
;
nd
->
seq
=
seq
;
*
seqp
=
seq
;
if
(
unlikely
(
dentry
->
d_flags
&
DCACHE_OP_REVALIDATE
))
{
if
(
unlikely
(
dentry
->
d_flags
&
DCACHE_OP_REVALIDATE
))
{
status
=
d_revalidate
(
dentry
,
nd
->
flags
);
status
=
d_revalidate
(
dentry
,
nd
->
flags
);
if
(
unlikely
(
status
<=
0
))
{
if
(
unlikely
(
status
<=
0
))
{
...
@@ -1449,10 +1450,10 @@ static int lookup_fast(struct nameidata *nd,
...
@@ -1449,10 +1450,10 @@ static int lookup_fast(struct nameidata *nd,
}
}
path
->
mnt
=
mnt
;
path
->
mnt
=
mnt
;
path
->
dentry
=
dentry
;
path
->
dentry
=
dentry
;
if
(
likely
(
__follow_mount_rcu
(
nd
,
path
,
inode
)))
if
(
likely
(
__follow_mount_rcu
(
nd
,
path
,
inode
,
seqp
)))
return
0
;
return
0
;
unlazy:
unlazy:
if
(
unlazy_walk
(
nd
,
dentry
,
nd
->
seq
))
if
(
unlazy_walk
(
nd
,
dentry
,
seq
))
return
-
ECHILD
;
return
-
ECHILD
;
}
else
{
}
else
{
dentry
=
__d_lookup
(
parent
,
&
nd
->
last
);
dentry
=
__d_lookup
(
parent
,
&
nd
->
last
);
...
@@ -1543,7 +1544,7 @@ static void terminate_walk(struct nameidata *nd)
...
@@ -1543,7 +1544,7 @@ static void terminate_walk(struct nameidata *nd)
put_link
(
nd
);
put_link
(
nd
);
}
}
static
int
pick_link
(
struct
nameidata
*
nd
,
struct
path
*
link
)
static
int
pick_link
(
struct
nameidata
*
nd
,
struct
path
*
link
,
unsigned
seq
)
{
{
int
error
;
int
error
;
struct
saved
*
last
;
struct
saved
*
last
;
...
@@ -1553,7 +1554,7 @@ static int pick_link(struct nameidata *nd, struct path *link)
...
@@ -1553,7 +1554,7 @@ static int pick_link(struct nameidata *nd, struct path *link)
}
}
if
(
nd
->
flags
&
LOOKUP_RCU
)
{
if
(
nd
->
flags
&
LOOKUP_RCU
)
{
if
(
unlikely
(
nd
->
path
.
mnt
!=
link
->
mnt
||
if
(
unlikely
(
nd
->
path
.
mnt
!=
link
->
mnt
||
unlazy_walk
(
nd
,
link
->
dentry
,
nd
->
seq
)))
{
unlazy_walk
(
nd
,
link
->
dentry
,
seq
)))
{
return
-
ECHILD
;
return
-
ECHILD
;
}
}
}
}
...
@@ -1577,13 +1578,14 @@ static int pick_link(struct nameidata *nd, struct path *link)
...
@@ -1577,13 +1578,14 @@ static int pick_link(struct nameidata *nd, struct path *link)
* so we keep a cache of "no, this doesn't need follow_link"
* so we keep a cache of "no, this doesn't need follow_link"
* for the common case.
* for the common case.
*/
*/
static
inline
int
should_follow_link
(
struct
nameidata
*
nd
,
struct
path
*
link
,
int
follow
)
static
inline
int
should_follow_link
(
struct
nameidata
*
nd
,
struct
path
*
link
,
int
follow
,
unsigned
seq
)
{
{
if
(
likely
(
!
d_is_symlink
(
link
->
dentry
)))
if
(
likely
(
!
d_is_symlink
(
link
->
dentry
)))
return
0
;
return
0
;
if
(
!
follow
)
if
(
!
follow
)
return
0
;
return
0
;
return
pick_link
(
nd
,
link
);
return
pick_link
(
nd
,
link
,
seq
);
}
}
enum
{
WALK_GET
=
1
,
WALK_PUT
=
2
};
enum
{
WALK_GET
=
1
,
WALK_PUT
=
2
};
...
@@ -1592,6 +1594,7 @@ static int walk_component(struct nameidata *nd, int flags)
...
@@ -1592,6 +1594,7 @@ static int walk_component(struct nameidata *nd, int flags)
{
{
struct
path
path
;
struct
path
path
;
struct
inode
*
inode
;
struct
inode
*
inode
;
unsigned
seq
;
int
err
;
int
err
;
/*
/*
* "." and ".." are special - ".." especially so because it has
* "." and ".." are special - ".." especially so because it has
...
@@ -1604,7 +1607,7 @@ static int walk_component(struct nameidata *nd, int flags)
...
@@ -1604,7 +1607,7 @@ static int walk_component(struct nameidata *nd, int flags)
put_link
(
nd
);
put_link
(
nd
);
return
err
;
return
err
;
}
}
err
=
lookup_fast
(
nd
,
&
path
,
&
inode
);
err
=
lookup_fast
(
nd
,
&
path
,
&
inode
,
&
seq
);
if
(
unlikely
(
err
))
{
if
(
unlikely
(
err
))
{
if
(
err
<
0
)
if
(
err
<
0
)
return
err
;
return
err
;
...
@@ -1614,6 +1617,7 @@ static int walk_component(struct nameidata *nd, int flags)
...
@@ -1614,6 +1617,7 @@ static int walk_component(struct nameidata *nd, int flags)
return
err
;
return
err
;
inode
=
path
.
dentry
->
d_inode
;
inode
=
path
.
dentry
->
d_inode
;
seq
=
0
;
/* we are already out of RCU mode */
err
=
-
ENOENT
;
err
=
-
ENOENT
;
if
(
d_is_negative
(
path
.
dentry
))
if
(
d_is_negative
(
path
.
dentry
))
goto
out_path_put
;
goto
out_path_put
;
...
@@ -1621,11 +1625,12 @@ static int walk_component(struct nameidata *nd, int flags)
...
@@ -1621,11 +1625,12 @@ static int walk_component(struct nameidata *nd, int flags)
if
(
flags
&
WALK_PUT
)
if
(
flags
&
WALK_PUT
)
put_link
(
nd
);
put_link
(
nd
);
err
=
should_follow_link
(
nd
,
&
path
,
flags
&
WALK_GET
);
err
=
should_follow_link
(
nd
,
&
path
,
flags
&
WALK_GET
,
seq
);
if
(
unlikely
(
err
))
if
(
unlikely
(
err
))
return
err
;
return
err
;
path_to_nameidata
(
&
path
,
nd
);
path_to_nameidata
(
&
path
,
nd
);
nd
->
inode
=
inode
;
nd
->
inode
=
inode
;
nd
->
seq
=
seq
;
return
0
;
return
0
;
out_path_put:
out_path_put:
...
@@ -2342,7 +2347,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
...
@@ -2342,7 +2347,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
put_link
(
nd
);
put_link
(
nd
);
path
->
dentry
=
dentry
;
path
->
dentry
=
dentry
;
path
->
mnt
=
nd
->
path
.
mnt
;
path
->
mnt
=
nd
->
path
.
mnt
;
error
=
should_follow_link
(
nd
,
path
,
nd
->
flags
&
LOOKUP_FOLLOW
);
error
=
should_follow_link
(
nd
,
path
,
nd
->
flags
&
LOOKUP_FOLLOW
,
0
);
if
(
unlikely
(
error
))
if
(
unlikely
(
error
))
return
error
;
return
error
;
mntget
(
path
->
mnt
);
mntget
(
path
->
mnt
);
...
@@ -2939,6 +2944,7 @@ static int do_last(struct nameidata *nd,
...
@@ -2939,6 +2944,7 @@ static int do_last(struct nameidata *nd,
bool
will_truncate
=
(
open_flag
&
O_TRUNC
)
!=
0
;
bool
will_truncate
=
(
open_flag
&
O_TRUNC
)
!=
0
;
bool
got_write
=
false
;
bool
got_write
=
false
;
int
acc_mode
=
op
->
acc_mode
;
int
acc_mode
=
op
->
acc_mode
;
unsigned
seq
;
struct
inode
*
inode
;
struct
inode
*
inode
;
struct
path
save_parent
=
{
.
dentry
=
NULL
,
.
mnt
=
NULL
};
struct
path
save_parent
=
{
.
dentry
=
NULL
,
.
mnt
=
NULL
};
struct
path
path
;
struct
path
path
;
...
@@ -2959,7 +2965,7 @@ static int do_last(struct nameidata *nd,
...
@@ -2959,7 +2965,7 @@ static int do_last(struct nameidata *nd,
if
(
nd
->
last
.
name
[
nd
->
last
.
len
])
if
(
nd
->
last
.
name
[
nd
->
last
.
len
])
nd
->
flags
|=
LOOKUP_FOLLOW
|
LOOKUP_DIRECTORY
;
nd
->
flags
|=
LOOKUP_FOLLOW
|
LOOKUP_DIRECTORY
;
/* we _can_ be in RCU mode here */
/* we _can_ be in RCU mode here */
error
=
lookup_fast
(
nd
,
&
path
,
&
inode
);
error
=
lookup_fast
(
nd
,
&
path
,
&
inode
,
&
seq
);
if
(
likely
(
!
error
))
if
(
likely
(
!
error
))
goto
finish_lookup
;
goto
finish_lookup
;
...
@@ -3047,6 +3053,7 @@ static int do_last(struct nameidata *nd,
...
@@ -3047,6 +3053,7 @@ static int do_last(struct nameidata *nd,
BUG_ON
(
nd
->
flags
&
LOOKUP_RCU
);
BUG_ON
(
nd
->
flags
&
LOOKUP_RCU
);
inode
=
path
.
dentry
->
d_inode
;
inode
=
path
.
dentry
->
d_inode
;
seq
=
0
;
/* out of RCU mode, so the value doesn't matter */
if
(
unlikely
(
d_is_negative
(
path
.
dentry
)))
{
if
(
unlikely
(
d_is_negative
(
path
.
dentry
)))
{
path_to_nameidata
(
&
path
,
nd
);
path_to_nameidata
(
&
path
,
nd
);
return
-
ENOENT
;
return
-
ENOENT
;
...
@@ -3054,7 +3061,7 @@ static int do_last(struct nameidata *nd,
...
@@ -3054,7 +3061,7 @@ static int do_last(struct nameidata *nd,
finish_lookup:
finish_lookup:
if
(
nd
->
depth
)
if
(
nd
->
depth
)
put_link
(
nd
);
put_link
(
nd
);
error
=
should_follow_link
(
nd
,
&
path
,
nd
->
flags
&
LOOKUP_FOLLOW
);
error
=
should_follow_link
(
nd
,
&
path
,
nd
->
flags
&
LOOKUP_FOLLOW
,
seq
);
if
(
unlikely
(
error
))
if
(
unlikely
(
error
))
return
error
;
return
error
;
...
@@ -3072,6 +3079,7 @@ static int do_last(struct nameidata *nd,
...
@@ -3072,6 +3079,7 @@ static int do_last(struct nameidata *nd,
}
}
nd
->
inode
=
inode
;
nd
->
inode
=
inode
;
nd
->
seq
=
seq
;
/* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
/* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
finish_open:
finish_open:
error
=
complete_walk
(
nd
);
error
=
complete_walk
(
nd
);
...
...
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