2005-04-17 02:20:36 +04:00
/*
* linux / fs / lockd / svcshare . c
*
* Management of DOS shares .
*
* Copyright ( C ) 1996 Olaf Kirch < okir @ monad . swb . de >
*/
# include <linux/time.h>
# include <linux/unistd.h>
# include <linux/string.h>
# include <linux/slab.h>
# include <linux/sunrpc/clnt.h>
# include <linux/sunrpc/svc.h>
# include <linux/lockd/lockd.h>
# include <linux/lockd/share.h>
static inline int
nlm_cmp_owner ( struct nlm_share * share , struct xdr_netobj * oh )
{
return share - > s_owner . len = = oh - > len
& & ! memcmp ( share - > s_owner . data , oh - > data , oh - > len ) ;
}
2006-10-20 10:28:46 +04:00
__be32
2005-04-17 02:20:36 +04:00
nlmsvc_share_file ( struct nlm_host * host , struct nlm_file * file ,
struct nlm_args * argp )
{
struct nlm_share * share ;
struct xdr_netobj * oh = & argp - > lock . oh ;
u8 * ohdata ;
for ( share = file - > f_shares ; share ; share = share - > s_next ) {
if ( share - > s_host = = host & & nlm_cmp_owner ( share , oh ) )
goto update ;
if ( ( argp - > fsm_access & share - > s_mode )
| | ( argp - > fsm_mode & share - > s_access ) )
return nlm_lck_denied ;
}
2006-12-13 11:35:56 +03:00
share = kmalloc ( sizeof ( * share ) + oh - > len ,
2005-04-17 02:20:36 +04:00
GFP_KERNEL ) ;
if ( share = = NULL )
return nlm_lck_denied_nolocks ;
/* Copy owner handle */
ohdata = ( u8 * ) ( share + 1 ) ;
memcpy ( ohdata , oh - > data , oh - > len ) ;
share - > s_file = file ;
share - > s_host = host ;
share - > s_owner . data = ohdata ;
share - > s_owner . len = oh - > len ;
share - > s_next = file - > f_shares ;
file - > f_shares = share ;
update :
share - > s_access = argp - > fsm_access ;
share - > s_mode = argp - > fsm_mode ;
return nlm_granted ;
}
/*
* Delete a share .
*/
2006-10-20 10:28:46 +04:00
__be32
2005-04-17 02:20:36 +04:00
nlmsvc_unshare_file ( struct nlm_host * host , struct nlm_file * file ,
struct nlm_args * argp )
{
struct nlm_share * share , * * shpp ;
struct xdr_netobj * oh = & argp - > lock . oh ;
2008-02-18 13:01:49 +03:00
for ( shpp = & file - > f_shares ; ( share = * shpp ) ! = NULL ;
shpp = & share - > s_next ) {
2005-04-17 02:20:36 +04:00
if ( share - > s_host = = host & & nlm_cmp_owner ( share , oh ) ) {
* shpp = share - > s_next ;
kfree ( share ) ;
return nlm_granted ;
}
}
/* X/Open spec says return success even if there was no
* corresponding share . */
return nlm_granted ;
}
/*
2006-10-04 13:15:59 +04:00
* Traverse all shares for a given file , and delete
* those owned by the given ( type of ) host
2005-04-17 02:20:36 +04:00
*/
2006-10-04 13:15:59 +04:00
void nlmsvc_traverse_shares ( struct nlm_host * host , struct nlm_file * file ,
nlm_host_match_fn_t match )
2005-04-17 02:20:36 +04:00
{
struct nlm_share * share , * * shpp ;
shpp = & file - > f_shares ;
while ( ( share = * shpp ) ! = NULL ) {
2006-10-04 13:15:59 +04:00
if ( match ( share - > s_host , host ) ) {
* shpp = share - > s_next ;
kfree ( share ) ;
continue ;
2005-04-17 02:20:36 +04:00
}
shpp = & share - > s_next ;
}
}