⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 st.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	    __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);	return retval;}/* Flush the tape buffer before close */static int st_flush(struct file *filp){	int result = 0, result2;	unsigned char cmd[MAX_COMMAND_SIZE];	Scsi_Request *SRpnt;	Scsi_Tape *STp;	ST_mode *STm;	ST_partstat *STps;	struct inode *inode = filp->f_dentry->d_inode;	kdev_t devt = inode->i_rdev;	int dev;	if (file_count(filp) > 1)		return 0;	dev = TAPE_NR(devt);	read_lock(&st_dev_arr_lock);	STp = scsi_tapes[dev];	read_unlock(&st_dev_arr_lock);	STm = &(STp->modes[STp->current_mode]);	STps = &(STp->ps[STp->partition]);	if (STps->rw == ST_WRITING && !(STp->device)->was_reset) {		result = flush_write_buffer(STp);		if (result != 0 && result != (-ENOSPC))			goto out;	}	if (STp->can_partitions &&	    (result2 = update_partition(STp)) < 0) {                DEBC(printk(ST_DEB_MSG                               "st%d: update_partition at close failed.\n", dev));		if (result == 0)			result = result2;		goto out;	}	if (STps->rw == ST_WRITING && !(STp->device)->was_reset) {                DEBC(printk(ST_DEB_MSG "st%d: File length %ld bytes.\n",                            dev, (long) (filp->f_pos));                     printk(ST_DEB_MSG "st%d: Async write waits %d, finished %d.\n",                            dev, STp->nbr_waits, STp->nbr_finished);		)		memset(cmd, 0, MAX_COMMAND_SIZE);		cmd[0] = WRITE_FILEMARKS;		cmd[4] = 1 + STp->two_fm;		SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE,				   STp->timeout, MAX_WRITE_RETRIES, TRUE);		if (!SRpnt) {			result = (STp->buffer)->syscall_result;			goto out;		}		if ((STp->buffer)->syscall_result != 0 &&		    ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||		     (SRpnt->sr_sense_buffer[2] & 0x4f) != 0x40 ||		     ((SRpnt->sr_sense_buffer[0] & 0x80) != 0 &&		      (SRpnt->sr_sense_buffer[3] | SRpnt->sr_sense_buffer[4] |		       SRpnt->sr_sense_buffer[5] |		       SRpnt->sr_sense_buffer[6]) != 0))) {			/* Filter out successful write at EOM */			scsi_release_request(SRpnt);			SRpnt = NULL;			printk(KERN_ERR "st%d: Error on write filemark.\n", dev);			if (result == 0)				result = (-EIO);		} else {			scsi_release_request(SRpnt);			SRpnt = NULL;			if (STps->drv_file >= 0)				STps->drv_file++;			STps->drv_block = 0;			if (STp->two_fm)				cross_eof(STp, FALSE);			STps->eof = ST_FM;		}                DEBC(printk(ST_DEB_MSG "st%d: Buffer flushed, %d EOF(s) written\n",                            dev, cmd[4]));	} else if (!STp->rew_at_close) {		STps = &(STp->ps[STp->partition]);		if (!STm->sysv || STps->rw != ST_READING) {			if (STp->can_bsr)				result = flush_buffer(STp, 0);			else if (STps->eof == ST_FM_HIT) {				result = cross_eof(STp, FALSE);				if (result) {					if (STps->drv_file >= 0)						STps->drv_file++;					STps->drv_block = 0;					STps->eof = ST_FM;				} else					STps->eof = ST_NOEOF;			}		} else if ((STps->eof == ST_NOEOF &&			    !(result = cross_eof(STp, TRUE))) ||			   STps->eof == ST_FM_HIT) {			if (STps->drv_file >= 0)				STps->drv_file++;			STps->drv_block = 0;			STps->eof = ST_FM;		}	}      out:	if (STp->rew_at_close) {		result2 = st_int_ioctl(STp, MTREW, 1);		if (result == 0)			result = result2;	}	return result;}/* Close the device and release it. BKL is not needed: this is the only thread   accessing this tape. */static int st_release(struct inode *inode, struct file *filp){	int result = 0;	Scsi_Tape *STp;	unsigned long flags;	kdev_t devt = inode->i_rdev;	int dev;	dev = TAPE_NR(devt);	read_lock(&st_dev_arr_lock);	STp = scsi_tapes[dev];	read_unlock(&st_dev_arr_lock);	if (STp->door_locked == ST_LOCKED_AUTO)		st_int_ioctl(STp, MTUNLOCK, 0);	if (STp->buffer != NULL) {		normalize_buffer(STp->buffer);		write_lock_irqsave(&st_dev_arr_lock, flags);		(STp->buffer)->in_use = 0;		STp->buffer = NULL;	}	else {		write_lock_irqsave(&st_dev_arr_lock, flags);	}	STp->in_use = 0;	write_unlock_irqrestore(&st_dev_arr_lock, flags);	if (STp->device->host->hostt->module)		__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);	return result;}/* Write command */static ssize_t st_write(struct file *filp, const char *buf, size_t count, loff_t * ppos){	struct inode *inode = filp->f_dentry->d_inode;	ssize_t total;	ssize_t i, do_count, blks, transfer;	ssize_t retval = 0;	int write_threshold;	int doing_write = 0;	unsigned char cmd[MAX_COMMAND_SIZE];	const char *b_point;	Scsi_Request *SRpnt = NULL;	Scsi_Tape *STp;	ST_mode *STm;	ST_partstat *STps;	int dev = TAPE_NR(inode->i_rdev);	read_lock(&st_dev_arr_lock);	STp = scsi_tapes[dev];	read_unlock(&st_dev_arr_lock);	if (down_interruptible(&STp->lock))		return -ERESTARTSYS;	/*	 * If we are in the middle of error recovery, don't let anyone	 * else try and use this device.  Also, if error recovery fails, it	 * may try and take the device offline, in which case all further	 * access to the device is prohibited.	 */	if (!scsi_block_when_processing_errors(STp->device)) {		retval = (-ENXIO);		goto out;	}	if (ppos != &filp->f_pos) {		/* "A request was outside the capabilities of the device." */		retval = (-ENXIO);		goto out;	}	if (STp->ready != ST_READY) {		if (STp->ready == ST_NO_TAPE)			retval = (-ENOMEDIUM);		else			retval = (-EIO);		goto out;	}	STm = &(STp->modes[STp->current_mode]);	if (!STm->defined) {		retval = (-ENXIO);		goto out;	}	if (count == 0)		goto out;	/*	 * If there was a bus reset, block further access	 * to this device.	 */	if (STp->device->was_reset) {		retval = (-EIO);		goto out;	}        DEB(	if (!STp->in_use) {		printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);		retval = (-EIO);		goto out;	} ) /* end DEB */	/* Write must be integral number of blocks */	if (STp->block_size != 0 && (count % STp->block_size) != 0) {		printk(KERN_WARNING "st%d: Write not multiple of tape block size.\n",		       dev);		retval = (-EINVAL);		goto out;	}	if (STp->can_partitions &&	    (retval = update_partition(STp)) < 0)		goto out;	STps = &(STp->ps[STp->partition]);	if (STp->write_prot) {		retval = (-EACCES);		goto out;	}	if (STp->block_size == 0) {		if (STp->max_block > 0 &&		    (count < STp->min_block || count > STp->max_block)) {			retval = (-EINVAL);			goto out;		}		if (count > (STp->buffer)->buffer_size &&		    !enlarge_buffer(STp->buffer, count, STp->restr_dma)) {			retval = (-EOVERFLOW);			goto out;		}	}	if ((STp->buffer)->buffer_blocks < 1) {		/* Fixed block mode with too small buffer */		if (!enlarge_buffer(STp->buffer, STp->block_size, STp->restr_dma)) {			retval = (-EOVERFLOW);			goto out;		}		(STp->buffer)->buffer_blocks = 1;	}	if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&	    !st_int_ioctl(STp, MTLOCK, 0))		STp->door_locked = ST_LOCKED_AUTO;	if (STps->rw == ST_READING) {		retval = flush_buffer(STp, 0);		if (retval)			goto out;		STps->rw = ST_WRITING;	} else if (STps->rw != ST_WRITING &&		   STps->drv_file == 0 && STps->drv_block == 0) {		if ((retval = set_mode_densblk(STp, STm)) < 0)			goto out;		if (STm->default_compression != ST_DONT_TOUCH &&		    !(STp->compression_changed)) {			if (st_compression(STp, (STm->default_compression == ST_YES))) {				printk(KERN_WARNING "st%d: Can't set default compression.\n",				       dev);				if (modes_defined) {					retval = (-EINVAL);					goto out;				}			}		}	}	if ((STp->buffer)->writing) {		write_behind_check(STp);		if ((STp->buffer)->syscall_result) {                        DEBC(printk(ST_DEB_MSG "st%d: Async write error (write) %x.\n",                                    dev, (STp->buffer)->midlevel_result));			if ((STp->buffer)->midlevel_result == INT_MAX)				STps->eof = ST_EOM_OK;			else				STps->eof = ST_EOM_ERROR;		}	}	if (STps->eof == ST_EOM_OK) {		retval = (-ENOSPC);		goto out;	}	else if (STps->eof == ST_EOM_ERROR) {		retval = (-EIO);		goto out;	}	/* Check the buffer readability in cases where copy_user might catch	   the problems after some tape movement. */	if (STp->block_size != 0 &&	    (copy_from_user(&i, buf, 1) != 0 ||	     copy_from_user(&i, buf + count - 1, 1) != 0)) {		retval = (-EFAULT);		goto out;	}	if (!STm->do_buffer_writes) {#if 0		if (STp->block_size != 0 && (count % STp->block_size) != 0) {			retval = (-EINVAL);	/* Write must be integral number of blocks */			goto out;		}#endif		write_threshold = 1;	} else		write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;	if (!STm->do_async_writes)		write_threshold--;	total = count;	memset(cmd, 0, MAX_COMMAND_SIZE);	cmd[0] = WRITE_6;	cmd[1] = (STp->block_size != 0);	STps->rw = ST_WRITING;	b_point = buf;	while ((STp->block_size == 0 && !STm->do_async_writes && count > 0) ||	       (STp->block_size != 0 &&		(STp->buffer)->buffer_bytes + count > write_threshold)) {		doing_write = 1;		if (STp->block_size == 0)			do_count = count;		else {			do_count = (STp->buffer)->buffer_blocks * STp->block_size -			    (STp->buffer)->buffer_bytes;			if (do_count > count)				do_count = count;		}		i = append_to_buffer(b_point, STp->buffer, do_count);		if (i) {			retval = i;			goto out;		}		if (STp->block_size == 0)			blks = transfer = do_count;		else {			blks = (STp->buffer)->buffer_bytes /			    STp->block_size;			transfer = blks * STp->block_size;		}		cmd[2] = blks >> 16;		cmd[3] = blks >> 8;		cmd[4] = blks;		SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,				   STp->timeout, MAX_WRITE_RETRIES, TRUE);		if (!SRpnt) {			retval = (STp->buffer)->syscall_result;			goto out;		}		if ((STp->buffer)->syscall_result != 0) {                        DEBC(printk(ST_DEB_MSG "st%d: Error on write:\n", dev));			if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&			    (SRpnt->sr_sense_buffer[2] & 0x40)) {				if (STp->block_size != 0 &&                                    (SRpnt->sr_sense_buffer[0] & 0x80) != 0)					transfer = (SRpnt->sr_sense_buffer[3] << 24) |					    (SRpnt->sr_sense_buffer[4] << 16) |					    (SRpnt->sr_sense_buffer[5] << 8) |                                                SRpnt->sr_sense_buffer[6];				else if (STp->block_size == 0 &&					 (SRpnt->sr_sense_buffer[2] & 0x0f) ==                                         VOLUME_OVERFLOW)					transfer = do_count;				else					transfer = 0;				if (STp->block_size != 0)					transfer *= STp->block_size;				if (transfer <= do_count) {					filp->f_pos += do_count - transfer;					count -= do_count - transfer;					if (STps->drv_block >= 0) {						if (STp->block_size == 0 &&                                                    transfer < do_count)							STps->drv_block++;						else if (STp->block_size != 0)							STps->drv_block +=                                                                (do_count - transfer) /                                                                STp->block_size;					}					STps->eof = ST_EOM_OK;					retval = (-ENOSPC); /* EOM within current request */                                        DEBC(printk(ST_DEB_MSG                                                       "st%d: EOM with %d bytes unwritten.\n",						       dev, transfer));				} else {					STps->eof = ST_EOM_ERROR;					STps->drv_block = (-1); /* Too cautious? */					retval = (-EIO);	/* EOM for old data */					DEBC(printk(ST_DEB_MSG                                                       "st%d: EOM with lost data.\n",                                                       dev));				}			} else {				STps->drv_block = (-1);		/* Too cautious? */				retval = (-EIO);			}			scsi_release_request(SRpnt);			SRpnt = NULL;			(STp->buffer)->buffer_bytes = 0;			STp->dirty = 0;			if (count < total)				retval = total - count;			goto out;		}		filp->f_pos += do_count;		b_point += do_count;		count -= do_count;		if (STps->drv_block >= 0) {			if (STp->block_size == 0)				STps->drv_block++;			else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -