mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
Revert "[PATCH] Fix d_path for lazy unmounts"
This reverts commit eb3dfb0cb1
.
It causes some strange Gnome problem with dbus-daemon getting stuck, so
we'll revert it until that problem is understood.
Reported by both walt and Greg KH, who both independently git-bisected
the problem to this commit.
Andreas is looking at it.
Reported-by: walt <wa1ter@myrealbox.com>
Reported-by: Greg KH <greg@kroah.com>
Acked-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
ec2f9d1331
commit
552ce544ed
1 changed files with 70 additions and 80 deletions
150
fs/dcache.c
150
fs/dcache.c
|
@ -1739,41 +1739,45 @@ shouldnt_be_hashed:
|
||||||
* @rootmnt: vfsmnt to which the root dentry belongs
|
* @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
|
||||||
* @fail_deleted: what to return for deleted files
|
|
||||||
*
|
*
|
||||||
* Convert a dentry into an ASCII path name. If the entry has been deleted,
|
* Convert a dentry into an ASCII path name. If the entry has been deleted
|
||||||
* then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
|
* the string " (deleted)" is appended. Note that this is ambiguous.
|
||||||
* the the string " (deleted)" is appended. Note that this is ambiguous.
|
|
||||||
*
|
*
|
||||||
* Returns the buffer or an error code.
|
* Returns the buffer or an error code if the path was too long.
|
||||||
|
*
|
||||||
|
* "buflen" should be positive. Caller holds the dcache_lock.
|
||||||
*/
|
*/
|
||||||
static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
|
static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
|
||||||
struct dentry *root, struct vfsmount *rootmnt,
|
struct dentry *root, struct vfsmount *rootmnt,
|
||||||
char *buffer, int buflen, int fail_deleted)
|
char *buffer, int buflen)
|
||||||
{
|
{
|
||||||
int namelen, is_slash;
|
char * end = buffer+buflen;
|
||||||
|
char * retval;
|
||||||
|
int namelen;
|
||||||
|
|
||||||
if (buflen < 2)
|
*--end = '\0';
|
||||||
return ERR_PTR(-ENAMETOOLONG);
|
buflen--;
|
||||||
buffer += --buflen;
|
|
||||||
*buffer = '\0';
|
|
||||||
|
|
||||||
spin_lock(&dcache_lock);
|
|
||||||
if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
|
if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
|
||||||
if (fail_deleted) {
|
|
||||||
buffer = ERR_PTR(-ENOENT);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (buflen < 10)
|
|
||||||
goto Elong;
|
|
||||||
buflen -= 10;
|
buflen -= 10;
|
||||||
buffer -= 10;
|
end -= 10;
|
||||||
memcpy(buffer, " (deleted)", 10);
|
if (buflen < 0)
|
||||||
|
goto Elong;
|
||||||
|
memcpy(end, " (deleted)", 10);
|
||||||
}
|
}
|
||||||
while (dentry != root || vfsmnt != rootmnt) {
|
|
||||||
|
if (buflen < 1)
|
||||||
|
goto Elong;
|
||||||
|
/* Get '/' right */
|
||||||
|
retval = end-1;
|
||||||
|
*retval = '/';
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
struct dentry * parent;
|
struct dentry * parent;
|
||||||
|
|
||||||
|
if (dentry == root && vfsmnt == rootmnt)
|
||||||
|
break;
|
||||||
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
|
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
|
||||||
|
/* Global root? */
|
||||||
spin_lock(&vfsmount_lock);
|
spin_lock(&vfsmount_lock);
|
||||||
if (vfsmnt->mnt_parent == vfsmnt) {
|
if (vfsmnt->mnt_parent == vfsmnt) {
|
||||||
spin_unlock(&vfsmount_lock);
|
spin_unlock(&vfsmount_lock);
|
||||||
|
@ -1787,60 +1791,33 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
|
||||||
parent = dentry->d_parent;
|
parent = dentry->d_parent;
|
||||||
prefetch(parent);
|
prefetch(parent);
|
||||||
namelen = dentry->d_name.len;
|
namelen = dentry->d_name.len;
|
||||||
if (buflen <= namelen)
|
|
||||||
goto Elong;
|
|
||||||
buflen -= namelen + 1;
|
buflen -= namelen + 1;
|
||||||
buffer -= namelen;
|
if (buflen < 0)
|
||||||
memcpy(buffer, dentry->d_name.name, namelen);
|
goto Elong;
|
||||||
*--buffer = '/';
|
end -= namelen;
|
||||||
|
memcpy(end, dentry->d_name.name, namelen);
|
||||||
|
*--end = '/';
|
||||||
|
retval = end;
|
||||||
dentry = parent;
|
dentry = parent;
|
||||||
}
|
}
|
||||||
/* Get '/' right */
|
|
||||||
if (*buffer != '/')
|
|
||||||
*--buffer = '/';
|
|
||||||
|
|
||||||
out:
|
return retval;
|
||||||
spin_unlock(&dcache_lock);
|
|
||||||
return buffer;
|
|
||||||
|
|
||||||
global_root:
|
global_root:
|
||||||
/*
|
|
||||||
* We went past the (vfsmount, dentry) we were looking for and have
|
|
||||||
* either hit a root dentry, a lazily unmounted dentry, an
|
|
||||||
* unconnected dentry, or the file is on a pseudo filesystem.
|
|
||||||
*/
|
|
||||||
namelen = dentry->d_name.len;
|
namelen = dentry->d_name.len;
|
||||||
is_slash = (namelen == 1 && *dentry->d_name.name == '/');
|
buflen -= namelen;
|
||||||
if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
|
if (buflen < 0)
|
||||||
/*
|
|
||||||
* Make sure we won't return a pathname starting with '/'.
|
|
||||||
*
|
|
||||||
* Historically, we also glue together the root dentry and
|
|
||||||
* remaining name for pseudo filesystems like pipefs, which
|
|
||||||
* have the MS_NOUSER flag set. This results in pathnames
|
|
||||||
* like "pipe:[439336]".
|
|
||||||
*/
|
|
||||||
if (*buffer == '/') {
|
|
||||||
buffer++;
|
|
||||||
buflen++;
|
|
||||||
}
|
|
||||||
if (is_slash)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (buflen < namelen)
|
|
||||||
goto Elong;
|
goto Elong;
|
||||||
buffer -= namelen;
|
retval -= namelen-1; /* hit the slash */
|
||||||
memcpy(buffer, dentry->d_name.name, namelen);
|
memcpy(retval, dentry->d_name.name, namelen);
|
||||||
goto out;
|
return retval;
|
||||||
|
|
||||||
Elong:
|
Elong:
|
||||||
buffer = ERR_PTR(-ENAMETOOLONG);
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write full pathname into buffer and return start of pathname */
|
/* write full pathname into buffer and return start of pathname */
|
||||||
char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
|
char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
|
||||||
int buflen)
|
char *buf, int buflen)
|
||||||
{
|
{
|
||||||
char *res;
|
char *res;
|
||||||
struct vfsmount *rootmnt;
|
struct vfsmount *rootmnt;
|
||||||
|
@ -1850,7 +1827,9 @@ char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
|
||||||
rootmnt = mntget(current->fs->rootmnt);
|
rootmnt = mntget(current->fs->rootmnt);
|
||||||
root = dget(current->fs->root);
|
root = dget(current->fs->root);
|
||||||
read_unlock(¤t->fs->lock);
|
read_unlock(¤t->fs->lock);
|
||||||
res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
|
spin_lock(&dcache_lock);
|
||||||
|
res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
|
||||||
|
spin_unlock(&dcache_lock);
|
||||||
dput(root);
|
dput(root);
|
||||||
mntput(rootmnt);
|
mntput(rootmnt);
|
||||||
return res;
|
return res;
|
||||||
|
@ -1876,10 +1855,10 @@ char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
|
||||||
*/
|
*/
|
||||||
asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
|
asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
|
||||||
{
|
{
|
||||||
int error, len;
|
int error;
|
||||||
struct vfsmount *pwdmnt, *rootmnt;
|
struct vfsmount *pwdmnt, *rootmnt;
|
||||||
struct dentry *pwd, *root;
|
struct dentry *pwd, *root;
|
||||||
char *page = (char *) __get_free_page(GFP_USER), *cwd;
|
char *page = (char *) __get_free_page(GFP_USER);
|
||||||
|
|
||||||
if (!page)
|
if (!page)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1891,18 +1870,29 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
|
||||||
root = dget(current->fs->root);
|
root = dget(current->fs->root);
|
||||||
read_unlock(¤t->fs->lock);
|
read_unlock(¤t->fs->lock);
|
||||||
|
|
||||||
cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
|
error = -ENOENT;
|
||||||
error = PTR_ERR(cwd);
|
/* Has the current directory has been unlinked? */
|
||||||
if (IS_ERR(cwd))
|
spin_lock(&dcache_lock);
|
||||||
goto out;
|
if (pwd->d_parent == pwd || !d_unhashed(pwd)) {
|
||||||
|
unsigned long len;
|
||||||
|
char * cwd;
|
||||||
|
|
||||||
error = -ERANGE;
|
cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
|
||||||
len = PAGE_SIZE + page - cwd;
|
spin_unlock(&dcache_lock);
|
||||||
if (len <= size) {
|
|
||||||
error = len;
|
error = PTR_ERR(cwd);
|
||||||
if (copy_to_user(buf, cwd, len))
|
if (IS_ERR(cwd))
|
||||||
error = -EFAULT;
|
goto out;
|
||||||
}
|
|
||||||
|
error = -ERANGE;
|
||||||
|
len = PAGE_SIZE + page - cwd;
|
||||||
|
if (len <= size) {
|
||||||
|
error = len;
|
||||||
|
if (copy_to_user(buf, cwd, len))
|
||||||
|
error = -EFAULT;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
spin_unlock(&dcache_lock);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
dput(pwd);
|
dput(pwd);
|
||||||
|
|
Loading…
Reference in a new issue