* [patch 0/3] vfs: d_path cleanups and fixes
@ 2008-06-16 11:28 Miklos Szeredi
2008-06-16 11:28 ` [patch 1/3] vfs: dcache cleanups Miklos Szeredi
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Miklos Szeredi @ 2008-06-16 11:28 UTC (permalink / raw)
To: viro; +Cc: linux-kernel, linux-fsdevel
Al,
Could you please take care of these dcache patches for 2.6.27?
Thanks,
Miklos
--
^ permalink raw reply [flat|nested] 9+ messages in thread* [patch 1/3] vfs: dcache cleanups 2008-06-16 11:28 [patch 0/3] vfs: d_path cleanups and fixes Miklos Szeredi @ 2008-06-16 11:28 ` Miklos Szeredi 2008-06-16 11:28 ` [patch 2/3] vfs: fix sys_getcwd for detached mounts Miklos Szeredi 2008-06-16 11:28 ` [patch 3/3] vfs: make d_path() consistent across mount operations Miklos Szeredi 2 siblings, 0 replies; 9+ messages in thread From: Miklos Szeredi @ 2008-06-16 11:28 UTC (permalink / raw) To: viro; +Cc: linux-kernel, linux-fsdevel, Christoph Hellwig [-- Attachment #1: vfs-dcache-cleanups.patch --] [-- Type: text/plain, Size: 6278 bytes --] From: Miklos Szeredi <mszeredi@suse.cz> d_path() cleanups and fix the following sparse warnings: fs/dcache.c:2183:19: warning: symbol 'filp_cachep' was not declared. Should it be static? fs/dcache.c:115:3: warning: context imbalance in 'dentry_iput' - unexpected unlock fs/dcache.c:188:2: warning: context imbalance in 'dput' - different lock contexts for basic block fs/dcache.c:400:2: warning: context imbalance in 'prune_one_dentry' - different lock contexts for basic block fs/dcache.c:431:22: warning: context imbalance in 'prune_dcache' - different lock contexts for basic block fs/dcache.c:563:2: warning: context imbalance in 'shrink_dcache_sb' - different lock contexts for basic block fs/dcache.c:1385:6: warning: context imbalance in 'd_delete' - wrong count at exit fs/dcache.c:1636:2: warning: context imbalance in '__d_unalias' - unexpected unlock fs/dcache.c:1735:2: warning: context imbalance in 'd_materialise_unique' - different lock contexts for basic block Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Reviewed-by: Matthew Wilcox <willy@linux.intel.com> Acked-by: Christoph Hellwig <hch@infradead.org> --- fs/dcache.c | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) Index: linux-2.6/fs/dcache.c =================================================================== --- linux-2.6.orig/fs/dcache.c 2008-06-11 10:16:10.000000000 +0200 +++ linux-2.6/fs/dcache.c 2008-06-13 13:12:57.000000000 +0200 @@ -17,6 +17,7 @@ #include <linux/syscalls.h> #include <linux/string.h> #include <linux/mm.h> +#include <linux/fdtable.h> #include <linux/fs.h> #include <linux/fsnotify.h> #include <linux/slab.h> @@ -106,9 +107,10 @@ static void dentry_lru_remove(struct den /* * Release the dentry's inode, using the filesystem * d_iput() operation if defined. - * Called with dcache_lock and per dentry lock held, drops both. */ static void dentry_iput(struct dentry * dentry) + __releases(dentry->d_lock) + __releases(dcache_lock) { struct inode *inode = dentry->d_inode; if (inode) { @@ -132,12 +134,13 @@ static void dentry_iput(struct dentry * * d_kill - kill dentry and return parent * @dentry: dentry to kill * - * Called with dcache_lock and d_lock, releases both. The dentry must - * already be unhashed and removed from the LRU. + * The dentry must already be unhashed and removed from the LRU. * * If this is the root of the dentry tree, return NULL. */ static struct dentry *d_kill(struct dentry *dentry) + __releases(dentry->d_lock) + __releases(dcache_lock) { struct dentry *parent; @@ -383,11 +386,11 @@ restart: * Try to prune ancestors as well. This is necessary to prevent * quadratic behavior of shrink_dcache_parent(), but is also expected * to be beneficial in reducing dentry cache fragmentation. - * - * Called with dcache_lock, drops it and then regains. - * Called with dentry->d_lock held, drops it. */ static void prune_one_dentry(struct dentry * dentry) + __releases(dentry->d_lock) + __releases(dcache_lock) + __acquires(dcache_lock) { __d_drop(dentry); dentry = d_kill(dentry); @@ -1604,10 +1607,9 @@ static int d_isparent(struct dentry *p1, * * Note: If ever the locking in lock_rename() changes, then please * remember to update this too... - * - * On return, dcache_lock will have been unlocked. */ static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias) + __releases(dcache_lock) { struct mutex *m1 = NULL, *m2 = NULL; struct dentry *ret; @@ -1743,7 +1745,6 @@ out_nolock: shouldnt_be_hashed: spin_unlock(&dcache_lock); BUG(); - goto shouldnt_be_hashed; } static int prepend(char **buffer, int *buflen, const char *str, @@ -1758,7 +1759,7 @@ static int prepend(char **buffer, int *b } /** - * d_path - return the path of a dentry + * __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 @@ -1779,8 +1780,9 @@ char *__d_path(const struct path *path, { struct dentry *dentry = path->dentry; struct vfsmount *vfsmnt = path->mnt; - char * end = buffer+buflen; - char * retval; + char *end = buffer + buflen; + char *retval; + struct qstr *name; prepend(&end, &buflen, "\0", 1); if (!IS_ROOT(dentry) && d_unhashed(dentry) && @@ -1812,8 +1814,8 @@ char *__d_path(const struct path *path, } parent = dentry->d_parent; prefetch(parent); - if ((prepend(&end, &buflen, dentry->d_name.name, - dentry->d_name.len) != 0) || + name = &dentry->d_name; + if ((prepend(&end, &buflen, name->name, name->len) != 0) || (prepend(&end, &buflen, "/", 1) != 0)) goto Elong; retval = end; @@ -1824,8 +1826,8 @@ char *__d_path(const struct path *path, global_root: retval += 1; /* hit the slash */ - if (prepend(&retval, &buflen, dentry->d_name.name, - dentry->d_name.len) != 0) + name = &dentry->d_name; + if (prepend(&retval, &buflen, name->name, name->len) != 0) goto Elong; root->mnt = vfsmnt; root->dentry = dentry; @@ -1845,7 +1847,7 @@ Elong: * * 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. */ char *d_path(struct path *path, char *buf, int buflen) { @@ -1915,16 +1917,13 @@ char *dentry_path(struct dentry *dentry, retval = end-1; *retval = '/'; - for (;;) { - struct dentry *parent; - if (IS_ROOT(dentry)) - break; + while (!IS_ROOT(dentry)) { + struct dentry *parent = dentry->d_parent; + struct qstr *name; - parent = dentry->d_parent; prefetch(parent); - - if ((prepend(&end, &buflen, dentry->d_name.name, - dentry->d_name.len) != 0) || + name = &dentry->d_name; + if ((prepend(&end, &buflen, name->name, name->len) != 0) || (prepend(&end, &buflen, "/", 1) != 0)) goto Elong; @@ -1975,7 +1974,7 @@ asmlinkage long sys_getcwd(char __user * error = -ENOENT; /* Has the current directory has been unlinked? */ spin_lock(&dcache_lock); - if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) { + if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) { unsigned long len; struct path tmp = root; char * cwd; -- ^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 2/3] vfs: fix sys_getcwd for detached mounts 2008-06-16 11:28 [patch 0/3] vfs: d_path cleanups and fixes Miklos Szeredi 2008-06-16 11:28 ` [patch 1/3] vfs: dcache cleanups Miklos Szeredi @ 2008-06-16 11:28 ` Miklos Szeredi 2008-06-23 13:55 ` Al Viro 2008-06-16 11:28 ` [patch 3/3] vfs: make d_path() consistent across mount operations Miklos Szeredi 2 siblings, 1 reply; 9+ messages in thread From: Miklos Szeredi @ 2008-06-16 11:28 UTC (permalink / raw) To: viro; +Cc: linux-kernel, linux-fsdevel, Christoph Hellwig [-- Attachment #1: vfs-fix-sys_getcwd-for-detached-mounts.patch --] [-- Type: text/plain, Size: 1540 bytes --] From: Miklos Szeredi <mszeredi@suse.cz> Currently getcwd(2) on a detached mount will give a garbled result: > mkdir /mnt/foo > mount --bind /etc /mnt/foo > cd /mnt/foo/skel > /bin/pwd /mnt/foo/skel > umount -l /mnt/foo > /bin/pwd etcskel After the patch it will give a much saner "/skel" result. Thanks to John Johansen for pointing out this bug. Reported-by: John Johansen <jjohansen@suse.de> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Acked-by: Christoph Hellwig <hch@infradead.org> --- fs/dcache.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) Index: linux-2.6/fs/dcache.c =================================================================== --- linux-2.6.orig/fs/dcache.c 2008-06-13 13:12:57.000000000 +0200 +++ linux-2.6/fs/dcache.c 2008-06-13 13:13:01.000000000 +0200 @@ -1825,10 +1825,20 @@ char *__d_path(const struct path *path, return retval; global_root: - retval += 1; /* hit the slash */ - name = &dentry->d_name; - if (prepend(&retval, &buflen, name->name, name->len) != 0) - goto Elong; + /* + * If this is a root dentry, then overwrite the slash. This + * will also DTRT with pseudo filesystems which have root + * dentries named "foo:". + * + * Otherwise this is the root of a detached mount, so don't do + * anything. + */ + if (IS_ROOT(dentry)) { + retval += 1; + name = &dentry->d_name; + if (prepend(&retval, &buflen, name->name, name->len) != 0) + goto Elong; + } root->mnt = vfsmnt; root->dentry = dentry; return retval; -- ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch 2/3] vfs: fix sys_getcwd for detached mounts 2008-06-16 11:28 ` [patch 2/3] vfs: fix sys_getcwd for detached mounts Miklos Szeredi @ 2008-06-23 13:55 ` Al Viro 2008-06-23 14:34 ` Miklos Szeredi 0 siblings, 1 reply; 9+ messages in thread From: Al Viro @ 2008-06-23 13:55 UTC (permalink / raw) To: Miklos Szeredi; +Cc: linux-kernel, linux-fsdevel, Christoph Hellwig On Mon, Jun 16, 2008 at 01:28:06PM +0200, Miklos Szeredi wrote: > After the patch it will give a much saner "/skel" result. I'm not sure that /skel is much saner, to be honest. Existing behaviour is BS, no arguments about that, but I suspect that we want that to be recognizable. How about doing something like detached:<rest of path> instead (c.f. "pipe:[6969]" and its ilk)? Lack of leading / currently points to pathname *not* resolving to object; it might be worth doing the same here. Comments? ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch 2/3] vfs: fix sys_getcwd for detached mounts 2008-06-23 13:55 ` Al Viro @ 2008-06-23 14:34 ` Miklos Szeredi 2008-06-23 14:41 ` Al Viro 0 siblings, 1 reply; 9+ messages in thread From: Miklos Szeredi @ 2008-06-23 14:34 UTC (permalink / raw) To: viro; +Cc: miklos, linux-kernel, linux-fsdevel, hch > > After the patch it will give a much saner "/skel" result. > > I'm not sure that /skel is much saner, to be honest. Just for argument's sake: before the patch getcwd() on detached object wasn't consistent with any definition of "absolute path". After the patch it's at least consistent with defining it as the path from the ultimate reachable ancestor (which does have at least some historical relevance). > Existing > behaviour is BS, no arguments about that, but I suspect that > we want that to be recognizable. How about doing something > like detached:<rest of path> instead (c.f. "pipe:[6969]" and > its ilk)? OK, obviously current users don't care, otherwise somebody would have complained about this issue. So if we agree on "detached:...", I'm fine with that. Thanks, Miklos ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch 2/3] vfs: fix sys_getcwd for detached mounts 2008-06-23 14:34 ` Miklos Szeredi @ 2008-06-23 14:41 ` Al Viro 0 siblings, 0 replies; 9+ messages in thread From: Al Viro @ 2008-06-23 14:41 UTC (permalink / raw) To: Miklos Szeredi; +Cc: linux-kernel, linux-fsdevel, hch On Mon, Jun 23, 2008 at 04:34:00PM +0200, Miklos Szeredi wrote: > > > After the patch it will give a much saner "/skel" result. > > > > I'm not sure that /skel is much saner, to be honest. > > Just for argument's sake: before the patch getcwd() on detached object > wasn't consistent with any definition of "absolute path". After the > patch it's at least consistent with defining it as the path from the > ultimate reachable ancestor (which does have at least some historical > relevance). Before the patch getcwd() on detached object generated junk, period. As for the path from ultimate reachable ancestor... I'm not sure that this definition actually matches any real-world problem. > > Existing > > behaviour is BS, no arguments about that, but I suspect that > > we want that to be recognizable. How about doing something > > like detached:<rest of path> instead (c.f. "pipe:[6969]" and > > its ilk)? > > OK, obviously current users don't care, otherwise somebody would have > complained about this issue. So if we agree on "detached:...", I'm > fine with that. Care to resend? BTW, one more thing - in the 1/3 I'd probably add a wrapper around prepend() that would take struct qstr * instead of name/length and used it instead of your locals. As in prepend_name(&end, &buflen, &dentry->d_name) etc. ^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 3/3] vfs: make d_path() consistent across mount operations 2008-06-16 11:28 [patch 0/3] vfs: d_path cleanups and fixes Miklos Szeredi 2008-06-16 11:28 ` [patch 1/3] vfs: dcache cleanups Miklos Szeredi 2008-06-16 11:28 ` [patch 2/3] vfs: fix sys_getcwd for detached mounts Miklos Szeredi @ 2008-06-16 11:28 ` Miklos Szeredi 2008-06-23 14:01 ` Al Viro 2 siblings, 1 reply; 9+ messages in thread From: Miklos Szeredi @ 2008-06-16 11:28 UTC (permalink / raw) To: viro Cc: linux-kernel, linux-fsdevel, Andreas Gruenbacher, John Johansen, Christoph Hellwig [-- Attachment #1: vfs-make-d_path-consistent-across-mount-operations.patch --] [-- Type: text/plain, Size: 2119 bytes --] From: Andreas Gruenbacher <agruen@suse.de> The path that __d_path() computes can become slightly inconsistent when it races with mount operations: it grabs the vfsmount_lock when traversing mount points but immediately drops it again, only to re-grab it when it reaches the next mount point. The result is that the filename computed is not always consisent, and the file may never have had that name. (This is unlikely, but still possible.) Fix this by grabbing the vfsmount_lock for the whole duration of __d_path(). Signed-off-by: Andreas Gruenbacher <agruen@suse.de> Signed-off-by: John Johansen <jjohansen@suse.de> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Acked-by: Christoph Hellwig <hch@infradead.org> --- fs/dcache.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) Index: linux-2.6/fs/dcache.c =================================================================== --- linux-2.6.orig/fs/dcache.c 2008-06-13 13:13:01.000000000 +0200 +++ linux-2.6/fs/dcache.c 2008-06-13 13:13:04.000000000 +0200 @@ -1784,6 +1784,7 @@ char *__d_path(const struct path *path, char *retval; struct qstr *name; + spin_lock(&vfsmount_lock); prepend(&end, &buflen, "\0", 1); if (!IS_ROOT(dentry) && d_unhashed(dentry) && (prepend(&end, &buflen, " (deleted)", 10) != 0)) @@ -1802,14 +1803,11 @@ char *__d_path(const struct path *path, break; if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { /* Global root? */ - spin_lock(&vfsmount_lock); if (vfsmnt->mnt_parent == vfsmnt) { - spin_unlock(&vfsmount_lock); goto global_root; } dentry = vfsmnt->mnt_mountpoint; vfsmnt = vfsmnt->mnt_parent; - spin_unlock(&vfsmount_lock); continue; } parent = dentry->d_parent; @@ -1822,6 +1820,8 @@ char *__d_path(const struct path *path, dentry = parent; } +out: + spin_unlock(&vfsmount_lock); return retval; global_root: @@ -1841,9 +1841,11 @@ global_root: } root->mnt = vfsmnt; root->dentry = dentry; - return retval; + goto out; + Elong: - return ERR_PTR(-ENAMETOOLONG); + retval = ERR_PTR(-ENAMETOOLONG); + goto out; } /** -- ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch 3/3] vfs: make d_path() consistent across mount operations 2008-06-16 11:28 ` [patch 3/3] vfs: make d_path() consistent across mount operations Miklos Szeredi @ 2008-06-23 14:01 ` Al Viro 2008-06-23 14:50 ` Andreas Gruenbacher 0 siblings, 1 reply; 9+ messages in thread From: Al Viro @ 2008-06-23 14:01 UTC (permalink / raw) To: Miklos Szeredi Cc: linux-kernel, linux-fsdevel, Andreas Gruenbacher, John Johansen, Christoph Hellwig On Mon, Jun 16, 2008 at 01:28:07PM +0200, Miklos Szeredi wrote: > From: Andreas Gruenbacher <agruen@suse.de> > > The path that __d_path() computes can become slightly inconsistent when it > races with mount operations: it grabs the vfsmount_lock when traversing mount > points but immediately drops it again, only to re-grab it when it reaches the > next mount point. The result is that the filename computed is not always > consisent, and the file may never have had that name. (This is unlikely, but > still possible.) > > Fix this by grabbing the vfsmount_lock for the whole duration of > __d_path(). Umm... I don't see problems with doing that, but I hope you realize that the notion of "ever having that name" is not the same as "pathnam resolution on that name ever leading to that file" - path_walk() is *NOT* atomic wrt rename() (or mount --move, indeed) and it's quite possible to walk into subdirectory, have it moved under you, then see .. as the next pathname component and step out into new parent. Said that, it makes sense to avoid dropping/regaining the lock in that case - it's less work and I don't believe that it would increase contention on vfsmount_lock. So I'm applying that one, just be careful with assumptions about consistency, etc. in the general area. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch 3/3] vfs: make d_path() consistent across mount operations 2008-06-23 14:01 ` Al Viro @ 2008-06-23 14:50 ` Andreas Gruenbacher 0 siblings, 0 replies; 9+ messages in thread From: Andreas Gruenbacher @ 2008-06-23 14:50 UTC (permalink / raw) To: Al Viro Cc: Miklos Szeredi, linux-kernel, linux-fsdevel, John Johansen, Christoph Hellwig On Monday 23 June 2008 16:01:44 Al Viro wrote: > Umm... I don't see problems with doing that, but I hope you realize that > the notion of "ever having that name" is not the same as "pathnam > resolution on that name ever leading to that file" - path_walk() is *NOT* > atomic wrt rename() (or mount --move, indeed) and it's quite possible to > walk into subdirectory, have it moved under you, then see .. as the next > pathname component and step out into new parent. Yes, that's understood. Relative lookups don't visit all directories up to the root (unless via ".."), so there can be infinite time between walking down a directory and computing a pathname for it. > Said that, it makes sense to avoid dropping/regaining the lock in that > case - it's less work and I don't believe that it would increase contention > on vfsmount_lock. So I'm applying that one, just be careful with > assumptions about consistency, etc. in the general area. Thanks. Andreas ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-06-23 14:50 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-06-16 11:28 [patch 0/3] vfs: d_path cleanups and fixes Miklos Szeredi 2008-06-16 11:28 ` [patch 1/3] vfs: dcache cleanups Miklos Szeredi 2008-06-16 11:28 ` [patch 2/3] vfs: fix sys_getcwd for detached mounts Miklos Szeredi 2008-06-23 13:55 ` Al Viro 2008-06-23 14:34 ` Miklos Szeredi 2008-06-23 14:41 ` Al Viro 2008-06-16 11:28 ` [patch 3/3] vfs: make d_path() consistent across mount operations Miklos Szeredi 2008-06-23 14:01 ` Al Viro 2008-06-23 14:50 ` Andreas Gruenbacher
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).