1/* 2 * linux/fs/lockd/svcshare.c 3 * 4 * Management of DOS shares. 5 * 6 * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> 7 */ 8 9#include <linux/sched.h> 10#include <linux/unistd.h> 11#include <linux/string.h> 12#include <linux/slab.h> 13 14#include <linux/sunrpc/clnt.h> 15#include <linux/sunrpc/svc.h> 16#include <linux/lockd/lockd.h> 17#include <linux/lockd/share.h> 18 19static inline int 20nlm_cmp_owner(struct nlm_share *share, struct xdr_netobj *oh) 21{ 22 return share->s_owner.len == oh->len 23 && !memcmp(share->s_owner.data, oh->data, oh->len); 24} 25 26u32 27nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file, 28 struct nlm_args *argp) 29{ 30 struct nlm_share *share; 31 struct xdr_netobj *oh = &argp->lock.oh; 32 u8 *ohdata; 33 34 for (share = file->f_shares; share; share = share->s_next) { 35 if (share->s_host == host && nlm_cmp_owner(share, oh)) 36 goto update; 37 if ((argp->fsm_access & share->s_mode) 38 || (argp->fsm_mode & share->s_access )) 39 return nlm_lck_denied; 40 } 41 42 share = (struct nlm_share *) kmalloc(sizeof(*share) + oh->len, 43 GFP_KERNEL); 44 if (share == NULL) 45 return nlm_lck_denied_nolocks; 46 47 /* Copy owner handle */ 48 ohdata = (u8 *) (share + 1); 49 memcpy(ohdata, oh->data, oh->len); 50 51 share->s_file = file; 52 share->s_host = host; 53 share->s_owner.data = ohdata; 54 share->s_owner.len = oh->len; 55 share->s_next = file->f_shares; 56 file->f_shares = share; 57 58update: 59 share->s_access = argp->fsm_access; 60 share->s_mode = argp->fsm_mode; 61 return nlm_granted; 62} 63 64/* 65 * Delete a share. 66 */ 67u32 68nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file, 69 struct nlm_args *argp) 70{ 71 struct nlm_share *share, **shpp; 72 struct xdr_netobj *oh = &argp->lock.oh; 73 74 for (shpp = &file->f_shares; (share = *shpp); shpp = &share->s_next) { 75 if (share->s_host == host && nlm_cmp_owner(share, oh)) { 76 *shpp = share->s_next; 77 kfree(share); 78 return nlm_granted; 79 } 80 } 81 82 /* X/Open spec says return success even if there was no 83 * corresponding share. */ 84 return nlm_granted; 85} 86 87/* 88 * Traverse all shares for a given file (and host). 89 * NLM_ACT_CHECK is handled by nlmsvc_inspect_file. 90 */ 91int 92nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file, int action) 93{ 94 struct nlm_share *share, **shpp; 95 96 shpp = &file->f_shares; 97 while ((share = *shpp) != NULL) { 98 if (action == NLM_ACT_MARK) 99 share->s_host->h_inuse = 1; 100 else if (action == NLM_ACT_UNLOCK) { 101 if (host == NULL || host == share->s_host) { 102 *shpp = share->s_next; 103 kfree(share); 104 continue; 105 } 106 } 107 shpp = &share->s_next; 108 } 109 110 return 0; 111} 112