2004-11-30 20:31:16

by Kai Mäkisara (Kolumbus)

[permalink] [raw]
Subject: [PATCH] SCSI tape: remove use of file_count(), was Re: [patchset] Lockfree fd lookup 0 of 5

On Tue, 30 Nov 2004, Ravikiran G Thirumalai wrote:

> Kai, can you mail the latest version of this patch to lkml? Willem, can
> you make a patch similar to this for osst.c and mail it to lkml?
>
OK. The patch at the end of this message modifies st so that file_count()
is not used. It has been used to find the last call to the st_flush()
method for possible writing of the final filemark and rewinding the tape.
While these have been in st_flush(), it has been possible to return errors
in the return value of close(). The patch moves these operations to st_release()
and logs the possible errors since it is not possible to return these
errors to the user any more. Flushing the tape drive buffer is added to
st_flush() to minimise the possibility of errors not reported at close().

The patch is against 2.6.10-rc2-bk13, it compiles, and is lightly tested.
It should not be applied unless file_count() really is removed.

Signed-off-by: Kai Makisara <[email protected]>

--
Kai

--- linux-2.6.10-rc2-bk13/drivers/scsi/st.c 2004-11-30 20:43:30.000000000 +0200
+++ linux-2.6.10-rc2-bk13-k1/drivers/scsi/st.c 2004-11-30 21:20:17.000000000 +0200
@@ -17,7 +17,7 @@
Last modified: 18-JAN-1998 Richard Gooch <[email protected]> Devfs support
*/

-static char *verstr = "20041025";
+static char *verstr = "20041130";

#include <linux/module.h>

@@ -1078,20 +1078,21 @@
static int st_flush(struct file *filp)
{
int result = 0, result2;
- unsigned char cmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt;
struct scsi_tape *STp = filp->private_data;
- struct st_modedef *STm = &(STp->modes[STp->current_mode]);
struct st_partstat *STps = &(STp->ps[STp->partition]);
- char *name = tape_name(STp);
+ DEB(char *name = tape_name(STp));

- if (file_count(filp) > 1)
- return 0;
+ if (down_interruptible(&STp->lock))
+ return -ERESTARTSYS;

if (STps->rw == ST_WRITING && !STp->pos_unknown) {
result = flush_write_buffer(STp);
if (result != 0 && result != (-ENOSPC))
goto out;
+ /* Flush to tape */
+ result = st_int_ioctl(STp, MTWEOF, 0);
+ if (result)
+ goto out;
}

if (STp->can_partitions &&
@@ -1100,9 +1101,27 @@
"%s: switch_partition at close failed.\n", name));
if (result == 0)
result = result2;
- goto out;
}

+ out:
+ up(&STp->lock);
+ return result;
+}
+
+
+/* Close the device and release it. BKL is not needed: this is the only thread
+ accessing this tape. STp->pos_unknown is set if to block further access if
+ tape re-positioning fails. */
+static int st_release(struct inode *inode, struct file *filp)
+{
+ int result = 0, result2;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_tape *STp = filp->private_data;
+ struct st_modedef *STm = &(STp->modes[STp->current_mode]);
+ struct st_partstat *STps = &(STp->ps[STp->partition]);
+ struct scsi_request *SRpnt;
+ char *name = tape_name(STp);
+
DEBC( if (STp->nbr_requests)
printk(KERN_WARNING "%s: Number of r/w requests %d, dio used in %d, pages %d (%d).\n",
name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages, STp->nbr_combinable));
@@ -1175,24 +1194,22 @@
STps->drv_block = 0;
STps->eof = ST_FM;
}
+ if (result) {
+ printk(KERN_ERR "%s: Final tape positioning failed.\n", name);
+ STp->pos_unknown = 1;
+ }
}

- out:
+out:
if (STp->rew_at_close) {
result2 = st_int_ioctl(STp, MTREW, 1);
+ if (result2) {
+ printk(KERN_ERR "%s: Auto-rewind failed.\n", name);
+ STp->pos_unknown = 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;
- struct scsi_tape *STp = filp->private_data;

if (STp->door_locked == ST_LOCKED_AUTO)
do_door_lock(STp, 0);