From: Linus Torvalds <torvalds@linux-foundation.org>
To: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>,
Borislav Petkov <petkovbb@googlemail.com>,
David Airlie <airlied@linux.ie>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Greg KH <greg@kroah.com>, Al Viro <viro@ZenIV.linux.org.uk>
Subject: Re: drm_vm.c:drm_mmap: possible circular locking dependency detected (was: Re: Linux 2.6.33-rc2 - Merry Christmas ...)
Date: Thu, 31 Dec 2009 11:04:48 -0800 (PST) [thread overview]
Message-ID: <alpine.LFD.2.00.0912311043330.11961@localhost.localdomain> (raw)
In-Reply-To: <m1fx6rtu31.fsf@fess.ebiederm.org>
On Thu, 31 Dec 2009, Eric W. Biederman wrote:
> >
> > - hibernate ends up with the sequence: _cpu_down (cpu_hotplug.lock) -> ..
> > kref_put .. -> sysfs_addrm_start (sysfs_mutex)
> >
> > Again, nothing suspicious or "bad", and this part of the dependency
> > chain has nothing to do with the DRM code itself.
>
> kobject_del with a lock held scares me.
I would not object at _all_ if sysfs fixed the locking here instead of in
filldir.
The problem is that releasing objects (with kref_put() and friends) is
something that is _commonly_ done with various locks held.
Btw, that "cpu_down()" is by no means the only case. I would suggest you
just google for
sysfs_mutex lockdep
and you'll find a _lot_ of cases, most of them not involving drm at all,
but ext4 and btrfs.
(Side note: almost all of them tend to _also_ have mmap_sem in the chain:
that's usually the thing that "closes the deal").
> There is a possible deadlock (that lockdep is ignorant of) if you hold
> a lock over sysfs_deactivate() and if any sysfs file takes that lock.
>
> I won't argue with a claim of inconvenient locking semantics here, and
> this is different to the problem you are seeing (except that fixing this
> problem would happen to fix the filldir issue).
I suspect that filldir is almost always implicated because mmap_sem is so
hard to do just one way: both page faulting and mmap have it held, and so
a lot of locks need to be gotten _after_ it, while filldir very often has
the exact reverse requirement.
So that's why filldir is kind of special (and the fundamental _reason_ it
is special is exactly because pretty much all other VFS operations work
with generic caches, and the actual filesystem only fills in the caches,
it doesn't copy to user space directly while holding any locks - although
ioctl's sometimes have the same issue as filldir for all the same
reasons).
Anyway, I'm in _no_ way saying that you need to break it at filldir: the
reason I pick on filldir is because I hate it, and think that it's a
really annoying special case at the VFS level. But from a sysfs
standpoint, I could well see that there are worse problems than that kind
of annoying VFS problem.
So if you can break it at that kref_put layer (which leads to releasing a
sysfs object etc), then that would be great. In fact, it would be better,
since kref_put and friends are in many ways "more fundamental" than some
filldir special case that we _could_ fix in other ways.
> The cheap fix here is mostly a matter of grabbing a reference to the
> sysfs_dirent and then revalidating that the reference is still useful
> after we reacquire the sysfs_mutex. If not we already have the code for
> restarting from just an offset. We just don't want to use it too much as
> that will give us O(n^2) times for sysfs readdir.
Well, the _trivial_ fix is to just move the mutex_lock/unlock _inside_ the
loop instead of of outside. Something like the appended might just work,
and is the really stupid approach.
Totally untested. And it will do a _lot_ more sysfs mutex accesses, since
now it will lock/unlock around each entry we return.
A smarter thing to do would probably be to rewrite the 's_sibling' search
to instead insert a fake entry in the list, so that we don't have to
traverse the s_sibling list every time for each entry (which is O(n**2) in
size of the directory, and just generally horribly evil and crap code).
Linus
---
fs/sysfs/dir.c | 34 +++++++++++++++++++---------------
1 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index f05f230..2d0fd42 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -847,29 +847,33 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
filp->f_pos++;
}
- if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) {
- mutex_lock(&sysfs_mutex);
+ while ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) {
+ const char * name;
+ int len, err;
+ mutex_lock(&sysfs_mutex);
/* Skip the dentries we have already reported */
pos = parent_sd->s_dir.children;
while (pos && (filp->f_pos > pos->s_ino))
pos = pos->s_sibling;
- for ( ; pos; pos = pos->s_sibling) {
- const char * name;
- int len;
+ /* This is ok even with 'pos == NULL' */
+ sysfs_get_active(pos);
+ mutex_unlock(&sysfs_mutex);
+ if (!pos) {
+ filp->f_pos = INT_MAX;
+ break;
+ }
- name = pos->s_name;
- len = strlen(name);
- filp->f_pos = ino = pos->s_ino;
+ name = pos->s_name;
+ len = strlen(name);
+ filp->f_pos = ino = pos->s_ino;
- if (filldir(dirent, name, len, filp->f_pos, ino,
- dt_type(pos)) < 0)
- break;
- }
- if (!pos)
- filp->f_pos = INT_MAX;
- mutex_unlock(&sysfs_mutex);
+ err = filldir(dirent, name, len, filp->f_pos, ino, dt_type(pos));
+ sysfs_put_active(pos);
+
+ if (err < 0)
+ break;
}
return 0;
}
next prev parent reply other threads:[~2009-12-31 19:05 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-12-24 22:00 Linux 2.6.33-rc2 - Merry Christmas Linus Torvalds
2009-12-25 10:27 ` -tip: origin tree boot crash Ingo Molnar
2009-12-25 19:49 ` Dmitry Torokhov
2009-12-26 20:19 ` Len Brown
2009-12-26 20:17 ` Len Brown
2009-12-27 4:20 ` Len Brown
2009-12-28 9:44 ` Ingo Molnar
2009-12-28 12:01 ` Ingo Molnar
2009-12-28 15:02 ` Paul Rolland
2009-12-28 16:15 ` Paul Rolland
2009-12-28 16:53 ` Paul Rolland
2009-12-28 20:17 ` Dmitry Torokhov
2009-12-30 6:14 ` Len Brown
2009-12-30 7:13 ` Paul Rolland
2009-12-30 6:19 ` [PATCH] wmi: check find_guid() return value to prevent oops Len Brown
2009-12-30 6:21 ` [PATCH] dell-wmi: sys_init_module: 'dell_wmi'->init suspiciously returned 21, it should follow 0/-E convention Len Brown
2009-12-25 13:10 ` Linux 2.6.33-rc2 - Blank screen for Intel KMS Miguel Calleja
2009-12-29 9:50 ` Miguel Calleja
2009-12-29 14:01 ` Rafael J. Wysocki
2009-12-25 20:00 ` Linux 2.6.33-rc2 - Merry Christmas Borislav Petkov
2009-12-25 21:50 ` Borislav Petkov
2009-12-26 6:00 ` Jesse Barnes
2009-12-26 8:02 ` Borislav Petkov
2009-12-26 9:36 ` EHCI resume sysfs duplicates (was: Re: Linux 2.6.33-rc2 - Merry Christmas ...) Borislav Petkov
2009-12-26 9:45 ` drm_vm.c:drm_mmap: possible circular locking dependency detected " Borislav Petkov
2009-12-28 0:40 ` KOSAKI Motohiro
2009-12-30 21:10 ` Linus Torvalds
2009-12-30 21:34 ` Eric W. Biederman
2009-12-30 22:03 ` Linus Torvalds
2009-12-31 8:40 ` Eric W. Biederman
2009-12-31 19:04 ` Linus Torvalds [this message]
2010-01-01 13:58 ` [PATCH] sysfs: Cache the last sysfs_dirent to improve readdir scalability Eric W. Biederman
2010-01-01 15:33 ` Borislav Petkov
2010-01-01 18:56 ` Linus Torvalds
2010-01-01 22:43 ` [PATCH] sysfs: Cache the last sysfs_dirent to improve readdir scalability v2 Eric W. Biederman
2010-01-01 23:10 ` Linus Torvalds
2010-01-02 5:59 ` Greg KH
2010-01-02 15:40 ` Borislav Petkov
2010-01-01 15:16 ` drm_vm.c:drm_mmap: possible circular locking dependency detected (was: Re: Linux 2.6.33-rc2 - Merry Christmas ...) Eric W. Biederman
2010-01-02 2:59 ` drm_vm.c:drm_mmap: possible circular locking dependency detected Tejun Heo
2010-01-02 21:37 ` [PATCH] sysfs: Add lockdep annotations for the sysfs active reference Eric W. Biederman
2010-01-03 0:02 ` Tejun Heo
2010-01-17 16:26 ` Ming Lei
2010-01-17 17:18 ` Eric W. Biederman
2010-01-17 18:03 ` Dominik Brodowski
2010-01-02 21:49 ` drm_vm.c:drm_mmap: possible circular locking dependency detected Eric W. Biederman
2010-01-03 0:32 ` Tejun Heo
2010-01-03 2:06 ` Eric W. Biederman
2010-01-03 5:01 ` Tejun Heo
2010-01-03 5:38 ` Eric W. Biederman
2010-01-03 6:05 ` Tejun Heo
2010-01-03 7:47 ` Dmitry Torokhov
2010-01-03 10:57 ` Eric W. Biederman
2010-01-03 11:14 ` Eric W. Biederman
2010-01-04 19:16 ` Dmitry Torokhov
2010-01-04 18:57 ` Dmitry Torokhov
2010-01-04 19:43 ` Eric W. Biederman
2010-01-04 21:12 ` Dmitry Torokhov
2010-01-04 23:09 ` Tejun Heo
2009-12-31 8:40 ` drm_vm.c:drm_mmap: possible circular locking dependency detected (was: Re: Linux 2.6.33-rc2 - Merry Christmas ...) Eric W. Biederman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.LFD.2.00.0912311043330.11961@localhost.localdomain \
--to=torvalds@linux-foundation.org \
--cc=airlied@linux.ie \
--cc=ebiederm@xmission.com \
--cc=greg@kroah.com \
--cc=kosaki.motohiro@jp.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=petkovbb@googlemail.com \
--cc=viro@ZenIV.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox