Exemple #1
0
/* rc=0 means ok
      1 means update
     <0 means error */
static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
{
        int rc;
        ENTRY;

        rc = mgs_check_index(obd, mti);
        if (rc == 0) {
                LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
                                   "this MGS does not know about it, preventing "
                                   "registration.\n", mti->mti_svname);
                rc = -ENOENT;
        } else if (rc == -1) {
                LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
                                   "disappeared! Regenerating all logs.\n",
                                   mti->mti_fsname);
                mti->mti_flags |= LDD_F_WRITECONF;
                rc = 1;
        } else {
                /* Index is correctly marked as used */

                /* If the logs don't contain the mti_nids then add
                   them as failover nids */
                rc = mgs_check_failnid(obd, mti);
        }

        RETURN(rc);
}
Exemple #2
0
void
lnet_connect_console_error (int rc, lnet_nid_t peer_nid,
                           __u32 peer_ip, int peer_port)
{
        switch (rc) {
        /* "normal" errors */
        case -ECONNREFUSED:
                CDEBUG(D_NETERROR, "Connection to %s at host %u.%u.%u.%u "
                       "on port %d was refused: "
                       "check that Lustre is running on that node.\n",
                       libcfs_nid2str(peer_nid),
                       HIPQUAD(peer_ip), peer_port);
                break;
        case -EHOSTUNREACH:
        case -ENETUNREACH:
                CDEBUG(D_NETERROR, "Connection to %s at host %u.%u.%u.%u "
                       "was unreachable: the network or that node may "
                       "be down, or Lustre may be misconfigured.\n",
                       libcfs_nid2str(peer_nid), HIPQUAD(peer_ip));
                break;
        case -ETIMEDOUT:
                CDEBUG(D_NETERROR, "Connection to %s at host %u.%u.%u.%u on "
                       "port %d took too long: that node may be hung "
                       "or experiencing high load.\n",
                       libcfs_nid2str(peer_nid),
                       HIPQUAD(peer_ip), peer_port);
                break;
        case -ECONNRESET:
                LCONSOLE_ERROR_MSG(0x11b, "Connection to %s at host %u.%u.%u.%u"
                                   " on port %d was reset: "
                                   "is it running a compatible version of "
                                   "Lustre and is %s one of its NIDs?\n",
                                   libcfs_nid2str(peer_nid),
                                   HIPQUAD(peer_ip), peer_port,
                                   libcfs_nid2str(peer_nid));
                break;
        case -EPROTO:
                LCONSOLE_ERROR_MSG(0x11c, "Protocol error connecting to %s at "
                                   "host %u.%u.%u.%u on port %d: is it running "
                                   "a compatible version of Lustre?\n",
                                   libcfs_nid2str(peer_nid),
                                   HIPQUAD(peer_ip), peer_port);
                break;
        case -EADDRINUSE:
                LCONSOLE_ERROR_MSG(0x11d, "No privileged ports available to "
                                   "connect to %s at host %u.%u.%u.%u on port "
                                   "%d\n", libcfs_nid2str(peer_nid),
                                   HIPQUAD(peer_ip), peer_port);
                break;
        default:
                LCONSOLE_ERROR_MSG(0x11e, "Unexpected error %d connecting to %s"
                                   " at host %u.%u.%u.%u on port %d\n", rc,
                                   libcfs_nid2str(peer_nid),
                                   HIPQUAD(peer_ip), peer_port);
                break;
        }
}
Exemple #3
0
/** Parse mount line options
 * e.g. mount -v -t lustre -o abort_recov uml1:uml2:/lustre-client /mnt/lustre
 * dev is passed as device=uml1:/lustre by mount.lustre
 */
static int lmd_parse(char *options, struct lustre_mount_data *lmd)
{
	char *s1, *s2, *devname = NULL;
	struct lustre_mount_data *raw = (struct lustre_mount_data *)options;
	int rc = 0;

	LASSERT(lmd);
	if (!options) {
		LCONSOLE_ERROR_MSG(0x162, "Missing mount data: check that "
				   "/sbin/mount.lustre is installed.\n");
		return -EINVAL;
	}

	/* Options should be a string - try to detect old lmd data */
	if ((raw->lmd_magic & 0xffffff00) == (LMD_MAGIC & 0xffffff00)) {
		LCONSOLE_ERROR_MSG(0x163, "You're using an old version of "
				   "/sbin/mount.lustre.  Please install "
				   "version %s\n", LUSTRE_VERSION_STRING);
		return -EINVAL;
	}
	lmd->lmd_magic = LMD_MAGIC;

	OBD_ALLOC(lmd->lmd_params, 4096);
	if (lmd->lmd_params == NULL)
		return -ENOMEM;
	lmd->lmd_params[0] = '\0';

	/* Set default flags here */

	s1 = options;
	while (*s1) {
		int clear = 0;
		int time_min = OBD_RECOVERY_TIME_MIN;

		/* Skip whitespace and extra commas */
		while (*s1 == ' ' || *s1 == ',')
			s1++;

		/* Client options are parsed in ll_options: eg. flock,
		   user_xattr, acl */

		/* Parse non-ldiskfs options here. Rather than modifying
		   ldiskfs, we just zero these out here */
		if (strncmp(s1, "abort_recov", 11) == 0) {
			lmd->lmd_flags |= LMD_FLG_ABORT_RECOV;
			clear++;
		} else if (strncmp(s1, "recovery_time_soft=", 19) == 0) {
			lmd->lmd_recovery_time_soft = max_t(int,
				simple_strtoul(s1 + 19, NULL, 10), time_min);
			clear++;
		} else if (strncmp(s1, "recovery_time_hard=", 19) == 0) {
Exemple #4
0
	/* Ghastly hack to allow LNET to inter-operate with portals.
	 * NET type 0 becomes an alias for whatever local network we have, and
	 * this assignment here means we can parse and print its NIDs */

	LASSERT (nf != NULL);
	LASSERT (nf0->nf_type < 0);

	nf0->nf_name = "zero";//nf->nf_name;
	nf0->nf_modname = nf->nf_modname;
	nf0->nf_addr2str = nf->nf_addr2str;
	nf0->nf_str2addr = nf->nf_str2addr;
	mb();
	nf0->nf_type = 0;
}

EXPORT_SYMBOL(libcfs_isknown_lnd);
EXPORT_SYMBOL(libcfs_lnd2modname);
EXPORT_SYMBOL(libcfs_lnd2str);
EXPORT_SYMBOL(libcfs_str2lnd);
EXPORT_SYMBOL(libcfs_net2str);
EXPORT_SYMBOL(libcfs_nid2str);
EXPORT_SYMBOL(libcfs_str2net);
EXPORT_SYMBOL(libcfs_str2nid);
EXPORT_SYMBOL(libcfs_id2str);
EXPORT_SYMBOL(libcfs_str2anynid);
EXPORT_SYMBOL(libcfs_setnet0alias);
#else  /* __KERNEL__ */
void
libcfs_setnet0alias(__unusedx int lnd)
{
	LCONSOLE_ERROR_MSG(0x125, "Liblustre cannot interoperate with old "
			   "Portals.\nportals_compatibility must be set to "
			   "'none'.\n");
}
Exemple #5
0
static void
lnet_syntax(char *name, char *str, int offset, int width)
{
    static char dots[LNET_SINGLE_TEXTBUF_NOB];
    static char dashes[LNET_SINGLE_TEXTBUF_NOB];

    memset(dots, '.', sizeof(dots));
    dots[sizeof(dots)-1] = 0;
    memset(dashes, '-', sizeof(dashes));
    dashes[sizeof(dashes)-1] = 0;

    LCONSOLE_ERROR_MSG(0x10f, "Error parsing '%s=\"%s\"'\n", name, str);
    LCONSOLE_ERROR_MSG(0x110, "here...........%.*s..%.*s|%.*s|\n",
                       (int)strlen(name), dots, offset, dots,
                       (width < 1) ? 0 : width - 1, dashes);
}
Exemple #6
0
/** Get a config log from the MGS and process it.
 * This func is called for both clients and servers.
 * Continue to process new statements appended to the logs
 * (whenever the config lock is revoked) until lustre_end_log
 * is called.
 * @param sb The superblock is used by the MGC to write to the local copy of
 *   the config log
 * @param logname The name of the llog to replicate from the MGS
 * @param cfg Since the same mgc may be used to follow multiple config logs
 *   (e.g. ost1, ost2, client), the config_llog_instance keeps the state for
 *   this log, and is added to the mgc's list of logs to follow.
 */
int lustre_process_log(struct super_block *sb, char *logname,
		     struct config_llog_instance *cfg)
{
	struct lustre_cfg *lcfg;
	struct lustre_cfg_bufs *bufs;
	struct lustre_sb_info *lsi = s2lsi(sb);
	struct obd_device *mgc = lsi->lsi_mgc;
	int rc;

	LASSERT(mgc);
	LASSERT(cfg);

	OBD_ALLOC_PTR(bufs);
	if (bufs == NULL)
		return -ENOMEM;

	/* mgc_process_config */
	lustre_cfg_bufs_reset(bufs, mgc->obd_name);
	lustre_cfg_bufs_set_string(bufs, 1, logname);
	lustre_cfg_bufs_set(bufs, 2, cfg, sizeof(*cfg));
	lustre_cfg_bufs_set(bufs, 3, &sb, sizeof(sb));
	lcfg = lustre_cfg_new(LCFG_LOG_START, bufs);
	rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
	lustre_cfg_free(lcfg);

	OBD_FREE_PTR(bufs);

	if (rc == -EINVAL)
		LCONSOLE_ERROR_MSG(0x15b, "%s: The configuration from log '%s'"
				   "failed from the MGS (%d).  Make sure this "
				   "client and the MGS are running compatible "
				   "versions of Lustre.\n",
				   mgc->obd_name, logname, rc);

	if (rc)
		LCONSOLE_ERROR_MSG(0x15c, "%s: The configuration from log '%s' "
				   "failed (%d). This may be the result of "
				   "communication errors between this node and "
				   "the MGS, a bad configuration, or other "
				   "errors. See the syslog for more "
				   "information.\n", mgc->obd_name, logname,
				   rc);

	/* class_obd_list(); */
	return rc;
}
Exemple #7
0
static inline int
accept2secure(const char *acc, long *sec)
{
	if (!strcmp(acc, "secure")) {
		*sec = 1;
		return 1;
	} else if (!strcmp(acc, "all")) {
		*sec = 0;
		return 1;
	} else if (!strcmp(acc, "none")) {
		return 0;
	} else {
		LCONSOLE_ERROR_MSG(0x124, "Can't parse 'accept=\"%s\"'\n",
				   acc);
		return -EINVAL;
	}
}
Exemple #8
0
/* Collect multiple values for mgsnid specifiers */
static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr)
{
	lnet_nid_t nid;
	char *tail = *ptr;
	char *mgsnid;
	int   length;
	int   oldlen = 0;

	/* Find end of nidlist */
	while (class_parse_nid_quiet(tail, &nid, &tail) == 0)
		;
	length = tail - *ptr;
	if (length == 0) {
		LCONSOLE_ERROR_MSG(0x159, "Can't parse NID '%s'\n", *ptr);
		return -EINVAL;
	}

	if (lmd->lmd_mgs != NULL)
		oldlen = strlen(lmd->lmd_mgs) + 1;

	mgsnid = kzalloc(oldlen + length + 1, GFP_NOFS);
	if (!mgsnid)
		return -ENOMEM;

	if (lmd->lmd_mgs != NULL) {
		/* Multiple mgsnid= are taken to mean failover locations */
		memcpy(mgsnid, lmd->lmd_mgs, oldlen);
		mgsnid[oldlen - 1] = ':';
		kfree(lmd->lmd_mgs);
	}
	memcpy(mgsnid + oldlen, *ptr, length);
	mgsnid[oldlen + length] = '\0';
	lmd->lmd_mgs = mgsnid;
	*ptr = tail;

	return 0;
}
Exemple #9
0
/**
 * Match client and OST server connection feature flags.
 *
 * Compute the compatibility flags for a connection request based on
 * features mutually supported by client and server.
 *
 * The obd_export::exp_connect_data.ocd_connect_flags field in \a exp
 * must not be updated here, otherwise a partially initialized value may
 * be exposed. After the connection request is successfully processed,
 * the top-level tgt_connect() request handler atomically updates the export
 * connect flags from the obd_connect_data::ocd_connect_flags field of the
 * reply. \see tgt_connect().
 *
 * \param[in] env		execution environment
 * \param[in] exp		the obd_export associated with this
 *				client/target pair
 * \param[in] data		stores data for this connect request
 * \param[in] new_connection	is this connection new or not
 *
 * \retval		0 if success
 * \retval		-EPROTO client and server feature requirements are
 *			incompatible
 * \retval		-EBADF  OST index in connect request doesn't match
 *			real OST index
 */
static int ofd_parse_connect_data(const struct lu_env *env,
				  struct obd_export *exp,
				  struct obd_connect_data *data,
				  bool new_connection)
{
	struct ofd_device		 *ofd = ofd_exp(exp);
	struct filter_export_data	 *fed = &exp->exp_filter_data;

	if (!data)
		RETURN(0);

	CDEBUG(D_RPCTRACE, "%s: cli %s/%p ocd_connect_flags: "LPX64
	       " ocd_version: %x ocd_grant: %d ocd_index: %u"
	       " ocd_group %u\n",
	       exp->exp_obd->obd_name, exp->exp_client_uuid.uuid, exp,
	       data->ocd_connect_flags, data->ocd_version,
	       data->ocd_grant, data->ocd_index, data->ocd_group);

	if (fed->fed_group != 0 && fed->fed_group != data->ocd_group) {
		CWARN("!!! This export (nid %s) used object group %d "
		      "earlier; now it's trying to use group %d!  This could "
		      "be a bug in the MDS. Please report to "
		      "https://jira.hpdd.intel.com/\n",
		      obd_export_nid2str(exp), fed->fed_group,
		      data->ocd_group);
		RETURN(-EPROTO);
	}
	fed->fed_group = data->ocd_group;

	data->ocd_connect_flags &= OST_CONNECT_SUPPORTED;
	data->ocd_version = LUSTRE_VERSION_CODE;

	/* Kindly make sure the SKIP_ORPHAN flag is from MDS. */
	if (data->ocd_connect_flags & OBD_CONNECT_MDS)
		CDEBUG(D_HA, "%s: Received MDS connection for group %u\n",
		       exp->exp_obd->obd_name, data->ocd_group);
	else if (data->ocd_connect_flags & OBD_CONNECT_SKIP_ORPHAN)
		RETURN(-EPROTO);

	if (ofd_grant_param_supp(exp)) {
		exp->exp_filter_data.fed_pagesize = data->ocd_blocksize;
		/* ocd_{blocksize,inodespace} are log2 values */
		data->ocd_blocksize  = ofd->ofd_blockbits;
		data->ocd_inodespace = ofd->ofd_dt_conf.ddp_inodespace;
		/* ocd_grant_extent is in 1K blocks */
		data->ocd_grant_extent = ofd->ofd_dt_conf.ddp_grant_frag >> 10;
	}

	if (data->ocd_connect_flags & OBD_CONNECT_GRANT)
		data->ocd_grant = ofd_grant_connect(env, exp, data->ocd_grant,
						    new_connection);

	if (data->ocd_connect_flags & OBD_CONNECT_INDEX) {
		struct lr_server_data *lsd = &ofd->ofd_lut.lut_lsd;
		int		       index = lsd->lsd_osd_index;

		if (index != data->ocd_index) {
			LCONSOLE_ERROR_MSG(0x136, "Connection from %s to index"
					   " %u doesn't match actual OST index"
					   " %u in last_rcvd file, bad "
					   "configuration?\n",
					   obd_export_nid2str(exp), index,
					   data->ocd_index);
			RETURN(-EBADF);
		}
		if (!(lsd->lsd_feature_compat & OBD_COMPAT_OST)) {
			/* this will only happen on the first connect */
			lsd->lsd_feature_compat |= OBD_COMPAT_OST;
			/* sync is not needed here as lut_client_add will
			 * set exp_need_sync flag */
			tgt_server_data_update(env, &ofd->ofd_lut, 0);
		}
	}
	if (OBD_FAIL_CHECK(OBD_FAIL_OST_BRW_SIZE)) {
		data->ocd_brw_size = 65536;
	} else if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) {
		data->ocd_brw_size = min(data->ocd_brw_size,
					 (__u32)DT_MAX_BRW_SIZE);
		if (data->ocd_brw_size == 0) {
			CERROR("%s: cli %s/%p ocd_connect_flags: "LPX64
			       " ocd_version: %x ocd_grant: %d ocd_index: %u "
			       "ocd_brw_size is unexpectedly zero, "
			       "network data corruption?"
			       "Refusing connection of this client\n",
			       exp->exp_obd->obd_name,
			       exp->exp_client_uuid.uuid,
			       exp, data->ocd_connect_flags, data->ocd_version,
			       data->ocd_grant, data->ocd_index);
			RETURN(-EPROTO);
		}
	}

	if (data->ocd_connect_flags & OBD_CONNECT_CKSUM) {
		__u32 cksum_types = data->ocd_cksum_types;

		/* The client set in ocd_cksum_types the checksum types it
		 * supports. We have to mask off the algorithms that we don't
		 * support */
		data->ocd_cksum_types &= cksum_types_supported_server();

		if (unlikely(data->ocd_cksum_types == 0)) {
			CERROR("%s: Connect with checksum support but no "
			       "ocd_cksum_types is set\n",
			       exp->exp_obd->obd_name);
			RETURN(-EPROTO);
		}

		CDEBUG(D_RPCTRACE, "%s: cli %s supports cksum type %x, return "
		       "%x\n", exp->exp_obd->obd_name, obd_export_nid2str(exp),
		       cksum_types, data->ocd_cksum_types);
	} else {
		/* This client does not support OBD_CONNECT_CKSUM
		 * fall back to CRC32 */
		CDEBUG(D_RPCTRACE, "%s: cli %s does not support "
		       "OBD_CONNECT_CKSUM, CRC32 will be used\n",
		       exp->exp_obd->obd_name, obd_export_nid2str(exp));
	}

	if (data->ocd_connect_flags & OBD_CONNECT_MAXBYTES)
		data->ocd_maxbytes = ofd->ofd_dt_conf.ddp_maxbytes;

	if (OCD_HAS_FLAG(data, PINGLESS)) {
		if (ptlrpc_pinger_suppress_pings()) {
			spin_lock(&exp->exp_obd->obd_dev_lock);
			list_del_init(&exp->exp_obd_chain_timed);
			spin_unlock(&exp->exp_obd->obd_dev_lock);
		} else {
			data->ocd_connect_flags &= ~OBD_CONNECT_PINGLESS;
		}
	}

	RETURN(0);
}
Exemple #10
0
int
lnet_acceptor(void *arg)
{
	socket_t  *newsock;
	int	    rc;
	__u32	  magic;
	__u32	  peer_ip;
	int	    peer_port;
	int	    secure = (int)((long_ptr_t)arg);

	LASSERT(lnet_acceptor_state.pta_sock == NULL);

	cfs_block_allsigs();

	rc = libcfs_sock_listen(&lnet_acceptor_state.pta_sock,
				0, accept_port, accept_backlog);
	if (rc != 0) {
		if (rc == -EADDRINUSE)
			LCONSOLE_ERROR_MSG(0x122, "Can't start acceptor on port %d: port already in use\n",
					   accept_port);
		else
			LCONSOLE_ERROR_MSG(0x123, "Can't start acceptor on port %d: unexpected error %d\n",
					   accept_port, rc);

		lnet_acceptor_state.pta_sock = NULL;
	} else {
		LCONSOLE(0, "Accept %s, port %d\n", accept_type, accept_port);
	}

	/* set init status and unblock parent */
	lnet_acceptor_state.pta_shutdown = rc;
	complete(&lnet_acceptor_state.pta_signal);

	if (rc != 0)
		return rc;

	while (!lnet_acceptor_state.pta_shutdown) {

		rc = libcfs_sock_accept(&newsock, lnet_acceptor_state.pta_sock);
		if (rc != 0) {
			if (rc != -EAGAIN) {
				CWARN("Accept error %d: pausing...\n", rc);
				cfs_pause(cfs_time_seconds(1));
			}
			continue;
		}

		/* maybe we're waken up with libcfs_sock_abort_accept() */
		if (lnet_acceptor_state.pta_shutdown) {
			libcfs_sock_release(newsock);
			break;
		}

		rc = libcfs_sock_getaddr(newsock, 1, &peer_ip, &peer_port);
		if (rc != 0) {
			CERROR("Can't determine new connection's address\n");
			goto failed;
		}

		if (secure && peer_port > LNET_ACCEPTOR_MAX_RESERVED_PORT) {
			CERROR("Refusing connection from %pI4h: insecure port %d\n",
			       &peer_ip, peer_port);
			goto failed;
		}

		rc = libcfs_sock_read(newsock, &magic, sizeof(magic),
				      accept_timeout);
		if (rc != 0) {
			CERROR("Error %d reading connection request from %pI4h\n",
				rc, &peer_ip);
			goto failed;
		}

		rc = lnet_accept(newsock, magic);
		if (rc != 0)
			goto failed;

		continue;

failed:
		libcfs_sock_release(newsock);
	}

	libcfs_sock_release(lnet_acceptor_state.pta_sock);
	lnet_acceptor_state.pta_sock = NULL;

	CDEBUG(D_NET, "Acceptor stopping\n");

	/* unblock lnet_acceptor_stop() */
	complete(&lnet_acceptor_state.pta_signal);
	return 0;
}
Exemple #11
0
int
lnet_accept(socket_t *sock, __u32 magic)
{
	lnet_acceptor_connreq_t cr;
	__u32		   peer_ip;
	int		     peer_port;
	int		     rc;
	int		     flip;
	lnet_ni_t	      *ni;
	char		   *str;

	LASSERT(sizeof(cr) <= 16);	     /* not too big for the stack */

	rc = libcfs_sock_getaddr(sock, 1, &peer_ip, &peer_port);
	LASSERT(rc == 0);		      /* we succeeded before */

	if (!lnet_accept_magic(magic, LNET_PROTO_ACCEPTOR_MAGIC)) {

		if (lnet_accept_magic(magic, LNET_PROTO_MAGIC)) {
			/* future version compatibility!
			 * When LNET unifies protocols over all LNDs, the first
			 * thing sent will be a version query.  I send back
			 * LNET_PROTO_ACCEPTOR_MAGIC to tell her I'm "old" */

			memset(&cr, 0, sizeof(cr));
			cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC;
			cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION;
			rc = libcfs_sock_write(sock, &cr, sizeof(cr),
					       accept_timeout);

			if (rc != 0)
				CERROR("Error sending magic+version in response to LNET magic from %pI4h: %d\n",
				       &peer_ip, rc);
			return -EPROTO;
		}

		if (magic == le32_to_cpu(LNET_PROTO_TCP_MAGIC))
			str = "'old' socknal/tcpnal";
		else if (lnet_accept_magic(magic, LNET_PROTO_RA_MAGIC))
			str = "'old' ranal";
		else
			str = "unrecognised";

		LCONSOLE_ERROR_MSG(0x11f, "Refusing connection from %pI4h magic %08x: %s acceptor protocol\n",
				   &peer_ip, magic, str);
		return -EPROTO;
	}

	flip = (magic != LNET_PROTO_ACCEPTOR_MAGIC);

	rc = libcfs_sock_read(sock, &cr.acr_version,
			      sizeof(cr.acr_version),
			      accept_timeout);
	if (rc != 0) {
		CERROR("Error %d reading connection request version from %pI4h\n",
			rc, &peer_ip);
		return -EIO;
	}

	if (flip)
		__swab32s(&cr.acr_version);

	if (cr.acr_version != LNET_PROTO_ACCEPTOR_VERSION) {
		/* future version compatibility!
		 * An acceptor-specific protocol rev will first send a version
		 * query.  I send back my current version to tell her I'm
		 * "old". */
		int peer_version = cr.acr_version;

		memset(&cr, 0, sizeof(cr));
		cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC;
		cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION;

		rc = libcfs_sock_write(sock, &cr, sizeof(cr),
				       accept_timeout);

		if (rc != 0)
			CERROR("Error sending magic+version in response to version %d from %pI4h: %d\n",
			       peer_version, &peer_ip, rc);
		return -EPROTO;
	}

	rc = libcfs_sock_read(sock, &cr.acr_nid,
			      sizeof(cr) -
			      offsetof(lnet_acceptor_connreq_t, acr_nid),
			      accept_timeout);
	if (rc != 0) {
		CERROR("Error %d reading connection request from %pI4h\n",
			rc, &peer_ip);
		return -EIO;
	}

	if (flip)
		__swab64s(&cr.acr_nid);

	ni = lnet_net2ni(LNET_NIDNET(cr.acr_nid));
	if (ni == NULL ||	       /* no matching net */
	    ni->ni_nid != cr.acr_nid) { /* right NET, wrong NID! */
		if (ni != NULL)
			lnet_ni_decref(ni);
		LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %pI4h for %s: No matching NI\n",
				   &peer_ip, libcfs_nid2str(cr.acr_nid));
		return -EPERM;
	}

	if (ni->ni_lnd->lnd_accept == NULL) {
		/* This catches a request for the loopback LND */
		lnet_ni_decref(ni);
		LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %pI4h for %s: NI doesn not accept IP connections\n",
				  &peer_ip, libcfs_nid2str(cr.acr_nid));
		return -EPERM;
	}

	CDEBUG(D_NET, "Accept %s from %pI4h\n",
	       libcfs_nid2str(cr.acr_nid), &peer_ip);

	rc = ni->ni_lnd->lnd_accept(ni, sock);

	lnet_ni_decref(ni);
	return rc;
}