* [Patch] cpusets: document proc status allowed fields
@ 2004-09-16 1:29 Paul Jackson
2004-09-16 14:01 ` [Patch] cpusets: fix race in cpuset_add_file() Simon Derr
0 siblings, 1 reply; 8+ messages in thread
From: Paul Jackson @ 2004-09-16 1:29 UTC (permalink / raw)
To: Andrew Morton; +Cc: Simon Derr, Paul Jackson, linux-kernel
Document the /proc/<pid>/status fields added in an
earlier cpuset patch for Cpus_allowed and Mems_allowed.
Signed-off-by: Paul Jackson <pj@sgi.com>
Index: 2.6.9-rc1-mm4/Documentation/cpusets.txt
===================================================================
--- 2.6.9-rc1-mm4.orig/Documentation/cpusets.txt 2004-09-08 15:09:56.000000000 -0700
+++ 2.6.9-rc1-mm4/Documentation/cpusets.txt 2004-09-12 00:29:01.000000000 -0700
@@ -151,6 +151,14 @@ Each task under /proc has an added file
the cpuset name, as the path relative to the root of the cpuset file
system.
+The /proc/<pid>/status file for each task has two added lines,
+displaying the tasks cpus_allowed (on which CPUs it may be scheduled)
+and mems_allowed (on which Memory Nodes it may obtain memory),
+in the format seen in the following example:
+
+ Cpus_allowed: ffffffff,ffffffff,ffffffff,ffffffff
+ Mems_allowed: ffffffff,ffffffff
+
Each cpuset is represented by a directory in the cpuset file system
containing the following files describing that cpuset:
--
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <pj@sgi.com> 1.650.933.1373
^ permalink raw reply [flat|nested] 8+ messages in thread* [Patch] cpusets: fix race in cpuset_add_file() 2004-09-16 1:29 [Patch] cpusets: document proc status allowed fields Paul Jackson @ 2004-09-16 14:01 ` Simon Derr 2004-09-16 14:55 ` Paul Jackson 0 siblings, 1 reply; 8+ messages in thread From: Simon Derr @ 2004-09-16 14:01 UTC (permalink / raw) To: Paul Jackson; +Cc: Andrew Morton, Simon Derr, linux-kernel Hi, This patch fixes a missing down()/up() pair in cpuset_add_file(). Without this patch, sometimes it is possible to have two duplicate dentries for a single file of a cpuset, with one of them being invalid, and thus the file is present but cannot be opened... Something like: # cd /dev/cpuset/foo # ls ls: cpus: No such file or directory The patch also removes comments that 1/are now bogus with this fix applied 2/were not respected anyway Signed-off-by: Simon Derr <simon.derr@bull.net> Index: mm4/kernel/cpuset.c =================================================================== --- mm4.orig/kernel/cpuset.c 2004-09-13 09:43:02.000000000 +0200 +++ mm4/kernel/cpuset.c 2004-09-16 15:46:21.847401360 +0200 @@ -956,13 +956,12 @@ static int cpuset_create_dir(struct cpus return error; } -/* MUST be called with dir->d_inode->i_sem held */ - static int cpuset_add_file(struct dentry *dir, const struct cftype *cft) { struct dentry *dentry; int error; + down(&dir->d_inode->i_sem); dentry = cpuset_get_dentry(dir, cft->name); if (!IS_ERR(dentry)) { error = cpuset_create_file(dentry, 0644 | S_IFREG); @@ -971,6 +970,7 @@ static int cpuset_add_file(struct dentry dput(dentry); } else error = PTR_ERR(dentry); + up(&dir->d_inode->i_sem); return error; } @@ -1162,7 +1162,6 @@ static struct cftype cft_notify_on_relea .private = FILE_NOTIFY_ON_RELEASE, }; -/* MUST be called with ->d_inode->i_sem held */ static int cpuset_populate_dir(struct dentry *cs_dentry) { int err; ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Patch] cpusets: fix race in cpuset_add_file() 2004-09-16 14:01 ` [Patch] cpusets: fix race in cpuset_add_file() Simon Derr @ 2004-09-16 14:55 ` Paul Jackson 2004-09-16 15:39 ` Simon Derr 0 siblings, 1 reply; 8+ messages in thread From: Paul Jackson @ 2004-09-16 14:55 UTC (permalink / raw) To: Simon Derr; +Cc: akpm, linux-kernel Color me confused - this cpuset_sem down/up should not be needed, and should deadlock. In the call chain: cpuset_mkdir -> cpuset_create -> cpuset_populate_dir -> cpuset_add_file cpuset_create() already holds the cpuset_sem for the duration, and you're adding another cpuset_sem down in cpuset_add_file(), which should deadlock. If you are seeing the duplicate invalid cpuset entries, then must be something else going on, unfortunately. That, or I'm confused. -- I won't rest till it's the best ... Programmer, Linux Scalability Paul Jackson <pj@sgi.com> 1.650.933.1373 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Patch] cpusets: fix race in cpuset_add_file() 2004-09-16 14:55 ` Paul Jackson @ 2004-09-16 15:39 ` Simon Derr 2004-09-16 16:03 ` Paul Jackson 2004-09-17 7:22 ` Paul Jackson 0 siblings, 2 replies; 8+ messages in thread From: Simon Derr @ 2004-09-16 15:39 UTC (permalink / raw) To: Paul Jackson; +Cc: Simon Derr, akpm, linux-kernel On Thu, 16 Sep 2004, Paul Jackson wrote: > Color me confused - this cpuset_sem down/up should not be needed, > and should deadlock. In the call chain: > > cpuset_mkdir -> cpuset_create -> cpuset_populate_dir -> cpuset_add_file > > cpuset_create() already holds the cpuset_sem for the duration, and you're > adding another cpuset_sem down in cpuset_add_file(), which should deadlock. > > If you are seeing the duplicate invalid cpuset entries, then must be > something else going on, unfortunately. > > That, or I'm confused. Neither. You've just read the patch too quickly: + down(&dir->d_inode->i_sem); NOT down(&cpuset_sem); However, your remark is welcome, since there is indeed a slight chance of deadlock with my patch, but it needs 2 mkdirs racing. imagine: mkdir a/b mkdir a/b/c sys_mkdir(): down(a->i_sem); cpuset_create(): down(cpuset_sem); sys_mkdir(): down(b->i_sem); cpuset_add_file(): down(b->i_sem); cpuset_create(): down(cpuset_sem); -> deadlock. So we should release cpuset_sem a bit earlier in cpuset_create(), before calling cpuset_populate_dir(). This updated patch should be better (hopefully). Signed-off-by: Simon Derr <simon.derr@bull.net> Index: mm4/kernel/cpuset.c =================================================================== --- mm4.orig/kernel/cpuset.c 2004-09-13 09:43:02.000000000 +0200 +++ mm4/kernel/cpuset.c 2004-09-16 17:23:48.764321923 +0200 @@ -956,13 +956,12 @@ static int cpuset_create_dir(struct cpus return error; } -/* MUST be called with dir->d_inode->i_sem held */ - static int cpuset_add_file(struct dentry *dir, const struct cftype *cft) { struct dentry *dentry; int error; + down(&dir->d_inode->i_sem); dentry = cpuset_get_dentry(dir, cft->name); if (!IS_ERR(dentry)) { error = cpuset_create_file(dentry, 0644 | S_IFREG); @@ -971,6 +970,7 @@ static int cpuset_add_file(struct dentry dput(dentry); } else error = PTR_ERR(dentry); + up(&dir->d_inode->i_sem); return error; } @@ -1162,7 +1162,6 @@ static struct cftype cft_notify_on_relea .private = FILE_NOTIFY_ON_RELEASE, }; -/* MUST be called with ->d_inode->i_sem held */ static int cpuset_populate_dir(struct dentry *cs_dentry) { int err; @@ -1219,9 +1218,16 @@ static long cpuset_create(struct cpuset err = cpuset_create_dir(cs, name, mode); if (err < 0) goto err; + + /* release cpuset_sem before cpuset_populate_dir() + * because it will down() this new directory's i_sem + * and if we race with another mkdir, + * we might deadlock + */ + up(&cpuset_sem); + err = cpuset_populate_dir(cs->dentry); /* If err < 0, we have a half-filled directory - oh well ;) */ - up(&cpuset_sem); return 0; err: list_del(&cs->sibling); ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Patch] cpusets: fix race in cpuset_add_file() 2004-09-16 15:39 ` Simon Derr @ 2004-09-16 16:03 ` Paul Jackson 2004-09-17 7:22 ` Paul Jackson 1 sibling, 0 replies; 8+ messages in thread From: Paul Jackson @ 2004-09-16 16:03 UTC (permalink / raw) To: Simon Derr; +Cc: akpm, linux-kernel Simon wrote: > However, your remark is welcome, since there is indeed a slight chance of > deadlock with my patch, but it needs 2 mkdirs racing. Glad my confusions led to some good. Let me think about this one a bit. I had it in my brain that the cpuset_sem should be held across the entire cpuset_populate_dir(), as if there would be a problem with another task getting this lock while a directory was half populated. But I don't know if that was a valid concern, or just a superstition on my part. I'll stare at this a bit more, and get back to you, either way. -- I won't rest till it's the best ... Programmer, Linux Scalability Paul Jackson <pj@sgi.com> 1.650.933.1373 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Patch] cpusets: fix race in cpuset_add_file() 2004-09-16 15:39 ` Simon Derr 2004-09-16 16:03 ` Paul Jackson @ 2004-09-17 7:22 ` Paul Jackson 2004-09-17 7:55 ` Simon Derr 1 sibling, 1 reply; 8+ messages in thread From: Paul Jackson @ 2004-09-17 7:22 UTC (permalink / raw) To: Simon Derr; +Cc: akpm, linux-kernel You can continue to ignore this patch, Andrew. I'm still thinking it through with Simon. Here's another possible way to skin this cat, Simon. Instead of adding an inode lock, how about just extending the cpuset_sem window. If we hold cpuset_sem for the entire cpuset_mkdir() operation, then no other cpuset_mkdir can overlap, and there should be no confused overlapping directory creations. This reduces the risks of unrecognized A-B-A deadlocks, and it removes the concern I have that dropping the cpuset_sem before we're done opens the way for more inconsistencies. This needs to be tested before it goes in - there is a non-zero risk that I made a stupid mistake and it locks up or something. Signed-off-by: Paul Jackson <pj@sgi.com> Index: 2.6.9-rc2-mm1/kernel/cpuset.c =================================================================== --- 2.6.9-rc2-mm1.orig/kernel/cpuset.c 2004-09-16 23:46:01.000000000 -0700 +++ 2.6.9-rc2-mm1/kernel/cpuset.c 2004-09-17 00:19:02.000000000 -0700 @@ -1235,7 +1235,6 @@ static long cpuset_create(struct cpuset if (!cs) return -ENOMEM; - down(&cpuset_sem); cs->flags = 0; if (notify_on_release(parent)) set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags); @@ -1256,22 +1255,23 @@ static long cpuset_create(struct cpuset goto err; err = cpuset_populate_dir(cs->dentry); /* If err < 0, we have a half-filled directory - oh well ;) */ - up(&cpuset_sem); return 0; err: list_del(&cs->sibling); - up(&cpuset_sem); kfree(cs); return err; } static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode) { - struct dentry *d_parent = dentry->d_parent; - struct cpuset *c_parent = (struct cpuset *)d_parent->d_fsdata; + struct cpuset *c_parent; + int rc; - /* the vfs holds inode->i_sem already */ - return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR); + down(&cpuset_sem); + c_parent = dentry->d_parent->d_fsdata; + rc = cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR); + up(&cpuset_sem); + return rc; } static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) -- I won't rest till it's the best ... Programmer, Linux Scalability Paul Jackson <pj@sgi.com> 1.650.933.1373 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Patch] cpusets: fix race in cpuset_add_file() 2004-09-17 7:22 ` Paul Jackson @ 2004-09-17 7:55 ` Simon Derr 2004-09-17 9:10 ` Paul Jackson 0 siblings, 1 reply; 8+ messages in thread From: Simon Derr @ 2004-09-17 7:55 UTC (permalink / raw) To: Paul Jackson; +Cc: Simon Derr, akpm, linux-kernel On Fri, 17 Sep 2004, Paul Jackson wrote: > You can continue to ignore this patch, Andrew. I'm still thinking it > through with Simon. > > Here's another possible way to skin this cat, Simon. > > Instead of adding an inode lock, how about just extending the cpuset_sem > window. If we hold cpuset_sem for the entire cpuset_mkdir() operation, > then no other cpuset_mkdir can overlap, and there should be no > confused overlapping directory creations. > no - the inode lock is necessary. don't let my second mail with the deadlock example confuse you : the original problem (i.e the problem my patch fixes) is a race between a cpuset mkdir() and another operation in the newly created directory, for instance just `ls'. the race is: mkdir a/b | ls a/b/cpus | cpuset_add_file(b, "cpus") | vfs_stat() cpuset_get_dentry(b, "cpus") | user_path_walk() lookup_hash(b, "cpus") | path_lookup() cached_lookup(b, "cpus") | link_path_walk() d_alloc(b, "cpus") | do_lookup() | real_lookup() | down(b->i_sem); | d_lookup(b, "cpus"); | d_alloc(b, "cpus"); The result is that `ls' and `mkdir' both create a dentry for a/b/cpus, and the dentry created by `ls' is bogus since it does not point to the cpuset data. The proper way to prevent this is to lock the i_sem of directory b. This can be done in cpuset_populate_dir(), in cpuset_add_file(), or cpuset_get_dentry(). The similar piece of code in sysfs does it in add_file(). If your are not convinced try the following script. Without my patch it triggers the bug in a few seconds. Simon. #! /bin/bash a() { name=$1 echo dir is /dev/cpuset/$name while :; do mkdir /dev/cpuset/$name if ! test -r /dev/cpuset/$name/cpus; then echo missing /dev/cpuset/$name/cpus exit 1 fi rmdir /dev/cpuset/$name done } b() { name=$1 while :; do test -r /dev/cpuset/$name/cpus done } p=$$ b $p & a $p ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Patch] cpusets: fix race in cpuset_add_file() 2004-09-17 7:55 ` Simon Derr @ 2004-09-17 9:10 ` Paul Jackson 0 siblings, 0 replies; 8+ messages in thread From: Paul Jackson @ 2004-09-17 9:10 UTC (permalink / raw) To: Simon Derr; +Cc: akpm, linux-kernel Simon wrote: > The result is that `ls' and `mkdir' both create a dentry for a/b/cpus Ouch - persuasive - well presented - thanks. On the flip side, I am not finding any firm basis in the concerns I had that led me down the other path. Give me a few hours to run this through a bit of unit testing on my side, then I will likely endorse your patch. I have two minor patches on my side: 1) add CONFIG_CPUSETS=y to sn2_defconfig, and 2) remove some more casts of (void *)d_fsdata. If it's ok by you, and I don't have any more questions, I will send all three along to Andrew, as a set, in a few hours. Good work, Simon. -- I won't rest till it's the best ... Programmer, Linux Scalability Paul Jackson <pj@sgi.com> 1.650.933.1373 ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2004-09-17 9:12 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-09-16 1:29 [Patch] cpusets: document proc status allowed fields Paul Jackson 2004-09-16 14:01 ` [Patch] cpusets: fix race in cpuset_add_file() Simon Derr 2004-09-16 14:55 ` Paul Jackson 2004-09-16 15:39 ` Simon Derr 2004-09-16 16:03 ` Paul Jackson 2004-09-17 7:22 ` Paul Jackson 2004-09-17 7:55 ` Simon Derr 2004-09-17 9:10 ` Paul Jackson
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.