Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
0b4aae7a
Commit
0b4aae7a
authored
Jun 20, 2008
by
Trond Myklebust
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NFS: Reduce the stack usage in NFSv3 create operations
Signed-off-by:
Trond Myklebust
<
Trond.Myklebust@netapp.com
>
parent
57dc9a57
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
142 additions
and
129 deletions
+142
-129
fs/nfs/nfs3proc.c
fs/nfs/nfs3proc.c
+142
-129
No files found.
fs/nfs/nfs3proc.c
View file @
0b4aae7a
...
...
@@ -248,6 +248,53 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page,
return
status
;
}
struct
nfs3_createdata
{
struct
rpc_message
msg
;
union
{
struct
nfs3_createargs
create
;
struct
nfs3_mkdirargs
mkdir
;
struct
nfs3_symlinkargs
symlink
;
struct
nfs3_mknodargs
mknod
;
}
arg
;
struct
nfs3_diropres
res
;
struct
nfs_fh
fh
;
struct
nfs_fattr
fattr
;
struct
nfs_fattr
dir_attr
;
};
static
struct
nfs3_createdata
*
nfs3_alloc_createdata
(
void
)
{
struct
nfs3_createdata
*
data
;
data
=
kzalloc
(
sizeof
(
*
data
),
GFP_KERNEL
);
if
(
data
!=
NULL
)
{
data
->
msg
.
rpc_argp
=
&
data
->
arg
;
data
->
msg
.
rpc_resp
=
&
data
->
res
;
data
->
res
.
fh
=
&
data
->
fh
;
data
->
res
.
fattr
=
&
data
->
fattr
;
data
->
res
.
dir_attr
=
&
data
->
dir_attr
;
nfs_fattr_init
(
data
->
res
.
fattr
);
nfs_fattr_init
(
data
->
res
.
dir_attr
);
}
return
data
;
}
static
int
nfs3_do_create
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nfs3_createdata
*
data
)
{
int
status
;
status
=
rpc_call_sync
(
NFS_CLIENT
(
dir
),
&
data
->
msg
,
0
);
nfs_post_op_update_inode
(
dir
,
data
->
res
.
dir_attr
);
if
(
status
==
0
)
status
=
nfs_instantiate
(
dentry
,
data
->
res
.
fh
,
data
->
res
.
fattr
);
return
status
;
}
static
void
nfs3_free_createdata
(
struct
nfs3_createdata
*
data
)
{
kfree
(
data
);
}
/*
* Create a regular file.
* For now, we don't implement O_EXCL.
...
...
@@ -256,70 +303,60 @@ static int
nfs3_proc_create
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
iattr
*
sattr
,
int
flags
,
struct
nameidata
*
nd
)
{
struct
nfs_fh
fhandle
;
struct
nfs_fattr
fattr
;
struct
nfs_fattr
dir_attr
;
struct
nfs3_createargs
arg
=
{
.
fh
=
NFS_FH
(
dir
),
.
name
=
dentry
->
d_name
.
name
,
.
len
=
dentry
->
d_name
.
len
,
.
sattr
=
sattr
,
};
struct
nfs3_diropres
res
=
{
.
dir_attr
=
&
dir_attr
,
.
fh
=
&
fhandle
,
.
fattr
=
&
fattr
};
struct
rpc_message
msg
=
{
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_CREATE
],
.
rpc_argp
=
&
arg
,
.
rpc_resp
=
&
res
,
};
struct
nfs3_createdata
*
data
;
mode_t
mode
=
sattr
->
ia_mode
;
int
status
;
int
status
=
-
ENOMEM
;
dprintk
(
"NFS call create %s
\n
"
,
dentry
->
d_name
.
name
);
arg
.
createmode
=
NFS3_CREATE_UNCHECKED
;
data
=
nfs3_alloc_createdata
();
if
(
data
==
NULL
)
goto
out
;
data
->
msg
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_CREATE
];
data
->
arg
.
create
.
fh
=
NFS_FH
(
dir
);
data
->
arg
.
create
.
name
=
dentry
->
d_name
.
name
;
data
->
arg
.
create
.
len
=
dentry
->
d_name
.
len
;
data
->
arg
.
create
.
sattr
=
sattr
;
data
->
arg
.
create
.
createmode
=
NFS3_CREATE_UNCHECKED
;
if
(
flags
&
O_EXCL
)
{
arg
.
createmode
=
NFS3_CREATE_EXCLUSIVE
;
arg
.
verifier
[
0
]
=
jiffies
;
arg
.
verifier
[
1
]
=
current
->
pid
;
data
->
arg
.
create
.
createmode
=
NFS3_CREATE_EXCLUSIVE
;
data
->
arg
.
create
.
verifier
[
0
]
=
jiffies
;
data
->
arg
.
create
.
verifier
[
1
]
=
current
->
pid
;
}
sattr
->
ia_mode
&=
~
current
->
fs
->
umask
;
again:
nfs_fattr_init
(
&
dir_attr
);
nfs_fattr_init
(
&
fattr
);
status
=
rpc_call_sync
(
NFS_CLIENT
(
dir
),
&
msg
,
0
);
nfs_refresh_inode
(
dir
,
&
dir_attr
);
for
(;;)
{
status
=
nfs3_do_create
(
dir
,
dentry
,
data
);
/* If the server doesn't support the exclusive creation semantics,
* try again with simple 'guarded' mode. */
if
(
status
==
-
ENOTSUPP
)
{
switch
(
arg
.
createmode
)
{
if
(
status
!=
-
ENOTSUPP
)
break
;
/* If the server doesn't support the exclusive creation
* semantics, try again with simple 'guarded' mode. */
switch
(
data
->
arg
.
create
.
createmode
)
{
case
NFS3_CREATE_EXCLUSIVE
:
arg
.
createmode
=
NFS3_CREATE_GUARDED
;
data
->
arg
.
create
.
createmode
=
NFS3_CREATE_GUARDED
;
break
;
case
NFS3_CREATE_GUARDED
:
arg
.
createmode
=
NFS3_CREATE_UNCHECKED
;
data
->
arg
.
create
.
createmode
=
NFS3_CREATE_UNCHECKED
;
break
;
case
NFS3_CREATE_UNCHECKED
:
goto
out
;
}
goto
again
;
nfs_fattr_init
(
data
->
res
.
dir_attr
);
nfs_fattr_init
(
data
->
res
.
fattr
);
}
if
(
status
==
0
)
status
=
nfs_instantiate
(
dentry
,
&
fhandle
,
&
fattr
);
if
(
status
!=
0
)
goto
out
;
/* When we created the file with exclusive semantics, make
* sure we set the attributes afterwards. */
if
(
arg
.
createmode
==
NFS3_CREATE_EXCLUSIVE
)
{
if
(
data
->
arg
.
create
.
createmode
==
NFS3_CREATE_EXCLUSIVE
)
{
dprintk
(
"NFS call setattr (post-create)
\n
"
);
if
(
!
(
sattr
->
ia_valid
&
ATTR_ATIME_SET
))
...
...
@@ -330,14 +367,15 @@ again:
/* Note: we could use a guarded setattr here, but I'm
* not sure this buys us anything (and I'd have
* to revamp the NFSv3 XDR code) */
status
=
nfs3_proc_setattr
(
dentry
,
&
fattr
,
sattr
);
nfs_post_op_update_inode
(
dentry
->
d_inode
,
&
fattr
);
status
=
nfs3_proc_setattr
(
dentry
,
data
->
res
.
fattr
,
sattr
);
nfs_post_op_update_inode
(
dentry
->
d_inode
,
data
->
res
.
fattr
);
dprintk
(
"NFS reply setattr (post-create): %d
\n
"
,
status
);
}
if
(
status
!=
0
)
goto
out
;
}
status
=
nfs3_proc_set_default_acl
(
dir
,
dentry
->
d_inode
,
mode
);
out:
nfs3_free_createdata
(
data
);
dprintk
(
"NFS reply create: %d
\n
"
,
status
);
return
status
;
}
...
...
@@ -452,40 +490,28 @@ static int
nfs3_proc_symlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
page
*
page
,
unsigned
int
len
,
struct
iattr
*
sattr
)
{
struct
nfs_fh
fhandle
;
struct
nfs_fattr
fattr
,
dir_attr
;
struct
nfs3_symlinkargs
arg
=
{
.
fromfh
=
NFS_FH
(
dir
),
.
fromname
=
dentry
->
d_name
.
name
,
.
fromlen
=
dentry
->
d_name
.
len
,
.
pages
=
&
page
,
.
pathlen
=
len
,
.
sattr
=
sattr
};
struct
nfs3_diropres
res
=
{
.
dir_attr
=
&
dir_attr
,
.
fh
=
&
fhandle
,
.
fattr
=
&
fattr
};
struct
rpc_message
msg
=
{
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_SYMLINK
],
.
rpc_argp
=
&
arg
,
.
rpc_resp
=
&
res
,
};
int
status
;
struct
nfs3_createdata
*
data
;
int
status
=
-
ENOMEM
;
if
(
len
>
NFS3_MAXPATHLEN
)
return
-
ENAMETOOLONG
;
dprintk
(
"NFS call symlink %s
\n
"
,
dentry
->
d_name
.
name
);
nfs_fattr_init
(
&
dir_attr
);
nfs_fattr_init
(
&
fattr
);
status
=
rpc_call_sync
(
NFS_CLIENT
(
dir
),
&
msg
,
0
);
nfs_post_op_update_inode
(
dir
,
&
dir_attr
);
if
(
status
!=
0
)
data
=
nfs3_alloc_createdata
();
if
(
data
==
NULL
)
goto
out
;
status
=
nfs_instantiate
(
dentry
,
&
fhandle
,
&
fattr
);
data
->
msg
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_SYMLINK
];
data
->
arg
.
symlink
.
fromfh
=
NFS_FH
(
dir
);
data
->
arg
.
symlink
.
fromname
=
dentry
->
d_name
.
name
;
data
->
arg
.
symlink
.
fromlen
=
dentry
->
d_name
.
len
;
data
->
arg
.
symlink
.
pages
=
&
page
;
data
->
arg
.
symlink
.
pathlen
=
len
;
data
->
arg
.
symlink
.
sattr
=
sattr
;
status
=
nfs3_do_create
(
dir
,
dentry
,
data
);
nfs3_free_createdata
(
data
);
out:
dprintk
(
"NFS reply symlink: %d
\n
"
,
status
);
return
status
;
...
...
@@ -494,42 +520,31 @@ out:
static
int
nfs3_proc_mkdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
iattr
*
sattr
)
{
struct
nfs_fh
fhandle
;
struct
nfs_fattr
fattr
,
dir_attr
;
struct
nfs3_mkdirargs
arg
=
{
.
fh
=
NFS_FH
(
dir
),
.
name
=
dentry
->
d_name
.
name
,
.
len
=
dentry
->
d_name
.
len
,
.
sattr
=
sattr
};
struct
nfs3_diropres
res
=
{
.
dir_attr
=
&
dir_attr
,
.
fh
=
&
fhandle
,
.
fattr
=
&
fattr
};
struct
rpc_message
msg
=
{
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_MKDIR
],
.
rpc_argp
=
&
arg
,
.
rpc_resp
=
&
res
,
};
struct
nfs3_createdata
*
data
;
int
mode
=
sattr
->
ia_mode
;
int
status
;
int
status
=
-
ENOMEM
;
dprintk
(
"NFS call mkdir %s
\n
"
,
dentry
->
d_name
.
name
);
sattr
->
ia_mode
&=
~
current
->
fs
->
umask
;
nfs_fattr_init
(
&
dir_attr
);
nfs_fattr_init
(
&
fattr
);
status
=
rpc_call_sync
(
NFS_CLIENT
(
dir
),
&
msg
,
0
);
nfs_post_op_update_inode
(
dir
,
&
dir_attr
);
if
(
status
!=
0
)
data
=
nfs3_alloc_createdata
();
if
(
data
==
NULL
)
goto
out
;
status
=
nfs_instantiate
(
dentry
,
&
fhandle
,
&
fattr
);
data
->
msg
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_MKDIR
];
data
->
arg
.
mkdir
.
fh
=
NFS_FH
(
dir
);
data
->
arg
.
mkdir
.
name
=
dentry
->
d_name
.
name
;
data
->
arg
.
mkdir
.
len
=
dentry
->
d_name
.
len
;
data
->
arg
.
mkdir
.
sattr
=
sattr
;
status
=
nfs3_do_create
(
dir
,
dentry
,
data
);
if
(
status
!=
0
)
goto
out
;
status
=
nfs3_proc_set_default_acl
(
dir
,
dentry
->
d_inode
,
mode
);
out:
nfs3_free_createdata
(
data
);
dprintk
(
"NFS reply mkdir: %d
\n
"
,
status
);
return
status
;
}
...
...
@@ -615,52 +630,50 @@ static int
nfs3_proc_mknod
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
iattr
*
sattr
,
dev_t
rdev
)
{
struct
nfs_fh
fh
;
struct
nfs_fattr
fattr
,
dir_attr
;
struct
nfs3_mknodargs
arg
=
{
.
fh
=
NFS_FH
(
dir
),
.
name
=
dentry
->
d_name
.
name
,
.
len
=
dentry
->
d_name
.
len
,
.
sattr
=
sattr
,
.
rdev
=
rdev
};
struct
nfs3_diropres
res
=
{
.
dir_attr
=
&
dir_attr
,
.
fh
=
&
fh
,
.
fattr
=
&
fattr
};
struct
rpc_message
msg
=
{
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_MKNOD
],
.
rpc_argp
=
&
arg
,
.
rpc_resp
=
&
res
,
};
struct
nfs3_createdata
*
data
;
mode_t
mode
=
sattr
->
ia_mode
;
int
status
;
switch
(
sattr
->
ia_mode
&
S_IFMT
)
{
case
S_IFBLK
:
arg
.
type
=
NF3BLK
;
break
;
case
S_IFCHR
:
arg
.
type
=
NF3CHR
;
break
;
case
S_IFIFO
:
arg
.
type
=
NF3FIFO
;
break
;
case
S_IFSOCK
:
arg
.
type
=
NF3SOCK
;
break
;
default:
return
-
EINVAL
;
}
int
status
=
-
ENOMEM
;
dprintk
(
"NFS call mknod %s %u:%u
\n
"
,
dentry
->
d_name
.
name
,
MAJOR
(
rdev
),
MINOR
(
rdev
));
sattr
->
ia_mode
&=
~
current
->
fs
->
umask
;
nfs_fattr_init
(
&
dir_attr
);
nfs_fattr_init
(
&
fattr
);
status
=
rpc_call_sync
(
NFS_CLIENT
(
dir
),
&
msg
,
0
);
nfs_post_op_update_inode
(
dir
,
&
dir_attr
);
if
(
status
!=
0
)
data
=
nfs3_alloc_createdata
();
if
(
data
==
NULL
)
goto
out
;
data
->
msg
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_MKNOD
];
data
->
arg
.
mknod
.
fh
=
NFS_FH
(
dir
);
data
->
arg
.
mknod
.
name
=
dentry
->
d_name
.
name
;
data
->
arg
.
mknod
.
len
=
dentry
->
d_name
.
len
;
data
->
arg
.
mknod
.
sattr
=
sattr
;
data
->
arg
.
mknod
.
rdev
=
rdev
;
switch
(
sattr
->
ia_mode
&
S_IFMT
)
{
case
S_IFBLK
:
data
->
arg
.
mknod
.
type
=
NF3BLK
;
break
;
case
S_IFCHR
:
data
->
arg
.
mknod
.
type
=
NF3CHR
;
break
;
case
S_IFIFO
:
data
->
arg
.
mknod
.
type
=
NF3FIFO
;
break
;
case
S_IFSOCK
:
data
->
arg
.
mknod
.
type
=
NF3SOCK
;
break
;
default:
status
=
-
EINVAL
;
goto
out
;
status
=
nfs_instantiate
(
dentry
,
&
fh
,
&
fattr
);
}
status
=
nfs3_do_create
(
dir
,
dentry
,
data
);
if
(
status
!=
0
)
goto
out
;
status
=
nfs3_proc_set_default_acl
(
dir
,
dentry
->
d_inode
,
mode
);
out:
nfs3_free_createdata
(
data
);
dprintk
(
"NFS reply mknod: %d
\n
"
,
status
);
return
status
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment