[patch 2/7] vfs: mountinfo: add seq_file_root()
Add a new function: seq_file_root() This is similar to seq_path(), but calculates the path relative to the given root, instead of current->fs->root. If the path was unreachable from root, then modify the root parameter to reflect this. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
6092d04818
commit
9d1bc60138
24
fs/dcache.c
24
fs/dcache.c
@ -1759,10 +1759,8 @@ static int prepend(char **buffer, int *buflen, const char *str,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* d_path - return the path of a dentry
|
* d_path - return the path of a dentry
|
||||||
* @dentry: dentry to report
|
* @path: the dentry/vfsmount to report
|
||||||
* @vfsmnt: vfsmnt to which the dentry belongs
|
* @root: root vfsmnt/dentry (may be modified by this function)
|
||||||
* @root: root dentry
|
|
||||||
* @rootmnt: vfsmnt to which the root dentry belongs
|
|
||||||
* @buffer: buffer to return value in
|
* @buffer: buffer to return value in
|
||||||
* @buflen: buffer length
|
* @buflen: buffer length
|
||||||
*
|
*
|
||||||
@ -1772,10 +1770,15 @@ static int prepend(char **buffer, int *buflen, const char *str,
|
|||||||
* Returns the buffer or an error code if the path was too long.
|
* Returns the buffer or an error code if the path was too long.
|
||||||
*
|
*
|
||||||
* "buflen" should be positive. Caller holds the dcache_lock.
|
* "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).
|
||||||
*/
|
*/
|
||||||
static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
|
char *__d_path(const struct path *path, struct path *root,
|
||||||
struct path *root, char *buffer, int buflen)
|
char *buffer, int buflen)
|
||||||
{
|
{
|
||||||
|
struct dentry *dentry = path->dentry;
|
||||||
|
struct vfsmount *vfsmnt = path->mnt;
|
||||||
char * end = buffer+buflen;
|
char * end = buffer+buflen;
|
||||||
char * retval;
|
char * retval;
|
||||||
|
|
||||||
@ -1824,6 +1827,8 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
|
|||||||
if (prepend(&retval, &buflen, dentry->d_name.name,
|
if (prepend(&retval, &buflen, dentry->d_name.name,
|
||||||
dentry->d_name.len) != 0)
|
dentry->d_name.len) != 0)
|
||||||
goto Elong;
|
goto Elong;
|
||||||
|
root->mnt = vfsmnt;
|
||||||
|
root->dentry = dentry;
|
||||||
return retval;
|
return retval;
|
||||||
Elong:
|
Elong:
|
||||||
return ERR_PTR(-ENAMETOOLONG);
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
@ -1846,6 +1851,7 @@ char *d_path(struct path *path, char *buf, int buflen)
|
|||||||
{
|
{
|
||||||
char *res;
|
char *res;
|
||||||
struct path root;
|
struct path root;
|
||||||
|
struct path tmp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have various synthetic filesystems that never get mounted. On
|
* We have various synthetic filesystems that never get mounted. On
|
||||||
@ -1862,7 +1868,8 @@ char *d_path(struct path *path, char *buf, int buflen)
|
|||||||
path_get(&root);
|
path_get(&root);
|
||||||
read_unlock(¤t->fs->lock);
|
read_unlock(¤t->fs->lock);
|
||||||
spin_lock(&dcache_lock);
|
spin_lock(&dcache_lock);
|
||||||
res = __d_path(path->dentry, path->mnt, &root, buf, buflen);
|
tmp = root;
|
||||||
|
res = __d_path(path, &tmp, buf, buflen);
|
||||||
spin_unlock(&dcache_lock);
|
spin_unlock(&dcache_lock);
|
||||||
path_put(&root);
|
path_put(&root);
|
||||||
return res;
|
return res;
|
||||||
@ -1970,9 +1977,10 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
|
|||||||
spin_lock(&dcache_lock);
|
spin_lock(&dcache_lock);
|
||||||
if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
|
if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
|
||||||
unsigned long len;
|
unsigned long len;
|
||||||
|
struct path tmp = root;
|
||||||
char * cwd;
|
char * cwd;
|
||||||
|
|
||||||
cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE);
|
cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
|
||||||
spin_unlock(&dcache_lock);
|
spin_unlock(&dcache_lock);
|
||||||
|
|
||||||
error = PTR_ERR(cwd);
|
error = PTR_ERR(cwd);
|
||||||
|
@ -392,6 +392,36 @@ int seq_path(struct seq_file *m, struct path *path, char *esc)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(seq_path);
|
EXPORT_SYMBOL(seq_path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Same as seq_path, but relative to supplied root.
|
||||||
|
*
|
||||||
|
* root may be changed, see __d_path().
|
||||||
|
*/
|
||||||
|
int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
|
||||||
|
char *esc)
|
||||||
|
{
|
||||||
|
int err = -ENAMETOOLONG;
|
||||||
|
if (m->count < m->size) {
|
||||||
|
char *s = m->buf + m->count;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
spin_lock(&dcache_lock);
|
||||||
|
p = __d_path(path, root, s, m->size - m->count);
|
||||||
|
spin_unlock(&dcache_lock);
|
||||||
|
err = PTR_ERR(p);
|
||||||
|
if (!IS_ERR(p)) {
|
||||||
|
s = mangle_path(s, p, esc);
|
||||||
|
if (s) {
|
||||||
|
p = m->buf + m->count;
|
||||||
|
m->count = s - m->buf;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m->count = m->size;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns the path of the 'dentry' from the root of its filesystem.
|
* returns the path of the 'dentry' from the root of its filesystem.
|
||||||
*/
|
*/
|
||||||
|
@ -301,6 +301,7 @@ extern int d_validate(struct dentry *, struct dentry *);
|
|||||||
*/
|
*/
|
||||||
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
|
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
|
||||||
|
|
||||||
|
extern char *__d_path(const struct path *path, struct path *root, char *, int);
|
||||||
extern char *d_path(struct path *, char *, int);
|
extern char *d_path(struct path *, char *, int);
|
||||||
extern char *dentry_path(struct dentry *, char *, int);
|
extern char *dentry_path(struct dentry *, char *, int);
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ int seq_printf(struct seq_file *, const char *, ...)
|
|||||||
|
|
||||||
int seq_path(struct seq_file *, struct path *, char *);
|
int seq_path(struct seq_file *, struct path *, char *);
|
||||||
int seq_dentry(struct seq_file *, struct dentry *, char *);
|
int seq_dentry(struct seq_file *, struct dentry *, char *);
|
||||||
|
int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
|
||||||
|
char *esc);
|
||||||
|
|
||||||
int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
|
int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
|
||||||
int single_release(struct inode *, struct file *);
|
int single_release(struct inode *, struct file *);
|
||||||
|
Loading…
Reference in New Issue
Block a user