Skip to content

Commit

Permalink
[PATCH] get stack footprint of pathname resolution back to relative s…
Browse files Browse the repository at this point in the history
…anity

Somebody had put struct nameidata in stack frame of link_path_walk().
Unfortunately, there are certain realities to deal with:
	* It's in the middle of recursion.  Depth is equal to the nesting
depth of symlinks, i.e. up to 8.
	* struct namiedata is, even if one discards the intent junk,
at least 12 pointers + 5 ints.
	* moreover, adding a stack frame is not free in that situation.
	* there are fs methods called on top of that, and they also have
stack footprint.
	* kernel stack is not infinite.

The thing is, even if one chooses to deal with -ESTALE that way (and it's
one hell of an overkill), the only thing that needs to be preserved is
vfsmount + dentry, not the entire struct nameidata.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Mar 19, 2008
1 parent b4d232e commit a02f76c
Showing 1 changed file with 32 additions and 31 deletions.
63 changes: 32 additions & 31 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
* any extra contention...
*/

static int link_path_walk(const char *name, struct nameidata *nd);
static int __link_path_walk(const char *name, struct nameidata *nd);

/* In order to reduce some races, while at the same time doing additional
* checking and hopefully speeding things up, we copy filenames to the
Expand Down Expand Up @@ -563,6 +563,37 @@ walk_init_root(const char *name, struct nameidata *nd)
return 1;
}

/*
* Wrapper to retry pathname resolution whenever the underlying
* file system returns an ESTALE.
*
* Retry the whole path once, forcing real lookup requests
* instead of relying on the dcache.
*/
static __always_inline int link_path_walk(const char *name, struct nameidata *nd)
{
struct path save = nd->path;
int result;

/* make sure the stuff we saved doesn't go away */
dget(save.dentry);
mntget(save.mnt);

result = __link_path_walk(name, nd);
if (result == -ESTALE) {
/* nd->path had been dropped */
nd->path = save;
dget(nd->path.dentry);
mntget(nd->path.mnt);
nd->flags |= LOOKUP_REVAL;
result = __link_path_walk(name, nd);
}

path_put(&save);

return result;
}

static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
{
int res = 0;
Expand Down Expand Up @@ -1020,36 +1051,6 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
return err;
}

/*
* Wrapper to retry pathname resolution whenever the underlying
* file system returns an ESTALE.
*
* Retry the whole path once, forcing real lookup requests
* instead of relying on the dcache.
*/
static int link_path_walk(const char *name, struct nameidata *nd)
{
struct nameidata save = *nd;
int result;

/* make sure the stuff we saved doesn't go away */
dget(save.path.dentry);
mntget(save.path.mnt);

result = __link_path_walk(name, nd);
if (result == -ESTALE) {
*nd = save;
dget(nd->path.dentry);
mntget(nd->path.mnt);
nd->flags |= LOOKUP_REVAL;
result = __link_path_walk(name, nd);
}

path_put(&save.path);

return result;
}

static int path_walk(const char *name, struct nameidata *nd)
{
current->total_link_count = 0;
Expand Down

0 comments on commit a02f76c

Please sign in to comment.