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
ba44b066
Commit
ba44b066
authored
May 20, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://nfsclient.bkbits.net/linux-2.5
into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents
a063b7fc
04d0f23c
Changes
26
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
706 additions
and
420 deletions
+706
-420
fs/nfs/direct.c
fs/nfs/direct.c
+162
-22
fs/nfs/file.c
fs/nfs/file.c
+10
-0
fs/nfs/inode.c
fs/nfs/inode.c
+10
-6
fs/nfs/nfs4state.c
fs/nfs/nfs4state.c
+2
-0
fs/nfs/read.c
fs/nfs/read.c
+23
-15
fs/nfs/write.c
fs/nfs/write.c
+19
-12
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+4
-0
include/linux/sunrpc/gss_api.h
include/linux/sunrpc/gss_api.h
+28
-42
include/linux/sunrpc/gss_asn1.h
include/linux/sunrpc/gss_asn1.h
+1
-2
include/linux/sunrpc/gss_krb5.h
include/linux/sunrpc/gss_krb5.h
+1
-1
include/linux/sunrpc/xprt.h
include/linux/sunrpc/xprt.h
+5
-5
net/sunrpc/auth_gss/Makefile
net/sunrpc/auth_gss/Makefile
+3
-3
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/auth_gss.c
+151
-106
net/sunrpc/auth_gss/gss_generic_token.c
net/sunrpc/auth_gss/gss_generic_token.c
+8
-7
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
+18
-13
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_krb5_mech.c
+20
-20
net/sunrpc/auth_gss/gss_krb5_seal.c
net/sunrpc/auth_gss/gss_krb5_seal.c
+9
-6
net/sunrpc/auth_gss/gss_krb5_seqnum.c
net/sunrpc/auth_gss/gss_krb5_seqnum.c
+1
-1
net/sunrpc/auth_gss/gss_krb5_unseal.c
net/sunrpc/auth_gss/gss_krb5_unseal.c
+6
-2
net/sunrpc/auth_gss/gss_mech_switch.c
net/sunrpc/auth_gss/gss_mech_switch.c
+126
-83
net/sunrpc/auth_gss/gss_pseudoflavors.c
net/sunrpc/auth_gss/gss_pseudoflavors.c
+11
-10
net/sunrpc/auth_gss/sunrpcgss_syms.c
net/sunrpc/auth_gss/sunrpcgss_syms.c
+10
-8
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/auth_gss/svcauth_gss.c
+16
-20
net/sunrpc/clnt.c
net/sunrpc/clnt.c
+1
-3
net/sunrpc/timer.c
net/sunrpc/timer.c
+1
-0
net/sunrpc/xprt.c
net/sunrpc/xprt.c
+60
-33
No files found.
fs/nfs/direct.c
View file @
ba44b066
...
...
@@ -32,6 +32,7 @@
* 18 Dec 2001 Initial implementation for 2.4 --cel
* 08 Jul 2002 Version for 2.4.19, with bug fixes --trondmy
* 08 Jun 2003 Port to 2.5 APIs --cel
* 31 Mar 2004 Handle direct I/O without VFS support --cel
*
*/
...
...
@@ -252,9 +253,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
{
const
unsigned
int
wsize
=
NFS_SERVER
(
inode
)
->
wsize
;
size_t
request
;
int
need_commit
;
int
tot_bytes
;
int
curpage
;
int
curpage
,
need_commit
,
result
,
tot_bytes
;
struct
nfs_writeverf
first_verf
;
struct
nfs_write_data
wdata
=
{
.
inode
=
inode
,
...
...
@@ -281,8 +280,6 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
wdata
.
args
.
pgbase
=
user_addr
&
~
PAGE_MASK
;
wdata
.
args
.
offset
=
file_offset
;
do
{
int
result
;
wdata
.
args
.
count
=
request
;
if
(
wdata
.
args
.
count
>
wsize
)
wdata
.
args
.
count
=
wsize
;
...
...
@@ -299,7 +296,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
if
(
result
<=
0
)
{
if
(
tot_bytes
>
0
)
break
;
return
resul
t
;
goto
ou
t
;
}
if
(
tot_bytes
==
0
)
...
...
@@ -324,8 +321,6 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
* Commit data written so far, even in the event of an error
*/
if
(
need_commit
)
{
int
result
;
wdata
.
args
.
count
=
tot_bytes
;
wdata
.
args
.
offset
=
file_offset
;
...
...
@@ -338,9 +333,12 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
VERF_SIZE
)
!=
0
)
goto
sync_retry
;
}
result
=
tot_bytes
;
out:
nfs_end_data_update_defer
(
inode
);
return
tot_bytes
;
return
result
;
sync_retry:
wdata
.
args
.
stable
=
NFS_FILE_SYNC
;
...
...
@@ -409,12 +407,6 @@ nfs_direct_write(struct inode *inode, struct file *file,
* file_offset: offset in file to begin the operation
* nr_segs: size of iovec array
*
* Usually a file system implements direct I/O by calling out to
* blockdev_direct_IO. The NFS client doesn't have a backing block
* device, so we do everything by hand instead.
*
* The inode's i_sem is no longer held by the VFS layer before it calls
* this function to do a write.
*/
ssize_t
nfs_direct_IO
(
int
rw
,
struct
kiocb
*
iocb
,
const
struct
iovec
*
iov
,
...
...
@@ -429,11 +421,7 @@ nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
* No support for async yet
*/
if
(
!
is_sync_kiocb
(
iocb
))
goto
out
;
result
=
nfs_revalidate_inode
(
NFS_SERVER
(
inode
),
inode
);
if
(
result
<
0
)
goto
out
;
return
result
;
switch
(
rw
)
{
case
READ
:
...
...
@@ -453,8 +441,160 @@ nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
default:
break
;
}
return
result
;
}
/**
* nfs_file_direct_read - file direct read operation for NFS files
* @iocb: target I/O control block
* @buf: user's buffer into which to read data
* count: number of bytes to read
* pos: byte offset in file where reading starts
*
* We use this function for direct reads instead of calling
* generic_file_aio_read() in order to avoid gfar's check to see if
* the request starts before the end of the file. For that check
* to work, we must generate a GETATTR before each direct read, and
* even then there is a window between the GETATTR and the subsequent
* READ where the file size could change. So our preference is simply
* to do all reads the application wants, and the server will take
* care of managing the end of file boundary.
*
* This function also eliminates unnecessarily updating the file's
* atime locally, as the NFS server sets the file's atime, and this
* client must read the updated atime from the server back into its
* cache.
*/
ssize_t
nfs_file_direct_read
(
struct
kiocb
*
iocb
,
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
ssize_t
retval
=
-
EINVAL
;
loff_t
*
ppos
=
&
iocb
->
ki_pos
;
struct
file
*
file
=
iocb
->
ki_filp
;
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
address_space
*
mapping
=
file
->
f_mapping
;
struct
inode
*
inode
=
mapping
->
host
;
struct
iovec
iov
=
{
.
iov_base
=
buf
,
.
iov_len
=
count
,
};
dprintk
(
"nfs: direct read(%s/%s, %lu@%lu)
\n
"
,
dentry
->
d_parent
->
d_name
.
name
,
dentry
->
d_name
.
name
,
(
unsigned
long
)
count
,
(
unsigned
long
)
pos
);
if
(
!
is_sync_kiocb
(
iocb
))
goto
out
;
if
(
count
<
0
)
goto
out
;
retval
=
-
EFAULT
;
if
(
!
access_ok
(
VERIFY_WRITE
,
iov
.
iov_base
,
iov
.
iov_len
))
goto
out
;
retval
=
0
;
if
(
!
count
)
goto
out
;
if
(
mapping
->
nrpages
)
{
retval
=
filemap_fdatawrite
(
mapping
);
if
(
retval
==
0
)
retval
=
filemap_fdatawait
(
mapping
);
if
(
retval
)
goto
out
;
}
retval
=
nfs_direct_read
(
inode
,
file
,
&
iov
,
pos
,
1
);
if
(
retval
>
0
)
*
ppos
=
pos
+
retval
;
out:
dprintk
(
"NFS: direct_IO result=%zd
\n
"
,
result
);
return
result
;
return
retval
;
}
/**
* nfs_file_direct_write - file direct write operation for NFS files
* @iocb: target I/O control block
* @buf: user's buffer from which to write data
* count: number of bytes to write
* pos: byte offset in file where writing starts
*
* We use this function for direct writes instead of calling
* generic_file_aio_write() in order to avoid taking the inode
* semaphore and updating the i_size. The NFS server will set
* the new i_size and this client must read the updated size
* back into its cache. We let the server do generic write
* parameter checking and report problems.
*
* We also avoid an unnecessary invocation of generic_osync_inode(),
* as it is fairly meaningless to sync the metadata of an NFS file.
*
* We eliminate local atime updates, see direct read above.
*
* We avoid unnecessary page cache invalidations for normal cached
* readers of this file.
*
* Note that O_APPEND is not supported for NFS direct writes, as there
* is no atomic O_APPEND write facility in the NFS protocol.
*/
ssize_t
nfs_file_direct_write
(
struct
kiocb
*
iocb
,
const
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
ssize_t
retval
=
-
EINVAL
;
loff_t
*
ppos
=
&
iocb
->
ki_pos
;
unsigned
long
limit
=
current
->
rlim
[
RLIMIT_FSIZE
].
rlim_cur
;
struct
file
*
file
=
iocb
->
ki_filp
;
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
address_space
*
mapping
=
file
->
f_mapping
;
struct
inode
*
inode
=
mapping
->
host
;
struct
iovec
iov
=
{
.
iov_base
=
(
void
__user
*
)
buf
,
.
iov_len
=
count
,
};
dfprintk
(
VFS
,
"nfs: direct write(%s/%s(%ld), %lu@%lu)
\n
"
,
dentry
->
d_parent
->
d_name
.
name
,
dentry
->
d_name
.
name
,
inode
->
i_ino
,
(
unsigned
long
)
count
,
(
unsigned
long
)
pos
);
if
(
!
is_sync_kiocb
(
iocb
))
goto
out
;
if
(
count
<
0
)
goto
out
;
if
(
pos
<
0
)
goto
out
;
retval
=
-
EFAULT
;
if
(
!
access_ok
(
VERIFY_READ
,
iov
.
iov_base
,
iov
.
iov_len
))
goto
out
;
if
(
file
->
f_error
)
{
retval
=
file
->
f_error
;
file
->
f_error
=
0
;
goto
out
;
}
retval
=
-
EFBIG
;
if
(
limit
!=
RLIM_INFINITY
)
{
if
(
pos
>=
limit
)
{
send_sig
(
SIGXFSZ
,
current
,
0
);
goto
out
;
}
if
(
count
>
limit
-
(
unsigned
long
)
pos
)
count
=
limit
-
(
unsigned
long
)
pos
;
}
retval
=
0
;
if
(
!
count
)
goto
out
;
if
(
mapping
->
nrpages
)
{
retval
=
filemap_fdatawrite
(
mapping
);
if
(
retval
==
0
)
retval
=
filemap_fdatawait
(
mapping
);
if
(
retval
)
goto
out
;
}
retval
=
nfs_direct_write
(
inode
,
file
,
&
iov
,
pos
,
1
);
if
(
mapping
->
nrpages
)
invalidate_inode_pages2
(
mapping
);
if
(
retval
>
0
)
*
ppos
=
pos
+
retval
;
out:
return
retval
;
}
fs/nfs/file.c
View file @
ba44b066
...
...
@@ -154,6 +154,11 @@ nfs_file_read(struct kiocb *iocb, char * buf, size_t count, loff_t pos)
struct
inode
*
inode
=
dentry
->
d_inode
;
ssize_t
result
;
#ifdef CONFIG_NFS_DIRECTIO
if
(
iocb
->
ki_filp
->
f_flags
&
O_DIRECT
)
return
nfs_file_direct_read
(
iocb
,
buf
,
count
,
pos
);
#endif
dfprintk
(
VFS
,
"nfs: read(%s/%s, %lu@%lu)
\n
"
,
dentry
->
d_parent
->
d_name
.
name
,
dentry
->
d_name
.
name
,
(
unsigned
long
)
count
,
(
unsigned
long
)
pos
);
...
...
@@ -268,6 +273,11 @@ nfs_file_write(struct kiocb *iocb, const char *buf, size_t count, loff_t pos)
struct
inode
*
inode
=
dentry
->
d_inode
;
ssize_t
result
;
#ifdef CONFIG_NFS_DIRECTIO
if
(
iocb
->
ki_filp
->
f_flags
&
O_DIRECT
)
return
nfs_file_direct_write
(
iocb
,
buf
,
count
,
pos
);
#endif
dfprintk
(
VFS
,
"nfs: write(%s/%s(%ld), %lu@%lu)
\n
"
,
dentry
->
d_parent
->
d_name
.
name
,
dentry
->
d_name
.
name
,
inode
->
i_ino
,
(
unsigned
long
)
count
,
(
unsigned
long
)
pos
);
...
...
fs/nfs/inode.c
View file @
ba44b066
...
...
@@ -237,7 +237,7 @@ nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *f
error
=
server
->
rpc_ops
->
getroot
(
server
,
rootfh
,
fsinfo
);
if
(
error
<
0
)
{
printk
(
KERN_NOTICE
"nfs_get_root: getattr error = %d
\n
"
,
-
error
);
dprintk
(
"nfs_get_root: getattr error = %d
\n
"
,
-
error
);
return
ERR_PTR
(
error
);
}
...
...
@@ -262,6 +262,7 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
struct
nfs_pathconf
pathinfo
=
{
.
fattr
=
&
fattr
,
};
int
no_root_error
=
0
;
/* We probably want something more informative here */
snprintf
(
sb
->
s_id
,
sizeof
(
sb
->
s_id
),
"%x:%x"
,
MAJOR
(
sb
->
s_dev
),
MINOR
(
sb
->
s_dev
));
...
...
@@ -272,12 +273,15 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
root_inode
=
nfs_get_root
(
sb
,
&
server
->
fh
,
&
fsinfo
);
/* Did getting the root inode fail? */
if
(
IS_ERR
(
root_inode
))
if
(
IS_ERR
(
root_inode
))
{
no_root_error
=
PTR_ERR
(
root_inode
);
goto
out_no_root
;
}
sb
->
s_root
=
d_alloc_root
(
root_inode
);
if
(
!
sb
->
s_root
)
if
(
!
sb
->
s_root
)
{
no_root_error
=
-
ENOMEM
;
goto
out_no_root
;
}
sb
->
s_root
->
d_op
=
server
->
rpc_ops
->
dentry_ops
;
/* Get some general file system info */
...
...
@@ -337,10 +341,10 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
return
0
;
/* Yargs. It didn't work out. */
out_no_root:
printk
(
"nfs_read_super: get root inode failed
\n
"
);
dprintk
(
"nfs_sb_init: get root inode failed: errno %d
\n
"
,
-
no_root_error
);
if
(
!
IS_ERR
(
root_inode
))
iput
(
root_inode
);
return
-
EINVAL
;
return
no_root_error
;
}
/*
...
...
fs/nfs/nfs4state.c
View file @
ba44b066
...
...
@@ -731,6 +731,8 @@ nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
int
status
=
0
;
list_for_each_entry
(
state
,
&
sp
->
so_states
,
open_states
)
{
if
(
state
->
state
==
0
)
continue
;
status
=
nfs4_open_reclaim
(
sp
,
state
);
if
(
status
>=
0
)
continue
;
...
...
fs/nfs/read.c
View file @
ba44b066
...
...
@@ -43,14 +43,12 @@ static mempool_t *nfs_rdata_mempool;
#define MIN_POOL_READ (32)
static
__inline__
struct
nfs_read_data
*
nfs_readdata_alloc
(
void
)
static
struct
nfs_read_data
*
nfs_readdata_alloc
(
void
)
{
struct
nfs_read_data
*
p
;
p
=
(
struct
nfs_read_data
*
)
mempool_alloc
(
nfs_rdata_mempool
,
SLAB_NOFS
);
if
(
p
)
{
if
(
p
)
memset
(
p
,
0
,
sizeof
(
*
p
));
INIT_LIST_HEAD
(
&
p
->
pages
);
}
return
p
;
}
...
...
@@ -99,10 +97,17 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
unsigned
int
rsize
=
NFS_SERVER
(
inode
)
->
rsize
;
unsigned
int
count
=
PAGE_CACHE_SIZE
;
int
result
;
struct
nfs_read_data
rdata
=
{
struct
nfs_read_data
*
rdata
;
rdata
=
nfs_readdata_alloc
();
if
(
!
rdata
)
return
-
ENOMEM
;
*
rdata
=
(
struct
nfs_read_data
)
{
.
flags
=
(
IS_SWAPFILE
(
inode
)
?
NFS_RPC_SWAPFLAGS
:
0
),
.
cred
=
NULL
,
.
inode
=
inode
,
.
pages
=
LIST_HEAD_INIT
(
rdata
->
pages
),
.
args
=
{
.
fh
=
NFS_FH
(
inode
),
.
lockowner
=
current
->
files
,
...
...
@@ -111,7 +116,7 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
.
count
=
rsize
,
},
.
res
=
{
.
fattr
=
&
rdata
.
fattr
,
.
fattr
=
&
rdata
->
fattr
,
}
};
...
...
@@ -123,19 +128,19 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
*/
do
{
if
(
count
<
rsize
)
rdata
.
args
.
count
=
count
;
rdata
.
res
.
count
=
rdata
.
args
.
count
;
rdata
.
args
.
offset
=
page_offset
(
page
)
+
rdata
.
args
.
pgbase
;
rdata
->
args
.
count
=
count
;
rdata
->
res
.
count
=
rdata
->
args
.
count
;
rdata
->
args
.
offset
=
page_offset
(
page
)
+
rdata
->
args
.
pgbase
;
dprintk
(
"NFS: nfs_proc_read(%s, (%s/%Ld), %Lu, %u)
\n
"
,
NFS_SERVER
(
inode
)
->
hostname
,
inode
->
i_sb
->
s_id
,
(
long
long
)
NFS_FILEID
(
inode
),
(
unsigned
long
long
)
rdata
.
args
.
pgbase
,
rdata
.
args
.
count
);
(
unsigned
long
long
)
rdata
->
args
.
pgbase
,
rdata
->
args
.
count
);
lock_kernel
();
result
=
NFS_PROTO
(
inode
)
->
read
(
&
rdata
,
file
);
result
=
NFS_PROTO
(
inode
)
->
read
(
rdata
,
file
);
unlock_kernel
();
/*
...
...
@@ -148,17 +153,17 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
goto
io_error
;
}
count
-=
result
;
rdata
.
args
.
pgbase
+=
result
;
rdata
->
args
.
pgbase
+=
result
;
/* Note: result == 0 should only happen if we're caching
* a write that extends the file and punches a hole.
*/
if
(
rdata
.
res
.
eof
!=
0
||
result
==
0
)
if
(
rdata
->
res
.
eof
!=
0
||
result
==
0
)
break
;
}
while
(
count
);
NFS_FLAGS
(
inode
)
|=
NFS_INO_INVALID_ATIME
;
if
(
count
)
memclear_highpage_flush
(
page
,
rdata
.
args
.
pgbase
,
count
);
memclear_highpage_flush
(
page
,
rdata
->
args
.
pgbase
,
count
);
SetPageUptodate
(
page
);
if
(
PageError
(
page
))
ClearPageError
(
page
);
...
...
@@ -166,6 +171,7 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
io_error:
unlock_page
(
page
);
nfs_readdata_free
(
rdata
);
return
result
;
}
...
...
@@ -305,6 +311,7 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
data
=
nfs_readdata_alloc
();
if
(
!
data
)
goto
out_bad
;
INIT_LIST_HEAD
(
&
data
->
pages
);
list_add
(
&
data
->
pages
,
&
list
);
requests
++
;
if
(
nbytes
<=
rsize
)
...
...
@@ -361,6 +368,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode)
if
(
!
data
)
goto
out_bad
;
INIT_LIST_HEAD
(
&
data
->
pages
);
pages
=
data
->
pagevec
;
count
=
0
;
while
(
!
list_empty
(
head
))
{
...
...
fs/nfs/write.c
View file @
ba44b066
...
...
@@ -179,7 +179,13 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
{
unsigned
int
wsize
=
NFS_SERVER
(
inode
)
->
wsize
;
int
result
,
written
=
0
;
struct
nfs_write_data
wdata
=
{
struct
nfs_write_data
*
wdata
;
wdata
=
kmalloc
(
sizeof
(
*
wdata
),
GFP_NOFS
);
if
(
!
wdata
)
return
-
ENOMEM
;
*
wdata
=
(
struct
nfs_write_data
)
{
.
flags
=
how
,
.
cred
=
NULL
,
.
inode
=
inode
,
...
...
@@ -192,8 +198,8 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
.
count
=
wsize
,
},
.
res
=
{
.
fattr
=
&
wdata
.
fattr
,
.
verf
=
&
wdata
.
verf
,
.
fattr
=
&
wdata
->
fattr
,
.
verf
=
&
wdata
->
verf
,
},
};
...
...
@@ -205,22 +211,22 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
nfs_begin_data_update
(
inode
);
do
{
if
(
count
<
wsize
)
wdata
.
args
.
count
=
count
;
wdata
.
args
.
offset
=
page_offset
(
page
)
+
wdata
.
args
.
pgbase
;
wdata
->
args
.
count
=
count
;
wdata
->
args
.
offset
=
page_offset
(
page
)
+
wdata
->
args
.
pgbase
;
result
=
NFS_PROTO
(
inode
)
->
write
(
&
wdata
,
file
);
result
=
NFS_PROTO
(
inode
)
->
write
(
wdata
,
file
);
if
(
result
<
0
)
{
/* Must mark the page invalid after I/O error */
ClearPageUptodate
(
page
);
goto
io_error
;
}
if
(
result
<
wdata
.
args
.
count
)
if
(
result
<
wdata
->
args
.
count
)
printk
(
KERN_WARNING
"NFS: short write, count=%u, result=%d
\n
"
,
wdata
.
args
.
count
,
result
);
wdata
->
args
.
count
,
result
);
wdata
.
args
.
offset
+=
result
;
wdata
.
args
.
pgbase
+=
result
;
wdata
->
args
.
offset
+=
result
;
wdata
->
args
.
pgbase
+=
result
;
written
+=
result
;
count
-=
result
;
}
while
(
count
);
...
...
@@ -234,9 +240,10 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
io_error:
nfs_end_data_update_defer
(
inode
);
if
(
wdata
.
cred
)
put_rpccred
(
wdata
.
cred
);
if
(
wdata
->
cred
)
put_rpccred
(
wdata
->
cred
);
kfree
(
wdata
);
return
written
?
written
:
result
;
}
...
...
include/linux/nfs_fs.h
View file @
ba44b066
...
...
@@ -306,6 +306,10 @@ nfs_file_cred(struct file *file)
*/
extern
ssize_t
nfs_direct_IO
(
int
,
struct
kiocb
*
,
const
struct
iovec
*
,
loff_t
,
unsigned
long
);
extern
ssize_t
nfs_file_direct_read
(
struct
kiocb
*
iocb
,
char
*
buf
,
size_t
count
,
loff_t
pos
);
extern
ssize_t
nfs_file_direct_write
(
struct
kiocb
*
iocb
,
const
char
*
buf
,
size_t
count
,
loff_t
pos
);
/*
* linux/fs/nfs/dir.c
...
...
include/linux/sunrpc/gss_api.h
View file @
ba44b066
...
...
@@ -50,46 +50,36 @@ u32 gss_verify_mic(
u32
gss_delete_sec_context
(
struct
gss_ctx
**
ctx_id
);
/* We maintain a list of the pseudoflavors (equivalently, mechanism-qop-service
* triples) that we currently support: */
struct
gss_api_mech
*
gss_mech_get_by_name
(
char
*
name
);
struct
gss_api_mech
*
gss_mech_get_by_pseudoflavor
(
u32
pseudoflavor
);
u32
gss_pseudoflavor_to_service
(
struct
gss_api_mech
*
,
u32
pseudoflavor
);
char
*
gss_service_to_auth_domain_name
(
struct
gss_api_mech
*
,
u32
service
);
struct
sup_sec_triple
{
struct
list_head
triples
;
struct
pf_desc
{
u32
pseudoflavor
;
struct
gss_api_mech
*
mech
;
u32
qop
;
u32
service
;
char
*
name
;
char
*
auth_domain_name
;
};
int
gss_register_triple
(
u32
pseudoflavor
,
struct
gss_api_mech
*
mech
,
u32
qop
,
u32
service
);
int
gss_unregister_triple
(
u32
pseudoflavor
);
int
gss_pseudoflavor_supported
(
u32
pseudoflavor
);
u32
gss_cmp_triples
(
u32
oid_len
,
char
*
oid_data
,
u32
qop
,
u32
service
);
u32
gss_get_pseudoflavor
(
struct
gss_ctx
*
ctx_id
,
u32
qop
,
u32
service
);
u32
gss_pseudoflavor_to_service
(
u32
pseudoflavor
);
/* Both return NULL on failure: */
struct
gss_api_mech
*
gss_pseudoflavor_to_mech
(
u32
pseudoflavor
);
int
gss_pseudoflavor_to_mechOID
(
u32
pseudoflavor
,
struct
xdr_netobj
*
mech
);
/* Different mechanisms (e.g., krb5 or spkm3) may implement gss-api, and
* mechanisms may be dynamically registered or unregistered by modules.
* Our only built-in mechanism is a trivial debugging mechanism that provides
* no actual security; the following function registers that mechanism: */
void
gss_mech_register_debug
(
void
);
* mechanisms may be dynamically registered or unregistered by modules. */
/* Each mechanism is described by the following struct: */
struct
gss_api_mech
{
struct
xdr_netobj
gm_oid
;
struct
list_head
gm_list
;
atomic_t
gm_count
;
struct
module
*
gm_owner
;
struct
xdr_netobj
gm_oid
;
char
*
gm_name
;
struct
gss_api_ops
*
gm_ops
;
/* pseudoflavors supported by this mechanism: */
int
gm_pf_num
;
struct
pf_desc
gm_pfs
[];
};
/* and must provide the following operations: */
struct
gss_api_ops
{
char
*
name
;
u32
(
*
gss_import_sec_context
)(
struct
xdr_netobj
*
input_token
,
struct
gss_ctx
*
ctx_id
);
...
...
@@ -107,29 +97,25 @@ struct gss_api_ops {
void
*
internal_ctx_id
);
};
/* Returns nonzero on failure. */
int
gss_mech_register
(
struct
xdr_netobj
*
,
struct
gss_api_ops
*
);
/* Returns nonzero iff someone still has a reference to this mech. */
int
gss_mech_unregister
(
struct
gss_api_mech
*
);
int
gss_mech_register
(
struct
gss_api_mech
*
);
void
gss_mech_unregister
(
struct
gss_api_mech
*
);
/* Returns nonzer iff someone still has a reference to some mech. */
int
gss_mech_unregister_all
(
void
);
/* returns a mechanism descriptor given an OID, an increments the mechanism's
/* returns a mechanism descriptor given an OID, and increments the mechanism's
* reference count. */
struct
gss_api_mech
*
gss_mech_get_by_OID
(
struct
xdr_netobj
*
);
/*
Similar, but get by name like "krb5", "spkm", etc., instead of OID
. */
/*
Returns a reference to a mechanism, given a name like "krb5" etc
. */
struct
gss_api_mech
*
gss_mech_get_by_name
(
char
*
);
/* Similar, but get by pseudoflavor. */
struct
gss_api_mech
*
gss_mech_get_by_pseudoflavor
(
u32
);
/* Just increments the mechanism's reference count and returns its input: */
struct
gss_api_mech
*
gss_mech_get
(
struct
gss_api_mech
*
);
/* Returns nonzero iff you've released the last reference to this mech.
* Note that for every succesful gss_get_mech call there must be exactly
* one corresponding call to gss_mech_put.*/
int
gss_mech_put
(
struct
gss_api_mech
*
);
/* For every succesful gss_mech_get or gss_mech_get_by_* call there must be a
* corresponding call to gss_mech_put. */
void
gss_mech_put
(
struct
gss_api_mech
*
);
#endif
/* __KERNEL__ */
#endif
/* _LINUX_SUNRPC_GSS_API_H */
...
...
include/linux/sunrpc/gss_asn1.h
View file @
ba44b066
...
...
@@ -81,5 +81,4 @@ int g_token_size(
void
g_make_token_header
(
struct
xdr_netobj
*
mech
,
int
body_size
,
unsigned
char
**
buf
,
int
tok_type
);
unsigned
char
**
buf
);
include/linux/sunrpc/gss_krb5.h
View file @
ba44b066
...
...
@@ -115,7 +115,7 @@ enum seal_alg {
#define ENCTYPE_UNKNOWN 0x01ff
s32
krb5_make_checksum
(
s32
cksumtype
,
char
*
header
,
struct
xdr_buf
*
body
,
make_checksum
(
s32
cksumtype
,
char
*
header
,
int
hdrlen
,
struct
xdr_buf
*
body
,
struct
xdr_netobj
*
cksum
);
u32
...
...
include/linux/sunrpc/xprt.h
View file @
ba44b066
...
...
@@ -69,8 +69,7 @@ extern unsigned int xprt_tcp_slot_table_entries;
* This describes a timeout strategy
*/
struct
rpc_timeout
{
unsigned
long
to_current
,
/* current timeout */
to_initval
,
/* initial timeout */
unsigned
long
to_initval
,
/* initial timeout */
to_maxval
,
/* max timeout */
to_increment
;
/* if !exponential */
unsigned
int
to_retries
;
/* max # of retries */
...
...
@@ -85,7 +84,6 @@ struct rpc_rqst {
* This is the user-visible part
*/
struct
rpc_xprt
*
rq_xprt
;
/* RPC client */
struct
rpc_timeout
rq_timeout
;
/* timeout parms */
struct
xdr_buf
rq_snd_buf
;
/* send buffer */
struct
xdr_buf
rq_rcv_buf
;
/* recv buffer */
...
...
@@ -103,6 +101,9 @@ struct rpc_rqst {
struct
xdr_buf
rq_private_buf
;
/* The receive buffer
* used in the softirq.
*/
unsigned
long
rq_majortimeo
;
/* major timeout alarm */
unsigned
long
rq_timeout
;
/* Current timeout value */
unsigned
int
rq_retries
;
/* # of retries */
/*
* For authentication (e.g. auth_des)
*/
...
...
@@ -115,7 +116,6 @@ struct rpc_rqst {
u32
rq_bytes_sent
;
/* Bytes we have sent */
unsigned
long
rq_xtime
;
/* when transmitted */
int
rq_ntimeo
;
int
rq_ntrans
;
};
#define rq_svec rq_snd_buf.head
...
...
@@ -210,7 +210,7 @@ void xprt_reserve(struct rpc_task *);
int
xprt_prepare_transmit
(
struct
rpc_task
*
);
void
xprt_transmit
(
struct
rpc_task
*
);
void
xprt_receive
(
struct
rpc_task
*
);
int
xprt_adjust_timeout
(
struct
rpc_
timeout
*
);
int
xprt_adjust_timeout
(
struct
rpc_
rqst
*
req
);
void
xprt_release
(
struct
rpc_task
*
);
void
xprt_connect
(
struct
rpc_task
*
);
int
xprt_clear_backlog
(
struct
rpc_xprt
*
);
...
...
net/sunrpc/auth_gss/Makefile
View file @
ba44b066
...
...
@@ -4,11 +4,11 @@
obj-$(CONFIG_SUNRPC_GSS)
+=
auth_rpcgss.o
auth_rpcgss-objs
:=
auth_gss.o gss_
pseudoflavors.o gss_
generic_token.o
\
sunrpcgss_syms.o gss_mech_switch.o svcauth_gss
.o
auth_rpcgss-objs
:=
auth_gss.o gss_generic_token.o
\
gss_mech_switch.o svcauth_gss.o gss_krb5_crypto
.o
obj-$(CONFIG_RPCSEC_GSS_KRB5)
+=
rpcsec_gss_krb5.o
rpcsec_gss_krb5-objs
:=
gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o
\
gss_krb5_
crypto.o gss_krb5_
seqnum.o
gss_krb5_seqnum.o
net/sunrpc/auth_gss/auth_gss.c
View file @
ba44b066
This diff is collapsed.
Click to expand it.
net/sunrpc/auth_gss/gss_generic_token.c
View file @
ba44b066
...
...
@@ -32,6 +32,7 @@
*/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/sunrpc/sched.h>
...
...
@@ -151,22 +152,23 @@ g_token_size(struct xdr_netobj *mech, unsigned int body_size)
return
(
1
+
der_length_size
(
body_size
)
+
body_size
);
}
EXPORT_SYMBOL
(
g_token_size
);
/* fills in a buffer with the token header. The buffer is assumed to
be the right size. buf is advanced past the token header */
void
g_make_token_header
(
struct
xdr_netobj
*
mech
,
int
body_size
,
unsigned
char
**
buf
,
int
tok_type
)
g_make_token_header
(
struct
xdr_netobj
*
mech
,
int
body_size
,
unsigned
char
**
buf
)
{
*
(
*
buf
)
++
=
0x60
;
der_write_length
(
buf
,
4
+
mech
->
len
+
body_size
);
*
(
*
buf
)
++
=
0x06
;
*
(
*
buf
)
++
=
(
unsigned
char
)
mech
->
len
;
TWRITE_STR
(
*
buf
,
mech
->
data
,
((
int
)
mech
->
len
));
*
(
*
buf
)
++
=
(
unsigned
char
)
((
tok_type
>>
8
)
&
0xff
);
*
(
*
buf
)
++
=
(
unsigned
char
)
(
tok_type
&
0xff
);
}
EXPORT_SYMBOL
(
g_make_token_header
);
/*
* Given a buffer containing a token, reads and verifies the token,
* leaving buf advanced past the token header, and setting body_size
...
...
@@ -221,9 +223,6 @@ g_verify_token_header(struct xdr_netobj *mech, int *body_size,
if
(
ret
)
return
(
ret
);
if
((
*
buf
++
!=
((
tok_type
>>
8
)
&
0xff
))
||
(
*
buf
++
!=
(
tok_type
&
0xff
)))
return
(
G_WRONG_TOKID
);
if
(
!
ret
)
{
*
buf_in
=
buf
;
*
body_size
=
toksize
;
...
...
@@ -232,6 +231,8 @@ g_verify_token_header(struct xdr_netobj *mech, int *body_size,
return
(
ret
);
}
EXPORT_SYMBOL
(
g_verify_token_header
);
/* Given a buffer containing a token, returns a copy of the mech oid in
* the parameter mech. */
u32
...
...
net/sunrpc/auth_gss/gss_krb5_crypto.c
View file @
ba44b066
...
...
@@ -84,10 +84,12 @@ krb5_encrypt(
dprintk
(
"RPC: krb5_encrypt: output data:
\n
"
);
print_hexl
((
u32
*
)
out
,
length
,
0
);
out:
dprintk
(
"krb5_encrypt returns %d
\n
"
,
ret
);
dprintk
(
"
RPC:
krb5_encrypt returns %d
\n
"
,
ret
);
return
(
ret
);
}
EXPORT_SYMBOL
(
krb5_encrypt
);
u32
krb5_decrypt
(
struct
crypto_tfm
*
tfm
,
...
...
@@ -124,10 +126,12 @@ krb5_decrypt(
dprintk
(
"RPC: krb5_decrypt: output_data:
\n
"
);
print_hexl
((
u32
*
)
out
,
length
,
0
);
out:
dprintk
(
"gss_k5decrypt returns %d
\n
"
,
ret
);
dprintk
(
"
RPC:
gss_k5decrypt returns %d
\n
"
,
ret
);
return
(
ret
);
}
EXPORT_SYMBOL
(
krb5_decrypt
);
void
buf_to_sg
(
struct
scatterlist
*
sg
,
char
*
ptr
,
int
len
)
{
sg
->
page
=
virt_to_page
(
ptr
);
...
...
@@ -135,10 +139,9 @@ buf_to_sg(struct scatterlist *sg, char *ptr, int len) {
sg
->
length
=
len
;
}
/* checksum the plaintext data and the first 8 bytes of the krb5 token header,
* as specified by the rfc: */
/* checksum the plaintext data and hdrlen bytes of the token header */
s32
krb5_make_checksum
(
s32
cksumtype
,
char
*
header
,
struct
xdr_buf
*
body
,
make_checksum
(
s32
cksumtype
,
char
*
header
,
int
hdrlen
,
struct
xdr_buf
*
body
,
struct
xdr_netobj
*
cksum
)
{
char
*
cksumname
;
...
...
@@ -164,7 +167,7 @@ krb5_make_checksum(s32 cksumtype, char *header, struct xdr_buf *body,
goto
out
;
crypto_digest_init
(
tfm
);
buf_to_sg
(
sg
,
header
,
8
);
buf_to_sg
(
sg
,
header
,
hdrlen
);
crypto_digest_update
(
tfm
,
sg
,
1
);
if
(
body
->
head
[
0
].
iov_len
)
{
buf_to_sg
(
sg
,
body
->
head
[
0
].
iov_base
,
body
->
head
[
0
].
iov_len
);
...
...
@@ -202,3 +205,5 @@ krb5_make_checksum(s32 cksumtype, char *header, struct xdr_buf *body,
crypto_free_tfm
(
tfm
);
return
code
;
}
EXPORT_SYMBOL
(
make_checksum
);
net/sunrpc/auth_gss/gss_krb5_mech.c
View file @
ba44b066
...
...
@@ -40,7 +40,6 @@
#include <linux/slab.h>
#include <linux/sunrpc/auth.h>
#include <linux/in.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/gss_krb5.h>
#include <linux/sunrpc/xdr.h>
#include <linux/crypto.h>
...
...
@@ -155,7 +154,7 @@ gss_import_sec_context_kerberos(struct xdr_netobj *inbuf,
goto
out_err_free_key2
;
ctx_id
->
internal_ctx_id
=
ctx
;
dprintk
(
"Succesfully imported new context.
\n
"
);
dprintk
(
"
RPC:
Succesfully imported new context.
\n
"
);
return
0
;
out_err_free_key2:
...
...
@@ -217,35 +216,36 @@ gss_get_mic_kerberos(struct gss_ctx *ctx,
}
static
struct
gss_api_ops
gss_kerberos_ops
=
{
.
name
=
"krb5"
,
.
gss_import_sec_context
=
gss_import_sec_context_kerberos
,
.
gss_get_mic
=
gss_get_mic_kerberos
,
.
gss_verify_mic
=
gss_verify_mic_kerberos
,
.
gss_delete_sec_context
=
gss_delete_sec_context_kerberos
,
};
/* XXX error checking? reference counting? */
static
struct
gss_api_mech
gss_kerberos_mech
=
{
.
gm_name
=
"krb5"
,
.
gm_owner
=
THIS_MODULE
,
.
gm_ops
=
&
gss_kerberos_ops
,
.
gm_pf_num
=
2
,
.
gm_pfs
=
{
{
RPC_AUTH_GSS_KRB5
,
0
,
RPC_GSS_SVC_NONE
,
"krb5"
},
{
RPC_AUTH_GSS_KRB5I
,
0
,
RPC_GSS_SVC_INTEGRITY
,
"krb5i"
},
},
};
static
int
__init
init_kerberos_module
(
void
)
{
struct
gss_api_mech
*
gm
;
int
status
;
if
(
gss_mech_register
(
&
gss_mech_krb5_oid
,
&
gss_kerberos_ops
))
status
=
gss_mech_register
(
&
gss_kerberos_mech
);
if
(
status
)
printk
(
"Failed to register kerberos gss mechanism!
\n
"
);
gm
=
gss_mech_get_by_OID
(
&
gss_mech_krb5_oid
);
gss_register_triple
(
RPC_AUTH_GSS_KRB5
,
gm
,
0
,
RPC_GSS_SVC_NONE
);
gss_register_triple
(
RPC_AUTH_GSS_KRB5I
,
gm
,
0
,
RPC_GSS_SVC_INTEGRITY
);
if
(
svcauth_gss_register_pseudoflavor
(
RPC_AUTH_GSS_KRB5
,
"krb5"
))
printk
(
"Failed to register %s with server!
\n
"
,
"krb5"
);
if
(
svcauth_gss_register_pseudoflavor
(
RPC_AUTH_GSS_KRB5I
,
"krb5i"
))
printk
(
"Failed to register %s with server!
\n
"
,
"krb5i"
);
gss_mech_put
(
gm
);
return
0
;
return
status
;
}
static
void
__exit
cleanup_kerberos_module
(
void
)
{
gss_unregister_triple
(
RPC_AUTH_GSS_KRB5I
);
gss_unregister_triple
(
RPC_AUTH_GSS_KRB5
);
gss_mech_unregister
(
&
gss_kerberos_mech
);
}
MODULE_LICENSE
(
"GPL"
);
...
...
net/sunrpc/auth_gss/gss_krb5_seal.c
View file @
ba44b066
...
...
@@ -91,7 +91,7 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
dprintk
(
"RPC: gss_krb5_seal
\n
"
);
now
=
jiffies
;
now
=
get_seconds
()
;
if
(
qop_req
!=
0
)
goto
out_err
;
...
...
@@ -122,7 +122,10 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
token
->
len
=
g_token_size
(
&
ctx
->
mech_used
,
22
+
tmsglen
);
ptr
=
token
->
data
;
g_make_token_header
(
&
ctx
->
mech_used
,
22
+
tmsglen
,
&
ptr
,
toktype
);
g_make_token_header
(
&
ctx
->
mech_used
,
22
+
tmsglen
,
&
ptr
);
*
ptr
++
=
(
unsigned
char
)
((
toktype
>>
8
)
&
0xff
);
*
ptr
++
=
(
unsigned
char
)
(
toktype
&
0xff
);
/* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
krb5_hdr
=
ptr
-
2
;
...
...
@@ -137,7 +140,7 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
/* XXX removing support for now */
goto
out_err
;
}
else
{
/* Sign only. */
if
(
krb5_make_checksum
(
checksum_type
,
krb5_hdr
,
text
,
if
(
make_checksum
(
checksum_type
,
krb5_hdr
,
8
,
text
,
&
md5cksum
))
goto
out_err
;
}
...
...
@@ -151,7 +154,7 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
md5cksum
.
data
+
md5cksum
.
len
-
KRB5_CKSUM_LENGTH
,
KRB5_CKSUM_LENGTH
);
dprintk
(
"make_seal_token: cksum data:
\n
"
);
dprintk
(
"
RPC:
make_seal_token: cksum data:
\n
"
);
print_hexl
((
u32
*
)
(
krb5_hdr
+
16
),
KRB5_CKSUM_LENGTH
,
0
);
break
;
default:
...
...
net/sunrpc/auth_gss/gss_krb5_seqnum.c
View file @
ba44b066
...
...
@@ -70,7 +70,7 @@ krb5_get_seq_num(struct crypto_tfm *key,
s32
code
;
unsigned
char
plain
[
8
];
dprintk
(
"
krb5_get_seq_num:
\n
"
);
dprintk
(
"
RPC: krb5_get_seq_num:
\n
"
);
if
((
code
=
krb5_decrypt
(
key
,
cksum
,
buf
,
plain
,
8
)))
return
code
;
...
...
net/sunrpc/auth_gss/gss_krb5_unseal.c
View file @
ba44b066
...
...
@@ -99,6 +99,10 @@ krb5_read_token(struct krb5_ctx *ctx,
if
(
g_verify_token_header
(
&
ctx
->
mech_used
,
&
bodysize
,
&
ptr
,
toktype
,
read_token
->
len
))
goto
out
;
if
((
*
ptr
++
!=
((
toktype
>>
8
)
&
0xff
))
||
(
*
ptr
++
!=
(
toktype
&
0xff
)))
goto
out
;
/* XXX sanity-check bodysize?? */
if
(
toktype
==
KG_TOK_WRAP_MSG
)
{
...
...
@@ -149,7 +153,7 @@ krb5_read_token(struct krb5_ctx *ctx,
switch
(
signalg
)
{
case
SGN_ALG_DES_MAC_MD5
:
ret
=
krb5_make_checksum
(
checksum_type
,
ptr
-
2
,
ret
=
make_checksum
(
checksum_type
,
ptr
-
2
,
8
,
message_buffer
,
&
md5cksum
);
if
(
ret
)
goto
out
;
...
...
@@ -174,7 +178,7 @@ krb5_read_token(struct krb5_ctx *ctx,
if
(
qop_state
)
*
qop_state
=
GSS_C_QOP_DEFAULT
;
now
=
jiffies
;
now
=
get_seconds
()
;
ret
=
GSS_S_CONTEXT_EXPIRED
;
if
(
now
>
ctx
->
endtime
)
...
...
net/sunrpc/auth_gss/gss_mech_switch.c
View file @
ba44b066
...
...
@@ -36,9 +36,11 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/socket.h>
#include <linux/module.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/gss_asn1.h>
#include <linux/sunrpc/auth_gss.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/gss_err.h>
#include <linux/sunrpc/sched.h>
#include <linux/sunrpc/gss_api.h>
...
...
@@ -51,146 +53,186 @@
static
LIST_HEAD
(
registered_mechs
);
static
spinlock_t
registered_mechs_lock
=
SPIN_LOCK_UNLOCKED
;
/* Reference counting: The reference count includes the reference in the
* global registered_mechs list. That reference will never diseappear
* (so the reference count will never go below 1) until after the mech
* is removed from the list. Nothing can be removed from the list without
* first getting the registered_mechs_lock, so a gss_api_mech won't diseappear
* from underneath us while we hold the registered_mech_lock. */
int
gss_mech_register
(
struct
xdr_netobj
*
mech_type
,
struct
gss_api_ops
*
ops
)
static
void
gss_mech_free
(
struct
gss_api_mech
*
gm
)
{
struct
gss_api_mech
*
gm
;
struct
pf_desc
*
pf
;
int
i
;
if
(
!
(
gm
=
kmalloc
(
sizeof
(
*
gm
),
GFP_KERNEL
)))
{
printk
(
"Failed to allocate memory in gss_mech_register"
);
return
-
1
;
for
(
i
=
0
;
i
<
gm
->
gm_pf_num
;
i
++
)
{
pf
=
&
gm
->
gm_pfs
[
i
];
if
(
pf
->
auth_domain_name
)
kfree
(
pf
->
auth_domain_name
);
pf
->
auth_domain_name
=
NULL
;
}
gm
->
gm_oid
.
len
=
mech_type
->
len
;
if
(
!
(
gm
->
gm_oid
.
data
=
kmalloc
(
mech_type
->
len
,
GFP_KERNEL
)))
{
kfree
(
gm
);
printk
(
"Failed to allocate memory in gss_mech_register"
);
return
-
1
;
}
memcpy
(
gm
->
gm_oid
.
data
,
mech_type
->
data
,
mech_type
->
len
);
/* We're counting the reference in the registered_mechs list: */
atomic_set
(
&
gm
->
gm_count
,
1
);
gm
->
gm_ops
=
ops
;
spin_lock
(
&
registered_mechs_lock
);
list_add
(
&
gm
->
gm_list
,
&
registered_mechs
);
spin_unlock
(
&
registered_mechs_lock
);
dprintk
(
"RPC: gss_mech_register: registered mechanism with oid:
\n
"
);
print_hexl
((
u32
*
)
mech_type
->
data
,
mech_type
->
len
,
0
);
return
0
;
}
/* The following must be called with spinlock held: */
int
do_gss_mech_unregister
(
struct
gss_api_mech
*
gm
)
static
inline
char
*
make_auth_domain_name
(
char
*
name
)
{
static
char
*
prefix
=
"gss/"
;
char
*
new
;
list_del
(
&
gm
->
gm_list
);
new
=
kmalloc
(
strlen
(
name
)
+
strlen
(
prefix
)
+
1
,
GFP_KERNEL
);
if
(
new
)
{
strcpy
(
new
,
prefix
);
strcat
(
new
,
name
);
}
return
new
;
}
dprintk
(
"RPC: unregistered mechanism with oid:
\n
"
);
print_hexl
((
u32
*
)
gm
->
gm_oid
.
data
,
gm
->
gm_oid
.
len
,
0
);
if
(
!
gss_mech_put
(
gm
))
{
dprintk
(
"RPC: We just unregistered a gss_mechanism which"
" someone is still using.
\n
"
);
return
-
1
;
}
else
{
return
0
;
static
int
gss_mech_svc_setup
(
struct
gss_api_mech
*
gm
)
{
struct
pf_desc
*
pf
;
int
i
,
status
;
for
(
i
=
0
;
i
<
gm
->
gm_pf_num
;
i
++
)
{
pf
=
&
gm
->
gm_pfs
[
i
];
pf
->
auth_domain_name
=
make_auth_domain_name
(
pf
->
name
);
status
=
-
ENOMEM
;
if
(
pf
->
auth_domain_name
==
NULL
)
goto
out
;
status
=
svcauth_gss_register_pseudoflavor
(
pf
->
pseudoflavor
,
pf
->
auth_domain_name
);
if
(
status
)
goto
out
;
}
return
0
;
out:
gss_mech_free
(
gm
);
return
status
;
}
int
gss_mech_
un
register
(
struct
gss_api_mech
*
gm
)
gss_mech_register
(
struct
gss_api_mech
*
gm
)
{
int
status
;
status
=
gss_mech_svc_setup
(
gm
);
if
(
status
)
return
status
;
spin_lock
(
&
registered_mechs_lock
);
status
=
do_gss_mech_unregister
(
gm
);
list_add
(
&
gm
->
gm_list
,
&
registered_mechs
);
spin_unlock
(
&
registered_mechs_lock
);
return
status
;
dprintk
(
"RPC: registered gss mechanism %s
\n
"
,
gm
->
gm_name
);
return
0
;
}
int
gss_mech_unregister_all
(
void
)
{
struct
list_head
*
pos
;
struct
gss_api_mech
*
gm
;
int
status
=
0
;
EXPORT_SYMBOL
(
gss_mech_register
);
void
gss_mech_unregister
(
struct
gss_api_mech
*
gm
)
{
spin_lock
(
&
registered_mechs_lock
);
while
(
!
list_empty
(
&
registered_mechs
))
{
pos
=
registered_mechs
.
next
;
gm
=
list_entry
(
pos
,
struct
gss_api_mech
,
gm_list
);
if
(
do_gss_mech_unregister
(
gm
))
status
=
-
1
;
}
list_del
(
&
gm
->
gm_list
);
spin_unlock
(
&
registered_mechs_lock
);
return
status
;
dprintk
(
"RPC: unregistered gss mechanism %s
\n
"
,
gm
->
gm_name
);
gss_mech_free
(
gm
);
}
EXPORT_SYMBOL
(
gss_mech_unregister
);
struct
gss_api_mech
*
gss_mech_get
(
struct
gss_api_mech
*
gm
)
{
atomic_inc
(
&
gm
->
gm_count
);
__module_get
(
gm
->
gm_owner
);
return
gm
;
}
EXPORT_SYMBOL
(
gss_mech_get
);
struct
gss_api_mech
*
gss_mech_get_by_
OID
(
struct
xdr_netobj
*
mech_typ
e
)
gss_mech_get_by_
name
(
char
*
nam
e
)
{
struct
gss_api_mech
*
pos
,
*
gm
=
NULL
;
dprintk
(
"RPC: gss_mech_get_by_OID searching for mechanism with OID:
\n
"
);
print_hexl
((
u32
*
)
mech_type
->
data
,
mech_type
->
len
,
0
);
spin_lock
(
&
registered_mechs_lock
);
list_for_each_entry
(
pos
,
&
registered_mechs
,
gm_list
)
{
if
(
(
pos
->
gm_oid
.
len
==
mech_type
->
len
)
&&
!
memcmp
(
pos
->
gm_oid
.
data
,
mech_type
->
data
,
mech_type
->
len
))
{
gm
=
gss_mech_get
(
pos
)
;
if
(
0
==
strcmp
(
name
,
pos
->
gm_name
))
{
if
(
!
try_module_get
(
pos
->
gm_owner
))
continue
;
gm
=
pos
;
break
;
}
}
spin_unlock
(
&
registered_mechs_lock
);
dprintk
(
"RPC: gss_mech_get_by_OID %s it
\n
"
,
gm
?
"found"
:
"didn't find"
);
return
gm
;
}
EXPORT_SYMBOL
(
gss_mech_get_by_name
);
static
inline
int
mech_supports_pseudoflavor
(
struct
gss_api_mech
*
gm
,
u32
pseudoflavor
)
{
int
i
;
for
(
i
=
0
;
i
<
gm
->
gm_pf_num
;
i
++
)
{
if
(
gm
->
gm_pfs
[
i
].
pseudoflavor
==
pseudoflavor
)
return
1
;
}
return
0
;
}
struct
gss_api_mech
*
gss_mech_get_by_
name
(
char
*
name
)
gss_mech_get_by_
pseudoflavor
(
u32
pseudoflavor
)
{
struct
gss_api_mech
*
pos
,
*
gm
=
NULL
;
spin_lock
(
&
registered_mechs_lock
);
list_for_each_entry
(
pos
,
&
registered_mechs
,
gm_list
)
{
if
(
0
==
strcmp
(
name
,
pos
->
gm_ops
->
name
))
{
gm
=
gss_mech_get
(
pos
);
break
;
if
(
!
try_module_get
(
pos
->
gm_owner
))
continue
;
if
(
!
mech_supports_pseudoflavor
(
pos
,
pseudoflavor
))
{
module_put
(
pos
->
gm_owner
);
continue
;
}
gm
=
pos
;
break
;
}
spin_unlock
(
&
registered_mechs_lock
);
return
gm
;
}
int
gss_mech_put
(
struct
gss_api_mech
*
gm
)
EXPORT_SYMBOL
(
gss_mech_get_by_pseudoflavor
);
u32
gss_pseudoflavor_to_service
(
struct
gss_api_mech
*
gm
,
u32
pseudoflavor
)
{
i
f
(
atomic_dec_and_test
(
&
gm
->
gm_count
))
{
if
(
gm
->
gm_oid
.
len
>
0
)
kfree
(
gm
->
gm_oid
.
data
);
kfree
(
gm
);
return
1
;
}
else
{
i
nt
i
;
for
(
i
=
0
;
i
<
gm
->
gm_pf_num
;
i
++
)
{
if
(
gm
->
gm_pfs
[
i
].
pseudoflavor
==
pseudoflavor
)
return
gm
->
gm_pfs
[
i
].
service
;
}
return
0
;
}
EXPORT_SYMBOL
(
gss_pseudoflavor_to_service
);
char
*
gss_service_to_auth_domain_name
(
struct
gss_api_mech
*
gm
,
u32
service
)
{
int
i
;
for
(
i
=
0
;
i
<
gm
->
gm_pf_num
;
i
++
)
{
if
(
gm
->
gm_pfs
[
i
].
service
==
service
)
return
gm
->
gm_pfs
[
i
].
auth_domain_name
;
}
return
NULL
;
}
EXPORT_SYMBOL
(
gss_service_to_auth_domain_name
);
void
gss_mech_put
(
struct
gss_api_mech
*
gm
)
{
module_put
(
gm
->
gm_owner
);
}
EXPORT_SYMBOL
(
gss_mech_put
);
/* The mech could probably be determined from the token instead, but it's just
* as easy for now to pass it in. */
u32
...
...
@@ -244,7 +286,8 @@ gss_verify_mic(struct gss_ctx *context_handle,
u32
gss_delete_sec_context
(
struct
gss_ctx
**
context_handle
)
{
dprintk
(
"gss_delete_sec_context deleting %p
\n
"
,
*
context_handle
);
dprintk
(
"RPC: gss_delete_sec_context deleting %p
\n
"
,
*
context_handle
);
if
(
!*
context_handle
)
return
(
GSS_S_NO_CONTEXT
);
...
...
net/sunrpc/auth_gss/gss_pseudoflavors.c
View file @
ba44b066
...
...
@@ -82,7 +82,8 @@ gss_register_triple(u32 pseudoflavor, struct gss_api_mech *mech,
spin_lock
(
&
registered_triples_lock
);
if
(
do_lookup_triple_by_pseudoflavor
(
pseudoflavor
))
{
printk
(
"Registered pseudoflavor %d again
\n
"
,
pseudoflavor
);
printk
(
KERN_WARNING
"RPC: Registered pseudoflavor %d again
\n
"
,
pseudoflavor
);
goto
err_unlock
;
}
list_add
(
&
triple
->
triples
,
&
registered_triples
);
...
...
@@ -145,7 +146,7 @@ gss_cmp_triples(u32 oid_len, char *oid_data, u32 qop, u32 service)
oid
.
len
=
oid_len
;
oid
.
data
=
oid_data
;
dprintk
(
"RPC:
gss_cmp_triples
\n
"
);
dprintk
(
"RPC:
gss_cmp_triples
\n
"
);
print_sec_triple
(
&
oid
,
qop
,
service
);
spin_lock
(
&
registered_triples_lock
);
...
...
@@ -193,8 +194,8 @@ gss_pseudoflavor_to_service(u32 pseudoflavor)
triple
=
do_lookup_triple_by_pseudoflavor
(
pseudoflavor
);
spin_unlock
(
&
registered_triples_lock
);
if
(
!
triple
)
{
dprintk
(
"RPC:
gss_pseudoflavor_to_service called with"
" unsupported pseudoflavor %d
\n
"
,
pseudoflavor
);
dprintk
(
"RPC:
gss_pseudoflavor_to_service called with unsupported pseudoflavor %d
\n
"
,
pseudoflavor
);
return
0
;
}
return
triple
->
service
;
...
...
@@ -211,8 +212,8 @@ gss_pseudoflavor_to_mech(u32 pseudoflavor) {
if
(
triple
)
mech
=
gss_mech_get
(
triple
->
mech
);
else
dprintk
(
"RPC:
gss_pseudoflavor_to_mech called with"
" unsupported pseudoflavor %d
\n
"
,
pseudoflavor
);
dprintk
(
"RPC:
gss_pseudoflavor_to_mech called with unsupported pseudoflavor %d
\n
"
,
pseudoflavor
);
return
mech
;
}
...
...
@@ -223,8 +224,8 @@ gss_pseudoflavor_to_mechOID(u32 pseudoflavor, struct xdr_netobj * oid)
mech
=
gss_pseudoflavor_to_mech
(
pseudoflavor
);
if
(
!
mech
)
{
dprintk
(
"RPC:
gss_pseudoflavor_to_mechOID called with"
" unsupported pseudoflavor %d
\n
"
,
pseudoflavor
);
dprintk
(
"RPC:
gss_pseudoflavor_to_mechOID called with unsupported pseudoflavor %d
\n
"
,
pseudoflavor
);
return
-
1
;
}
oid
->
len
=
mech
->
gm_oid
.
len
;
...
...
net/sunrpc/auth_gss/sunrpcgss_syms.c
View file @
ba44b066
...
...
@@ -10,26 +10,28 @@
#include <linux/sunrpc/auth_gss.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/gss_asn1.h>
#include <linux/sunrpc/gss_krb5.h>
/* sec_triples: */
EXPORT_SYMBOL
(
gss_register_triple
);
EXPORT_SYMBOL
(
gss_unregister_triple
);
EXPORT_SYMBOL
(
gss_cmp_triples
);
EXPORT_SYMBOL
(
gss_pseudoflavor_to_mechOID
);
EXPORT_SYMBOL
(
gss_pseudoflavor_supported
);
EXPORT_SYMBOL
(
gss_pseudoflavor_to_service
);
/* svcauth_gss.c: */
EXPORT_SYMBOL
(
svcauth_gss_register_pseudoflavor
);
/* registering gss mechanisms to the mech switching code: */
EXPORT_SYMBOL
(
gss_mech_register
);
EXPORT_SYMBOL
(
gss_mech_unregister
);
EXPORT_SYMBOL
(
gss_mech_get
);
EXPORT_SYMBOL
(
gss_mech_get_by_OID
);
EXPORT_SYMBOL
(
gss_mech_get_by_pseudoflavor
);
EXPORT_SYMBOL
(
gss_mech_get_by_name
);
EXPORT_SYMBOL
(
gss_mech_put
);
EXPORT_SYMBOL
(
gss_pseudoflavor_to_service
);
EXPORT_SYMBOL
(
gss_service_to_auth_domain_name
);
/* generic functionality in gss code: */
EXPORT_SYMBOL
(
g_make_token_header
);
EXPORT_SYMBOL
(
g_verify_token_header
);
EXPORT_SYMBOL
(
g_token_size
);
EXPORT_SYMBOL
(
make_checksum
);
EXPORT_SYMBOL
(
krb5_encrypt
);
EXPORT_SYMBOL
(
krb5_decrypt
);
/* debug */
EXPORT_SYMBOL
(
print_hexl
);
net/sunrpc/auth_gss/svcauth_gss.c
View file @
ba44b066
...
...
@@ -570,14 +570,14 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
}
if
(
gc
->
gc_seq
>
MAXSEQ
)
{
dprintk
(
"
svcauth_gss: discarding request with large"
" sequence number %d
\n
"
,
gc
->
gc_seq
);
dprintk
(
"
RPC: svcauth_gss: discarding request with large sequence number %d
\n
"
,
gc
->
gc_seq
);
*
authp
=
rpcsec_gsserr_ctxproblem
;
return
SVC_DENIED
;
}
if
(
!
gss_check_seq_num
(
rsci
,
gc
->
gc_seq
))
{
dprintk
(
"
svcauth_gss: discarding request with old"
" sequence number %d
\n
"
,
gc
->
gc_seq
);
dprintk
(
"
RPC: svcauth_gss: discarding request with old sequence number %d
\n
"
,
gc
->
gc_seq
);
return
SVC_DROP
;
}
return
SVC_OK
;
...
...
@@ -617,19 +617,15 @@ struct gss_domain {
u32
pseudoflavor
;
};
/* XXX this should be done in gss_pseudoflavors, and shouldn't be hardcoded: */
static
struct
auth_domain
*
find_gss_auth_domain
(
struct
gss_ctx
*
ctx
,
u32
svc
)
{
switch
(
gss_get_pseudoflavor
(
ctx
,
0
,
svc
))
{
case
RPC_AUTH_GSS_KRB5
:
return
auth_domain_find
(
"gss/krb5"
);
case
RPC_AUTH_GSS_KRB5I
:
return
auth_domain_find
(
"gss/krb5i"
);
case
RPC_AUTH_GSS_KRB5P
:
return
auth_domain_find
(
"gss/krb5p"
);
}
char
*
name
;
name
=
gss_service_to_auth_domain_name
(
ctx
->
mech_type
,
svc
);
if
(
!
name
)
return
NULL
;
return
auth_domain_find
(
name
);
}
int
...
...
@@ -637,19 +633,17 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
{
struct
gss_domain
*
new
;
struct
auth_domain
*
test
;
static
char
*
prefix
=
"gss/"
;
int
stat
=
-
1
;
int
stat
=
-
ENOMEM
;
new
=
kmalloc
(
sizeof
(
*
new
),
GFP_KERNEL
);
if
(
!
new
)
goto
out
;
cache_init
(
&
new
->
h
.
h
);
atomic_inc
(
&
new
->
h
.
h
.
refcnt
);
new
->
h
.
name
=
kmalloc
(
strlen
(
name
)
+
strlen
(
prefix
)
+
1
,
GFP_KERNEL
);
new
->
h
.
name
=
kmalloc
(
strlen
(
name
)
+
1
,
GFP_KERNEL
);
if
(
!
new
->
h
.
name
)
goto
out_free_dom
;
strcpy
(
new
->
h
.
name
,
prefix
);
strcat
(
new
->
h
.
name
,
name
);
strcpy
(
new
->
h
.
name
,
name
);
new
->
h
.
flavour
=
RPC_AUTH_GSS
;
new
->
pseudoflavor
=
pseudoflavor
;
new
->
h
.
h
.
expiry_time
=
NEVER
;
...
...
@@ -670,6 +664,8 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
return
stat
;
}
EXPORT_SYMBOL
(
svcauth_gss_register_pseudoflavor
);
static
inline
int
read_u32_from_xdr_buf
(
struct
xdr_buf
*
buf
,
int
base
,
u32
*
obj
)
{
...
...
net/sunrpc/clnt.c
View file @
ba44b066
...
...
@@ -788,13 +788,11 @@ static void
call_timeout
(
struct
rpc_task
*
task
)
{
struct
rpc_clnt
*
clnt
=
task
->
tk_client
;
struct
rpc_timeout
*
to
=
&
task
->
tk_rqstp
->
rq_timeout
;
if
(
xprt_adjust_timeout
(
t
o
)
)
{
if
(
xprt_adjust_timeout
(
t
ask
->
tk_rqstp
)
==
0
)
{
dprintk
(
"RPC: %4d call_timeout (minor)
\n
"
,
task
->
tk_pid
);
goto
retry
;
}
to
->
to_retries
=
clnt
->
cl_timeout
.
to_retries
;
dprintk
(
"RPC: %4d call_timeout (major)
\n
"
,
task
->
tk_pid
);
if
(
RPC_IS_SOFT
(
task
))
{
...
...
net/sunrpc/timer.c
View file @
ba44b066
...
...
@@ -39,6 +39,7 @@ rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo)
for
(
i
=
0
;
i
<
5
;
i
++
)
{
rt
->
srtt
[
i
]
=
init
;
rt
->
sdrtt
[
i
]
=
RPC_RTO_INIT
;
rt
->
ntimeouts
[
i
]
=
0
;
}
}
...
...
net/sunrpc/xprt.c
View file @
ba44b066
...
...
@@ -352,35 +352,57 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
}
/*
*
Adjust timeout values etc for next retransmit
*
Reset the major timeout value
*/
int
xprt_adjust_timeout
(
struct
rpc_timeout
*
to
)
static
void
xprt_reset_majortimeo
(
struct
rpc_rqst
*
req
)
{
if
(
to
->
to_retries
>
0
)
{
struct
rpc_timeout
*
to
=
&
req
->
rq_xprt
->
timeout
;
req
->
rq_majortimeo
=
req
->
rq_timeout
;
if
(
to
->
to_exponential
)
to
->
to_current
<<=
1
;
req
->
rq_majortimeo
<<=
to
->
to_retries
;
else
to
->
to_current
+=
to
->
to_increment
;
if
(
to
->
to_maxval
&&
to
->
to_current
>=
to
->
to_maxval
)
to
->
to_current
=
to
->
to_maxval
;
}
else
{
req
->
rq_majortimeo
+=
to
->
to_increment
*
to
->
to_retries
;
if
(
req
->
rq_majortimeo
>
to
->
to_maxval
||
req
->
rq_majortimeo
==
0
)
req
->
rq_majortimeo
=
to
->
to_maxval
;
req
->
rq_majortimeo
+=
jiffies
;
}
/*
* Adjust timeout values etc for next retransmit
*/
int
xprt_adjust_timeout
(
struct
rpc_rqst
*
req
)
{
struct
rpc_xprt
*
xprt
=
req
->
rq_xprt
;
struct
rpc_timeout
*
to
=
&
xprt
->
timeout
;
int
status
=
0
;
if
(
time_before
(
jiffies
,
req
->
rq_majortimeo
))
{
if
(
to
->
to_exponential
)
to
->
to_initval
<<=
1
;
req
->
rq_timeout
<<=
1
;
else
to
->
to_initval
+=
to
->
to_increment
;
if
(
to
->
to_maxval
&&
to
->
to_initval
>=
to
->
to_maxval
)
to
->
to_initval
=
to
->
to_maxval
;
to
->
to_current
=
to
->
to_initval
;
req
->
rq_timeout
+=
to
->
to_increment
;
if
(
to
->
to_maxval
&&
req
->
rq_timeout
>=
to
->
to_maxval
)
req
->
rq_timeout
=
to
->
to_maxval
;
req
->
rq_retries
++
;
pprintk
(
"RPC: %lu retrans
\n
"
,
jiffies
);
}
else
{
req
->
rq_timeout
=
to
->
to_initval
;
req
->
rq_retries
=
0
;
xprt_reset_majortimeo
(
req
);
/* Reset the RTT counters == "slow start" */
spin_lock_bh
(
&
xprt
->
sock_lock
);
rpc_init_rtt
(
req
->
rq_task
->
tk_client
->
cl_rtt
,
to
->
to_initval
);
spin_unlock_bh
(
&
xprt
->
sock_lock
);
pprintk
(
"RPC: %lu timeout
\n
"
,
jiffies
);
status
=
-
ETIMEDOUT
;
}
if
(
!
to
->
to_current
)
{
printk
(
KERN_WARNING
"xprt_adjust_timeout:
to_curren
t = 0!
\n
"
);
to
->
to_curren
t
=
5
*
HZ
;
if
(
req
->
rq_timeout
==
0
)
{
printk
(
KERN_WARNING
"xprt_adjust_timeout:
rq_timeou
t = 0!
\n
"
);
req
->
rq_timeou
t
=
5
*
HZ
;
}
pprintk
(
"RPC: %lu %s
\n
"
,
jiffies
,
to
->
to_retries
?
"retrans"
:
"timeout"
);
return
to
->
to_retries
--
>
0
;
return
status
;
}
/*
...
...
@@ -537,8 +559,17 @@ void xprt_connect(struct rpc_task *task)
task
->
tk_timeout
=
RPC_CONNECT_TIMEOUT
;
rpc_sleep_on
(
&
xprt
->
pending
,
task
,
xprt_connect_status
,
NULL
);
if
(
!
test_and_set_bit
(
XPRT_CONNECTING
,
&
xprt
->
sockstate
))
if
(
!
test_and_set_bit
(
XPRT_CONNECTING
,
&
xprt
->
sockstate
))
{
/* Note: if we are here due to a dropped connection
* we delay reconnecting by RPC_REESTABLISH_TIMEOUT/HZ
* seconds
*/
if
(
xprt
->
sock
!=
NULL
)
schedule_delayed_work
(
&
xprt
->
sock_connect
,
RPC_REESTABLISH_TIMEOUT
);
else
schedule_work
(
&
xprt
->
sock_connect
);
}
return
;
out_write:
xprt_release_write
(
xprt
,
task
);
...
...
@@ -566,7 +597,6 @@ xprt_connect_status(struct rpc_task *task)
case
-
ECONNREFUSED
:
case
-
ECONNRESET
:
case
-
ENOTCONN
:
rpc_delay
(
task
,
RPC_REESTABLISH_TIMEOUT
);
return
;
case
-
ETIMEDOUT
:
dprintk
(
"RPC: %4d xprt_connect_status: timed out
\n
"
,
...
...
@@ -1166,6 +1196,7 @@ xprt_transmit(struct rpc_task *task)
/* Add request to the receive list */
list_add_tail
(
&
req
->
rq_list
,
&
xprt
->
recv
);
spin_unlock_bh
(
&
xprt
->
sock_lock
);
xprt_reset_majortimeo
(
req
);
}
}
else
if
(
!
req
->
rq_bytes_sent
)
return
;
...
...
@@ -1221,7 +1252,7 @@ xprt_transmit(struct rpc_task *task)
if
(
!
xprt_connected
(
xprt
))
task
->
tk_status
=
-
ENOTCONN
;
else
if
(
test_bit
(
SOCK_NOSPACE
,
&
xprt
->
sock
->
flags
))
{
task
->
tk_timeout
=
req
->
rq_timeout
.
to_current
;
task
->
tk_timeout
=
req
->
rq_timeout
;
rpc_sleep_on
(
&
xprt
->
pending
,
task
,
NULL
,
NULL
);
}
spin_unlock_bh
(
&
xprt
->
sock_lock
);
...
...
@@ -1248,13 +1279,11 @@ xprt_transmit(struct rpc_task *task)
if
(
!
xprt
->
nocong
)
{
int
timer
=
task
->
tk_msg
.
rpc_proc
->
p_timer
;
task
->
tk_timeout
=
rpc_calc_rto
(
clnt
->
cl_rtt
,
timer
);
task
->
tk_timeout
<<=
rpc_ntimeo
(
clnt
->
cl_rtt
,
timer
);
task
->
tk_timeout
<<=
clnt
->
cl_timeout
.
to_retries
-
req
->
rq_timeout
.
to_retries
;
if
(
task
->
tk_timeout
>
req
->
rq_timeout
.
to_maxval
)
task
->
tk_timeout
=
req
->
rq_timeout
.
to_maxval
;
task
->
tk_timeout
<<=
rpc_ntimeo
(
clnt
->
cl_rtt
,
timer
)
+
req
->
rq_retries
;
if
(
task
->
tk_timeout
>
xprt
->
timeout
.
to_maxval
||
task
->
tk_timeout
==
0
)
task
->
tk_timeout
=
xprt
->
timeout
.
to_maxval
;
}
else
task
->
tk_timeout
=
req
->
rq_timeout
.
to_current
;
task
->
tk_timeout
=
req
->
rq_timeout
;
/* Don't race with disconnect */
if
(
!
xprt_connected
(
xprt
))
task
->
tk_status
=
-
ENOTCONN
;
...
...
@@ -1324,7 +1353,7 @@ xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
{
struct
rpc_rqst
*
req
=
task
->
tk_rqstp
;
req
->
rq_timeout
=
xprt
->
timeout
;
req
->
rq_timeout
=
xprt
->
timeout
.
to_initval
;
req
->
rq_task
=
task
;
req
->
rq_xprt
=
xprt
;
req
->
rq_xid
=
xprt_alloc_xid
(
xprt
);
...
...
@@ -1381,7 +1410,6 @@ xprt_default_timeout(struct rpc_timeout *to, int proto)
void
xprt_set_timeout
(
struct
rpc_timeout
*
to
,
unsigned
int
retr
,
unsigned
long
incr
)
{
to
->
to_current
=
to
->
to_initval
=
to
->
to_increment
=
incr
;
to
->
to_maxval
=
incr
*
retr
;
...
...
@@ -1446,7 +1474,6 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
/* Set timeout parameters */
if
(
to
)
{
xprt
->
timeout
=
*
to
;
xprt
->
timeout
.
to_current
=
to
->
to_initval
;
}
else
xprt_default_timeout
(
&
xprt
->
timeout
,
xprt
->
prot
);
...
...
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