2005-04-16 15:20:36 -07: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 ) ;
}
u32
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 ;
}
share = ( struct nlm_share * ) kmalloc ( sizeof ( * share ) + oh - > len ,
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 .
*/
u32
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 ;
for ( shpp = & file - > f_shares ; ( share = * shpp ) ! = 0 ; shpp = & share - > s_next ) {
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 ;
}
/*
* Traverse all shares for a given file ( and host ) .
* NLM_ACT_CHECK is handled by nlmsvc_inspect_file .
*/
2006-03-20 23:24:25 -05:00
void
2005-04-16 15:20:36 -07:00
nlmsvc_traverse_shares ( struct nlm_host * host , struct nlm_file * file , int action )
{
struct nlm_share * share , * * shpp ;
shpp = & file - > f_shares ;
while ( ( share = * shpp ) ! = NULL ) {
if ( action = = NLM_ACT_MARK )
share - > s_host - > h_inuse = 1 ;
else if ( action = = NLM_ACT_UNLOCK ) {
if ( host = = NULL | | host = = share - > s_host ) {
* shpp = share - > s_next ;
kfree ( share ) ;
continue ;
}
}
shpp = & share - > s_next ;
}
}