Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * linux/fs/lockd/svcshare.c
0004  *
0005  * Management of DOS shares.
0006  *
0007  * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de>
0008  */
0009 
0010 #include <linux/time.h>
0011 #include <linux/unistd.h>
0012 #include <linux/string.h>
0013 #include <linux/slab.h>
0014 
0015 #include <linux/sunrpc/clnt.h>
0016 #include <linux/sunrpc/svc.h>
0017 #include <linux/lockd/lockd.h>
0018 #include <linux/lockd/share.h>
0019 
0020 static inline int
0021 nlm_cmp_owner(struct nlm_share *share, struct xdr_netobj *oh)
0022 {
0023     return share->s_owner.len == oh->len
0024         && !memcmp(share->s_owner.data, oh->data, oh->len);
0025 }
0026 
0027 __be32
0028 nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file,
0029             struct nlm_args *argp)
0030 {
0031     struct nlm_share    *share;
0032     struct xdr_netobj   *oh = &argp->lock.oh;
0033     u8          *ohdata;
0034 
0035     for (share = file->f_shares; share; share = share->s_next) {
0036         if (share->s_host == host && nlm_cmp_owner(share, oh))
0037             goto update;
0038         if ((argp->fsm_access & share->s_mode)
0039          || (argp->fsm_mode   & share->s_access ))
0040             return nlm_lck_denied;
0041     }
0042 
0043     share = kmalloc(sizeof(*share) + oh->len,
0044                         GFP_KERNEL);
0045     if (share == NULL)
0046         return nlm_lck_denied_nolocks;
0047 
0048     /* Copy owner handle */
0049     ohdata = (u8 *) (share + 1);
0050     memcpy(ohdata, oh->data, oh->len);
0051 
0052     share->s_file       = file;
0053     share->s_host       = host;
0054     share->s_owner.data = ohdata;
0055     share->s_owner.len  = oh->len;
0056     share->s_next       = file->f_shares;
0057     file->f_shares      = share;
0058 
0059 update:
0060     share->s_access = argp->fsm_access;
0061     share->s_mode   = argp->fsm_mode;
0062     return nlm_granted;
0063 }
0064 
0065 /*
0066  * Delete a share.
0067  */
0068 __be32
0069 nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
0070             struct nlm_args *argp)
0071 {
0072     struct nlm_share    *share, **shpp;
0073     struct xdr_netobj   *oh = &argp->lock.oh;
0074 
0075     for (shpp = &file->f_shares; (share = *shpp) != NULL;
0076                     shpp = &share->s_next) {
0077         if (share->s_host == host && nlm_cmp_owner(share, oh)) {
0078             *shpp = share->s_next;
0079             kfree(share);
0080             return nlm_granted;
0081         }
0082     }
0083 
0084     /* X/Open spec says return success even if there was no
0085      * corresponding share. */
0086     return nlm_granted;
0087 }
0088 
0089 /*
0090  * Traverse all shares for a given file, and delete
0091  * those owned by the given (type of) host
0092  */
0093 void nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file,
0094         nlm_host_match_fn_t match)
0095 {
0096     struct nlm_share    *share, **shpp;
0097 
0098     shpp = &file->f_shares;
0099     while ((share = *shpp) !=  NULL) {
0100         if (match(share->s_host, host)) {
0101             *shpp = share->s_next;
0102             kfree(share);
0103             continue;
0104         }
0105         shpp = &share->s_next;
0106     }
0107 }