* panic in do_last()
@ 2014-04-18 1:14 Lin Ming
2014-04-18 1:57 ` Al Viro
0 siblings, 1 reply; 12+ messages in thread
From: Lin Ming @ 2014-04-18 1:14 UTC (permalink / raw)
To: David Howells; +Cc: linux-fsdevel, viro, Hugh Dickins
[-- Attachment #1: Type: text/plain, Size: 4577 bytes --]
Hi Dave,
I tried to reproduce bug "BUG at mm/filemap.c:202!"
https://lkml.org/lkml/2014/4/15/577 with the attached programs.
I can't reproduce it, but it triggered another bug related to commit b18825a7c.
commit b18825a7c8e37a7cf6abb97a12a6ad71af160de7
Author: David Howells <dhowells@redhat.com>
Date: Thu Sep 12 19:22:53 2013 +0100
VFS: Put a small type field into struct dentry::d_flags
[ 216.673863] BUG: unable to handle kernel NULL pointer dereference
at (null)
[ 216.674235] IP: [<ffffffff81108961>] do_last.isra.44+0x7d2/0x9ea
[ 216.674487] PGD 3d3f0067 PUD 3c82a067 PMD 0
[ 216.674853] Oops: 0000 [#1] SMP
[ 216.675126] Modules linked in:
[ 216.675324] CPU: 1 PID: 30121 Comm: test Not tainted 3.15.0-rc1 #14
[ 216.675501] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
BIOS Bochs 01/01/2011
[ 216.675709] task: ffff88003d1788c0 ti: ffff88003ca84000 task.ti:
ffff88003ca84000
[ 216.675906] RIP: 0010:[<ffffffff81108961>] [<ffffffff81108961>]
do_last.isra.44+0x7d2/0x9ea
[ 216.676195] RSP: 0018:ffff88003ca85cf8 EFLAGS: 00010246
[ 216.676356] RAX: 0000000000000000 RBX: ffff88003ca85e40 RCX: 0000000000000020
[ 216.676547] RDX: 000060ffc00002c0 RSI: 0000000000000101 RDI: ffff88003ca85e40
[ 216.676737] RBP: ffff88003ca85d98 R08: ffff88003ca062d0 R09: ffff88003ca062d0
[ 216.676933] R10: 2f2f2f2f2f2f2f2f R11: ffffffff81108817 R12: ffff88003ca85dd8
[ 216.677123] R13: ffff88003ca3f400 R14: 0000000000000000 R15: ffff88003daba840
[ 216.677434] FS: 00007f0453b55700(0000) GS:ffff88003fd00000(0000)
knlGS:0000000000000000
[ 216.677808] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 216.677808] CR2: 0000000000000000 CR3: 0000000000047000 CR4: 00000000000006e0
[ 216.677808] Stack:
[ 216.677808] ffff88003ca062d0 ffffffff8110576a 00000000000080d0
0000002600000000
[ 216.677808] ffff880000c083c0 ffff88003d1788c0 000081b600005d68
ffff88003ca85f24
[ 216.677808] ffff88003ca85dcc ffff8800010001c0 0100000578742ee8
0000000000000000
[ 216.677808] Call Trace:
[ 216.677808] [<ffffffff8110576a>] ? link_path_walk+0x6c/0x739
[ 216.677808] [<ffffffff81108d7c>] path_openat+0x203/0x54b
[ 216.677808] [<ffffffff81109410>] do_filp_open+0x3a/0x8a
[ 216.677808] [<ffffffff8111383d>] ? __alloc_fd+0x60/0xec
[ 216.677808] [<ffffffff810fc334>] do_sys_open+0x14f/0x1de
[ 216.677808] [<ffffffff8110547a>] ? final_putname+0x35/0x39
[ 216.677808] [<ffffffff810fc3e5>] SyS_open+0x22/0x24
[ 216.677808] [<ffffffff81382cd2>] system_call_fastpath+0x16/0x1b
2872 static int do_last(struct nameidata *nd, struct path *path,
....
2993 inode = path->dentry->d_inode; <---- Here "inode" is NULL
2994 finish_lookup:
2995 /* we _can_ be in RCU mode here */
2996 error = -ENOENT;
2997 if (d_is_negative(path->dentry)) { <---- But here
"dentry->d_flags" is 0x 400088, so it's positive
2998 path_to_nameidata(path, nd);
2999 goto out;
3000 }
To reproduce it:
cc -o test test.c
write.sh &
1.sh &
1.sh &
I modified below code, then it can't be reproduced any more.
But I know it's not the correct fix.
diff --git a/fs/namei.c b/fs/namei.c
index c6157c8..951c6ee 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2994,7 +2994,7 @@ static int do_last(struct nameidata *nd, struct
path *path,
finish_lookup:
/* we _can_ be in RCU mode here */
error = -ENOENT;
- if (d_is_negative(path->dentry)) {
+ if (!inode) {
path_to_nameidata(path, nd);
goto out;
}
One possibility is there is a race between __d_instantiate() and do_last()
cpu 0: in __d_instantiate() cpu 1: in do_last()
set DCACHE_FILE_TYPE
inode = path->dentry->d_inode (Didn't see ->d_inode set yet)
dentry->d_inode = inode;
d_is_negative(path->dentry) (Saw DCACHE_FILE_TYPE set)
So I tried below fix, but it still not work.
Any idea?
diff --git a/fs/dcache.c b/fs/dcache.c
index 40707d8..15b2163 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1647,11 +1647,11 @@ static void __d_instantiate(struct dentry
*dentry, struct inode *inode)
unsigned add_flags = d_flags_for_inode(inode);
spin_lock(&dentry->d_lock);
+ dentry->d_inode = inode;
dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
dentry->d_flags |= add_flags;
if (inode)
hlist_add_head(&dentry->d_alias, &inode->i_dentry);
- dentry->d_inode = inode;
dentry_rcuwalk_barrier(dentry);
spin_unlock(&dentry->d_lock);
fsnotify_d_instantiate(dentry, inode);
[-- Attachment #2: 1.sh --]
[-- Type: application/x-sh, Size: 43 bytes --]
[-- Attachment #3: test.c --]
[-- Type: text/x-csrc, Size: 261 bytes --]
#include <stdio.h>
#include <stdlib.h>
int main()
{
int fd;
char c;
int ret;
while (1) {
fd = open("/mnt/t.txt", 0666);
if (fd != -1)
break;
}
while (1) {
ret = read(fd, &c, 1);
if (ret != -1)
break;
}
printf("%c\n", c);
return 0;
}
[-- Attachment #4: write.sh --]
[-- Type: application/x-sh, Size: 104 bytes --]
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 1:14 panic in do_last() Lin Ming
@ 2014-04-18 1:57 ` Al Viro
2014-04-18 2:17 ` Al Viro
[not found] ` <CAF1ivSbqM2LorrED3MvgKBDxA9sLz_RkOEPwAfvYYmL5C9K0vA@mail.gmail.com>
0 siblings, 2 replies; 12+ messages in thread
From: Al Viro @ 2014-04-18 1:57 UTC (permalink / raw)
To: Lin Ming; +Cc: David Howells, linux-fsdevel, Hugh Dickins
On Thu, Apr 17, 2014 at 06:14:51PM -0700, Lin Ming wrote:
> Hi Dave,
>
> I tried to reproduce bug "BUG at mm/filemap.c:202!"
> https://lkml.org/lkml/2014/4/15/577 with the attached programs.
> I can't reproduce it, but it triggered another bug related to commit b18825a7c.
>
> commit b18825a7c8e37a7cf6abb97a12a6ad71af160de7
> Author: David Howells <dhowells@redhat.com>
> Date: Thu Sep 12 19:22:53 2013 +0100
>
> VFS: Put a small type field into struct dentry::d_flags
>
> [ 216.673863] BUG: unable to handle kernel NULL pointer dereference
> at (null)
> [ 216.674235] IP: [<ffffffff81108961>] do_last.isra.44+0x7d2/0x9ea
Where is it in do_last()? Hard to tell without even the hex dump of
oopsing code (and trying to reproduce it here hasn't produced any oopsen
so far).
And your test.c is _really_ weird:
> fd = open("/mnt/t.txt", 0666);
Just what is that 0666 doing, in your opinion? And how is it different
from O_NOCTTY | O_EXCL | O_RDWR (which also makes zero sense)?
And this read() loop is just plain odd - you are leaving it if read(fd, &c, 1)
gives you 0 and proceed to print (uninitialized in that case) value of c...
Anyway, I'd really like to see your .config (or, better yet, disassembly of
do_last) along with the hex dump of oopsing code. Without that...
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 1:57 ` Al Viro
@ 2014-04-18 2:17 ` Al Viro
2014-04-18 2:22 ` Lin Ming
2014-04-18 2:35 ` Lin Ming
[not found] ` <CAF1ivSbqM2LorrED3MvgKBDxA9sLz_RkOEPwAfvYYmL5C9K0vA@mail.gmail.com>
1 sibling, 2 replies; 12+ messages in thread
From: Al Viro @ 2014-04-18 2:17 UTC (permalink / raw)
To: Lin Ming; +Cc: David Howells, linux-fsdevel, Hugh Dickins
On Fri, Apr 18, 2014 at 02:57:50AM +0100, Al Viro wrote:
> Where is it in do_last()? Hard to tell without even the hex dump of
> oopsing code (and trying to reproduce it here hasn't produced any oopsen
> so far).
Hmm... Still no oopsen, but it looks like it *is* possible to get
screwed there. RCU mode isn't a problem, AFAICS (we'll fail on d_seq
mismatch in complete_walk() and that will be the end of it), but
non-lazy mode *can* get buggered. We are holding a reference to
nd->path.dentry and that's enough to prevent positive-to-negative
transition, but negative-to-positive is fair game. So it does
happen and we end up with nd->inode being set to NULL. And _that_
promptly blows up on
if (!S_ISREG(nd->inode->i_mode))
will_truncate = false;
Actually, it might very well be the only source of breakage - that late
in the game (already out of RCU mode, for starters) we don't give a damn
about nd->inode.
Ah, actually there's also
BUG_ON(inode != path->dentry->d_inode);
in symlink case (similar "negative to positive", but it will be a symlink(2),
not creat(2)). Pointless BUG_ON, actually...
The reason why your reordering hadn't done any good is that CPU cache is free
to reorder behind your back - no barriers between these two stores.
I'd still like the disassembly of your do_last() and the missing hex dump...
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 2:17 ` Al Viro
@ 2014-04-18 2:22 ` Lin Ming
2014-04-18 2:35 ` Lin Ming
1 sibling, 0 replies; 12+ messages in thread
From: Lin Ming @ 2014-04-18 2:22 UTC (permalink / raw)
To: Al Viro; +Cc: David Howells, linux-fsdevel, Hugh Dickins
[-- Attachment #1: Type: text/plain, Size: 242 bytes --]
On Thu, Apr 17, 2014 at 7:17 PM, Al Viro <viro@zeniv.linux.org.uk> wrote:
> I'd still like the disassembly of your do_last() and the missing hex dump...
disassmebly of do_last() attached.
the missing hex dump should be in previous panic.log
[-- Attachment #2: do_last.S --]
[-- Type: application/octet-stream, Size: 73085 bytes --]
vmlinux: file format elf64-x86-64
Disassembly of section .text:
ffffffff81108dd3 <do_last.isra.44>:
}
/*
* Handle the last step of open()
*/
static int do_last(struct nameidata *nd, struct path *path,
ffffffff81108dd3: e8 68 a7 27 00 callq ffffffff81383540 <__fentry__>
ffffffff81108dd8: 55 push %rbp
ffffffff81108dd9: 48 89 e5 mov %rsp,%rbp
ffffffff81108ddc: 41 57 push %r15
ffffffff81108dde: 41 56 push %r14
ffffffff81108de0: 41 55 push %r13
ffffffff81108de2: 49 89 d5 mov %rdx,%r13
ffffffff81108de5: 41 54 push %r12
ffffffff81108de7: 49 89 f4 mov %rsi,%r12
ffffffff81108dea: 53 push %rbx
ffffffff81108deb: 48 89 fb mov %rdi,%rbx
ffffffff81108dee: 48 83 ec 78 sub $0x78,%rsp
struct file *file, const struct open_flags *op,
int *opened, struct filename *name)
{
struct dentry *dir = nd->path.dentry;
int open_flag = op->open_flag;
ffffffff81108df2: 8b 11 mov (%rcx),%edx
*/
static int do_last(struct nameidata *nd, struct path *path,
struct file *file, const struct open_flags *op,
int *opened, struct filename *name)
{
struct dentry *dir = nd->path.dentry;
ffffffff81108df4: 48 8b 47 08 mov 0x8(%rdi),%rax
}
/*
* Handle the last step of open()
*/
static int do_last(struct nameidata *nd, struct path *path,
ffffffff81108df8: 48 89 4d 98 mov %rcx,-0x68(%rbp)
ffffffff81108dfc: 4c 89 45 a0 mov %r8,-0x60(%rbp)
bool will_truncate = (open_flag & O_TRUNC) != 0;
bool got_write = false;
int acc_mode = op->acc_mode;
struct inode *inode;
bool symlink_ok = false;
struct path save_parent = { .dentry = NULL, .mnt = NULL };
ffffffff81108e00: 48 c7 45 c0 00 00 00 movq $0x0,-0x40(%rbp)
ffffffff81108e07: 00
ffffffff81108e08: 48 c7 45 c8 00 00 00 movq $0x0,-0x38(%rbp)
ffffffff81108e0f: 00
*/
static int do_last(struct nameidata *nd, struct path *path,
struct file *file, const struct open_flags *op,
int *opened, struct filename *name)
{
struct dentry *dir = nd->path.dentry;
ffffffff81108e10: 48 89 45 80 mov %rax,-0x80(%rbp)
int open_flag = op->open_flag;
bool will_truncate = (open_flag & O_TRUNC) != 0;
ffffffff81108e14: 89 d0 mov %edx,%eax
static int do_last(struct nameidata *nd, struct path *path,
struct file *file, const struct open_flags *op,
int *opened, struct filename *name)
{
struct dentry *dir = nd->path.dentry;
int open_flag = op->open_flag;
ffffffff81108e16: 89 55 94 mov %edx,-0x6c(%rbp)
bool will_truncate = (open_flag & O_TRUNC) != 0;
ffffffff81108e19: c1 e8 09 shr $0x9,%eax
int error;
nd->flags &= ~LOOKUP_PARENT;
nd->flags |= op->intent;
if (nd->last_type != LAST_NORM) {
ffffffff81108e1c: 8b 57 44 mov 0x44(%rdi),%edx
struct file *file, const struct open_flags *op,
int *opened, struct filename *name)
{
struct dentry *dir = nd->path.dentry;
int open_flag = op->open_flag;
bool will_truncate = (open_flag & O_TRUNC) != 0;
ffffffff81108e1f: 83 e0 01 and $0x1,%eax
ffffffff81108e22: 88 45 aa mov %al,-0x56(%rbp)
bool got_write = false;
int acc_mode = op->acc_mode;
ffffffff81108e25: 8b 41 08 mov 0x8(%rcx),%eax
ffffffff81108e28: 89 85 7c ff ff ff mov %eax,-0x84(%rbp)
bool symlink_ok = false;
struct path save_parent = { .dentry = NULL, .mnt = NULL };
bool retried = false;
int error;
nd->flags &= ~LOOKUP_PARENT;
ffffffff81108e2e: 8b 47 38 mov 0x38(%rdi),%eax
ffffffff81108e31: 83 e0 ef and $0xffffffef,%eax
ffffffff81108e34: 89 47 38 mov %eax,0x38(%rdi)
nd->flags |= op->intent;
ffffffff81108e37: 0b 41 0c or 0xc(%rcx),%eax
if (nd->last_type != LAST_NORM) {
ffffffff81108e3a: 85 d2 test %edx,%edx
struct path save_parent = { .dentry = NULL, .mnt = NULL };
bool retried = false;
int error;
nd->flags &= ~LOOKUP_PARENT;
nd->flags |= op->intent;
ffffffff81108e3c: 89 47 38 mov %eax,0x38(%rdi)
if (nd->last_type != LAST_NORM) {
ffffffff81108e3f: 74 29 je ffffffff81108e6a <do_last.isra.44+0x97>
return inode_permission(nd->inode, MAY_EXEC);
}
static inline int handle_dots(struct nameidata *nd, int type)
{
if (type == LAST_DOTDOT) {
ffffffff81108e41: 83 fa 03 cmp $0x3,%edx
ffffffff81108e44: 0f 85 0c 09 00 00 jne ffffffff81109756 <do_last.isra.44+0x983>
if (nd->flags & LOOKUP_RCU) {
ffffffff81108e4a: a8 40 test $0x40,%al
ffffffff81108e4c: 74 12 je ffffffff81108e60 <do_last.isra.44+0x8d>
if (follow_dotdot_rcu(nd))
ffffffff81108e4e: e8 d8 c0 ff ff callq ffffffff81104f2b <follow_dotdot_rcu>
ffffffff81108e53: 85 c0 test %eax,%eax
ffffffff81108e55: 0f 85 f3 08 00 00 jne ffffffff8110974e <do_last.isra.44+0x97b>
ffffffff81108e5b: e9 f6 08 00 00 jmpq ffffffff81109756 <do_last.isra.44+0x983>
return -ECHILD;
} else
follow_dotdot(nd);
ffffffff81108e60: e8 16 c5 ff ff callq ffffffff8110537b <follow_dotdot>
ffffffff81108e65: e9 ec 08 00 00 jmpq ffffffff81109756 <do_last.isra.44+0x983>
if (error)
return error;
goto finish_open;
}
if (!(open_flag & O_CREAT)) {
ffffffff81108e6a: f6 45 94 40 testb $0x40,-0x6c(%rbp)
ffffffff81108e6e: 75 64 jne ffffffff81108ed4 <do_last.isra.44+0x101>
if (nd->last.name[nd->last.len])
ffffffff81108e70: 8b 57 14 mov 0x14(%rdi),%edx
ffffffff81108e73: 48 8b 4f 18 mov 0x18(%rdi),%rcx
ffffffff81108e77: 80 3c 11 00 cmpb $0x0,(%rcx,%rdx,1)
ffffffff81108e7b: 74 06 je ffffffff81108e83 <do_last.isra.44+0xb0>
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
ffffffff81108e7d: 83 c8 03 or $0x3,%eax
ffffffff81108e80: 89 47 38 mov %eax,0x38(%rdi)
if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
ffffffff81108e83: f7 45 94 00 00 20 00 testl $0x200000,-0x6c(%rbp)
int open_flag = op->open_flag;
bool will_truncate = (open_flag & O_TRUNC) != 0;
bool got_write = false;
int acc_mode = op->acc_mode;
struct inode *inode;
bool symlink_ok = false;
ffffffff81108e8a: c6 45 93 00 movb $0x0,-0x6d(%rbp)
}
if (!(open_flag & O_CREAT)) {
if (nd->last.name[nd->last.len])
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
ffffffff81108e8e: 74 0f je ffffffff81108e9f <do_last.isra.44+0xcc>
ffffffff81108e90: 8b 43 38 mov 0x38(%rbx),%eax
ffffffff81108e93: 83 e0 01 and $0x1,%eax
ffffffff81108e96: 83 f0 01 xor $0x1,%eax
ffffffff81108e99: 83 e0 01 and $0x1,%eax
ffffffff81108e9c: 88 45 93 mov %al,-0x6d(%rbp)
symlink_ok = true;
/* we _can_ be in RCU mode here */
error = lookup_fast(nd, path, &inode);
ffffffff81108e9f: 48 8d 55 b8 lea -0x48(%rbp),%rdx
ffffffff81108ea3: 4c 89 e6 mov %r12,%rsi
ffffffff81108ea6: 48 89 df mov %rbx,%rdi
ffffffff81108ea9: e8 eb cc ff ff callq ffffffff81105b99 <lookup_fast>
if (likely(!error))
ffffffff81108eae: 83 f8 00 cmp $0x0,%eax
if (nd->last.name[nd->last.len])
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
symlink_ok = true;
/* we _can_ be in RCU mode here */
error = lookup_fast(nd, path, &inode);
ffffffff81108eb1: 41 89 c6 mov %eax,%r14d
bool got_write = false;
int acc_mode = op->acc_mode;
struct inode *inode;
bool symlink_ok = false;
struct path save_parent = { .dentry = NULL, .mnt = NULL };
bool retried = false;
ffffffff81108eb4: c6 45 92 00 movb $0x0,-0x6e(%rbp)
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
symlink_ok = true;
/* we _can_ be in RCU mode here */
error = lookup_fast(nd, path, &inode);
if (likely(!error))
ffffffff81108eb8: 0f 84 9d 05 00 00 je ffffffff8110945b <do_last.isra.44+0x688>
goto finish_lookup;
if (error < 0)
ffffffff81108ebe: 0f 8c f5 07 00 00 jl ffffffff811096b9 <do_last.isra.44+0x8e6>
goto out;
BUG_ON(nd->inode != dir->d_inode);
ffffffff81108ec4: 48 8b 45 80 mov -0x80(%rbp),%rax
ffffffff81108ec8: 48 8b 40 30 mov 0x30(%rax),%rax
ffffffff81108ecc: 48 39 43 30 cmp %rax,0x30(%rbx)
ffffffff81108ed0: 74 32 je ffffffff81108f04 <do_last.isra.44+0x131>
ffffffff81108ed2: 0f 0b ud2
/*
* This will *only* deal with leaving RCU mode - LOOKUP_JUMPED
* has been cleared when we got to the last component we are
* about to look up
*/
error = complete_walk(nd);
ffffffff81108ed4: e8 d8 c1 ff ff callq ffffffff811050b1 <complete_walk>
if (error)
ffffffff81108ed9: 85 c0 test %eax,%eax
/*
* This will *only* deal with leaving RCU mode - LOOKUP_JUMPED
* has been cleared when we got to the last component we are
* about to look up
*/
error = complete_walk(nd);
ffffffff81108edb: 41 89 c6 mov %eax,%r14d
if (error)
ffffffff81108ede: 0f 85 c7 08 00 00 jne ffffffff811097ab <do_last.isra.44+0x9d8>
return error;
audit_inode(name, dir, LOOKUP_PARENT);
error = -EISDIR;
/* trailing slashes? */
if (nd->last.name[nd->last.len])
ffffffff81108ee4: 8b 43 14 mov 0x14(%rbx),%eax
ffffffff81108ee7: 48 8b 53 18 mov 0x18(%rbx),%rdx
ffffffff81108eeb: 80 3c 02 00 cmpb $0x0,(%rdx,%rax,1)
ffffffff81108eef: 74 0b je ffffffff81108efc <do_last.isra.44+0x129>
error = complete_walk(nd);
if (error)
return error;
audit_inode(name, dir, LOOKUP_PARENT);
error = -EISDIR;
ffffffff81108ef1: 41 be eb ff ff ff mov $0xffffffeb,%r14d
ffffffff81108ef7: e9 bd 07 00 00 jmpq ffffffff811096b9 <do_last.isra.44+0x8e6>
bool got_write = false;
int acc_mode = op->acc_mode;
struct inode *inode;
bool symlink_ok = false;
struct path save_parent = { .dentry = NULL, .mnt = NULL };
bool retried = false;
ffffffff81108efc: c6 45 92 00 movb $0x0,-0x6e(%rbp)
int open_flag = op->open_flag;
bool will_truncate = (open_flag & O_TRUNC) != 0;
bool got_write = false;
int acc_mode = op->acc_mode;
struct inode *inode;
bool symlink_ok = false;
ffffffff81108f00: c6 45 93 00 movb $0x0,-0x6d(%rbp)
if (nd->last.name[nd->last.len])
goto out;
}
retry_lookup:
if (op->open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {
ffffffff81108f04: 48 8b 55 98 mov -0x68(%rbp),%rdx
ffffffff81108f08: c6 45 ab 00 movb $0x0,-0x55(%rbp)
ffffffff81108f0c: f7 02 43 02 00 00 testl $0x243,(%rdx)
ffffffff81108f12: 74 0e je ffffffff81108f22 <do_last.isra.44+0x14f>
error = mnt_want_write(nd->path.mnt);
ffffffff81108f14: 48 8b 3b mov (%rbx),%rdi
ffffffff81108f17: e8 2c d2 00 00 callq ffffffff81116148 <mnt_want_write>
if (!error)
ffffffff81108f1c: 85 c0 test %eax,%eax
ffffffff81108f1e: 0f 94 45 ab sete -0x55(%rbp)
* do _not_ fail yet - we might not need that or fail with
* a different error; let lookup_open() decide; we'll be
* dropping this one anyway.
*/
}
mutex_lock(&dir->d_inode->i_mutex);
ffffffff81108f22: 48 8b 45 80 mov -0x80(%rbp),%rax
ffffffff81108f26: 48 8b 40 30 mov 0x30(%rax),%rax
ffffffff81108f2a: 48 89 c7 mov %rax,%rdi
ffffffff81108f2d: 48 81 c7 a0 00 00 00 add $0xa0,%rdi
ffffffff81108f34: e8 7e 8b 27 00 callq ffffffff81381ab7 <mutex_lock>
static int lookup_open(struct nameidata *nd, struct path *path,
struct file *file,
const struct open_flags *op,
bool got_write, int *opened)
{
struct dentry *dir = nd->path.dentry;
ffffffff81108f39: 4c 8b 73 08 mov 0x8(%rbx),%r14
struct inode *dir_inode = dir->d_inode;
struct dentry *dentry;
int error;
bool need_lookup;
*opened &= ~FILE_CREATED;
ffffffff81108f3d: 48 8b 55 a0 mov -0x60(%rbp),%rdx
dentry = lookup_dcache(&nd->last, dir, nd->flags, &need_lookup);
ffffffff81108f41: 48 8d 7b 10 lea 0x10(%rbx),%rdi
ffffffff81108f45: 48 8d 4d b7 lea -0x49(%rbp),%rcx
struct file *file,
const struct open_flags *op,
bool got_write, int *opened)
{
struct dentry *dir = nd->path.dentry;
struct inode *dir_inode = dir->d_inode;
ffffffff81108f49: 4d 8b 46 30 mov 0x30(%r14),%r8
struct dentry *dentry;
int error;
bool need_lookup;
*opened &= ~FILE_CREATED;
ffffffff81108f4d: 83 22 fe andl $0xfffffffe,(%rdx)
dentry = lookup_dcache(&nd->last, dir, nd->flags, &need_lookup);
ffffffff81108f50: 4c 89 f6 mov %r14,%rsi
ffffffff81108f53: 8b 53 38 mov 0x38(%rbx),%edx
ffffffff81108f56: 4c 89 85 60 ff ff ff mov %r8,-0xa0(%rbp)
ffffffff81108f5d: e8 50 c8 ff ff callq ffffffff811057b2 <lookup_dcache>
if (IS_ERR(dentry))
ffffffff81108f62: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax
struct dentry *dentry;
int error;
bool need_lookup;
*opened &= ~FILE_CREATED;
dentry = lookup_dcache(&nd->last, dir, nd->flags, &need_lookup);
ffffffff81108f68: 49 89 c7 mov %rax,%r15
if (IS_ERR(dentry))
ffffffff81108f6b: 4c 8b 85 60 ff ff ff mov -0xa0(%rbp),%r8
ffffffff81108f72: 76 05 jbe ffffffff81108f79 <do_last.isra.44+0x1a6>
ffffffff81108f74: e9 61 03 00 00 jmpq ffffffff811092da <do_last.isra.44+0x507>
return PTR_ERR(dentry);
/* Cached positive dentry: will open in f_op->open */
if (!need_lookup && dentry->d_inode)
ffffffff81108f79: 8a 45 b7 mov -0x49(%rbp),%al
ffffffff81108f7c: 84 c0 test %al,%al
ffffffff81108f7e: 88 45 a9 mov %al,-0x57(%rbp)
ffffffff81108f81: 75 0b jne ffffffff81108f8e <do_last.isra.44+0x1bb>
ffffffff81108f83: 49 83 7f 30 00 cmpq $0x0,0x30(%r15)
ffffffff81108f88: 0f 85 b7 03 00 00 jne ffffffff81109345 <do_last.isra.44+0x572>
goto out_no_open;
if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) {
ffffffff81108f8e: 8b 53 38 mov 0x38(%rbx),%edx
ffffffff81108f91: f6 c6 01 test $0x1,%dh
ffffffff81108f94: 0f 84 1b 03 00 00 je ffffffff811092b5 <do_last.isra.44+0x4e2>
ffffffff81108f9a: 49 8b 40 20 mov 0x20(%r8),%rax
ffffffff81108f9e: 48 83 b8 b8 00 00 00 cmpq $0x0,0xb8(%rax)
ffffffff81108fa5: 00
ffffffff81108fa6: 0f 84 09 03 00 00 je ffffffff811092b5 <do_last.isra.44+0x4e2>
struct path *path, struct file *file,
const struct open_flags *op,
bool got_write, bool need_lookup,
int *opened)
{
struct inode *dir = nd->path.dentry->d_inode;
ffffffff81108fac: 48 8b 43 08 mov 0x8(%rbx),%rax
unsigned open_flag = open_to_namei_flags(op->open_flag);
ffffffff81108fb0: 48 8b 55 98 mov -0x68(%rbp),%rdx
struct path *path, struct file *file,
const struct open_flags *op,
bool got_write, bool need_lookup,
int *opened)
{
struct inode *dir = nd->path.dentry->d_inode;
ffffffff81108fb4: 48 8b 40 30 mov 0x30(%rax),%rax
unsigned open_flag = open_to_namei_flags(op->open_flag);
ffffffff81108fb8: 44 8b 32 mov (%rdx),%r14d
struct path *path, struct file *file,
const struct open_flags *op,
bool got_write, bool need_lookup,
int *opened)
{
struct inode *dir = nd->path.dentry->d_inode;
ffffffff81108fbb: 48 89 45 88 mov %rax,-0x78(%rbp)
return error;
}
static inline int open_to_namei_flags(int flag)
{
if ((flag & O_ACCMODE) == 3)
ffffffff81108fbf: 44 89 f0 mov %r14d,%eax
ffffffff81108fc2: 83 e0 03 and $0x3,%eax
flag--;
ffffffff81108fc5: 83 f8 03 cmp $0x3,%eax
ffffffff81108fc8: 0f 94 c0 sete %al
ffffffff81108fcb: 0f b6 c0 movzbl %al,%eax
ffffffff81108fce: 41 29 c6 sub %eax,%r14d
int acc_mode;
int create_error = 0;
struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
bool excl;
BUG_ON(dentry->d_inode);
ffffffff81108fd1: 49 83 7f 30 00 cmpq $0x0,0x30(%r15)
ffffffff81108fd6: 74 02 je ffffffff81108fda <do_last.isra.44+0x207>
ffffffff81108fd8: 0f 0b ud2
/* Don't create child dentry for a dead directory. */
if (unlikely(IS_DEADDIR(dir))) {
ffffffff81108fda: 48 8b 45 88 mov -0x78(%rbp),%rax
ffffffff81108fde: f6 40 0c 10 testb $0x10,0xc(%rax)
ffffffff81108fe2: 0f 85 3d 02 00 00 jne ffffffff81109225 <do_last.isra.44+0x452>
error = -ENOENT;
goto out;
}
mode = op->mode;
ffffffff81108fe8: 48 8b 55 98 mov -0x68(%rbp),%rdx
if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))
ffffffff81108fec: 41 f6 c6 40 test $0x40,%r14b
if (unlikely(IS_DEADDIR(dir))) {
error = -ENOENT;
goto out;
}
mode = op->mode;
ffffffff81108ff0: 8b 52 04 mov 0x4(%rdx),%edx
ffffffff81108ff3: 66 89 55 90 mov %dx,-0x70(%rbp)
if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))
ffffffff81108ff7: 74 15 je ffffffff8110900e <do_last.isra.44+0x23b>
ffffffff81108ff9: 48 8b 40 28 mov 0x28(%rax),%rax
ffffffff81108ffd: f6 40 52 01 testb $0x1,0x52(%rax)
ffffffff81109001: 75 0b jne ffffffff8110900e <do_last.isra.44+0x23b>
mode &= ~current_umask();
ffffffff81109003: e8 c0 a5 01 00 callq ffffffff811235c8 <current_umask>
ffffffff81109008: f7 d0 not %eax
ffffffff8110900a: 66 21 45 90 and %ax,-0x70(%rbp)
excl = (open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT);
ffffffff8110900e: 44 89 f0 mov %r14d,%eax
ffffffff81109011: 25 c0 00 00 00 and $0xc0,%eax
ffffffff81109016: 3d c0 00 00 00 cmp $0xc0,%eax
if (excl)
open_flag &= ~O_TRUNC;
ffffffff8110901b: 44 89 f0 mov %r14d,%eax
mode = op->mode;
if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))
mode &= ~current_umask();
excl = (open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT);
ffffffff8110901e: 0f 94 45 a8 sete -0x58(%rbp)
if (excl)
open_flag &= ~O_TRUNC;
ffffffff81109022: 80 e4 fd and $0xfd,%ah
ffffffff81109025: 80 7d a8 00 cmpb $0x0,-0x58(%rbp)
ffffffff81109029: 44 0f 45 f0 cmovne %eax,%r14d
ffffffff8110902d: 44 89 75 ac mov %r14d,-0x54(%rbp)
* to check access and if not granted clear O_CREAT from the flags.
*
* Another problem is returing the "right" error value (e.g. for an
* O_EXCL open we want to return EEXIST not EROFS).
*/
if (((open_flag & (O_CREAT | O_TRUNC)) ||
ffffffff81109031: 41 81 e6 43 02 00 00 and $0x243,%r14d
struct inode *dir = nd->path.dentry->d_inode;
unsigned open_flag = open_to_namei_flags(op->open_flag);
umode_t mode;
int error;
int acc_mode;
int create_error = 0;
ffffffff81109038: 41 be 00 00 00 00 mov $0x0,%r14d
* to check access and if not granted clear O_CREAT from the flags.
*
* Another problem is returing the "right" error value (e.g. for an
* O_EXCL open we want to return EEXIST not EROFS).
*/
if (((open_flag & (O_CREAT | O_TRUNC)) ||
ffffffff8110903e: 74 27 je ffffffff81109067 <do_last.isra.44+0x294>
(open_flag & O_ACCMODE) != O_RDONLY) && unlikely(!got_write)) {
ffffffff81109040: 80 7d ab 00 cmpb $0x0,-0x55(%rbp)
ffffffff81109044: 75 21 jne ffffffff81109067 <do_last.isra.44+0x294>
if (!(open_flag & O_CREAT)) {
ffffffff81109046: f6 45 ac 40 testb $0x40,-0x54(%rbp)
ffffffff8110904a: 0f 84 f9 01 00 00 je ffffffff81109249 <do_last.isra.44+0x476>
/*
* No O_CREATE -> atomicity not a requirement -> fall
* back to lookup + open
*/
goto no_open;
} else if (open_flag & (O_EXCL | O_TRUNC)) {
ffffffff81109050: f7 45 ac 80 02 00 00 testl $0x280,-0x54(%rbp)
ffffffff81109057: 0f 85 e6 01 00 00 jne ffffffff81109243 <do_last.isra.44+0x470>
create_error = -EROFS;
goto no_open;
} else {
/* No side effects, safe to clear O_CREAT */
create_error = -EROFS;
open_flag &= ~O_CREAT;
ffffffff8110905d: 83 65 ac bf andl $0xffffffbf,-0x54(%rbp)
/* Fall back and fail with the right error */
create_error = -EROFS;
goto no_open;
} else {
/* No side effects, safe to clear O_CREAT */
create_error = -EROFS;
ffffffff81109061: 41 be e2 ff ff ff mov $0xffffffe2,%r14d
open_flag &= ~O_CREAT;
}
}
if (open_flag & O_CREAT) {
ffffffff81109067: f6 45 ac 40 testb $0x40,-0x54(%rbp)
ffffffff8110906b: 74 3f je ffffffff811090ac <do_last.isra.44+0x2d9>
{
int error = security_path_mknod(dir, dentry, mode, 0);
if (error)
return error;
error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
ffffffff8110906d: 48 8b 43 08 mov 0x8(%rbx),%rax
ffffffff81109071: be 03 00 00 00 mov $0x3,%esi
ffffffff81109076: 48 8b 78 30 mov 0x30(%rax),%rdi
ffffffff8110907a: e8 7c d2 ff ff callq ffffffff811062fb <inode_permission>
if (error)
ffffffff8110907f: 85 c0 test %eax,%eax
ffffffff81109081: 75 18 jne ffffffff8110909b <do_last.isra.44+0x2c8>
return error;
return security_inode_create(dir->dentry->d_inode, dentry, mode);
ffffffff81109083: 48 8b 43 08 mov 0x8(%rbx),%rax
ffffffff81109087: 0f b7 55 90 movzwl -0x70(%rbp),%edx
ffffffff8110908b: 4c 89 fe mov %r15,%rsi
ffffffff8110908e: 48 8b 78 30 mov 0x30(%rax),%rdi
ffffffff81109092: e8 3c d0 0d 00 callq ffffffff811e60d3 <security_inode_create>
}
}
if (open_flag & O_CREAT) {
error = may_o_create(&nd->path, dentry, mode);
if (error) {
ffffffff81109097: 85 c0 test %eax,%eax
ffffffff81109099: 74 11 je ffffffff811090ac <do_last.isra.44+0x2d9>
create_error = error;
if (open_flag & O_EXCL)
ffffffff8110909b: f6 45 ac 80 testb $0x80,-0x54(%rbp)
int error = security_path_mknod(dir, dentry, mode, 0);
if (error)
return error;
error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
if (error)
ffffffff8110909f: 41 89 c6 mov %eax,%r14d
if (open_flag & O_CREAT) {
error = may_o_create(&nd->path, dentry, mode);
if (error) {
create_error = error;
if (open_flag & O_EXCL)
ffffffff811090a2: 0f 85 a1 01 00 00 jne ffffffff81109249 <do_last.isra.44+0x476>
goto no_open;
open_flag &= ~O_CREAT;
ffffffff811090a8: 83 65 ac bf andl $0xffffffbf,-0x54(%rbp)
}
}
if (nd->flags & LOOKUP_DIRECTORY)
open_flag |= O_DIRECTORY;
ffffffff811090ac: 8b 45 ac mov -0x54(%rbp),%eax
file->f_path.dentry = DENTRY_NOT_SET;
file->f_path.mnt = nd->path.mnt;
error = dir->i_op->atomic_open(dir, dentry, file, open_flag, mode,
ffffffff811090af: 48 8b 55 88 mov -0x78(%rbp),%rdx
ffffffff811090b3: 4c 89 fe mov %r15,%rsi
ffffffff811090b6: 44 0f b7 45 90 movzwl -0x70(%rbp),%r8d
ffffffff811090bb: 4c 8b 4d a0 mov -0x60(%rbp),%r9
ffffffff811090bf: 48 8b 7d 88 mov -0x78(%rbp),%rdi
open_flag &= ~O_CREAT;
}
}
if (nd->flags & LOOKUP_DIRECTORY)
open_flag |= O_DIRECTORY;
ffffffff811090c3: 0d 00 00 01 00 or $0x10000,%eax
ffffffff811090c8: f6 43 38 02 testb $0x2,0x38(%rbx)
file->f_path.dentry = DENTRY_NOT_SET;
ffffffff811090cc: 49 c7 45 18 ff ff ff movq $0xffffffffffffffff,0x18(%r13)
ffffffff811090d3: ff
open_flag &= ~O_CREAT;
}
}
if (nd->flags & LOOKUP_DIRECTORY)
open_flag |= O_DIRECTORY;
ffffffff811090d4: 0f 44 45 ac cmove -0x54(%rbp),%eax
ffffffff811090d8: 89 45 ac mov %eax,-0x54(%rbp)
file->f_path.dentry = DENTRY_NOT_SET;
file->f_path.mnt = nd->path.mnt;
ffffffff811090db: 48 8b 03 mov (%rbx),%rax
error = dir->i_op->atomic_open(dir, dentry, file, open_flag, mode,
ffffffff811090de: 8b 4d ac mov -0x54(%rbp),%ecx
if (nd->flags & LOOKUP_DIRECTORY)
open_flag |= O_DIRECTORY;
file->f_path.dentry = DENTRY_NOT_SET;
file->f_path.mnt = nd->path.mnt;
ffffffff811090e1: 49 89 45 10 mov %rax,0x10(%r13)
error = dir->i_op->atomic_open(dir, dentry, file, open_flag, mode,
ffffffff811090e5: 48 8b 42 20 mov 0x20(%rdx),%rax
ffffffff811090e9: 4c 89 ea mov %r13,%rdx
ffffffff811090ec: ff 90 b8 00 00 00 callq *0xb8(%rax)
opened);
if (error < 0) {
ffffffff811090f2: 83 f8 00 cmp $0x0,%eax
ffffffff811090f5: 7d 17 jge ffffffff8110910e <do_last.isra.44+0x33b>
if (create_error && error == -ENOENT)
ffffffff811090f7: 83 f8 fe cmp $0xfffffffe,%eax
ffffffff811090fa: 0f 85 30 01 00 00 jne ffffffff81109230 <do_last.isra.44+0x45d>
ffffffff81109100: 45 85 f6 test %r14d,%r14d
ffffffff81109103: 0f 85 56 02 00 00 jne ffffffff8110935f <do_last.isra.44+0x58c>
ffffffff81109109: e9 22 01 00 00 jmpq ffffffff81109230 <do_last.isra.44+0x45d>
error = create_error;
goto out;
}
if (error) { /* returned 1, that is */
ffffffff8110910e: 0f 84 a3 00 00 00 je ffffffff811091b7 <do_last.isra.44+0x3e4>
if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
ffffffff81109114: 49 8b 45 18 mov 0x18(%r13),%rax
ffffffff81109118: 48 83 f8 ff cmp $0xffffffffffffffff,%rax
ffffffff8110911c: 0f 85 41 06 00 00 jne ffffffff81109763 <do_last.isra.44+0x990>
ffffffff81109122: be 98 0a 00 00 mov $0xa98,%esi
ffffffff81109127: 48 c7 c7 91 a0 4e 81 mov $0xffffffff814ea091,%rdi
error = -EIO;
ffffffff8110912e: 41 be fb ff ff ff mov $0xfffffffb,%r14d
error = create_error;
goto out;
}
if (error) { /* returned 1, that is */
if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
ffffffff81109134: e8 9a 05 f3 ff callq ffffffff810396d3 <warn_slowpath_null>
ffffffff81109139: e9 21 02 00 00 jmpq ffffffff8110935f <do_last.isra.44+0x58c>
error = -EIO;
goto out;
}
if (file->f_path.dentry) {
dput(dentry);
ffffffff8110913e: 4c 89 ff mov %r15,%rdi
ffffffff81109141: e8 83 65 00 00 callq ffffffff8110f6c9 <dput>
dentry = file->f_path.dentry;
ffffffff81109146: 4d 8b 7d 18 mov 0x18(%r13),%r15
}
if (*opened & FILE_CREATED)
ffffffff8110914a: 48 8b 45 a0 mov -0x60(%rbp),%rax
ffffffff8110914e: f6 00 01 testb $0x1,(%rax)
ffffffff81109151: 74 1e je ffffffff81109171 <do_last.isra.44+0x39e>
*/
static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
{
audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
ffffffff81109153: 49 8b 57 30 mov 0x30(%r15),%rdx
ffffffff81109157: 4d 8b 47 28 mov 0x28(%r15),%r8
ffffffff8110915b: 45 31 c9 xor %r9d,%r9d
ffffffff8110915e: 48 8b 7d 88 mov -0x78(%rbp),%rdi
ffffffff81109162: b9 02 00 00 00 mov $0x2,%ecx
ffffffff81109167: be 00 01 00 00 mov $0x100,%esi
ffffffff8110916c: e8 d4 73 02 00 callq ffffffff81130545 <fsnotify>
fsnotify_create(dir, dentry);
if (!dentry->d_inode) {
ffffffff81109171: 49 83 7f 30 00 cmpq $0x0,0x30(%r15)
ffffffff81109176: 75 23 jne ffffffff8110919b <do_last.isra.44+0x3c8>
WARN_ON(*opened & FILE_CREATED);
ffffffff81109178: 48 8b 55 a0 mov -0x60(%rbp),%rdx
ffffffff8110917c: f6 02 01 testb $0x1,(%rdx)
ffffffff8110917f: 0f 84 bb 01 00 00 je ffffffff81109340 <do_last.isra.44+0x56d>
ffffffff81109185: be a3 0a 00 00 mov $0xaa3,%esi
ffffffff8110918a: 48 c7 c7 91 a0 4e 81 mov $0xffffffff814ea091,%rdi
ffffffff81109191: e8 3d 05 f3 ff callq ffffffff810396d3 <warn_slowpath_null>
ffffffff81109196: e9 a5 01 00 00 jmpq ffffffff81109340 <do_last.isra.44+0x56d>
if (create_error) {
error = create_error;
goto out;
}
} else {
if (excl && !(*opened & FILE_CREATED)) {
ffffffff8110919b: 80 7d a8 00 cmpb $0x0,-0x58(%rbp)
ffffffff8110919f: 0f 84 a0 01 00 00 je ffffffff81109345 <do_last.isra.44+0x572>
ffffffff811091a5: 48 8b 45 a0 mov -0x60(%rbp),%rax
ffffffff811091a9: f6 00 01 testb $0x1,(%rax)
ffffffff811091ac: 0f 85 93 01 00 00 jne ffffffff81109345 <do_last.isra.44+0x572>
ffffffff811091b2: e9 81 00 00 00 jmpq ffffffff81109238 <do_last.isra.44+0x465>
/*
* We didn't have the inode before the open, so check open permission
* here.
*/
acc_mode = op->acc_mode;
if (*opened & FILE_CREATED) {
ffffffff811091b7: 48 8b 45 a0 mov -0x60(%rbp),%rax
/*
* We didn't have the inode before the open, so check open permission
* here.
*/
acc_mode = op->acc_mode;
ffffffff811091bb: 48 8b 55 98 mov -0x68(%rbp),%rdx
if (*opened & FILE_CREATED) {
ffffffff811091bf: f6 00 01 testb $0x1,(%rax)
/*
* We didn't have the inode before the open, so check open permission
* here.
*/
acc_mode = op->acc_mode;
ffffffff811091c2: 8b 72 08 mov 0x8(%rdx),%esi
if (*opened & FILE_CREATED) {
ffffffff811091c5: 74 3a je ffffffff81109201 <do_last.isra.44+0x42e>
WARN_ON(!(open_flag & O_CREAT));
ffffffff811091c7: f6 45 ac 40 testb $0x40,-0x54(%rbp)
ffffffff811091cb: 75 11 jne ffffffff811091de <do_last.isra.44+0x40b>
ffffffff811091cd: be b7 0a 00 00 mov $0xab7,%esi
ffffffff811091d2: 48 c7 c7 91 a0 4e 81 mov $0xffffffff814ea091,%rdi
ffffffff811091d9: e8 f5 04 f3 ff callq ffffffff810396d3 <warn_slowpath_null>
ffffffff811091de: 49 8b 57 30 mov 0x30(%r15),%rdx
ffffffff811091e2: 4d 8b 47 28 mov 0x28(%r15),%r8
ffffffff811091e6: be 00 01 00 00 mov $0x100,%esi
ffffffff811091eb: 48 8b 7d 88 mov -0x78(%rbp),%rdi
ffffffff811091ef: 45 31 c9 xor %r9d,%r9d
ffffffff811091f2: b9 02 00 00 00 mov $0x2,%ecx
ffffffff811091f7: e8 49 73 02 00 callq ffffffff81130545 <fsnotify>
fsnotify_create(dir, dentry);
acc_mode = MAY_OPEN;
ffffffff811091fc: be 20 00 00 00 mov $0x20,%esi
}
error = may_open(&file->f_path, acc_mode, open_flag);
ffffffff81109201: 8b 55 ac mov -0x54(%rbp),%edx
ffffffff81109204: 49 8d 7d 10 lea 0x10(%r13),%rdi
ffffffff81109208: e8 dc fa ff ff callq ffffffff81108ce9 <may_open>
if (error)
ffffffff8110920d: 85 c0 test %eax,%eax
if (*opened & FILE_CREATED) {
WARN_ON(!(open_flag & O_CREAT));
fsnotify_create(dir, dentry);
acc_mode = MAY_OPEN;
}
error = may_open(&file->f_path, acc_mode, open_flag);
ffffffff8110920f: 41 89 c6 mov %eax,%r14d
if (error)
ffffffff81109212: 0f 84 47 01 00 00 je ffffffff8110935f <do_last.isra.44+0x58c>
fput(file);
ffffffff81109218: 4c 89 ef mov %r13,%rdi
ffffffff8110921b: e8 d6 56 ff ff callq ffffffff810fe8f6 <fput>
ffffffff81109220: e9 3a 01 00 00 jmpq ffffffff8110935f <do_last.isra.44+0x58c>
BUG_ON(dentry->d_inode);
/* Don't create child dentry for a dead directory. */
if (unlikely(IS_DEADDIR(dir))) {
error = -ENOENT;
ffffffff81109225: 41 be fe ff ff ff mov $0xfffffffe,%r14d
ffffffff8110922b: e9 2f 01 00 00 jmpq ffffffff8110935f <do_last.isra.44+0x58c>
file->f_path.dentry = DENTRY_NOT_SET;
file->f_path.mnt = nd->path.mnt;
error = dir->i_op->atomic_open(dir, dentry, file, open_flag, mode,
opened);
if (error < 0) {
if (create_error && error == -ENOENT)
ffffffff81109230: 41 89 c6 mov %eax,%r14d
ffffffff81109233: e9 27 01 00 00 jmpq ffffffff8110935f <do_last.isra.44+0x58c>
error = create_error;
goto out;
}
} else {
if (excl && !(*opened & FILE_CREATED)) {
error = -EEXIST;
ffffffff81109238: 41 be ef ff ff ff mov $0xffffffef,%r14d
ffffffff8110923e: e9 1c 01 00 00 jmpq ffffffff8110935f <do_last.isra.44+0x58c>
* back to lookup + open
*/
goto no_open;
} else if (open_flag & (O_EXCL | O_TRUNC)) {
/* Fall back and fail with the right error */
create_error = -EROFS;
ffffffff81109243: 41 be e2 ff ff ff mov $0xffffffe2,%r14d
out:
dput(dentry);
return error;
no_open:
if (need_lookup) {
ffffffff81109249: 80 7d a9 00 cmpb $0x0,-0x57(%rbp)
ffffffff8110924d: 0f 84 f2 00 00 00 je ffffffff81109345 <do_last.isra.44+0x572>
dentry = lookup_real(dir, dentry, nd->flags);
ffffffff81109253: 8b 53 38 mov 0x38(%rbx),%edx
ffffffff81109256: 48 8b 7d 88 mov -0x78(%rbp),%rdi
ffffffff8110925a: 4c 89 fe mov %r15,%rsi
ffffffff8110925d: e8 82 bc ff ff callq ffffffff81104ee4 <lookup_real>
if (IS_ERR(dentry))
ffffffff81109262: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax
dput(dentry);
return error;
no_open:
if (need_lookup) {
dentry = lookup_real(dir, dentry, nd->flags);
ffffffff81109268: 49 89 c7 mov %rax,%r15
if (IS_ERR(dentry))
ffffffff8110926b: 76 02 jbe ffffffff8110926f <do_last.isra.44+0x49c>
ffffffff8110926d: eb 6b jmp ffffffff811092da <do_last.isra.44+0x507>
return PTR_ERR(dentry);
if (create_error) {
ffffffff8110926f: 45 85 f6 test %r14d,%r14d
ffffffff81109272: 0f 84 cd 00 00 00 je ffffffff81109345 <do_last.isra.44+0x572>
int open_flag = op->open_flag;
ffffffff81109278: 48 8b 45 98 mov -0x68(%rbp),%rax
ffffffff8110927c: 8b 10 mov (%rax),%edx
error = create_error;
if ((open_flag & O_EXCL)) {
ffffffff8110927e: f6 c2 80 test $0x80,%dl
ffffffff81109281: 74 07 je ffffffff8110928a <do_last.isra.44+0x4b7>
if (!dentry->d_inode)
ffffffff81109283: 49 83 7f 30 00 cmpq $0x0,0x30(%r15)
ffffffff81109288: eb 20 jmp ffffffff811092aa <do_last.isra.44+0x4d7>
goto out;
} else if (!dentry->d_inode) {
ffffffff8110928a: 49 8b 47 30 mov 0x30(%r15),%rax
ffffffff8110928e: 48 85 c0 test %rax,%rax
ffffffff81109291: 0f 84 c8 00 00 00 je ffffffff8110935f <do_last.isra.44+0x58c>
goto out;
} else if ((open_flag & O_TRUNC) &&
ffffffff81109297: 80 e6 02 and $0x2,%dh
ffffffff8110929a: 0f 84 a5 00 00 00 je ffffffff81109345 <do_last.isra.44+0x572>
S_ISREG(dentry->d_inode->i_mode)) {
ffffffff811092a0: 8b 00 mov (%rax),%eax
ffffffff811092a2: 66 25 00 f0 and $0xf000,%ax
if ((open_flag & O_EXCL)) {
if (!dentry->d_inode)
goto out;
} else if (!dentry->d_inode) {
goto out;
} else if ((open_flag & O_TRUNC) &&
ffffffff811092a6: 66 3d 00 80 cmp $0x8000,%ax
ffffffff811092aa: 0f 84 af 00 00 00 je ffffffff8110935f <do_last.isra.44+0x58c>
ffffffff811092b0: e9 90 00 00 00 jmpq ffffffff81109345 <do_last.isra.44+0x572>
if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) {
return atomic_open(nd, dentry, path, file, op, got_write,
need_lookup, opened);
}
if (need_lookup) {
ffffffff811092b5: 80 7d a9 00 cmpb $0x0,-0x57(%rbp)
ffffffff811092b9: 74 27 je ffffffff811092e2 <do_last.isra.44+0x50f>
BUG_ON(dentry->d_inode);
ffffffff811092bb: 49 83 7f 30 00 cmpq $0x0,0x30(%r15)
ffffffff811092c0: 74 02 je ffffffff811092c4 <do_last.isra.44+0x4f1>
ffffffff811092c2: 0f 0b ud2
dentry = lookup_real(dir_inode, dentry, nd->flags);
ffffffff811092c4: 4c 89 fe mov %r15,%rsi
ffffffff811092c7: 4c 89 c7 mov %r8,%rdi
ffffffff811092ca: e8 15 bc ff ff callq ffffffff81104ee4 <lookup_real>
if (IS_ERR(dentry))
ffffffff811092cf: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax
}
if (need_lookup) {
BUG_ON(dentry->d_inode);
dentry = lookup_real(dir_inode, dentry, nd->flags);
ffffffff811092d5: 49 89 c7 mov %rax,%r15
if (IS_ERR(dentry))
ffffffff811092d8: 76 08 jbe ffffffff811092e2 <do_last.isra.44+0x50f>
return PTR_ERR(dentry);
ffffffff811092da: 45 89 fe mov %r15d,%r14d
ffffffff811092dd: e9 85 00 00 00 jmpq ffffffff81109367 <do_last.isra.44+0x594>
}
/* Negative dentry, just create the file */
if (!dentry->d_inode && (op->open_flag & O_CREAT)) {
ffffffff811092e2: 49 83 7f 30 00 cmpq $0x0,0x30(%r15)
ffffffff811092e7: 75 5c jne ffffffff81109345 <do_last.isra.44+0x572>
ffffffff811092e9: 48 8b 55 98 mov -0x68(%rbp),%rdx
ffffffff811092ed: f6 02 40 testb $0x40,(%rdx)
ffffffff811092f0: 74 53 je ffffffff81109345 <do_last.isra.44+0x572>
umode_t mode = op->mode;
if (!IS_POSIXACL(dir->d_inode))
ffffffff811092f2: 49 8b 46 30 mov 0x30(%r14),%rax
return PTR_ERR(dentry);
}
/* Negative dentry, just create the file */
if (!dentry->d_inode && (op->open_flag & O_CREAT)) {
umode_t mode = op->mode;
ffffffff811092f6: 8b 52 04 mov 0x4(%rdx),%edx
if (!IS_POSIXACL(dir->d_inode))
ffffffff811092f9: 48 8b 40 28 mov 0x28(%rax),%rax
ffffffff811092fd: f6 40 52 01 testb $0x1,0x52(%rax)
ffffffff81109301: 75 15 jne ffffffff81109318 <do_last.isra.44+0x545>
mode &= ~current_umask();
ffffffff81109303: 89 95 60 ff ff ff mov %edx,-0xa0(%rbp)
ffffffff81109309: e8 ba a2 01 00 callq ffffffff811235c8 <current_umask>
ffffffff8110930e: 8b 95 60 ff ff ff mov -0xa0(%rbp),%edx
ffffffff81109314: f7 d0 not %eax
ffffffff81109316: 21 c2 and %eax,%edx
* rw->ro transition does not occur between
* the time when the file is created and when
* a permanent write count is taken through
* the 'struct file' in finish_open().
*/
if (!got_write) {
ffffffff81109318: 80 7d ab 00 cmpb $0x0,-0x55(%rbp)
ffffffff8110931c: 74 3b je ffffffff81109359 <do_last.isra.44+0x586>
error = -EROFS;
goto out_dput;
}
*opened |= FILE_CREATED;
ffffffff8110931e: 48 8b 45 a0 mov -0x60(%rbp),%rax
error = security_path_mknod(&nd->path, dentry, mode, 0);
if (error)
goto out_dput;
error = vfs_create(dir->d_inode, dentry, mode,
ffffffff81109322: 0f b7 d2 movzwl %dx,%edx
ffffffff81109325: 4c 89 fe mov %r15,%rsi
*/
if (!got_write) {
error = -EROFS;
goto out_dput;
}
*opened |= FILE_CREATED;
ffffffff81109328: 83 08 01 orl $0x1,(%rax)
error = security_path_mknod(&nd->path, dentry, mode, 0);
if (error)
goto out_dput;
error = vfs_create(dir->d_inode, dentry, mode,
ffffffff8110932b: 8b 4b 38 mov 0x38(%rbx),%ecx
ffffffff8110932e: 49 8b 7e 30 mov 0x30(%r14),%rdi
ffffffff81109332: c1 e9 0a shr $0xa,%ecx
ffffffff81109335: 83 e1 01 and $0x1,%ecx
ffffffff81109338: e8 94 db ff ff callq ffffffff81106ed1 <vfs_create>
ffffffff8110933d: 41 89 c6 mov %eax,%r14d
nd->flags & LOOKUP_EXCL);
if (error)
ffffffff81109340: 45 85 f6 test %r14d,%r14d
ffffffff81109343: 75 1a jne ffffffff8110935f <do_last.isra.44+0x58c>
goto out_dput;
}
out_no_open:
path->dentry = dentry;
ffffffff81109345: 4d 89 7c 24 08 mov %r15,0x8(%r12)
path->mnt = nd->path.mnt;
ffffffff8110934a: 48 8b 03 mov (%rbx),%rax
return 1;
ffffffff8110934d: 41 be 01 00 00 00 mov $0x1,%r14d
if (error)
goto out_dput;
}
out_no_open:
path->dentry = dentry;
path->mnt = nd->path.mnt;
ffffffff81109353: 49 89 04 24 mov %rax,(%r12)
ffffffff81109357: eb 0e jmp ffffffff81109367 <do_last.isra.44+0x594>
* the time when the file is created and when
* a permanent write count is taken through
* the 'struct file' in finish_open().
*/
if (!got_write) {
error = -EROFS;
ffffffff81109359: 41 be e2 ff ff ff mov $0xffffffe2,%r14d
path->dentry = dentry;
path->mnt = nd->path.mnt;
return 1;
out_dput:
dput(dentry);
ffffffff8110935f: 4c 89 ff mov %r15,%rdi
ffffffff81109362: e8 62 63 00 00 callq ffffffff8110f6c9 <dput>
* dropping this one anyway.
*/
}
mutex_lock(&dir->d_inode->i_mutex);
error = lookup_open(nd, path, file, op, got_write, opened);
mutex_unlock(&dir->d_inode->i_mutex);
ffffffff81109367: 48 8b 55 80 mov -0x80(%rbp),%rdx
ffffffff8110936b: 48 8b 52 30 mov 0x30(%rdx),%rdx
ffffffff8110936f: 48 89 d7 mov %rdx,%rdi
ffffffff81109372: 48 81 c7 a0 00 00 00 add $0xa0,%rdi
ffffffff81109379: e8 4a 85 27 00 callq ffffffff813818c8 <mutex_unlock>
if (error <= 0) {
ffffffff8110937e: 41 83 fe 00 cmp $0x0,%r14d
ffffffff81109382: 7f 31 jg ffffffff811093b5 <do_last.isra.44+0x5e2>
if (error)
ffffffff81109384: 0f 85 21 03 00 00 jne ffffffff811096ab <do_last.isra.44+0x8d8>
goto out;
if ((*opened & FILE_CREATED) ||
ffffffff8110938a: 48 8b 45 a0 mov -0x60(%rbp),%rax
ffffffff8110938e: f6 00 01 testb $0x1,(%rax)
ffffffff81109391: 0f 85 93 02 00 00 jne ffffffff8110962a <do_last.isra.44+0x857>
!S_ISREG(file_inode(file)->i_mode))
ffffffff81109397: 49 8b 45 20 mov 0x20(%r13),%rax
will_truncate = false;
ffffffff8110939b: 8a 55 aa mov -0x56(%rbp),%dl
if (error <= 0) {
if (error)
goto out;
if ((*opened & FILE_CREATED) ||
!S_ISREG(file_inode(file)->i_mode))
ffffffff8110939e: 8b 00 mov (%rax),%eax
ffffffff811093a0: 66 25 00 f0 and $0xf000,%ax
will_truncate = false;
ffffffff811093a4: 66 3d 00 80 cmp $0x8000,%ax
ffffffff811093a8: b0 00 mov $0x0,%al
ffffffff811093aa: 0f 45 d0 cmovne %eax,%edx
ffffffff811093ad: 88 55 aa mov %dl,-0x56(%rbp)
ffffffff811093b0: e9 79 02 00 00 jmpq ffffffff8110962e <do_last.isra.44+0x85b>
audit_inode(name, file->f_path.dentry, 0);
goto opened;
}
if (*opened & FILE_CREATED) {
ffffffff811093b5: 48 8b 45 a0 mov -0x60(%rbp),%rax
ffffffff811093b9: f6 00 01 testb $0x1,(%rax)
ffffffff811093bc: 74 47 je ffffffff81109405 <do_last.isra.44+0x632>
/* Don't check for write permission, don't truncate */
open_flag &= ~O_TRUNC;
ffffffff811093be: 81 65 94 ff fd ff ff andl $0xfffffdff,-0x6c(%rbp)
}
static inline void path_to_nameidata(const struct path *path,
struct nameidata *nd)
{
if (!(nd->flags & LOOKUP_RCU)) {
ffffffff811093c5: f6 43 38 40 testb $0x40,0x38(%rbx)
ffffffff811093c9: 75 17 jne ffffffff811093e2 <do_last.isra.44+0x60f>
dput(nd->path.dentry);
ffffffff811093cb: 48 8b 7b 08 mov 0x8(%rbx),%rdi
ffffffff811093cf: e8 f5 62 00 00 callq ffffffff8110f6c9 <dput>
if (nd->path.mnt != path->mnt)
ffffffff811093d4: 48 8b 3b mov (%rbx),%rdi
ffffffff811093d7: 49 3b 3c 24 cmp (%r12),%rdi
ffffffff811093db: 74 05 je ffffffff811093e2 <do_last.isra.44+0x60f>
mntput(nd->path.mnt);
ffffffff811093dd: e8 b1 ca 00 00 callq ffffffff81115e93 <mntput>
}
nd->path.mnt = path->mnt;
ffffffff811093e2: 49 8b 04 24 mov (%r12),%rax
}
if (*opened & FILE_CREATED) {
/* Don't check for write permission, don't truncate */
open_flag &= ~O_TRUNC;
will_truncate = false;
ffffffff811093e6: c6 45 aa 00 movb $0x0,-0x56(%rbp)
acc_mode = MAY_OPEN;
ffffffff811093ea: c7 85 7c ff ff ff 20 movl $0x20,-0x84(%rbp)
ffffffff811093f1: 00 00 00
if (!(nd->flags & LOOKUP_RCU)) {
dput(nd->path.dentry);
if (nd->path.mnt != path->mnt)
mntput(nd->path.mnt);
}
nd->path.mnt = path->mnt;
ffffffff811093f4: 48 89 03 mov %rax,(%rbx)
nd->path.dentry = path->dentry;
ffffffff811093f7: 49 8b 44 24 08 mov 0x8(%r12),%rax
ffffffff811093fc: 48 89 43 08 mov %rax,0x8(%rbx)
ffffffff81109400: e9 d9 01 00 00 jmpq ffffffff811095de <do_last.isra.44+0x80b>
/*
* If atomic_open() acquired write access it is dropped now due to
* possible mount and symlink following (this might be optimized away if
* necessary...)
*/
if (got_write) {
ffffffff81109405: 80 7d ab 00 cmpb $0x0,-0x55(%rbp)
ffffffff81109409: 74 08 je ffffffff81109413 <do_last.isra.44+0x640>
mnt_drop_write(nd->path.mnt);
ffffffff8110940b: 48 8b 3b mov (%rbx),%rdi
ffffffff8110940e: e8 75 bf 00 00 callq ffffffff81115388 <mnt_drop_write>
got_write = false;
}
error = -EEXIST;
if ((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))
ffffffff81109413: 8b 45 94 mov -0x6c(%rbp),%eax
ffffffff81109416: 25 c0 00 00 00 and $0xc0,%eax
ffffffff8110941b: 3d c0 00 00 00 cmp $0xc0,%eax
ffffffff81109420: 0f 84 a9 02 00 00 je ffffffff811096cf <do_last.isra.44+0x8fc>
goto exit_dput;
error = follow_managed(path, nd->flags);
ffffffff81109426: 8b 73 38 mov 0x38(%rbx),%esi
ffffffff81109429: 4c 89 e7 mov %r12,%rdi
ffffffff8110942c: e8 f2 c0 ff ff callq ffffffff81105523 <follow_managed>
if (error < 0)
ffffffff81109431: 83 f8 00 cmp $0x0,%eax
error = -EEXIST;
if ((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))
goto exit_dput;
error = follow_managed(path, nd->flags);
ffffffff81109434: 41 89 c6 mov %eax,%r14d
if (error < 0)
ffffffff81109437: 0f 8c 98 02 00 00 jl ffffffff811096d5 <do_last.isra.44+0x902>
goto exit_dput;
if (error)
ffffffff8110943d: 74 07 je ffffffff81109446 <do_last.isra.44+0x673>
nd->flags |= LOOKUP_JUMPED;
ffffffff8110943f: 81 4b 38 00 10 00 00 orl $0x1000,0x38(%rbx)
BUG_ON(nd->flags & LOOKUP_RCU);
ffffffff81109446: f6 43 38 40 testb $0x40,0x38(%rbx)
ffffffff8110944a: 74 02 je ffffffff8110944e <do_last.isra.44+0x67b>
ffffffff8110944c: 0f 0b ud2
inode = path->dentry->d_inode;
ffffffff8110944e: 49 8b 44 24 08 mov 0x8(%r12),%rax
ffffffff81109453: 48 8b 40 30 mov 0x30(%rax),%rax
ffffffff81109457: 48 89 45 b8 mov %rax,-0x48(%rbp)
finish_lookup:
/* we _can_ be in RCU mode here */
error = -ENOENT;
if (d_is_negative(path->dentry)) {
ffffffff8110945b: 49 8b 74 24 08 mov 0x8(%r12),%rsi
ffffffff81109460: 8b 43 38 mov 0x38(%rbx),%eax
ffffffff81109463: 8b 16 mov (%rsi),%edx
ffffffff81109465: 81 e2 00 00 70 00 and $0x700000,%edx
ffffffff8110946b: 75 36 jne ffffffff811094a3 <do_last.isra.44+0x6d0>
}
static inline void path_to_nameidata(const struct path *path,
struct nameidata *nd)
{
if (!(nd->flags & LOOKUP_RCU)) {
ffffffff8110946d: a8 40 test $0x40,%al
ffffffff8110946f: 75 17 jne ffffffff81109488 <do_last.isra.44+0x6b5>
dput(nd->path.dentry);
ffffffff81109471: 48 8b 7b 08 mov 0x8(%rbx),%rdi
ffffffff81109475: e8 4f 62 00 00 callq ffffffff8110f6c9 <dput>
if (nd->path.mnt != path->mnt)
ffffffff8110947a: 48 8b 3b mov (%rbx),%rdi
ffffffff8110947d: 49 3b 3c 24 cmp (%r12),%rdi
ffffffff81109481: 74 05 je ffffffff81109488 <do_last.isra.44+0x6b5>
mntput(nd->path.mnt);
ffffffff81109483: e8 0b ca 00 00 callq ffffffff81115e93 <mntput>
}
nd->path.mnt = path->mnt;
ffffffff81109488: 49 8b 04 24 mov (%r12),%rax
BUG_ON(nd->flags & LOOKUP_RCU);
inode = path->dentry->d_inode;
finish_lookup:
/* we _can_ be in RCU mode here */
error = -ENOENT;
ffffffff8110948c: 41 be fe ff ff ff mov $0xfffffffe,%r14d
if (!(nd->flags & LOOKUP_RCU)) {
dput(nd->path.dentry);
if (nd->path.mnt != path->mnt)
mntput(nd->path.mnt);
}
nd->path.mnt = path->mnt;
ffffffff81109492: 48 89 03 mov %rax,(%rbx)
nd->path.dentry = path->dentry;
ffffffff81109495: 49 8b 44 24 08 mov 0x8(%r12),%rax
ffffffff8110949a: 48 89 43 08 mov %rax,0x8(%rbx)
ffffffff8110949e: e9 16 02 00 00 jmpq ffffffff811096b9 <do_last.isra.44+0x8e6>
* so we keep a cache of "no, this doesn't need follow_link"
* for the common case.
*/
static inline int should_follow_link(struct dentry *dentry, int follow)
{
return unlikely(d_is_symlink(dentry)) ? follow : 0;
ffffffff811094a3: 81 fa 00 00 30 00 cmp $0x300000,%edx
ffffffff811094a9: 75 37 jne ffffffff811094e2 <do_last.isra.44+0x70f>
if (d_is_negative(path->dentry)) {
path_to_nameidata(path, nd);
goto out;
}
if (should_follow_link(path->dentry, !symlink_ok)) {
ffffffff811094ab: 80 7d 93 00 cmpb $0x0,-0x6d(%rbp)
ffffffff811094af: 75 31 jne ffffffff811094e2 <do_last.isra.44+0x70f>
if (nd->flags & LOOKUP_RCU) {
ffffffff811094b1: a8 40 test $0x40,%al
ffffffff811094b3: 75 1a jne ffffffff811094cf <do_last.isra.44+0x6fc>
if (unlikely(unlazy_walk(nd, path->dentry))) {
error = -ECHILD;
goto out;
}
}
BUG_ON(inode != path->dentry->d_inode);
ffffffff811094b5: 49 8b 44 24 08 mov 0x8(%r12),%rax
ffffffff811094ba: 48 8b 50 30 mov 0x30(%rax),%rdx
ffffffff811094be: 48 39 55 b8 cmp %rdx,-0x48(%rbp)
ffffffff811094c2: 75 1c jne ffffffff811094e0 <do_last.isra.44+0x70d>
return 1;
ffffffff811094c4: 41 be 01 00 00 00 mov $0x1,%r14d
ffffffff811094ca: e9 dc 02 00 00 jmpq ffffffff811097ab <do_last.isra.44+0x9d8>
goto out;
}
if (should_follow_link(path->dentry, !symlink_ok)) {
if (nd->flags & LOOKUP_RCU) {
if (unlikely(unlazy_walk(nd, path->dentry))) {
ffffffff811094cf: 48 89 df mov %rbx,%rdi
ffffffff811094d2: e8 48 bf ff ff callq ffffffff8110541f <unlazy_walk>
ffffffff811094d7: 85 c0 test %eax,%eax
ffffffff811094d9: 74 da je ffffffff811094b5 <do_last.isra.44+0x6e2>
ffffffff811094db: e9 c0 02 00 00 jmpq ffffffff811097a0 <do_last.isra.44+0x9cd>
error = -ECHILD;
goto out;
}
}
BUG_ON(inode != path->dentry->d_inode);
ffffffff811094e0: 0f 0b ud2
return 1;
}
if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
ffffffff811094e2: a8 40 test $0x40,%al
ffffffff811094e4: 75 20 jne ffffffff81109506 <do_last.isra.44+0x733>
ffffffff811094e6: 48 8b 03 mov (%rbx),%rax
ffffffff811094e9: 49 3b 04 24 cmp (%r12),%rax
ffffffff811094ed: 48 8b 7b 08 mov 0x8(%rbx),%rdi
ffffffff811094f1: 74 1c je ffffffff8110950f <do_last.isra.44+0x73c>
static inline void path_to_nameidata(const struct path *path,
struct nameidata *nd)
{
if (!(nd->flags & LOOKUP_RCU)) {
dput(nd->path.dentry);
ffffffff811094f3: e8 d1 61 00 00 callq ffffffff8110f6c9 <dput>
if (nd->path.mnt != path->mnt)
ffffffff811094f8: 48 8b 3b mov (%rbx),%rdi
ffffffff811094fb: 49 3b 3c 24 cmp (%r12),%rdi
ffffffff811094ff: 74 05 je ffffffff81109506 <do_last.isra.44+0x733>
mntput(nd->path.mnt);
ffffffff81109501: e8 8d c9 00 00 callq ffffffff81115e93 <mntput>
}
nd->path.mnt = path->mnt;
ffffffff81109506: 49 8b 04 24 mov (%r12),%rax
ffffffff8110950a: 48 89 03 mov %rax,(%rbx)
ffffffff8110950d: eb 10 jmp ffffffff8110951f <do_last.isra.44+0x74c>
}
if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
path_to_nameidata(path, nd);
} else {
save_parent.dentry = nd->path.dentry;
ffffffff8110950f: 48 89 7d c8 mov %rdi,-0x38(%rbp)
save_parent.mnt = mntget(path->mnt);
ffffffff81109513: 48 89 c7 mov %rax,%rdi
ffffffff81109516: e8 d0 b9 00 00 callq ffffffff81114eeb <mntget>
ffffffff8110951b: 48 89 45 c0 mov %rax,-0x40(%rbp)
nd->path.dentry = path->dentry;
ffffffff8110951f: 49 8b 44 24 08 mov 0x8(%r12),%rax
ffffffff81109524: 48 89 43 08 mov %rax,0x8(%rbx)
}
nd->inode = inode;
ffffffff81109528: 48 8b 45 b8 mov -0x48(%rbp),%rax
ffffffff8110952c: 48 89 43 30 mov %rax,0x30(%rbx)
/* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
finish_open:
error = complete_walk(nd);
ffffffff81109530: 48 89 df mov %rbx,%rdi
ffffffff81109533: e8 79 bb ff ff callq ffffffff811050b1 <complete_walk>
if (error) {
ffffffff81109538: 85 c0 test %eax,%eax
}
nd->inode = inode;
/* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
finish_open:
error = complete_walk(nd);
ffffffff8110953a: 41 89 c6 mov %eax,%r14d
if (error) {
ffffffff8110953d: 74 0e je ffffffff8110954d <do_last.isra.44+0x77a>
path_put(&save_parent);
ffffffff8110953f: 48 8d 7d c0 lea -0x40(%rbp),%rdi
ffffffff81109543: e8 15 bb ff ff callq ffffffff8110505d <path_put>
ffffffff81109548: e9 5e 02 00 00 jmpq ffffffff811097ab <do_last.isra.44+0x9d8>
return error;
}
audit_inode(name, nd->path.dentry, 0);
error = -EISDIR;
if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
ffffffff8110954d: f6 45 94 40 testb $0x40,-0x6c(%rbp)
ffffffff81109551: 74 2c je ffffffff8110957f <do_last.isra.44+0x7ac>
const struct inode_operations page_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
};
EXPORT_SYMBOL(page_symlink_inode_operations);
ffffffff81109553: 48 8b 43 08 mov 0x8(%rbx),%rax
spin_unlock(&dentry->d_lock);
}
static inline unsigned __d_entry_type(const struct dentry *dentry)
{
return dentry->d_flags & DCACHE_ENTRY_TYPE;
ffffffff81109557: 8b 00 mov (%rax),%eax
ffffffff81109559: 25 00 00 70 00 and $0x700000,%eax
return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE;
}
static inline bool d_is_dir(const struct dentry *dentry)
{
return d_can_lookup(dentry) || d_is_autodir(dentry);
ffffffff8110955e: 3d 00 00 10 00 cmp $0x100000,%eax
ffffffff81109563: 74 0d je ffffffff81109572 <do_last.isra.44+0x79f>
ffffffff81109565: 3d 00 00 20 00 cmp $0x200000,%eax
ffffffff8110956a: 0f 94 c0 sete %al
ffffffff8110956d: 0f b6 c0 movzbl %al,%eax
ffffffff81109570: eb 05 jmp ffffffff81109577 <do_last.isra.44+0x7a4>
ffffffff81109572: b8 01 00 00 00 mov $0x1,%eax
path_put(&save_parent);
return error;
}
audit_inode(name, nd->path.dentry, 0);
error = -EISDIR;
if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
ffffffff81109577: 85 c0 test %eax,%eax
ffffffff81109579: 0f 85 72 f9 ff ff jne ffffffff81108ef1 <do_last.isra.44+0x11e>
goto out;
error = -ENOTDIR;
if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
ffffffff8110957f: f6 43 38 02 testb $0x2,0x38(%rbx)
ffffffff81109583: 74 1c je ffffffff811095a1 <do_last.isra.44+0x7ce>
const struct inode_operations page_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
};
EXPORT_SYMBOL(page_symlink_inode_operations);
ffffffff81109585: 48 8b 43 08 mov 0x8(%rbx),%rax
}
audit_inode(name, nd->path.dentry, 0);
error = -EISDIR;
if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
goto out;
error = -ENOTDIR;
ffffffff81109589: 41 be ec ff ff ff mov $0xffffffec,%r14d
spin_unlock(&dentry->d_lock);
}
static inline unsigned __d_entry_type(const struct dentry *dentry)
{
return dentry->d_flags & DCACHE_ENTRY_TYPE;
ffffffff8110958f: 8b 00 mov (%rax),%eax
ffffffff81109591: 25 00 00 70 00 and $0x700000,%eax
if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
ffffffff81109596: 3d 00 00 10 00 cmp $0x100000,%eax
ffffffff8110959b: 0f 85 18 01 00 00 jne ffffffff811096b9 <do_last.isra.44+0x8e6>
goto out;
if (!S_ISREG(nd->inode->i_mode))
ffffffff811095a1: 48 8b 43 30 mov 0x30(%rbx),%rax
ffffffff811095a5: 8b 00 mov (%rax),%eax
ffffffff811095a7: 66 25 00 f0 and $0xf000,%ax
ffffffff811095ab: 66 3d 00 80 cmp $0x8000,%ax
ffffffff811095af: 75 1f jne ffffffff811095d0 <do_last.isra.44+0x7fd>
will_truncate = false;
if (will_truncate) {
ffffffff811095b1: 80 7d aa 00 cmpb $0x0,-0x56(%rbp)
ffffffff811095b5: 74 23 je ffffffff811095da <do_last.isra.44+0x807>
error = mnt_want_write(nd->path.mnt);
ffffffff811095b7: 48 8b 3b mov (%rbx),%rdi
ffffffff811095ba: e8 89 cb 00 00 callq ffffffff81116148 <mnt_want_write>
if (error)
ffffffff811095bf: 85 c0 test %eax,%eax
goto out;
if (!S_ISREG(nd->inode->i_mode))
will_truncate = false;
if (will_truncate) {
error = mnt_want_write(nd->path.mnt);
ffffffff811095c1: 41 89 c6 mov %eax,%r14d
if (error)
ffffffff811095c4: 0f 85 ef 00 00 00 jne ffffffff811096b9 <do_last.isra.44+0x8e6>
goto out;
got_write = true;
ffffffff811095ca: c6 45 ab 01 movb $0x1,-0x55(%rbp)
ffffffff811095ce: eb 0e jmp ffffffff811095de <do_last.isra.44+0x80b>
if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
goto out;
error = -ENOTDIR;
if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
goto out;
if (!S_ISREG(nd->inode->i_mode))
ffffffff811095d0: c6 45 ab 00 movb $0x0,-0x55(%rbp)
ffffffff811095d4: c6 45 aa 00 movb $0x0,-0x56(%rbp)
ffffffff811095d8: eb 04 jmp ffffffff811095de <do_last.isra.44+0x80b>
will_truncate = false;
if (will_truncate) {
ffffffff811095da: c6 45 ab 00 movb $0x0,-0x55(%rbp)
if (error)
goto out;
got_write = true;
}
finish_open_created:
error = may_open(&nd->path, acc_mode, open_flag);
ffffffff811095de: 8b 55 94 mov -0x6c(%rbp),%edx
ffffffff811095e1: 8b b5 7c ff ff ff mov -0x84(%rbp),%esi
ffffffff811095e7: 48 89 df mov %rbx,%rdi
ffffffff811095ea: e8 fa f6 ff ff callq ffffffff81108ce9 <may_open>
if (error)
ffffffff811095ef: 85 c0 test %eax,%eax
if (error)
goto out;
got_write = true;
}
finish_open_created:
error = may_open(&nd->path, acc_mode, open_flag);
ffffffff811095f1: 41 89 c6 mov %eax,%r14d
if (error)
ffffffff811095f4: 0f 85 b1 00 00 00 jne ffffffff811096ab <do_last.isra.44+0x8d8>
goto out;
file->f_path.mnt = nd->path.mnt;
ffffffff811095fa: 48 8b 03 mov (%rbx),%rax
error = finish_open(file, nd->path.dentry, NULL, opened);
ffffffff811095fd: 48 8b 4d a0 mov -0x60(%rbp),%rcx
ffffffff81109601: 31 d2 xor %edx,%edx
ffffffff81109603: 4c 89 ef mov %r13,%rdi
}
finish_open_created:
error = may_open(&nd->path, acc_mode, open_flag);
if (error)
goto out;
file->f_path.mnt = nd->path.mnt;
ffffffff81109606: 49 89 45 10 mov %rax,0x10(%r13)
error = finish_open(file, nd->path.dentry, NULL, opened);
ffffffff8110960a: 48 8b 73 08 mov 0x8(%rbx),%rsi
ffffffff8110960e: e8 91 29 ff ff callq ffffffff810fbfa4 <finish_open>
if (error) {
ffffffff81109613: 85 c0 test %eax,%eax
finish_open_created:
error = may_open(&nd->path, acc_mode, open_flag);
if (error)
goto out;
file->f_path.mnt = nd->path.mnt;
error = finish_open(file, nd->path.dentry, NULL, opened);
ffffffff81109615: 41 89 c6 mov %eax,%r14d
if (error) {
ffffffff81109618: 74 14 je ffffffff8110962e <do_last.isra.44+0x85b>
if (error == -EOPENSTALE)
ffffffff8110961a: 3d fa fd ff ff cmp $0xfffffdfa,%eax
ffffffff8110961f: 0f 85 86 00 00 00 jne ffffffff811096ab <do_last.isra.44+0x8d8>
ffffffff81109625: e9 c2 00 00 00 jmpq ffffffff811096ec <do_last.isra.44+0x919>
if (error)
goto out;
if ((*opened & FILE_CREATED) ||
!S_ISREG(file_inode(file)->i_mode))
will_truncate = false;
ffffffff8110962a: c6 45 aa 00 movb $0x0,-0x56(%rbp)
if (error == -EOPENSTALE)
goto stale_open;
goto out;
}
opened:
error = open_check_o_direct(file);
ffffffff8110962e: 4c 89 ef mov %r13,%rdi
ffffffff81109631: e8 e6 35 ff ff callq ffffffff810fcc1c <open_check_o_direct>
if (error)
ffffffff81109636: 85 c0 test %eax,%eax
if (error == -EOPENSTALE)
goto stale_open;
goto out;
}
opened:
error = open_check_o_direct(file);
ffffffff81109638: 41 89 c6 mov %eax,%r14d
if (error)
ffffffff8110963b: 0f 85 a1 00 00 00 jne ffffffff811096e2 <do_last.isra.44+0x90f>
goto exit_fput;
error = ima_file_check(file, op->acc_mode);
if (error)
goto exit_fput;
if (will_truncate) {
ffffffff81109641: 80 7d aa 00 cmpb $0x0,-0x56(%rbp)
ffffffff81109645: 74 64 je ffffffff811096ab <do_last.isra.44+0x8d8>
}
static int handle_truncate(struct file *filp)
{
struct path *path = &filp->f_path;
struct inode *inode = path->dentry->d_inode;
ffffffff81109647: 49 8b 45 18 mov 0x18(%r13),%rax
#ifndef atomic_inc_unless_negative
static inline int atomic_inc_unless_negative(atomic_t *p)
{
int v, v1;
for (v = 0; v >= 0; v = v1) {
ffffffff8110964b: 31 d2 xor %edx,%edx
ffffffff8110964d: 4c 8b 60 30 mov 0x30(%rax),%r12
v1 = atomic_cmpxchg(p, v, v + 1);
ffffffff81109651: 8d 4a 01 lea 0x1(%rdx),%ecx
#define atomic_inc_return(v) (atomic_add_return(1, v))
#define atomic_dec_return(v) (atomic_sub_return(1, v))
static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{
return cmpxchg(&v->counter, old, new);
ffffffff81109654: 89 d0 mov %edx,%eax
ffffffff81109656: f0 41 0f b1 8c 24 30 lock cmpxchg %ecx,0x130(%r12)
ffffffff8110965d: 01 00 00
if (likely(v1 == v))
ffffffff81109660: 39 d0 cmp %edx,%eax
ffffffff81109662: 0f 84 09 01 00 00 je ffffffff81109771 <do_last.isra.44+0x99e>
#ifndef atomic_inc_unless_negative
static inline int atomic_inc_unless_negative(atomic_t *p)
{
int v, v1;
for (v = 0; v >= 0; v = v1) {
ffffffff81109668: 85 c0 test %eax,%eax
ffffffff8110966a: 89 c2 mov %eax,%edx
ffffffff8110966c: 79 e3 jns ffffffff81109651 <do_last.isra.44+0x87e>
* use {get,deny}_write_access() - these functions check the sign and refuse
* to do the change if sign is wrong.
*/
static inline int get_write_access(struct inode *inode)
{
return atomic_inc_unless_negative(&inode->i_writecount) ? 0 : -ETXTBSY;
ffffffff8110966e: 41 be e6 ff ff ff mov $0xffffffe6,%r14d
ffffffff81109674: eb 6c jmp ffffffff811096e2 <do_last.isra.44+0x90f>
* but no group execute bit - an otherwise meaningless combination.
*/
static inline int __mandatory_lock(struct inode *ino)
{
return (ino->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID;
ffffffff81109676: 66 8b 00 mov (%rax),%ax
ffffffff81109679: 66 25 08 04 and $0x408,%ax
* otherwise these will be advisory locks
*/
static inline int mandatory_lock(struct inode *ino)
{
return IS_MANDLOCK(ino) && __mandatory_lock(ino);
ffffffff8110967d: 66 3d 00 04 cmp $0x400,%ax
ffffffff81109681: 0f 84 01 01 00 00 je ffffffff81109788 <do_last.isra.44+0x9b5>
*/
error = locks_verify_locked(filp);
if (!error)
error = security_path_truncate(path);
if (!error) {
error = do_truncate(path->dentry, 0,
ffffffff81109687: 49 8b 7d 18 mov 0x18(%r13),%rdi
ffffffff8110968b: 4c 89 e9 mov %r13,%rcx
ffffffff8110968e: ba 60 80 00 00 mov $0x8060,%edx
ffffffff81109693: 31 f6 xor %esi,%esi
ffffffff81109695: e8 1c 2a ff ff callq ffffffff810fc0b6 <do_truncate>
ffffffff8110969a: 41 89 c6 mov %eax,%r14d
*
* Atomically decrements @v by 1.
*/
static inline void atomic_dec(atomic_t *v)
{
asm volatile(LOCK_PREFIX "decl %0"
ffffffff8110969d: f0 41 ff 8c 24 30 01 lock decl 0x130(%r12)
ffffffff811096a4: 00 00
if (error)
goto exit_fput;
if (will_truncate) {
error = handle_truncate(file);
if (error)
ffffffff811096a6: 45 85 f6 test %r14d,%r14d
ffffffff811096a9: 75 37 jne ffffffff811096e2 <do_last.isra.44+0x90f>
goto exit_fput;
}
out:
if (got_write)
ffffffff811096ab: 80 7d ab 00 cmpb $0x0,-0x55(%rbp)
ffffffff811096af: 74 08 je ffffffff811096b9 <do_last.isra.44+0x8e6>
mnt_drop_write(nd->path.mnt);
ffffffff811096b1: 48 8b 3b mov (%rbx),%rdi
ffffffff811096b4: e8 cf bc 00 00 callq ffffffff81115388 <mnt_drop_write>
path_put(&save_parent);
ffffffff811096b9: 48 8d 7d c0 lea -0x40(%rbp),%rdi
ffffffff811096bd: e8 9b b9 ff ff callq ffffffff8110505d <path_put>
terminate_walk(nd);
ffffffff811096c2: 48 89 df mov %rbx,%rdi
ffffffff811096c5: e8 b8 b9 ff ff callq ffffffff81105082 <terminate_walk>
ffffffff811096ca: e9 dc 00 00 00 jmpq ffffffff811097ab <do_last.isra.44+0x9d8>
if (got_write) {
mnt_drop_write(nd->path.mnt);
got_write = false;
}
error = -EEXIST;
ffffffff811096cf: 41 be ef ff ff ff mov $0xffffffef,%r14d
path_put(&save_parent);
terminate_walk(nd);
return error;
exit_dput:
path_put_conditional(path, nd);
ffffffff811096d5: 48 89 de mov %rbx,%rsi
ffffffff811096d8: 4c 89 e7 mov %r12,%rdi
ffffffff811096db: e8 8b c4 ff ff callq ffffffff81105b6b <path_put_conditional.isra.28>
ffffffff811096e0: eb d7 jmp ffffffff811096b9 <do_last.isra.44+0x8e6>
goto out;
exit_fput:
fput(file);
ffffffff811096e2: 4c 89 ef mov %r13,%rdi
ffffffff811096e5: e8 0c 52 ff ff callq ffffffff810fe8f6 <fput>
ffffffff811096ea: eb bf jmp ffffffff811096ab <do_last.isra.44+0x8d8>
goto out;
stale_open:
/* If no saved parent or already retried then can't retry */
if (!save_parent.dentry || retried)
ffffffff811096ec: 48 8b 45 c8 mov -0x38(%rbp),%rax
ffffffff811096f0: 48 85 c0 test %rax,%rax
ffffffff811096f3: 74 b6 je ffffffff811096ab <do_last.isra.44+0x8d8>
ffffffff811096f5: 80 7d 92 00 cmpb $0x0,-0x6e(%rbp)
ffffffff811096f9: 75 b0 jne ffffffff811096ab <do_last.isra.44+0x8d8>
goto out;
BUG_ON(save_parent.dentry != dir);
ffffffff811096fb: 48 3b 45 80 cmp -0x80(%rbp),%rax
ffffffff811096ff: 74 02 je ffffffff81109703 <do_last.isra.44+0x930>
ffffffff81109701: 0f 0b ud2
path_put(&nd->path);
ffffffff81109703: 48 89 df mov %rbx,%rdi
ffffffff81109706: e8 52 b9 ff ff callq ffffffff8110505d <path_put>
nd->path = save_parent;
ffffffff8110970b: 48 8b 45 c8 mov -0x38(%rbp),%rax
ffffffff8110970f: 48 8b 7d c0 mov -0x40(%rbp),%rdi
nd->inode = dir->d_inode;
ffffffff81109713: 48 8b 55 80 mov -0x80(%rbp),%rdx
save_parent.mnt = NULL;
save_parent.dentry = NULL;
if (got_write) {
ffffffff81109717: 80 7d ab 00 cmpb $0x0,-0x55(%rbp)
BUG_ON(save_parent.dentry != dir);
path_put(&nd->path);
nd->path = save_parent;
nd->inode = dir->d_inode;
save_parent.mnt = NULL;
ffffffff8110971b: 48 c7 45 c0 00 00 00 movq $0x0,-0x40(%rbp)
ffffffff81109722: 00
save_parent.dentry = NULL;
ffffffff81109723: 48 c7 45 c8 00 00 00 movq $0x0,-0x38(%rbp)
ffffffff8110972a: 00
if (!save_parent.dentry || retried)
goto out;
BUG_ON(save_parent.dentry != dir);
path_put(&nd->path);
nd->path = save_parent;
ffffffff8110972b: 48 89 3b mov %rdi,(%rbx)
ffffffff8110972e: 48 89 43 08 mov %rax,0x8(%rbx)
nd->inode = dir->d_inode;
ffffffff81109732: 48 8b 42 30 mov 0x30(%rdx),%rax
save_parent.dentry = NULL;
if (got_write) {
mnt_drop_write(nd->path.mnt);
got_write = false;
}
retried = true;
ffffffff81109736: c6 45 92 01 movb $0x1,-0x6e(%rbp)
goto out;
BUG_ON(save_parent.dentry != dir);
path_put(&nd->path);
nd->path = save_parent;
nd->inode = dir->d_inode;
ffffffff8110973a: 48 89 43 30 mov %rax,0x30(%rbx)
save_parent.mnt = NULL;
save_parent.dentry = NULL;
if (got_write) {
ffffffff8110973e: 0f 84 c0 f7 ff ff je ffffffff81108f04 <do_last.isra.44+0x131>
mnt_drop_write(nd->path.mnt);
ffffffff81109744: e8 3f bc 00 00 callq ffffffff81115388 <mnt_drop_write>
ffffffff81109749: e9 b6 f7 ff ff jmpq ffffffff81108f04 <do_last.isra.44+0x131>
static inline int handle_dots(struct nameidata *nd, int type)
{
if (type == LAST_DOTDOT) {
if (nd->flags & LOOKUP_RCU) {
if (follow_dotdot_rcu(nd))
return -ECHILD;
ffffffff8110974e: 41 be f6 ff ff ff mov $0xfffffff6,%r14d
ffffffff81109754: eb 55 jmp ffffffff811097ab <do_last.isra.44+0x9d8>
bool got_write = false;
int acc_mode = op->acc_mode;
struct inode *inode;
bool symlink_ok = false;
struct path save_parent = { .dentry = NULL, .mnt = NULL };
bool retried = false;
ffffffff81109756: c6 45 92 00 movb $0x0,-0x6e(%rbp)
int open_flag = op->open_flag;
bool will_truncate = (open_flag & O_TRUNC) != 0;
bool got_write = false;
int acc_mode = op->acc_mode;
struct inode *inode;
bool symlink_ok = false;
ffffffff8110975a: c6 45 93 00 movb $0x0,-0x6d(%rbp)
ffffffff8110975e: e9 cd fd ff ff jmpq ffffffff81109530 <do_last.isra.44+0x75d>
if (error) { /* returned 1, that is */
if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
error = -EIO;
goto out;
}
if (file->f_path.dentry) {
ffffffff81109763: 48 85 c0 test %rax,%rax
ffffffff81109766: 0f 85 d2 f9 ff ff jne ffffffff8110913e <do_last.isra.44+0x36b>
ffffffff8110976c: e9 d9 f9 ff ff jmpq ffffffff8110914a <do_last.isra.44+0x377>
const struct inode_operations page_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
};
EXPORT_SYMBOL(page_symlink_inode_operations);
ffffffff81109771: 49 8b 45 20 mov 0x20(%r13),%rax
ffffffff81109775: 48 8b 50 28 mov 0x28(%rax),%rdx
ffffffff81109779: f6 42 50 40 testb $0x40,0x50(%rdx)
ffffffff8110977d: 0f 85 f3 fe ff ff jne ffffffff81109676 <do_last.isra.44+0x8a3>
ffffffff81109783: e9 ff fe ff ff jmpq ffffffff81109687 <do_last.isra.44+0x8b4>
}
static inline int locks_verify_locked(struct file *file)
{
if (mandatory_lock(file_inode(file)))
return locks_mandatory_locked(file);
ffffffff81109788: 4c 89 ef mov %r13,%rdi
ffffffff8110978b: e8 52 0c 03 00 callq ffffffff8113a3e2 <locks_mandatory_locked>
return error;
/*
* Refuse to truncate files with mandatory locks held on them.
*/
error = locks_verify_locked(filp);
if (!error)
ffffffff81109790: 85 c0 test %eax,%eax
ffffffff81109792: 41 89 c6 mov %eax,%r14d
ffffffff81109795: 0f 85 02 ff ff ff jne ffffffff8110969d <do_last.isra.44+0x8ca>
ffffffff8110979b: e9 e7 fe ff ff jmpq ffffffff81109687 <do_last.isra.44+0x8b4>
}
if (should_follow_link(path->dentry, !symlink_ok)) {
if (nd->flags & LOOKUP_RCU) {
if (unlikely(unlazy_walk(nd, path->dentry))) {
error = -ECHILD;
ffffffff811097a0: 41 be f6 ff ff ff mov $0xfffffff6,%r14d
ffffffff811097a6: e9 0e ff ff ff jmpq ffffffff811096b9 <do_last.isra.44+0x8e6>
mnt_drop_write(nd->path.mnt);
got_write = false;
}
retried = true;
goto retry_lookup;
}
ffffffff811097ab: 48 83 c4 78 add $0x78,%rsp
ffffffff811097af: 44 89 f0 mov %r14d,%eax
ffffffff811097b2: 5b pop %rbx
ffffffff811097b3: 41 5c pop %r12
ffffffff811097b5: 41 5d pop %r13
ffffffff811097b7: 41 5e pop %r14
ffffffff811097b9: 41 5f pop %r15
ffffffff811097bb: 5d pop %rbp
ffffffff811097bc: c3 retq
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 2:17 ` Al Viro
2014-04-18 2:22 ` Lin Ming
@ 2014-04-18 2:35 ` Lin Ming
2014-04-18 2:42 ` Al Viro
1 sibling, 1 reply; 12+ messages in thread
From: Lin Ming @ 2014-04-18 2:35 UTC (permalink / raw)
To: Al Viro; +Cc: David Howells, linux-fsdevel, Hugh Dickins
On Thu, Apr 17, 2014 at 7:17 PM, Al Viro <viro@zeniv.linux.org.uk> wrote:
> On Fri, Apr 18, 2014 at 02:57:50AM +0100, Al Viro wrote:
>
>> Where is it in do_last()? Hard to tell without even the hex dump of
>> oopsing code (and trying to reproduce it here hasn't produced any oopsen
>> so far).
>
> Hmm... Still no oopsen, but it looks like it *is* possible to get
> screwed there. RCU mode isn't a problem, AFAICS (we'll fail on d_seq
> mismatch in complete_walk() and that will be the end of it), but
> non-lazy mode *can* get buggered. We are holding a reference to
> nd->path.dentry and that's enough to prevent positive-to-negative
> transition, but negative-to-positive is fair game. So it does
> happen and we end up with nd->inode being set to NULL. And _that_
> promptly blows up on
> if (!S_ISREG(nd->inode->i_mode))
> will_truncate = false;
> Actually, it might very well be the only source of breakage - that late
> in the game (already out of RCU mode, for starters) we don't give a damn
> about nd->inode.
>
> Ah, actually there's also
> BUG_ON(inode != path->dentry->d_inode);
> in symlink case (similar "negative to positive", but it will be a symlink(2),
> not creat(2)). Pointless BUG_ON, actually...
>
> The reason why your reordering hadn't done any good is that CPU cache is free
> to reorder behind your back - no barriers between these two stores.
Added a barrier(), but still panic.
diff --git a/fs/dcache.c b/fs/dcache.c
index 40707d8..1d6b529 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1647,11 +1647,12 @@ static void __d_instantiate(struct dentry
*dentry, struct inode *inode)
unsigned add_flags = d_flags_for_inode(inode);
spin_lock(&dentry->d_lock);
+ dentry->d_inode = inode;
+ barrier();
dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
dentry->d_flags |= add_flags;
if (inode)
hlist_add_head(&dentry->d_alias, &inode->i_dentry);
- dentry->d_inode = inode;
dentry_rcuwalk_barrier(dentry);
spin_unlock(&dentry->d_lock);
fsnotify_d_instantiate(dentry, inode);
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: panic in do_last()
[not found] ` <CAF1ivSbqM2LorrED3MvgKBDxA9sLz_RkOEPwAfvYYmL5C9K0vA@mail.gmail.com>
@ 2014-04-18 2:38 ` Al Viro
2014-04-18 2:48 ` Al Viro
0 siblings, 1 reply; 12+ messages in thread
From: Al Viro @ 2014-04-18 2:38 UTC (permalink / raw)
To: Lin Ming; +Cc: David Howells, linux-fsdevel, Hugh Dickins, Linus Torvalds
On Thu, Apr 17, 2014 at 07:16:30PM -0700, Lin Ming wrote:
> (gdb) list *do_last+0x7d2
> 0xffffffff811095a5 is in do_last (/home/mlin/linux/fs/namei.c:3036).
> 3031 if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
> 3032 goto out;
> 3033 error = -ENOTDIR;
> 3034 if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
> 3035 goto out;
> 3036 if (!S_ISREG(nd->inode->i_mode))
> 3037 will_truncate = false;
Aha, so my guess in another posting was correct. OK...
So it's not about RCU case at all - if dentry changes under us
in lazy mode, we'll simply fail when we get to checking d_seq. It's
non-lazy case + transition from negative to positive that causes the
trouble.
Another piece of breakage in there is should_follow_link() directly
afterwards - there the problem is with false negatives. I.e. we
see new dentry->d_inode, but not the new dentry->d_flags.
I wonder if the right fix would be simply
if (!inode || d_is_negative(dentry))
bailing out unless both updates are seen. Probably cheaper than any
games with barriers...
Comments?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 2:35 ` Lin Ming
@ 2014-04-18 2:42 ` Al Viro
0 siblings, 0 replies; 12+ messages in thread
From: Al Viro @ 2014-04-18 2:42 UTC (permalink / raw)
To: Lin Ming; +Cc: David Howells, linux-fsdevel, Hugh Dickins
On Thu, Apr 17, 2014 at 07:35:14PM -0700, Lin Ming wrote:
> Added a barrier(), but still panic.
Wrong kind of barrier ;-) This one just says the compiler that it
shouldn't reorder; it doesn't help other CPUs at all.
Read Documentation/memory-barriers.txt for details, but I seriously
wonder if we _want_ to mess with barriers in the first place...
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 2:38 ` Al Viro
@ 2014-04-18 2:48 ` Al Viro
2014-04-18 3:17 ` Al Viro
0 siblings, 1 reply; 12+ messages in thread
From: Al Viro @ 2014-04-18 2:48 UTC (permalink / raw)
To: Lin Ming; +Cc: David Howells, linux-fsdevel, Hugh Dickins, Linus Torvalds
On Fri, Apr 18, 2014 at 03:38:22AM +0100, Al Viro wrote:
> Aha, so my guess in another posting was correct. OK...
>
> So it's not about RCU case at all - if dentry changes under us
> in lazy mode, we'll simply fail when we get to checking d_seq. It's
> non-lazy case + transition from negative to positive that causes the
> trouble.
>
> Another piece of breakage in there is should_follow_link() directly
> afterwards - there the problem is with false negatives. I.e. we
> see new dentry->d_inode, but not the new dentry->d_flags.
>
> I wonder if the right fix would be simply
> if (!inode || d_is_negative(dentry))
> bailing out unless both updates are seen. Probably cheaper than any
> games with barriers...
Crap... No, it's a bit trickier - we start with clearing all flags,
so if we see the _intermediate_ d_flags and new d_inode, we'll sail
past the check. Which would leave us with correct inode, but might
give us a false negative in should_follow_link().
Hmm... How about the following, then?
diff --git a/fs/dcache.c b/fs/dcache.c
index 40707d8..494a9def 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1647,8 +1647,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
unsigned add_flags = d_flags_for_inode(inode);
spin_lock(&dentry->d_lock);
- dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
- dentry->d_flags |= add_flags;
+ __d_set_type(dentry, add_flags);
if (inode)
hlist_add_head(&dentry->d_alias, &inode->i_dentry);
dentry->d_inode = inode;
diff --git a/fs/namei.c b/fs/namei.c
index c6157c8..7560db7 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2994,7 +2994,7 @@ retry_lookup:
finish_lookup:
/* we _can_ be in RCU mode here */
error = -ENOENT;
- if (d_is_negative(path->dentry)) {
+ if (!inode || d_is_negative(path->dentry)) {
path_to_nameidata(path, nd);
goto out;
}
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 2:48 ` Al Viro
@ 2014-04-18 3:17 ` Al Viro
2014-04-18 3:40 ` Lin Ming
0 siblings, 1 reply; 12+ messages in thread
From: Al Viro @ 2014-04-18 3:17 UTC (permalink / raw)
To: Lin Ming; +Cc: David Howells, linux-fsdevel, Hugh Dickins, Linus Torvalds
On Fri, Apr 18, 2014 at 03:48:37AM +0100, Al Viro wrote:
> Crap... No, it's a bit trickier - we start with clearing all flags,
> so if we see the _intermediate_ d_flags and new d_inode, we'll sail
> past the check. Which would leave us with correct inode, but might
> give us a false negative in should_follow_link().
Note that most of the places calling d_is_...() are protected by
the following: if we'd obtained dentry by __lookup_hash() and friends
*after* grabbing ->i_mutex on parent, we are fine - both positive-to-negative
and negative-to-positive are possible only with ->i_mutex held, so it
gives us a barrier.
AFAICS, there are two more tricky places: walk_component() doing
if (!inode)
goto out_path_put;
if (should_follow_link(path->dentry, follow)) {
with unpleasant consequences if the second test gives a false negative,
and similar for mountpoint_last().
Basically, we'd concentrated on RCU races back then, and missed the possibility
of non-RCU-but-without-i_mutex ones. Proposed fix follows:
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
diff --git a/fs/dcache.c b/fs/dcache.c
index 40707d8..494a9def 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1647,8 +1647,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
unsigned add_flags = d_flags_for_inode(inode);
spin_lock(&dentry->d_lock);
- dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
- dentry->d_flags |= add_flags;
+ __d_set_type(dentry, add_flags);
if (inode)
hlist_add_head(&dentry->d_alias, &inode->i_dentry);
dentry->d_inode = inode;
diff --git a/fs/namei.c b/fs/namei.c
index c6157c8..8016827 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1542,7 +1542,7 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
inode = path->dentry->d_inode;
}
err = -ENOENT;
- if (!inode)
+ if (!inode || d_is_negative(path->dentry))
goto out_path_put;
if (should_follow_link(path->dentry, follow)) {
@@ -2249,7 +2249,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
mutex_unlock(&dir->d_inode->i_mutex);
done:
- if (!dentry->d_inode) {
+ if (!dentry->d_inode || d_is_negative(dentry)) {
error = -ENOENT;
dput(dentry);
goto out;
@@ -2994,7 +2994,7 @@ retry_lookup:
finish_lookup:
/* we _can_ be in RCU mode here */
error = -ENOENT;
- if (d_is_negative(path->dentry)) {
+ if (!inode || d_is_negative(path->dentry)) {
path_to_nameidata(path, nd);
goto out;
}
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 3:17 ` Al Viro
@ 2014-04-18 3:40 ` Lin Ming
2014-04-18 15:11 ` Lin Ming
0 siblings, 1 reply; 12+ messages in thread
From: Lin Ming @ 2014-04-18 3:40 UTC (permalink / raw)
To: Al Viro; +Cc: David Howells, linux-fsdevel, Hugh Dickins, Linus Torvalds
On Thu, Apr 17, 2014 at 8:17 PM, Al Viro <viro@zeniv.linux.org.uk> wrote:
> On Fri, Apr 18, 2014 at 03:48:37AM +0100, Al Viro wrote:
>> Crap... No, it's a bit trickier - we start with clearing all flags,
>> so if we see the _intermediate_ d_flags and new d_inode, we'll sail
>> past the check. Which would leave us with correct inode, but might
>> give us a false negative in should_follow_link().
>
> Note that most of the places calling d_is_...() are protected by
> the following: if we'd obtained dentry by __lookup_hash() and friends
> *after* grabbing ->i_mutex on parent, we are fine - both positive-to-negative
> and negative-to-positive are possible only with ->i_mutex held, so it
> gives us a barrier.
>
> AFAICS, there are two more tricky places: walk_component() doing
> if (!inode)
> goto out_path_put;
>
> if (should_follow_link(path->dentry, follow)) {
> with unpleasant consequences if the second test gives a false negative,
> and similar for mountpoint_last().
>
> Basically, we'd concentrated on RCU races back then, and missed the possibility
> of non-RCU-but-without-i_mutex ones. Proposed fix follows:
Should be OK. I'll test it tomorrow.
Thanks.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
> diff --git a/fs/dcache.c b/fs/dcache.c
> index 40707d8..494a9def 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -1647,8 +1647,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
> unsigned add_flags = d_flags_for_inode(inode);
>
> spin_lock(&dentry->d_lock);
> - dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
> - dentry->d_flags |= add_flags;
> + __d_set_type(dentry, add_flags);
> if (inode)
> hlist_add_head(&dentry->d_alias, &inode->i_dentry);
> dentry->d_inode = inode;
> diff --git a/fs/namei.c b/fs/namei.c
> index c6157c8..8016827 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -1542,7 +1542,7 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
> inode = path->dentry->d_inode;
> }
> err = -ENOENT;
> - if (!inode)
> + if (!inode || d_is_negative(path->dentry))
> goto out_path_put;
>
> if (should_follow_link(path->dentry, follow)) {
> @@ -2249,7 +2249,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
> mutex_unlock(&dir->d_inode->i_mutex);
>
> done:
> - if (!dentry->d_inode) {
> + if (!dentry->d_inode || d_is_negative(dentry)) {
> error = -ENOENT;
> dput(dentry);
> goto out;
> @@ -2994,7 +2994,7 @@ retry_lookup:
> finish_lookup:
> /* we _can_ be in RCU mode here */
> error = -ENOENT;
> - if (d_is_negative(path->dentry)) {
> + if (!inode || d_is_negative(path->dentry)) {
> path_to_nameidata(path, nd);
> goto out;
> }
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 3:40 ` Lin Ming
@ 2014-04-18 15:11 ` Lin Ming
2014-04-22 17:51 ` Lin Ming
0 siblings, 1 reply; 12+ messages in thread
From: Lin Ming @ 2014-04-18 15:11 UTC (permalink / raw)
To: Al Viro; +Cc: David Howells, linux-fsdevel, Hugh Dickins, Linus Torvalds
On Thu, Apr 17, 2014 at 8:40 PM, Lin Ming <minggr@gmail.com> wrote:
> On Thu, Apr 17, 2014 at 8:17 PM, Al Viro <viro@zeniv.linux.org.uk> wrote:
>> On Fri, Apr 18, 2014 at 03:48:37AM +0100, Al Viro wrote:
>>> Crap... No, it's a bit trickier - we start with clearing all flags,
>>> so if we see the _intermediate_ d_flags and new d_inode, we'll sail
>>> past the check. Which would leave us with correct inode, but might
>>> give us a false negative in should_follow_link().
>>
>> Note that most of the places calling d_is_...() are protected by
>> the following: if we'd obtained dentry by __lookup_hash() and friends
>> *after* grabbing ->i_mutex on parent, we are fine - both positive-to-negative
>> and negative-to-positive are possible only with ->i_mutex held, so it
>> gives us a barrier.
>>
>> AFAICS, there are two more tricky places: walk_component() doing
>> if (!inode)
>> goto out_path_put;
>>
>> if (should_follow_link(path->dentry, follow)) {
>> with unpleasant consequences if the second test gives a false negative,
>> and similar for mountpoint_last().
>>
>> Basically, we'd concentrated on RCU races back then, and missed the possibility
>> of non-RCU-but-without-i_mutex ones. Proposed fix follows:
>
> Should be OK. I'll test it tomorrow.
Confirmed it's OK.
Reported-and-tested-by: Lin Ming <minggr@gmail.com>
Thanks.
>
> Thanks.
>
>>
>> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
>> ---
>> diff --git a/fs/dcache.c b/fs/dcache.c
>> index 40707d8..494a9def 100644
>> --- a/fs/dcache.c
>> +++ b/fs/dcache.c
>> @@ -1647,8 +1647,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
>> unsigned add_flags = d_flags_for_inode(inode);
>>
>> spin_lock(&dentry->d_lock);
>> - dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
>> - dentry->d_flags |= add_flags;
>> + __d_set_type(dentry, add_flags);
>> if (inode)
>> hlist_add_head(&dentry->d_alias, &inode->i_dentry);
>> dentry->d_inode = inode;
>> diff --git a/fs/namei.c b/fs/namei.c
>> index c6157c8..8016827 100644
>> --- a/fs/namei.c
>> +++ b/fs/namei.c
>> @@ -1542,7 +1542,7 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
>> inode = path->dentry->d_inode;
>> }
>> err = -ENOENT;
>> - if (!inode)
>> + if (!inode || d_is_negative(path->dentry))
>> goto out_path_put;
>>
>> if (should_follow_link(path->dentry, follow)) {
>> @@ -2249,7 +2249,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
>> mutex_unlock(&dir->d_inode->i_mutex);
>>
>> done:
>> - if (!dentry->d_inode) {
>> + if (!dentry->d_inode || d_is_negative(dentry)) {
>> error = -ENOENT;
>> dput(dentry);
>> goto out;
>> @@ -2994,7 +2994,7 @@ retry_lookup:
>> finish_lookup:
>> /* we _can_ be in RCU mode here */
>> error = -ENOENT;
>> - if (d_is_negative(path->dentry)) {
>> + if (!inode || d_is_negative(path->dentry)) {
>> path_to_nameidata(path, nd);
>> goto out;
>> }
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: panic in do_last()
2014-04-18 15:11 ` Lin Ming
@ 2014-04-22 17:51 ` Lin Ming
0 siblings, 0 replies; 12+ messages in thread
From: Lin Ming @ 2014-04-22 17:51 UTC (permalink / raw)
To: Al Viro; +Cc: David Howells, linux-fsdevel, Hugh Dickins, Linus Torvalds
On Fri, Apr 18, 2014 at 8:11 AM, Lin Ming <minggr@gmail.com> wrote:
> On Thu, Apr 17, 2014 at 8:40 PM, Lin Ming <minggr@gmail.com> wrote:
>> On Thu, Apr 17, 2014 at 8:17 PM, Al Viro <viro@zeniv.linux.org.uk> wrote:
>>> On Fri, Apr 18, 2014 at 03:48:37AM +0100, Al Viro wrote:
>>>> Crap... No, it's a bit trickier - we start with clearing all flags,
>>>> so if we see the _intermediate_ d_flags and new d_inode, we'll sail
>>>> past the check. Which would leave us with correct inode, but might
>>>> give us a false negative in should_follow_link().
>>>
>>> Note that most of the places calling d_is_...() are protected by
>>> the following: if we'd obtained dentry by __lookup_hash() and friends
>>> *after* grabbing ->i_mutex on parent, we are fine - both positive-to-negative
>>> and negative-to-positive are possible only with ->i_mutex held, so it
>>> gives us a barrier.
>>>
>>> AFAICS, there are two more tricky places: walk_component() doing
>>> if (!inode)
>>> goto out_path_put;
>>>
>>> if (should_follow_link(path->dentry, follow)) {
>>> with unpleasant consequences if the second test gives a false negative,
>>> and similar for mountpoint_last().
>>>
>>> Basically, we'd concentrated on RCU races back then, and missed the possibility
>>> of non-RCU-but-without-i_mutex ones. Proposed fix follows:
>>
>> Should be OK. I'll test it tomorrow.
>
> Confirmed it's OK.
>
> Reported-and-tested-by: Lin Ming <minggr@gmail.com>
Hi Al,
Was this fix merged in your vfs tree?
Thanks.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-04-22 17:51 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-18 1:14 panic in do_last() Lin Ming
2014-04-18 1:57 ` Al Viro
2014-04-18 2:17 ` Al Viro
2014-04-18 2:22 ` Lin Ming
2014-04-18 2:35 ` Lin Ming
2014-04-18 2:42 ` Al Viro
[not found] ` <CAF1ivSbqM2LorrED3MvgKBDxA9sLz_RkOEPwAfvYYmL5C9K0vA@mail.gmail.com>
2014-04-18 2:38 ` Al Viro
2014-04-18 2:48 ` Al Viro
2014-04-18 3:17 ` Al Viro
2014-04-18 3:40 ` Lin Ming
2014-04-18 15:11 ` Lin Ming
2014-04-22 17:51 ` Lin Ming
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).