summaryrefslogtreecommitdiff
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2020-03-03 19:22:34 +0300
committerAl Viro <viro@zeniv.linux.org.uk>2020-04-02 08:09:25 +0300
commit49055906af51b59d50a34b18820f85cc7d085218 (patch)
treed024f1b9c5557247d16a06a686c1faa5d40644a0 /fs/namei.c
parentaef9404d8cc3a5730dea74d05e9cb2e4c2b4a511 (diff)
downloadlinux-49055906af51b59d50a34b18820f85cc7d085218.tar.xz
pick_link(): take reserving space on stack into a new helper
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c46
1 files changed, 25 insertions, 21 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 1f3d3981fe02..6025406e01e5 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1580,6 +1580,28 @@ static inline int may_lookup(struct nameidata *nd)
return inode_permission(nd->inode, MAY_EXEC);
}
+static int reserve_stack(struct nameidata *nd, struct path *link, unsigned seq)
+{
+ int error;
+
+ if (unlikely(nd->total_link_count++ >= MAXSYMLINKS))
+ return -ELOOP;
+ error = nd_alloc_stack(nd);
+ if (likely(!error))
+ return 0;
+ if (error == -ECHILD) {
+ // we must grab link first
+ bool grabbed_link = legitimize_path(nd, link, seq);
+ // ... and we must unlazy to be able to clean up
+ error = unlazy_walk(nd);
+ if (unlikely(!grabbed_link))
+ error = -ECHILD;
+ if (!error)
+ error = nd_alloc_stack(nd);
+ }
+ return error;
+}
+
enum {WALK_TRAILING = 1, WALK_MORE = 2, WALK_NOFOLLOW = 4};
static const char *pick_link(struct nameidata *nd, struct path *link,
@@ -1587,31 +1609,13 @@ static const char *pick_link(struct nameidata *nd, struct path *link,
{
struct saved *last;
const char *res;
- int error;
+ int error = reserve_stack(nd, link, seq);
- if (unlikely(nd->total_link_count++ >= MAXSYMLINKS)) {
- if (!(nd->flags & LOOKUP_RCU))
- path_put(link);
- return ERR_PTR(-ELOOP);
- }
- error = nd_alloc_stack(nd);
if (unlikely(error)) {
- if (error == -ECHILD) {
- // we must grab link first
- bool grabbed_link = legitimize_path(nd, link, seq);
- // ... and we must unlazy to be able to clean up
- error = unlazy_walk(nd);
- if (unlikely(!grabbed_link))
- error = -ECHILD;
- if (!error)
- error = nd_alloc_stack(nd);
- }
- if (error) {
+ if (!(nd->flags & LOOKUP_RCU))
path_put(link);
- return ERR_PTR(error);
- }
+ return ERR_PTR(error);
}
-
last = nd->stack + nd->depth++;
last->link = *link;
clear_delayed_call(&last->done);