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