Skip to content

Commit

Permalink
vfs: add prepend_path() helper
Browse files Browse the repository at this point in the history
Split off prepend_path() from __d_path().  This new helper takes an
end-of-buffer pointer and buffer-length pointer just like the other
prepend_* functions.  Move the " (deleted)" postfix out to __d_path().

This patch doesn't change any functionality but paves the way for the
following patches.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Miklos Szeredi authored and Al Viro committed Aug 11, 2010
1 parent 98dc568 commit f2eb657
Showing 1 changed file with 58 additions and 36 deletions.
94 changes: 58 additions & 36 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1905,48 +1905,30 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name)
}

/**
* __d_path - return the path of a dentry
* Prepend path string to a buffer
*
* @path: the dentry/vfsmount to report
* @root: root vfsmnt/dentry (may be modified by this function)
* @buffer: buffer to return value in
* @buflen: buffer length
*
* Convert a dentry into an ASCII path name. If the entry has been deleted
* the string " (deleted)" is appended. Note that this is ambiguous.
*
* Returns a pointer into the buffer or an error code if the
* path was too long.
* @buffer: pointer to the end of the buffer
* @buflen: pointer to buffer length
*
* "buflen" should be positive. Caller holds the dcache_lock.
* Caller holds the dcache_lock.
*
* If path is not reachable from the supplied root, then the value of
* root is changed (without modifying refcounts).
*/
char *__d_path(const struct path *path, struct path *root,
char *buffer, int buflen)
static int prepend_path(const struct path *path, struct path *root,
char **buffer, int *buflen)
{
struct dentry *dentry = path->dentry;
struct vfsmount *vfsmnt = path->mnt;
char *end = buffer + buflen;
char *retval;
bool slash = false;
int error = 0;

spin_lock(&vfsmount_lock);
prepend(&end, &buflen, "\0", 1);
if (d_unlinked(dentry) &&
(prepend(&end, &buflen, " (deleted)", 10) != 0))
goto Elong;

if (buflen < 1)
goto Elong;
/* Get '/' right */
retval = end-1;
*retval = '/';

for (;;) {
while (dentry != root->dentry || vfsmnt != root->mnt) {
struct dentry * parent;

if (dentry == root->dentry && vfsmnt == root->mnt)
break;
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
/* Global root? */
if (vfsmnt->mnt_parent == vfsmnt) {
Expand All @@ -1958,16 +1940,22 @@ char *__d_path(const struct path *path, struct path *root,
}
parent = dentry->d_parent;
prefetch(parent);
if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
(prepend(&end, &buflen, "/", 1) != 0))
goto Elong;
retval = end;
error = prepend_name(buffer, buflen, &dentry->d_name);
if (!error)
error = prepend(buffer, buflen, "/", 1);
if (error)
break;

slash = true;
dentry = parent;
}

out:
if (!error && !slash)
error = prepend(buffer, buflen, "/", 1);

spin_unlock(&vfsmount_lock);
return retval;
return error;

global_root:
/*
Expand All @@ -1982,10 +1970,44 @@ char *__d_path(const struct path *path, struct path *root,
root->mnt = vfsmnt;
root->dentry = dentry;
goto out;
}

Elong:
retval = ERR_PTR(-ENAMETOOLONG);
goto out;
/**
* __d_path - return the path of a dentry
* @path: the dentry/vfsmount to report
* @root: root vfsmnt/dentry (may be modified by this function)
* @buffer: buffer to return value in
* @buflen: buffer length
*
* Convert a dentry into an ASCII path name. If the entry has been deleted
* the string " (deleted)" is appended. Note that this is ambiguous.
*
* Returns a pointer into the buffer or an error code if the
* path was too long.
*
* "buflen" should be positive. Caller holds the dcache_lock.
*
* If path is not reachable from the supplied root, then the value of
* root is changed (without modifying refcounts).
*/
char *__d_path(const struct path *path, struct path *root,
char *buf, int buflen)
{
char *res = buf + buflen;
int error;

prepend(&res, &buflen, "\0", 1);
if (d_unlinked(path->dentry)) {
error = prepend(&res, &buflen, " (deleted)", 10);
if (error)
return ERR_PTR(error);
}

error = prepend_path(path, root, &res, &buflen);
if (error)
return ERR_PTR(error);

return res;
}

/**
Expand Down

0 comments on commit f2eb657

Please sign in to comment.