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
38d7463e
Commit
38d7463e
authored
Sep 12, 2002
by
James Simmons
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linus.bkbits.net/linux-2.5
into maxwell.earthlink.net:/usr/src/linus-2.5
parents
bca102e6
c39f7320
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
516 additions
and
570 deletions
+516
-570
drivers/md/md.c
drivers/md/md.c
+22
-34
drivers/md/multipath.c
drivers/md/multipath.c
+0
-14
drivers/md/raid5.c
drivers/md/raid5.c
+12
-11
fs/lockd/host.c
fs/lockd/host.c
+34
-34
fs/lockd/lockd_syms.c
fs/lockd/lockd_syms.c
+0
-1
fs/lockd/mon.c
fs/lockd/mon.c
+35
-35
fs/lockd/svc.c
fs/lockd/svc.c
+21
-37
fs/lockd/svc4proc.c
fs/lockd/svc4proc.c
+20
-34
fs/lockd/svcproc.c
fs/lockd/svcproc.c
+18
-34
fs/lockd/svcsubs.c
fs/lockd/svcsubs.c
+4
-6
fs/lockd/xdr.c
fs/lockd/xdr.c
+16
-16
fs/lockd/xdr4.c
fs/lockd/xdr4.c
+3
-3
fs/nfsd/export.c
fs/nfsd/export.c
+229
-219
fs/nfsd/lockd.c
fs/nfsd/lockd.c
+8
-15
fs/nfsd/nfsctl.c
fs/nfsd/nfsctl.c
+19
-2
fs/nfsd/nfsfh.c
fs/nfsd/nfsfh.c
+20
-22
fs/nfsd/vfs.c
fs/nfsd/vfs.c
+8
-8
include/linux/lockd/bind.h
include/linux/lockd/bind.h
+0
-5
include/linux/lockd/lockd.h
include/linux/lockd/lockd.h
+5
-3
include/linux/lockd/sm_inter.h
include/linux/lockd/sm_inter.h
+1
-0
include/linux/lockd/xdr.h
include/linux/lockd/xdr.h
+2
-0
include/linux/nfsd/auth.h
include/linux/nfsd/auth.h
+0
-18
include/linux/nfsd/export.h
include/linux/nfsd/export.h
+26
-19
include/linux/nfsd/nfsfh.h
include/linux/nfsd/nfsfh.h
+13
-0
No files found.
drivers/md/md.c
View file @
38d7463e
...
...
@@ -56,11 +56,8 @@
#include <linux/blk.h>
#define DEBUG 0
#if DEBUG
# define dprintk(x...) printk(x)
#else
# define dprintk(x...) do { } while(0)
#endif
#define dprintk(x...) ((void)(DEBUG && printk(x)))
#ifndef MODULE
static
void
autostart_arrays
(
void
);
...
...
@@ -604,18 +601,6 @@ static void export_array(mddev_t *mddev)
mddev
->
raid_disks
=
0
;
}
static
void
free_mddev
(
mddev_t
*
mddev
)
{
if
(
!
mddev
)
{
MD_BUG
();
return
;
}
export_array
(
mddev
);
md_size
[
mdidx
(
mddev
)]
=
0
;
set_capacity
(
disks
[
mdidx
(
mddev
)],
0
);
}
#undef BAD_CSUM
#undef BAD_MAGIC
#undef OUT_OF_MEM
...
...
@@ -1533,7 +1518,6 @@ static int do_md_stop(mddev_t * mddev, int ro)
{
int
err
=
0
;
kdev_t
dev
=
mddev_to_kdev
(
mddev
);
struct
gendisk
*
disk
;
if
(
atomic_read
(
&
mddev
->
active
)
>
1
)
{
printk
(
STILL_IN_USE
,
mdidx
(
mddev
));
...
...
@@ -1582,21 +1566,25 @@ static int do_md_stop(mddev_t * mddev, int ro)
if
(
ro
)
set_device_ro
(
dev
,
1
);
}
disk
=
disks
[
mdidx
(
mddev
)];
disks
[
mdidx
(
mddev
)]
=
NULL
;
if
(
disk
)
{
del_gendisk
(
disk
);
kfree
(
disk
->
major_name
);
kfree
(
disk
);
}
/*
* Free resources if final stop
*/
if
(
!
ro
)
{
struct
gendisk
*
disk
;
printk
(
KERN_INFO
"md: md%d stopped.
\n
"
,
mdidx
(
mddev
));
free_mddev
(
mddev
);
export_array
(
mddev
);
md_size
[
mdidx
(
mddev
)]
=
0
;
disk
=
disks
[
mdidx
(
mddev
)];
disks
[
mdidx
(
mddev
)]
=
NULL
;
if
(
disk
)
{
del_gendisk
(
disk
);
kfree
(
disk
->
major_name
);
kfree
(
disk
);
}
}
else
printk
(
KERN_INFO
"md: md%d switched to read-only mode.
\n
"
,
mdidx
(
mddev
));
err
=
0
;
...
...
@@ -2593,7 +2581,7 @@ static void md_recover_arrays(void)
void
md_error
(
mddev_t
*
mddev
,
mdk_rdev_t
*
rdev
)
{
dprintk
(
"md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).
\n
"
,
MD_MAJOR
,
mdidx
(
mddev
),
MAJOR
(
bdev
->
bd_dev
),
MINOR
(
bdev
->
bd_dev
),
MD_MAJOR
,
mdidx
(
mddev
),
MAJOR
(
rdev
->
bdev
->
bd_dev
),
MINOR
(
rdev
->
bdev
->
bd_dev
),
__builtin_return_address
(
0
),
__builtin_return_address
(
1
),
__builtin_return_address
(
2
),
__builtin_return_address
(
3
));
...
...
@@ -3149,11 +3137,11 @@ request_queue_t * md_queue_proc(kdev_t dev)
{
mddev_t
*
mddev
=
mddev_find
(
minor
(
dev
));
request_queue_t
*
q
=
BLK_DEFAULT_QUEUE
(
MAJOR_NR
);
if
(
!
mddev
||
atomic_read
(
&
mddev
->
active
)
<
2
)
BUG
();
if
(
mddev
->
pers
)
q
=
&
mddev
->
queue
;
mddev_put
(
mddev
);
/* the caller must hold a reference... */
if
(
mddev
)
{
if
(
mddev
->
pers
)
q
=
&
mddev
->
queue
;
mddev_put
(
mddev
)
;
}
return
q
;
}
...
...
drivers/md/multipath.c
View file @
38d7463e
...
...
@@ -37,20 +37,6 @@
#define NR_RESERVED_BUFS 32
/*
* The following can be used to debug the driver
*/
#define MULTIPATH_DEBUG 0
#if MULTIPATH_DEBUG
#define PRINTK(x...) printk(x)
#define inline
#define __inline__
#else
#define PRINTK(x...) do { } while (0)
#endif
static
mdk_personality_t
multipath_personality
;
static
spinlock_t
retry_list_lock
=
SPIN_LOCK_UNLOCKED
;
struct
multipath_bh
*
multipath_retry_list
=
NULL
,
**
multipath_retry_tail
;
...
...
drivers/md/raid5.c
View file @
38d7463e
...
...
@@ -49,12 +49,10 @@
# define CHECK_DEVLOCK()
#endif
#define PRINTK(x...) ((void)(RAID5_DEBUG && printk(x)))
#if RAID5_DEBUG
#define PRINTK(x...) printk(x)
#define inline
#define __inline__
#else
#define PRINTK(x...) do { } while (0)
#endif
static
void
print_raid5_conf
(
raid5_conf_t
*
conf
);
...
...
@@ -933,13 +931,16 @@ static void handle_stripe(struct stripe_head *sh)
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
))
||
(
failed
==
1
&&
failed_num
==
sh
->
pd_idx
))
)
{
/* any written block on an uptodate or failed drive can be returned */
/* any written block on an uptodate or failed drive can be returned.
* Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
* never LOCKED, so we don't need to test 'failed' directly.
*/
for
(
i
=
disks
;
i
--
;
)
if
(
sh
->
dev
[
i
].
written
)
{
dev
=
&
sh
->
dev
[
i
];
if
(
!
test_bit
(
R5_
Insync
,
&
sh
->
dev
[
sh
->
pd_idx
].
flags
)
&&
(
!
test_bit
(
R5_LOCKED
,
&
dev
->
flags
)
&&
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
)
)
)
{
/*
maybe we can return some
write requests */
if
(
!
test_bit
(
R5_
LOCKED
,
&
dev
->
flags
)
&&
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
)
)
{
/*
We can return any
write requests */
struct
bio
*
wbi
,
*
wbi2
;
PRINTK
(
"Return write for disc %d
\n
"
,
i
);
wbi
=
dev
->
written
;
...
...
@@ -1164,7 +1165,7 @@ static void handle_stripe(struct stripe_head *sh)
md_sync_acct
(
rdev
,
STRIPE_SECTORS
);
bi
->
bi_bdev
=
rdev
->
bdev
;
PRINTK
(
"for %ld schedule op %d on disc %d
\n
"
,
sh
->
sector
,
bi
->
bi_rw
,
i
);
PRINTK
(
"for %ld schedule op %
l
d on disc %d
\n
"
,
sh
->
sector
,
bi
->
bi_rw
,
i
);
atomic_inc
(
&
sh
->
count
);
bi
->
bi_sector
=
sh
->
sector
;
bi
->
bi_flags
=
0
;
...
...
@@ -1175,7 +1176,7 @@ static void handle_stripe(struct stripe_head *sh)
bi
->
bi_next
=
NULL
;
generic_make_request
(
bi
);
}
else
{
PRINTK
(
"skip op %d on disc %d for sector %ld
\n
"
,
bi
->
bi_rw
,
i
,
sh
->
sector
);
PRINTK
(
"skip op %
l
d on disc %d for sector %ld
\n
"
,
bi
->
bi_rw
,
i
,
sh
->
sector
);
clear_bit
(
R5_LOCKED
,
&
dev
->
flags
);
set_bit
(
STRIPE_HANDLE
,
&
sh
->
state
);
}
...
...
@@ -1242,8 +1243,8 @@ static int make_request (request_queue_t *q, struct bio * bi)
new_sector
=
raid5_compute_sector
(
logical_sector
,
raid_disks
,
data_disks
,
&
dd_idx
,
&
pd_idx
,
conf
);
PRINTK
(
"raid5: make_request, sector %
ul logical %ul
\n
"
,
new_sector
,
logical_sector
);
PRINTK
(
"raid5: make_request, sector %
Lu logical %Lu
\n
"
,
(
unsigned
long
long
)
new_sector
,
(
unsigned
long
long
)
logical_sector
);
sh
=
get_active_stripe
(
conf
,
new_sector
,
pd_idx
,
(
bi
->
bi_rw
&
RWA_MASK
));
if
(
sh
)
{
...
...
fs/lockd/host.c
View file @
38d7463e
...
...
@@ -22,7 +22,6 @@
#define NLM_HOST_MAX 64
#define NLM_HOST_NRHASH 32
#define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1))
#define NLM_PTRHASH(ptr) ((((u32)(unsigned long) ptr) / 32) & (NLM_HOST_NRHASH-1))
#define NLM_HOST_REBIND (60 * HZ)
#define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
#define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ)
...
...
@@ -42,7 +41,7 @@ static void nlm_gc_hosts(void);
struct
nlm_host
*
nlmclnt_lookup_host
(
struct
sockaddr_in
*
sin
,
int
proto
,
int
version
)
{
return
nlm_lookup_host
(
NULL
,
sin
,
proto
,
version
);
return
nlm_lookup_host
(
0
,
sin
,
proto
,
version
);
}
/*
...
...
@@ -51,45 +50,25 @@ nlmclnt_lookup_host(struct sockaddr_in *sin, int proto, int version)
struct
nlm_host
*
nlmsvc_lookup_host
(
struct
svc_rqst
*
rqstp
)
{
return
nlm_lookup_host
(
rqstp
->
rq_client
,
&
rqstp
->
rq_addr
,
return
nlm_lookup_host
(
1
,
&
rqstp
->
rq_addr
,
rqstp
->
rq_prot
,
rqstp
->
rq_vers
);
}
/*
* Match the given host against client/address
*/
static
inline
int
nlm_match_host
(
struct
nlm_host
*
host
,
struct
svc_client
*
clnt
,
struct
sockaddr_in
*
sin
)
{
if
(
clnt
)
return
host
->
h_exportent
==
clnt
;
return
nlm_cmp_addr
(
&
host
->
h_addr
,
sin
);
}
/*
* Common host lookup routine for server & client
*/
struct
nlm_host
*
nlm_lookup_host
(
struct
svc_client
*
clnt
,
struct
sockaddr_in
*
sin
,
nlm_lookup_host
(
int
server
,
struct
sockaddr_in
*
sin
,
int
proto
,
int
version
)
{
struct
nlm_host
*
host
,
**
hp
;
u32
addr
;
int
hash
;
if
(
!
clnt
&&
!
sin
)
{
printk
(
KERN_NOTICE
"lockd: no clnt or addr in lookup_host!
\n
"
);
return
NULL
;
}
dprintk
(
"lockd: nlm_lookup_host(%08x, p=%d, v=%d)
\n
"
,
(
unsigned
)(
sin
?
ntohl
(
sin
->
sin_addr
.
s_addr
)
:
0
),
proto
,
version
);
if
(
clnt
)
hash
=
NLM_PTRHASH
(
clnt
);
else
hash
=
NLM_ADDRHASH
(
sin
->
sin_addr
.
s_addr
);
hash
=
NLM_ADDRHASH
(
sin
->
sin_addr
.
s_addr
);
/* Lock hash table */
down
(
&
nlm_host_sema
);
...
...
@@ -98,12 +77,14 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
nlm_gc_hosts
();
for
(
hp
=
&
nlm_hosts
[
hash
];
(
host
=
*
hp
);
hp
=
&
host
->
h_next
)
{
if
(
proto
&&
host
->
h_proto
!=
proto
)
if
(
host
->
h_proto
!=
proto
)
continue
;
if
(
host
->
h_version
!=
version
)
continue
;
if
(
version
&&
host
->
h_version
!=
version
)
if
(
host
->
h_server
!=
server
)
continue
;
if
(
nlm_
match_host
(
host
,
clnt
,
sin
))
{
if
(
nlm_
cmp_addr
(
&
host
->
h_addr
,
sin
))
{
if
(
hp
!=
nlm_hosts
+
hash
)
{
*
hp
=
host
->
h_next
;
host
->
h_next
=
nlm_hosts
[
hash
];
...
...
@@ -115,10 +96,6 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
}
}
/* special hack for nlmsvc_invalidate_client */
if
(
sin
==
NULL
)
goto
nohost
;
/* Ooops, no host found, create it */
dprintk
(
"lockd: creating host entry
\n
"
);
...
...
@@ -146,8 +123,7 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
init_waitqueue_head
(
&
host
->
h_gracewait
);
host
->
h_state
=
0
;
/* pseudo NSM state */
host
->
h_nsmstate
=
0
;
/* real NSM state */
host
->
h_exportent
=
clnt
;
host
->
h_server
=
server
;
host
->
h_next
=
nlm_hosts
[
hash
];
nlm_hosts
[
hash
]
=
host
;
...
...
@@ -159,6 +135,30 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
return
host
;
}
struct
nlm_host
*
nlm_find_client
(
void
)
{
/* find a nlm_host for a client for which h_killed == 0.
* and return it
*/
int
hash
;
down
(
&
nlm_host_sema
);
for
(
hash
=
0
;
hash
<
NLM_HOST_NRHASH
;
hash
++
)
{
struct
nlm_host
*
host
,
**
hp
;
for
(
hp
=
&
nlm_hosts
[
hash
];
(
host
=
*
hp
)
;
hp
=
&
host
->
h_next
)
{
if
(
host
->
h_server
&&
host
->
h_killed
==
0
)
{
nlm_get_host
(
host
);
up
(
&
nlm_host_sema
);
return
host
;
}
}
}
up
(
&
nlm_host_sema
);
return
NULL
;
}
/*
* Create the NLM RPC client for an NLM peer
*/
...
...
fs/lockd/lockd_syms.c
View file @
38d7463e
...
...
@@ -32,7 +32,6 @@ EXPORT_SYMBOL(lockd_down);
EXPORT_SYMBOL
(
nlmclnt_proc
);
/* NFS server entry points/hooks */
EXPORT_SYMBOL
(
nlmsvc_invalidate_client
);
EXPORT_SYMBOL
(
nlmsvc_ops
);
#endif
/* CONFIG_MODULES */
fs/lockd/mon.c
View file @
38d7463e
...
...
@@ -42,6 +42,7 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
goto
out
;
args
.
addr
=
host
->
h_addr
.
sin_addr
.
s_addr
;
args
.
proto
=
(
host
->
h_proto
<<
1
)
|
host
->
h_server
;
args
.
prog
=
NLM_PROGRAM
;
args
.
vers
=
host
->
h_version
;
args
.
proc
=
NLMPROC_NSM_NOTIFY
;
...
...
@@ -167,8 +168,8 @@ xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
/* This is the private part. Needed only for SM_MON call */
if
(
rqstp
->
rq_task
->
tk_msg
.
rpc_proc
==
SM_MON
)
{
*
p
++
=
argp
->
addr
;
*
p
++
=
0
;
*
p
++
=
0
;
*
p
++
=
argp
->
vers
;
*
p
++
=
argp
->
proto
;
*
p
++
=
0
;
}
...
...
@@ -206,61 +207,60 @@ xdr_decode_stat(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp)
static
struct
rpc_procinfo
nsm_procedures
[]
=
{
{
p_procname:
"sm_null"
,
p_encode:
(
kxdrproc_t
)
xdr_error
,
p_decode:
(
kxdrproc_t
)
xdr_error
,
.
p_procname
=
"sm_null"
,
.
p_encode
=
(
kxdrproc_t
)
xdr_error
,
.
p_decode
=
(
kxdrproc_t
)
xdr_error
,
},
{
p_procname:
"sm_stat"
,
p_encode:
(
kxdrproc_t
)
xdr_error
,
p_decode:
(
kxdrproc_t
)
xdr_error
,
.
p_procname
=
"sm_stat"
,
.
p_encode
=
(
kxdrproc_t
)
xdr_error
,
.
p_decode
=
(
kxdrproc_t
)
xdr_error
,
},
{
p_procname:
"sm_mon"
,
p_encode:
(
kxdrproc_t
)
xdr_encode_mon
,
p_decode:
(
kxdrproc_t
)
xdr_decode_stat_res
,
p_bufsiz:
MAX
(
SM_mon_sz
,
SM_monres_sz
)
<<
2
,
.
p_procname
=
"sm_mon"
,
.
p_encode
=
(
kxdrproc_t
)
xdr_encode_mon
,
.
p_decode
=
(
kxdrproc_t
)
xdr_decode_stat_res
,
.
p_bufsiz
=
MAX
(
SM_mon_sz
,
SM_monres_sz
)
<<
2
,
},
{
p_procname:
"sm_unmon"
,
p_encode:
(
kxdrproc_t
)
xdr_encode_mon
,
p_decode:
(
kxdrproc_t
)
xdr_decode_stat
,
p_bufsiz:
MAX
(
SM_mon_id_sz
,
SM_unmonres_sz
)
<<
2
,
.
p_procname
=
"sm_unmon"
,
.
p_encode
=
(
kxdrproc_t
)
xdr_encode_mon
,
.
p_decode
=
(
kxdrproc_t
)
xdr_decode_stat
,
.
p_bufsiz
=
MAX
(
SM_mon_id_sz
,
SM_unmonres_sz
)
<<
2
,
},
{
p_procname:
"sm_unmon_all"
,
p_encode:
(
kxdrproc_t
)
xdr_error
,
p_decode:
(
kxdrproc_t
)
xdr_error
,
.
p_procname
=
"sm_unmon_all"
,
.
p_encode
=
(
kxdrproc_t
)
xdr_error
,
.
p_decode
=
(
kxdrproc_t
)
xdr_error
,
},
{
p_procname:
"sm_simu_crash"
,
p_encode:
(
kxdrproc_t
)
xdr_error
,
p_decode:
(
kxdrproc_t
)
xdr_error
,
0
,
0
.
p_procname
=
"sm_simu_crash"
,
.
p_encode
=
(
kxdrproc_t
)
xdr_error
,
.
p_decode
=
(
kxdrproc_t
)
xdr_error
,
},
{
p_procname:
"sm_notify"
,
p_encode:
(
kxdrproc_t
)
xdr_error
,
p_decode:
(
kxdrproc_t
)
xdr_error
,
.
p_procname
=
"sm_notify"
,
.
p_encode
=
(
kxdrproc_t
)
xdr_error
,
.
p_decode
=
(
kxdrproc_t
)
xdr_error
,
},
};
static
struct
rpc_version
nsm_version1
=
{
number:
1
,
nrprocs:
sizeof
(
nsm_procedures
)
/
sizeof
(
nsm_procedures
[
0
]),
procs:
nsm_procedures
.
number
=
1
,
.
nrprocs
=
sizeof
(
nsm_procedures
)
/
sizeof
(
nsm_procedures
[
0
]),
.
procs
=
nsm_procedures
};
static
struct
rpc_version
*
nsm_version
[]
=
{
NULL
,
&
nsm_version1
,
[
1
]
=
&
nsm_version1
,
};
static
struct
rpc_stat
nsm_stats
;
struct
rpc_program
nsm_program
=
{
name:
"statd"
,
number:
SM_PROGRAM
,
nrvers:
sizeof
(
nsm_version
)
/
sizeof
(
nsm_version
[
0
]),
version:
nsm_version
,
stats:
&
nsm_stats
.
name
=
"statd"
,
.
number
=
SM_PROGRAM
,
.
nrvers
=
sizeof
(
nsm_version
)
/
sizeof
(
nsm_version
[
0
]),
.
version
=
nsm_version
,
.
stats
=
&
nsm_stats
};
fs/lockd/svc.c
View file @
38d7463e
...
...
@@ -130,7 +130,7 @@ lockd(struct svc_rqst *rqstp)
flush_signals
(
current
);
spin_unlock_irq
(
&
current
->
sigmask_lock
);
if
(
nlmsvc_ops
)
{
nlmsvc_
ops
->
detach
();
nlmsvc_
invalidate_all
();
grace_period_expire
=
set_grace_period
();
}
}
...
...
@@ -163,22 +163,8 @@ lockd(struct svc_rqst *rqstp)
dprintk
(
"lockd: request from %08x
\n
"
,
(
unsigned
)
ntohl
(
rqstp
->
rq_addr
.
sin_addr
.
s_addr
));
/*
* Look up the NFS client handle. The handle is needed for
* all but the GRANTED callback RPCs.
*/
rqstp
->
rq_client
=
NULL
;
if
(
nlmsvc_ops
)
{
nlmsvc_ops
->
exp_readlock
();
rqstp
->
rq_client
=
nlmsvc_ops
->
exp_getclient
(
&
rqstp
->
rq_addr
);
}
svc_process
(
serv
,
rqstp
);
/* Unlock export hash tables */
if
(
nlmsvc_ops
)
nlmsvc_ops
->
exp_unlock
();
}
/*
...
...
@@ -187,7 +173,7 @@ lockd(struct svc_rqst *rqstp)
*/
if
(
!
nlmsvc_pid
||
current
->
pid
==
nlmsvc_pid
)
{
if
(
nlmsvc_ops
)
nlmsvc_
ops
->
detach
();
nlmsvc_
invalidate_all
();
nlm_shutdown_hosts
();
nlmsvc_pid
=
0
;
}
else
...
...
@@ -369,29 +355,27 @@ __setup("lockd.tcpport=", tcpport_set);
* Define NLM program and procedures
*/
static
struct
svc_version
nlmsvc_version1
=
{
vs_vers:
1
,
vs_nproc:
17
,
vs_proc:
nlmsvc_procedures
,
.
vs_vers
=
1
,
.
vs_nproc
=
17
,
.
vs_proc
=
nlmsvc_procedures
,
};
static
struct
svc_version
nlmsvc_version3
=
{
vs_vers:
3
,
vs_nproc:
24
,
vs_proc:
nlmsvc_procedures
,
.
vs_vers
=
3
,
.
vs_nproc
=
24
,
.
vs_proc
=
nlmsvc_procedures
,
};
#ifdef CONFIG_LOCKD_V4
static
struct
svc_version
nlmsvc_version4
=
{
vs_vers:
4
,
vs_nproc:
24
,
vs_proc:
nlmsvc_procedures4
,
.
vs_vers
=
4
,
.
vs_nproc
=
24
,
.
vs_proc
=
nlmsvc_procedures4
,
};
#endif
static
struct
svc_version
*
nlmsvc_version
[]
=
{
NULL
,
&
nlmsvc_version1
,
NULL
,
&
nlmsvc_version3
,
[
1
]
=
&
nlmsvc_version1
,
[
3
]
=
&
nlmsvc_version3
,
#ifdef CONFIG_LOCKD_V4
&
nlmsvc_version4
,
[
4
]
=
&
nlmsvc_version4
,
#endif
};
...
...
@@ -399,11 +383,11 @@ static struct svc_stat nlmsvc_stats;
#define NLM_NRVERS (sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
struct
svc_program
nlmsvc_program
=
{
pg_prog:
NLM_PROGRAM
,
/* program number */
pg_lovers:
1
,
// version
pg_hivers:
NLM_NRVERS
-
1
,
// range
pg_nvers:
NLM_NRVERS
,
/* number of entries in nlmsvc_version */
pg_vers:
nlmsvc_version
,
/* version table */
pg_name:
"lockd"
,
/* service name */
pg_stats:
&
nlmsvc_stats
,
/* stats table */
.
pg_prog
=
NLM_PROGRAM
,
/* program number */
.
pg_lovers
=
1
,
/* version */
.
pg_hivers
=
NLM_NRVERS
-
1
,
/* range */
.
pg_nvers
=
NLM_NRVERS
,
/* number of entries in nlmsvc_version */
.
pg_vers
=
nlmsvc_version
,
/* version table */
.
pg_name
=
"lockd"
,
/* service name */
.
pg_stats
=
&
nlmsvc_stats
,
/* stats table */
};
fs/lockd/svc4proc.c
View file @
38d7463e
...
...
@@ -40,15 +40,6 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
if
(
!
nlmsvc_ops
)
return
nlm_lck_denied_nolocks
;
/* Obtain handle for client host */
if
(
rqstp
->
rq_client
==
NULL
)
{
printk
(
KERN_NOTICE
"lockd: unauthenticated request from (%08x:%d)
\n
"
,
ntohl
(
rqstp
->
rq_addr
.
sin_addr
.
s_addr
),
ntohs
(
rqstp
->
rq_addr
.
sin_port
));
return
nlm_lck_denied_nolocks
;
}
/* Obtain host handle */
if
(
!
(
host
=
nlmsvc_lookup_host
(
rqstp
))
||
(
argp
->
monitor
&&
!
host
->
h_monitored
&&
nsm_monitor
(
host
)
<
0
))
...
...
@@ -420,8 +411,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void
*
resp
)
{
struct
sockaddr_in
saddr
=
rqstp
->
rq_addr
;
int
vers
=
rqstp
->
rq_vers
;
int
prot
=
rqstp
->
rq_prot
;
int
vers
=
argp
->
vers
;
int
prot
=
argp
->
proto
>>
1
;
struct
nlm_host
*
host
;
dprintk
(
"lockd: SM_NOTIFY called
\n
"
);
...
...
@@ -438,24 +430,20 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
* reclaim all locks we hold on this server.
*/
saddr
.
sin_addr
.
s_addr
=
argp
->
addr
;
if
((
host
=
nlmclnt_lookup_host
(
&
saddr
,
prot
,
vers
))
!=
NULL
)
{
nlmclnt_recovery
(
host
,
argp
->
state
);
nlm_release_host
(
host
);
}
/* If we run on an NFS server, delete all locks held by the client */
if
(
nlmsvc_ops
!=
NULL
)
{
struct
svc_client
*
clnt
;
saddr
.
sin_addr
.
s_addr
=
argp
->
addr
;
nlmsvc_ops
->
exp_readlock
();
if
((
clnt
=
nlmsvc_ops
->
exp_getclient
(
&
saddr
))
!=
NULL
&&
(
host
=
nlm_lookup_host
(
clnt
,
&
saddr
,
0
,
0
))
!=
NULL
)
{
if
((
argp
->
proto
&
1
)
==
0
)
{
if
((
host
=
nlmclnt_lookup_host
(
&
saddr
,
prot
,
vers
))
!=
NULL
)
{
nlmclnt_recovery
(
host
,
argp
->
state
);
nlm_release_host
(
host
);
}
}
else
{
/* If we run on an NFS server, delete all locks held by the client */
if
((
host
=
nlm_lookup_host
(
1
,
&
saddr
,
prot
,
vers
))
!=
NULL
)
{
nlmsvc_free_host_resources
(
host
);
nlm_release_host
(
host
);
}
nlm_release_host
(
host
);
nlmsvc_ops
->
exp_unlock
();
}
return
rpc_success
;
}
...
...
@@ -527,15 +515,13 @@ nlm4svc_callback_exit(struct rpc_task *task)
struct
nlm_void
{
int
dummy
;
};
#define PROC(name, xargt, xrest, argt, rest, respsize) \
{ (svc_procfunc) nlm4svc_proc_##name, \
(kxdrproc_t) nlm4svc_decode_##xargt, \
(kxdrproc_t) nlm4svc_encode_##xrest, \
NULL, \
sizeof(struct nlm_##argt), \
sizeof(struct nlm_##rest), \
0, \
0, \
respsize, \
{ .pc_func = (svc_procfunc) nlm4svc_proc_##name, \
.pc_decode = (kxdrproc_t) nlm4svc_decode_##xargt, \
.pc_encode = (kxdrproc_t) nlm4svc_encode_##xrest, \
.pc_release = NULL, \
.pc_argsize = sizeof(struct nlm_##argt), \
.pc_ressize = sizeof(struct nlm_##rest), \
.pc_xdrressize = respsize, \
}
#define Ck (1+8)
/* cookie */
#define No (1+1024/4)
/* netobj */
...
...
fs/lockd/svcproc.c
View file @
38d7463e
...
...
@@ -69,15 +69,6 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
if
(
!
nlmsvc_ops
)
return
nlm_lck_denied_nolocks
;
/* Obtain handle for client host */
if
(
rqstp
->
rq_client
==
NULL
)
{
printk
(
KERN_NOTICE
"lockd: unauthenticated request from (%08x:%d)
\n
"
,
ntohl
(
rqstp
->
rq_addr
.
sin_addr
.
s_addr
),
ntohs
(
rqstp
->
rq_addr
.
sin_port
));
return
nlm_lck_denied_nolocks
;
}
/* Obtain host handle */
if
(
!
(
host
=
nlmsvc_lookup_host
(
rqstp
))
||
(
argp
->
monitor
&&
!
host
->
h_monitored
&&
nsm_monitor
(
host
)
<
0
))
...
...
@@ -448,8 +439,8 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void
*
resp
)
{
struct
sockaddr_in
saddr
=
rqstp
->
rq_addr
;
int
vers
=
rqstp
->
rq_
vers
;
int
prot
=
rqstp
->
rq_prot
;
int
vers
=
argp
->
vers
;
int
prot
=
argp
->
proto
>>
1
;
struct
nlm_host
*
host
;
dprintk
(
"lockd: SM_NOTIFY called
\n
"
);
...
...
@@ -466,22 +457,17 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
* reclaim all locks we hold on this server.
*/
saddr
.
sin_addr
.
s_addr
=
argp
->
addr
;
if
((
host
=
nlmclnt_lookup_host
(
&
saddr
,
prot
,
vers
))
!=
NULL
)
{
nlmclnt_recovery
(
host
,
argp
->
state
);
nlm_release_host
(
host
);
}
/* If we run on an NFS server, delete all locks held by the client */
if
(
nlmsvc_ops
!=
NULL
)
{
struct
svc_client
*
clnt
;
saddr
.
sin_addr
.
s_addr
=
argp
->
addr
;
nlmsvc_ops
->
exp_readlock
();
if
((
clnt
=
nlmsvc_ops
->
exp_getclient
(
&
saddr
))
!=
NULL
&&
(
host
=
nlm_lookup_host
(
clnt
,
&
saddr
,
0
,
0
))
!=
NULL
)
{
if
((
argp
->
proto
&
1
)
==
0
)
{
if
((
host
=
nlmclnt_lookup_host
(
&
saddr
,
prot
,
vers
))
!=
NULL
)
{
nlmclnt_recovery
(
host
,
argp
->
state
);
nlm_release_host
(
host
);
}
}
else
{
/* If we run on an NFS server, delete all locks held by the client */
if
((
host
=
nlm_lookup_host
(
1
,
&
saddr
,
prot
,
vers
))
!=
NULL
)
{
nlmsvc_free_host_resources
(
host
);
nlm_release_host
(
host
);
}
nlm_release_host
(
host
);
nlmsvc_ops
->
exp_unlock
();
}
return
rpc_success
;
...
...
@@ -555,15 +541,13 @@ nlmsvc_callback_exit(struct rpc_task *task)
struct
nlm_void
{
int
dummy
;
};
#define PROC(name, xargt, xrest, argt, rest, respsize) \
{ (svc_procfunc) nlmsvc_proc_##name, \
(kxdrproc_t) nlmsvc_decode_##xargt, \
(kxdrproc_t) nlmsvc_encode_##xrest, \
NULL, \
sizeof(struct nlm_##argt), \
sizeof(struct nlm_##rest), \
0, \
0, \
respsize, \
{ .pc_func = (svc_procfunc) nlmsvc_proc_##name, \
.pc_decode = (kxdrproc_t) nlmsvc_decode_##xargt, \
.pc_encode = (kxdrproc_t) nlmsvc_encode_##xrest, \
.pc_release = NULL, \
.pc_argsize = sizeof(struct nlm_##argt), \
.pc_ressize = sizeof(struct nlm_##rest), \
.pc_xdrressize = respsize, \
}
#define Ck (1+8)
/* cookie */
...
...
fs/lockd/svcsubs.c
View file @
38d7463e
...
...
@@ -294,15 +294,13 @@ nlmsvc_free_host_resources(struct nlm_host *host)
}
/*
*
Delete a client when the nfsd entry is removed.
*
delete all hosts structs for clients
*/
void
nlmsvc_invalidate_
client
(
struct
svc_client
*
clnt
)
nlmsvc_invalidate_
all
(
void
)
{
struct
nlm_host
*
host
;
if
((
host
=
nlm_lookup_host
(
clnt
,
NULL
,
0
,
0
))
!=
NULL
)
{
dprintk
(
"lockd: invalidating client for %s
\n
"
,
host
->
h_name
);
struct
nlm_host
*
host
;
while
((
host
=
nlm_find_client
())
!=
NULL
)
{
nlmsvc_free_host_resources
(
host
);
host
->
h_expires
=
0
;
host
->
h_killed
=
1
;
...
...
fs/lockd/xdr.c
View file @
38d7463e
...
...
@@ -369,6 +369,8 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
argp
->
state
=
ntohl
(
*
p
++
);
/* Preserve the address in network byte order */
argp
->
addr
=
*
p
++
;
argp
->
vers
=
*
p
++
;
argp
->
proto
=
*
p
++
;
return
xdr_argsize_check
(
rqstp
,
p
);
}
...
...
@@ -602,15 +604,15 @@ static struct rpc_procinfo nlm_procedures[] = {
};
static
struct
rpc_version
nlm_version1
=
{
number:
1
,
nrprocs:
16
,
procs:
nlm_procedures
,
.
number
=
1
,
.
nrprocs
=
16
,
.
procs
=
nlm_procedures
,
};
static
struct
rpc_version
nlm_version3
=
{
number:
3
,
nrprocs:
24
,
procs:
nlm_procedures
,
.
number
=
3
,
.
nrprocs
=
24
,
.
procs
=
nlm_procedures
,
};
#ifdef CONFIG_LOCKD_V4
...
...
@@ -618,23 +620,21 @@ extern struct rpc_version nlm_version4;
#endif
static
struct
rpc_version
*
nlm_versions
[]
=
{
NULL
,
&
nlm_version1
,
NULL
,
&
nlm_version3
,
[
1
]
=
&
nlm_version1
,
[
3
]
=
&
nlm_version3
,
#ifdef CONFIG_LOCKD_V4
&
nlm_version4
,
[
4
]
=
&
nlm_version4
,
#endif
};
static
struct
rpc_stat
nlm_stats
;
struct
rpc_program
nlm_program
=
{
name:
"lockd"
,
number:
NLM_PROGRAM
,
nrvers:
sizeof
(
nlm_versions
)
/
sizeof
(
nlm_versions
[
0
]),
version:
nlm_versions
,
stats:
&
nlm_stats
,
.
name
=
"lockd"
,
.
number
=
NLM_PROGRAM
,
.
nrvers
=
sizeof
(
nlm_versions
)
/
sizeof
(
nlm_versions
[
0
]),
.
version
=
nlm_versions
,
.
stats
=
&
nlm_stats
,
};
#ifdef LOCKD_DEBUG
...
...
fs/lockd/xdr4.c
View file @
38d7463e
...
...
@@ -608,7 +608,7 @@ static struct rpc_procinfo nlm4_procedures[] = {
};
struct
rpc_version
nlm_version4
=
{
number:
4
,
nrprocs:
24
,
procs:
nlm4_procedures
,
.
number
=
4
,
.
nrprocs
=
24
,
.
procs
=
nlm4_procedures
,
};
fs/nfsd/export.c
View file @
38d7463e
...
...
@@ -35,10 +35,6 @@
typedef
struct
svc_client
svc_client
;
typedef
struct
svc_export
svc_export
;
static
svc_export
*
exp_parent
(
svc_client
*
clp
,
struct
super_block
*
sb
,
struct
dentry
*
dentry
);
static
svc_export
*
exp_child
(
svc_client
*
clp
,
struct
super_block
*
sb
,
struct
dentry
*
dentry
);
static
void
exp_unexport_all
(
svc_client
*
clp
);
static
void
exp_do_unexport
(
svc_export
*
unexp
);
static
svc_client
*
exp_getclientbyname
(
char
*
name
);
...
...
@@ -51,9 +47,25 @@ static int exp_verify_string(char *cp, int max);
#define CLIENT_HASHMASK (CLIENT_HASHMAX - 1)
#define CLIENT_HASH(a) \
((((a)>>24) ^ ((a)>>16) ^ ((a)>>8) ^(a)) & CLIENT_HASHMASK)
/* XXX: is this adequate for 32bit kdev_t ? */
#define EXPORT_HASH(dev) (MINOR(dev) & (NFSCLNT_EXPMAX - 1))
#define EXPORT_FSID_HASH(fsid) ((fsid) & (NFSCLNT_EXPMAX - 1))
#define EXPKEY_HASHBITS 8
#define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
static
struct
list_head
expkey_table
[
EXPKEY_HASHMAX
];
static
inline
int
expkey_hash
(
struct
svc_client
*
clp
,
int
type
,
u32
*
fsidv
)
{
int
hash
=
type
;
char
*
cp
=
(
char
*
)
fsidv
;
int
len
=
(
type
==
0
)
?
8
:
4
;
while
(
len
--
)
hash
+=
*
cp
++
;
cp
=
(
char
*
)
&
clp
;
len
=
sizeof
(
clp
);
while
(
len
--
)
hash
+=
*
cp
++
;
return
hash
&
EXPKEY_HASHMASK
;
}
struct
svc_clnthash
{
struct
svc_clnthash
*
h_next
;
...
...
@@ -63,123 +75,131 @@ struct svc_clnthash {
static
struct
svc_clnthash
*
clnt_hash
[
CLIENT_HASHMAX
];
static
svc_client
*
clients
;
/* hash table of exports indexed by dentry+client */
#define EXPORT_HASHBITS 8
#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
#define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
/*
* Find the client's export entry matching xdev/xino.
*/
svc_export
*
exp_get
(
svc_client
*
clp
,
dev_t
dev
,
ino_t
ino
)
struct
list_head
export_table
[
EXPORT_HASHMAX
];
static
int
export_hash
(
svc_client
*
clp
,
struct
dentry
*
dentry
)
{
void
*
k
[
2
];
unsigned
char
*
cp
;
int
rv
,
i
;
k
[
0
]
=
clp
;
k
[
1
]
=
dentry
;
cp
=
(
char
*
)
k
;
rv
=
0
;
for
(
i
=
0
;
i
<
sizeof
(
k
);
i
++
)
rv
^=
cp
[
i
];
return
rv
&
EXPORT_HASHMASK
;
}
struct
svc_expkey
*
exp_find_key
(
svc_client
*
clp
,
int
fsid_type
,
u32
*
fsidv
)
{
struct
list_head
*
head
,
*
p
;
struct
list_head
*
head
;
struct
svc_expkey
*
ek
;
if
(
!
clp
)
return
NULL
;
head
=
&
clp
->
cl_export
[
EXPORT_HASH
(
dev
)];
list_for_each
(
p
,
head
)
{
svc_export
*
exp
=
list_entry
(
p
,
svc_export
,
ex_hash
);
if
(
exp
->
ex_ino
==
ino
&&
exp
->
ex_dev
==
dev
)
return
exp
;
}
head
=
&
expkey_table
[
expkey_hash
(
clp
,
fsid_type
,
fsidv
)];
list_for_each_entry
(
ek
,
head
,
ek_hash
)
if
(
ek
->
ek_fsidtype
==
fsid_type
&&
fsidv
[
0
]
==
ek
->
ek_fsid
[
0
]
&&
(
fsid_type
==
1
||
fsidv
[
1
]
==
ek
->
ek_fsid
[
1
])
&&
clp
==
ek
->
ek_client
)
return
ek
;
return
NULL
;
}
/*
* Find the client's export entry matching
fsid
* Find the client's export entry matching
xdev/xino.
*/
s
vc_export
*
exp_get_
fsid
(
svc_client
*
clp
,
int
fsid
)
s
tatic
inline
struct
svc_expkey
*
exp_get_
key
(
svc_client
*
clp
,
dev_t
dev
,
ino_t
ino
)
{
struct
list_head
*
head
,
*
p
;
u32
fsidv
[
2
];
mk_fsid_v0
(
fsidv
,
dev
,
ino
);
return
exp_find_key
(
clp
,
0
,
fsidv
);
}
static
inline
svc_export
*
exp_get
(
svc_client
*
clp
,
dev_t
dev
,
ino_t
ino
)
{
struct
svc_expkey
*
ek
;
if
(
!
clp
)
ek
=
exp_get_key
(
clp
,
dev
,
ino
);
if
(
ek
)
return
ek
->
ek_export
;
else
return
NULL
;
}
head
=
&
clp
->
cl_expfsid
[
EXPORT_FSID_HASH
(
fsid
)];
list_for_each
(
p
,
head
)
{
svc_export
*
exp
=
list_entry
(
p
,
svc_export
,
ex_fsid_hash
);
if
(
exp
->
ex_fsid
==
fsid
)
return
exp
;
}
return
NULL
;
/*
* Find the client's export entry matching fsid
*/
static
inline
struct
svc_expkey
*
exp_get_fsid_key
(
svc_client
*
clp
,
int
fsid
)
{
u32
fsidv
[
2
];
mk_fsid_v1
(
fsidv
,
fsid
);
return
exp_find_key
(
clp
,
1
,
fsidv
);
}
svc_export
*
exp_get_
by_name
(
svc_client
*
clp
,
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
)
s
tatic
inline
s
vc_export
*
exp_get_
fsid
(
svc_client
*
clp
,
int
fsid
)
{
struct
list_head
*
head
,
*
p
;
int
hash
=
EXPORT_HASH
(
mnt
->
mnt_sb
->
s_dev
);
struct
svc_expkey
*
ek
;
if
(
!
clp
)
ek
=
exp_get_fsid_key
(
clp
,
fsid
);
if
(
ek
)
return
ek
->
ek_export
;
else
return
NULL
;
head
=
&
clp
->
cl_export
[
hash
];
list_for_each
(
p
,
head
)
{
svc_export
*
exp
=
list_entry
(
p
,
svc_export
,
ex_hash
);
if
(
exp
->
ex_dentry
==
dentry
&&
exp
->
ex_mnt
==
mnt
)
break
;
}
return
NULL
;
}
/*
* Find the export entry for a given dentry. <gam3@acm.org>
*/
static
svc_export
*
exp_parent
(
svc_client
*
clp
,
struct
super_block
*
sb
,
struct
dentry
*
dentry
)
svc_export
*
exp_get_by_name
(
svc_client
*
clp
,
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
)
{
struct
list_head
*
head
=
&
clp
->
cl_export
[
EXPORT_HASH
(
sb
->
s_dev
)];
struct
list_head
*
p
;
svc_export
*
exp
;
struct
list_head
*
head
=
&
export_table
[
export_hash
(
clp
,
dentry
)];
if
(
!
clp
)
return
NULL
;
spin_lock
(
&
dcache_lock
);
list_for_each
(
p
,
head
)
{
svc_export
*
exp
=
list_entry
(
p
,
svc_export
,
ex_hash
);
if
(
is_subdir
(
dentry
,
exp
->
ex_dentry
))
{
spin_unlock
(
&
dcache_lock
);
list_for_each_entry
(
exp
,
head
,
ex_hash
)
{
if
(
exp
->
ex_dentry
==
dentry
&&
exp
->
ex_mnt
==
mnt
&&
exp
->
ex_client
==
clp
)
return
exp
;
}
}
spin_unlock
(
&
dcache_lock
);
return
NULL
;
}
/*
* Find the child export entry for a given fs. This function is used
* only by the export syscall to keep the export tree consistent.
* <gam3@acm.org>
* Find the export entry for a given dentry.
*/
static
svc_export
*
exp_child
(
svc_client
*
clp
,
struct
super_block
*
sb
,
struct
dentry
*
dentry
)
{
struct
list_head
*
head
=
&
clp
->
cl_export
[
EXPORT_HASH
(
sb
->
s_dev
)];
struct
list_head
*
p
;
struct
dentry
*
ndentry
;
spin_lock
(
&
dcache_lock
);
list_for_each
(
p
,
head
)
{
svc_export
*
exp
=
list_entry
(
p
,
svc_export
,
ex_hash
);
ndentry
=
exp
->
ex_dentry
;
if
(
ndentry
&&
is_subdir
(
ndentry
->
d_parent
,
dentry
))
{
spin_unlock
(
&
dcache_lock
);
return
exp
;
}
}
spin_unlock
(
&
dcache_lock
);
return
NULL
;
}
/* Update parent pointers of all exports */
static
void
exp_change_parents
(
svc_client
*
clp
,
svc_export
*
old
,
svc_export
*
new
)
struct
svc_export
*
exp_parent
(
svc_client
*
clp
,
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
)
{
struct
list_head
*
head
=
&
clp
->
cl_list
;
struct
list_head
*
p
;
svc_export
*
exp
;
list_for_each
(
p
,
head
)
{
svc_export
*
exp
=
list_entry
(
p
,
svc_export
,
ex_list
);
if
(
exp
->
ex_parent
==
old
)
exp
->
ex_parent
=
new
;
read_lock
(
&
dparent_lock
);
exp
=
exp_get_by_name
(
clp
,
mnt
,
dentry
);
while
(
exp
==
NULL
&&
dentry
!=
dentry
->
d_parent
)
{
dentry
=
dentry
->
d_parent
;
exp
=
exp_get_by_name
(
clp
,
mnt
,
dentry
);
}
read_unlock
(
&
dparent_lock
);
return
exp
;
}
/*
...
...
@@ -217,23 +237,75 @@ exp_writeunlock(void)
static
void
exp_fsid_unhash
(
struct
svc_export
*
exp
)
{
struct
svc_expkey
*
ek
;
if
((
exp
->
ex_flags
&
NFSEXP_FSID
)
==
0
)
return
;
list_del_init
(
&
exp
->
ex_fsid_hash
);
ek
=
exp_get_fsid_key
(
exp
->
ex_client
,
exp
->
ex_fsid
);
if
(
ek
)
{
list_del
(
&
ek
->
ek_hash
);
kfree
(
ek
);
}
}
static
void
exp_fsid_hash
(
struct
svc_client
*
clp
,
struct
svc_export
*
exp
)
static
int
exp_fsid_hash
(
struct
svc_client
*
clp
,
struct
svc_export
*
exp
)
{
struct
list_head
*
head
;
struct
svc_expkey
*
ek
;
if
((
exp
->
ex_flags
&
NFSEXP_FSID
)
==
0
)
return
;
head
=
clp
->
cl_expfsid
+
EXPORT_FSID_HASH
(
exp
->
ex_fsid
);
list_add
(
&
exp
->
ex_fsid_hash
,
head
);
return
0
;
ek
=
kmalloc
(
sizeof
(
*
ek
),
GFP_KERNEL
);
if
(
ek
==
NULL
)
return
-
ENOMEM
;
ek
->
ek_fsidtype
=
1
;
ek
->
ek_export
=
exp
;
ek
->
ek_client
=
clp
;
mk_fsid_v1
(
ek
->
ek_fsid
,
exp
->
ex_fsid
);
head
=
&
expkey_table
[
expkey_hash
(
clp
,
1
,
ek
->
ek_fsid
)];
list_add
(
&
ek
->
ek_hash
,
head
);
return
0
;
}
static
int
exp_hash
(
struct
svc_client
*
clp
,
struct
svc_export
*
exp
)
{
struct
list_head
*
head
;
struct
svc_expkey
*
ek
;
struct
inode
*
inode
;
ek
=
kmalloc
(
sizeof
(
*
ek
),
GFP_KERNEL
);
if
(
ek
==
NULL
)
return
-
ENOMEM
;
ek
->
ek_fsidtype
=
0
;
ek
->
ek_export
=
exp
;
ek
->
ek_client
=
clp
;
inode
=
exp
->
ex_dentry
->
d_inode
;
mk_fsid_v0
(
ek
->
ek_fsid
,
inode
->
i_sb
->
s_dev
,
inode
->
i_ino
);
head
=
&
expkey_table
[
expkey_hash
(
clp
,
0
,
ek
->
ek_fsid
)];
list_add
(
&
ek
->
ek_hash
,
head
);
return
0
;
}
static
void
exp_unhash
(
struct
svc_export
*
exp
)
{
struct
svc_expkey
*
ek
;
struct
inode
*
inode
=
exp
->
ex_dentry
->
d_inode
;
ek
=
exp_get_key
(
exp
->
ex_client
,
inode
->
i_sb
->
s_dev
,
inode
->
i_ino
);
if
(
ek
)
{
list_del
(
&
ek
->
ek_hash
);
kfree
(
ek
);
}
}
extern
struct
dentry
*
find_exported_dentry
(
struct
super_block
*
sb
,
void
*
obj
,
void
*
parent
,
int
(
*
acceptable
)(
void
*
context
,
struct
dentry
*
de
),
...
...
@@ -245,13 +317,11 @@ int
exp_export
(
struct
nfsctl_export
*
nxp
)
{
svc_client
*
clp
;
svc_export
*
exp
=
NULL
,
*
parent
;
svc_export
*
exp
=
NULL
;
svc_export
*
fsid_exp
;
struct
nameidata
nd
;
struct
inode
*
inode
=
NULL
;
int
err
;
dev_t
dev
;
ino_t
ino
;
/* Consistency check */
err
=
-
EINVAL
;
...
...
@@ -276,11 +346,9 @@ exp_export(struct nfsctl_export *nxp)
if
(
err
)
goto
out_unlock
;
inode
=
nd
.
dentry
->
d_inode
;
dev
=
inode
->
i_sb
->
s_dev
;
ino
=
inode
->
i_ino
;
err
=
-
EINVAL
;
exp
=
exp_get
(
clp
,
dev
,
ino
);
exp
=
exp_get
_by_name
(
clp
,
nd
.
mnt
,
nd
.
dentry
);
/* must make sure there wont be an ex_fsid clash */
if
((
nxp
->
ex_flags
&
NFSEXP_FSID
)
&&
...
...
@@ -296,8 +364,8 @@ exp_export(struct nfsctl_export *nxp)
exp
->
ex_anon_uid
=
nxp
->
ex_anon_uid
;
exp
->
ex_anon_gid
=
nxp
->
ex_anon_gid
;
exp
->
ex_fsid
=
nxp
->
ex_dev
;
exp_fsid_hash
(
clp
,
exp
);
err
=
0
;
err
=
exp_fsid_hash
(
clp
,
exp
)
;
goto
finish
;
}
...
...
@@ -332,45 +400,30 @@ exp_export(struct nfsctl_export *nxp)
inode
->
i_sb
->
s_export_op
->
find_exported_dentry
=
find_exported_dentry
;
if
((
parent
=
exp_child
(
clp
,
inode
->
i_sb
,
nd
.
dentry
))
!=
NULL
)
{
dprintk
(
"exp_export: export not valid (Rule 3).
\n
"
);
goto
finish
;
}
/* Is this is a sub-export, must be a proper subset of FS */
if
((
parent
=
exp_parent
(
clp
,
inode
->
i_sb
,
nd
.
dentry
))
!=
NULL
)
{
dprintk
(
"exp_export: sub-export not valid (Rule 2).
\n
"
);
goto
finish
;
}
err
=
-
ENOMEM
;
if
(
!
(
exp
=
kmalloc
(
sizeof
(
*
exp
),
GFP_USER
)))
goto
finish
;
dprintk
(
"nfsd: created export entry %p for client %p
\n
"
,
exp
,
clp
);
strcpy
(
exp
->
ex_path
,
nxp
->
ex_path
);
exp
->
ex_client
=
clp
;
exp
->
ex_parent
=
parent
;
exp
->
ex_mnt
=
mntget
(
nd
.
mnt
);
exp
->
ex_dentry
=
dget
(
nd
.
dentry
);
exp
->
ex_flags
=
nxp
->
ex_flags
;
exp
->
ex_dev
=
dev
;
exp
->
ex_ino
=
ino
;
exp
->
ex_anon_uid
=
nxp
->
ex_anon_uid
;
exp
->
ex_anon_gid
=
nxp
->
ex_anon_gid
;
exp
->
ex_fsid
=
nxp
->
ex_dev
;
/* Update parent pointers of all exports */
if
(
parent
)
exp_change_parents
(
clp
,
parent
,
exp
);
list_add
(
&
exp
->
ex_hash
,
clp
->
cl_export
+
EXPORT_HASH
(
dev
));
list_add_tail
(
&
exp
->
ex_list
,
&
clp
->
cl_list
);
exp_fsid_hash
(
clp
,
exp
);
list_add_tail
(
&
exp
->
ex_hash
,
&
export_table
[
export_hash
(
clp
,
nd
.
dentry
)]);
err
=
0
;
if
(
exp_hash
(
clp
,
exp
)
||
exp_fsid_hash
(
clp
,
exp
))
{
/* failed to create at least one index */
exp_do_unexport
(
exp
);
err
=
-
ENOMEM
;
}
finish:
path_release
(
&
nd
);
out_unlock:
...
...
@@ -390,16 +443,12 @@ exp_do_unexport(svc_export *unexp)
struct
vfsmount
*
mnt
;
struct
inode
*
inode
;
list_del
(
&
unexp
->
ex_list
);
list_del
(
&
unexp
->
ex_hash
);
exp_unhash
(
unexp
);
exp_fsid_unhash
(
unexp
);
/* Update parent pointers. */
exp_change_parents
(
unexp
->
ex_client
,
unexp
,
unexp
->
ex_parent
);
dentry
=
unexp
->
ex_dentry
;
mnt
=
unexp
->
ex_mnt
;
inode
=
dentry
->
d_inode
;
if
(
unexp
->
ex_dev
!=
inode
->
i_sb
->
s_dev
||
unexp
->
ex_ino
!=
inode
->
i_ino
)
printk
(
KERN_WARNING
"nfsd: bad dentry in unexport!
\n
"
);
dput
(
dentry
);
mntput
(
mnt
);
...
...
@@ -412,14 +461,17 @@ exp_do_unexport(svc_export *unexp)
static
void
exp_unexport_all
(
svc_client
*
clp
)
{
struct
list_head
*
p
=
&
clp
->
cl_list
;
struct
list_head
*
lp
,
*
tmp
;
int
index
;
dprintk
(
"unexporting all fs's for clnt %p
\n
"
,
clp
);
while
(
!
list_empty
(
p
))
{
svc_export
*
exp
=
list_entry
(
p
->
next
,
svc_export
,
ex_list
);
exp_do_unexport
(
exp
);
}
for
(
index
=
0
;
index
<
EXPORT_HASHMAX
;
index
++
)
list_for_each_safe
(
lp
,
tmp
,
&
export_table
[
index
])
{
svc_export
*
exp
=
list_entry
(
lp
,
struct
svc_export
,
ex_hash
);
if
(
exp
->
ex_client
==
clp
)
exp_do_unexport
(
exp
);
}
}
/*
...
...
@@ -476,7 +528,7 @@ exp_rootfh(struct svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
dprintk
(
"nfsd: exp_rootfh(%s [%p] %s:%s/%ld)
\n
"
,
path
,
nd
.
dentry
,
clp
->
cl_ident
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
);
exp
=
exp_parent
(
clp
,
inode
->
i_sb
,
nd
.
dentry
);
exp
=
exp_parent
(
clp
,
nd
.
mnt
,
nd
.
dentry
);
if
(
!
exp
)
{
dprintk
(
"nfsd: exp_rootfh export not found.
\n
"
);
goto
out
;
...
...
@@ -555,56 +607,52 @@ exp_getclientbyname(char *ident)
static
void
*
e_start
(
struct
seq_file
*
m
,
loff_t
*
pos
)
{
loff_t
n
=
*
pos
;
unsigned
client
,
export
;
svc_client
*
clp
;
struct
list_head
*
p
;
unsigned
hash
,
export
;
svc_export
*
exp
;
exp_readlock
();
if
(
!
n
--
)
return
(
void
*
)
1
;
client
=
n
>>
32
;
hash
=
n
>>
32
;
export
=
n
&
((
1LL
<<
32
)
-
1
);
for
(
clp
=
clients
;
client
&&
clp
;
clp
=
clp
->
cl_next
,
client
--
)
;
if
(
!
clp
)
return
NULL
;
list_for_each
(
p
,
&
clp
->
cl_list
)
list_for_each_entry
(
exp
,
&
export_table
[
hash
],
ex_hash
)
if
(
!
export
--
)
return
list_entry
(
p
,
svc_export
,
ex_list
)
;
return
exp
;
n
&=
~
((
1LL
<<
32
)
-
1
);
do
{
clp
=
clp
->
cl_next
;
hash
++
;
n
+=
1LL
<<
32
;
}
while
(
clp
&&
list_empty
(
&
clp
->
cl_list
));
if
(
!
clp
)
}
while
(
hash
<
EXPORT_HASHMAX
&&
list_empty
(
&
export_table
[
hash
]
));
if
(
hash
>=
EXPORT_HASHMAX
)
return
NULL
;
*
pos
=
n
+
1
;
return
list_entry
(
clp
->
cl_list
.
next
,
svc_export
,
ex_list
);
return
list_entry
(
export_table
[
hash
].
next
,
svc_export
,
ex_hash
);
}
static
void
*
e_next
(
struct
seq_file
*
m
,
void
*
p
,
loff_t
*
pos
)
{
svc_export
*
exp
=
p
;
svc_client
*
clp
;
int
hash
=
(
*
pos
>>
32
)
;
if
(
p
==
(
void
*
)
1
)
clp
=
clients
;
else
if
(
exp
->
ex_
list
.
next
==
&
exp
->
ex_client
->
cl_list
)
{
clp
=
exp
->
ex_client
->
cl_next
;
hash
=
0
;
else
if
(
exp
->
ex_
hash
.
next
==
&
export_table
[
hash
]
)
{
hash
++
;
*
pos
+=
1LL
<<
32
;
}
else
{
++*
pos
;
return
list_entry
(
exp
->
ex_
list
.
next
,
svc_export
,
ex_list
);
return
list_entry
(
exp
->
ex_
hash
.
next
,
svc_export
,
ex_hash
);
}
*
pos
&=
~
((
1LL
<<
32
)
-
1
);
while
(
clp
&&
list_empty
(
&
clp
->
cl_list
))
{
clp
=
clp
->
cl_next
;
while
(
hash
<
EXPORT_HASHMAX
&&
list_empty
(
&
export_table
[
hash
]
))
{
hash
++
;
*
pos
+=
1LL
<<
32
;
}
if
(
!
clp
)
if
(
hash
>=
EXPORT_HASHMAX
)
return
NULL
;
++*
pos
;
return
list_entry
(
clp
->
cl_list
.
next
,
svc_export
,
ex_list
);
return
list_entry
(
export_table
[
hash
].
next
,
svc_export
,
ex_hash
);
}
static
void
e_stop
(
struct
seq_file
*
m
,
void
*
p
)
...
...
@@ -634,7 +682,7 @@ struct flags {
{
0
,
{
""
,
""
}}
};
static
void
exp_flags
(
struct
seq_file
*
m
,
int
flag
,
int
fsid
)
static
void
exp_flags
(
struct
seq_file
*
m
,
int
flag
,
int
fsid
,
uid_t
anonu
,
uid_t
anong
)
{
int
first
=
0
;
struct
flags
*
flg
;
...
...
@@ -646,6 +694,10 @@ static void exp_flags(struct seq_file *m, int flag, int fsid)
}
if
(
flag
&
NFSEXP_FSID
)
seq_printf
(
m
,
"%sfsid=%d"
,
first
++?
","
:
""
,
fsid
);
if
(
anonu
!=
(
uid_t
)
-
2
&&
anonu
!=
(
0x10000
-
2
))
seq_printf
(
m
,
"%sanonuid=%d"
,
first
++?
","
:
""
,
anonu
);
if
(
anong
!=
(
gid_t
)
-
2
&&
anong
!=
(
0x10000
-
2
))
seq_printf
(
m
,
"%sanongid=%d"
,
first
++?
","
:
""
,
anong
);
}
static
inline
void
mangle
(
struct
seq_file
*
m
,
const
char
*
s
)
...
...
@@ -657,7 +709,7 @@ static int e_show(struct seq_file *m, void *p)
{
struct
svc_export
*
exp
=
p
;
struct
svc_client
*
clp
;
int
j
,
first
=
0
;
char
*
pbuf
;
if
(
p
==
(
void
*
)
1
)
{
seq_puts
(
m
,
"# Version 1.1
\n
"
);
...
...
@@ -667,36 +719,16 @@ static int e_show(struct seq_file *m, void *p)
clp
=
exp
->
ex_client
;
mangle
(
m
,
exp
->
ex_path
);
pbuf
=
m
->
private
;
mangle
(
m
,
d_path
(
exp
->
ex_dentry
,
exp
->
ex_mnt
,
pbuf
,
PAGE_SIZE
));
seq_putc
(
m
,
'\t'
);
mangle
(
m
,
clp
->
cl_ident
);
seq_putc
(
m
,
'('
);
exp_flags
(
m
,
exp
->
ex_flags
,
exp
->
ex_fsid
);
seq_puts
(
m
,
") # "
);
for
(
j
=
0
;
j
<
clp
->
cl_naddr
;
j
++
)
{
struct
svc_clnthash
**
hp
,
**
head
,
*
tmp
;
struct
in_addr
addr
=
clp
->
cl_addr
[
j
];
head
=
&
clnt_hash
[
CLIENT_HASH
(
addr
.
s_addr
)];
for
(
hp
=
head
;
(
tmp
=
*
hp
)
!=
NULL
;
hp
=
&
(
tmp
->
h_next
))
{
if
(
tmp
->
h_addr
.
s_addr
==
addr
.
s_addr
)
break
;
}
if
(
tmp
)
{
if
(
first
++
)
seq_putc
(
m
,
' '
);
if
(
tmp
->
h_client
!=
clp
)
seq_putc
(
m
,
'('
);
seq_printf
(
m
,
"%d.%d.%d.%d"
,
htonl
(
addr
.
s_addr
)
>>
24
&
0xff
,
htonl
(
addr
.
s_addr
)
>>
16
&
0xff
,
htonl
(
addr
.
s_addr
)
>>
8
&
0xff
,
htonl
(
addr
.
s_addr
)
>>
0
&
0xff
);
if
(
tmp
->
h_client
!=
clp
)
seq_putc
(
m
,
')'
);
}
}
seq_putc
(
m
,
'\n'
);
exp_flags
(
m
,
exp
->
ex_flags
,
exp
->
ex_fsid
,
exp
->
ex_anon_uid
,
exp
->
ex_anon_gid
);
seq_puts
(
m
,
")
\n
"
);
return
0
;
}
...
...
@@ -741,16 +773,10 @@ exp_addclient(struct nfsctl_client *ncp)
if
(
!
(
clp
=
kmalloc
(
sizeof
(
*
clp
),
GFP_KERNEL
)))
goto
out_unlock
;
memset
(
clp
,
0
,
sizeof
(
*
clp
));
for
(
i
=
0
;
i
<
NFSCLNT_EXPMAX
;
i
++
)
{
INIT_LIST_HEAD
(
&
clp
->
cl_export
[
i
]);
INIT_LIST_HEAD
(
&
clp
->
cl_expfsid
[
i
]);
}
INIT_LIST_HEAD
(
&
clp
->
cl_list
);
dprintk
(
"created client %s (%p)
\n
"
,
ncp
->
cl_ident
,
clp
);
strcpy
(
clp
->
cl_ident
,
ncp
->
cl_ident
);
clp
->
cl_idlen
=
ilen
;
}
/* Allocate hash buckets */
...
...
@@ -765,19 +791,13 @@ exp_addclient(struct nfsctl_client *ncp)
}
}
/* Copy addresses. */
for
(
i
=
0
;
i
<
ncp
->
cl_naddr
;
i
++
)
{
clp
->
cl_addr
[
i
]
=
ncp
->
cl_addrlist
[
i
];
}
clp
->
cl_naddr
=
ncp
->
cl_naddr
;
/* Remove old client hash entries. */
if
(
change
)
exp_unhashclient
(
clp
);
/* Insert client into hashtable. */
for
(
i
=
0
;
i
<
ncp
->
cl_naddr
;
i
++
)
{
struct
in_addr
addr
=
clp
->
cl_addr
[
i
];
struct
in_addr
addr
=
ncp
->
cl_addrlist
[
i
];
int
hash
;
hash
=
CLIENT_HASH
(
addr
.
s_addr
);
...
...
@@ -838,9 +858,7 @@ exp_freeclient(svc_client *clp)
{
exp_unhashclient
(
clp
);
/* umap_free(&(clp->cl_umap)); */
exp_unexport_all
(
clp
);
nfsd_lockd_unexport
(
clp
);
kfree
(
clp
);
}
...
...
@@ -869,26 +887,12 @@ exp_unhashclient(svc_client *clp)
}
}
}
if
(
count
!=
clp
->
cl_naddr
)
printk
(
KERN_WARNING
"nfsd: bad address count in freeclient!
\n
"
);
if
(
err
)
goto
again
;
for
(
i
=
0
;
i
<
count
;
i
++
)
kfree
(
ch
[
i
]);
}
/*
* Lockd is shutting down and tells us to unregister all clients
*/
void
exp_nlmdetach
(
void
)
{
struct
svc_client
*
clp
;
for
(
clp
=
clients
;
clp
;
clp
=
clp
->
cl_next
)
nfsd_lockd_unexport
(
clp
);
}
/*
* Verify that string is non-empty and does not exceed max length.
*/
...
...
@@ -919,6 +923,12 @@ nfsd_export_init(void)
clnt_hash
[
i
]
=
NULL
;
clients
=
NULL
;
for
(
i
=
0
;
i
<
EXPORT_HASHMAX
;
i
++
)
INIT_LIST_HEAD
(
&
export_table
[
i
]);
for
(
i
=
0
;
i
<
EXPKEY_HASHMAX
;
i
++
)
INIT_LIST_HEAD
(
&
expkey_table
[
i
]);
}
/*
...
...
fs/nfsd/lockd.c
View file @
38d7463e
...
...
@@ -31,12 +31,19 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
memcpy
((
char
*
)
&
fh
.
fh_handle
.
fh_base
,
f
->
data
,
f
->
size
);
fh
.
fh_export
=
NULL
;
nfserr
=
nfsd_open
(
rqstp
,
&
fh
,
S_IFREG
,
MAY_LOCK
,
filp
);
exp_readlock
();
rqstp
->
rq_client
=
exp_getclient
(
&
rqstp
->
rq_addr
);
if
(
rqstp
->
rq_client
==
NULL
)
nfserr
=
nfserr_stale
;
else
nfserr
=
nfsd_open
(
rqstp
,
&
fh
,
S_IFREG
,
MAY_LOCK
,
filp
);
if
(
!
nfserr
)
{
dget
(
filp
->
f_dentry
);
mntget
(
filp
->
f_vfsmnt
);
}
fh_put
(
&
fh
);
rqstp
->
rq_client
=
NULL
;
exp_readunlock
();
/* nlm and nfsd don't share error codes.
* we invent: 0 = no error
* 1 = stale file handle
...
...
@@ -61,24 +68,10 @@ nlm_fclose(struct file *filp)
}
struct
nlmsvc_binding
nfsd_nlm_ops
=
{
.
exp_readlock
=
exp_readlock
,
/* lock export table for reading */
.
exp_unlock
=
exp_readunlock
,
/* unlock export table */
.
exp_getclient
=
exp_getclient
,
/* look up NFS client */
.
fopen
=
nlm_fopen
,
/* open file for locking */
.
fclose
=
nlm_fclose
,
/* close file */
.
detach
=
exp_nlmdetach
,
/* lockd shutdown notification */
};
/*
* When removing an NFS client entry, notify lockd that it is gone.
* FIXME: We should do the same when unexporting an NFS volume.
*/
void
nfsd_lockd_unexport
(
struct
svc_client
*
clnt
)
{
nlmsvc_invalidate_client
(
clnt
);
}
void
nfsd_lockd_init
(
void
)
{
...
...
fs/nfsd/nfsctl.c
View file @
38d7463e
...
...
@@ -127,13 +127,30 @@ static struct file_operations reader_ops = {
extern
struct
seq_operations
nfs_exports_op
;
static
int
exports_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
nfs_exports_op
);
int
res
;
res
=
seq_open
(
file
,
&
nfs_exports_op
);
if
(
!
res
)
{
char
*
namebuf
=
kmalloc
(
PAGE_SIZE
,
GFP_KERNEL
);
if
(
namebuf
==
NULL
)
res
=
-
ENOMEM
;
else
((
struct
seq_file
*
)
file
->
private_data
)
->
private
=
namebuf
;
}
return
res
;
}
static
int
exports_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
seq_file
*
m
=
(
struct
seq_file
*
)
file
->
private_data
;
kfree
(
m
->
private
);
m
->
private
=
NULL
;
return
seq_release
(
inode
,
file
);
}
static
struct
file_operations
exports_operations
=
{
.
open
=
exports_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq
_release
,
.
release
=
exports
_release
,
};
/*
...
...
fs/nfsd/nfsfh.c
View file @
38d7463e
...
...
@@ -97,14 +97,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
rqstp
->
rq_reffh
=
fh
;
if
(
!
fhp
->
fh_dentry
)
{
dev_t
xdev
=
0
;
ino_t
xino
=
0
;
__u32
*
datap
=
NULL
;
__u32
tfh
[
3
];
/* filehandle fragment for oldstyle filehandles */
int
fileid_type
;
int
data_left
=
fh
->
fh_size
/
4
;
int
nfsdev
;
int
fsid
=
0
;
error
=
nfserr_stale
;
if
(
rqstp
->
rq_vers
>
2
)
...
...
@@ -113,6 +109,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
return
nfserr_nofilehandle
;
if
(
fh
->
fh_version
==
1
)
{
int
len
;
datap
=
fh
->
fh_auth
;
if
(
--
data_left
<
0
)
goto
out
;
switch
(
fh
->
fh_auth_type
)
{
...
...
@@ -122,39 +119,37 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
switch
(
fh
->
fh_fsid_type
)
{
case
0
:
if
((
data_left
-=
2
)
<
0
)
goto
out
;
nfsdev
=
ntohl
(
*
datap
++
);
xdev
=
MKDEV
(
nfsdev
>>
16
,
nfsdev
&
0xFFFF
);
xino
=
*
datap
++
;
len
=
2
;
break
;
case
1
:
if
((
data_left
-=
1
)
<
0
)
goto
out
;
fsid
=
*
datap
++
;
len
=
1
;
break
;
default:
goto
out
;
}
if
((
data_left
-=
len
)
<
0
)
goto
out
;
exp
=
exp_find
(
rqstp
->
rq_client
,
fh
->
fh_fsid_type
,
datap
);
datap
+=
len
;
}
else
{
dev_t
xdev
;
ino_t
xino
;
if
(
fh
->
fh_size
!=
NFS_FHSIZE
)
goto
out
;
/* assume old filehandle format */
xdev
=
u32_to_dev_t
(
fh
->
ofh_xdev
);
xino
=
u32_to_ino_t
(
fh
->
ofh_xino
);
mk_fsid_v0
(
tfh
,
xdev
,
xino
);
exp
=
exp_find
(
rqstp
->
rq_client
,
0
,
tfh
);
}
/*
* Look up the export entry.
*/
error
=
nfserr_stale
;
if
(
fh
->
fh_version
==
1
&&
fh
->
fh_fsid_type
==
1
)
exp
=
exp_get_fsid
(
rqstp
->
rq_client
,
fsid
);
else
exp
=
exp_get
(
rqstp
->
rq_client
,
xdev
,
xino
);
if
(
!
exp
)
{
if
(
!
exp
)
/* export entry revoked */
goto
out
;
}
/* Check if the request originated from a secure port. */
error
=
nfserr_perm
;
...
...
@@ -322,9 +317,11 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
dentry
*
parent
=
dentry
->
d_parent
;
__u32
*
datap
;
dev_t
ex_dev
=
exp
->
ex_dentry
->
d_inode
->
i_sb
->
s_dev
;
dprintk
(
"nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)
\n
"
,
MAJOR
(
exp
->
ex_dev
),
MINOR
(
exp
->
ex_dev
),
(
long
)
exp
->
ex_ino
,
MAJOR
(
ex_dev
),
MINOR
(
ex_dev
),
(
long
)
exp
->
ex_dentry
->
d_inode
->
i_ino
,
parent
->
d_name
.
name
,
dentry
->
d_name
.
name
,
(
inode
?
inode
->
i_ino
:
0
));
...
...
@@ -351,9 +348,9 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
memset
(
&
fhp
->
fh_handle
.
fh_base
,
0
,
NFS_FHSIZE
);
fhp
->
fh_handle
.
fh_size
=
NFS_FHSIZE
;
fhp
->
fh_handle
.
ofh_dcookie
=
0xfeebbaca
;
fhp
->
fh_handle
.
ofh_dev
=
htonl
((
MAJOR
(
ex
p
->
ex_dev
)
<<
16
)
|
MINOR
(
exp
->
ex_dev
));
fhp
->
fh_handle
.
ofh_dev
=
htonl
((
MAJOR
(
ex
_dev
)
<<
16
)
|
MINOR
(
ex_dev
));
fhp
->
fh_handle
.
ofh_xdev
=
fhp
->
fh_handle
.
ofh_dev
;
fhp
->
fh_handle
.
ofh_xino
=
ino_t_to_u32
(
exp
->
ex_ino
);
fhp
->
fh_handle
.
ofh_xino
=
ino_t_to_u32
(
exp
->
ex_
dentry
->
d_inode
->
i_
ino
);
fhp
->
fh_handle
.
ofh_dirino
=
ino_t_to_u32
(
parent_ino
(
dentry
));
if
(
inode
)
_fh_update_old
(
dentry
,
exp
,
&
fhp
->
fh_handle
);
...
...
@@ -365,13 +362,14 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
(
ref_fh_fsid_type
==
1
))
{
fhp
->
fh_handle
.
fh_fsid_type
=
1
;
/* fsid_type 1 == 4 bytes filesystem id */
*
datap
++
=
exp
->
ex_fsid
;
mk_fsid_v1
(
datap
,
exp
->
ex_fsid
);
datap
+=
1
;
fhp
->
fh_handle
.
fh_size
=
2
*
4
;
}
else
{
fhp
->
fh_handle
.
fh_fsid_type
=
0
;
/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
*
datap
++
=
htonl
((
MAJOR
(
exp
->
ex_dev
)
<<
16
)
|
MINOR
(
exp
->
ex_dev
)
);
*
datap
++
=
ino_t_to_u32
(
exp
->
ex_ino
)
;
mk_fsid_v0
(
datap
,
ex_dev
,
exp
->
ex_dentry
->
d_inode
->
i_ino
);
datap
+=
2
;
fhp
->
fh_handle
.
fh_size
=
3
*
4
;
}
if
(
inode
)
{
...
...
fs/nfsd/vfs.c
View file @
38d7463e
...
...
@@ -119,24 +119,24 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
else
{
/* checking mountpoint crossing is very different when stepping up */
struct
svc_export
*
exp2
=
NULL
;
struct
dentry
*
dp
,
*
old
;
struct
dentry
*
dp
;
struct
vfsmount
*
mnt
=
mntget
(
exp
->
ex_mnt
);
dentry
=
dget
(
dparent
);
while
(
follow_up
(
&
mnt
,
&
dentry
))
;
old
=
dentry
;
read_lock
(
&
dparent_lock
);
dp
=
dentry
->
d_parent
;
for
(
;
!
exp2
&&
dp
->
d_parent
!=
dp
;
dp
=
dp
->
d_parent
)
exp2
=
exp_get_by_name
(
exp
->
ex_client
,
mnt
,
dp
);
dp
=
dget
(
dentry
->
d_parent
);
read_unlock
(
&
dparent_lock
);
dput
(
dentry
);
dentry
=
dp
;
exp2
=
exp_parent
(
exp
->
ex_client
,
mnt
,
dentry
);
if
(
!
exp2
)
{
dput
(
dentry
);
dentry
=
dget
(
dparent
);
}
else
{
dget
(
dentry
->
d_parent
);
exp
=
exp2
;
}
read_unlock
(
&
dparent_lock
);
dput
(
old
);
mntput
(
mnt
);
}
}
else
{
...
...
include/linux/lockd/bind.h
View file @
38d7463e
...
...
@@ -19,14 +19,10 @@ struct svc_client; /* opaque type */
* This is the set of functions for lockd->nfsd communication
*/
struct
nlmsvc_binding
{
void
(
*
exp_readlock
)(
void
);
void
(
*
exp_unlock
)(
void
);
struct
svc_client
*
(
*
exp_getclient
)(
struct
sockaddr_in
*
);
u32
(
*
fopen
)(
struct
svc_rqst
*
,
struct
nfs_fh
*
,
struct
file
*
);
void
(
*
fclose
)(
struct
file
*
);
void
(
*
detach
)(
void
);
};
extern
struct
nlmsvc_binding
*
nlmsvc_ops
;
...
...
@@ -34,7 +30,6 @@ extern struct nlmsvc_binding * nlmsvc_ops;
/*
* Functions exported by the lockd module
*/
extern
void
nlmsvc_invalidate_client
(
struct
svc_client
*
clnt
);
extern
int
nlmclnt_proc
(
struct
inode
*
,
int
,
struct
file_lock
*
);
extern
int
lockd_up
(
void
);
extern
void
lockd_down
(
void
);
...
...
include/linux/lockd/lockd.h
View file @
38d7463e
...
...
@@ -39,13 +39,13 @@
struct
nlm_host
{
struct
nlm_host
*
h_next
;
/* linked list (hash table) */
struct
sockaddr_in
h_addr
;
/* peer address */
struct
svc_client
*
h_exportent
;
/* NFS client */
struct
rpc_clnt
*
h_rpcclnt
;
/* RPC client to talk to peer */
char
h_name
[
20
];
/* remote hostname */
u32
h_version
;
/* interface version */
unsigned
short
h_proto
;
/* transport proto */
unsigned
short
h_authflavor
;
/* RPC authentication type */
unsigned
short
h_reclaiming
:
1
,
h_server
:
1
,
/* server side, not client side */
h_inuse
:
1
,
h_killed
:
1
,
h_monitored
:
1
;
...
...
@@ -143,13 +143,14 @@ void nlmclnt_freegrantargs(struct nlm_rqst *);
*/
struct
nlm_host
*
nlmclnt_lookup_host
(
struct
sockaddr_in
*
,
int
,
int
);
struct
nlm_host
*
nlmsvc_lookup_host
(
struct
svc_rqst
*
);
struct
nlm_host
*
nlm_lookup_host
(
struct
svc_client
*
,
struct
sockaddr_in
*
,
int
,
int
);
struct
nlm_host
*
nlm_lookup_host
(
int
server
,
struct
sockaddr_in
*
,
int
,
int
);
struct
rpc_clnt
*
nlm_bind_host
(
struct
nlm_host
*
);
void
nlm_rebind_host
(
struct
nlm_host
*
);
struct
nlm_host
*
nlm_get_host
(
struct
nlm_host
*
);
void
nlm_release_host
(
struct
nlm_host
*
);
void
nlm_shutdown_hosts
(
void
);
extern
struct
nlm_host
*
nlm_find_client
(
void
);
/*
* Server-side lock handling
...
...
@@ -173,6 +174,7 @@ u32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
void
nlm_release_file
(
struct
nlm_file
*
);
void
nlmsvc_mark_resources
(
void
);
void
nlmsvc_free_host_resources
(
struct
nlm_host
*
);
void
nlmsvc_invalidate_all
(
void
);
static
__inline__
struct
inode
*
nlmsvc_file_inode
(
struct
nlm_file
*
file
)
...
...
include/linux/lockd/sm_inter.h
View file @
38d7463e
...
...
@@ -28,6 +28,7 @@ struct nsm_args {
u32
prog
;
/* RPC callback info */
u32
vers
;
u32
proc
;
u32
proto
;
/* protocol (udp/tcp) plus server/client flag */
};
/*
...
...
include/linux/lockd/xdr.h
View file @
38d7463e
...
...
@@ -76,6 +76,8 @@ struct nlm_reboot {
int
len
;
u32
state
;
u32
addr
;
u32
vers
;
u32
proto
;
};
/*
...
...
include/linux/nfsd/auth.h
View file @
38d7463e
...
...
@@ -23,23 +23,5 @@
*/
void
nfsd_setuser
(
struct
svc_rqst
*
,
struct
svc_export
*
);
#if 0
/*
* These must match the actual size of uid_t and gid_t
*/
#define UGID_BITS (8 * sizeof(uid_t))
#define UGID_SHIFT 8
#define UGID_MASK ((1 << UGID_SHIFT) - 1)
#define UGID_NRENTRIES ((1 << (UGID_BITS - UGID_SHIFT)) + 1)
#define UGID_NONE ((unsigned short)-1)
typedef struct svc_uidmap {
uid_t * um_ruid[UGID_NRENTRIES];
uid_t * um_luid[UGID_NRENTRIES];
gid_t * um_rgid[UGID_NRENTRIES];
gid_t * um_lgid[UGID_NRENTRIES];
} svc_uidmap;
#endif
#endif
/* __KERNEL__ */
#endif
/* LINUX_NFSD_AUTH_H */
include/linux/nfsd/export.h
View file @
38d7463e
...
...
@@ -45,38 +45,36 @@
#ifdef __KERNEL__
/* The following are hashtable sizes and must be powers of 2 */
#define NFSCLNT_EXPMAX 16
struct
svc_client
{
struct
svc_client
*
cl_next
;
char
cl_ident
[
NFSCLNT_IDMAX
];
int
cl_idlen
;
int
cl_naddr
;
struct
in_addr
cl_addr
[
NFSCLNT_ADDRMAX
];
struct
svc_uidmap
*
cl_umap
;
struct
list_head
cl_export
[
NFSCLNT_EXPMAX
];
struct
list_head
cl_expfsid
[
NFSCLNT_EXPMAX
];
struct
list_head
cl_list
;
};
struct
svc_export
{
struct
list_head
ex_hash
;
struct
list_head
ex_fsid_hash
;
struct
list_head
ex_list
;
char
ex_path
[
NFS_MAXPATHLEN
+
1
];
struct
svc_export
*
ex_parent
;
struct
svc_client
*
ex_client
;
int
ex_flags
;
struct
vfsmount
*
ex_mnt
;
struct
dentry
*
ex_dentry
;
dev_t
ex_dev
;
ino_t
ex_ino
;
uid_t
ex_anon_uid
;
gid_t
ex_anon_gid
;
int
ex_fsid
;
};
/* an "export key" (expkey) maps a filehandlefragement to an
* svc_export for a given client. There can be two per export, one
* for type 0 (dev/ino), one for type 1 (fsid)
*/
struct
svc_expkey
{
struct
list_head
ek_hash
;
struct
svc_client
*
ek_client
;
int
ek_fsidtype
;
u32
ek_fsid
[
2
];
struct
svc_export
*
ek_export
;
};
#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
#define EX_RDONLY(exp) ((exp)->ex_flags & NFSEXP_READONLY)
...
...
@@ -94,16 +92,25 @@ void exp_readlock(void);
void
exp_readunlock
(
void
);
struct
svc_client
*
exp_getclient
(
struct
sockaddr_in
*
sin
);
void
exp_putclient
(
struct
svc_client
*
clp
);
struct
svc_export
*
exp_get
(
struct
svc_client
*
clp
,
dev_t
dev
,
ino_t
ino
);
struct
svc_export
*
exp_get_fsid
(
struct
svc_client
*
clp
,
int
fsid
);
struct
svc_expkey
*
exp_find_key
(
struct
svc_client
*
clp
,
int
fsid_type
,
u32
*
fsidv
);
struct
svc_export
*
exp_get_by_name
(
struct
svc_client
*
clp
,
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
);
struct
svc_export
*
exp_parent
(
struct
svc_client
*
clp
,
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
);
int
exp_rootfh
(
struct
svc_client
*
,
char
*
path
,
struct
knfsd_fh
*
,
int
maxsize
);
int
nfserrno
(
int
errno
);
void
exp_nlmdetach
(
void
);
static
inline
struct
svc_export
*
exp_find
(
struct
svc_client
*
clp
,
int
fsid_type
,
u32
*
fsidv
)
{
struct
svc_expkey
*
ek
=
exp_find_key
(
clp
,
fsid_type
,
fsidv
);
if
(
ek
)
return
ek
->
ek_export
;
else
return
NULL
;
}
#endif
/* __KERNEL__ */
...
...
include/linux/nfsd/nfsfh.h
View file @
38d7463e
...
...
@@ -199,6 +199,19 @@ typedef struct svc_fh {
}
svc_fh
;
static
inline
void
mk_fsid_v0
(
u32
*
fsidv
,
dev_t
dev
,
ino_t
ino
)
{
fsidv
[
0
]
=
htonl
((
MAJOR
(
dev
)
<<
16
)
|
MINOR
(
dev
));
fsidv
[
1
]
=
ino_t_to_u32
(
ino
);
}
static
inline
void
mk_fsid_v1
(
u32
*
fsidv
,
u32
fsid
)
{
fsidv
[
0
]
=
fsid
;
}
/*
* Shorthand for dprintk()'s
*/
...
...
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