Beispiel #1
0
/*
 * LOCK: Try to create a lock
 *
 *			Programmer Harassment Alert
 *
 * When given a blocking lock request in a sync RPC call, the HPUX lockd
 * will faithfully return LCK_BLOCKED but never cares to notify us when
 * the lock could be granted. This way, our local process could hang
 * around forever waiting for the callback.
 *
 *  Solution A:	Implement busy-waiting
 *  Solution B: Use the async version of the call (NLM_LOCK_{MSG,RES})
 *
 * For now I am implementing solution A, because I hate the idea of
 * re-implementing lockd for a third time in two months. The async
 * calls shouldn't be too hard to do, however.
 *
 * This is one of the lovely things about standards in the NFS area:
 * they're so soft and squishy you can't really blame HP for doing this.
 */
static int
nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
{
	struct nlm_host	*host = req->a_host;
	struct nlm_res	*resp = &req->a_res;
	int		status;

	if (!host->h_monitored && nsm_monitor(host) < 0) {
		printk(KERN_NOTICE "lockd: failed to monitor %s\n",
					host->h_name);
		return -ENOLCK;
	}

	while (1) {
		if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) {
			if (resp->status != NLM_LCK_BLOCKED)
				break;
			status = nlmclnt_block(host, fl, &resp->status);
		}
		if (status < 0)
			return status;
	}

	if (resp->status == NLM_LCK_GRANTED) {
		fl->fl_u.nfs_fl.state = host->h_state;
		fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
	}

	return nlm_stat_to_errno(resp->status);
}
Beispiel #2
0
/*
 * Obtain client and file from arguments
 */
static u32
nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
			struct nlm_host **hostp, struct nlm_file **filp)
{
	struct nlm_host		*host = NULL;
	struct nlm_file		*file = NULL;
	struct nlm_lock		*lock = &argp->lock;
	u32			error = 0;

	/* nfsd callbacks must have been installed for this procedure */
	if (!nlmsvc_ops)
		return nlm_lck_denied_nolocks;

	/* Obtain handle for client host */
	if (rqstp->rq_client == NULL) {
		printk(KERN_NOTICE
			"lockd: unauthenticated request from (%08x:%d)\n",
			ntohl(rqstp->rq_addr.sin_addr.s_addr),
			ntohs(rqstp->rq_addr.sin_port));
		return nlm_lck_denied_nolocks;
	}

	/* Obtain host handle */
	if (!(host = nlmsvc_lookup_host(rqstp))
	 || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0))
		goto no_locks;
	*hostp = host;

	/* Obtain file pointer. Not used by FREE_ALL call. */
	if (filp != NULL) {
		if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
			goto no_locks;
		*filp = file;

		/* Set up the missing parts of the file_lock structure */
		lock->fl.fl_file  = &file->f_file;
		lock->fl.fl_owner = (fl_owner_t) host;
	}

	return 0;

no_locks:
	if (host)
		nlm_release_host(host);
 	if (error)
		return error;	
	return nlm_lck_denied_nolocks;
}
Beispiel #3
0
/*
 * Obtain client and file from arguments
 */
static __be32
nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
			struct nlm_host **hostp, struct nlm_file **filp)
{
	struct nlm_host		*host = NULL;
	struct nlm_file		*file = NULL;
	struct nlm_lock		*lock = &argp->lock;
	__be32			error = 0;

	/* nfsd callbacks must have been installed for this procedure */
	if (!nlmsvc_ops)
		return nlm_lck_denied_nolocks;

	/* Obtain host handle */
	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
	 || (argp->monitor && nsm_monitor(host) < 0))
		goto no_locks;
	*hostp = host;

	/* Obtain file pointer. Not used by FREE_ALL call. */
	if (filp != NULL) {
		if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
			goto no_locks;
		*filp = file;

		/* Set up the missing parts of the file_lock structure */
		lock->fl.fl_file  = file->f_file;
		lock->fl.fl_owner = (fl_owner_t) host;
		lock->fl.fl_lmops = &nlmsvc_lock_operations;
	}

	return 0;

no_locks:
	if (host)
		nlm_release_host(host);
 	if (error)
		return error;	
	return nlm_lck_denied_nolocks;
}
Beispiel #4
0
static __be32
nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
			struct nlm_host **hostp, struct nlm_file **filp)
{
	struct nlm_host		*host = NULL;
	struct nlm_file		*file = NULL;
	struct nlm_lock		*lock = &argp->lock;
	__be32			error = 0;

	
	if (!nlmsvc_ops)
		return nlm_lck_denied_nolocks;

	
	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
	 || (argp->monitor && nsm_monitor(host) < 0))
		goto no_locks;
	*hostp = host;

	
	if (filp != NULL) {
		error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh));
		if (error != 0)
			goto no_locks;
		*filp = file;

		
		lock->fl.fl_file  = file->f_file;
		lock->fl.fl_owner = (fl_owner_t) host;
		lock->fl.fl_lmops = &nlmsvc_lock_operations;
	}

	return 0;

no_locks:
	nlmsvc_release_host(host);
	if (error)
		return error;
	return nlm_lck_denied_nolocks;
}
Beispiel #5
0
state_nlm_client_t *get_nlm_client(care_t               care,
                                   SVCXPRT            * xprt,
                                   state_nsm_client_t * pnsm_client,
                                   char               * caller_name)
{
  state_nlm_client_t   key;
  state_nlm_client_t * pclient;
  char                 str[HASHTABLE_DISPLAY_STRLEN];
  struct hash_latch    latch;
  hash_error_t         rc;
  hash_buffer_t        buffkey;
  hash_buffer_t        buffval;

  if(caller_name == NULL)
    return NULL;

  memset(&key, 0, sizeof(key));

  key.slc_nsm_client          = pnsm_client;
  key.slc_nlm_caller_name_len = strlen(caller_name);
  key.slc_client_type         = svc_get_xprt_type(xprt);

  if(key.slc_nlm_caller_name_len > LM_MAXSTRLEN)
    return NULL;

  key.slc_nlm_caller_name = caller_name;
  
  if(isFullDebug(COMPONENT_STATE))
    {
      display_nlm_client(&key, str);
      LogFullDebug(COMPONENT_STATE,
                   "Find {%s}", str);
    }

  buffkey.pdata = &key;
  buffkey.len   = sizeof(key);

  rc = HashTable_GetLatch(ht_nlm_client,
                          &buffkey,
                          &buffval,
                          TRUE,
                          &latch);

  /* If we found it, return it */
  if(rc == HASHTABLE_SUCCESS)
    {
      pclient = buffval.pdata;

      /* Return the found NLM Client */
      if(isFullDebug(COMPONENT_STATE))
        {
          display_nlm_client(pclient, str);
          LogFullDebug(COMPONENT_STATE,
                       "Found {%s}",
                       str);
        }

      /* Increment refcount under hash latch.
       * This prevents dec ref from removing this entry from hash if a race
       * occurs.
       */
      inc_nlm_client_ref(pclient);

      HashTable_ReleaseLatched(ht_nlm_client, &latch);

      if(care == CARE_MONITOR && !nsm_monitor(pnsm_client))
          {
            dec_nlm_client_ref(pclient);
            pclient = NULL;
          }

      return pclient;
    }

  /* An error occurred, return NULL */
  if(rc != HASHTABLE_ERROR_NO_SUCH_KEY)
    {
      display_nlm_client(&key, str);

      LogCrit(COMPONENT_STATE,
              "Error %s, could not find {%s}",
              hash_table_err_to_str(rc), str);

      return NULL;
    }

  /* Not found, but we don't care, return NULL */
  if(care == CARE_NOT)
    {
      /* Return the found NLM Client */
      if(isFullDebug(COMPONENT_STATE))
        {
          display_nlm_client(&key, str);
          LogFullDebug(COMPONENT_STATE,
                       "Ignoring {%s}",
                       str);
        }

      HashTable_ReleaseLatched(ht_nlm_client, &latch);

      return NULL;
    }

  pclient = gsh_malloc(sizeof(*pclient));

  if(pclient == NULL)
    {
      display_nlm_client(&key, str);
      LogCrit(COMPONENT_STATE,
              "No memory for {%s}",
              str);

      return NULL;
    }

  /* Copy everything over */
  memcpy(pclient, &key, sizeof(key));

  pclient->slc_nlm_caller_name = gsh_strdup(key.slc_nlm_caller_name);

  /* Take a reference to the NSM Client */
  inc_nsm_client_ref(pnsm_client);

  if(pclient->slc_nlm_caller_name == NULL)
    {
      /* Discard the created client */
      free_nlm_client(pclient);
      return NULL;
    }

  pclient->slc_refcount = 1;

  if(isFullDebug(COMPONENT_STATE))
    {
      display_nlm_client(pclient, str);
      LogFullDebug(COMPONENT_STATE,
                   "New {%s}", str);
    }

  buffkey.pdata = pclient;
  buffkey.len   = sizeof(*pclient);
  buffval.pdata = pclient;
  buffval.len   = sizeof(*pclient);

  rc = HashTable_SetLatched(ht_nlm_client,
                            &buffval,
                            &buffval,
                            &latch,
                            FALSE,
                            NULL,
                            NULL);

  /* An error occurred, return NULL */
  if(rc != HASHTABLE_SUCCESS)
    {
      display_nlm_client(pclient, str);

      LogCrit(COMPONENT_STATE,
              "Error %s, inserting {%s}",
              hash_table_err_to_str(rc), str);

      free_nlm_client(pclient);

      return NULL;
    }

  if(care != CARE_MONITOR || nsm_monitor(pnsm_client))
    return pclient;

  /* Failed to monitor, release client reference
   * and almost certainly remove it from the hash table.
   */
  dec_nlm_client_ref(pclient);

  return NULL;
}
Beispiel #6
0
state_nsm_client_t *get_nsm_client(care_t    care,
                                   SVCXPRT * xprt,
                                   char    * caller_name)
{
  state_nsm_client_t   key;
  state_nsm_client_t * pclient;
  char                 sock_name[SOCK_NAME_MAX];
  char                 str[HASHTABLE_DISPLAY_STRLEN];
  struct hash_latch    latch;
  hash_error_t         rc;
  hash_buffer_t        buffkey;
  hash_buffer_t        buffval;

  if(caller_name == NULL)
    return NULL;

  memset(&key, 0, sizeof(key));

  if(nfs_param.core_param.nsm_use_caller_name)
    {
      key.ssc_nlm_caller_name_len = strlen(caller_name);

      if(key.ssc_nlm_caller_name_len > LM_MAXSTRLEN)
        {
          return NULL;
        }

      key.ssc_nlm_caller_name = caller_name;
    }
  else if(xprt == NULL)
    {
      int rc = ipstring_to_sockaddr(caller_name, &key.ssc_client_addr);
      if(rc != 0)
        {
          LogEvent(COMPONENT_STATE,
                   "Error %s, converting caller_name %s to an ipaddress",
                   gai_strerror(rc), caller_name);

          return NULL;
        }

      key.ssc_nlm_caller_name_len = strlen(caller_name);

      if(key.ssc_nlm_caller_name_len > LM_MAXSTRLEN)
        {
          return NULL;
        }

      key.ssc_nlm_caller_name = caller_name;
    }
  else
    {
      key.ssc_nlm_caller_name = sock_name;

      if(copy_xprt_addr(&key.ssc_client_addr, xprt) == 0)
        {
          LogCrit(COMPONENT_STATE,
                  "Error converting caller_name %s to an ipaddress",
                  caller_name);

          return NULL;
        }

      if(sprint_sockip(&key.ssc_client_addr,
                       key.ssc_nlm_caller_name,
                       sizeof(sock_name)) == 0)
        {
          LogCrit(COMPONENT_STATE,
                  "Error converting caller_name %s to an ipaddress",
                  caller_name);

          return NULL;
        }

      key.ssc_nlm_caller_name_len = strlen(key.ssc_nlm_caller_name);
    }

  
  if(isFullDebug(COMPONENT_STATE))
    {
      display_nsm_client(&key, str);
      LogFullDebug(COMPONENT_STATE,
                   "Find {%s}", str);
    }

  buffkey.pdata = &key;
  buffkey.len   = sizeof(key);

  rc = HashTable_GetLatch(ht_nsm_client,
                          &buffkey,
                          &buffval,
                          TRUE,
                          &latch);

  /* If we found it, return it */
  if(rc == HASHTABLE_SUCCESS)
    {
      pclient = buffval.pdata;

      /* Return the found NSM Client */
      if(isFullDebug(COMPONENT_STATE))
        {
          display_nsm_client(pclient, str);
          LogFullDebug(COMPONENT_STATE,
                       "Found {%s}",
                       str);
        }

      /* Increment refcount under hash latch.
       * This prevents dec ref from removing this entry from hash if a race
       * occurs.
       */
      inc_nsm_client_ref(pclient);

      HashTable_ReleaseLatched(ht_nsm_client, &latch);

      if(care == CARE_MONITOR && !nsm_monitor(pclient))
          {
            dec_nsm_client_ref(pclient);
            pclient = NULL;
          }

      return pclient;
    }

  /* An error occurred, return NULL */
  if(rc != HASHTABLE_ERROR_NO_SUCH_KEY)
    {
      display_nsm_client(&key, str);

      LogCrit(COMPONENT_STATE,
              "Error %s, could not find {%s}",
              hash_table_err_to_str(rc), str);

      return NULL;
    }

  /* Not found, but we don't care, return NULL */
  if(care == CARE_NOT)
    {
      /* Return the found NSM Client */
      if(isFullDebug(COMPONENT_STATE))
        {
          display_nsm_client(&key, str);
          LogFullDebug(COMPONENT_STATE,
                       "Ignoring {%s}",
                       str);
        }

      HashTable_ReleaseLatched(ht_nsm_client, &latch);

      return NULL;
    }

  pclient = gsh_malloc(sizeof(*pclient));

  if(pclient == NULL)
    {
      display_nsm_client(&key, str);
      LogCrit(COMPONENT_STATE,
              "No memory for {%s}",
              str);

      return NULL;
    }

  /* Copy everything over */
  memcpy(pclient, &key, sizeof(key));

  if(pthread_mutex_init(&pclient->ssc_mutex, NULL) == -1)
    {
      /* Mutex initialization failed, free the created client */
      display_nsm_client(&key, str);
      LogCrit(COMPONENT_STATE,
              "Could not init mutex for {%s}",
              str);

      gsh_free(pclient);
      return NULL;
    }

  pclient->ssc_nlm_caller_name = gsh_strdup(key.ssc_nlm_caller_name);

  if(pclient->ssc_nlm_caller_name == NULL)
    {
      /* Discard the created client */
      free_nsm_client(pclient);
      return NULL;
    }

  init_glist(&pclient->ssc_lock_list);
  init_glist(&pclient->ssc_share_list);
  pclient->ssc_refcount = 1;

  if(isFullDebug(COMPONENT_STATE))
    {
      display_nsm_client(pclient, str);
      LogFullDebug(COMPONENT_STATE,
                   "New {%s}", str);
    }

  buffkey.pdata = pclient;
  buffkey.len   = sizeof(*pclient);
  buffval.pdata = pclient;
  buffval.len   = sizeof(*pclient);

  rc = HashTable_SetLatched(ht_nsm_client,
                            &buffval,
                            &buffval,
                            &latch,
                            FALSE,
                            NULL,
                            NULL);

  /* An error occurred, return NULL */
  if(rc != HASHTABLE_SUCCESS)
    {
      display_nsm_client(pclient, str);

      LogCrit(COMPONENT_STATE,
              "Error %s, inserting {%s}",
              hash_table_err_to_str(rc), str);

      free_nsm_client(pclient);

      return NULL;
    }

  if(care != CARE_MONITOR || nsm_monitor(pclient))
    return pclient;

  /* Failed to monitor, release client reference
   * and almost certainly remove it from the hash table.
   */
  dec_nsm_client_ref(pclient);

  return NULL;
}
Beispiel #7
0
state_nsm_client_t *get_nsm_client(care_t       care,
                                   SVCXPRT    * xprt,
                                   const char * caller_name)
{
  state_nsm_client_t *pkey, *pclient;

  if(caller_name == NULL)
    return NULL;

  pkey = (state_nsm_client_t *)Mem_Alloc(sizeof(*pkey));
  if(pkey == NULL)
    return NULL;

  memset(pkey, 0, sizeof(*pkey));
  pkey->ssc_refcount            = 1;

  if(nfs_param.core_param.nsm_use_caller_name)
    {
      pkey->ssc_nlm_caller_name_len = strlen(caller_name);

      if(pkey->ssc_nlm_caller_name_len > LM_MAXSTRLEN)
        {
          /* Discard the key we created */
          free_nsm_client(pkey);
          return NULL;
        }

      pkey->ssc_nlm_caller_name = Mem_Alloc(pkey->ssc_nlm_caller_name_len + 1);
      if(pkey->ssc_nlm_caller_name == NULL)
        {
          /* Discard the key we created */
          free_nsm_client(pkey);
          return NULL;
        }

      memcpy(pkey->ssc_nlm_caller_name,
             caller_name,
             pkey->ssc_nlm_caller_name_len);
      pkey->ssc_nlm_caller_name[pkey->ssc_nlm_caller_name_len] = '\0';
    }
  else
    {
      pkey->ssc_nlm_caller_name_len = SOCK_NAME_MAX;
      pkey->ssc_nlm_caller_name     = Mem_Alloc(SOCK_NAME_MAX);
      if(pkey->ssc_nlm_caller_name == NULL)
        {
          /* Discard the key we created */
          free_nsm_client(pkey);
          return NULL;
        }

      if(copy_xprt_addr(&pkey->ssc_client_addr, xprt) == 0)
        {
          /* Discard the key we created */
          free_nsm_client(pkey);
          return NULL;
        }

      if(sprint_sockip(&pkey->ssc_client_addr, pkey->ssc_nlm_caller_name, SOCK_NAME_MAX) == 0)
        {
          /* Discard the key we created */
          free_nsm_client(pkey);
          return NULL;
        }
      pkey->ssc_nlm_caller_name_len = strlen(pkey->ssc_nlm_caller_name);
    }

  
  if(isFullDebug(COMPONENT_STATE))
    {
      char str[HASHTABLE_DISPLAY_STRLEN];

      display_nsm_client(pkey, str);
      LogFullDebug(COMPONENT_STATE,
                   "Find NSM Client pkey {%s}", str);
    }

  /* If we found it, return it, if we don't care, return NULL */
  if(nsm_client_Get_Pointer(pkey, &pclient) == 1 || care == CARE_NOT)
    {
      /* Discard the key we created and return the found NSM Client */
      free_nsm_client(pkey);

      if(isFullDebug(COMPONENT_STATE))
        {
          char str[HASHTABLE_DISPLAY_STRLEN];

          display_nsm_client(pclient, str);
          LogFullDebug(COMPONENT_STATE,
                       "Found NSM Client {%s}",
                       str);
        }

      if(care == CARE_MONITOR)
        if(!nsm_monitor(pclient))
          {
            dec_nsm_client_ref(pclient);
            return NULL;
          }

      return pclient;
    }

  pclient = (state_nsm_client_t *)Mem_Alloc(sizeof(*pkey));
  if(pclient == NULL)
    {
      free_nsm_client(pkey);
      return NULL;
    }

  /* Copy everything over */
  *pclient = *pkey;

  pclient->ssc_nlm_caller_name = Mem_Alloc(pkey->ssc_nlm_caller_name_len + 1);
  if(pclient->ssc_nlm_caller_name == NULL)
    {
      /* Discard the key and created client */
      free_nsm_client(pkey);
      free_nsm_client(pclient);
      return NULL;
    }

  memcpy(pclient->ssc_nlm_caller_name,
         pkey->ssc_nlm_caller_name,
         pclient->ssc_nlm_caller_name_len);
  pclient->ssc_nlm_caller_name[pclient->ssc_nlm_caller_name_len] = '\0';

  init_glist(&pclient->ssc_lock_list);

  if(isFullDebug(COMPONENT_STATE))
    {
      char str[HASHTABLE_DISPLAY_STRLEN];

      display_nsm_client(pclient, str);
      LogFullDebug(COMPONENT_STATE,
                   "New NSM Client {%s}", str);
    }

  if(pthread_mutex_init(&pclient->ssc_mutex, NULL) == -1)
    {
      /* Mutex initialization failed, free the key and created client */
      free_nsm_client(pkey);
      free_nsm_client(pclient);
      return NULL;
    }

  if(nsm_client_Set(pkey, pclient) == 1)
    {
      if(isFullDebug(COMPONENT_STATE))
        {
          char str[HASHTABLE_DISPLAY_STRLEN];

          display_nsm_client(pclient, str);
          LogFullDebug(COMPONENT_STATE,
                       "Set NSM Client {%s}",
                       str);
        }

      if(care != CARE_MONITOR || nsm_monitor(pclient))
        return pclient;

      dec_nsm_client_ref(pclient);
      return NULL;
    }

  free_nsm_client(pkey);
  free_nsm_client(pclient);
  return NULL;
}
Beispiel #8
0
state_nlm_client_t *get_nlm_client(care_t               care,
                                   SVCXPRT            * xprt,
                                   state_nsm_client_t * pnsm_client,
                                   const char         * caller_name)
{
  state_nlm_client_t *pkey, *pclient;

  if(caller_name == NULL)
    return NULL;

  pkey = (state_nlm_client_t *)Mem_Alloc(sizeof(*pkey));
  if(pkey == NULL)
    return NULL;

  memset(pkey, 0, sizeof(*pkey));
  pkey->slc_refcount            = 1;
  pkey->slc_nsm_client          = pnsm_client;
  pkey->slc_nlm_caller_name_len = strlen(caller_name);
  pkey->slc_client_type         = get_xprt_type(xprt);

  if(pkey->slc_nlm_caller_name_len > LM_MAXSTRLEN)
    {
      /* Discard the key we created */
      Mem_Free(pkey);
      return NULL;
    }

  memcpy(pkey->slc_nlm_caller_name,
         caller_name,
         pkey->slc_nlm_caller_name_len);
  pkey->slc_nlm_caller_name[pkey->slc_nlm_caller_name_len] = '\0';
  
  if(isFullDebug(COMPONENT_STATE))
    {
      char str[HASHTABLE_DISPLAY_STRLEN];

      display_nlm_client(pkey, str);
      LogFullDebug(COMPONENT_STATE,
                   "Find NLM Client pkey {%s}", str);
    }

  /* If we found it, return it, if we don't care, return NULL */
  if(nlm_client_Get_Pointer(pkey, &pclient) == 1 || care == CARE_NOT)
    {
      /* Discard the key we created and return the found NLM Client */
      Mem_Free(pkey);

      if(isFullDebug(COMPONENT_STATE))
        {
          char str[HASHTABLE_DISPLAY_STRLEN];

          display_nlm_client(pclient, str);
          LogFullDebug(COMPONENT_STATE,
                       "Found NLM Client {%s}",
                       str);
        }

      if(care == CARE_MONITOR)
        if(!nsm_monitor(pnsm_client))
          {
            dec_nlm_client_ref(pclient);
            return NULL;
          }

      return pclient;
    }

  pclient = (state_nlm_client_t *)Mem_Alloc(sizeof(*pkey));
  if(pclient == NULL)
    {
      Mem_Free(pkey);
      return NULL;
    }

  /* Copy everything over */
  *pclient = *pkey;

  if(isFullDebug(COMPONENT_STATE))
    {
      char str[HASHTABLE_DISPLAY_STRLEN];

      display_nlm_client(pclient, str);
      LogFullDebug(COMPONENT_STATE,
                   "New NLM Client {%s}", str);
    }

  if(pthread_mutex_init(&pclient->slc_mutex, NULL) == -1)
    {
      /* Mutex initialization failed, free the key and created owner */
      Mem_Free(pkey);
      Mem_Free(pclient);
      return NULL;
    }

  /* Ref count the NSM Client as being used by this NLM Client */
  inc_nsm_client_ref(pnsm_client);

  if(nlm_client_Set(pkey, pclient) == 1)
    {
      if(isFullDebug(COMPONENT_STATE))
        {
          char str[HASHTABLE_DISPLAY_STRLEN];

          display_nlm_client(pclient, str);
          LogFullDebug(COMPONENT_STATE,
                       "Set NLM Client {%s}",
                       str);
        }

      if(care != CARE_MONITOR || nsm_monitor(pnsm_client))
        return pclient;

      dec_nlm_client_ref(pclient);
      return NULL;
    }

  dec_nsm_client_ref(pnsm_client);
  Mem_Free(pkey);
  Mem_Free(pclient);
  return NULL;
}
Beispiel #9
0
/**
 * @brief Get an NSM client
 *
 * @param[in] care        Care status
 * @param[in] xprt        RPC transport
 * @param[in] caller_name Caller name
 *
 * @return NSM client or NULL.
 */
state_nsm_client_t *get_nsm_client(care_t care, SVCXPRT *xprt,
				   char *caller_name)
{
	state_nsm_client_t key;
	state_nsm_client_t *pclient;
	char str[LOG_BUFF_LEN];
	struct display_buffer dspbuf = {sizeof(str), str, str};
	struct hash_latch latch;
	hash_error_t rc;
	struct gsh_buffdesc buffkey;
	struct gsh_buffdesc buffval;

	if (caller_name == NULL)
		return NULL;

	memset(&key, 0, sizeof(key));

	if (nfs_param.core_param.nsm_use_caller_name) {
		key.ssc_nlm_caller_name_len = strlen(caller_name);

		if (key.ssc_nlm_caller_name_len > LM_MAXSTRLEN)
			return NULL;

		key.ssc_nlm_caller_name = caller_name;
	} else if (op_ctx->client == NULL) {
		LogCrit(COMPONENT_STATE,
			"No gsh_client for caller_name %s", caller_name);

		return NULL;
	} else {
		key.ssc_nlm_caller_name = op_ctx->client->hostaddr_str;
		key.ssc_nlm_caller_name_len = strlen(key.ssc_nlm_caller_name);
		key.ssc_client = op_ctx->client;
	}

	if (isFullDebug(COMPONENT_STATE)) {
		display_nsm_client(&dspbuf, &key);
		LogFullDebug(COMPONENT_STATE, "Find {%s}", str);
	}

	buffkey.addr = &key;
	buffkey.len = sizeof(key);

	rc = hashtable_getlatch(ht_nsm_client, &buffkey, &buffval, true,
				&latch);

	/* If we found it, return it */
	if (rc == HASHTABLE_SUCCESS) {
		pclient = buffval.addr;

		/* Return the found NSM Client */
		if (isFullDebug(COMPONENT_STATE)) {
			display_nsm_client(&dspbuf, pclient);
			LogFullDebug(COMPONENT_STATE, "Found {%s}", str);
		}

		/* Increment refcount under hash latch.
		 * This prevents dec ref from removing this entry from hash
		 * if a race occurs.
		 */
		inc_nsm_client_ref(pclient);

		hashtable_releaselatched(ht_nsm_client, &latch);

		if (care == CARE_MONITOR && !nsm_monitor(pclient)) {
			dec_nsm_client_ref(pclient);
			pclient = NULL;
		}

		return pclient;
	}

	/* An error occurred, return NULL */
	if (rc != HASHTABLE_ERROR_NO_SUCH_KEY) {
		display_nsm_client(&dspbuf, &key);

		LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}",
			hash_table_err_to_str(rc), str);

		return NULL;
	}

	/* Not found, but we don't care, return NULL */
	if (care == CARE_NOT) {
		/* Return the found NSM Client */
		if (isFullDebug(COMPONENT_STATE)) {
			display_nsm_client(&dspbuf, &key);
			LogFullDebug(COMPONENT_STATE, "Ignoring {%s}", str);
		}

		hashtable_releaselatched(ht_nsm_client, &latch);

		return NULL;
	}

	pclient = gsh_malloc(sizeof(*pclient));

	if (pclient == NULL) {
		display_nsm_client(&dspbuf, &key);
		LogCrit(COMPONENT_STATE, "No memory for {%s}", str);

		return NULL;
	}

	/* Copy everything over */
	memcpy(pclient, &key, sizeof(key));

	PTHREAD_MUTEX_init(&pclient->ssc_mutex, NULL);

	pclient->ssc_nlm_caller_name = gsh_strdup(key.ssc_nlm_caller_name);

	if (pclient->ssc_nlm_caller_name == NULL) {
		/* Discard the created client */
		PTHREAD_MUTEX_destroy(&pclient->ssc_mutex);
		free_nsm_client(pclient);
		return NULL;
	}

	glist_init(&pclient->ssc_lock_list);
	glist_init(&pclient->ssc_share_list);
	pclient->ssc_refcount = 1;

	if (op_ctx->client != NULL) {
		pclient->ssc_client = op_ctx->client;
		inc_gsh_client_refcount(op_ctx->client);
	}

	if (isFullDebug(COMPONENT_STATE)) {
		display_nsm_client(&dspbuf, pclient);
		LogFullDebug(COMPONENT_STATE, "New {%s}", str);
	}

	buffkey.addr = pclient;
	buffkey.len = sizeof(*pclient);
	buffval.addr = pclient;
	buffval.len = sizeof(*pclient);

	rc = hashtable_setlatched(ht_nsm_client, &buffval, &buffval, &latch,
				  false, NULL, NULL);

	/* An error occurred, return NULL */
	if (rc != HASHTABLE_SUCCESS) {
		display_nsm_client(&dspbuf, pclient);

		LogCrit(COMPONENT_STATE, "Error %s, inserting {%s}",
			hash_table_err_to_str(rc), str);

		PTHREAD_MUTEX_destroy(&pclient->ssc_mutex);
		free_nsm_client(pclient);

		return NULL;
	}

	if (care != CARE_MONITOR || nsm_monitor(pclient))
		return pclient;

	/* Failed to monitor, release client reference
	 * and almost certainly remove it from the hash table.
	 */
	dec_nsm_client_ref(pclient);

	return NULL;
}
Beispiel #10
0
/**
 * @brief Get an NLM client
 *
 * @param[in] care        Care status
 * @param[in] xprt        RPC transport
 * @param[in] nsm_client  Related NSM client
 * @param[in] caller_name Caller name
 *
 * @return NLM client or NULL.
 */
state_nlm_client_t *get_nlm_client(care_t care, SVCXPRT *xprt,
				   state_nsm_client_t *nsm_client,
				   char *caller_name)
{
	state_nlm_client_t key;
	state_nlm_client_t *pclient;
	char str[LOG_BUFF_LEN];
	struct display_buffer dspbuf = {sizeof(str), str, str};
	struct hash_latch latch;
	hash_error_t rc;
	struct gsh_buffdesc buffkey;
	struct gsh_buffdesc buffval;
	struct sockaddr_storage local_addr;
	socklen_t addr_len;

	if (caller_name == NULL)
		return NULL;

	memset(&key, 0, sizeof(key));

	key.slc_nsm_client = nsm_client;
	key.slc_nlm_caller_name_len = strlen(caller_name);
	key.slc_client_type = svc_get_xprt_type(xprt);

	addr_len = sizeof(local_addr);
	if (getsockname(xprt->xp_fd, (struct sockaddr *)&local_addr, &addr_len)
	    == -1) {
		LogEvent(COMPONENT_CLIENTID, "Failed to get local addr.");
	} else {
		memcpy(&(key.slc_server_addr), &local_addr,
		       sizeof(struct sockaddr_storage));
	}

	if (key.slc_nlm_caller_name_len > LM_MAXSTRLEN)
		return NULL;

	key.slc_nlm_caller_name = caller_name;

	if (isFullDebug(COMPONENT_STATE)) {
		display_nlm_client(&dspbuf, &key);
		LogFullDebug(COMPONENT_STATE, "Find {%s}", str);
	}

	buffkey.addr = &key;
	buffkey.len = sizeof(key);

	rc = hashtable_getlatch(ht_nlm_client, &buffkey, &buffval, true,
				&latch);

	/* If we found it, return it */
	if (rc == HASHTABLE_SUCCESS) {
		pclient = buffval.addr;

		/* Return the found NLM Client */
		if (isFullDebug(COMPONENT_STATE)) {
			display_nlm_client(&dspbuf, pclient);
			LogFullDebug(COMPONENT_STATE, "Found {%s}", str);
		}

		/* Increment refcount under hash latch.
		 * This prevents dec ref from removing this entry from hash
		 * if a race occurs.
		 */
		inc_nlm_client_ref(pclient);

		hashtable_releaselatched(ht_nlm_client, &latch);

		if (care == CARE_MONITOR && !nsm_monitor(nsm_client)) {
			dec_nlm_client_ref(pclient);
			pclient = NULL;
		}

		return pclient;
	}

	/* An error occurred, return NULL */
	if (rc != HASHTABLE_ERROR_NO_SUCH_KEY) {
		display_nlm_client(&dspbuf, &key);

		LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}",
			hash_table_err_to_str(rc), str);

		return NULL;
	}

	/* Not found, but we don't care, return NULL */
	if (care == CARE_NOT) {
		/* Return the found NLM Client */
		if (isFullDebug(COMPONENT_STATE)) {
			display_nlm_client(&dspbuf, &key);
			LogFullDebug(COMPONENT_STATE, "Ignoring {%s}", str);
		}

		hashtable_releaselatched(ht_nlm_client, &latch);

		return NULL;
	}

	pclient = gsh_malloc(sizeof(*pclient));

	if (pclient == NULL) {
		display_nlm_client(&dspbuf, &key);
		LogCrit(COMPONENT_STATE, "No memory for {%s}", str);

		return NULL;
	}

	/* Copy everything over */
	memcpy(pclient, &key, sizeof(key));

	pclient->slc_nlm_caller_name = gsh_strdup(key.slc_nlm_caller_name);

	/* Take a reference to the NSM Client */
	inc_nsm_client_ref(nsm_client);

	if (pclient->slc_nlm_caller_name == NULL) {
		/* Discard the created client */
		free_nlm_client(pclient);
		return NULL;
	}

	pclient->slc_refcount = 1;

	if (isFullDebug(COMPONENT_STATE)) {
		display_nlm_client(&dspbuf, pclient);
		LogFullDebug(COMPONENT_STATE, "New {%s}", str);
	}

	buffkey.addr = pclient;
	buffkey.len = sizeof(*pclient);
	buffval.addr = pclient;
	buffval.len = sizeof(*pclient);

	rc = hashtable_setlatched(ht_nlm_client, &buffval, &buffval, &latch,
				  false, NULL, NULL);

	/* An error occurred, return NULL */
	if (rc != HASHTABLE_SUCCESS) {
		display_nlm_client(&dspbuf, pclient);

		LogCrit(COMPONENT_STATE, "Error %s, inserting {%s}",
			hash_table_err_to_str(rc), str);

		free_nlm_client(pclient);

		return NULL;
	}

	if (care != CARE_MONITOR || nsm_monitor(nsm_client))
		return pclient;

	/* Failed to monitor, release client reference
	 * and almost certainly remove it from the hash table.
	 */
	dec_nlm_client_ref(pclient);

	return NULL;
}