diff options
| author | Rajesh Amaravathi <rajesh@redhat.com> | 2012-04-12 14:49:44 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2012-05-17 02:12:49 -0700 | 
| commit | cbcf82aa58058fe05dbd9a8d8879ca0364e5df95 (patch) | |
| tree | 83c7dc8da592fb0442d5626eac6779c813d61655 /xlators/nfs/server | |
| parent | d8ede99e6f429d3a63b794c495f99fc8f76e9651 (diff) | |
nfs/nlm: procedures for PC clients
*  This change introduces four NLMv4 procedures:
   NM_LOCK, SHARE, UNSHARE and FREE_ALL.
   These are used by PC clients (windows/dos) to control access
   to files.
   1. NM_LOCK: this lock is not monitored by statd.
   2. SHARE: A share reservation is a lock on the whole file
      that is taken whenever a file is opened on windows clients.
      This has ACCESS (N, R, W, RW) and DENY MODE (N, R, W, RW).
        ACCESS:    mode of access requested by the client;
        DENY MODE: what the requesting client wants to
                   deny other clients.
   3. UNSHARE: remove a share reservation obtained by SHARE.
      Called while closing a file.
   4. FREE_ALL: remove all share reservations and locks,
      both monitored and unmonitored, of the calling client.
*  lock and nm_lock use a common function with only
   a flag conveying whether or not to monitor a lock.
*  NOTES:
   1. SHARE reservations are not STACK_WIND'd to subsequent xlators.
      These are maintained in-memory in the nfs xlator.
   2. Consequently, for SHARE reservations to work effectively,
      all PC clients  *must* mount from the same gNfs server.
      Not doing so will result in different servers maintaining
      separate SHARE reservations which will not be enforced
      for obvious reasons.
Change-Id: Id4f22670a94ed58691a6a7f4c80aa8c11421a277
BUG: 800287
Signed-off-by: Rajesh Amaravathi <rajesh@redhat.com>
Reviewed-on: http://review.gluster.com/3212
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Krishna Srinivas <krishna@gluster.com>
Diffstat (limited to 'xlators/nfs/server')
| -rw-r--r-- | xlators/nfs/server/src/nfs-mem-types.h | 1 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs.c | 9 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3.h | 2 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nlm4.c | 618 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nlm4.h | 10 | 
5 files changed, 605 insertions, 35 deletions
diff --git a/xlators/nfs/server/src/nfs-mem-types.h b/xlators/nfs/server/src/nfs-mem-types.h index e2dae4a34..1a3b25281 100644 --- a/xlators/nfs/server/src/nfs-mem-types.h +++ b/xlators/nfs/server/src/nfs-mem-types.h @@ -47,6 +47,7 @@ enum gf_nfs_mem_types_ {  	gf_nfs_mt_nlm4_cm,  	gf_nfs_mt_nlm4_fde,          gf_nfs_mt_nlm4_nlmclnt, +        gf_nfs_mt_nlm4_share,          gf_nfs_mt_end  };  #endif diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c index 42edc95f6..a48e11499 100644 --- a/xlators/nfs/server/src/nfs.c +++ b/xlators/nfs/server/src/nfs.c @@ -849,6 +849,15 @@ fini (xlator_t *this)  int32_t  nfs_forget (xlator_t *this, inode_t *inode)  { +        uint64_t           ctx        = 0; +        struct list_head  *head       = NULL; + +        if (inode_ctx_del (inode, this, &ctx)) +                return -1; + +        head = (struct list_head *)ctx; +        GF_FREE (head); +          return 0;  } diff --git a/xlators/nfs/server/src/nfs3.h b/xlators/nfs/server/src/nfs3.h index e6b9edee5..78eb01b60 100644 --- a/xlators/nfs/server/src/nfs3.h +++ b/xlators/nfs/server/src/nfs3.h @@ -154,6 +154,7 @@ typedef union args_ {          nlm4_unlockargs nlm4_unlockargs;          nlm4_shareargs nlm4_shareargs;          nlm4_shareres nlm4_shareres; +        nlm4_freeallargs nlm4_freeallargs;  } args; @@ -230,6 +231,7 @@ struct nfs3_local {          nlm4_lkowner_t          lkowner;          char                    cookiebytes[1024];          struct nfs3_fh          lockfh; +        int                     monitor;          rpc_transport_t         *trans;          call_frame_t            *frame;  }; diff --git a/xlators/nfs/server/src/nlm4.c b/xlators/nfs/server/src/nlm4.c index 4f9a1c4fc..72f71609a 100644 --- a/xlators/nfs/server/src/nlm4.c +++ b/xlators/nfs/server/src/nlm4.c @@ -199,12 +199,40 @@ nlm4_prep_nlm4_unlockargs (nlm4_unlockargs *args, struct nfs3_fh *fh,  }  void +nlm4_prep_shareargs (nlm4_shareargs *args, struct nfs3_fh *fh, +                     nlm4_lkowner_t *oh, char *cookiebytes) +{ +        memset (args, 0, sizeof (*args)); +        args->share.fh.n_bytes = (void *)fh; +        args->share.oh.n_bytes = (void *)oh; +        args->cookie.n_bytes = (void *)cookiebytes; +} + +void +nlm4_prep_freeallargs (nlm4_freeallargs *args, nlm4_lkowner_t *oh) +{ +        memset (args, 0, sizeof (*args)); +        args->name = (void *)oh; +} + +void  nlm_copy_lkowner (gf_lkowner_t *dst, netobj *src)  {          dst->len = src->n_len;          memcpy (dst->data, src->n_bytes, dst->len);  } +int +nlm_is_oh_same_lkowner (gf_lkowner_t *a, netobj *b) +{ +        if (!a || !b) { +                gf_log (GF_NLM, GF_LOG_ERROR, "invalid args"); +                return -1; +        } + +        return (a->len == b->n_len && +                !memcmp (a->data, b->n_bytes, a->len)); +}  nfsstat3  nlm4_errno_to_nlm4stat (int errnum) @@ -251,6 +279,7 @@ nlm4_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req)          cs->req = req;          cs->nfsx = s->nfsx;          cs->nfs3state = s; +        cs->monitor = 1;          return cs;  } @@ -270,9 +299,11 @@ nlm_monitor (char *caller_name)                  }          }          UNLOCK (&nlm_client_list_lk); -        if (monitor == -1) { -                gf_log (GF_NLM, GF_LOG_ERROR, "%s was not found in the nlmclnt list", caller_name); -        } + +        if (monitor == -1) +                gf_log (GF_NLM, GF_LOG_ERROR, "%s was not found in " +                        "the nlmclnt list", caller_name); +          return monitor;  } @@ -401,6 +432,7 @@ nlm_add_nlmclnt (char *caller_name)                  INIT_LIST_HEAD(&nlmclnt->fdes);                  INIT_LIST_HEAD(&nlmclnt->nlm_clients); +                INIT_LIST_HEAD(&nlmclnt->shares);                  list_add (&nlmclnt->nlm_clients, &nlm_client_list);                  nlmclnt->caller_name = gf_strdup (caller_name); @@ -541,23 +573,31 @@ out:  }  nlm_client_t * -nlm_get_uniq (char *caller_name) +__nlm_get_uniq (char *caller_name)  {          nlm_client_t *nlmclnt = NULL; -        int nlmclnt_found = 0; -        LOCK (&nlm_client_list_lk); +        if (!caller_name) +                return NULL; +          list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) { -                if (!strcmp(caller_name, nlmclnt->caller_name)) { -                        nlmclnt_found = 1; -                        break; -                } +                if (!strcmp(caller_name, nlmclnt->caller_name)) +                        return nlmclnt;          } + +        return NULL; +} + +nlm_client_t * +nlm_get_uniq (char *caller_name) +{ +        nlm_client_t *nlmclnt = NULL; + +        LOCK (&nlm_client_list_lk); +        nlmclnt = __nlm_get_uniq (caller_name);          UNLOCK (&nlm_client_list_lk); -        if (nlmclnt_found) -                return nlmclnt; -        else -                return NULL; + +        return nlmclnt;  } @@ -1247,11 +1287,11 @@ nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                    int32_t op_ret, int32_t op_errno, struct gf_flock *flock,                    dict_t *xdata)  { -        nlm4_stats                      stat = nlm4_denied; -        nfs3_call_state_t              *cs = NULL; -        int                             transit_cnt = -1; +        nlm4_stats                       stat        = nlm4_denied; +        int                              transit_cnt = -1;          char                            *caller_name = NULL; -        pthread_t thr; +        nfs3_call_state_t               *cs          = NULL; +        pthread_t                        thr;          cs = frame->local;          caller_name = cs->args.nlm4_lockargs.alock.caller_name; @@ -1265,7 +1305,7 @@ nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  goto err;          } else {                  stat = nlm4_granted; -                if (!nlm_monitor (caller_name)) { +                if (cs->monitor && !nlm_monitor (caller_name)) {                          /* FIXME: handle nsm_monitor failure */                          pthread_create (&thr, NULL, nsm_monitor, (void*)caller_name);                  } @@ -1331,8 +1371,8 @@ int  nlm4_lock_resume (void *carg)  {          nlm4_stats                      stat = nlm4_failed; -        int                             ret = -1; -        nfs3_call_state_t               *cs = NULL; +        int                             ret  = -1; +        nfs3_call_state_t              *cs   = NULL;          if (!carg)                  return ret; @@ -1354,17 +1394,16 @@ nlm4err:          return ret;  } -  int -nlm4svc_lock (rpcsvc_request_t *req) +nlm4svc_lock_common (rpcsvc_request_t *req, int mon)  { -        xlator_t                        *vol = NULL; -        nlm4_stats                      stat = nlm4_failed; -        struct nfs_state               *nfs = NULL; -        nfs3_state_t                   *nfs3 = NULL; -        nfs3_call_state_t               *cs = NULL; -        int                             ret = RPCSVC_ACTOR_ERROR; -        struct nfs3_fh                  fh = {{0}, }; +        int                              ret      = RPCSVC_ACTOR_ERROR; +        nlm4_stats                       stat     = nlm4_failed; +        struct nfs3_fh                   fh       = {{0}, }; +        xlator_t                        *vol      = NULL; +        nfs3_state_t                    *nfs3     = NULL; +        nfs3_call_state_t               *cs       = NULL; +        struct nfs_state                *nfs      = NULL;          if (!req)                  return ret; @@ -1381,7 +1420,9 @@ nlm4svc_lock (rpcsvc_request_t *req)                  rpcsvc_request_seterr (req, GARBAGE_ARGS);                  goto rpcerr;          } +          fh = cs->lockfh; +        cs->monitor = mon;          nlm4_validate_gluster_fh (&fh, stat, nlm4err);          nlm4_map_fh_to_volume (cs->nfs3state, fh, req, vol, stat, nlm4err); @@ -1415,10 +1456,23 @@ rpcerr:          if (ret < 0) {                  nfs3_call_state_wipe (cs);          } +          return ret;  }  int +nlm4svc_lock (rpcsvc_request_t *req) +{ +        return nlm4svc_lock_common (req, 1); +} + +int +nlm4svc_nm_lock (rpcsvc_request_t *req) +{ +        return nlm4svc_lock_common (req, 0); +} + +int  nlm4svc_cancel_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                      int32_t op_ret, int32_t op_errno, struct gf_flock *flock,                      dict_t *xdata) @@ -1729,6 +1783,500 @@ rpcerr:          return ret;  } +int +nlm4_share_reply (nfs3_call_state_t *cs, nlm4_stats stat) +{ +        nlm4_shareres  res = {{0}, 0, 0}; + +        if (!cs) +                return -1; + +        res.cookie = cs->args.nlm4_shareargs.cookie; +        res.stat = stat; +        res.sequence = 0; + +        nlm4svc_submit_reply (cs->req, (void *)&res, +                              (nlm4_serializer)xdr_serialize_nlm4_shareres); +        return 0; +} + +nlm_share_t * +nlm4_share_new () +{ +        nlm_share_t      *share     = NULL; + +        share = GF_CALLOC (1, sizeof (nlm_share_t), +                           gf_nfs_mt_nlm4_share); +        if (!share) +                goto out; + +        INIT_LIST_HEAD (&share->client_list); +        INIT_LIST_HEAD (&share->inode_list); + out: +        return share; +} + +int +nlm4_add_share_to_inode (nlm_share_t *share) +{ +        int                    ret     = -1; +        uint64_t               ctx     = 0; +        struct list_head      *head    = NULL; +        xlator_t              *this    = NULL; +        inode_t               *inode   = NULL; + +        this = THIS; +        inode = share->inode; +        ret = inode_ctx_get (inode, this, &ctx); + +        head = (struct list_head *)ctx; + +        if (ret || !head) { +                head = GF_CALLOC (1, sizeof (struct list_head), +                                  gf_common_mt_list_head); +                if (!head ) { +                        ret = -1; +                        goto out; +                } + +                INIT_LIST_HEAD (head); +                ret = inode_ctx_put (inode, this, (uint64_t)head); +                if (ret) +                        goto out; +        } + +        list_add (&share->inode_list, head); + + out: +        if (ret && head) +                GF_FREE (head); + +        return ret; +} + +int +nlm4_approve_share_reservation (nfs3_call_state_t *cs) +{ +        int                       ret               = -1; +        uint64_t                  ctx               = 0; +        fsh_mode                  req_mode          = 0; +        fsh_access                req_access        = 0; +        inode_t                  *inode             = NULL; +        nlm_share_t              *share             = NULL; +        struct list_head         *head              = NULL; + +        if (!cs) +                goto out; + +        inode = cs->resolvedloc.inode; + +        ret = inode_ctx_get (inode, THIS, &ctx); +        if (ret) { +                ret = 0; +                goto out; +        } + +        head = (struct list_head *)ctx; +        if (!head || list_empty (head)) +                goto out; + +        req_mode = cs->args.nlm4_shareargs.share.mode; +        req_access = cs->args.nlm4_shareargs.share.access; + +        list_for_each_entry (share, head, inode_list) { +                ret = (((req_mode & share->access) == 0) && +                       ((req_access & share->mode) == 0)); +                if (!ret) { +                        ret = -1; +                        goto out; +                } +        } +        ret = 0; + + out: +         return ret; +} + +int +nlm4_create_share_reservation (nfs3_call_state_t *cs) +{ +        int                       ret        = -1; +        nlm_share_t              *share      = NULL; +        nlm_client_t             *client     = NULL; +        inode_t                  *inode      = NULL; + +        LOCK (&nlm_client_list_lk); + +        inode = inode_ref (cs->resolvedloc.inode); +        if (!inode) { +                gf_log (GF_NLM, GF_LOG_ERROR, "inode not found"); +                goto out; +        } + +        client = __nlm_get_uniq (cs->args.nlm4_shareargs.share.caller_name); +        if (!client) { +                /* DO NOT add client. the client is supposed +                   to be here, since nlm4svc_share adds it */ +                gf_log (GF_NLM, GF_LOG_ERROR, "client not found"); +                goto out; +        } + +        ret = nlm4_approve_share_reservation (cs); +        if (ret) +                goto out; + +        share = nlm4_share_new (); +        if (!share) { +                ret = -1; +                goto out; +        } + +        share->inode  = inode; +        share->mode   = cs->args.nlm4_shareargs.share.mode; +        share->access = cs->args.nlm4_shareargs.share.access; +        nlm_copy_lkowner (&share->lkowner, +                          &cs->args.nlm4_shareargs.share.oh); + +        ret = nlm4_add_share_to_inode (share); +        if (ret) +                goto out; + +        list_add (&share->client_list, &client->shares); + + out: +        if (ret && inode) { +                inode_unref (inode); +                if (share) +                        GF_FREE (share); +        } + +        UNLOCK (&nlm_client_list_lk); +        return ret; +} + +/* +  SHARE and UNSHARE calls DO NOT perform STACK_WIND, +  the (non-monitored) share reservations are maintained +  at *nfs xlator level only*, in memory +*/ +int +nlm4_share_resume (void *call_state) +{ +        int                             ret             = -1; +        nlm4_stats                      stat            = nlm4_failed; +        nfs3_call_state_t              *cs              = NULL; + +        if (!call_state) +                return ret; + +        cs = (nfs3_call_state_t *)call_state; +        nlm4_check_fh_resolve_status (cs, stat, out); + +        ret = nlm4_create_share_reservation (cs); +        if (!ret) +                stat = nlm4_granted; + + out: +        nlm4_share_reply (cs, stat); +        nfs3_call_state_wipe (cs); +        return 0; +} + +int +nlm4svc_share (rpcsvc_request_t *req) +{ +        nlm4_stats                    stat      = nlm4_failed; +        xlator_t                     *vol       = NULL; +        nfs3_state_t                 *nfs3      = NULL; +        nfs3_call_state_t            *cs        = NULL; +        struct nfs_state             *nfs       = NULL; +        struct nfs3_fh                fh        = {{0}, }; +        int                           ret       = RPCSVC_ACTOR_ERROR; + +        if (!req) +                return ret; + +        nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret); +        nfs = nfs_state (nfs3->nfsx); +        nlm4_handle_call_state_init (nfs->nfs3state, cs, req, +                                     stat, rpcerr); + +        nlm4_prep_shareargs (&cs->args.nlm4_shareargs, &cs->lockfh, +                             &cs->lkowner, cs->cookiebytes); + +        if (xdr_to_nlm4_shareargs (req->msg[0], +                                   &cs->args.nlm4_shareargs) <= 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding SHARE args"); +                rpcsvc_request_seterr (req, GARBAGE_ARGS); +                goto rpcerr; +        } + +        fh = cs->lockfh; +        nlm4_validate_gluster_fh (&fh, stat, nlm4err); +        nlm4_map_fh_to_volume (cs->nfs3state, fh, req, +                               vol, stat, nlm4err); + +        if (nlm_grace_period && !cs->args.nlm4_shareargs.reclaim) { +                gf_log (GF_NLM, GF_LOG_DEBUG, "NLM in grace period"); +                stat = nlm4_denied_grace_period; +                nlm4_share_reply (cs, stat); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +        cs->vol = vol; +        cs->trans = rpcsvc_request_transport_ref(req); +        nlm4_volume_started_check (nfs3, vol, ret, rpcerr); + +        ret = nlm_add_nlmclnt (cs->args.nlm4_shareargs.share.caller_name); + +        ret = nfs3_fh_resolve_and_resume (cs, &fh, NULL, nlm4_share_resume); + + nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "SHARE call failed"); +                nlm4_share_reply (cs, stat); +                nfs3_call_state_wipe (cs); +                return 0; +        } + + rpcerr: +        if (ret < 0) +                nfs3_call_state_wipe (cs); + +        return ret; +} + +int +nlm4_remove_share_reservation (nfs3_call_state_t *cs) +{ +        int                ret        = -1; +        uint64_t           ctx        = 0; +        fsh_mode           req_mode   = 0; +        fsh_access         req_access = 0; +        nlm_share_t       *share      = NULL; +        nlm_share_t       *tmp        = NULL; +        nlm_client_t      *client     = NULL; +        char              *caller     = NULL; +        inode_t           *inode      = NULL; +        xlator_t          *this       = NULL; +        struct list_head  *head       = NULL; +        nlm4_shareargs    *args       = NULL; + +        LOCK (&nlm_client_list_lk); + +        args = &cs->args.nlm4_shareargs; +        caller = args->share.caller_name; + +        client = __nlm_get_uniq (caller); +        if (!client) { +                gf_log (GF_NLM, GF_LOG_ERROR, +                        "client not found: %s", caller); +                goto out; +        } + +        inode = cs->resolvedloc.inode; +        if (!inode) { +                gf_log (GF_NLM, GF_LOG_ERROR, +                        "inode not found: client: %s", caller); +                goto out; +        } + +        this = THIS; +        ret = inode_ctx_get (inode, this, &ctx); +        if (ret) { +                gf_log (GF_NLM, GF_LOG_ERROR, +                        "no shares found for inode:" +                        "gfid: %s; client: %s", +                        inode->gfid, caller); +                goto out; +        } + +        head = (struct list_head *)ctx; +        if (list_empty (head)) { +                ret = -1; +                goto out; +        } + +        ret = 0; +        req_mode = args->share.mode; +        req_access = args->share.access; + +        list_for_each_entry_safe (share, tmp, head, inode_list) { +                ret = ((req_mode == share->mode) && +                       (req_access == share->access) && +                       nlm_is_oh_same_lkowner (&share->lkowner, &args->share.oh)); +                if (ret) { +                        list_del (&share->client_list); +                        list_del (&share->inode_list); +                        inode_unref (share->inode); +                        GF_FREE (share); +                        break; +                } +        } + +        ret = 0; + out: +        UNLOCK (&nlm_client_list_lk); +        return ret; + +} + +int +nlm4_unshare_resume (void *call_state) +{ +        int                ret        = -1; +        nlm4_stats         stat       = nlm4_failed; +        nfs3_call_state_t *cs         = NULL; + +        if (!call_state) +                return ret; + +        cs = (nfs3_call_state_t *)call_state; + +        nlm4_check_fh_resolve_status (cs, stat, out); +        ret = nlm4_remove_share_reservation (cs); +        if (!ret) +                stat = nlm4_granted; + + out: +        nlm4_share_reply (cs, stat); +        nfs3_call_state_wipe (cs); +        return 0; +} + +int +nlm4svc_unshare (rpcsvc_request_t *req) +{ +        nlm4_stats                    stat      = nlm4_failed; +        xlator_t                     *vol       = NULL; +        nfs3_state_t                 *nfs3      = NULL; +        nfs3_call_state_t            *cs        = NULL; +        struct nfs_state             *nfs       = NULL; +        struct nfs3_fh                fh        = {{0}, }; +        int                           ret       = RPCSVC_ACTOR_ERROR; + +        if (!req) +                return ret; + +        nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret); +        nfs = nfs_state (nfs3->nfsx); +        nlm4_handle_call_state_init (nfs->nfs3state, cs, req, +                                     stat, rpcerr); + +        nlm4_prep_shareargs (&cs->args.nlm4_shareargs, &cs->lockfh, +                             &cs->lkowner, cs->cookiebytes); + +        if (xdr_to_nlm4_shareargs (req->msg[0], +                                   &cs->args.nlm4_shareargs) <= 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding UNSHARE args"); +                rpcsvc_request_seterr (req, GARBAGE_ARGS); +                goto rpcerr; +        } + +        fh = cs->lockfh; +        nlm4_validate_gluster_fh (&fh, stat, nlm4err); +        nlm4_map_fh_to_volume (cs->nfs3state, fh, req, +                               vol, stat, nlm4err); + +        if (nlm_grace_period && !cs->args.nlm4_shareargs.reclaim) { +                gf_log (GF_NLM, GF_LOG_DEBUG, "NLM in grace period"); +                stat = nlm4_denied_grace_period; +                nlm4_share_reply (cs, stat); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +        cs->vol = vol; +        cs->trans = rpcsvc_request_transport_ref(req); +        nlm4_volume_started_check (nfs3, vol, ret, rpcerr); + +        ret = nfs3_fh_resolve_and_resume (cs, &fh, NULL, +                                          nlm4_unshare_resume); + + nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "UNSHARE call failed"); +                nlm4_share_reply (cs, stat); +                ret = 0; +                return 0; +        } + + rpcerr: +        if (ret < 0) +                nfs3_call_state_wipe (cs); + +        return ret; +} + +int +nlm4_free_all_shares (char *caller_name) +{ +        nlm_share_t             *share      = NULL; +        nlm_share_t             *tmp        = NULL; +        nlm_client_t            *client     = NULL; + +        LOCK (&nlm_client_list_lk); + +        client = __nlm_get_uniq (caller_name); +        if (!client) { +                gf_log (GF_NLM, GF_LOG_DEBUG, +                        "client not found: %s", caller_name); +                goto out; +        } + +        list_for_each_entry_safe (share, tmp, &client->shares, client_list) { +                list_del (&share->inode_list); +                list_del (&share->client_list); +                inode_unref (share->inode); +                GF_FREE (share); +        } + out: +        UNLOCK (&nlm_client_list_lk); +        return 0; +} + +int +nlm4svc_free_all (rpcsvc_request_t *req) +{ +        int                           ret       = RPCSVC_ACTOR_ERROR; +        nlm4_stats                    stat      = nlm4_failed; +        nfs3_state_t                 *nfs3      = NULL; +        nfs3_call_state_t            *cs        = NULL; +        struct nfs_state             *nfs       = NULL; + +        nlm4_validate_nfs3_state (req, nfs3, stat, err, ret); +        nfs = nfs_state (nfs3->nfsx); +        nlm4_handle_call_state_init (nfs->nfs3state, cs, +                                     req, stat, err); + +        nlm4_prep_freeallargs (&cs->args.nlm4_freeallargs, +                               &cs->lkowner); + +        if (xdr_to_nlm4_freeallargs (req->msg[0], +                                     &cs->args.nlm4_freeallargs) <= 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding FREE_ALL args"); +                rpcsvc_request_seterr (req, GARBAGE_ARGS); +                goto err; +        } + +        ret = nlm4_free_all_shares (cs->args.nlm4_freeallargs.name); +        if (ret) +                goto err; + +        ret = nlm_cleanup_fds (cs->args.nlm4_freeallargs.name); +        if (ret) +                goto err; + + err: +        nfs3_call_state_wipe (cs); +        if (ret) +                gf_log (GF_NLM, GF_LOG_DEBUG, +                        "error in free all; stat: %d", stat); +        return ret; + +} +  void  nlm4svc_sm_notify (struct nlm_sm_status *status)  { @@ -1757,17 +2305,17 @@ rpcsvc_actor_t  nlm4svc_actors[NLM4_PROC_COUNT] = {          {"LOCK",       NLM4_LOCK_RES,     NULL,              NULL, NULL},          {"CANCEL",     NLM4_CANCEL_RES,   NULL,              NULL, NULL},          {"UNLOCK",     NLM4_UNLOCK_RES,   NULL,              NULL, NULL}, -        /* 15 ; 17,18,19 are dummy actors */ +        /* 15 ; procedures 17,18,19 are not defined by nlm */          {"GRANTED",    NLM4_GRANTED_RES,  NULL,              NULL, NULL},          {"SM_NOTIFY",  NLM4_SM_NOTIFY,    NULL,              NULL, NULL},          {"SEVENTEEN",  NLM4_SEVENTEEN,    NULL,              NULL, NULL},          {"EIGHTEEN",   NLM4_EIGHTEEN,     NULL,              NULL, NULL},          {"NINETEEN",   NLM4_NINETEEN,     NULL,              NULL, NULL},          /* 20 */ -        {"SHARE",      NLM4_SHARE,        NULL,              NULL, NULL}, -        {"UNSHARE",    NLM4_UNSHARE,      NULL,              NULL, NULL}, -        {"NM_LOCK",    NLM4_NM_LOCK,      NULL,              NULL, NULL}, -        {"FREE_ALL",   NLM4_FREE_ALL,     nlm4svc_null,      NULL, NULL}, +        {"SHARE",      NLM4_SHARE,        nlm4svc_share,     NULL, NULL}, +        {"UNSHARE",    NLM4_UNSHARE,      nlm4svc_unshare,   NULL, NULL}, +        {"NM_LOCK",    NLM4_NM_LOCK,      nlm4svc_nm_lock,   NULL, NULL}, +        {"FREE_ALL",   NLM4_FREE_ALL,     nlm4svc_free_all,  NULL, NULL},  };  rpcsvc_program_t        nlm4prog = { diff --git a/xlators/nfs/server/src/nlm4.h b/xlators/nfs/server/src/nlm4.h index db5874387..bcc7ae573 100644 --- a/xlators/nfs/server/src/nlm4.h +++ b/xlators/nfs/server/src/nlm4.h @@ -60,11 +60,21 @@ typedef struct nlm_client {          pid_t uniq;          struct list_head nlm_clients;          struct list_head fdes; +        struct list_head shares;          struct rpc_clnt *rpc_clnt;          char *caller_name;          int nsm_monitor;  } nlm_client_t; +typedef struct nlm_share { +        struct list_head     client_list; +        struct list_head     inode_list; +        gf_lkowner_t         lkowner; +        inode_t             *inode; +        fsh_mode             mode; +        fsh_access           access; +} nlm_share_t; +  typedef struct nlm_fde {          struct list_head fde_list;          fd_t *fd;  | 
