Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
f884dcae
Commit
f884dcae
authored
Aug 10, 2009
by
Trond Myklebust
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'sunrpc_cache-for-2.6.32' into nfs-for-2.6.32
parents
976a6f92
8854e82d
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
939 additions
and
485 deletions
+939
-485
fs/nfs/idmap.c
fs/nfs/idmap.c
+3
-3
fs/nfsd/export.c
fs/nfsd/export.c
+12
-2
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4idmap.c
+16
-4
include/linux/sunrpc/cache.h
include/linux/sunrpc/cache.h
+34
-6
include/linux/sunrpc/clnt.h
include/linux/sunrpc/clnt.h
+2
-3
include/linux/sunrpc/rpc_pipe_fs.h
include/linux/sunrpc/rpc_pipe_fs.h
+14
-4
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/auth_gss.c
+6
-6
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/auth_gss/svcauth_gss.c
+6
-1
net/sunrpc/cache.c
net/sunrpc/cache.c
+401
-149
net/sunrpc/clnt.c
net/sunrpc/clnt.c
+39
-21
net/sunrpc/rpc_pipe.c
net/sunrpc/rpc_pipe.c
+394
-284
net/sunrpc/svcauth_unix.c
net/sunrpc/svcauth_unix.c
+12
-2
No files found.
fs/nfs/idmap.c
View file @
f884dcae
...
...
@@ -101,7 +101,7 @@ static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
static
unsigned
int
fnvhash32
(
const
void
*
,
size_t
);
static
struct
rpc_pipe_ops
idmap_upcall_ops
=
{
static
const
struct
rpc_pipe_ops
idmap_upcall_ops
=
{
.
upcall
=
idmap_pipe_upcall
,
.
downcall
=
idmap_pipe_downcall
,
.
destroy_msg
=
idmap_pipe_destroy_msg
,
...
...
@@ -119,8 +119,8 @@ nfs_idmap_new(struct nfs_client *clp)
if
(
idmap
==
NULL
)
return
-
ENOMEM
;
idmap
->
idmap_dentry
=
rpc_mkpipe
(
clp
->
cl_rpcclient
->
cl_
dentry
,
"idmap"
,
idmap
,
&
idmap_upcall_ops
,
0
);
idmap
->
idmap_dentry
=
rpc_mkpipe
(
clp
->
cl_rpcclient
->
cl_
path
.
dentry
,
"idmap"
,
idmap
,
&
idmap_upcall_ops
,
0
);
if
(
IS_ERR
(
idmap
->
idmap_dentry
))
{
error
=
PTR_ERR
(
idmap
->
idmap_dentry
);
kfree
(
idmap
);
...
...
fs/nfsd/export.c
View file @
f884dcae
...
...
@@ -85,6 +85,11 @@ static void expkey_request(struct cache_detail *cd,
(
*
bpp
)[
-
1
]
=
'\n'
;
}
static
int
expkey_upcall
(
struct
cache_detail
*
cd
,
struct
cache_head
*
h
)
{
return
sunrpc_cache_pipe_upcall
(
cd
,
h
,
expkey_request
);
}
static
struct
svc_expkey
*
svc_expkey_update
(
struct
svc_expkey
*
new
,
struct
svc_expkey
*
old
);
static
struct
svc_expkey
*
svc_expkey_lookup
(
struct
svc_expkey
*
);
static
struct
cache_detail
svc_expkey_cache
;
...
...
@@ -259,7 +264,7 @@ static struct cache_detail svc_expkey_cache = {
.
hash_table
=
expkey_table
,
.
name
=
"nfsd.fh"
,
.
cache_put
=
expkey_put
,
.
cache_
request
=
expkey_request
,
.
cache_
upcall
=
expkey_upcall
,
.
cache_parse
=
expkey_parse
,
.
cache_show
=
expkey_show
,
.
match
=
expkey_match
,
...
...
@@ -355,6 +360,11 @@ static void svc_export_request(struct cache_detail *cd,
(
*
bpp
)[
-
1
]
=
'\n'
;
}
static
int
svc_export_upcall
(
struct
cache_detail
*
cd
,
struct
cache_head
*
h
)
{
return
sunrpc_cache_pipe_upcall
(
cd
,
h
,
svc_export_request
);
}
static
struct
svc_export
*
svc_export_update
(
struct
svc_export
*
new
,
struct
svc_export
*
old
);
static
struct
svc_export
*
svc_export_lookup
(
struct
svc_export
*
);
...
...
@@ -724,7 +734,7 @@ struct cache_detail svc_export_cache = {
.
hash_table
=
export_table
,
.
name
=
"nfsd.export"
,
.
cache_put
=
svc_export_put
,
.
cache_
request
=
svc_export_request
,
.
cache_
upcall
=
svc_export_upcall
,
.
cache_parse
=
svc_export_parse
,
.
cache_show
=
svc_export_show
,
.
match
=
svc_export_match
,
...
...
fs/nfsd/nfs4idmap.c
View file @
f884dcae
...
...
@@ -145,6 +145,12 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
(
*
bpp
)[
-
1
]
=
'\n'
;
}
static
int
idtoname_upcall
(
struct
cache_detail
*
cd
,
struct
cache_head
*
ch
)
{
return
sunrpc_cache_pipe_upcall
(
cd
,
ch
,
idtoname_request
);
}
static
int
idtoname_match
(
struct
cache_head
*
ca
,
struct
cache_head
*
cb
)
{
...
...
@@ -175,10 +181,10 @@ idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
}
static
void
warn_no_idmapd
(
struct
cache_detail
*
detail
)
warn_no_idmapd
(
struct
cache_detail
*
detail
,
int
has_died
)
{
printk
(
"nfsd: nfsv4 idmapping failing: has idmapd %s?
\n
"
,
detail
->
last_close
?
"died"
:
"not been started"
);
has_died
?
"died"
:
"not been started"
);
}
...
...
@@ -192,7 +198,7 @@ static struct cache_detail idtoname_cache = {
.
hash_table
=
idtoname_table
,
.
name
=
"nfs4.idtoname"
,
.
cache_put
=
ent_put
,
.
cache_
request
=
idtoname_request
,
.
cache_
upcall
=
idtoname_upcall
,
.
cache_parse
=
idtoname_parse
,
.
cache_show
=
idtoname_show
,
.
warn_no_listener
=
warn_no_idmapd
,
...
...
@@ -324,6 +330,12 @@ nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
(
*
bpp
)[
-
1
]
=
'\n'
;
}
static
int
nametoid_upcall
(
struct
cache_detail
*
cd
,
struct
cache_head
*
ch
)
{
return
sunrpc_cache_pipe_upcall
(
cd
,
ch
,
nametoid_request
);
}
static
int
nametoid_match
(
struct
cache_head
*
ca
,
struct
cache_head
*
cb
)
{
...
...
@@ -363,7 +375,7 @@ static struct cache_detail nametoid_cache = {
.
hash_table
=
nametoid_table
,
.
name
=
"nfs4.nametoid"
,
.
cache_put
=
ent_put
,
.
cache_
request
=
nametoid_request
,
.
cache_
upcall
=
nametoid_upcall
,
.
cache_parse
=
nametoid_parse
,
.
cache_show
=
nametoid_show
,
.
warn_no_listener
=
warn_no_idmapd
,
...
...
include/linux/sunrpc/cache.h
View file @
f884dcae
...
...
@@ -59,6 +59,15 @@ struct cache_head {
#define CACHE_NEW_EXPIRY 120
/* keep new things pending confirmation for 120 seconds */
struct
cache_detail_procfs
{
struct
proc_dir_entry
*
proc_ent
;
struct
proc_dir_entry
*
flush_ent
,
*
channel_ent
,
*
content_ent
;
};
struct
cache_detail_pipefs
{
struct
dentry
*
dir
;
};
struct
cache_detail
{
struct
module
*
owner
;
int
hash_size
;
...
...
@@ -70,15 +79,17 @@ struct cache_detail {
char
*
name
;
void
(
*
cache_put
)(
struct
kref
*
);
void
(
*
cache_request
)(
struct
cache_detail
*
cd
,
struct
cache_head
*
h
,
char
**
bpp
,
int
*
blen
);
int
(
*
cache_upcall
)(
struct
cache_detail
*
,
struct
cache_head
*
);
int
(
*
cache_parse
)(
struct
cache_detail
*
,
char
*
buf
,
int
len
);
int
(
*
cache_show
)(
struct
seq_file
*
m
,
struct
cache_detail
*
cd
,
struct
cache_head
*
h
);
void
(
*
warn_no_listener
)(
struct
cache_detail
*
cd
,
int
has_died
);
struct
cache_head
*
(
*
alloc
)(
void
);
int
(
*
match
)(
struct
cache_head
*
orig
,
struct
cache_head
*
new
);
...
...
@@ -96,13 +107,15 @@ struct cache_detail {
/* fields for communication over channel */
struct
list_head
queue
;
struct
proc_dir_entry
*
proc_ent
;
struct
proc_dir_entry
*
flush_ent
,
*
channel_ent
,
*
content_ent
;
atomic_t
readers
;
/* how many time is /chennel open */
time_t
last_close
;
/* if no readers, when did last close */
time_t
last_warn
;
/* when we last warned about no readers */
void
(
*
warn_no_listener
)(
struct
cache_detail
*
cd
);
union
{
struct
cache_detail_procfs
procfs
;
struct
cache_detail_pipefs
pipefs
;
}
u
;
};
...
...
@@ -127,6 +140,10 @@ struct cache_deferred_req {
};
extern
const
struct
file_operations
cache_file_operations_pipefs
;
extern
const
struct
file_operations
content_file_operations_pipefs
;
extern
const
struct
file_operations
cache_flush_operations_pipefs
;
extern
struct
cache_head
*
sunrpc_cache_lookup
(
struct
cache_detail
*
detail
,
struct
cache_head
*
key
,
int
hash
);
...
...
@@ -134,6 +151,13 @@ extern struct cache_head *
sunrpc_cache_update
(
struct
cache_detail
*
detail
,
struct
cache_head
*
new
,
struct
cache_head
*
old
,
int
hash
);
extern
int
sunrpc_cache_pipe_upcall
(
struct
cache_detail
*
detail
,
struct
cache_head
*
h
,
void
(
*
cache_request
)(
struct
cache_detail
*
,
struct
cache_head
*
,
char
**
,
int
*
));
extern
void
cache_clean_deferred
(
void
*
owner
);
...
...
@@ -171,6 +195,10 @@ extern void cache_purge(struct cache_detail *detail);
extern
int
cache_register
(
struct
cache_detail
*
cd
);
extern
void
cache_unregister
(
struct
cache_detail
*
cd
);
extern
int
sunrpc_cache_register_pipefs
(
struct
dentry
*
parent
,
const
char
*
,
mode_t
,
struct
cache_detail
*
);
extern
void
sunrpc_cache_unregister_pipefs
(
struct
cache_detail
*
);
extern
void
qword_add
(
char
**
bpp
,
int
*
lp
,
char
*
str
);
extern
void
qword_addhex
(
char
**
bpp
,
int
*
lp
,
char
*
buf
,
int
blen
);
extern
int
qword_get
(
char
**
bpp
,
char
*
dest
,
int
bufsize
);
...
...
include/linux/sunrpc/clnt.h
View file @
f884dcae
...
...
@@ -21,6 +21,7 @@
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/timer.h>
#include <asm/signal.h>
#include <linux/path.h>
struct
rpc_inode
;
...
...
@@ -54,9 +55,7 @@ struct rpc_clnt {
int
cl_nodelen
;
/* nodename length */
char
cl_nodename
[
UNX_MAXNODENAME
];
char
cl_pathname
[
30
];
/* Path in rpc_pipe_fs */
struct
vfsmount
*
cl_vfsmnt
;
struct
dentry
*
cl_dentry
;
/* inode */
struct
path
cl_path
;
struct
rpc_clnt
*
cl_parent
;
/* Points to parent of clones */
struct
rpc_rtt
cl_rtt_default
;
struct
rpc_timeout
cl_timeout_default
;
...
...
include/linux/sunrpc/rpc_pipe_fs.h
View file @
f884dcae
...
...
@@ -32,8 +32,8 @@ struct rpc_inode {
wait_queue_head_t
waitq
;
#define RPC_PIPE_WAIT_FOR_OPEN 1
int
flags
;
struct
rpc_pipe_ops
*
ops
;
struct
delayed_work
queue_timeout
;
const
struct
rpc_pipe_ops
*
ops
;
};
static
inline
struct
rpc_inode
*
...
...
@@ -44,9 +44,19 @@ RPC_I(struct inode *inode)
extern
int
rpc_queue_upcall
(
struct
inode
*
,
struct
rpc_pipe_msg
*
);
extern
struct
dentry
*
rpc_mkdir
(
char
*
,
struct
rpc_clnt
*
);
extern
int
rpc_rmdir
(
struct
dentry
*
);
extern
struct
dentry
*
rpc_mkpipe
(
struct
dentry
*
,
const
char
*
,
void
*
,
struct
rpc_pipe_ops
*
,
int
flags
);
struct
rpc_clnt
;
extern
struct
dentry
*
rpc_create_client_dir
(
struct
dentry
*
,
struct
qstr
*
,
struct
rpc_clnt
*
);
extern
int
rpc_remove_client_dir
(
struct
dentry
*
);
struct
cache_detail
;
extern
struct
dentry
*
rpc_create_cache_dir
(
struct
dentry
*
,
struct
qstr
*
,
mode_t
umode
,
struct
cache_detail
*
);
extern
void
rpc_remove_cache_dir
(
struct
dentry
*
);
extern
struct
dentry
*
rpc_mkpipe
(
struct
dentry
*
,
const
char
*
,
void
*
,
const
struct
rpc_pipe_ops
*
,
int
flags
);
extern
int
rpc_unlink
(
struct
dentry
*
);
extern
struct
vfsmount
*
rpc_get_mount
(
void
);
extern
void
rpc_put_mount
(
void
);
...
...
net/sunrpc/auth_gss/auth_gss.c
View file @
f884dcae
...
...
@@ -89,8 +89,8 @@ static struct rpc_wait_queue pipe_version_rpc_waitqueue;
static
DECLARE_WAIT_QUEUE_HEAD
(
pipe_version_waitqueue
);
static
void
gss_free_ctx
(
struct
gss_cl_ctx
*
);
static
struct
rpc_pipe_ops
gss_upcall_ops_v0
;
static
struct
rpc_pipe_ops
gss_upcall_ops_v1
;
static
const
struct
rpc_pipe_ops
gss_upcall_ops_v0
;
static
const
struct
rpc_pipe_ops
gss_upcall_ops_v1
;
static
inline
struct
gss_cl_ctx
*
gss_get_ctx
(
struct
gss_cl_ctx
*
ctx
)
...
...
@@ -777,7 +777,7 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
* that we supported only the old pipe. So we instead create
* the new pipe first.
*/
gss_auth
->
dentry
[
1
]
=
rpc_mkpipe
(
clnt
->
cl_dentry
,
gss_auth
->
dentry
[
1
]
=
rpc_mkpipe
(
clnt
->
cl_
path
.
dentry
,
"gssd"
,
clnt
,
&
gss_upcall_ops_v1
,
RPC_PIPE_WAIT_FOR_OPEN
);
...
...
@@ -786,7 +786,7 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
goto
err_put_mech
;
}
gss_auth
->
dentry
[
0
]
=
rpc_mkpipe
(
clnt
->
cl_dentry
,
gss_auth
->
dentry
[
0
]
=
rpc_mkpipe
(
clnt
->
cl_
path
.
dentry
,
gss_auth
->
mech
->
gm_name
,
clnt
,
&
gss_upcall_ops_v0
,
RPC_PIPE_WAIT_FOR_OPEN
);
...
...
@@ -1507,7 +1507,7 @@ static const struct rpc_credops gss_nullops = {
.
crunwrap_resp
=
gss_unwrap_resp
,
};
static
struct
rpc_pipe_ops
gss_upcall_ops_v0
=
{
static
const
struct
rpc_pipe_ops
gss_upcall_ops_v0
=
{
.
upcall
=
gss_pipe_upcall
,
.
downcall
=
gss_pipe_downcall
,
.
destroy_msg
=
gss_pipe_destroy_msg
,
...
...
@@ -1515,7 +1515,7 @@ static struct rpc_pipe_ops gss_upcall_ops_v0 = {
.
release_pipe
=
gss_pipe_release
,
};
static
struct
rpc_pipe_ops
gss_upcall_ops_v1
=
{
static
const
struct
rpc_pipe_ops
gss_upcall_ops_v1
=
{
.
upcall
=
gss_pipe_upcall
,
.
downcall
=
gss_pipe_downcall
,
.
destroy_msg
=
gss_pipe_destroy_msg
,
...
...
net/sunrpc/auth_gss/svcauth_gss.c
View file @
f884dcae
...
...
@@ -181,6 +181,11 @@ static void rsi_request(struct cache_detail *cd,
(
*
bpp
)[
-
1
]
=
'\n'
;
}
static
int
rsi_upcall
(
struct
cache_detail
*
cd
,
struct
cache_head
*
h
)
{
return
sunrpc_cache_pipe_upcall
(
cd
,
h
,
rsi_request
);
}
static
int
rsi_parse
(
struct
cache_detail
*
cd
,
char
*
mesg
,
int
mlen
)
...
...
@@ -270,7 +275,7 @@ static struct cache_detail rsi_cache = {
.
hash_table
=
rsi_table
,
.
name
=
"auth.rpcsec.init"
,
.
cache_put
=
rsi_put
,
.
cache_
request
=
rsi_request
,
.
cache_
upcall
=
rsi_upcall
,
.
cache_parse
=
rsi_parse
,
.
match
=
rsi_match
,
.
init
=
rsi_init
,
...
...
net/sunrpc/cache.c
View file @
f884dcae
...
...
@@ -27,10 +27,12 @@
#include <linux/net.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
#include <asm/ioctls.h>
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/cache.h>
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
#define RPCDBG_FACILITY RPCDBG_CACHE
...
...
@@ -175,7 +177,13 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
}
EXPORT_SYMBOL_GPL
(
sunrpc_cache_update
);
static
int
cache_make_upcall
(
struct
cache_detail
*
detail
,
struct
cache_head
*
h
);
static
int
cache_make_upcall
(
struct
cache_detail
*
cd
,
struct
cache_head
*
h
)
{
if
(
!
cd
->
cache_upcall
)
return
-
EINVAL
;
return
cd
->
cache_upcall
(
cd
,
h
);
}
/*
* This is the generic cache management routine for all
* the authentication caches.
...
...
@@ -284,76 +292,11 @@ static DEFINE_SPINLOCK(cache_list_lock);
static
struct
cache_detail
*
current_detail
;
static
int
current_index
;
static
const
struct
file_operations
cache_file_operations
;
static
const
struct
file_operations
content_file_operations
;
static
const
struct
file_operations
cache_flush_operations
;
static
void
do_cache_clean
(
struct
work_struct
*
work
);
static
DECLARE_DELAYED_WORK
(
cache_cleaner
,
do_cache_clean
);
static
void
remove_cache_proc_entries
(
struct
cache_detail
*
cd
)
{
if
(
cd
->
proc_ent
==
NULL
)
return
;
if
(
cd
->
flush_ent
)
remove_proc_entry
(
"flush"
,
cd
->
proc_ent
);
if
(
cd
->
channel_ent
)
remove_proc_entry
(
"channel"
,
cd
->
proc_ent
);
if
(
cd
->
content_ent
)
remove_proc_entry
(
"content"
,
cd
->
proc_ent
);
cd
->
proc_ent
=
NULL
;
remove_proc_entry
(
cd
->
name
,
proc_net_rpc
);
}
#ifdef CONFIG_PROC_FS
static
int
create_cache_proc_entries
(
struct
cache_detail
*
cd
)
{
struct
proc_dir_entry
*
p
;
cd
->
proc_ent
=
proc_mkdir
(
cd
->
name
,
proc_net_rpc
);
if
(
cd
->
proc_ent
==
NULL
)
goto
out_nomem
;
cd
->
channel_ent
=
cd
->
content_ent
=
NULL
;
p
=
proc_create_data
(
"flush"
,
S_IFREG
|
S_IRUSR
|
S_IWUSR
,
cd
->
proc_ent
,
&
cache_flush_operations
,
cd
);
cd
->
flush_ent
=
p
;
if
(
p
==
NULL
)
goto
out_nomem
;
if
(
cd
->
cache_request
||
cd
->
cache_parse
)
{
p
=
proc_create_data
(
"channel"
,
S_IFREG
|
S_IRUSR
|
S_IWUSR
,
cd
->
proc_ent
,
&
cache_file_operations
,
cd
);
cd
->
channel_ent
=
p
;
if
(
p
==
NULL
)
goto
out_nomem
;
}
if
(
cd
->
cache_show
)
{
p
=
proc_create_data
(
"content"
,
S_IFREG
|
S_IRUSR
|
S_IWUSR
,
cd
->
proc_ent
,
&
content_file_operations
,
cd
);
cd
->
content_ent
=
p
;
if
(
p
==
NULL
)
goto
out_nomem
;
}
return
0
;
out_nomem:
remove_cache_proc_entries
(
cd
);
return
-
ENOMEM
;
}
#else
/* CONFIG_PROC_FS */
static
int
create_cache_proc_entries
(
struct
cache_detail
*
cd
)
{
return
0
;
}
#endif
int
cache_register
(
struct
cache_detail
*
cd
)
static
void
sunrpc_init_cache_detail
(
struct
cache_detail
*
cd
)
{
int
ret
;
ret
=
create_cache_proc_entries
(
cd
);
if
(
ret
)
return
ret
;
rwlock_init
(
&
cd
->
hash_lock
);
INIT_LIST_HEAD
(
&
cd
->
queue
);
spin_lock
(
&
cache_list_lock
);
...
...
@@ -367,11 +310,9 @@ int cache_register(struct cache_detail *cd)
/* start the cleaning process */
schedule_delayed_work
(
&
cache_cleaner
,
0
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
cache_register
);
void
cache_unregister
(
struct
cache_detail
*
cd
)
static
void
sunrpc_destroy_cache_detail
(
struct
cache_detail
*
cd
)
{
cache_purge
(
cd
);
spin_lock
(
&
cache_list_lock
);
...
...
@@ -386,7 +327,6 @@ void cache_unregister(struct cache_detail *cd)
list_del_init
(
&
cd
->
others
);
write_unlock
(
&
cd
->
hash_lock
);
spin_unlock
(
&
cache_list_lock
);
remove_cache_proc_entries
(
cd
);
if
(
list_empty
(
&
cache_list
))
{
/* module must be being unloaded so its safe to kill the worker */
cancel_delayed_work_sync
(
&
cache_cleaner
);
...
...
@@ -395,7 +335,6 @@ void cache_unregister(struct cache_detail *cd)
out:
printk
(
KERN_ERR
"nfsd: failed to unregister %s cache
\n
"
,
cd
->
name
);
}
EXPORT_SYMBOL_GPL
(
cache_unregister
);
/* clean cache tries to find something to clean
* and cleans it.
...
...
@@ -687,18 +626,18 @@ struct cache_reader {
int
offset
;
/* if non-0, we have a refcnt on next request */
};
static
ssize_t
cache_read
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
cache_read
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
,
struct
cache_detail
*
cd
)
{
struct
cache_reader
*
rp
=
filp
->
private_data
;
struct
cache_request
*
rq
;
struct
cache_detail
*
cd
=
PDE
(
filp
->
f_path
.
dentry
->
d_inode
)
->
data
;
struct
inode
*
inode
=
filp
->
f_path
.
dentry
->
d_inode
;
int
err
;
if
(
count
==
0
)
return
0
;
mutex_lock
(
&
queue_io
_mutex
);
/* protect against multiple concurrent
mutex_lock
(
&
inode
->
i
_mutex
);
/* protect against multiple concurrent
* readers on this file */
again:
spin_lock
(
&
queue_lock
);
...
...
@@ -711,7 +650,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
}
if
(
rp
->
q
.
list
.
next
==
&
cd
->
queue
)
{
spin_unlock
(
&
queue_lock
);
mutex_unlock
(
&
queue_io
_mutex
);
mutex_unlock
(
&
inode
->
i
_mutex
);
BUG_ON
(
rp
->
offset
);
return
0
;
}
...
...
@@ -758,49 +697,90 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
}
if
(
err
==
-
EAGAIN
)
goto
again
;
mutex_unlock
(
&
queue_io
_mutex
);
mutex_unlock
(
&
inode
->
i
_mutex
);
return
err
?
err
:
count
;
}
static
char
write_buf
[
8192
];
/* protected by queue_io_mutex */
static
ssize_t
cache_do_downcall
(
char
*
kaddr
,
const
char
__user
*
buf
,
size_t
count
,
struct
cache_detail
*
cd
)
{
ssize_t
ret
;
if
(
copy_from_user
(
kaddr
,
buf
,
count
))
return
-
EFAULT
;
kaddr
[
count
]
=
'\0'
;
ret
=
cd
->
cache_parse
(
cd
,
kaddr
,
count
);
if
(
!
ret
)
ret
=
count
;
return
ret
;
}
static
ssize_t
cache_write
(
struct
file
*
filp
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
cache_slow_downcall
(
const
char
__user
*
buf
,
size_t
count
,
struct
cache_detail
*
cd
)
{
int
err
;
s
truct
cache_detail
*
cd
=
PDE
(
filp
->
f_path
.
dentry
->
d_inode
)
->
data
;
static
char
write_buf
[
8192
];
/* protected by queue_io_mutex */
s
size_t
ret
=
-
EINVAL
;
if
(
count
==
0
)
return
0
;
if
(
count
>=
sizeof
(
write_buf
))
return
-
EINVAL
;
goto
out
;
mutex_lock
(
&
queue_io_mutex
);
ret
=
cache_do_downcall
(
write_buf
,
buf
,
count
,
cd
);
mutex_unlock
(
&
queue_io_mutex
);
out:
return
ret
;
}
if
(
copy_from_user
(
write_buf
,
buf
,
count
))
{
mutex_unlock
(
&
queue_io_mutex
);
return
-
EFAULT
;
}
write_buf
[
count
]
=
'\0'
;
if
(
cd
->
cache_parse
)
err
=
cd
->
cache_parse
(
cd
,
write_buf
,
count
);
else
err
=
-
EINVAL
;
static
ssize_t
cache_downcall
(
struct
address_space
*
mapping
,
const
char
__user
*
buf
,
size_t
count
,
struct
cache_detail
*
cd
)
{
struct
page
*
page
;
char
*
kaddr
;
ssize_t
ret
=
-
ENOMEM
;
if
(
count
>=
PAGE_CACHE_SIZE
)
goto
out_slow
;
page
=
find_or_create_page
(
mapping
,
0
,
GFP_KERNEL
);
if
(
!
page
)
goto
out_slow
;
kaddr
=
kmap
(
page
);
ret
=
cache_do_downcall
(
kaddr
,
buf
,
count
,
cd
);
kunmap
(
page
);
unlock_page
(
page
);
page_cache_release
(
page
);
return
ret
;
out_slow:
return
cache_slow_downcall
(
buf
,
count
,
cd
);
}
mutex_unlock
(
&
queue_io_mutex
);
return
err
?
err
:
count
;
static
ssize_t
cache_write
(
struct
file
*
filp
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
,
struct
cache_detail
*
cd
)
{
struct
address_space
*
mapping
=
filp
->
f_mapping
;
struct
inode
*
inode
=
filp
->
f_path
.
dentry
->
d_inode
;
ssize_t
ret
=
-
EINVAL
;
if
(
!
cd
->
cache_parse
)
goto
out
;
mutex_lock
(
&
inode
->
i_mutex
);
ret
=
cache_downcall
(
mapping
,
buf
,
count
,
cd
);
mutex_unlock
(
&
inode
->
i_mutex
);
out:
return
ret
;
}
static
DECLARE_WAIT_QUEUE_HEAD
(
queue_wait
);
static
unsigned
int
cache_poll
(
struct
file
*
filp
,
poll_table
*
wait
)
static
unsigned
int
cache_poll
(
struct
file
*
filp
,
poll_table
*
wait
,
struct
cache_detail
*
cd
)
{
unsigned
int
mask
;
struct
cache_reader
*
rp
=
filp
->
private_data
;
struct
cache_queue
*
cq
;
struct
cache_detail
*
cd
=
PDE
(
filp
->
f_path
.
dentry
->
d_inode
)
->
data
;
poll_wait
(
filp
,
&
queue_wait
,
wait
);
...
...
@@ -822,14 +802,13 @@ cache_poll(struct file *filp, poll_table *wait)
return
mask
;
}
static
int
cache_ioctl
(
struct
inode
*
ino
,
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
)
static
int
cache_ioctl
(
struct
inode
*
ino
,
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
,
struct
cache_detail
*
cd
)
{
int
len
=
0
;
struct
cache_reader
*
rp
=
filp
->
private_data
;
struct
cache_queue
*
cq
;
struct
cache_detail
*
cd
=
PDE
(
ino
)
->
data
;
if
(
cmd
!=
FIONREAD
||
!
rp
)
return
-
EINVAL
;
...
...
@@ -852,15 +831,13 @@ cache_ioctl(struct inode *ino, struct file *filp,
return
put_user
(
len
,
(
int
__user
*
)
arg
);
}
static
int
cache_open
(
struct
inode
*
inode
,
struct
file
*
filp
)
static
int
cache_open
(
struct
inode
*
inode
,
struct
file
*
filp
,
struct
cache_detail
*
cd
)
{
struct
cache_reader
*
rp
=
NULL
;
nonseekable_open
(
inode
,
filp
);
if
(
filp
->
f_mode
&
FMODE_READ
)
{
struct
cache_detail
*
cd
=
PDE
(
inode
)
->
data
;
rp
=
kmalloc
(
sizeof
(
*
rp
),
GFP_KERNEL
);
if
(
!
rp
)
return
-
ENOMEM
;
...
...
@@ -875,11 +852,10 @@ cache_open(struct inode *inode, struct file *filp)
return
0
;
}
static
int
cache_release
(
struct
inode
*
inode
,
struct
file
*
filp
)
static
int
cache_release
(
struct
inode
*
inode
,
struct
file
*
filp
,
struct
cache_detail
*
cd
)
{
struct
cache_reader
*
rp
=
filp
->
private_data
;
struct
cache_detail
*
cd
=
PDE
(
inode
)
->
data
;
if
(
rp
)
{
spin_lock
(
&
queue_lock
);
...
...
@@ -908,18 +884,6 @@ cache_release(struct inode *inode, struct file *filp)
static
const
struct
file_operations
cache_file_operations
=
{
.
owner
=
THIS_MODULE
,
.
llseek
=
no_llseek
,
.
read
=
cache_read
,
.
write
=
cache_write
,
.
poll
=
cache_poll
,
.
ioctl
=
cache_ioctl
,
/* for FIONREAD */
.
open
=
cache_open
,
.
release
=
cache_release
,
};
static
void
queue_loose
(
struct
cache_detail
*
detail
,
struct
cache_head
*
ch
)
{
struct
cache_queue
*
cq
;
...
...
@@ -1020,15 +984,21 @@ static void warn_no_listener(struct cache_detail *detail)
if
(
detail
->
last_warn
!=
detail
->
last_close
)
{
detail
->
last_warn
=
detail
->
last_close
;
if
(
detail
->
warn_no_listener
)
detail
->
warn_no_listener
(
detail
);
detail
->
warn_no_listener
(
detail
,
detail
->
last_close
!=
0
);
}
}
/*
* register an upcall request to user-space.
* register an upcall request to user-space and queue it up for read() by the
* upcall daemon.
*
* Each request is at most one page long.
*/
static
int
cache_make_upcall
(
struct
cache_detail
*
detail
,
struct
cache_head
*
h
)
int
sunrpc_cache_pipe_upcall
(
struct
cache_detail
*
detail
,
struct
cache_head
*
h
,
void
(
*
cache_request
)(
struct
cache_detail
*
,
struct
cache_head
*
,
char
**
,
int
*
))
{
char
*
buf
;
...
...
@@ -1036,9 +1006,6 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h)
char
*
bp
;
int
len
;
if
(
detail
->
cache_request
==
NULL
)
return
-
EINVAL
;
if
(
atomic_read
(
&
detail
->
readers
)
==
0
&&
detail
->
last_close
<
get_seconds
()
-
30
)
{
warn_no_listener
(
detail
);
...
...
@@ -1057,7 +1024,7 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h)
bp
=
buf
;
len
=
PAGE_SIZE
;
detail
->
cache_request
(
detail
,
h
,
&
bp
,
&
len
);
cache_request
(
detail
,
h
,
&
bp
,
&
len
);
if
(
len
<
0
)
{
kfree
(
buf
);
...
...
@@ -1075,6 +1042,7 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h)
wake_up
(
&
queue_wait
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
sunrpc_cache_pipe_upcall
);
/*
* parse a message from user-space and pass it
...
...
@@ -1242,10 +1210,10 @@ static const struct seq_operations cache_content_op = {
.
show
=
c_show
,
};
static
int
content_open
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
content_open
(
struct
inode
*
inode
,
struct
file
*
file
,
struct
cache_detail
*
cd
)
{
struct
handle
*
han
;
struct
cache_detail
*
cd
=
PDE
(
inode
)
->
data
;
han
=
__seq_open_private
(
file
,
&
cache_content_op
,
sizeof
(
*
han
));
if
(
han
==
NULL
)
...
...
@@ -1255,17 +1223,10 @@ static int content_open(struct inode *inode, struct file *file)
return
0
;
}
static
const
struct
file_operations
content_file_operations
=
{
.
open
=
content_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
static
ssize_t
read_flush
(
struct
file
*
file
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
size_t
count
,
loff_t
*
ppos
,
struct
cache_detail
*
cd
)
{
struct
cache_detail
*
cd
=
PDE
(
file
->
f_path
.
dentry
->
d_inode
)
->
data
;
char
tbuf
[
20
];
unsigned
long
p
=
*
ppos
;
size_t
len
;
...
...
@@ -1283,10 +1244,10 @@ static ssize_t read_flush(struct file *file, char __user *buf,
return
len
;
}
static
ssize_t
write_flush
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
write_flush
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
,
struct
cache_detail
*
cd
)
{
struct
cache_detail
*
cd
=
PDE
(
file
->
f_path
.
dentry
->
d_inode
)
->
data
;
char
tbuf
[
20
];
char
*
ep
;
long
flushtime
;
...
...
@@ -1307,8 +1268,299 @@ static ssize_t write_flush(struct file * file, const char __user * buf,
return
count
;
}
static
const
struct
file_operations
cache_flush_operations
=
{
static
ssize_t
cache_read_procfs
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
cache_detail
*
cd
=
PDE
(
filp
->
f_path
.
dentry
->
d_inode
)
->
data
;
return
cache_read
(
filp
,
buf
,
count
,
ppos
,
cd
);
}
static
ssize_t
cache_write_procfs
(
struct
file
*
filp
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
cache_detail
*
cd
=
PDE
(
filp
->
f_path
.
dentry
->
d_inode
)
->
data
;
return
cache_write
(
filp
,
buf
,
count
,
ppos
,
cd
);
}
static
unsigned
int
cache_poll_procfs
(
struct
file
*
filp
,
poll_table
*
wait
)
{
struct
cache_detail
*
cd
=
PDE
(
filp
->
f_path
.
dentry
->
d_inode
)
->
data
;
return
cache_poll
(
filp
,
wait
,
cd
);
}
static
int
cache_ioctl_procfs
(
struct
inode
*
inode
,
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
cache_detail
*
cd
=
PDE
(
inode
)
->
data
;
return
cache_ioctl
(
inode
,
filp
,
cmd
,
arg
,
cd
);
}
static
int
cache_open_procfs
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
struct
cache_detail
*
cd
=
PDE
(
inode
)
->
data
;
return
cache_open
(
inode
,
filp
,
cd
);
}
static
int
cache_release_procfs
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
struct
cache_detail
*
cd
=
PDE
(
inode
)
->
data
;
return
cache_release
(
inode
,
filp
,
cd
);
}
static
const
struct
file_operations
cache_file_operations_procfs
=
{
.
owner
=
THIS_MODULE
,
.
llseek
=
no_llseek
,
.
read
=
cache_read_procfs
,
.
write
=
cache_write_procfs
,
.
poll
=
cache_poll_procfs
,
.
ioctl
=
cache_ioctl_procfs
,
/* for FIONREAD */
.
open
=
cache_open_procfs
,
.
release
=
cache_release_procfs
,
};
static
int
content_open_procfs
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
struct
cache_detail
*
cd
=
PDE
(
inode
)
->
data
;
return
content_open
(
inode
,
filp
,
cd
);
}
static
const
struct
file_operations
content_file_operations_procfs
=
{
.
open
=
content_open_procfs
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
static
ssize_t
read_flush_procfs
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
cache_detail
*
cd
=
PDE
(
filp
->
f_path
.
dentry
->
d_inode
)
->
data
;
return
read_flush
(
filp
,
buf
,
count
,
ppos
,
cd
);
}
static
ssize_t
write_flush_procfs
(
struct
file
*
filp
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
cache_detail
*
cd
=
PDE
(
filp
->
f_path
.
dentry
->
d_inode
)
->
data
;
return
write_flush
(
filp
,
buf
,
count
,
ppos
,
cd
);
}
static
const
struct
file_operations
cache_flush_operations_procfs
=
{
.
open
=
nonseekable_open
,
.
read
=
read_flush_procfs
,
.
write
=
write_flush_procfs
,
};
static
void
remove_cache_proc_entries
(
struct
cache_detail
*
cd
)
{
if
(
cd
->
u
.
procfs
.
proc_ent
==
NULL
)
return
;
if
(
cd
->
u
.
procfs
.
flush_ent
)
remove_proc_entry
(
"flush"
,
cd
->
u
.
procfs
.
proc_ent
);
if
(
cd
->
u
.
procfs
.
channel_ent
)
remove_proc_entry
(
"channel"
,
cd
->
u
.
procfs
.
proc_ent
);
if
(
cd
->
u
.
procfs
.
content_ent
)
remove_proc_entry
(
"content"
,
cd
->
u
.
procfs
.
proc_ent
);
cd
->
u
.
procfs
.
proc_ent
=
NULL
;
remove_proc_entry
(
cd
->
name
,
proc_net_rpc
);
}
#ifdef CONFIG_PROC_FS
static
int
create_cache_proc_entries
(
struct
cache_detail
*
cd
)
{
struct
proc_dir_entry
*
p
;
cd
->
u
.
procfs
.
proc_ent
=
proc_mkdir
(
cd
->
name
,
proc_net_rpc
);
if
(
cd
->
u
.
procfs
.
proc_ent
==
NULL
)
goto
out_nomem
;
cd
->
u
.
procfs
.
channel_ent
=
NULL
;
cd
->
u
.
procfs
.
content_ent
=
NULL
;
p
=
proc_create_data
(
"flush"
,
S_IFREG
|
S_IRUSR
|
S_IWUSR
,
cd
->
u
.
procfs
.
proc_ent
,
&
cache_flush_operations_procfs
,
cd
);
cd
->
u
.
procfs
.
flush_ent
=
p
;
if
(
p
==
NULL
)
goto
out_nomem
;
if
(
cd
->
cache_upcall
||
cd
->
cache_parse
)
{
p
=
proc_create_data
(
"channel"
,
S_IFREG
|
S_IRUSR
|
S_IWUSR
,
cd
->
u
.
procfs
.
proc_ent
,
&
cache_file_operations_procfs
,
cd
);
cd
->
u
.
procfs
.
channel_ent
=
p
;
if
(
p
==
NULL
)
goto
out_nomem
;
}
if
(
cd
->
cache_show
)
{
p
=
proc_create_data
(
"content"
,
S_IFREG
|
S_IRUSR
|
S_IWUSR
,
cd
->
u
.
procfs
.
proc_ent
,
&
content_file_operations_procfs
,
cd
);
cd
->
u
.
procfs
.
content_ent
=
p
;
if
(
p
==
NULL
)
goto
out_nomem
;
}
return
0
;
out_nomem:
remove_cache_proc_entries
(
cd
);
return
-
ENOMEM
;
}
#else
/* CONFIG_PROC_FS */
static
int
create_cache_proc_entries
(
struct
cache_detail
*
cd
)
{
return
0
;
}
#endif
int
cache_register
(
struct
cache_detail
*
cd
)
{
int
ret
;
sunrpc_init_cache_detail
(
cd
);
ret
=
create_cache_proc_entries
(
cd
);
if
(
ret
)
sunrpc_destroy_cache_detail
(
cd
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
cache_register
);
void
cache_unregister
(
struct
cache_detail
*
cd
)
{
remove_cache_proc_entries
(
cd
);
sunrpc_destroy_cache_detail
(
cd
);
}
EXPORT_SYMBOL_GPL
(
cache_unregister
);
static
ssize_t
cache_read_pipefs
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
cache_detail
*
cd
=
RPC_I
(
filp
->
f_path
.
dentry
->
d_inode
)
->
private
;
return
cache_read
(
filp
,
buf
,
count
,
ppos
,
cd
);
}
static
ssize_t
cache_write_pipefs
(
struct
file
*
filp
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
cache_detail
*
cd
=
RPC_I
(
filp
->
f_path
.
dentry
->
d_inode
)
->
private
;
return
cache_write
(
filp
,
buf
,
count
,
ppos
,
cd
);
}
static
unsigned
int
cache_poll_pipefs
(
struct
file
*
filp
,
poll_table
*
wait
)
{
struct
cache_detail
*
cd
=
RPC_I
(
filp
->
f_path
.
dentry
->
d_inode
)
->
private
;
return
cache_poll
(
filp
,
wait
,
cd
);
}
static
int
cache_ioctl_pipefs
(
struct
inode
*
inode
,
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
cache_detail
*
cd
=
RPC_I
(
inode
)
->
private
;
return
cache_ioctl
(
inode
,
filp
,
cmd
,
arg
,
cd
);
}
static
int
cache_open_pipefs
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
struct
cache_detail
*
cd
=
RPC_I
(
inode
)
->
private
;
return
cache_open
(
inode
,
filp
,
cd
);
}
static
int
cache_release_pipefs
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
struct
cache_detail
*
cd
=
RPC_I
(
inode
)
->
private
;
return
cache_release
(
inode
,
filp
,
cd
);
}
const
struct
file_operations
cache_file_operations_pipefs
=
{
.
owner
=
THIS_MODULE
,
.
llseek
=
no_llseek
,
.
read
=
cache_read_pipefs
,
.
write
=
cache_write_pipefs
,
.
poll
=
cache_poll_pipefs
,
.
ioctl
=
cache_ioctl_pipefs
,
/* for FIONREAD */
.
open
=
cache_open_pipefs
,
.
release
=
cache_release_pipefs
,
};
static
int
content_open_pipefs
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
struct
cache_detail
*
cd
=
RPC_I
(
inode
)
->
private
;
return
content_open
(
inode
,
filp
,
cd
);
}
const
struct
file_operations
content_file_operations_pipefs
=
{
.
open
=
content_open_pipefs
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
static
ssize_t
read_flush_pipefs
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
cache_detail
*
cd
=
RPC_I
(
filp
->
f_path
.
dentry
->
d_inode
)
->
private
;
return
read_flush
(
filp
,
buf
,
count
,
ppos
,
cd
);
}
static
ssize_t
write_flush_pipefs
(
struct
file
*
filp
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
cache_detail
*
cd
=
RPC_I
(
filp
->
f_path
.
dentry
->
d_inode
)
->
private
;
return
write_flush
(
filp
,
buf
,
count
,
ppos
,
cd
);
}
const
struct
file_operations
cache_flush_operations_pipefs
=
{
.
open
=
nonseekable_open
,
.
read
=
read_flush
,
.
write
=
write_flush
,
.
read
=
read_flush
_pipefs
,
.
write
=
write_flush
_pipefs
,
};
int
sunrpc_cache_register_pipefs
(
struct
dentry
*
parent
,
const
char
*
name
,
mode_t
umode
,
struct
cache_detail
*
cd
)
{
struct
qstr
q
;
struct
dentry
*
dir
;
int
ret
=
0
;
sunrpc_init_cache_detail
(
cd
);
q
.
name
=
name
;
q
.
len
=
strlen
(
name
);
q
.
hash
=
full_name_hash
(
q
.
name
,
q
.
len
);
dir
=
rpc_create_cache_dir
(
parent
,
&
q
,
umode
,
cd
);
if
(
!
IS_ERR
(
dir
))
cd
->
u
.
pipefs
.
dir
=
dir
;
else
{
sunrpc_destroy_cache_detail
(
cd
);
ret
=
PTR_ERR
(
dir
);
}
return
ret
;
}
EXPORT_SYMBOL_GPL
(
sunrpc_cache_register_pipefs
);
void
sunrpc_cache_unregister_pipefs
(
struct
cache_detail
*
cd
)
{
rpc_remove_cache_dir
(
cd
->
u
.
pipefs
.
dir
);
cd
->
u
.
pipefs
.
dir
=
NULL
;
sunrpc_destroy_cache_detail
(
cd
);
}
EXPORT_SYMBOL_GPL
(
sunrpc_cache_unregister_pipefs
);
net/sunrpc/clnt.c
View file @
f884dcae
...
...
@@ -27,6 +27,8 @@
#include <linux/types.h>
#include <linux/kallsyms.h>
#include <linux/mm.h>
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/slab.h>
#include <linux/utsname.h>
#include <linux/workqueue.h>
...
...
@@ -97,33 +99,49 @@ static int
rpc_setup_pipedir
(
struct
rpc_clnt
*
clnt
,
char
*
dir_name
)
{
static
uint32_t
clntid
;
struct
nameidata
nd
;
struct
path
path
;
char
name
[
15
];
struct
qstr
q
=
{
.
name
=
name
,
};
int
error
;
clnt
->
cl_
vfs
mnt
=
ERR_PTR
(
-
ENOENT
);
clnt
->
cl_dentry
=
ERR_PTR
(
-
ENOENT
);
clnt
->
cl_
path
.
mnt
=
ERR_PTR
(
-
ENOENT
);
clnt
->
cl_
path
.
dentry
=
ERR_PTR
(
-
ENOENT
);
if
(
dir_name
==
NULL
)
return
0
;
clnt
->
cl_vfsmnt
=
rpc_get_mount
();
if
(
IS_ERR
(
clnt
->
cl_vfsmnt
))
return
PTR_ERR
(
clnt
->
cl_vfsmnt
);
path
.
mnt
=
rpc_get_mount
();
if
(
IS_ERR
(
path
.
mnt
))
return
PTR_ERR
(
path
.
mnt
);
error
=
vfs_path_lookup
(
path
.
mnt
->
mnt_root
,
path
.
mnt
,
dir_name
,
0
,
&
nd
);
if
(
error
)
goto
err
;
for
(;;)
{
snprintf
(
clnt
->
cl_pathname
,
sizeof
(
clnt
->
cl_pathname
),
"%s/clnt%x"
,
dir_name
,
(
unsigned
int
)
clntid
++
);
clnt
->
cl_pathname
[
sizeof
(
clnt
->
cl_pathname
)
-
1
]
=
'\0'
;
clnt
->
cl_dentry
=
rpc_mkdir
(
clnt
->
cl_pathname
,
clnt
);
if
(
!
IS_ERR
(
clnt
->
cl_dentry
))
return
0
;
error
=
PTR_ERR
(
clnt
->
cl_dentry
);
q
.
len
=
snprintf
(
name
,
sizeof
(
name
),
"clnt%x"
,
(
unsigned
int
)
clntid
++
);
name
[
sizeof
(
name
)
-
1
]
=
'\0'
;
q
.
hash
=
full_name_hash
(
q
.
name
,
q
.
len
);
path
.
dentry
=
rpc_create_client_dir
(
nd
.
path
.
dentry
,
&
q
,
clnt
);
if
(
!
IS_ERR
(
path
.
dentry
))
break
;
error
=
PTR_ERR
(
path
.
dentry
);
if
(
error
!=
-
EEXIST
)
{
printk
(
KERN_INFO
"RPC: Couldn't create pipefs entry
%s, error %d
\n
"
,
clnt
->
cl_pathname
,
error
);
rpc_put_mount
(
);
return
error
;
printk
(
KERN_INFO
"RPC: Couldn't create pipefs entry
"
" %s/%s, error %d
\n
"
,
dir_name
,
name
,
error
);
goto
err_path_put
;
}
}
path_put
(
&
nd
.
path
);
clnt
->
cl_path
=
path
;
return
0
;
err_path_put:
path_put
(
&
nd
.
path
);
err:
rpc_put_mount
();
return
error
;
}
static
struct
rpc_clnt
*
rpc_new_client
(
const
struct
rpc_create_args
*
args
,
struct
rpc_xprt
*
xprt
)
...
...
@@ -231,8 +249,8 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
return
clnt
;
out_no_auth:
if
(
!
IS_ERR
(
clnt
->
cl_dentry
))
{
rpc_r
mdir
(
clnt
->
cl_
dentry
);
if
(
!
IS_ERR
(
clnt
->
cl_
path
.
dentry
))
{
rpc_r
emove_client_dir
(
clnt
->
cl_path
.
dentry
);
rpc_put_mount
();
}
out_no_path:
...
...
@@ -423,8 +441,8 @@ rpc_free_client(struct kref *kref)
dprintk
(
"RPC: destroying %s client for %s
\n
"
,
clnt
->
cl_protname
,
clnt
->
cl_server
);
if
(
!
IS_ERR
(
clnt
->
cl_dentry
))
{
rpc_r
mdir
(
clnt
->
cl_
dentry
);
if
(
!
IS_ERR
(
clnt
->
cl_
path
.
dentry
))
{
rpc_r
emove_client_dir
(
clnt
->
cl_path
.
dentry
);
rpc_put_mount
();
}
if
(
clnt
->
cl_parent
!=
clnt
)
{
...
...
net/sunrpc/rpc_pipe.c
View file @
f884dcae
...
...
@@ -26,6 +26,7 @@
#include <linux/sunrpc/clnt.h>
#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
#include <linux/sunrpc/cache.h>
static
struct
vfsmount
*
rpc_mount
__read_mostly
;
static
int
rpc_mount_count
;
...
...
@@ -125,7 +126,7 @@ static void
rpc_close_pipes
(
struct
inode
*
inode
)
{
struct
rpc_inode
*
rpci
=
RPC_I
(
inode
);
struct
rpc_pipe_ops
*
ops
;
const
struct
rpc_pipe_ops
*
ops
;
int
need_release
;
mutex_lock
(
&
inode
->
i_mutex
);
...
...
@@ -397,67 +398,13 @@ static const struct file_operations rpc_info_operations = {
};
/*
* We have a single directory with 1 node in it.
*/
enum
{
RPCAUTH_Root
=
1
,
RPCAUTH_lockd
,
RPCAUTH_mount
,
RPCAUTH_nfs
,
RPCAUTH_portmap
,
RPCAUTH_statd
,
RPCAUTH_nfsd4_cb
,
RPCAUTH_RootEOF
};
/*
* Description of fs contents.
*/
struct
rpc_filelist
{
char
*
name
;
c
onst
c
har
*
name
;
const
struct
file_operations
*
i_fop
;
int
mode
;
};
static
struct
rpc_filelist
files
[]
=
{
[
RPCAUTH_lockd
]
=
{
.
name
=
"lockd"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_mount
]
=
{
.
name
=
"mount"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_nfs
]
=
{
.
name
=
"nfs"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_portmap
]
=
{
.
name
=
"portmap"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_statd
]
=
{
.
name
=
"statd"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_nfsd4_cb
]
=
{
.
name
=
"nfsd4_cb"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
};
enum
{
RPCAUTH_info
=
2
,
RPCAUTH_EOF
};
static
struct
rpc_filelist
authfiles
[]
=
{
[
RPCAUTH_info
]
=
{
.
name
=
"info"
,
.
i_fop
=
&
rpc_info_operations
,
.
mode
=
S_IFREG
|
S_IRUSR
,
},
umode_t
mode
;
};
struct
vfsmount
*
rpc_get_mount
(
void
)
...
...
@@ -484,39 +431,8 @@ static const struct dentry_operations rpc_dentry_operations = {
.
d_delete
=
rpc_delete_dentry
,
};
static
int
rpc_lookup_parent
(
char
*
path
,
struct
nameidata
*
nd
)
{
struct
vfsmount
*
mnt
;
if
(
path
[
0
]
==
'\0'
)
return
-
ENOENT
;
mnt
=
rpc_get_mount
();
if
(
IS_ERR
(
mnt
))
{
printk
(
KERN_WARNING
"%s: %s failed to mount "
"pseudofilesystem
\n
"
,
__FILE__
,
__func__
);
return
PTR_ERR
(
mnt
);
}
if
(
vfs_path_lookup
(
mnt
->
mnt_root
,
mnt
,
path
,
LOOKUP_PARENT
,
nd
))
{
printk
(
KERN_WARNING
"%s: %s failed to find path %s
\n
"
,
__FILE__
,
__func__
,
path
);
rpc_put_mount
();
return
-
ENOENT
;
}
return
0
;
}
static
void
rpc_release_path
(
struct
nameidata
*
nd
)
{
path_put
(
&
nd
->
path
);
rpc_put_mount
();
}
static
struct
inode
*
rpc_get_inode
(
struct
super_block
*
sb
,
in
t
mode
)
rpc_get_inode
(
struct
super_block
*
sb
,
umode_
t
mode
)
{
struct
inode
*
inode
=
new_inode
(
sb
);
if
(
!
inode
)
...
...
@@ -534,212 +450,274 @@ rpc_get_inode(struct super_block *sb, int mode)
return
inode
;
}
/*
* FIXME: This probably has races.
*/
static
void
rpc_depopulate
(
struct
dentry
*
parent
,
unsigned
long
start
,
unsigned
long
eof
)
static
int
__rpc_create_common
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
const
struct
file_operations
*
i_fop
,
void
*
private
)
{
struct
inode
*
dir
=
parent
->
d_inode
;
struct
list_head
*
pos
,
*
next
;
struct
dentry
*
dentry
,
*
dvec
[
10
];
int
n
=
0
;
struct
inode
*
inode
;
mutex_lock_nested
(
&
dir
->
i_mutex
,
I_MUTEX_CHILD
);
repeat:
spin_lock
(
&
dcache_lock
);
list_for_each_safe
(
pos
,
next
,
&
parent
->
d_subdirs
)
{
dentry
=
list_entry
(
pos
,
struct
dentry
,
d_u
.
d_child
);
if
(
!
dentry
->
d_inode
||
dentry
->
d_inode
->
i_ino
<
start
||
dentry
->
d_inode
->
i_ino
>=
eof
)
continue
;
spin_lock
(
&
dentry
->
d_lock
);
if
(
!
d_unhashed
(
dentry
))
{
dget_locked
(
dentry
);
__d_drop
(
dentry
);
spin_unlock
(
&
dentry
->
d_lock
);
dvec
[
n
++
]
=
dentry
;
if
(
n
==
ARRAY_SIZE
(
dvec
))
break
;
}
else
spin_unlock
(
&
dentry
->
d_lock
);
}
spin_unlock
(
&
dcache_lock
);
if
(
n
)
{
do
{
dentry
=
dvec
[
--
n
];
if
(
S_ISREG
(
dentry
->
d_inode
->
i_mode
))
simple_unlink
(
dir
,
dentry
);
else
if
(
S_ISDIR
(
dentry
->
d_inode
->
i_mode
))
simple_rmdir
(
dir
,
dentry
);
d_delete
(
dentry
);
dput
(
dentry
);
}
while
(
n
);
goto
repeat
;
}
mutex_unlock
(
&
dir
->
i_mutex
);
BUG_ON
(
!
d_unhashed
(
dentry
));
inode
=
rpc_get_inode
(
dir
->
i_sb
,
mode
);
if
(
!
inode
)
goto
out_err
;
inode
->
i_ino
=
iunique
(
dir
->
i_sb
,
100
);
if
(
i_fop
)
inode
->
i_fop
=
i_fop
;
if
(
private
)
rpc_inode_setowner
(
inode
,
private
);
d_add
(
dentry
,
inode
);
return
0
;
out_err:
printk
(
KERN_WARNING
"%s: %s failed to allocate inode for dentry %s
\n
"
,
__FILE__
,
__func__
,
dentry
->
d_name
.
name
);
dput
(
dentry
);
return
-
ENOMEM
;
}
static
int
rpc_populate
(
struct
dentry
*
parent
,
struct
rpc_filelist
*
files
,
int
start
,
int
eof
)
static
int
__rpc_create
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
const
struct
file_operations
*
i_fop
,
void
*
private
)
{
struct
inode
*
inode
,
*
dir
=
parent
->
d_inode
;
void
*
private
=
RPC_I
(
dir
)
->
private
;
struct
dentry
*
dentry
;
int
mode
,
i
;
int
err
;
mutex_lock
(
&
dir
->
i_mutex
);
for
(
i
=
start
;
i
<
eof
;
i
++
)
{
dentry
=
d_alloc_name
(
parent
,
files
[
i
].
name
);
if
(
!
dentry
)
goto
out_bad
;
dentry
->
d_op
=
&
rpc_dentry_operations
;
mode
=
files
[
i
].
mode
;
inode
=
rpc_get_inode
(
dir
->
i_sb
,
mode
);
if
(
!
inode
)
{
dput
(
dentry
);
goto
out_bad
;
}
inode
->
i_ino
=
i
;
if
(
files
[
i
].
i_fop
)
inode
->
i_fop
=
files
[
i
].
i_fop
;
if
(
private
)
rpc_inode_setowner
(
inode
,
private
);
if
(
S_ISDIR
(
mode
))
inc_nlink
(
dir
);
d_add
(
dentry
,
inode
);
fsnotify_create
(
dir
,
dentry
);
}
mutex_unlock
(
&
dir
->
i_mutex
);
err
=
__rpc_create_common
(
dir
,
dentry
,
S_IFREG
|
mode
,
i_fop
,
private
);
if
(
err
)
return
err
;
fsnotify_create
(
dir
,
dentry
);
return
0
;
out_bad:
mutex_unlock
(
&
dir
->
i_mutex
);
printk
(
KERN_WARNING
"%s: %s failed to populate directory %s
\n
"
,
__FILE__
,
__func__
,
parent
->
d_name
.
name
);
return
-
ENOMEM
;
}
static
int
__rpc_mkdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
static
int
__rpc_mkdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
const
struct
file_operations
*
i_fop
,
void
*
private
)
{
struct
inode
*
inode
;
int
err
;
inode
=
rpc_get_inode
(
dir
->
i_sb
,
S_IFDIR
|
S_IRUGO
|
S_IXUGO
);
if
(
!
inode
)
goto
out_err
;
inode
->
i_ino
=
iunique
(
dir
->
i_sb
,
100
);
d_instantiate
(
dentry
,
inode
);
err
=
__rpc_create_common
(
dir
,
dentry
,
S_IFDIR
|
mode
,
i_fop
,
private
);
if
(
err
)
return
err
;
inc_nlink
(
dir
);
fsnotify_mkdir
(
dir
,
dentry
);
return
0
;
out_err:
printk
(
KERN_WARNING
"%s: %s failed to allocate inode for dentry %s
\n
"
,
__FILE__
,
__func__
,
dentry
->
d_name
.
name
);
return
-
ENOMEM
;
}
static
int
__rpc_rmdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
static
int
__rpc_mkpipe
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
umode_t
mode
,
const
struct
file_operations
*
i_fop
,
void
*
private
,
const
struct
rpc_pipe_ops
*
ops
,
int
flags
)
{
int
error
;
error
=
simple_rmdir
(
dir
,
dentry
);
if
(
!
error
)
d_delete
(
dentry
);
return
error
;
struct
rpc_inode
*
rpci
;
int
err
;
err
=
__rpc_create_common
(
dir
,
dentry
,
S_IFIFO
|
mode
,
i_fop
,
private
);
if
(
err
)
return
err
;
rpci
=
RPC_I
(
dentry
->
d_inode
);
rpci
->
nkern_readwriters
=
1
;
rpci
->
private
=
private
;
rpci
->
flags
=
flags
;
rpci
->
ops
=
ops
;
fsnotify_create
(
dir
,
dentry
);
return
0
;
}
static
struct
dentry
*
rpc_lookup_create
(
struct
dentry
*
parent
,
const
char
*
name
,
int
len
,
int
exclusive
)
static
int
__rpc_rmdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
{
int
ret
;
dget
(
dentry
);
ret
=
simple_rmdir
(
dir
,
dentry
);
d_delete
(
dentry
);
dput
(
dentry
);
return
ret
;
}
static
int
__rpc_unlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
{
int
ret
;
dget
(
dentry
);
ret
=
simple_unlink
(
dir
,
dentry
);
d_delete
(
dentry
);
dput
(
dentry
);
return
ret
;
}
static
int
__rpc_rmpipe
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
rpc_inode
*
rpci
=
RPC_I
(
inode
);
rpci
->
nkern_readwriters
--
;
if
(
rpci
->
nkern_readwriters
!=
0
)
return
0
;
rpc_close_pipes
(
inode
);
return
__rpc_unlink
(
dir
,
dentry
);
}
static
struct
dentry
*
__rpc_lookup_create
(
struct
dentry
*
parent
,
struct
qstr
*
name
)
{
struct
inode
*
dir
=
parent
->
d_inode
;
struct
dentry
*
dentry
;
mutex_lock_nested
(
&
dir
->
i_mutex
,
I_MUTEX_PARENT
);
dentry
=
lookup_one_len
(
name
,
parent
,
len
);
if
(
IS_ERR
(
dentry
))
goto
out_err
;
dentry
=
d_lookup
(
parent
,
name
);
if
(
!
dentry
)
{
dentry
=
d_alloc
(
parent
,
name
);
if
(
!
dentry
)
{
dentry
=
ERR_PTR
(
-
ENOMEM
);
goto
out_err
;
}
}
if
(
!
dentry
->
d_inode
)
dentry
->
d_op
=
&
rpc_dentry_operations
;
else
if
(
exclusive
)
{
dput
(
dentry
);
dentry
=
ERR_PTR
(
-
EEXIST
);
goto
out_err
;
}
return
dentry
;
out_err:
mutex_unlock
(
&
dir
->
i_mutex
);
return
dentry
;
}
static
struct
dentry
*
rpc_lookup_negative
(
char
*
path
,
struct
nameidata
*
nd
)
static
struct
dentry
*
__rpc_lookup_create_exclusive
(
struct
dentry
*
parent
,
struct
qstr
*
name
)
{
struct
dentry
*
dentry
;
int
error
;
if
((
error
=
rpc_lookup_parent
(
path
,
nd
))
!=
0
)
return
ERR_PTR
(
error
);
dentry
=
rpc_lookup_create
(
nd
->
path
.
dentry
,
nd
->
last
.
name
,
nd
->
last
.
len
,
1
);
if
(
IS_ERR
(
dentry
))
rpc_release_path
(
nd
);
return
dentry
;
dentry
=
__rpc_lookup_create
(
parent
,
name
);
if
(
dentry
->
d_inode
==
NULL
)
return
dentry
;
dput
(
dentry
);
return
ERR_PTR
(
-
EEXIST
);
}
/**
* rpc_mkdir - Create a new directory in rpc_pipefs
* @path: path from the rpc_pipefs root to the new directory
* @rpc_client: rpc client to associate with this directory
*
* This creates a directory at the given @path associated with
* @rpc_clnt, which will contain a file named "info" with some basic
* information about the client, together with any "pipes" that may
* later be created using rpc_mkpipe().
/*
* FIXME: This probably has races.
*/
struct
dentry
*
rpc_mkdir
(
char
*
path
,
struct
rpc_clnt
*
rpc_client
)
static
void
__rpc_depopulate
(
struct
dentry
*
parent
,
const
struct
rpc_filelist
*
files
,
int
start
,
int
eof
)
{
struct
nameidata
nd
;
struct
inode
*
dir
=
parent
->
d_inode
;
struct
dentry
*
dentry
;
struct
inode
*
dir
;
struct
qstr
name
;
int
i
;
for
(
i
=
start
;
i
<
eof
;
i
++
)
{
name
.
name
=
files
[
i
].
name
;
name
.
len
=
strlen
(
files
[
i
].
name
);
name
.
hash
=
full_name_hash
(
name
.
name
,
name
.
len
);
dentry
=
d_lookup
(
parent
,
&
name
);
if
(
dentry
==
NULL
)
continue
;
if
(
dentry
->
d_inode
==
NULL
)
goto
next
;
switch
(
dentry
->
d_inode
->
i_mode
&
S_IFMT
)
{
default:
BUG
();
case
S_IFREG
:
__rpc_unlink
(
dir
,
dentry
);
break
;
case
S_IFDIR
:
__rpc_rmdir
(
dir
,
dentry
);
}
next:
dput
(
dentry
);
}
}
static
void
rpc_depopulate
(
struct
dentry
*
parent
,
const
struct
rpc_filelist
*
files
,
int
start
,
int
eof
)
{
struct
inode
*
dir
=
parent
->
d_inode
;
mutex_lock_nested
(
&
dir
->
i_mutex
,
I_MUTEX_CHILD
);
__rpc_depopulate
(
parent
,
files
,
start
,
eof
);
mutex_unlock
(
&
dir
->
i_mutex
);
}
static
int
rpc_populate
(
struct
dentry
*
parent
,
const
struct
rpc_filelist
*
files
,
int
start
,
int
eof
,
void
*
private
)
{
struct
inode
*
dir
=
parent
->
d_inode
;
struct
dentry
*
dentry
;
int
i
,
err
;
mutex_lock
(
&
dir
->
i_mutex
);
for
(
i
=
start
;
i
<
eof
;
i
++
)
{
struct
qstr
q
;
q
.
name
=
files
[
i
].
name
;
q
.
len
=
strlen
(
files
[
i
].
name
);
q
.
hash
=
full_name_hash
(
q
.
name
,
q
.
len
);
dentry
=
__rpc_lookup_create_exclusive
(
parent
,
&
q
);
err
=
PTR_ERR
(
dentry
);
if
(
IS_ERR
(
dentry
))
goto
out_bad
;
switch
(
files
[
i
].
mode
&
S_IFMT
)
{
default:
BUG
();
case
S_IFREG
:
err
=
__rpc_create
(
dir
,
dentry
,
files
[
i
].
mode
,
files
[
i
].
i_fop
,
private
);
break
;
case
S_IFDIR
:
err
=
__rpc_mkdir
(
dir
,
dentry
,
files
[
i
].
mode
,
NULL
,
private
);
}
if
(
err
!=
0
)
goto
out_bad
;
}
mutex_unlock
(
&
dir
->
i_mutex
);
return
0
;
out_bad:
__rpc_depopulate
(
parent
,
files
,
start
,
eof
);
mutex_unlock
(
&
dir
->
i_mutex
);
printk
(
KERN_WARNING
"%s: %s failed to populate directory %s
\n
"
,
__FILE__
,
__func__
,
parent
->
d_name
.
name
);
return
err
;
}
static
struct
dentry
*
rpc_mkdir_populate
(
struct
dentry
*
parent
,
struct
qstr
*
name
,
umode_t
mode
,
void
*
private
,
int
(
*
populate
)(
struct
dentry
*
,
void
*
),
void
*
args_populate
)
{
struct
dentry
*
dentry
;
struct
inode
*
dir
=
parent
->
d_inode
;
int
error
;
dentry
=
rpc_lookup_negative
(
path
,
&
nd
);
mutex_lock_nested
(
&
dir
->
i_mutex
,
I_MUTEX_PARENT
);
dentry
=
__rpc_lookup_create_exclusive
(
parent
,
name
);
if
(
IS_ERR
(
dentry
))
return
dentry
;
dir
=
nd
.
path
.
dentry
->
d_inode
;
if
((
error
=
__rpc_mkdir
(
dir
,
dentry
))
!=
0
)
goto
err_dput
;
RPC_I
(
dentry
->
d_inode
)
->
private
=
rpc_client
;
error
=
rpc_populate
(
dentry
,
authfiles
,
RPCAUTH_info
,
RPCAUTH_EOF
);
if
(
error
)
goto
err_depopulate
;
dget
(
dentry
);
goto
out
;
error
=
__rpc_mkdir
(
dir
,
dentry
,
mode
,
NULL
,
private
);
if
(
error
!=
0
)
goto
out_err
;
if
(
populate
!=
NULL
)
{
error
=
populate
(
dentry
,
args_populate
);
if
(
error
)
goto
err_rmdir
;
}
out:
mutex_unlock
(
&
dir
->
i_mutex
);
rpc_release_path
(
&
nd
);
return
dentry
;
err_depopulate:
rpc_depopulate
(
dentry
,
RPCAUTH_info
,
RPCAUTH_EOF
);
err_rmdir:
__rpc_rmdir
(
dir
,
dentry
);
err_dput:
dput
(
dentry
);
printk
(
KERN_WARNING
"%s: %s() failed to create directory %s (errno = %d)
\n
"
,
__FILE__
,
__func__
,
path
,
error
);
out_err:
dentry
=
ERR_PTR
(
error
);
goto
out
;
}
/**
* rpc_rmdir - Remove a directory created with rpc_mkdir()
* @dentry: directory to remove
*/
int
rpc_rmdir
(
struct
dentry
*
dentry
)
static
int
rpc_rmdir_depopulate
(
struct
dentry
*
dentry
,
void
(
*
depopulate
)(
struct
dentry
*
))
{
struct
dentry
*
parent
;
struct
inode
*
dir
;
...
...
@@ -748,9 +726,9 @@ rpc_rmdir(struct dentry *dentry)
parent
=
dget_parent
(
dentry
);
dir
=
parent
->
d_inode
;
mutex_lock_nested
(
&
dir
->
i_mutex
,
I_MUTEX_PARENT
);
rpc_depopulate
(
dentry
,
RPCAUTH_info
,
RPCAUTH_EOF
);
if
(
depopulate
!=
NULL
)
depopulate
(
dentry
);
error
=
__rpc_rmdir
(
dir
,
dentry
);
dput
(
dentry
);
mutex_unlock
(
&
dir
->
i_mutex
);
dput
(
parent
);
return
error
;
...
...
@@ -776,50 +754,54 @@ rpc_rmdir(struct dentry *dentry)
* The @private argument passed here will be available to all these methods
* from the file pointer, via RPC_I(file->f_dentry->d_inode)->private.
*/
struct
dentry
*
rpc_mkpipe
(
struct
dentry
*
parent
,
const
char
*
name
,
void
*
private
,
struct
rpc_pipe_ops
*
ops
,
int
flags
)
struct
dentry
*
rpc_mkpipe
(
struct
dentry
*
parent
,
const
char
*
name
,
void
*
private
,
const
struct
rpc_pipe_ops
*
ops
,
int
flags
)
{
struct
dentry
*
dentry
;
struct
inode
*
dir
,
*
inode
;
struct
rpc_inode
*
rpci
;
struct
inode
*
dir
=
parent
->
d_inode
;
umode_t
umode
=
S_IFIFO
|
S_IRUSR
|
S_IWUSR
;
struct
qstr
q
;
int
err
;
dentry
=
rpc_lookup_create
(
parent
,
name
,
strlen
(
name
),
0
);
if
(
ops
->
upcall
==
NULL
)
umode
&=
~
S_IRUGO
;
if
(
ops
->
downcall
==
NULL
)
umode
&=
~
S_IWUGO
;
q
.
name
=
name
;
q
.
len
=
strlen
(
name
);
q
.
hash
=
full_name_hash
(
q
.
name
,
q
.
len
),
mutex_lock_nested
(
&
dir
->
i_mutex
,
I_MUTEX_PARENT
);
dentry
=
__rpc_lookup_create
(
parent
,
&
q
);
if
(
IS_ERR
(
dentry
))
return
dentry
;
dir
=
parent
->
d_inode
;
goto
out
;
if
(
dentry
->
d_inode
)
{
rpci
=
RPC_I
(
dentry
->
d_inode
);
struct
rpc_inode
*
rpci
=
RPC_I
(
dentry
->
d_inode
);
if
(
rpci
->
private
!=
private
||
rpci
->
ops
!=
ops
||
rpci
->
flags
!=
flags
)
{
dput
(
dentry
);
dentry
=
ERR_PTR
(
-
EBUSY
);
err
=
-
EBUSY
;
goto
out_err
;
}
rpci
->
nkern_readwriters
++
;
goto
out
;
}
inode
=
rpc_get_inode
(
dir
->
i_sb
,
S_IFIFO
|
S_IRUSR
|
S_IWUSR
);
if
(
!
inode
)
goto
err_dput
;
inode
->
i_ino
=
iunique
(
dir
->
i_sb
,
100
);
inode
->
i_fop
=
&
rpc_pipe_fops
;
d_instantiate
(
dentry
,
inode
);
rpci
=
RPC_I
(
inode
);
rpci
->
private
=
private
;
rpci
->
flags
=
flags
;
rpci
->
ops
=
ops
;
rpci
->
nkern_readwriters
=
1
;
fsnotify_create
(
dir
,
dentry
);
dget
(
dentry
);
err
=
__rpc_mkpipe
(
dir
,
dentry
,
umode
,
&
rpc_pipe_fops
,
private
,
ops
,
flags
);
if
(
err
)
goto
out_err
;
out:
mutex_unlock
(
&
dir
->
i_mutex
);
return
dentry
;
err_dput:
dput
(
dentry
);
dentry
=
ERR_PTR
(
-
ENOMEM
);
out_err:
dentry
=
ERR_PTR
(
err
);
printk
(
KERN_WARNING
"%s: %s() failed to create pipe %s/%s (errno = %d)
\n
"
,
__FILE__
,
__func__
,
parent
->
d_name
.
name
,
name
,
-
ENOMEM
);
err
);
goto
out
;
}
EXPORT_SYMBOL_GPL
(
rpc_mkpipe
);
...
...
@@ -842,19 +824,107 @@ rpc_unlink(struct dentry *dentry)
parent
=
dget_parent
(
dentry
);
dir
=
parent
->
d_inode
;
mutex_lock_nested
(
&
dir
->
i_mutex
,
I_MUTEX_PARENT
);
if
(
--
RPC_I
(
dentry
->
d_inode
)
->
nkern_readwriters
==
0
)
{
rpc_close_pipes
(
dentry
->
d_inode
);
error
=
simple_unlink
(
dir
,
dentry
);
if
(
!
error
)
d_delete
(
dentry
);
}
dput
(
dentry
);
error
=
__rpc_rmpipe
(
dir
,
dentry
);
mutex_unlock
(
&
dir
->
i_mutex
);
dput
(
parent
);
return
error
;
}
EXPORT_SYMBOL_GPL
(
rpc_unlink
);
enum
{
RPCAUTH_info
,
RPCAUTH_EOF
};
static
const
struct
rpc_filelist
authfiles
[]
=
{
[
RPCAUTH_info
]
=
{
.
name
=
"info"
,
.
i_fop
=
&
rpc_info_operations
,
.
mode
=
S_IFREG
|
S_IRUSR
,
},
};
static
int
rpc_clntdir_populate
(
struct
dentry
*
dentry
,
void
*
private
)
{
return
rpc_populate
(
dentry
,
authfiles
,
RPCAUTH_info
,
RPCAUTH_EOF
,
private
);
}
static
void
rpc_clntdir_depopulate
(
struct
dentry
*
dentry
)
{
rpc_depopulate
(
dentry
,
authfiles
,
RPCAUTH_info
,
RPCAUTH_EOF
);
}
/**
* rpc_create_client_dir - Create a new rpc_client directory in rpc_pipefs
* @path: path from the rpc_pipefs root to the new directory
* @rpc_client: rpc client to associate with this directory
*
* This creates a directory at the given @path associated with
* @rpc_clnt, which will contain a file named "info" with some basic
* information about the client, together with any "pipes" that may
* later be created using rpc_mkpipe().
*/
struct
dentry
*
rpc_create_client_dir
(
struct
dentry
*
dentry
,
struct
qstr
*
name
,
struct
rpc_clnt
*
rpc_client
)
{
return
rpc_mkdir_populate
(
dentry
,
name
,
S_IRUGO
|
S_IXUGO
,
NULL
,
rpc_clntdir_populate
,
rpc_client
);
}
/**
* rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir()
* @dentry: directory to remove
*/
int
rpc_remove_client_dir
(
struct
dentry
*
dentry
)
{
return
rpc_rmdir_depopulate
(
dentry
,
rpc_clntdir_depopulate
);
}
static
const
struct
rpc_filelist
cache_pipefs_files
[
3
]
=
{
[
0
]
=
{
.
name
=
"channel"
,
.
i_fop
=
&
cache_file_operations_pipefs
,
.
mode
=
S_IFIFO
|
S_IRUSR
|
S_IWUSR
,
},
[
1
]
=
{
.
name
=
"content"
,
.
i_fop
=
&
content_file_operations_pipefs
,
.
mode
=
S_IFREG
|
S_IRUSR
,
},
[
2
]
=
{
.
name
=
"flush"
,
.
i_fop
=
&
cache_flush_operations_pipefs
,
.
mode
=
S_IFREG
|
S_IRUSR
|
S_IWUSR
,
},
};
static
int
rpc_cachedir_populate
(
struct
dentry
*
dentry
,
void
*
private
)
{
return
rpc_populate
(
dentry
,
cache_pipefs_files
,
0
,
3
,
private
);
}
static
void
rpc_cachedir_depopulate
(
struct
dentry
*
dentry
)
{
rpc_depopulate
(
dentry
,
cache_pipefs_files
,
0
,
3
);
}
struct
dentry
*
rpc_create_cache_dir
(
struct
dentry
*
parent
,
struct
qstr
*
name
,
mode_t
umode
,
struct
cache_detail
*
cd
)
{
return
rpc_mkdir_populate
(
parent
,
name
,
umode
,
NULL
,
rpc_cachedir_populate
,
cd
);
}
void
rpc_remove_cache_dir
(
struct
dentry
*
dentry
)
{
rpc_rmdir_depopulate
(
dentry
,
rpc_cachedir_depopulate
);
}
/*
* populate the filesystem
*/
...
...
@@ -866,6 +936,46 @@ static struct super_operations s_ops = {
#define RPCAUTH_GSSMAGIC 0x67596969
/*
* We have a single directory with 1 node in it.
*/
enum
{
RPCAUTH_lockd
,
RPCAUTH_mount
,
RPCAUTH_nfs
,
RPCAUTH_portmap
,
RPCAUTH_statd
,
RPCAUTH_nfsd4_cb
,
RPCAUTH_RootEOF
};
static
const
struct
rpc_filelist
files
[]
=
{
[
RPCAUTH_lockd
]
=
{
.
name
=
"lockd"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_mount
]
=
{
.
name
=
"mount"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_nfs
]
=
{
.
name
=
"nfs"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_portmap
]
=
{
.
name
=
"portmap"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_statd
]
=
{
.
name
=
"statd"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
[
RPCAUTH_nfsd4_cb
]
=
{
.
name
=
"nfsd4_cb"
,
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
},
};
static
int
rpc_fill_super
(
struct
super_block
*
sb
,
void
*
data
,
int
silent
)
{
...
...
@@ -886,7 +996,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
iput
(
inode
);
return
-
ENOMEM
;
}
if
(
rpc_populate
(
root
,
files
,
RPCAUTH_
Root
+
1
,
RPCAUTH_RootEOF
))
if
(
rpc_populate
(
root
,
files
,
RPCAUTH_
lockd
,
RPCAUTH_RootEOF
,
NULL
))
goto
out
;
sb
->
s_root
=
root
;
return
0
;
...
...
net/sunrpc/svcauth_unix.c
View file @
f884dcae
...
...
@@ -171,6 +171,11 @@ static void ip_map_request(struct cache_detail *cd,
(
*
bpp
)[
-
1
]
=
'\n'
;
}
static
int
ip_map_upcall
(
struct
cache_detail
*
cd
,
struct
cache_head
*
h
)
{
return
sunrpc_cache_pipe_upcall
(
cd
,
h
,
ip_map_request
);
}
static
struct
ip_map
*
ip_map_lookup
(
char
*
class
,
struct
in6_addr
*
addr
);
static
int
ip_map_update
(
struct
ip_map
*
ipm
,
struct
unix_domain
*
udom
,
time_t
expiry
);
...
...
@@ -289,7 +294,7 @@ struct cache_detail ip_map_cache = {
.
hash_table
=
ip_table
,
.
name
=
"auth.unix.ip"
,
.
cache_put
=
ip_map_put
,
.
cache_
request
=
ip_map_request
,
.
cache_
upcall
=
ip_map_upcall
,
.
cache_parse
=
ip_map_parse
,
.
cache_show
=
ip_map_show
,
.
match
=
ip_map_match
,
...
...
@@ -523,6 +528,11 @@ static void unix_gid_request(struct cache_detail *cd,
(
*
bpp
)[
-
1
]
=
'\n'
;
}
static
int
unix_gid_upcall
(
struct
cache_detail
*
cd
,
struct
cache_head
*
h
)
{
return
sunrpc_cache_pipe_upcall
(
cd
,
h
,
unix_gid_request
);
}
static
struct
unix_gid
*
unix_gid_lookup
(
uid_t
uid
);
extern
struct
cache_detail
unix_gid_cache
;
...
...
@@ -622,7 +632,7 @@ struct cache_detail unix_gid_cache = {
.
hash_table
=
gid_table
,
.
name
=
"auth.unix.gid"
,
.
cache_put
=
unix_gid_put
,
.
cache_
request
=
unix_gid_request
,
.
cache_
upcall
=
unix_gid_upcall
,
.
cache_parse
=
unix_gid_parse
,
.
cache_show
=
unix_gid_show
,
.
match
=
unix_gid_match
,
...
...
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