11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/fs/lockd/svcshare.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Management of DOS shares. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> 71da177e4SLinus Torvalds */ 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #include <linux/time.h> 101da177e4SLinus Torvalds #include <linux/unistd.h> 111da177e4SLinus Torvalds #include <linux/string.h> 121da177e4SLinus Torvalds #include <linux/slab.h> 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h> 151da177e4SLinus Torvalds #include <linux/sunrpc/svc.h> 161da177e4SLinus Torvalds #include <linux/lockd/lockd.h> 171da177e4SLinus Torvalds #include <linux/lockd/share.h> 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds static inline int 201da177e4SLinus Torvalds nlm_cmp_owner(struct nlm_share *share, struct xdr_netobj *oh) 211da177e4SLinus Torvalds { 221da177e4SLinus Torvalds return share->s_owner.len == oh->len 231da177e4SLinus Torvalds && !memcmp(share->s_owner.data, oh->data, oh->len); 241da177e4SLinus Torvalds } 251da177e4SLinus Torvalds 26*52921e02SAl Viro __be32 271da177e4SLinus Torvalds nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file, 281da177e4SLinus Torvalds struct nlm_args *argp) 291da177e4SLinus Torvalds { 301da177e4SLinus Torvalds struct nlm_share *share; 311da177e4SLinus Torvalds struct xdr_netobj *oh = &argp->lock.oh; 321da177e4SLinus Torvalds u8 *ohdata; 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds for (share = file->f_shares; share; share = share->s_next) { 351da177e4SLinus Torvalds if (share->s_host == host && nlm_cmp_owner(share, oh)) 361da177e4SLinus Torvalds goto update; 371da177e4SLinus Torvalds if ((argp->fsm_access & share->s_mode) 381da177e4SLinus Torvalds || (argp->fsm_mode & share->s_access )) 391da177e4SLinus Torvalds return nlm_lck_denied; 401da177e4SLinus Torvalds } 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds share = (struct nlm_share *) kmalloc(sizeof(*share) + oh->len, 431da177e4SLinus Torvalds GFP_KERNEL); 441da177e4SLinus Torvalds if (share == NULL) 451da177e4SLinus Torvalds return nlm_lck_denied_nolocks; 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds /* Copy owner handle */ 481da177e4SLinus Torvalds ohdata = (u8 *) (share + 1); 491da177e4SLinus Torvalds memcpy(ohdata, oh->data, oh->len); 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds share->s_file = file; 521da177e4SLinus Torvalds share->s_host = host; 531da177e4SLinus Torvalds share->s_owner.data = ohdata; 541da177e4SLinus Torvalds share->s_owner.len = oh->len; 551da177e4SLinus Torvalds share->s_next = file->f_shares; 561da177e4SLinus Torvalds file->f_shares = share; 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds update: 591da177e4SLinus Torvalds share->s_access = argp->fsm_access; 601da177e4SLinus Torvalds share->s_mode = argp->fsm_mode; 611da177e4SLinus Torvalds return nlm_granted; 621da177e4SLinus Torvalds } 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds /* 651da177e4SLinus Torvalds * Delete a share. 661da177e4SLinus Torvalds */ 67*52921e02SAl Viro __be32 681da177e4SLinus Torvalds nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file, 691da177e4SLinus Torvalds struct nlm_args *argp) 701da177e4SLinus Torvalds { 711da177e4SLinus Torvalds struct nlm_share *share, **shpp; 721da177e4SLinus Torvalds struct xdr_netobj *oh = &argp->lock.oh; 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds for (shpp = &file->f_shares; (share = *shpp) != 0; shpp = &share->s_next) { 751da177e4SLinus Torvalds if (share->s_host == host && nlm_cmp_owner(share, oh)) { 761da177e4SLinus Torvalds *shpp = share->s_next; 771da177e4SLinus Torvalds kfree(share); 781da177e4SLinus Torvalds return nlm_granted; 791da177e4SLinus Torvalds } 801da177e4SLinus Torvalds } 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds /* X/Open spec says return success even if there was no 831da177e4SLinus Torvalds * corresponding share. */ 841da177e4SLinus Torvalds return nlm_granted; 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds /* 88f2af793dSOlaf Kirch * Traverse all shares for a given file, and delete 89f2af793dSOlaf Kirch * those owned by the given (type of) host 901da177e4SLinus Torvalds */ 91f2af793dSOlaf Kirch void nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file, 92f2af793dSOlaf Kirch nlm_host_match_fn_t match) 931da177e4SLinus Torvalds { 941da177e4SLinus Torvalds struct nlm_share *share, **shpp; 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds shpp = &file->f_shares; 971da177e4SLinus Torvalds while ((share = *shpp) != NULL) { 98f2af793dSOlaf Kirch if (match(share->s_host, host)) { 991da177e4SLinus Torvalds *shpp = share->s_next; 1001da177e4SLinus Torvalds kfree(share); 1011da177e4SLinus Torvalds continue; 1021da177e4SLinus Torvalds } 1031da177e4SLinus Torvalds shpp = &share->s_next; 1041da177e4SLinus Torvalds } 1051da177e4SLinus Torvalds } 106