Example #1
0
/**
 * fc_lport_flogi_fill() - Fill in FLOGI command for request
 * @lport: The local port the FLOGI is for
 * @flogi: The FLOGI command
 * @op:	   The opcode
 */
static void fc_lport_flogi_fill(struct fc_lport *lport,
				struct fc_els_flogi *flogi,
				unsigned int op)
{
	struct fc_els_csp *sp;
	struct fc_els_cssp *cp;

	memset(flogi, 0, sizeof(*flogi));
	flogi->fl_cmd = (u8) op;
	put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
	put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
	sp = &flogi->fl_csp;
	sp->sp_hi_ver = 0x20;
	sp->sp_lo_ver = 0x20;
	sp->sp_bb_cred = htons(10);	/* this gets set by gateway */
	sp->sp_bb_data = htons((u16) lport->mfs);
	cp = &flogi->fl_cssp[3 - 1];	/* class 3 parameters */
	cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
	if (op != ELS_FLOGI) {
		sp->sp_features = htons(FC_SP_FT_CIRO);
		sp->sp_tot_seq = htons(255);	/* seq. we accept */
		sp->sp_rel_off = htons(0x1f);
		sp->sp_e_d_tov = htonl(lport->e_d_tov);

		cp->cp_rdfs = htons((u16) lport->mfs);
		cp->cp_con_seq = htons(255);
		cp->cp_open_seq = 1;
	}
}
Example #2
0
static unsigned char *do_40bit(unsigned char *dst, uint64_t d1)
{
	uint64_t d2;

	d2   = d1;                    /* copy */
	d2 >>= 12;                    /* shift copy */
	d1  &= 0xFFFFFFFF00000000ULL; /* eliminate */
	d2  &= 0x00000000FFFFFFFFULL;
	d1  |= d2;                    /* join */
	d2   = d1;                    /* copy */
	d2 >>= 6;                     /* shift copy */
	d1  &= 0xFFFF0000FFFF0000ULL; /* eliminate */
 	d2  &= 0x0000FFFF0000FFFFULL;
	d1  |= d2;                    /* join */
	d2   = d1;                    /* copy */
	d2 >>= 3;                     /* shift copy */
	d1  &= 0xFF00FF00FF00FF00ULL; /* eliminate */
	d2  &= 0x00FF00FF00FF00FFULL;
	d1  |= d2;                    /* join */
	d1 >>= 3;                     /* bring it down */
	d1  &= 0x1F1F1F1F1F1F1F1FULL; /* eliminate */

	/* convert */
	d1  += 0x6161616161616161ULL;
	d1  -= zapnot(0x4949494949494949ULL, cmpbge(d1, 0x7B7B7B7B7B7B7B7BULL));
	/* write out */
	put_unaligned_be64(d1, dst);
	return dst + 8;
}
Example #3
0
static void nft_byteorder_eval(const struct nft_expr *expr,
			       struct nft_regs *regs,
			       const struct nft_pktinfo *pkt)
{
	const struct nft_byteorder *priv = nft_expr_priv(expr);
	u32 *src = &regs->data[priv->sreg];
	u32 *dst = &regs->data[priv->dreg];
	union { u32 u32; u16 u16; } *s, *d;
	unsigned int i;

	s = (void *)src;
	d = (void *)dst;

	switch (priv->size) {
	case 8: {
		u64 src64;

		switch (priv->op) {
		case NFT_BYTEORDER_NTOH:
			for (i = 0; i < priv->len / 8; i++) {
				src64 = get_unaligned((u64 *)&src[i]);
				put_unaligned_be64(src64, &dst[i]);
			}
			break;
		case NFT_BYTEORDER_HTON:
			for (i = 0; i < priv->len / 8; i++) {
				src64 = get_unaligned_be64(&src[i]);
				put_unaligned(src64, (u64 *)&dst[i]);
			}
			break;
		}
		break;
	}
	case 4:
		switch (priv->op) {
		case NFT_BYTEORDER_NTOH:
			for (i = 0; i < priv->len / 4; i++)
				d[i].u32 = ntohl((__force __be32)s[i].u32);
			break;
		case NFT_BYTEORDER_HTON:
			for (i = 0; i < priv->len / 4; i++)
				d[i].u32 = (__force __u32)htonl(s[i].u32);
			break;
		}
		break;
	case 2:
		switch (priv->op) {
		case NFT_BYTEORDER_NTOH:
			for (i = 0; i < priv->len / 2; i++)
				d[i].u16 = ntohs((__force __be16)s[i].u16);
			break;
		case NFT_BYTEORDER_HTON:
			for (i = 0; i < priv->len / 2; i++)
				d[i].u16 = (__force __u16)htons(s[i].u16);
			break;
		}
		break;
	}
}
Example #4
0
void qedf_fcoe_send_vlan_req(struct qedf_ctx *qedf)
{
	struct sk_buff *skb;
	char *eth_fr;
	int fr_len;
	struct fip_vlan *vlan;
#define MY_FIP_ALL_FCF_MACS        ((__u8[6]) { 1, 0x10, 0x18, 1, 0, 2 })
	static u8 my_fcoe_all_fcfs[ETH_ALEN] = MY_FIP_ALL_FCF_MACS;

	skb = dev_alloc_skb(sizeof(struct fip_vlan));
	if (!skb)
		return;

	fr_len = sizeof(*vlan);
	eth_fr = (char *)skb->data;
	vlan = (struct fip_vlan *)eth_fr;

	memset(vlan, 0, sizeof(*vlan));
	ether_addr_copy(vlan->eth.h_source, qedf->mac);
	ether_addr_copy(vlan->eth.h_dest, my_fcoe_all_fcfs);
	vlan->eth.h_proto = htons(ETH_P_FIP);

	vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
	vlan->fip.fip_op = htons(FIP_OP_VLAN);
	vlan->fip.fip_subcode = FIP_SC_VL_REQ;
	vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);

	vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
	vlan->desc.mac.fd_desc.fip_dlen = sizeof(vlan->desc.mac) / FIP_BPW;
	ether_addr_copy(vlan->desc.mac.fd_mac, qedf->mac);

	vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
	vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW;
	put_unaligned_be64(qedf->lport->wwnn, &vlan->desc.wwnn.fd_wwn);

	skb_put(skb, sizeof(*vlan));
	skb->protocol = htons(ETH_P_FIP);
	skb_reset_mac_header(skb);
	skb_reset_network_header(skb);

	QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Sending FIP VLAN "
		   "request.");

	if (atomic_read(&qedf->link_state) != QEDF_LINK_UP) {
		QEDF_WARN(&(qedf->dbg_ctx), "Cannot send vlan request "
		    "because link is not up.\n");

		kfree_skb(skb);
		return;
	}
	qed_ops->ll2->start_xmit(qedf->cdev, skb);
}
Example #5
0
static void
xfs_dir2_sf_put_ino(
	struct xfs_dir2_sf_hdr	*hdr,
	xfs_dir2_inou_t		*to,
	xfs_ino_t		ino)
{
	ASSERT((ino & 0xff00000000000000ULL) == 0);

	if (hdr->i8count)
		put_unaligned_be64(ino, &to->i8.i);
	else
		put_unaligned_be32(ino, &to->i4.i);
}
Example #6
0
static void update_seq_access_counters(struct seqAccessDevice *sa,
				struct priv_lu_ssc *lu_ssc)
{
	put_unaligned_be64(lu_ssc->bytesWritten_I,
				&sa->writeDataB4Compression);
	put_unaligned_be64(lu_ssc->bytesWritten_M,
				&sa->writeDataAfCompression);
	put_unaligned_be64(lu_ssc->bytesRead_M,
				&sa->readDataB4Compression);
	put_unaligned_be64(lu_ssc->bytesRead_I,
				&sa->readDataAfCompression);

	/* Values in MBytes */
	if (lu_ssc->tapeLoaded == TAPE_LOADED) {
		put_unaligned_be32(lu_ssc->max_capacity >> 20,
					&sa->capacity_bop_eod);
		put_unaligned_be32(lu_ssc->early_warning_position >> 20,
					&sa->capacity_bop_ew);
		put_unaligned_be32(lu_ssc->early_warning_sz >> 20,
					&sa->capacity_ew_leop);
		put_unaligned_be32(current_tape_offset() >> 20,
					&sa->capacity_bop_curr);
	} else {
Example #7
0
/**
 * ecryptfs_write_inode_size_to_header
 *
 * Writes the lower file size to the first 8 bytes of the header.
 *
 * Returns zero on success; non-zero on error.
 */
static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
{
	char *file_size_virt;
	int rc;

	file_size_virt = kmalloc(sizeof(u64), GFP_KERNEL);
	if (!file_size_virt) {
		rc = -ENOMEM;
		goto out;
	}
	put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt);
	rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
				  sizeof(u64));
	kfree(file_size_virt);
	if (rc)
		printk(KERN_ERR "%s: Error writing file size to header; "
		       "rc = [%d]\n", __func__, rc);
out:
	return rc;
}
Example #8
0
int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd)
{
	struct request *rq = cmd->request;
	struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
	sector_t lba, sector = blk_rq_pos(rq);
	unsigned int nr_bytes = blk_rq_bytes(rq);
	int ret;

	WARN_ON(nr_bytes == 0);

	if (!sd_is_zoned(sdkp))
		/* Not a zoned device */
		return BLKPREP_KILL;

	ret = scsi_init_io(cmd);
	if (ret != BLKPREP_OK)
		return ret;

	cmd->cmd_len = 16;
	memset(cmd->cmnd, 0, cmd->cmd_len);
	cmd->cmnd[0] = ZBC_IN;
	cmd->cmnd[1] = ZI_REPORT_ZONES;
	lba = sectors_to_logical(sdkp->device, sector);
	put_unaligned_be64(lba, &cmd->cmnd[2]);
	put_unaligned_be32(nr_bytes, &cmd->cmnd[10]);
	/* Do partial report for speeding things up */
	cmd->cmnd[14] = ZBC_REPORT_ZONE_PARTIAL;

	cmd->sc_data_direction = DMA_FROM_DEVICE;
	cmd->sdb.length = nr_bytes;
	cmd->transfersize = sdkp->device->sector_size;
	cmd->allowed = 0;

	/*
	 * Report may return less bytes than requested. Make sure
	 * to report completion on the entire initial request.
	 */
	rq->__data_len = nr_bytes;

	return BLKPREP_OK;
}
Example #9
0
static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
{
	ssize_t size;
	void *xattr_virt;
	struct dentry *lower_dentry =
		ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry;
	struct inode *lower_inode = lower_dentry->d_inode;
	int rc;

	if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
		printk(KERN_WARNING
		       "No support for setting xattr in lower filesystem\n");
		rc = -ENOSYS;
		goto out;
	}
	xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
	if (!xattr_virt) {
		printk(KERN_ERR "Out of memory whilst attempting to write "
		       "inode size to xattr\n");
		rc = -ENOMEM;
		goto out;
	}
	mutex_lock(&lower_inode->i_mutex);
	size = lower_inode->i_op->getxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
					   xattr_virt, PAGE_CACHE_SIZE);
	if (size < 0)
		size = 8;
	put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
	rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
					 xattr_virt, size, 0);
	mutex_unlock(&lower_inode->i_mutex);
	if (rc)
		printk(KERN_ERR "Error whilst attempting to write inode size "
		       "to lower file xattr; rc = [%d]\n", rc);
	kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
out:
	return rc;
}
Example #10
0
/**
 * Issue a REPORT ZONES scsi command.
 */
static int sd_zbc_report_zones(struct scsi_disk *sdkp, unsigned char *buf,
			       unsigned int buflen, sector_t lba)
{
	struct scsi_device *sdp = sdkp->device;
	const int timeout = sdp->request_queue->rq_timeout;
	struct scsi_sense_hdr sshdr;
	unsigned char cmd[16];
	unsigned int rep_len;
	int result;

	memset(cmd, 0, 16);
	cmd[0] = ZBC_IN;
	cmd[1] = ZI_REPORT_ZONES;
	put_unaligned_be64(lba, &cmd[2]);
	put_unaligned_be32(buflen, &cmd[10]);
	memset(buf, 0, buflen);

	result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
				  buf, buflen, &sshdr,
				  timeout, SD_MAX_RETRIES, NULL);
	if (result) {
		sd_printk(KERN_ERR, sdkp,
			  "REPORT ZONES lba %llu failed with %d/%d\n",
			  (unsigned long long)lba,
			  host_byte(result), driver_byte(result));
		return -EIO;
	}

	rep_len = get_unaligned_be32(&buf[0]);
	if (rep_len < 64) {
		sd_printk(KERN_ERR, sdkp,
			  "REPORT ZONES report invalid length %u\n",
			  rep_len);
		return -EIO;
	}

	return 0;
}
Example #11
0
/**
 * scsi_set_sense_information - set the information field in a
 *		formatted sense data buffer
 * @buf:	Where to build sense data
 * @buf_len:    buffer length
 * @info:	64-bit information value to be set
 *
 * Return value:
 *	0 on success or EINVAL for invalid sense buffer length
 **/
int scsi_set_sense_information(u8 *buf, int buf_len, u64 info)
{
	if ((buf[0] & 0x7f) == 0x72) {
		u8 *ucp, len;

		len = buf[7];
		ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0);
		if (!ucp) {
			buf[7] = len + 0xc;
			ucp = buf + 8 + len;
		}

		if (buf_len < len + 0xc)
			/* Not enough room for info */
			return -EINVAL;

		ucp[0] = 0;
		ucp[1] = 0xa;
		ucp[2] = 0x80; /* Valid bit */
		ucp[3] = 0;
		put_unaligned_be64(info, &ucp[4]);
	} else if ((buf[0] & 0x7f) == 0x70) {
		/*
		 * Only set the 'VALID' bit if we can represent the value
		 * correctly; otherwise just fill out the lower bytes and
		 * clear the 'VALID' flag.
		 */
		if (info <= 0xffffffffUL)
			buf[0] |= 0x80;
		else
			buf[0] &= 0x7f;
		put_unaligned_be32((u32)info, &buf[3]);
	}

	return 0;
}
Example #12
0
static void
skd_prep_discard_cdb(struct skd_scsi_request *scsi_req,
		     struct skd_request_context *skreq,
		     struct page *page,
		     u32 lba, u32 count)
{
	char *buf;
	unsigned long len;
	struct request *req;

	buf = page_address(page);
	len = SKD_DISCARD_CDB_LENGTH;

	scsi_req->cdb[0] = UNMAP;
	scsi_req->cdb[8] = len;

	put_unaligned_be16(6 + 16, &buf[0]);
	put_unaligned_be16(16, &buf[2]);
	put_unaligned_be64(lba, &buf[8]);
	put_unaligned_be32(count, &buf[16]);

	req = skreq->req;
	blk_add_request_payload(req, page, len);
}
Example #13
0
File: bs_rbd.c Project: chitr/tgt
static void bs_rbd_request(struct scsi_cmd *cmd)
{
	int ret;
	uint32_t length;
	int result = SAM_STAT_GOOD;
	uint8_t key;
	uint16_t asc;
#if 0
	/*
	 * This should go in the sense data on error for COMPARE_AND_WRITE, but
	 * there doesn't seem to be any attempt to do so...
	 */

	uint32_t info = 0;
#endif
	char *tmpbuf;
	size_t blocksize;
	uint64_t offset = cmd->offset;
	uint32_t tl     = cmd->tl;
	int do_verify = 0;
	int i;
	char *ptr;
	const char *write_buf = NULL;
	ret = length = 0;
	key = asc = 0;
	struct active_rbd *rbd = RBDP(cmd->dev->fd);

	switch (cmd->scb[0]) {
	case ORWRITE_16:
		length = scsi_get_out_length(cmd);

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = SAM_STAT_CHECK_CONDITION;
			key = HARDWARE_ERROR;
			asc = ASC_INTERNAL_TGT_FAILURE;
			break;
		}

		ret = rbd_read(rbd->rbd_image, offset, length, tmpbuf);

		if (ret != length) {
			set_medium_error(&result, &key, &asc);
			free(tmpbuf);
			break;
		}

		ptr = scsi_get_out_buffer(cmd);
		for (i = 0; i < length; i++)
			ptr[i] |= tmpbuf[i];

		free(tmpbuf);

		write_buf = scsi_get_out_buffer(cmd);
		goto write;
	case COMPARE_AND_WRITE:
		/* Blocks are transferred twice, first the set that
		 * we compare to the existing data, and second the set
		 * to write if the compare was successful.
		 */
		length = scsi_get_out_length(cmd) / 2;
		if (length != cmd->tl) {
			result = SAM_STAT_CHECK_CONDITION;
			key = ILLEGAL_REQUEST;
			asc = ASC_INVALID_FIELD_IN_CDB;
			break;
		}

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = SAM_STAT_CHECK_CONDITION;
			key = HARDWARE_ERROR;
			asc = ASC_INTERNAL_TGT_FAILURE;
			break;
		}

		ret = rbd_read(rbd->rbd_image, offset, length, tmpbuf);

		if (ret != length) {
			set_medium_error(&result, &key, &asc);
			free(tmpbuf);
			break;
		}

		if (memcmp(scsi_get_out_buffer(cmd), tmpbuf, length)) {
			uint32_t pos = 0;
			char *spos = scsi_get_out_buffer(cmd);
			char *dpos = tmpbuf;

			/*
			 * Data differed, this is assumed to be 'rare'
			 * so use a much more expensive byte-by-byte
			 * comparasion to find out at which offset the
			 * data differs.
			 */
			for (pos = 0; pos < length && *spos++ == *dpos++;
			     pos++)
				;
#if 0
			/* See comment above at declaration */
			info = pos;
#endif
			result = SAM_STAT_CHECK_CONDITION;
			key = MISCOMPARE;
			asc = ASC_MISCOMPARE_DURING_VERIFY_OPERATION;
			free(tmpbuf);
			break;
		}

		/* no DPO bit (cache retention advice) support */
		free(tmpbuf);

		write_buf = scsi_get_out_buffer(cmd) + length;
		goto write;
	case SYNCHRONIZE_CACHE:
	case SYNCHRONIZE_CACHE_16:
		/* TODO */
		length = (cmd->scb[0] == SYNCHRONIZE_CACHE) ? 0 : 0;

		if (cmd->scb[1] & 0x2) {
			result = SAM_STAT_CHECK_CONDITION;
			key = ILLEGAL_REQUEST;
			asc = ASC_INVALID_FIELD_IN_CDB;
		} else
			bs_sync_sync_range(cmd, length, &result, &key, &asc);
		break;
	case WRITE_VERIFY:
	case WRITE_VERIFY_12:
	case WRITE_VERIFY_16:
		do_verify = 1;
	case WRITE_6:
	case WRITE_10:
	case WRITE_12:
	case WRITE_16:
		length = scsi_get_out_length(cmd);
		write_buf = scsi_get_out_buffer(cmd);
write:
		ret = rbd_write(rbd->rbd_image, offset, length, write_buf);
		if (ret == length) {
			struct mode_pg *pg;

			/*
			 * it would be better not to access to pg
			 * directy.
			 */
			pg = find_mode_page(cmd->dev, 0x08, 0);
			if (pg == NULL) {
				result = SAM_STAT_CHECK_CONDITION;
				key = ILLEGAL_REQUEST;
				asc = ASC_INVALID_FIELD_IN_CDB;
				break;
			}
			if (((cmd->scb[0] != WRITE_6) && (cmd->scb[1] & 0x8)) ||
			    !(pg->mode_data[0] & 0x04))
				bs_sync_sync_range(cmd, length, &result, &key,
						   &asc);
		} else
			set_medium_error(&result, &key, &asc);

		if (do_verify)
			goto verify;
		break;
	case WRITE_SAME:
	case WRITE_SAME_16:
		/* WRITE_SAME used to punch hole in file */
		if (cmd->scb[1] & 0x08) {
			ret = rbd_discard(rbd->rbd_image, offset, tl);
			if (ret != 0) {
				eprintf("Failed to punch hole for WRITE_SAME"
					" command\n");
				result = SAM_STAT_CHECK_CONDITION;
				key = HARDWARE_ERROR;
				asc = ASC_INTERNAL_TGT_FAILURE;
				break;
			}
			break;
		}
		while (tl > 0) {
			blocksize = 1 << cmd->dev->blk_shift;
			tmpbuf = scsi_get_out_buffer(cmd);

			switch (cmd->scb[1] & 0x06) {
			case 0x02: /* PBDATA==0 LBDATA==1 */
				put_unaligned_be32(offset, tmpbuf);
				break;
			case 0x04: /* PBDATA==1 LBDATA==0 */
				/* physical sector format */
				put_unaligned_be64(offset, tmpbuf);
				break;
			}

			ret = rbd_write(rbd->rbd_image, offset, blocksize,
					tmpbuf);
			if (ret != blocksize)
				set_medium_error(&result, &key, &asc);

			offset += blocksize;
			tl     -= blocksize;
		}
		break;
	case READ_6:
	case READ_10:
	case READ_12:
	case READ_16:
		length = scsi_get_in_length(cmd);
		ret = rbd_read(rbd->rbd_image, offset, length,
			       scsi_get_in_buffer(cmd));

		if (ret != length)
			set_medium_error(&result, &key, &asc);

		break;
	case PRE_FETCH_10:
	case PRE_FETCH_16:
		break;
	case VERIFY_10:
	case VERIFY_12:
	case VERIFY_16:
verify:
		length = scsi_get_out_length(cmd);

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = SAM_STAT_CHECK_CONDITION;
			key = HARDWARE_ERROR;
			asc = ASC_INTERNAL_TGT_FAILURE;
			break;
		}

		ret = rbd_read(rbd->rbd_image, offset, length, tmpbuf);

		if (ret != length)
			set_medium_error(&result, &key, &asc);
		else if (memcmp(scsi_get_out_buffer(cmd), tmpbuf, length)) {
			result = SAM_STAT_CHECK_CONDITION;
			key = MISCOMPARE;
			asc = ASC_MISCOMPARE_DURING_VERIFY_OPERATION;
		}

		free(tmpbuf);
		break;
	case UNMAP:
		if (!cmd->dev->attrs.thinprovisioning) {
			result = SAM_STAT_CHECK_CONDITION;
			key = ILLEGAL_REQUEST;
			asc = ASC_INVALID_FIELD_IN_CDB;
			break;
		}

		length = scsi_get_out_length(cmd);
		tmpbuf = scsi_get_out_buffer(cmd);

		if (length < 8)
			break;

		length -= 8;
		tmpbuf += 8;

		while (length >= 16) {
			offset = get_unaligned_be64(&tmpbuf[0]);
			offset = offset << cmd->dev->blk_shift;

			tl = get_unaligned_be32(&tmpbuf[8]);
			tl = tl << cmd->dev->blk_shift;

			if (offset + tl > cmd->dev->size) {
				eprintf("UNMAP beyond EOF\n");
				result = SAM_STAT_CHECK_CONDITION;
				key = ILLEGAL_REQUEST;
				asc = ASC_LBA_OUT_OF_RANGE;
				break;
			}

			if (tl > 0) {
				if (rbd_discard(rbd->rbd_image, offset, tl)
				    != 0) {
					eprintf("Failed to punch hole for"
						" UNMAP at offset:%" PRIu64
						" length:%d\n",
						offset, tl);
					result = SAM_STAT_CHECK_CONDITION;
					key = HARDWARE_ERROR;
					asc = ASC_INTERNAL_TGT_FAILURE;
					break;
				}
			}

			length -= 16;
			tmpbuf += 16;
		}
		break;
	default:
		break;
	}

	dprintf("io done %p %x %d %u\n", cmd, cmd->scb[0], ret, length);

	scsi_set_result(cmd, result);

	if (result != SAM_STAT_GOOD) {
		eprintf("io error %p %x %d %d %" PRIu64 ", %m\n",
			cmd, cmd->scb[0], ret, length, offset);
		sense_data_build(cmd, key, asc);
	}
}
Example #14
0
static int target_xcopy_write_destination(
	struct se_cmd *ec_cmd,
	struct xcopy_op *xop,
	struct se_device *dst_dev,
	sector_t dst_lba,
	u32 dst_sectors)
{
	struct xcopy_pt_cmd *xpt_cmd;
	struct se_cmd *se_cmd;
	u32 length = (dst_sectors * dst_dev->dev_attrib.block_size);
	int rc;
	unsigned char cdb[16];
	bool remote_port = (xop->op_origin == XCOL_SOURCE_RECV_OP);

	xpt_cmd = kzalloc(sizeof(struct xcopy_pt_cmd), GFP_KERNEL);
	if (!xpt_cmd) {
		pr_err("Unable to allocate xcopy_pt_cmd\n");
		return -ENOMEM;
	}
	init_completion(&xpt_cmd->xpt_passthrough_sem);
	se_cmd = &xpt_cmd->se_cmd;

	memset(&cdb[0], 0, 16);
	cdb[0] = WRITE_16;
	put_unaligned_be64(dst_lba, &cdb[2]);
	put_unaligned_be32(dst_sectors, &cdb[10]);
	pr_debug("XCOPY: Built WRITE_16: LBA: %llu Sectors: %u Length: %u\n",
		(unsigned long long)dst_lba, dst_sectors, length);

	transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
			      DMA_TO_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
	xop->dst_pt_cmd = xpt_cmd;

	rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, dst_dev, &cdb[0],
				remote_port, false);
	if (rc < 0) {
		struct se_cmd *src_cmd = &xop->src_pt_cmd->se_cmd;
		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
		/*
		 * If the failure happened before the t_mem_list hand-off in
		 * target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that
		 * core releases this memory on error during X-COPY WRITE I/O.
		 */
		src_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
		src_cmd->t_data_sg = xop->xop_data_sg;
		src_cmd->t_data_nents = xop->xop_data_nents;

		transport_generic_free_cmd(se_cmd, 0);
		return rc;
	}

	rc = target_xcopy_issue_pt_cmd(xpt_cmd);
	if (rc < 0) {
		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
		se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
		transport_generic_free_cmd(se_cmd, 0);
		return rc;
	}

	return 0;
}
static void w8be(uint64_t val, uint64_t *x)
{
	put_unaligned_be64(val, x);
}
Example #16
0
int main(int argc, char *argv[])
{
	unsigned char sam_stat;
	char *progname = argv[0];
	char *pcl = NULL;
	char *mediaType = NULL;
	char *mediaCapacity = NULL;
	char *density = NULL;
	uint64_t size;
	struct MAM new_mam;
	char *lib = NULL;
	int libno = 0;
	int indx;
	int rc;
	char *config = MHVTL_CONFIG_PATH"/device.conf";
	FILE *conf;
	char *b;	/* Read from file into this buffer */
	char *s;	/* Somewhere for sscanf to store results */

	if (sizeof(struct MAM) != 1024) {
		printf("Structure of MAM incorrect size: %d\n",
						(int)sizeof(struct MAM));
		exit(2);
	}

	if (argc < 2) {
		usage(progname);
		exit(1);
	}

	debug = 0;
	my_id = 0;
	verbose = 0;
	wp = 0;

	while (argc > 0) {
		if (argv[0][0] == '-') {
			switch (argv[0][1]) {
			case 'd':
				if (argc > 1)
					density = argv[1];
				break;
			case 'l':
				if (argc > 1) {
					lib = argv[1];
				} else {
					puts("    More args needed for -l\n");
					exit(1);
				}
				break;
			case 'm':
				if (argc > 1) {
					pcl = argv[1];
				} else {
					puts("    More args needed for -m\n");
					exit(1);
				}
				break;
			case 's':
				if (argc > 1) {
					mediaCapacity = argv[1];
				} else {
					puts("    More args needed for -s\n");
					exit(1);
				}
				break;
			case 't':
				if (argc > 1) {
					mediaType = argv[1];
				} else {
					puts("    More args needed for -t\n");
					exit(1);
				}
				break;
			case 'V':
				printf("%s: version %s\n%s\n\n",
						progname, MHVTL_VERSION,
						(char *)largefile_support);
				break;
			case 'v':
				verbose++;
				break;
			case 'w':
				if (argc > 1) {
					if (!strncasecmp("yes", argv[1], 3))
						wp = WRITE_PROTECT_ON;
					else if (!strncasecmp("on", argv[1], 3))
						wp = WRITE_PROTECT_ON;
					else
						wp = WRITE_PROTECT_OFF;
				} else {
					puts("    More args needed for -m\n");
					exit(1);
				}
				break;
			}
		}
		argv++;
		argc--;
	}

	if (pcl == NULL) {
		printf("Please supply a barcode (-b barcode)\n\n");
		usage(progname);
		exit(1);
	}

	conf = fopen(config , "r");
	if (!conf) {
		printf("Can not open config file %s : %s", config,
					strerror(errno));
		perror("Can not open config file");
		exit(1);
	}
	s = zalloc(MALLOC_SZ);
	if (!s) {
		perror("Could not allocate memory");
		exit(1);
	}
	b = zalloc(MALLOC_SZ);
	if (!b) {
		perror("Could not allocate memory");
		exit(1);
	}

	rc = ENOENT;

	if (lib) {
		sscanf(lib, "%d", &libno);
		printf("Looking for PCL: %s in library %d\n", pcl, libno);
		find_media_home_directory(home_directory, libno);
		rc = load_tape(pcl, &sam_stat);
	} else { /* Walk thru all defined libraries looking for media */
		while (readline(b, MALLOC_SZ, conf) != NULL) {
			if (b[0] == '#')	/* Ignore comments */
				continue;
			/* If found a library: Attempt to load media
			 * Break out of loop if found. Otherwise try next lib.
			 */
			if (sscanf(b, "Library: %d CHANNEL:", &indx)) {
				find_media_home_directory(home_directory, indx);
				rc = load_tape(pcl, &sam_stat);
				if (!rc)
					break;
			}
		}
	}

	fclose(conf);
	free(s);
	free(b);

	if (rc) {
		fprintf(stderr, "PCL %s cannot be dumped, "
				"load_tape() returned %d\n",
					pcl, rc);
		exit(1);
	}

	/* Copy media MAM into temp location */
	memcpy(&new_mam, &mam, sizeof(mam));

	size = 0L;
	if (mediaCapacity) {
		sscanf(mediaCapacity, "%" PRId64, &size);
		printf("New capacity for %s: %ldMB\n",
					pcl, (unsigned long)size);
	}

	if (mediaType) {
		if (!strncasecmp("clean", mediaType, 5)) {
			MHVTL_DBG(1, "Setting media type to CLEAN");
			new_mam.MediumType = MEDIA_TYPE_CLEAN;
			new_mam.MediumTypeInformation = 20;
		} else if (!strncasecmp("data", mediaType, 4)) {
			MHVTL_DBG(1, "Setting media type to DATA");
			new_mam.MediumType = MEDIA_TYPE_DATA;
		} else if (!strncasecmp("null", mediaType, 4)) {
			MHVTL_DBG(1, "Setting media type to NULL");
			new_mam.MediumType = MEDIA_TYPE_NULL;
		} else if (!strncasecmp("WORM", mediaType, 4)) {
			MHVTL_DBG(1, "Setting media type to NULL");
			new_mam.MediumType = MEDIA_TYPE_WORM;
		} else {
			printf("Unknown media type: %s\n", mediaType);
			usage(progname);
			exit(1);
		}
	}
	if (density) {
		printf("Setting density to %s\n", density);
		if (set_media_params(&new_mam, density)) {
			printf("Could not determine media density: %s\n",
					density);
			unload_tape(&sam_stat);
			exit(1);
		}
	}
	if (size) {
		put_unaligned_be64(size * 1048576, &new_mam.max_capacity);
		/* This will set incorrect value to start with but next media
		 * Usage, this will be recalculated correctly
		 */
		put_unaligned_be64(size * 1048576, &new_mam.remaining_capacity);
	}
	switch (wp) {
	case WRITE_PROTECT_ON:
		new_mam.Flags |= MAM_FLAGS_MEDIA_WRITE_PROTECT;
		printf("Setting write-protect for %s\n", pcl);
		break;
	case WRITE_PROTECT_OFF:
		new_mam.Flags &= ~MAM_FLAGS_MEDIA_WRITE_PROTECT;
		printf("Turning off write-protect for %s\n", pcl);
		break;
	}

	put_unaligned_be64(sizeof(mam.pad), &new_mam.MAMSpaceRemaining);

	memcpy(&mam, &new_mam, sizeof(mam));
	rewriteMAM(&sam_stat);
	unload_tape(&sam_stat);

	exit(0);
}
Example #17
0
int main(int argc, char *argv[])
{
	unsigned char sam_stat;
	char *progname = argv[0];
	char *pcl = NULL;
	char *mediaType = NULL;
	char *mediaCapacity = NULL;
	char *density = NULL;
	char *lib = NULL;
	uint64_t size;
	int libno;
	struct stat statb;
	struct passwd *pw;

	if (sizeof(struct MAM) != 1024) {
		printf("Structure of MAM incorrect size: %d\n",
						(int)sizeof(struct MAM));
		exit(2);
	}

	if (argc < 2) {
		usage(progname);
		exit(1);
	}

	while(argc > 0) {
		if (argv[0][0] == '-') {
			switch (argv[0][1]) {
			case 'd':
				if (argc > 1)
					density = argv[1];
				break;
			case 'l':
				if (argc > 1) {
					lib = argv[1];
				} else {
					puts("    More args needed for -l\n");
					exit(1);
				}
				break;
			case 'm':
				if (argc > 1) {
					pcl = argv[1];
				} else {
					puts("    More args needed for -m\n");
					exit(1);
				}
				break;
			case 's':
				if (argc > 1) {
					mediaCapacity = argv[1];
				} else {
					puts("    More args needed for -s\n");
					exit(1);
				}
				break;
			case 't':
				if (argc > 1) {
					mediaType = argv[1];
				} else {
					puts("    More args needed for -t\n");
					exit(1);
				}
				break;
			case 'V':
				printf("%s: version %s\n%s\n\n",
						progname, MHVTL_VERSION,
						(char *)largefile_support);
				break;
			case 'v':
				verbose++;
				break;
			}
		}
		argv++;
		argc--;
	}

	if (pcl == NULL) {
		printf("Please supply a barcode (-b barcode)\n\n");
		usage(progname);
		exit(1);
	}
	if (mediaCapacity == NULL) {
		printf("Please supply media capacity (-s xx)\n\n");
		usage(progname);
		exit(1);
	}
	if (mediaType == NULL) {
		printf("Please supply cart type (-t data|clean|WORM)\n\n");
		usage(progname);
		exit(1);
	}
	if (lib == NULL) {
		printf("Please supply Library number (-l xx)\n\n");
		usage(progname);
		exit(1);
	}
	if (density == NULL) {
		printf("Please supply media density (-d xx)\n\n");
		usage(progname);
		exit(1);
	}

	sscanf(mediaCapacity, "%" PRId64, &size);
	if (size == 0)
		size = 8000;

	sscanf(lib, "%d", &libno);
	if (!libno) {
		printf("Invalid library number\n");
		exit(1);
	}

	find_media_home_directory(home_directory, libno);

	if (strlen(pcl) > MAX_BARCODE_LEN) {
		printf("Max barcode length (%d) exceeded\n\n", MAX_BARCODE_LEN);
		usage(progname);
		exit(1);
	}

	pw = getpwnam(USR);	/* Find UID for user 'vtl' */

	/* Verify that the MHVTL home directory exists. */
	if (stat(home_directory, &statb) < 0 && errno == ENOENT) {
		umask(0007);
		if (mkdir(home_directory, 02770) < 0) {
			printf("Cannot create PCL %s, directory %s:"
				"Doesn't exist and cannot be created\n",
						pcl, home_directory);
			exit(1);
		}
	}

	/* Don't really care if this fails or not..
	 * But lets try anyway
	 */
	if (chown(home_directory, pw->pw_uid, pw->pw_gid))
		;

	/* Initialize the contents of the MAM to be used for the new PCL. */
	memset((uint8_t *)&mam, 0, sizeof(mam));

	mam.tape_fmt_version = TAPE_FMT_VERSION;
	mam.mam_fmt_version = MAM_VERSION;
	put_unaligned_be64(size * 1048576, &mam.max_capacity);
	put_unaligned_be64(size * 1048576, &mam.remaining_capacity);
	put_unaligned_be64(sizeof(mam.pad), &mam.MAMSpaceRemaining);

	memcpy(&mam.MediumManufacturer, "linuxVTL", 8);
	memcpy(&mam.ApplicationVendor, "vtl-1.4 ", 8);
	sprintf((char *)mam.ApplicationVersion, "%d", TAPE_FMT_VERSION);

	if (! strncmp("clean", mediaType, 5)) {
		mam.MediumType = MEDIA_TYPE_CLEAN;	/* Cleaning cart */
		mam.MediumTypeInformation = 20;		/* Max cleaning loads */
	} else if (! strncmp("WORM", mediaType, 4)) {
		mam.MediumType = MEDIA_TYPE_WORM;	/* WORM cart */
	} else {
		mam.MediumType = MEDIA_TYPE_DATA;	/* Normal data cart */
	}
	set_media_params(&mam, density);

	sprintf((char *)mam.MediumSerialNumber, "%s_%d", pcl, (int)time(NULL));
	sprintf((char *)mam.MediumManufactureDate, "%d", (int)time(NULL));
	sprintf((char *)mam.Barcode, "%-31s", pcl);

	/* Create the PCL using the initialized MAM. */

	exit(create_tape(pcl, &mam, &sam_stat));
}
Example #18
0
static int target_xcopy_read_source(
	struct se_cmd *ec_cmd,
	struct xcopy_op *xop,
	struct se_device *src_dev,
	sector_t src_lba,
	u32 src_sectors)
{
	struct xcopy_pt_cmd *xpt_cmd;
	struct se_cmd *se_cmd;
	u32 length = (src_sectors * src_dev->dev_attrib.block_size);
	int rc;
	unsigned char cdb[16];
	bool remote_port = (xop->op_origin == XCOL_DEST_RECV_OP);

	xpt_cmd = kzalloc(sizeof(struct xcopy_pt_cmd), GFP_KERNEL);
	if (!xpt_cmd) {
		pr_err("Unable to allocate xcopy_pt_cmd\n");
		return -ENOMEM;
	}
	init_completion(&xpt_cmd->xpt_passthrough_sem);
	se_cmd = &xpt_cmd->se_cmd;

	memset(&cdb[0], 0, 16);
	cdb[0] = READ_16;
	put_unaligned_be64(src_lba, &cdb[2]);
	put_unaligned_be32(src_sectors, &cdb[10]);
	pr_debug("XCOPY: Built READ_16: LBA: %llu Sectors: %u Length: %u\n",
		(unsigned long long)src_lba, src_sectors, length);

	transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
			      DMA_FROM_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
	xop->src_pt_cmd = xpt_cmd;

	rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0],
				remote_port, true);
	if (rc < 0) {
		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
		transport_generic_free_cmd(se_cmd, 0);
		return rc;
	}

	xop->xop_data_sg = se_cmd->t_data_sg;
	xop->xop_data_nents = se_cmd->t_data_nents;
	pr_debug("XCOPY-READ: Saved xop->xop_data_sg: %p, num: %u for READ"
		" memory\n", xop->xop_data_sg, xop->xop_data_nents);

	rc = target_xcopy_issue_pt_cmd(xpt_cmd);
	if (rc < 0) {
		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
		transport_generic_free_cmd(se_cmd, 0);
		return rc;
	}
	/*
	 * Clear off the allocated t_data_sg, that has been saved for
	 * zero-copy WRITE submission reuse in struct xcopy_op..
	 */
	se_cmd->t_data_sg = NULL;
	se_cmd->t_data_nents = 0;

	return 0;
}