Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1613770
| From | Nicolai Stange <nicstange@gmail.com> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | Re: deadlock in synchronize_srcu() in debugfs? |
| Date | 2017-03-31 11:10 +0200 |
| Message-ID | <tr0Jc-2AS-45@gated-at.bofh.it> (permalink) |
| References | (2 earlier) <tpBtw-7vp-3@gated-at.bofh.it> <tqCQy-2Ql-25@gated-at.bofh.it> <tqD9U-2XU-21@gated-at.bofh.it> <tqFv4-4UX-1@gated-at.bofh.it> <tqGhs-5vQ-19@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
On Thu, Mar 30 2017, Johannes Berg wrote: > On Thu, 2017-03-30 at 12:27 +0200, Nicolai Stange wrote: >> So, please correct me if I'm wrong, there are two problems with >> indefinitely blocking debugfs files' fops: >> >> 1. The one which actually hung your system: >> An indefinitely blocking debugfs_remove() while holding a lock. >> Other tasks attempting to grab that same lock get stuck as well. >> >> 2. The other one you've found, namely that the locking granularity is >> too coarse: a debugfs_remove() would get blocked by unrelated >> files' >> pending fops. > > No, this isn't really an accurate description of the two problems. > >> AFAICS, the first one can't get resolved by simply refining the >> blocking granularity: a debugfs_remove() on the indefinitely blocking >> file would still block as well. > > Correct. > > The first problem - the one I ran into - is the following: > > 1) > A given debugfs file's .read() was waiting for some event to happen > (being a blocking file), and I was trying to debugfs_remove() some > completely unrelated file, this got stuck. I got it now. I was missing the "completely unrelated file" part. (Admittedly, a related file would have made no sense at all -- the remover would have been responsible to cancel any indefinite blocking in there, as you said). > Due to me holding a lock while doing this debugfs_remove(), other tasks > *also* got stuck, but that's just a sub-problem - having the > debugfs_remove() of an unrelated file get stuck would already have been > a problem - the fact that other tasks also got stuck was just an > additional wrinkle. > > Mind - this is a livelock of sorts - if the debugfs file will ever make > progress, the system can recover. > > 2) > There's a complete deadlock situation if this happens: > > CPU1 CPU2 > > debugfs_file_read(file="foo") mutex_lock(&M); > srcu_read_lock(&debugfs_srcu); debugfs_remove(file="bar") > mutex_lock(&M); synchronize_srcu(&debugfs_srcu) > > This is intrinsically unrecoverable. Let's address this in a second step. > This is the core of the problem really - that you're tying completely > unrelated processes together. > > Therefore, to continue using SRCU in this way means that you have to > disallow blocking debugfs files. There may not be many of those, but > any single one of them would be a problem. > > If we stop using SRCU this way we can discuss how we can fix it - but > anything more coarse grained than per-file (which really makes SRCU > unsuitable) would still have the same problem one way or another. And > we haven't even addressed the deadlock situation (2 above) either. > >> When I did this, per-file reader/writer locks actuallt came to my >> mind first. The problem here is that debugfs_use_file_start() must >> grab the lock first and check whether the file has been deleted in >> the meanwhile. But as it stands, there's nothing that would guarantee >> the existence of the lock at the time it's to be taken. > > That seems like a strange argument to me - something has to exist for a > process to be able to look up the file, and currently the proxy also > has to exist? No, the proxies are created at file _open_ time and installed at the struct file. Rationale: there are potentially many debugfs files with only few of them opened at a time and a proxy, i.e. a struct file_operations, is quite large. > So when a file is created you can allocate the proxy for it, and if you > can look up the proxy object - perhaps even using plain RCU - then you > also have the lock? IOW, instead of storing just the real_fops in > d_fsdata, you can store a small object that holds a lock and the > real_fops. You can always access that object, and lock it, but the > real_fops inside it might eventually end up NULL which you handle > through proxying. No? As said, there isn't always a proxy object around. Of course, attaching some sort of lock on a per-file basis should be doable. I just refrained from doing it so far (and resorted to SRCU instead) because I wasn't aware of those indefinite blockers and wanted to avoid the additional complexity (namely avoiding use-after-frees on that lock). I'll work out a solution this weekend and send some RFC patches then. Thanks for your clarifications! Nicolai
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Re: deadlock in synchronize_srcu() in debugfs? Nicolai Stange <nicstange@gmail.com> - 2017-03-30 09:40 +0200
Re: deadlock in synchronize_srcu() in debugfs? Johannes Berg <johannes@sipsolutions.net> - 2017-03-30 10:00 +0200
Re: deadlock in synchronize_srcu() in debugfs? Nicolai Stange <nicstange@gmail.com> - 2017-03-30 12:30 +0200
Re: deadlock in synchronize_srcu() in debugfs? Johannes Berg <johannes@sipsolutions.net> - 2017-03-30 13:20 +0200
Re: deadlock in synchronize_srcu() in debugfs? Nicolai Stange <nicstange@gmail.com> - 2017-03-31 11:10 +0200
Re: deadlock in synchronize_srcu() in debugfs? Johannes Berg <johannes@sipsolutions.net> - 2017-03-31 11:50 +0200
csiph-web