vfs-scale git tree update
Git tree is here:
git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin.git
Branch is: vfs-scale-working
Head is: b3e19d924b6eaf2ca7d22cba99a517c5171007b6
Changes since last posting:
* Implemented Linus' suggestions:
- Switch the filesystem methods in one hit rather than having _rcu variants. This avoids a lot of cruft from core code.
- Implement filesystem rcu-walk aware conversions in seperate patches after the APIs are changed, making bisectability better.
- Change dentry_memcmp to dentry_cmp
- Rework the way ->d_revalidate is handled to be simpler.
* Fixed configfs bug caused by switching d_op on live dentry.
* Leave d_revalidate filesystem changes out for now. The sysfs one in particular seems to have been causing a funny regression.
* Bit more tweaking of changelogs documentation and comments.
* Passes ltp, xfstests, dbench stressing over nfs, and some of my own racer tests on a couple of filesystems. Needs wider testing.
Quoted 19 lines · Nick Piggin
Git tree is here:
git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin.gitBranch is: vfs-scale-working
Head is:
b3e19d924b6eaf2ca7d22cba99a517c5171007b6Changes since last posting:
* Implemented Linus' suggestions:
- Switch the filesystem methods in one hit rather than having_rcuvariants. This avoids a lot of cruft from core code.
- Implement filesystem rcu-walk aware conversions in seperate patches after the APIs are changed, making bisectability better.
- Changedentry_memcmptodentry_cmp
- Rework the way ->d_revalidate is handled to be simpler.* Fixed configfs bug caused by switching
d_opon live dentry.
Quoted 7 lines
* Leave
d_revalidatefilesystem changes out for now. The sysfs one in particular seems to have been causing a funny regression.* Bit more tweaking of changelogs documentation and comments.
* Passes ltp, xfstests, dbench stressing over nfs, and some of my own racer tests on a couple of filesystems. Needs wider testing.
FYI, when using this code, as merged by Linus, I hit the BUG_ON() at the beginning of d_set_d_op() when it's called by autofs4_dir_mkdir(). I managed to work around it by just commenting out those BUG_ON() calls but it's something that ought to get addressed properly. Console grab below.
I first saw it with a kernel built from a merge of latest XFS from oss.sgi.com with e54be894eae1... from Linus, but I have now verified I get the same problem using Linus' tree alone.
-Alex
Commit: e54be894eae10eca9892e965cc9532f5d5a11767
. . .
Starting ypbind
done
Starting smartd
done
Starting automount ------------[ cut here ]------------ kernel BUG at /home/aelder/xfs/xfs/fs/dcache.c:1358! invalid opcode: 0000 [#1] SMP
last sysfs
file: /sys/devices/pci0000:00/0000:00:1e.0/0000:08:01.0/local_cpus CPU 1
Modules linked in: autofs4 binfmt_misc nfs lockd nfs_acl auth_rpcgss
sunrpc mperf ib_ipoib ib_cm ib_sa ipv6 ib_uverbs ib_umad iw_cxgb3 cxgb3 mdio mlx4_ib mlx4_core microcode fuse loop dm_mod sr_mod cdrom mptfc ib_mthca scsi_transport_fc scsi_tgt ib_mad ib_core e1000e i5k_amb shpchp i5000_edac rtc_cmos pci_hotplug edac_core iTCO_wdt usb_storage ioatdma iTCO_vendor_support tpm_tis tpm container tpm_bios button dca i2c_i801 i2c_core rtc_core rtc_lib serio_raw pcspkr joydev sg usbhid hid uhci_hcd ehci_hcd sd_mod crc_t10dif usbcore ext3 jbd mbcache piix edd xfs exportfs fan thermal processor thermal_sys hwmon ide_generic ide_core sata_nv megaraid_sas mptsas mptscsih mptbase scsi_transport_sas ata_piix ahci libahci libata scsi_mod
Pid: 3848, comm: automount Not tainted 2.6.37-alex #2 X7DGT-INF/AltixXE310
RIP: 0010:[<ffffffff810e54bf>] [<ffffffff810e54bf>] d_set_d_op+0xb/0x58 RSP: 0018:ffff88011e465e18 EFLAGS: 00010282 RAX: ffff88010c783e00 RBX: ffff88010a069800 RCX: 0000000000000013 RDX: 0000000000000000 RSI: ffffffffa02e6e80 RDI: ffff88010c78ccc0 RBP: ffff88011e465e18 R08: ffff88010a069800 R09: ffff88012268f800 R10: ffff88011185f007 R11: ffff88011e465e48 R12: ffff88010c78ccc0 R13: ffff88010a069800 R14: ffff88011c05fda0 R15: ffff8801269bb288 FS: 00007fd2db210950(0000) GS:ffff8800cfc80000(0000)
knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fd2dc37de30 CR3: 000000010a55a000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process automount (pid: 3848, threadinfo ffff88011e464000, task ffff88010aacc1c0)
Stack: ffff88011e465e58 ffffffffa02e3fb7 ffff88011e465e38 0000000000000000 ffff8801269bb288 000000000000016d ffff88010c78ccc0 00007fd2dc5c8216 ffff88011e465e88 ffffffff810dee5d 0000000000000000 ffff88010c78ccc0 Call Trace: [<ffffffffa02e3fb7>] autofs4_dir_mkdir+0x124/0x19b [autofs4] [<ffffffff810dee5d>] vfs_mkdir+0x7e/0xd6 [<ffffffff810e151a>] sys_mkdirat+0x91/0xe1 [<ffffffff810e157d>] sys_mkdir+0x13/0x15 [<ffffffff8100293b>] system_call_fastpath+0x16/0x1b Code: 89 f7 e8 29 75 ff ff 4c 89 ff e8 d3 ce 1e 00 5a 5b 44 89 e0 41 5c
41 5d 41 5e 41 5f c9 c3 90 90 48 83 7f 60 00 55 48 89 e5 74 04 <0f> 0b eb fe 66 f7 07 00 f0 74 04 0f 0b eb fe 48 85 f6 48 89 77 RIP [<ffffffff810e54bf>] d_set_d_op+0xb/0x58
RSP <ffff88011e465e18>
---[ end trace d78cc1e6e1dedc2f ]---
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.
Yeah, removing the BUG_ON() isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.
Possibly the thing could be relaxed to allow setting the _same_ d_op pointer, ie do something like
if (dentry->d_op == op)
return;
at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
The fact that autofs4 does "d_add()" before it sets the d_ops (or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.
Does it make any difference if you move the various d_add() calls down to the end of the functions to when the "dentry" has really been instantiated?
Linus
Quoted 12 lines · Linus Torvalds
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.Yeah, removing the
BUG_ON()isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.
Quoted 8 lines
Possibly the thing could be relaxed to allow setting the _same_
d_oppointer, ie do something likeif (dentry->d_op == op) return;at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
That's easy enough, but it seems everybody else ensures this gets done just once per dentry, and it would be nice to preserve that "tightness" if possible.
Quoted 4 lines
The fact that autofs4 does "
d_add()" before it sets thed_ops(or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.
Agreed.
Quoted 3 lines
Does it make any difference if you move the various
d_add()calls down to the end of the functions to when the "dentry" has really been instantiated?
Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
-Alex
[ Added Ian to cc - the BUG_ON() in d_set_d_op() triggers on autofs4, see lkml thread for more details if you care ]
Quoted 5 lines · Alex Elder
Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
You're right - without looking closer or thinking about it any more, I was thinking mkdir etc would create the new dentry, but it can easily be a pre-existing negative one. So it's not like mkdir is always going to be something new that can just be initialized.
So yeah, no race or anything like that required - just regular acceses.
That said, if we make sure that the d_op gets cleared (or the dentry dropped) when something turns negative, and a negative lookup never sets d_op, it should all basically work.
Can you figure out the exact sequence that causes this? Is it enough to just mount something once?
Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 15 lines · Linus Torvalds
[ Added Ian to cc - the
BUG_ON()ind_set_d_op()triggers on autofs4, see lkml thread for more details if you care ]Quoted 5 lines · Alex Elder
Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
You're right - without looking closer or thinking about it any more, I was thinking mkdir etc would create the new dentry, but it can easily be a pre-existing negative one. So it's not like mkdir is always going to be something new that can just be initialized.
Quoted 8 lines
So yeah, no race or anything like that required - just regular acceses.
That said, if we make sure that the
d_opgets cleared (or the dentry dropped) when something turns negative, and a negative lookup never setsd_op, it should all basically work.Can you figure out the exact sequence that causes this? Is it enough to just mount something once?
Doh, sorry I probably didn't re-test autofs4 since putting that BUG_ON in there. Now it's trivial to revert the d_set_d_op function to the same raciness that was "allowed" before (simply by resetting the d_flags bits). There is no new fundamental race that the patch introduced there... But I think it is much cleaner to just fix up all filesystems, and will potentially close obscure races.
Often the best way is to just set the same d_ops for negative and positive dentries, and have the operations handle both cases.
Ian?
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 26 lines · Alex Elder
Quoted 12 lines · Linus Torvalds
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.Yeah, removing the
BUG_ON()isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.Quoted 8 lines
Possibly the thing could be relaxed to allow setting the _same_
d_oppointer, ie do something likeif (dentry->d_op == op) return;at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
That's easy enough, but it seems everybody else ensures this gets done just once per dentry, and it would be nice to preserve that "tightness" if possible.
Quoted 6 lines
Quoted 4 lines
The fact that autofs4 does "
d_add()" before it sets thed_ops(or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.Agreed.
Isn't the parent i_mutex held during mkdir()?
Still the order can be changed, of course.
Quoted 9 lines
Quoted 4 lines
Does it make any difference if you move the various
d_add()calls down to the end of the functions to when the "dentry" has really been instantiated?Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Quoted 8 lines
-Alex
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Quoted 27 lines · Ian Kent
Quoted 26 lines · Alex Elder
Quoted 12 lines · Linus Torvalds
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.Yeah, removing the
BUG_ON()isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.Quoted 8 lines
Possibly the thing could be relaxed to allow setting the _same_
d_oppointer, ie do something likeif (
dentry->d_op== op)
return;at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
That's easy enough, but it seems everybody else ensures this gets done just once per dentry, and it would be nice to preserve that "tightness" if possible.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
The fact that autofs4 does "
d_add()" before it sets thed_ops(or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.Agreed.
Isn't the parent
i_mutexheld duringmkdir()?
Yes but there are concurrency cases allowed without i_mutex.
Lookup, for example, which ends up touching d_revalidate and when dropping the dentry, possibly d_delete.
There seems no benefit to allowing switch of d_ops on a live dentry, and many downsides. So the rule should just be that it is not allowed.
Quoted 7 lines
Still the order can be changed, of course.
Quoted 5 lines
Quoted 4 lines
Does it make any difference if you move the various
d_add()calls down to the end of the functions to when the "dentry" has really been instantiated?
Quoted 7 lines
Quoted 4 lines
Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
How about negative dentries? They should be set up with d_ops upon allocation, preferably if your operations can handle negative dentries.
Thanks,
Nick
Quoted 2 lines · Ian Kent
Isn't the parent
i_mutexheld duringmkdir()?
Yes, but a lookup that hits in the dentry cache won't actually take the parent mutex.
So as far as I can tell, doing the "d_add()" before setting d_op can result in another CPU coming in and seeing the newly added dentry before d_op has actually been initialized. Exactly because it will do the dentry lookup without holding any mutex.
Of course, it's a very small window, so it probably doesn't matter in practice.
Quoted 7 lines
Quoted 4 lines
Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Alex, care to test just removing the d_set_d_op() call from autofs4_lookup()?
(That code is a bit scary, though - it explicitly makes it a negative dentry with a d_instantiate(dentry, NULL), and then hides the inode information away separately. Scary scary)
Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 42 lines · Ian Kent
Quoted 26 lines · Alex Elder
Quoted 12 lines · Linus Torvalds
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.Yeah, removing the
BUG_ON()isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.Quoted 8 lines
Possibly the thing could be relaxed to allow setting the _same_
d_oppointer, ie do something likeif (dentry->d_op == op) return;at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
That's easy enough, but it seems everybody else ensures this gets done just once per dentry, and it would be nice to preserve that "tightness" if possible.
Quoted 6 lines
Quoted 4 lines
The fact that autofs4 does "
d_add()" before it sets thed_ops(or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.Agreed.
Isn't the parent
i_mutexheld duringmkdir()?
Still the order can be changed, of course.Quoted 5 lines
Quoted 4 lines
Does it make any difference if you move the various
d_add()calls down to the end of the functions to when the "dentry" has really been instantiated?
Quoted 7 lines
Quoted 4 lines
Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Could you try this patch please.
autofs4 - dont set dentry op in ->lookup()
From: Ian Kent <[email protected]>
With the introduction of the vfs-scale patch series setting dentry operations more than once (or changing them) triggers a BUG_ON().
Also, move the d_add() in ->symlink() and ->mkdir() to the end of the function.
---
fs/autofs4/root.c | 19 ++++--------------- 1 files changed, 4 insertions(+), 15 deletions(-)
fs/autofs4/root.c +4 -15
@@ -568,19 +568,6 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s ino =autofs4_dentry_ino (dentry); }else {/* -* Mark the dentry incomplete but don't hash it. We do this -* to serialize our inode creation operations (symlink and -* mkdir) which prevents deadlock during the callback to -* the daemon. Subsequent user space lookups for the same -* dentry are placed on the wait queue while the daemon -* itself is allowed passage unresticted so the create -* operation itself can then hash the dentry. Finally, -* we check for the hashed dentry and return the newly -* hashed dentry. -*/ -d_set_d_op (dentry, &autofs4_root_dentry_operations); - -/* * And we need to ensure that the same dentry is used for * all following lookup calls until it is hashed so that * the dentry flags are persistent throughout the request.
@@ -714,7 +701,6 @@ static int autofs4_dir_symlink(struct inode *dir,kfree (ino);return -ENOMEM ; } -d_add (dentry, inode);if (dir == dir->i_sb->s_root->d_inode)d_set_d_op (dentry, &autofs4_root_dentry_operations);
@@ -732,6 +718,8 @@ static int autofs4_dir_symlink(struct inode *dir, ino->u.symlink = cp; dir->i_mtime =CURRENT_TIME ; +d_add (dentry, inode); +return 0 ; }
@@ -849,7 +837,6 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)kfree (ino);return -ENOMEM ; } -d_add (dentry, inode);if (dir == dir->i_sb->s_root->d_inode)d_set_d_op (dentry, &autofs4_root_dentry_operations);
@@ -866,6 +853,8 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)inc_nlink (dir); dir->i_mtime =CURRENT_TIME ; +d_add (dentry, inode); +return 0 ; }
Quoted 19 lines · Linus Torvalds
Quoted 2 lines · Ian Kent
Isn't the parent
i_mutexheld duringmkdir()?Yes, but a lookup that hits in the dentry cache won't actually take the parent mutex.
So as far as I can tell, doing the "
d_add()" before settingd_opcan result in another CPU coming in and seeing the newly added dentry befored_ophas actually been initialized. Exactly because it will do the dentry lookup without holding any mutex.Of course, it's a very small window, so it probably doesn't matter in practice.
Quoted 5 lines
Quoted 4 lines
Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Quoted 8 lines
Quoted 2 lines
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Alex, care to test just removing the
d_set_d_op()call fromautofs4_lookup()?(That code is a bit scary, though - it explicitly makes it a negative dentry with a
d_instantiate(dentry, NULL), and then hides the inode information away separately. Scary scary)
Yeah, but the expire to mount races with autofs are difficult to handle and this approach has worked well under heavy stress testing. It's true that this would almost certainly be bad for a file system that supported a full range of functionality but that's not so for autofs.
Quoted 6 lines
Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 42 lines · Ian Kent
Quoted 26 lines · Alex Elder
Quoted 12 lines · Linus Torvalds
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.Yeah, removing the
BUG_ON()isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.Quoted 8 lines
Possibly the thing could be relaxed to allow setting the _same_
d_oppointer, ie do something likeif (dentry->d_op == op) return;at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
That's easy enough, but it seems everybody else ensures this gets done just once per dentry, and it would be nice to preserve that "tightness" if possible.
Quoted 6 lines
Quoted 4 lines
The fact that autofs4 does "
d_add()" before it sets thed_ops(or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.Agreed.
Isn't the parent
i_mutexheld duringmkdir()?
Still the order can be changed, of course.Quoted 5 lines
Quoted 4 lines
Does it make any difference if you move the various
d_add()calls down to the end of the functions to when the "dentry" has really been instantiated?
Quoted 8 lines
Quoted 4 lines
Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
for 9p I did the other way round. lookup now set the dentry op for both negative and positive dentries and rest of the place we dropped d_set_d_op (b8b80cf37c7f0e32729262f805bc0fa81c3e9d12 have the details)
-aneesh
Quoted 48 lines · Aneesh Kumar K. V
Quoted 47 lines · Ian Kent
Quoted 26 lines · Alex Elder
Quoted 12 lines · Linus Torvalds
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.Yeah, removing the
BUG_ON()isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.Quoted 8 lines
Possibly the thing could be relaxed to allow setting the _same_
d_oppointer, ie do something likeif (dentry->d_op == op) return;at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
That's easy enough, but it seems everybody else ensures this gets done just once per dentry, and it would be nice to preserve that "tightness" if possible.
Quoted 6 lines
Quoted 4 lines
The fact that autofs4 does "
d_add()" before it sets thed_ops(or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.Agreed.
Isn't the parent
i_mutexheld duringmkdir()?
Still the order can be changed, of course.Quoted 9 lines
Quoted 4 lines
Does it make any difference if you move the various
d_add()calls down to the end of the functions to when the "dentry" has really been instantiated?Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Quoted 7 lines
Quoted 3 lines
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
for 9p I did the other way round. lookup now set the dentry op for both negative and positive dentries and rest of the place we dropped
d_set_d_op(b8b80cf37c7f0e32729262f805bc0fa81c3e9d12have the details)
Sadly I can't do that.
For now I need to avoid calls to ->d_revalidate() as much as possible to reduce a potential deadlock and have access to the flags of the negative dentry (during create) for the purpose of blocking concurrent walks.
But, if all goes well, later changes will see the autofs ->d_revalidate() gone and consequently the potential deadlock gone as well.
Ian
Quoted 25 lines · Ian Kent
Quoted 24 lines · Linus Torvalds
Quoted 2 lines · Ian Kent
Isn't the parent
i_mutexheld duringmkdir()?Yes, but a lookup that hits in the dentry cache won't actually take the parent mutex.
So as far as I can tell, doing the "
d_add()" before settingd_opcan result in another CPU coming in and seeing the newly added dentry befored_ophas actually been initialized. Exactly because it will do the dentry lookup without holding any mutex.Of course, it's a very small window, so it probably doesn't matter in practice.
Quoted 7 lines
Quoted 4 lines
Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Alex, care to test just removing the
d_set_d_op()call fromautofs4_lookup()?
Quoted 8 lines
Quoted 3 lines
(That code is a bit scary, though - it explicitly makes it a negative dentry with a
d_instantiate(dentry, NULL), and then hides the inode information away separately. Scary scary)Yeah, but the expire to mount races with autofs are difficult to handle and this approach has worked well under heavy stress testing. It's true that this would almost certainly be bad for a file system that supported a full range of functionality but that's not so for autofs.
I think I have to partly take this back.
With Nick's recent vfs-scale patches this may not be OK any more since the dcache_lock has gone away and, at first glance, it looks like the added autofs4_lock spin lock doesn't provide the needed protection.
Ian
Quoted 48 lines · Ian Kent
Quoted 47 lines · Ian Kent
Quoted 26 lines · Alex Elder
Quoted 12 lines · Linus Torvalds
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.Yeah, removing the
BUG_ON()isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.Quoted 8 lines
Possibly the thing could be relaxed to allow setting the _same_
d_oppointer, ie do something likeif (dentry->d_op == op) return;at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
That's easy enough, but it seems everybody else ensures this gets done just once per dentry, and it would be nice to preserve that "tightness" if possible.
Quoted 6 lines
Quoted 4 lines
The fact that autofs4 does "
d_add()" before it sets thed_ops(or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.Agreed.
Isn't the parent
i_mutexheld duringmkdir()?
Still the order can be changed, of course.Quoted 9 lines
Quoted 4 lines
Does it make any difference if you move the various
d_add()calls down to the end of the functions to when the "dentry" has really been instantiated?Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Quoted 4 lines
Quoted 2 lines
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Could you try this patch please.
OK, sorry for the delay. I tried the patch. I applied it against 4162cf64973df51fc885825bc9ca4d055891c49f, which is the linus/master branch I had on hand. This time I got a different failure due to a null pointer dereference. Console capture below. I can log in still but the boot sequence never got to the login prompt on the console as it normally does.
-Alex
Quoted 1 line
autofs4 - dont set dentry op in ->lookup()
. . .
Starting smartd
done
Starting network time protocol daemon (NTPD)
done
Starting automount BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
IP: [<ffffffffa0296744>] autofs4_lookup+0x3dd/0x4a7 [autofs4] PGD 0
Oops: 0000 [#1] SMP last sysfs file: /sys/devices/pci0000:00/0000:00:1e.0/0000:08:01.0/local_cpus CPU 2 Modules linked in: autofs4 binfmt_misc nfs lockd nfs_acl auth_rpcgss
sunrpc ib_ipoib ib_cm ib_sa ipv6 mperf ib_uverbs ib_umad iw_cxgb3 cxgb3 mdio mlx4_ib mlx4_core microcode fuse loop dm_mod sr_mod cdrom ib_mthca ib_mad e1000e mptfc scsi_transport_fc scsi_tgt ib_core shpchp usb_storage i5k_amb pci_hotplug rtc_cmos rtc_core iTCO_wdt rtc_lib tpm_tis i2c_i801 i2c_core ioatdma dca tpm i5000_edac iTCO_vendor_support edac_core pcspkr container button joydev tpm_bios serio_raw sg usbhid hid uhci_hcd ehci_hcd sd_mod crc_t10dif usbcore ext3 jbd mbcache piix edd xfs exportfs fan thermal processor thermal_sys hwmon ide_generic ide_core sata_nv megaraid_sas mptsas mptscsih mptbase scsi_transport_sas ata_piix ahci libahci libata scsi_mod
Pid: 3880, comm: automount Not tainted 2.6.37-alex #1 X7DGT-INF/AltixXE310
RIP: 0010:[<ffffffffa0296744>] [<ffffffffa0296744>] autofs4_lookup +0x3dd/0x4a7 [autofs4] RSP: 0018:ffff88011f7a3b88 EFLAGS: 00010202 RAX: 0000000000000002 RBX: ffff880117faeb40 RCX: 0000000000000011 RDX: 0000000000000000 RSI: ffff88011ecfcb38 RDI: ffff88011ecfcb38 RBP: ffff88011f7a3c38 R08: 0000000000000000 R09: ffff88011ed41578 R10: ffff880120f4c007 R11: 000000000000343e R12: ffff880117fae9f8 R13: ffff88011ecfcb00 R14: 0000000000000001 R15: ffff88011ecfcb00 FS: 00007ffb9915a950(0000) GS:ffff8800cfd00000(0000)
knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000010 CR3: 000000011e7d1000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process automount (pid: 3880, threadinfo ffff88011f7a2000, task ffff880124628480)
Stack: ffff88011f7a3c08 0000000000000011 ffff88012ffd9e00 ffff88011f7a3db8 ffff880120247050 ffff8800cfd0e0e0 ffff880117faeb40 0000000000000000 00000001249405f8 ffff880117faebc0 ffff88011ecfcb38 00000011dc2bc535 Call Trace: [<ffffffff810e86fb>] ? d_alloc+0x165/0x1bd [<ffffffff810de19e>] d_alloc_and_lookup+0x49/0x68 [<ffffffff810de34c>] do_lookup+0x18f/0x23a [<ffffffff810e07a9>] link_path_walk+0x5ad/0xa90 [<ffffffff810e0edd>] do_path_lookup+0x4b/0x107 [<ffffffff810e1973>] user_path_at+0x52/0x8c [<ffffffff810d91fe>] ? cp_new_stat+0xe2/0xee [<ffffffff810e7525>] ? dput+0x25/0x23e [<ffffffff810d93bc>] vfs_fstatat+0x35/0x62 [<ffffffff810d94cb>] vfs_stat+0x16/0x18 [<ffffffff810d94e7>] sys_newstat+0x1a/0x3b [<ffffffff8100293b>] system_call_fastpath+0x16/0x1b Code: 47 60 48 85 c0 74 14 48 8b 00 48 85 c0 74 0c 48 8b b5 68 ff ff ff
4c 89 ff ff d0 48 8b bd 78 ff ff ff e8 79 c1 03 e1 48 8b 55 88 <f6> 42 10 04 74 76 65 48 8b 14 25 80 b5 00 00 48 8b 42 08 48 8b RIP [<ffffffffa0296744>] autofs4_lookup+0x3dd/0x4a7 [autofs4]
RSP <ffff88011f7a3b88>
CR2: 0000000000000010
---[ end trace 6655d1f57e42cf9e ]---
Starting mail service (Postfix)
done
Starting CRON daemon
done
eth0: no IPv6 routers present
Quoted 10 lines · Ian Kent
Quoted 3 lines · Aneesh Kumar K. V
for 9p I did the other way round. lookup now set the dentry op for both negative and positive dentries and rest of the place we dropped
d_set_d_op(b8b80cf37c7f0e32729262f805bc0fa81c3e9d12have the details)Sadly I can't do that.
For now I need to avoid calls to ->d_revalidate() as much as possible to reduce a potential deadlock and have access to the flags of the negative dentry (during create) for the purpose of blocking concurrent walks.
What prevents your d_revalidate from just checking for negative dentry?
Quoted 18 lines · Ian Kent
Quoted 8 lines · Ian Kent
Quoted 7 lines · Linus Torvalds
Quoted 2 lines · Ian Kent
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Alex, care to test just removing the
d_set_d_op()call fromautofs4_lookup()?Quoted 8 lines
Quoted 3 lines
(That code is a bit scary, though - it explicitly makes it a negative dentry with a
d_instantiate(dentry, NULL), and then hides the inode information away separately. Scary scary)Yeah, but the expire to mount races with autofs are difficult to handle and this approach has worked well under heavy stress testing. It's true that this would almost certainly be bad for a file system that supported a full range of functionality but that's not so for autofs.
Quoted 4 lines
I think I have to partly take this back.
With Nick's recent vfs-scale patches this may not be OK any more since thedcache_lockhas gone away and, at first glance, it looks like the addedautofs4_lockspin lock doesn't provide the needed protection.
Hm, what are the concurrencies that you need protection from?
Quoted 6 lines · Nick Piggin
Quoted 5 lines · Ian Kent
Quoted 3 lines · Aneesh Kumar K. V
for 9p I did the other way round. lookup now set the dentry op for both negative and positive dentries and rest of the place we dropped
d_set_d_op(b8b80cf37c7f0e32729262f805bc0fa81c3e9d12have the details)
Quoted 7 lines
Quoted 5 lines
Sadly I can't do that.
For now I need to avoid calls to ->d_revalidate() as much as possible to reduce a potential deadlock and have access to the flags of the negative dentry (during create) for the purpose of blocking concurrent walks.
What prevents your
d_revalidatefrom just checking for negative dentry?
Whether the dentry is negative or not doesn't change the need to block walks which introduces the possibility of blocking while holding the parent i_mutex, since it can't be released in revalidate.
Quoted 19 lines · Nick Piggin
Quoted 18 lines · Ian Kent
Quoted 16 lines · Ian Kent
Quoted 10 lines · Linus Torvalds
Quoted 2 lines · Ian Kent
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Alex, care to test just removing the
d_set_d_op()call fromautofs4_lookup()?(That code is a bit scary, though - it explicitly makes it a negative dentry with a
d_instantiate(dentry, NULL), and then hides the inode information away separately. Scary scary)Yeah, but the expire to mount races with autofs are difficult to handle and this approach has worked well under heavy stress testing. It's true that this would almost certainly be bad for a file system that supported a full range of functionality but that's not so for autofs.
Quoted 6 lines
Quoted 4 lines
I think I have to partly take this back.
With Nick's recent vfs-scale patches this may not be OK any more since thedcache_lockhas gone away and, at first glance, it looks like the addedautofs4_lockspin lock doesn't provide the needed protection.Hm, what are the concurrencies that you need protection from?
Ha, I think I'm wrong about this, after looking more closely at this I'm struggling to see why autofs4_lock is needed at all.
Quoted 5 lines · Ian Kent
Quoted 1 line · Nick Piggin
Hm, what are the concurrencies that you need protection from?
Ha, I think I'm wrong about this, after looking more closely at this I'm struggling to see why
autofs4_lockis needed at all.
Well you did send me a series of patches to remove it, but unfortunately that was just as you made some larger changes to autofs4 upstream and I wasn't able to keep them up to date.
It would be much appreciated if you had time to take another look at all the locking and streamline it.
Thanks,
Nick
Quoted 54 lines · Alex Elder
Quoted 48 lines · Ian Kent
Quoted 47 lines · Ian Kent
Quoted 26 lines · Alex Elder
Quoted 12 lines · Linus Torvalds
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.Yeah, removing the
BUG_ON()isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.Quoted 8 lines
Possibly the thing could be relaxed to allow setting the _same_
d_oppointer, ie do something likeif (dentry->d_op == op) return;at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
That's easy enough, but it seems everybody else ensures this gets done just once per dentry, and it would be nice to preserve that "tightness" if possible.
Quoted 6 lines
Quoted 4 lines
The fact that autofs4 does "
d_add()" before it sets thed_ops(or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.Agreed.
Isn't the parent
i_mutexheld duringmkdir()?
Still the order can be changed, of course.Quoted 9 lines
Quoted 4 lines
Does it make any difference if you move the various
d_add()calls down to the end of the functions to when the "dentry" has really been instantiated?Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Quoted 4 lines
Quoted 2 lines
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Could you try this patch please.
Quoted 7 lines
OK, sorry for the delay. I tried the patch. I applied it against
4162cf64973df51fc885825bc9ca4d055891c49f, which is the linus/master branch I had on hand. This time I got a different failure due to a null pointer dereference. Console capture below. I can log in still but the boot sequence never got to the login prompt on the console as it normally does.
Sorry, that is rather an obvious mistake on my part. There's a call to d_op->d_revalidate() just below where the dentry operations are set. I'm tempted to just call the revalidate function directly since it is always called anyway. But let me check we've done in the our current of tree autofs patch series first.
Quoted 79 lines
-Alex
Quoted 1 line
autofs4 - dont set dentry op in ->lookup()
. . .
Starting smartd
done
Starting network time protocol daemon (NTPD)
done
Starting automount BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
IP: [<ffffffffa0296744>]autofs4_lookup+0x3dd/0x4a7[autofs4] PGD 0Oops: 0000 [#1] SMP last sysfs file: /sys/devices/pci0000:00/0000:00:1e.0/0000:08:01.0/local_cpus CPU 2 Modules linked in: autofs4 binfmt_misc nfs lockd nfs_acl auth_rpcgsssunrpc
ib_ipoibib_cmib_saipv6 mperfib_uverbsib_umadiw_cxgb3cxgb3 mdiomlx4_ibmlx4_coremicrocode fuse loopdm_modsr_modcdromib_mthcaib_made1000e mptfcscsi_transport_fcscsi_tgtib_coreshpchpusb_storagei5k_ambpci_hotplugrtc_cmosrtc_coreiTCO_wdtrtc_libtpm_tisi2c_i801i2c_coreioatdma dca tpmi5000_edaciTCO_vendor_supportedac_corepcspkr container button joydevtpm_biosserio_rawsg usbhid hiduhci_hcdehci_hcdsd_modcrc_t10difusbcore ext3 jbd mbcache piix edd xfs exportfs fan thermal processorthermal_syshwmonide_genericide_coresata_nvmegaraid_sasmptsas mptscsih mptbasescsi_transport_sasata_piixahci libahci libatascsi_modPid: 3880, comm: automount Not tainted 2.6.37-alex #1 X7DGT-INF/AltixXE310
RIP: 0010:[<ffffffffa0296744>] [<ffffffffa0296744>] autofs4_lookup +0x3dd/0x4a7 [autofs4] RSP: 0018:ffff88011f7a3b88 EFLAGS: 00010202 RAX: 0000000000000002 RBX: ffff880117faeb40 RCX: 0000000000000011 RDX: 0000000000000000 RSI: ffff88011ecfcb38 RDI: ffff88011ecfcb38 RBP: ffff88011f7a3c38 R08: 0000000000000000 R09: ffff88011ed41578 R10: ffff880120f4c007 R11: 000000000000343e R12: ffff880117fae9f8 R13: ffff88011ecfcb00 R14: 0000000000000001 R15: ffff88011ecfcb00 FS: 00007ffb9915a950(0000) GS:ffff8800cfd00000(0000)knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000010 CR3:000000011e7d1000CR4:00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6:00000000ffff0ff0DR7: 0000000000000400 Process automount (pid: 3880, threadinfoffff88011f7a2000, taskffff880124628480)Stack: ffff88011f7a3c08 0000000000000011 ffff88012ffd9e00 ffff88011f7a3db8 ffff880120247050 ffff8800cfd0e0e0 ffff880117faeb40 0000000000000000 00000001249405f8 ffff880117faebc0 ffff88011ecfcb38 00000011dc2bc535 Call Trace: [<ffffffff810e86fb>] ? d_alloc+0x165/0x1bd [<ffffffff810de19e>] d_alloc_and_lookup+0x49/0x68 [<ffffffff810de34c>] do_lookup+0x18f/0x23a [<ffffffff810e07a9>] link_path_walk+0x5ad/0xa90 [<ffffffff810e0edd>] do_path_lookup+0x4b/0x107 [<ffffffff810e1973>] user_path_at+0x52/0x8c [<ffffffff810d91fe>] ? cp_new_stat+0xe2/0xee [<ffffffff810e7525>] ? dput+0x25/0x23e [<ffffffff810d93bc>] vfs_fstatat+0x35/0x62 [<ffffffff810d94cb>] vfs_stat+0x16/0x18 [<ffffffff810d94e7>] sys_newstat+0x1a/0x3b [<ffffffff8100293b>] system_call_fastpath+0x16/0x1b Code: 47 60 48 85 c0 74 14 48 8b 00 48 85 c0 74 0c 48 8b b5 68 ff ff ff4c 89 ff ff d0 48 8b bd 78 ff ff ff e8 79 c1 03 e1 48 8b 55 88 <f6> 42 10 04 74 76 65 48 8b 14 25 80 b5 00 00 48 8b 42 08 48 8b RIP [<
ffffffffa0296744>]autofs4_lookup+0x3dd/0x4a7[autofs4]
RSP <ffff88011f7a3b88>
CR2: 0000000000000010---[ end trace 6655d1f57e42cf9e ]---Starting mail service (Postfix)
done
Starting CRON daemon
done
eth0: no IPv6 routers present
Quoted 64 lines · Ian Kent
Quoted 54 lines · Alex Elder
Quoted 48 lines · Ian Kent
Quoted 47 lines · Ian Kent
Quoted 26 lines · Alex Elder
Quoted 12 lines · Linus Torvalds
Quoted 6 lines · Alex Elder
FYI, when using this code, as merged by Linus, I hit the
BUG_ON()at the beginning ofd_set_d_op()when it's called byautofs4_dir_mkdir(). I managed to work around it by just commenting out thoseBUG_ON()calls but it's something that ought to get addressed properly.Yeah, removing the
BUG_ON()isn't the right thing to do - it means that autofs4 is obviously setting the dentry ops twice for the same dentry.Quoted 8 lines
Possibly the thing could be relaxed to allow setting the _same_
d_oppointer, ie do something likeif (dentry->d_op == op) return;at the top of that function. But looking at it, I don't think that fixes the autofs4 issue.
That's easy enough, but it seems everybody else ensures this gets done just once per dentry, and it would be nice to preserve that "tightness" if possible.
Quoted 6 lines
Quoted 4 lines
The fact that autofs4 does "
d_add()" before it sets thed_ops(or other dentry state, for that matter) looks a bit scary. To me that smells like it might get a dentry lookup hit before it's actually fully done.Agreed.
Isn't the parent
i_mutexheld duringmkdir()?
Still the order can be changed, of course.Quoted 9 lines
Quoted 4 lines
Does it make any difference if you move the various
d_add()calls down to the end of the functions to when the "dentry" has really been instantiated?Looking at it quickly, I don't think that would matter for the case at hand. I.e., that might be safer but it doesn't address the fact that these fields are getting initialized multiple times.
Quoted 4 lines
Quoted 2 lines
Yeah, a hangover from changes done over time. Not setting the dentry op in ->lookup() should fix this.
Could you try this patch please.
Quoted 7 lines
OK, sorry for the delay. I tried the patch. I applied it against
4162cf64973df51fc885825bc9ca4d055891c49f, which is the linus/master branch I had on hand. This time I got a different failure due to a null pointer dereference. Console capture below. I can log in still but the boot sequence never got to the login prompt on the console as it normally does.
Quoted 5 lines
Sorry, that is rather an obvious mistake on my part. There's a call to
d_op->d_revalidate()just below where the dentry operations are set. I'm tempted to just call the revalidate function directly since it is always called anyway. But let me check we've done in the our current of tree autofs patch series first.
Ha, there is no revalidate in the current not yet merged autofs. So I think we just need to work around it.
Try this and see if it resolves the issue.
autofs4 - set dentry op in ->lookup() only
From: Ian Kent <[email protected]>
With the introduction of the vfs-scale patch series setting dentry operations more than once (or changing them) triggers a BUG_ON(). Since the two dentry operations used are the same, just set the operations in ->lookup() and remove the set in ->symlink() and ->mkdir().
Also, move the d_add() in ->symlink() and ->mkdir() to the end of the function.
---
fs/autofs4/root.c | 40 +++++++--------------------------------- 1 files changed, 7 insertions(+), 33 deletions(-)
fs/autofs4/root.c +7 -33
@@ -419,12 +419,6 @@ void autofs4_dentry_release(struct dentry *de) } } -/* For dentries of directories in the root dir */ -static const struct dentry_operations autofs4_root_dentry_operations = { - .d_revalidate = autofs4_revalidate, - .d_release = autofs4_dentry_release, -}; -/* For other dentries */ static const struct dentry_operations autofs4_dentry_operations = { .d_revalidate = autofs4_revalidate,
@@ -568,19 +562,6 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s ino =autofs4_dentry_ino (dentry); }else {/* -* Mark the dentry incomplete but don't hash it. We do this -* to serialize our inode creation operations (symlink and -* mkdir) which prevents deadlock during the callback to -* the daemon. Subsequent user space lookups for the same -* dentry are placed on the wait queue while the daemon -* itself is allowed passage unresticted so the create -* operation itself can then hash the dentry. Finally, -* we check for the hashed dentry and return the newly -* hashed dentry. -*/ -d_set_d_op (dentry, &autofs4_root_dentry_operations); - -/* * And we need to ensure that the same dentry is used for * all following lookup calls until it is hashed so that * the dentry flags are persistent throughout the request.
@@ -589,6 +570,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, sif (!ino)return ERR_PTR (-ENOMEM ); +d_set_d_op (dentry, &autofs4_dentry_operations); + dentry->d_fsdata = ino; ino->dentry = dentry;
@@ -714,12 +697,6 @@ static int autofs4_dir_symlink(struct inode *dir,kfree (ino);return -ENOMEM ; } -d_add (dentry, inode); - -if (dir == dir->i_sb->s_root->d_inode) -d_set_d_op (dentry, &autofs4_root_dentry_operations); -else -d_set_d_op (dentry, &autofs4_dentry_operations); dentry->d_fsdata = ino; ino->dentry =dget (dentry);
@@ -732,6 +709,8 @@ static int autofs4_dir_symlink(struct inode *dir, ino->u.symlink = cp; dir->i_mtime =CURRENT_TIME ; +d_add (dentry, inode); +return 0 ; }
@@ -849,12 +828,6 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)kfree (ino);return -ENOMEM ; } -d_add (dentry, inode); - -if (dir == dir->i_sb->s_root->d_inode) -d_set_d_op (dentry, &autofs4_root_dentry_operations); -else -d_set_d_op (dentry, &autofs4_dentry_operations); dentry->d_fsdata = ino; ino->dentry =dget (dentry);
@@ -866,6 +839,8 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)inc_nlink (dir); dir->i_mtime =CURRENT_TIME ; +d_add (dentry, inode); +return 0 ; }
@@ -944,8 +919,7 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)int is_autofs4_dentry (struct dentry *dentry) {return dentry && dentry->d_inode && - (dentry->d_op == &autofs4_root_dentry_operations || - dentry->d_op == &autofs4_dentry_operations) && + (dentry->d_op == &autofs4_dentry_operations) && dentry->d_fsdata !=NULL ; }
Quoted 7 lines · Nick Piggin
Quoted 5 lines · Ian Kent
Quoted 1 line · Nick Piggin
Hm, what are the concurrencies that you need protection from?
Ha, I think I'm wrong about this, after looking more closely at this I'm struggling to see why
autofs4_lockis needed at all.
Quoted 6 lines
Well you did send me a series of patches to remove it, but unfortunately that was just as you made some larger changes to autofs4 upstream and I wasn't able to keep them up to date.
It would be much appreciated if you had time to take another look at all the locking and streamline it.
I have started looking at it but just the autofs4_lock.
As you know, we have some significant autofs changes in progress, so I don't want to spend a huge amount of time testing (and the testing does take a long time) against source that will be very different. So far I can't see that the autofs4_lock will introduce any problem so I want to leave it for now and (probably) eliminate it in the new code since that will need changes as well and will need to be re-tested.
I'd appreciate it if you could find time to reply to David's questions about the changes to our d_automount patch series. Although, based on our previous discussion, I think he has it about right, but a word or two from you would be really helpful.
Ian
Quoted 15 lines · Ian Kent
Quoted 7 lines · Nick Piggin
Quoted 5 lines · Ian Kent
Quoted 1 line · Nick Piggin
Hm, what are the concurrencies that you need protection from?
Ha, I think I'm wrong about this, after looking more closely at this I'm struggling to see why
autofs4_lockis needed at all.Quoted 6 lines
Well you did send me a series of patches to remove it, but unfortunately that was just as you made some larger changes to autofs4 upstream and I wasn't able to keep them up to date.
It would be much appreciated if you had time to take another look at all the locking and streamline it.
Quoted 8 lines
I have started looking at it but just the
autofs4_lock.As you know, we have some significant autofs changes in progress, so I don't want to spend a huge amount of time testing (and the testing does take a long time) against source that will be very different. So far I can't see that the
autofs4_lockwill introduce any problem so I want to leave it for now and (probably) eliminate it in the new code since that will need changes as well and will need to be re-tested.
Fair enough.
Quoted 4 lines
I'd appreciate it if you could find time to reply to David's questions about the changes to our
d_automountpatch series. Although, based on our previous discussion, I think he has it about right, but a word or two from you would be really helpful.
Yes I am meaning to take a look, I'm a bit busy for the next week, however.
Quoted 4 lines · Ian Kent
Quoted 3 lines · Ian Kent
Quoted 2 lines · Alex Elder
Quoted 1 line · Ian Kent
On Wed, 2011-01-12 at 11:59 +0800, Ian Kent wrote:
. . .
Quoted 17 lines
Quoted 11 lines
Quoted 9 lines
Quoted 1 line
Could you try this patch please.
OK, sorry for the delay. I tried the patch. I applied it against
4162cf64973df51fc885825bc9ca4d055891c49f, which is the linus/master branch I had on hand. This time I got a different failure due to a null pointer dereference. Console capture below. I can log in still but the boot sequence never got to the login prompt on the console as it normally does.Quoted 5 lines
Sorry, that is rather an obvious mistake on my part. There's a call to
d_op->d_revalidate()just below where the dentry operations are set. I'm tempted to just call the revalidate function directly since it is always called anyway. But let me check we've done in the our current of tree autofs patch series first.
Quoted 4 lines
Ha, there is no revalidate in the current not yet merged autofs. So I think we just need to work around it.
Try this and see if it resolves the issue.
This one works. I am able to boot without hitting the BUG_ON() in d_set_d_op() and there is no longer the null pointer dereference that occurred with the last one.
-Alex
Quoted 120 lines
autofs4 - set dentry op in ->lookup() only
From: Ian Kent <[email protected]>
With the introduction of the vfs-scale patch series setting dentry operations more than once (or changing them) triggers a
BUG_ON(). Since the two dentry operations used are the same, just set the operations in ->lookup() and remove the set in ->symlink() and ->mkdir().Also, move the
d_add()in ->symlink() and ->mkdir() to the end of the function.
---fs/autofs4/root.c | 40 +++++++--------------------------------- 1 files changed, 7 insertions(+), 33 deletions(-)fs/autofs4/root.c +7
-33@@ -419,12 +419,6 @@ void autofs4_dentry_release(struct dentry *de) } } -/* For dentries of directories in the root dir */ -static const struct dentry_operations autofs4_root_dentry_operations = { - .d_revalidate = autofs4_revalidate, - .d_release = autofs4_dentry_release, -}; -/* For other dentries */ static const struct dentry_operations autofs4_dentry_operations = { .d_revalidate = autofs4_revalidate,@@ -568,19 +562,6 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s ino =autofs4_dentry_ino (dentry); }else {/* -* Mark the dentry incomplete but don't hash it. We do this -* to serialize our inode creation operations (symlink and -* mkdir) which prevents deadlock during the callback to -* the daemon. Subsequent user space lookups for the same -* dentry are placed on the wait queue while the daemon -* itself is allowed passage unresticted so the create -* operation itself can then hash the dentry. Finally, -* we check for the hashed dentry and return the newly -* hashed dentry. -*/ -d_set_d_op (dentry, &autofs4_root_dentry_operations); - -/* * And we need to ensure that the same dentry is used for * all following lookup calls until it is hashed so that * the dentry flags are persistent throughout the request. @@ -589,6 +570,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, sif (!ino)return ERR_PTR (-ENOMEM ); +d_set_d_op (dentry, &autofs4_dentry_operations); + dentry->d_fsdata = ino; ino->dentry = dentry;@@ -714,12 +697,6 @@ static int autofs4_dir_symlink(struct inode *dir,kfree (ino);return -ENOMEM ; } -d_add (dentry, inode); - -if (dir == dir->i_sb->s_root->d_inode) -d_set_d_op (dentry, &autofs4_root_dentry_operations); -else -d_set_d_op (dentry, &autofs4_dentry_operations); dentry->d_fsdata = ino; ino->dentry =dget (dentry);@@ -732,6 +709,8 @@ static int autofs4_dir_symlink(struct inode *dir, ino->u.symlink = cp; dir->i_mtime =CURRENT_TIME ; +d_add (dentry, inode); +return 0 ; }@@ -849,12 +828,6 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)kfree (ino);return -ENOMEM ; } -d_add (dentry, inode); - -if (dir == dir->i_sb->s_root->d_inode) -d_set_d_op (dentry, &autofs4_root_dentry_operations); -else -d_set_d_op (dentry, &autofs4_dentry_operations); dentry->d_fsdata = ino; ino->dentry =dget (dentry);@@ -866,6 +839,8 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)inc_nlink (dir); dir->i_mtime =CURRENT_TIME ; +d_add (dentry, inode); +return 0 ; }@@ -944,8 +919,7 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)int is_autofs4_dentry (struct dentry *dentry) {return dentry && dentry->d_inode && - (dentry->d_op == &autofs4_root_dentry_operations || - dentry->d_op == &autofs4_dentry_operations) && + (dentry->d_op == &autofs4_dentry_operations) && dentry->d_fsdata !=NULL ; }