Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
27c43263
Commit
27c43263
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 0.99.14i
parent
3b100d90
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
749 additions
and
499 deletions
+749
-499
drivers/scsi/scsi.c
drivers/scsi/scsi.c
+7
-1
drivers/scsi/scsi.h
drivers/scsi/scsi.h
+1
-0
drivers/scsi/st.c
drivers/scsi/st.c
+507
-369
drivers/scsi/st.h
drivers/scsi/st.h
+12
-0
fs/nfs/proc.c
fs/nfs/proc.c
+104
-53
include/linux/in.h
include/linux/in.h
+33
-20
ipc/msg.c
ipc/msg.c
+3
-4
ipc/sem.c
ipc/sem.c
+4
-4
ipc/shm.c
ipc/shm.c
+4
-4
kernel/printk.c
kernel/printk.c
+3
-1
net/inet/icmp.c
net/inet/icmp.c
+2
-2
net/inet/inet.h
net/inet/inet.h
+1
-1
net/inet/route.c
net/inet/route.c
+64
-38
tools/build.c
tools/build.c
+4
-2
No files found.
drivers/scsi/scsi.c
View file @
27c43263
...
...
@@ -922,7 +922,11 @@ static int check_sense (Scsi_Cmnd * SCpnt)
switch
(
SCpnt
->
sense_buffer
[
2
]
&
0xf
)
{
case
NO_SENSE
:
return
0
;
case
RECOVERED_ERROR
:
if
(
scsi_devices
[
SCpnt
->
index
].
type
==
TYPE_TAPE
)
return
SUGGEST_IS_OK
;
else
return
0
;
case
ABORTED_COMMAND
:
...
...
@@ -1041,6 +1045,8 @@ static void scsi_done (Scsi_Cmnd * SCpnt)
update_timeout
(
SCpnt
,
oldto
);
status
=
REDO
;
break
;
case
SUGGEST_IS_OK
:
break
;
case
SUGGEST_REMAP
:
case
SUGGEST_RETRY
:
#ifdef DEBUG
...
...
drivers/scsi/scsi.h
View file @
27c43263
...
...
@@ -192,6 +192,7 @@ extern const unsigned char scsi_command_size[8];
#define SUGGEST_REMAP 0x30
#define SUGGEST_DIE 0x40
#define SUGGEST_SENSE 0x80
#define SUGGEST_IS_OK 0xff
#define DRIVER_SENSE 0x08
...
...
drivers/scsi/st.c
View file @
27c43263
...
...
@@ -5,6 +5,8 @@
History:
Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
Contribution and ideas from several people including Eric Youngdale and
Wolfgang Denk.
Features:
- support for different block sizes and internal buffering
...
...
@@ -25,15 +27,16 @@
Nonrewind device has the minor number equal to tape number + 128.
Problems:
The end of media detection may not work correctly because of the buffering.
If you want to do multiple tape backups relying on end of tape detection,
you should disable write behind and in addition to that check that the
tapes are readable.
The end of media detection works correctly in writing only if the drive
writes the buffer contents after the early-warning mark. If you want to
be sure that EOM is reported correctly, you should uncomment the line
defining ST_NO_DELAYED_WRITES. Note that when delayed writes are disabled
each write byte count must be an integral number of blocks.
Copyright 1992, 1993 Kai Makisara
email makisara@vtinsx.ins.vtt.fi or Kai.Makisara@vtt.fi
Last modified:
Sat Jul 10 17:40:05 1993 by root
Last modified:
Thu Nov 25 21:49:02 1993 by root@kai.home
*/
#include <linux/fs.h>
...
...
@@ -52,10 +55,7 @@
#include "scsi.h"
#include "scsi_ioctl.h"
#include "st.h"
#define MAX_RETRIES 0
#define MAX_READY_RETRIES 5
#define NO_TAPE NOT_READY
#include "constants.h"
/* Uncomment the following if you want the rewind, etc. commands return
before command completion. */
...
...
@@ -66,26 +66,43 @@
to the filemarks even wihout ST_IN_FILE_POS defined */
/* #define ST_IN_FILE_POS */
/* #define DEBUG */
/* Uncomment the following if you want recovered write errors to be
fatal. */
/* #define ST_RECOVERED_WRITE_FATAL */
#define ST_TIMEOUT 9000
#define ST_LONG_TIMEOUT 200000
/* Uncomment the following if you want all data from a write command to
be written to tape before the command returns. Disables write-behind. */
/* #define ST_NO_DELAYED_WRITES */
/* Number of ST_BLOCK_SIZE blocks in the buffers */
#define ST_BUFFER_BLOCKS 64
/* Write-behind can be disabled by setting ST_WRITE_THRESHOLD_BLOCKS equal
to or
larger than ST_BUFFER_BLOCKS */
/* Write-behind can be disabled by setting ST_WRITE_THRESHOLD_BLOCKS equal
to or
larger than ST_BUFFER_BLOCKS */
#define ST_WRITE_THRESHOLD_BLOCKS 60
#define ST_BLOCK_SIZE 512
#define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_BLOCK_SIZE)
#define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_BLOCK_SIZE)
#ifdef ST_NO_DELAYED_WRITES
#undef ST_WRITE_THRESHOLD_BLOCKS
#define ST_WRITE_THRESHOLD_BLOCKS ST_BUFFER_BLOCKS
#endif
/* The buffer size should fit into the 24 bits reserved for length in the
6-byte SCSI read and write commands. */
#if ST_BUFFER_SIZE >= (2 << 24 - 1)
#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
#endif
/* #define DEBUG */
#define MAX_RETRIES 0
#define MAX_READY_RETRIES 5
#define NO_TAPE NOT_READY
#define ST_TIMEOUT 9000
#define ST_LONG_TIMEOUT 200000
static
int
st_nbr_buffers
;
static
ST_buffer
*
st_buffers
[
2
];
...
...
@@ -99,72 +116,113 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
/* Wakeup from interrupt */
static
void
st_sleep_done
(
Scsi_Cmnd
*
SCpnt
)
{
int
st_nbr
;
if
((
st_nbr
=
SCpnt
->
request
.
dev
)
<
NR_ST
&&
st_nbr
>=
0
)
{
if
(
scsi_tapes
[
st_nbr
].
buffer
->
writing
&&
(
SCpnt
->
sense_buffer
[
0
]
&
0x70
)
==
0x70
&&
(
SCpnt
->
sense_buffer
[
2
]
&
0x40
))
scsi_tapes
[
st_nbr
].
buffer
->
last_result
=
INT_MAX
;
else
scsi_tapes
[
st_nbr
].
buffer
->
last_result
=
SCpnt
->
result
;
if
(
scsi_tapes
[
st_nbr
].
buffer
->
writing
)
SCpnt
->
request
.
dev
=
-
1
;
else
SCpnt
->
request
.
dev
=
0xffff
;
if
(
scsi_tapes
[
st_nbr
].
buffer
->
writing
<=
0
)
wake_up
(
&
scsi_tapes
[
st_nbr
].
waiting
);
}
#ifdef DEBUG
else
printk
(
"st?: Illegal interrupt device %x
\n
"
,
st_nbr
);
#endif
}
/* Convert the result to success code */
static
int
st_chk_result
(
Scsi_Cmnd
*
SCpnt
)
static
int
st_chk_result
(
Scsi_Cmnd
*
SCpnt
)
{
#ifdef DEBUG
int
dev
=
SCpnt
->
request
.
dev
;
#endif
int
result
=
SCpnt
->
result
;
unsigned
char
*
sense
=
SCpnt
->
sense_buffer
;
char
*
stp
;
if
(
!
result
)
if
(
!
result
&&
SCpnt
->
sense_buffer
[
0
]
==
0
)
return
0
;
#ifdef DEBUG
printk
(
"st%d: Error: %x
\n
"
,
dev
,
result
);
print_sense
(
"st"
,
SCpnt
);
#endif
/* if ((sense[0] & 0x70) == 0x70 &&
((sense[2] & 0x80) ))
return 0; */
if
((
sense
[
0
]
&
0x70
)
==
0x70
&&
((
sense
[
2
]
&
0x80
)
/* || ((sense[2] & 0x0f) == 8) */
))
sense
[
2
]
==
RECOVERED_ERROR
#ifdef ST_RECOVERED_WRITE_FATAL
&&
SCpnt
->
cmnd
[
0
]
!=
WRITE_6
&&
SCpnt
->
cmnd
[
0
]
!=
WRITE_FILEMARKS
#endif
)
{
scsi_tapes
[
dev
].
recover_count
++
;
if
(
SCpnt
->
cmnd
[
0
]
==
READ_6
)
stp
=
"read"
;
else
if
(
SCpnt
->
cmnd
[
0
]
==
WRITE_6
)
stp
=
"write"
;
else
stp
=
"ioctl"
;
printk
(
"st%d: Recovered %s error (%d).
\n
"
,
dev
,
stp
,
scsi_tapes
[
dev
].
recover_count
);
return
0
;
}
return
(
-
EIO
);
}
/* Wakeup from interrupt */
static
void
st_sleep_done
(
Scsi_Cmnd
*
SCpnt
)
{
int
st_nbr
,
remainder
;
Scsi_Tape
*
STp
;
if
((
st_nbr
=
SCpnt
->
request
.
dev
)
<
NR_ST
&&
st_nbr
>=
0
)
{
STp
=
&
(
scsi_tapes
[
st_nbr
]);
if
((
STp
->
buffer
)
->
writing
&&
(
SCpnt
->
sense_buffer
[
0
]
&
0x70
)
==
0x70
&&
(
SCpnt
->
sense_buffer
[
2
]
&
0x40
))
{
/* EOM at write-behind, has all been written? */
if
((
SCpnt
->
sense_buffer
[
0
]
&
0x80
)
!=
0
)
remainder
=
(
SCpnt
->
sense_buffer
[
3
]
<<
24
)
|
(
SCpnt
->
sense_buffer
[
4
]
<<
16
)
|
(
SCpnt
->
sense_buffer
[
5
]
<<
8
)
|
SCpnt
->
sense_buffer
[
6
];
else
remainder
=
0
;
if
((
SCpnt
->
sense_buffer
[
2
]
&
0x0f
)
==
VOLUME_OVERFLOW
||
remainder
>
0
)
(
STp
->
buffer
)
->
last_result
=
SCpnt
->
result
;
/* Error */
else
(
STp
->
buffer
)
->
last_result
=
INT_MAX
;
/* OK */
}
else
(
STp
->
buffer
)
->
last_result
=
SCpnt
->
result
;
(
STp
->
buffer
)
->
last_result_fatal
=
st_chk_result
(
SCpnt
);
if
((
STp
->
buffer
)
->
writing
)
SCpnt
->
request
.
dev
=
-
1
;
else
SCpnt
->
request
.
dev
=
0xffff
;
if
((
STp
->
buffer
)
->
writing
<=
0
)
wake_up
(
&
(
STp
->
waiting
)
);
}
#ifdef DEBUG
else
printk
(
"st?: Illegal interrupt device %x
\n
"
,
st_nbr
);
#endif
}
#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
/* Handle the write-behind checking */
static
void
write_behind_check
(
int
dev
)
static
void
write_behind_check
(
int
dev
)
{
Scsi_Tape
*
STp
;
ST_buffer
*
STbuffer
;
STp
=
&
(
scsi_tapes
[
dev
]);
STbuffer
=
STp
->
buffer
;
cli
();
if
(
scsi_tapes
[
dev
].
buffer
->
last_result
<
0
)
{
scsi_tapes
[
dev
].
buffer
->
writing
=
(
-
scsi_tapes
[
dev
].
buffer
->
writing
);
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
scsi_tapes
[
dev
].
buffer
->
writing
=
(
-
scsi_tapes
[
dev
].
buffer
->
writing
);
if
(
ST
buffer
->
last_result
<
0
)
{
STbuffer
->
writing
=
(
-
ST
buffer
->
writing
);
sleep_on
(
&
(
STp
->
waiting
)
);
STbuffer
->
writing
=
(
-
ST
buffer
->
writing
);
}
sti
();
if
(
scsi_tapes
[
dev
].
buffer
->
writing
<
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
)
memcpy
(
scsi_tapes
[
dev
].
buffer
->
b_data
,
scsi_tapes
[
dev
].
buffer
->
b_data
+
scsi_tapes
[
dev
].
buffer
->
writing
,
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
-
scsi_tapes
[
dev
].
buffer
->
writing
);
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
-=
scsi_tapes
[
dev
].
buffer
->
writing
;
scsi_tapes
[
dev
].
buffer
->
writing
=
0
;
if
(
STbuffer
->
writing
<
STbuffer
->
buffer_bytes
)
memcpy
(
STbuffer
->
b_data
,
STbuffer
->
b_data
+
STbuffer
->
writing
,
STbuffer
->
buffer_bytes
-
STbuffer
->
writing
);
STbuffer
->
buffer_bytes
-=
STbuffer
->
writing
;
STbuffer
->
writing
=
0
;
return
;
}
...
...
@@ -172,63 +230,72 @@ static void write_behind_check(int dev)
/* Flush the write buffer (never need to write if variable blocksize). */
static
int
flush_write_buffer
(
int
dev
)
static
int
flush_write_buffer
(
int
dev
)
{
int
offset
,
transfer
,
blks
;
int
result
;
unsigned
char
cmd
[
10
];
Scsi_Cmnd
*
SCpnt
;
Scsi_Tape
*
STp
=
&
(
scsi_tapes
[
dev
]);
#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
if
(
scsi_tapes
[
dev
].
buffer
->
writing
)
{
if
(
(
STp
->
buffer
)
->
writing
)
{
write_behind_check
(
dev
);
if
(
scsi_tapes
[
dev
].
buffer
->
last_result
)
{
if
(
(
STp
->
buffer
)
->
last_result_fatal
)
{
#ifdef DEBUG
printk
(
"st%d: Async write error %x.
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
last_result
);
(
STp
->
buffer
)
->
last_result
);
#endif
if
((
STp
->
buffer
)
->
last_result
==
INT_MAX
)
return
(
-
ENOSPC
);
return
(
-
EIO
);
}
}
#endif
result
=
0
;
if
(
scsi_tapes
[
dev
].
dirty
==
1
)
{
SCpnt
=
allocate_device
(
NULL
,
scsi_tapes
[
dev
].
device
->
index
,
1
);
if
(
STp
->
dirty
==
1
)
{
SCpnt
=
allocate_device
(
NULL
,
(
STp
->
device
)
->
index
,
1
);
offset
=
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
;
transfer
=
((
offset
+
scsi_tapes
[
dev
].
block_size
-
1
)
/
scsi_tapes
[
dev
].
block_size
)
*
scsi_tapes
[
dev
].
block_size
;
offset
=
(
STp
->
buffer
)
->
buffer_bytes
;
transfer
=
((
offset
+
STp
->
block_size
-
1
)
/
STp
->
block_size
)
*
STp
->
block_size
;
#ifdef DEBUG
printk
(
"st%d: Flushing %d bytes.
\n
"
,
dev
,
transfer
);
#endif
memset
(
scsi_tapes
[
dev
].
buffer
->
b_data
+
offset
,
0
,
transfer
-
offset
);
memset
(
(
STp
->
buffer
)
->
b_data
+
offset
,
0
,
transfer
-
offset
);
SCpnt
->
sense_buffer
[
0
]
=
0
;
memset
(
cmd
,
0
,
10
);
cmd
[
0
]
=
WRITE_6
;
cmd
[
1
]
=
1
;
blks
=
transfer
/
scsi_tapes
[
dev
].
block_size
;
blks
=
transfer
/
STp
->
block_size
;
cmd
[
2
]
=
blks
>>
16
;
cmd
[
3
]
=
blks
>>
8
;
cmd
[
4
]
=
blks
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
scsi_tapes
[
dev
].
buffer
->
b_data
,
transfer
,
(
void
*
)
cmd
,
(
STp
->
buffer
)
->
b_data
,
transfer
,
st_sleep_done
,
ST_TIMEOUT
,
MAX_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
if
(
SCpnt
->
result
!=
0
)
{
printk
(
"st%d: Error on flush:
\n
"
,
dev
);
#ifdef DEBUG
st_chk_result
(
SCpnt
);
#endif
if
((
STp
->
buffer
)
->
last_result_fatal
!=
0
)
{
printk
(
"st%d: Error on flush.
\n
"
,
dev
);
if
((
SCpnt
->
sense_buffer
[
0
]
&
0x70
)
==
0x70
&&
(
SCpnt
->
sense_buffer
[
2
]
&
0x40
)
&&
(
SCpnt
->
sense_buffer
[
2
]
&
0x0f
)
!=
VOLUME_OVERFLOW
)
{
STp
->
dirty
=
0
;
(
STp
->
buffer
)
->
buffer_bytes
=
0
;
result
=
(
-
ENOSPC
);
}
else
result
=
(
-
EIO
);
}
else
{
scsi_tapes
[
dev
].
dirty
=
0
;
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
0
;
STp
->
dirty
=
0
;
(
STp
->
buffer
)
->
buffer_bytes
=
0
;
}
SCpnt
->
request
.
dev
=
-
1
;
/* Mark as not busy */
}
...
...
@@ -238,52 +305,63 @@ static int flush_write_buffer(int dev)
/* Flush the tape buffer. The tape will be positioned correctly unless
seek_next is true. */
static
int
flush_buffer
(
struct
inode
*
inode
,
struct
file
*
filp
,
int
seek_next
)
static
int
flush_buffer
(
struct
inode
*
inode
,
struct
file
*
filp
,
int
seek_next
)
{
int
dev
;
int
backspace
,
result
;
Scsi_Tape
*
STp
;
ST_buffer
*
STbuffer
;
dev
=
MINOR
(
inode
->
i_rdev
)
&
127
;
STp
=
&
(
scsi_tapes
[
dev
]);
STbuffer
=
STp
->
buffer
;
if
(
scsi_tapes
[
dev
].
rw
==
2
)
/* Writing */
if
(
STp
->
rw
==
ST_WRITING
)
/* Writing */
return
flush_write_buffer
(
dev
);
if
(
scsi_tapes
[
dev
].
block_size
==
0
)
if
(
STp
->
block_size
==
0
)
return
0
;
backspace
=
(
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
+
scsi_tapes
[
dev
].
buffer
->
read_pointer
)
/
scsi_tapes
[
dev
].
block_size
-
(
scsi_tapes
[
dev
].
buffer
->
read_pointer
+
scsi_tapes
[
dev
].
block_size
-
1
)
/
scsi_tapes
[
dev
].
block_size
;
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
0
;
scsi_tapes
[
dev
].
buffer
->
read_pointer
=
0
;
backspace
=
(
(
STp
->
buffer
)
->
buffer_bytes
+
(
STp
->
buffer
)
->
read_pointer
)
/
STp
->
block_size
-
(
(
STp
->
buffer
)
->
read_pointer
+
STp
->
block_size
-
1
)
/
STp
->
block_size
;
(
STp
->
buffer
)
->
buffer_bytes
=
0
;
(
STp
->
buffer
)
->
read_pointer
=
0
;
result
=
0
;
if
(
!
seek_next
&&
backspace
>
0
)
{
result
=
st_int_ioctl
(
inode
,
filp
,
MTBSR
,
backspace
);
if
(
!
seek_next
)
{
if
((
STp
->
eof
==
ST_FM
)
&&
!
STp
->
eof_hit
)
{
result
=
st_int_ioctl
(
inode
,
filp
,
MTBSF
,
1
);
/* Back over the EOF hit */
if
(
!
result
)
{
scsi_tapes
[
dev
].
eof
=
0
;
scsi_tapes
[
dev
].
eof_hit
=
0
;
STp
->
eof
=
ST_NOEOF
;
STp
->
eof_hit
=
0
;
}
}
if
(
!
result
&&
backspace
>
0
)
result
=
st_int_ioctl
(
inode
,
filp
,
MTBSR
,
backspace
);
}
return
result
;
}
/* Open the device */
static
int
scsi_tape_open
(
struct
inode
*
inode
,
struct
file
*
filp
)
static
int
scsi_tape_open
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
int
dev
;
unsigned
short
flags
;
int
i
;
unsigned
char
cmd
[
10
];
Scsi_Cmnd
*
SCpnt
;
Scsi_Tape
*
STp
;
dev
=
MINOR
(
inode
->
i_rdev
)
&
127
;
if
(
dev
>=
NR_ST
)
return
(
-
ENODEV
);
if
(
scsi_tapes
[
dev
].
in_use
)
{
STp
=
&
(
scsi_tapes
[
dev
]);
if
(
STp
->
in_use
)
{
printk
(
"st%d: Device already in use.
\n
"
,
dev
);
return
(
-
EBUSY
);
}
...
...
@@ -296,20 +374,21 @@ static int scsi_tape_open(struct inode * inode, struct file * filp)
printk
(
"st%d: No free buffers.
\n
"
,
dev
);
return
(
-
EBUSY
);
}
st_buffers
[
i
]
->
in_use
=
1
;
st_buffers
[
i
]
->
writing
=
0
;
scsi_tapes
[
dev
].
buffer
=
st_buffers
[
i
]
;
scsi_tapes
[
dev
].
in_use
=
1
;
STp
->
buffer
=
st_buffers
[
i
]
;
(
STp
->
buffer
)
->
in_use
=
1
;
(
STp
->
buffer
)
->
writing
=
0
;
STp
->
in_use
=
1
;
flags
=
filp
->
f_flags
;
scsi_tapes
[
dev
].
write_prot
=
((
flags
&
O_ACCMODE
)
==
O_RDONLY
);
STp
->
write_prot
=
((
flags
&
O_ACCMODE
)
==
O_RDONLY
);
scsi_tapes
[
dev
].
dirty
=
0
;
scsi_tapes
[
dev
].
rw
=
0
;
scsi_tapes
[
dev
].
eof
=
0
;
scsi_tapes
[
dev
].
eof_hit
=
0
;
STp
->
dirty
=
0
;
STp
->
rw
=
ST_IDLE
;
STp
->
eof
=
ST_NOEOF
;
STp
->
eof_hit
=
0
;
STp
->
recover_count
=
0
;
SCpnt
=
allocate_device
(
NULL
,
scsi_tapes
[
dev
].
device
->
index
,
1
);
SCpnt
=
allocate_device
(
NULL
,
(
STp
->
device
)
->
index
,
1
);
if
(
!
SCpnt
)
{
printk
(
"st%d: Tape request not allocated"
,
dev
);
return
(
-
EBUSY
);
...
...
@@ -320,40 +399,34 @@ static int scsi_tape_open(struct inode * inode, struct file * filp)
cmd
[
0
]
=
TEST_UNIT_READY
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
(
void
*
)
scsi_tapes
[
dev
].
buffer
->
b_data
,
(
void
*
)
cmd
,
(
void
*
)
(
STp
->
buffer
)
->
b_data
,
ST_BLOCK_SIZE
,
st_sleep_done
,
ST_LONG_TIMEOUT
,
MAX_READY_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
if
((
SCpnt
->
sense_buffer
[
0
]
&
0x70
)
==
0x70
&&
(
SCpnt
->
sense_buffer
[
2
]
&
0x0f
)
==
UNIT_ATTENTION
)
{
/* New media? */
#ifdef DEBUG
print_sense
(
"st"
,
SCpnt
);
#endif
SCpnt
->
sense_buffer
[
0
]
=
0
;
memset
((
void
*
)
&
cmd
[
0
],
0
,
10
);
cmd
[
0
]
=
TEST_UNIT_READY
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
(
void
*
)
scsi_tapes
[
dev
].
buffer
->
b_data
,
(
void
*
)
cmd
,
(
void
*
)
(
STp
->
buffer
)
->
b_data
,
ST_BLOCK_SIZE
,
st_sleep_done
,
ST_LONG_TIMEOUT
,
MAX_READY_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
}
if
(
SCpnt
->
result
!=
0
)
{
#ifdef DEBUG
print_sense
(
"st"
,
SCpnt
);
#endif
if
((
STp
->
buffer
)
->
last_result_fatal
!=
0
)
{
if
((
SCpnt
->
sense_buffer
[
0
]
&
0x70
)
==
0x70
&&
(
SCpnt
->
sense_buffer
[
2
]
&
0x0f
)
==
NO_TAPE
)
printk
(
"st%d: No tape.
\n
"
,
dev
);
else
printk
(
"st%d: Error %x.
\n
"
,
dev
,
SCpnt
->
result
);
scsi_tapes
[
dev
].
buffer
->
in_use
=
0
;
scsi_tapes
[
dev
].
in_use
=
0
;
(
STp
->
buffer
)
->
in_use
=
0
;
STp
->
in_use
=
0
;
SCpnt
->
request
.
dev
=
-
1
;
/* Mark as not busy */
return
(
-
EIO
);
}
...
...
@@ -363,23 +436,23 @@ static int scsi_tape_open(struct inode * inode, struct file * filp)
cmd
[
0
]
=
READ_BLOCK_LIMITS
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
(
void
*
)
scsi_tapes
[
dev
].
buffer
->
b_data
,
(
void
*
)
cmd
,
(
void
*
)
(
STp
->
buffer
)
->
b_data
,
ST_BLOCK_SIZE
,
st_sleep_done
,
ST_TIMEOUT
,
MAX_READY_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
if
(
!
SCpnt
->
result
&&
!
SCpnt
->
sense_buffer
[
0
])
{
scsi_tapes
[
dev
].
max_block
=
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
1
]
<<
16
)
|
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
2
]
<<
8
)
|
scsi_tapes
[
dev
].
buffer
->
b_data
[
3
];
scsi_tapes
[
dev
].
min_block
=
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
4
]
<<
8
)
|
scsi_tapes
[
dev
].
buffer
->
b_data
[
5
];
STp
->
max_block
=
((
STp
->
buffer
)
->
b_data
[
1
]
<<
16
)
|
(
(
STp
->
buffer
)
->
b_data
[
2
]
<<
8
)
|
(
STp
->
buffer
)
->
b_data
[
3
];
STp
->
min_block
=
((
STp
->
buffer
)
->
b_data
[
4
]
<<
8
)
|
(
STp
->
buffer
)
->
b_data
[
5
];
#ifdef DEBUG
printk
(
"st%d: Block limits %d - %d bytes.
\n
"
,
dev
,
scsi_tapes
[
dev
].
min_block
,
scsi_tapes
[
dev
].
max_block
);
printk
(
"st%d: Block limits %d - %d bytes.
\n
"
,
dev
,
STp
->
min_block
,
STp
->
max_block
);
#endif
}
else
{
scsi_tapes
[
dev
].
min_block
=
scsi_tapes
[
dev
].
max_block
=
(
-
1
);
STp
->
min_block
=
STp
->
max_block
=
(
-
1
);
#ifdef DEBUG
printk
(
"st%d: Can't read block limits.
\n
"
,
dev
);
#endif
...
...
@@ -391,73 +464,69 @@ static int scsi_tape_open(struct inode * inode, struct file * filp)
cmd
[
4
]
=
12
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
(
void
*
)
scsi_tapes
[
dev
].
buffer
->
b_data
,
(
void
*
)
cmd
,
(
void
*
)
(
STp
->
buffer
)
->
b_data
,
ST_BLOCK_SIZE
,
st_sleep_done
,
ST_TIMEOUT
,
MAX_READY_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
i
=
st_chk_result
(
SCpnt
);
if
(
i
)
{
if
((
STp
->
buffer
)
->
last_result_fatal
!=
0
)
{
#ifdef DEBUG
printk
(
"st%d: No Mode Sense.
\n
"
,
dev
);
#endif
scsi_tapes
[
dev
].
buffer
->
b_data
[
2
]
=
scsi_tapes
[
dev
].
buffer
->
b_data
[
3
]
=
0
;
(
STp
->
buffer
)
->
b_data
[
2
]
=
(
STp
->
buffer
)
->
b_data
[
3
]
=
0
;
}
SCpnt
->
request
.
dev
=
-
1
;
/* Mark as not busy */
#ifdef DEBUG
printk
(
"st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
b_data
[
0
],
scsi_tapes
[
dev
].
buffer
->
b_data
[
1
],
scsi_tapes
[
dev
].
buffer
->
b_data
[
2
],
scsi_tapes
[
dev
].
buffer
->
b_data
[
3
]);
(
STp
->
buffer
)
->
b_data
[
0
],
(
STp
->
buffer
)
->
b_data
[
1
],
(
STp
->
buffer
)
->
b_data
[
2
],
(
STp
->
buffer
)
->
b_data
[
3
]);
#endif
if
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
3
]
>=
8
)
{
scsi_tapes
[
dev
].
drv_buffer
=
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
2
]
>>
4
)
&
7
;
scsi_tapes
[
dev
].
density
=
scsi_tapes
[
dev
].
buffer
->
b_data
[
4
];
scsi_tapes
[
dev
].
block_size
=
scsi_tapes
[
dev
].
buffer
->
b_data
[
9
]
*
65536
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
10
]
*
256
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
11
];
if
(
(
STp
->
buffer
)
->
b_data
[
3
]
>=
8
)
{
STp
->
drv_buffer
=
((
STp
->
buffer
)
->
b_data
[
2
]
>>
4
)
&
7
;
STp
->
density
=
(
STp
->
buffer
)
->
b_data
[
4
];
STp
->
block_size
=
(
STp
->
buffer
)
->
b_data
[
9
]
*
65536
+
(
STp
->
buffer
)
->
b_data
[
10
]
*
256
+
(
STp
->
buffer
)
->
b_data
[
11
];
#ifdef DEBUG
printk
(
"st%d: Density %x, tape length: %x, blocksize: %d, drv buffer: %d
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
b_data
[
4
],
scsi_tapes
[
dev
].
buffer
->
b_data
[
5
]
*
65536
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
6
]
*
256
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
7
],
scsi_tapes
[
dev
].
buffer
->
b_data
[
9
]
*
65536
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
10
]
*
256
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
11
],
scsi_tapes
[
dev
].
drv_buffer
);
printk
(
"st%d: Density %x, tape length: %x, blocksize: %d, drv buffer: %d
\n
"
,
dev
,
STp
->
density
,
(
STp
->
buffer
)
->
b_data
[
5
]
*
65536
+
(
STp
->
buffer
)
->
b_data
[
6
]
*
256
+
(
STp
->
buffer
)
->
b_data
[
7
],
STp
->
block_size
,
STp
->
drv_buffer
);
#endif
if
(
scsi_tapes
[
dev
].
block_size
>
ST_BUFFER_SIZE
)
{
if
(
STp
->
block_size
>
ST_BUFFER_SIZE
)
{
printk
(
"st%d: Blocksize %d too large for buffer.
\n
"
,
dev
,
scsi_tapes
[
dev
].
block_size
);
scsi_tapes
[
dev
].
buffer
->
in_use
=
0
;
scsi_tapes
[
dev
].
in_use
=
0
;
STp
->
block_size
);
(
STp
->
buffer
)
->
in_use
=
0
;
STp
->
in_use
=
0
;
return
(
-
EIO
);
}
}
else
scsi_tapes
[
dev
].
block_size
=
ST_BLOCK_SIZE
;
STp
->
block_size
=
ST_BLOCK_SIZE
;
if
(
scsi_tapes
[
dev
].
block_size
>
0
)
{
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
=
ST_BUFFER_SIZE
/
scsi_tapes
[
dev
].
block_size
;
scsi_tapes
[
dev
].
buffer
->
buffer_size
=
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
*
scsi_tapes
[
dev
].
block_size
;
if
(
STp
->
block_size
>
0
)
{
(
STp
->
buffer
)
->
buffer_blocks
=
ST_BUFFER_SIZE
/
STp
->
block_size
;
(
STp
->
buffer
)
->
buffer_size
=
(
STp
->
buffer
)
->
buffer_blocks
*
STp
->
block_size
;
}
else
{
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
=
1
;
scsi_tapes
[
dev
].
buffer
->
buffer_size
=
ST_BUFFER_SIZE
;
(
STp
->
buffer
)
->
buffer_blocks
=
1
;
(
STp
->
buffer
)
->
buffer_size
=
ST_BUFFER_SIZE
;
}
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
scsi_tapes
[
dev
].
buffer
->
read_pointer
=
0
;
(
STp
->
buffer
)
->
buffer_bytes
=
(
STp
->
buffer
)
->
read_pointer
=
0
;
#ifdef DEBUG
printk
(
"st%d: Block size: %d, buffer size: %d (%d blocks).
\n
"
,
dev
,
scsi_tapes
[
dev
].
block_size
,
scsi_tapes
[
dev
].
buffer
->
buffer_size
,
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
);
STp
->
block_size
,
(
STp
->
buffer
)
->
buffer_size
,
(
STp
->
buffer
)
->
buffer_blocks
);
#endif
if
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
2
]
&
0x80
)
{
scsi_tapes
[
dev
].
write_prot
=
1
;
if
(
(
STp
->
buffer
)
->
b_data
[
2
]
&
0x80
)
{
STp
->
write_prot
=
1
;
#ifdef DEBUG
printk
(
"st%d: Write protected
\n
"
,
dev
);
#endif
...
...
@@ -468,19 +537,22 @@ static int scsi_tape_open(struct inode * inode, struct file * filp)
/* Close the device*/
static
void
scsi_tape_close
(
struct
inode
*
inode
,
struct
file
*
filp
)
static
void
scsi_tape_close
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
int
dev
;
int
result
;
int
rewind
;
static
unsigned
char
cmd
[
10
];
Scsi_Cmnd
*
SCpnt
;
Scsi_Tape
*
STp
;
dev
=
MINOR
(
inode
->
i_rdev
);
rewind
=
(
dev
&
0x80
)
==
0
;
dev
=
dev
&
127
;
STp
=
&
(
scsi_tapes
[
dev
]);
if
(
scsi_tapes
[
dev
].
rw
==
2
)
{
if
(
STp
->
rw
==
ST_WRITING
)
{
result
=
flush_write_buffer
(
dev
);
...
...
@@ -488,8 +560,8 @@ static void scsi_tape_close(struct inode * inode, struct file * filp)
printk
(
"st%d: File length %d bytes.
\n
"
,
dev
,
filp
->
f_pos
);
#endif
if
(
!
result
)
{
SCpnt
=
allocate_device
(
NULL
,
scsi_tapes
[
dev
].
device
->
index
,
1
);
if
(
result
==
0
||
result
==
(
-
ENOSPC
)
)
{
SCpnt
=
allocate_device
(
NULL
,
(
STp
->
device
)
->
index
,
1
);
SCpnt
->
sense_buffer
[
0
]
=
0
;
memset
(
cmd
,
0
,
10
);
...
...
@@ -497,17 +569,14 @@ static void scsi_tape_close(struct inode * inode, struct file * filp)
cmd
[
4
]
=
1
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
(
void
*
)
scsi_tapes
[
dev
].
buffer
->
b_data
,
(
void
*
)
cmd
,
(
void
*
)
(
STp
->
buffer
)
->
b_data
,
ST_BLOCK_SIZE
,
st_sleep_done
,
ST_TIMEOUT
,
MAX_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
if
(
SCpnt
->
result
)
{
if
(
(
STp
->
buffer
)
->
last_result_fatal
!=
0
)
printk
(
"st%d: Error on write filemark.
\n
"
,
dev
);
#ifdef DEBUG
st_chk_result
(
SCpnt
);
#endif
}
SCpnt
->
request
.
dev
=
-
1
;
/* Mark as not busy */
}
...
...
@@ -516,9 +585,10 @@ static void scsi_tape_close(struct inode * inode, struct file * filp)
#endif
}
else
if
(
!
rewind
)
{
if
((
scsi_tapes
[
dev
].
eof
==
1
)
&&
!
scsi_tapes
[
dev
].
eof_hit
)
#ifndef ST_IN_FILE_POS
if
((
STp
->
eof
==
ST_FM
)
&&
!
STp
->
eof_hit
)
st_int_ioctl
(
inode
,
filp
,
MTBSF
,
1
);
/* Back over the EOF hit */
#
ifdef ST_IN_FILE_POS
#
else
flush_buffer
(
inode
,
filp
,
0
);
#endif
}
...
...
@@ -526,117 +596,169 @@ static void scsi_tape_close(struct inode * inode, struct file * filp)
if
(
rewind
)
st_int_ioctl
(
inode
,
filp
,
MTREW
,
1
);
scsi_tapes
[
dev
].
buffer
->
in_use
=
0
;
scsi_tapes
[
dev
].
in_use
=
0
;
(
STp
->
buffer
)
->
in_use
=
0
;
STp
->
in_use
=
0
;
return
;
}
/* Write command */
int
st_write
(
struct
inode
*
inode
,
struct
file
*
filp
,
char
*
buf
,
int
count
)
static
int
st_write
(
struct
inode
*
inode
,
struct
file
*
filp
,
char
*
buf
,
int
count
)
{
int
dev
;
int
total
,
do_count
,
blks
,
retval
;
int
total
,
do_count
,
blks
,
retval
,
transfer
;
int
write_threshold
;
static
unsigned
char
cmd
[
10
];
char
*
b_point
;
Scsi_Cmnd
*
SCpnt
;
Scsi_Tape
*
STp
;
dev
=
MINOR
(
inode
->
i_rdev
)
&
127
;
STp
=
&
(
scsi_tapes
[
dev
]);
#ifdef DEBUG
if
(
!
scsi_tapes
[
dev
].
in_use
)
{
if
(
!
STp
->
in_use
)
{
printk
(
"st%d: Incorrect device.
\n
"
,
dev
);
return
(
-
EIO
);
}
#endif
if
(
scsi_tapes
[
dev
].
write_prot
)
if
(
STp
->
write_prot
)
return
(
-
EACCES
);
if
(
scsi_tapes
[
dev
].
block_size
==
0
&&
count
>
ST_BUFFER_SIZE
)
if
(
STp
->
block_size
==
0
&&
count
>
ST_BUFFER_SIZE
)
return
(
-
EOVERFLOW
);
if
(
scsi_tapes
[
dev
].
rw
==
1
)
{
if
(
STp
->
rw
==
ST_READING
)
{
retval
=
flush_buffer
(
inode
,
filp
,
0
);
if
(
retval
)
return
retval
;
scsi_tapes
[
dev
].
rw
=
2
;
STp
->
rw
=
ST_WRITING
;
}
#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
if
(
scsi_tapes
[
dev
].
buffer
->
writing
)
{
if
(
(
STp
->
buffer
)
->
writing
)
{
write_behind_check
(
dev
);
if
(
scsi_tapes
[
dev
].
buffer
->
last_result
)
{
if
(
(
STp
->
buffer
)
->
last_result_fatal
)
{
#ifdef DEBUG
printk
(
"st%d: Async write error %x.
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
last_result
);
(
STp
->
buffer
)
->
last_result
);
#endif
/*if (scsi_tapes[dev].buffer->last_result = INT_MAX)
retval = (-ENOSPC);
else */
if
((
STp
->
buffer
)
->
last_result
==
INT_MAX
)
{
retval
=
(
-
ENOSPC
);
/* All has been written */
STp
->
eof
=
ST_EOM_OK
;
}
else
retval
=
(
-
EIO
);
return
retval
;
}
}
#endif
SCpnt
=
allocate_device
(
NULL
,
scsi_tapes
[
dev
].
device
->
index
,
1
);
if
(
STp
->
eof
==
ST_EOM_OK
)
return
(
-
ENOSPC
);
else
if
(
STp
->
eof
==
ST_EOM_ERROR
)
return
(
-
EIO
);
#ifdef ST_NO_DELAYED_WRITES
if
(
STp
->
block_size
!=
0
&&
(
count
%
STp
->
block_size
)
!=
0
)
return
(
-
EIO
);
/* Write must be integral number of blocks */
write_threshold
=
1
;
#else
write_threshold
=
(
STp
->
buffer
)
->
buffer_size
;
#endif
SCpnt
=
allocate_device
(
NULL
,
(
STp
->
device
)
->
index
,
1
);
total
=
count
;
memset
(
cmd
,
0
,
10
);
cmd
[
0
]
=
WRITE_6
;
cmd
[
1
]
=
(
scsi_tapes
[
dev
].
block_size
!=
0
);
cmd
[
1
]
=
(
STp
->
block_size
!=
0
);
scsi_tapes
[
dev
].
rw
=
2
;
STp
->
rw
=
ST_WRITING
;
b_point
=
buf
;
while
(
#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
scsi_tapes
[
dev
].
block_size
!=
0
&&
(
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
+
count
)
>
scsi_tapes
[
dev
].
buffer
->
buffer_size
)
STp
->
block_size
!=
0
&&
(
(
STp
->
buffer
)
->
buffer_bytes
+
count
)
>
write_threshold
)
#else
(
scsi_tapes
[
dev
].
block_size
==
0
&&
count
>
0
)
||
(
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
+
count
)
>=
scsi_tapes
[
dev
].
buffer
->
buffer_size
)
(
STp
->
block_size
==
0
&&
count
>
0
)
||
(
(
STp
->
buffer
)
->
buffer_bytes
+
count
)
>=
write_threshold
)
#endif
{
if
(
scsi_tapes
[
dev
].
block_size
==
0
)
if
(
STp
->
block_size
==
0
)
do_count
=
count
;
else
do_count
=
scsi_tapes
[
dev
].
buffer
->
buffer_size
-
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
;
memcpy_fromfs
(
scsi_tapes
[
dev
].
buffer
->
b_data
+
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
,
b_point
,
do_count
);
else
{
do_count
=
(
STp
->
buffer
)
->
buffer_size
-
(
STp
->
buffer
)
->
buffer_bytes
;
if
(
do_count
>
count
)
do_count
=
count
;
}
memcpy_fromfs
((
STp
->
buffer
)
->
b_data
+
(
STp
->
buffer
)
->
buffer_bytes
,
b_point
,
do_count
);
if
(
scsi_tapes
[
dev
].
block_size
==
0
)
if
(
STp
->
block_size
==
0
)
blks
=
do_count
;
else
blks
=
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
;
blks
=
((
STp
->
buffer
)
->
buffer_bytes
+
do_count
)
/
STp
->
block_size
;
cmd
[
2
]
=
blks
>>
16
;
cmd
[
3
]
=
blks
>>
8
;
cmd
[
4
]
=
blks
;
SCpnt
->
sense_buffer
[
0
]
=
0
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
scsi_tapes
[
dev
].
buffer
->
b_data
,
scsi_tapes
[
dev
].
buffer
->
buffer_size
,
(
void
*
)
cmd
,
(
STp
->
buffer
)
->
b_data
,
(
STp
->
buffer
)
->
buffer_size
,
st_sleep_done
,
ST_TIMEOUT
,
MAX_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
if
(
SCpnt
->
result
||
SCpnt
->
sense_buffer
[
0
]
!=
0
)
{
if
(
(
STp
->
buffer
)
->
last_result_fatal
!=
0
)
{
#ifdef DEBUG
printk
(
"st%d: Error on write:
\n
"
,
dev
);
st_chk_result
(
SCpnt
);
#endif
if
((
SCpnt
->
sense_buffer
[
0
]
&
0x70
)
==
0x70
&&
(
SCpnt
->
sense_buffer
[
2
]
&
0x40
))
retval
=
(
-
ENOSPC
);
/* EOM */
(
SCpnt
->
sense_buffer
[
2
]
&
0x40
))
{
if
(
STp
->
block_size
!=
0
&&
(
SCpnt
->
sense_buffer
[
0
]
&
0x80
)
!=
0
)
transfer
=
(
SCpnt
->
sense_buffer
[
3
]
<<
24
)
|
(
SCpnt
->
sense_buffer
[
4
]
<<
16
)
|
(
SCpnt
->
sense_buffer
[
5
]
<<
8
)
|
SCpnt
->
sense_buffer
[
6
];
else
if
(
STp
->
block_size
==
0
&&
(
SCpnt
->
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
;
STp
->
eof
=
ST_EOM_OK
;
retval
=
(
-
ENOSPC
);
/* EOM within current request */
#ifdef DEBUG
printk
(
"st%d: EOM with %d bytes unwritten.
\n
"
,
dev
,
transfer
);
#endif
}
else
{
STp
->
eof
=
ST_EOM_ERROR
;
retval
=
(
-
EIO
);
/* EOM for old data */
#ifdef DEBUG
printk
(
"st%d: EOM with lost data.
\n
"
,
dev
);
#endif
}
}
else
retval
=
(
-
EIO
);
SCpnt
->
request
.
dev
=
-
1
;
/* Mark as not busy */
(
STp
->
buffer
)
->
buffer_bytes
=
0
;
STp
->
dirty
=
0
;
if
(
count
<
total
)
return
total
-
count
;
else
...
...
@@ -645,48 +767,47 @@ int st_write(struct inode * inode, struct file * filp, char * buf, int count)
filp
->
f_pos
+=
do_count
;
b_point
+=
do_count
;
count
-=
do_count
;
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
0
;
scsi_tapes
[
dev
].
dirty
=
0
;
(
STp
->
buffer
)
->
buffer_bytes
=
0
;
STp
->
dirty
=
0
;
}
if
(
count
!=
0
)
{
scsi_tapes
[
dev
].
dirty
=
1
;
memcpy_fromfs
(
scsi_tapes
[
dev
].
buffer
->
b_data
+
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
,
b_point
,
count
);
STp
->
dirty
=
1
;
memcpy_fromfs
(
(
STp
->
buffer
)
->
b_data
+
(
STp
->
buffer
)
->
buffer_bytes
,
b_point
,
count
);
filp
->
f_pos
+=
count
;
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
+=
count
;
(
STp
->
buffer
)
->
buffer_bytes
+=
count
;
count
=
0
;
}
do_count
=
st_chk_result
(
SCpnt
);
if
(
do_count
)
{
if
((
STp
->
buffer
)
->
last_result_fatal
!=
0
)
{
SCpnt
->
request
.
dev
=
-
1
;
return
do_count
;
return
(
STp
->
buffer
)
->
last_result_fatal
;
}
#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
if
(
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
>=
ST_WRITE_THRESHOLD
||
scsi_tapes
[
dev
].
block_size
==
0
)
{
if
(
(
STp
->
buffer
)
->
buffer_bytes
>=
ST_WRITE_THRESHOLD
||
STp
->
block_size
==
0
)
{
/* Schedule an asynchronous write */
if
(
scsi_tapes
[
dev
].
block_size
==
0
)
scsi_tapes
[
dev
].
buffer
->
writing
=
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
;
if
(
STp
->
block_size
==
0
)
(
STp
->
buffer
)
->
writing
=
(
STp
->
buffer
)
->
buffer_bytes
;
else
scsi_tapes
[
dev
].
buffer
->
writing
=
(
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
/
scsi_tapes
[
dev
].
block_size
)
*
scsi_tapes
[
dev
].
block_size
;
scsi_tapes
[
dev
].
dirty
=
0
;
(
STp
->
buffer
)
->
writing
=
((
STp
->
buffer
)
->
buffer_bytes
/
STp
->
block_size
)
*
STp
->
block_size
;
STp
->
dirty
=
0
;
if
(
scsi_tapes
[
dev
].
block_size
==
0
)
blks
=
scsi_tapes
[
dev
].
buffer
->
writing
;
if
(
STp
->
block_size
==
0
)
blks
=
(
STp
->
buffer
)
->
writing
;
else
blks
=
scsi_tapes
[
dev
].
buffer
->
writing
/
scsi_tapes
[
dev
].
block_size
;
blks
=
(
STp
->
buffer
)
->
writing
/
STp
->
block_size
;
cmd
[
2
]
=
blks
>>
16
;
cmd
[
3
]
=
blks
>>
8
;
cmd
[
4
]
=
blks
;
SCpnt
->
result
=
scsi_tapes
[
dev
].
buffer
->
last_result
=
-
1
;
SCpnt
->
result
=
(
STp
->
buffer
)
->
last_result
=
-
1
;
SCpnt
->
sense_buffer
[
0
]
=
0
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
scsi_tapes
[
dev
].
buffer
->
b_data
,
scsi_tapes
[
dev
].
buffer
->
writing
,
(
void
*
)
cmd
,
(
STp
->
buffer
)
->
b_data
,
(
STp
->
buffer
)
->
writing
,
st_sleep_done
,
ST_TIMEOUT
,
MAX_RETRIES
);
}
else
...
...
@@ -698,58 +819,61 @@ int st_write(struct inode * inode, struct file * filp, char * buf, int count)
/* Read command */
int
st_read
(
struct
inode
*
inode
,
struct
file
*
filp
,
char
*
buf
,
int
count
)
static
int
st_read
(
struct
inode
*
inode
,
struct
file
*
filp
,
char
*
buf
,
int
count
)
{
int
dev
;
int
total
;
int
transfer
,
blks
,
bytes
;
static
unsigned
char
cmd
[
10
];
Scsi_Cmnd
*
SCpnt
;
Scsi_Tape
*
STp
;
dev
=
MINOR
(
inode
->
i_rdev
)
&
127
;
STp
=
&
(
scsi_tapes
[
dev
]);
#ifdef DEBUG
if
(
!
scsi_tapes
[
dev
].
in_use
)
{
if
(
!
STp
->
in_use
)
{
printk
(
"st%d: Incorrect device.
\n
"
,
dev
);
return
(
-
EIO
);
}
#endif
if
(
scsi_tapes
[
dev
].
block_size
==
0
&&
count
>
ST_BUFFER_SIZE
)
if
(
STp
->
block_size
==
0
&&
count
>
ST_BUFFER_SIZE
)
return
(
-
EOVERFLOW
);
if
(
scsi_tapes
[
dev
].
rw
==
2
)
{
if
(
STp
->
rw
==
ST_WRITING
)
{
transfer
=
flush_buffer
(
inode
,
filp
,
0
);
if
(
transfer
)
return
transfer
;
scsi_tapes
[
dev
].
rw
=
1
;
STp
->
rw
=
ST_READING
;
}
#ifdef DEBUG
if
(
scsi_tapes
[
dev
].
eof
)
if
(
STp
->
eof
!=
ST_NOEOF
)
printk
(
"st%d: EOF flag up. Bytes %d
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
);
(
STp
->
buffer
)
->
buffer_bytes
);
#endif
if
((
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
==
0
)
&&
scsi_tapes
[
dev
].
eof
==
2
)
/* EOM or Blank Check */
if
((
(
STp
->
buffer
)
->
buffer_bytes
==
0
)
&&
STp
->
eof
==
ST_EOM_OK
)
/* EOM or Blank Check */
return
(
-
EIO
);
scsi_tapes
[
dev
].
rw
=
1
;
STp
->
rw
=
ST_READING
;
SCpnt
=
allocate_device
(
NULL
,
scsi_tapes
[
dev
].
device
->
index
,
1
);
SCpnt
=
allocate_device
(
NULL
,
(
STp
->
device
)
->
index
,
1
);
for
(
total
=
0
;
total
<
count
;
)
{
if
(
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
==
0
&&
scsi_tapes
[
dev
].
eof
==
0
)
{
if
(
(
STp
->
buffer
)
->
buffer_bytes
==
0
&&
STp
->
eof
==
ST_NOEOF
)
{
memset
(
cmd
,
0
,
10
);
cmd
[
0
]
=
READ_6
;
cmd
[
1
]
=
(
scsi_tapes
[
dev
].
block_size
!=
0
);
if
(
scsi_tapes
[
dev
].
block_size
==
0
)
cmd
[
1
]
=
(
STp
->
block_size
!=
0
);
if
(
STp
->
block_size
==
0
)
blks
=
bytes
=
count
;
else
{
blks
=
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
;
bytes
=
blks
*
scsi_tapes
[
dev
].
block_size
;
blks
=
(
STp
->
buffer
)
->
buffer_blocks
;
bytes
=
blks
*
STp
->
block_size
;
}
cmd
[
2
]
=
blks
>>
16
;
cmd
[
3
]
=
blks
>>
8
;
...
...
@@ -758,16 +882,16 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
SCpnt
->
sense_buffer
[
0
]
=
0
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
scsi_tapes
[
dev
].
buffer
->
b_data
,
scsi_tapes
[
dev
].
buffer
->
buffer_size
,
(
void
*
)
cmd
,
(
STp
->
buffer
)
->
b_data
,
(
STp
->
buffer
)
->
buffer_size
,
st_sleep_done
,
ST_TIMEOUT
,
MAX_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
scsi_tapes
[
dev
].
buffer
->
read_pointer
=
0
;
scsi_tapes
[
dev
].
eof_hit
=
0
;
(
STp
->
buffer
)
->
read_pointer
=
0
;
STp
->
eof_hit
=
0
;
if
(
SCpnt
->
result
!=
0
||
SCpnt
->
sense_buffer
[
0
]
!=
0
)
{
if
(
(
STp
->
buffer
)
->
last_result_fatal
)
{
#ifdef DEBUG
printk
(
"st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x
\n
"
,
dev
,
SCpnt
->
sense_buffer
[
0
],
SCpnt
->
sense_buffer
[
1
],
...
...
@@ -778,15 +902,22 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
if
((
SCpnt
->
sense_buffer
[
0
]
&
0x70
)
==
0x70
)
{
/* extended sense */
if
((
SCpnt
->
sense_buffer
[
2
]
&
0xe0
)
!=
0
)
{
/* EOF, EOM, or ILI */
if
((
SCpnt
->
sense_buffer
[
0
]
&
0x80
)
!=
0
)
transfer
=
(
SCpnt
->
sense_buffer
[
3
]
<<
24
)
|
(
SCpnt
->
sense_buffer
[
4
]
<<
16
)
|
(
SCpnt
->
sense_buffer
[
5
]
<<
8
)
|
SCpnt
->
sense_buffer
[
6
];
else
transfer
=
0
;
if
(
STp
->
block_size
==
0
&&
(
SCpnt
->
sense_buffer
[
2
]
&
0x0f
)
==
MEDIUM_ERROR
)
transfer
=
bytes
;
if
(
SCpnt
->
sense_buffer
[
2
]
&
0x20
)
{
if
(
scsi_tapes
[
dev
].
block_size
==
0
)
{
if
(
STp
->
block_size
==
0
)
{
if
(
transfer
<=
0
)
transfer
=
0
;
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
count
-
transfer
;
(
STp
->
buffer
)
->
buffer_bytes
=
count
-
transfer
;
}
else
{
printk
(
"st%d: Incorrect block size.
\n
"
,
dev
);
...
...
@@ -795,35 +926,36 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
}
}
else
if
(
SCpnt
->
sense_buffer
[
2
]
&
0x40
)
{
scsi_tapes
[
dev
].
eof
=
2
;
/* What should be done at EOM ? */
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
(
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
-
transfer
)
*
scsi_tapes
[
dev
].
block_size
;
STp
->
eof
=
ST_EOM_OK
;
if
(
STp
->
block_size
==
0
)
(
STp
->
buffer
)
->
buffer_bytes
=
count
-
transfer
;
else
(
STp
->
buffer
)
->
buffer_bytes
=
((
STp
->
buffer
)
->
buffer_blocks
-
transfer
)
*
STp
->
block_size
;
#ifdef DEBUG
printk
(
"st%d: EOM detected (%d b
lock
s read).
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
-
transfer
);
printk
(
"st%d: EOM detected (%d b
yte
s read).
\n
"
,
dev
,
(
STp
->
buffer
)
->
buffer_bytes
);
#endif
}
else
if
(
SCpnt
->
sense_buffer
[
2
]
&
0x80
)
{
scsi_tapes
[
dev
].
eof
=
1
;
if
(
scsi_tapes
[
dev
].
block_size
==
0
)
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
count
-
transfer
;
STp
->
eof
=
ST_FM
;
if
(
STp
->
block_size
==
0
)
(
STp
->
buffer
)
->
buffer_bytes
=
0
;
else
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
(
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
-
transfer
)
*
scsi_tapes
[
dev
].
block_size
;
(
STp
->
buffer
)
->
buffer_bytes
=
(
(
STp
->
buffer
)
->
buffer_blocks
-
transfer
)
*
STp
->
block_size
;
#ifdef DEBUG
printk
(
"st%d: EOF detected (%d blocks read, transferred %d bytes).
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
-
transfer
,
total
);
printk
(
"st%d: EOF detected (%d bytes read, transferred %d bytes).
\n
"
,
dev
,
(
STp
->
buffer
)
->
buffer_bytes
,
total
);
#endif
}
/* end of EOF, EOM, ILI test */
}
else
{
/* nonzero sense key */
#ifdef DEBUG
printk
(
"st%d: Tape error. Sense key %x
\n
"
,
dev
,
SCpnt
->
sense_buffer
[
2
]
&
0x0f
);
print_sense
(
"st"
,
SCpnt
);
printk
(
"st%d: Tape error while reading.
\n
"
,
dev
);
#endif
SCpnt
->
request
.
dev
=
-
1
;
if
(
total
)
...
...
@@ -833,44 +965,44 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
}
}
else
{
transfer
=
st_chk_result
(
SCpnt
)
;
transfer
=
(
STp
->
buffer
)
->
last_result_fatal
;
SCpnt
->
request
.
dev
=
-
1
;
/* Mark as not busy */
return
transfer
;
}
}
else
/* Read successfu
|
*/
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
bytes
;
else
/* Read successfu
l
*/
(
STp
->
buffer
)
->
buffer_bytes
=
bytes
;
}
/* if (
scsi_tapes[dev].buffer
->buffer_bytes == 0 &&
scsi_tapes[dev].eof == 0
) */
}
/* if (
(STp->buffer)
->buffer_bytes == 0 &&
STp->eof == ST_NOEOF
) */
if
(
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
>
0
)
{
if
(
(
STp
->
buffer
)
->
buffer_bytes
>
0
)
{
#ifdef DEBUG
if
(
scsi_tapes
[
dev
].
eof
)
if
(
STp
->
eof
!=
ST_NOEOF
)
printk
(
"st%d: EOF up. Left %d, needed %d.
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
,
count
-
total
);
(
STp
->
buffer
)
->
buffer_bytes
,
count
-
total
);
#endif
transfer
=
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
<
count
-
total
?
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
:
count
-
total
;
memcpy_tofs
(
buf
,
scsi_tapes
[
dev
].
buffer
->
b_data
+
scsi_tapes
[
dev
].
buffer
->
read_pointer
,
transfer
);
transfer
=
(
STp
->
buffer
)
->
buffer_bytes
<
count
-
total
?
(
STp
->
buffer
)
->
buffer_bytes
:
count
-
total
;
memcpy_tofs
(
buf
,
(
STp
->
buffer
)
->
b_data
+
(
STp
->
buffer
)
->
read_pointer
,
transfer
);
filp
->
f_pos
+=
transfer
;
buf
+=
transfer
;
total
+=
transfer
;
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
-=
transfer
;
scsi_tapes
[
dev
].
buffer
->
read_pointer
+=
transfer
;
(
STp
->
buffer
)
->
buffer_bytes
-=
transfer
;
(
STp
->
buffer
)
->
read_pointer
+=
transfer
;
}
else
if
(
scsi_tapes
[
dev
].
eof
)
{
scsi_tapes
[
dev
].
eof_hit
=
1
;
else
if
(
STp
->
eof
!=
ST_NOEOF
)
{
STp
->
eof_hit
=
1
;
SCpnt
->
request
.
dev
=
-
1
;
/* Mark as not busy */
if
(
total
==
0
&&
scsi_tapes
[
dev
].
eof
==
1
)
scsi_tapes
[
dev
].
eof
=
0
;
if
(
total
==
0
&&
scsi_tapes
[
dev
].
eof
==
2
)
return
(
-
EIO
);
if
(
total
==
0
&&
STp
->
eof
==
ST_FM
)
STp
->
eof
=
0
;
if
(
total
==
0
&&
STp
->
eof
==
ST_EOM_OK
)
return
(
-
EIO
);
/* ST_EOM_ERROR not used in read */
return
total
;
}
if
(
scsi_tapes
[
dev
].
block_size
==
0
)
if
(
STp
->
block_size
==
0
)
count
=
total
;
/* Read only one variable length block */
}
/* for (total = 0; total < count; ) */
...
...
@@ -882,7 +1014,8 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
/* Internal ioctl function */
static
int
st_int_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
static
int
st_int_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd_in
,
unsigned
long
arg
)
{
int
dev
=
MINOR
(
inode
->
i_rdev
);
...
...
@@ -891,8 +1024,10 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
int
ioctl_result
;
unsigned
char
cmd
[
10
];
Scsi_Cmnd
*
SCpnt
;
Scsi_Tape
*
STp
;
dev
=
dev
&
127
;
STp
=
&
(
scsi_tapes
[
dev
]);
memset
(
cmd
,
0
,
10
);
switch
(
cmd_in
)
{
...
...
@@ -904,7 +1039,7 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
cmd
[
3
]
=
(
arg
>>
8
);
cmd
[
4
]
=
arg
;
#ifdef DEBUG
printk
(
"st%d: Spacing tape forward
%d file
s.
\n
"
,
dev
,
printk
(
"st%d: Spacing tape forward
over %d filemark
s.
\n
"
,
dev
,
cmd
[
2
]
*
65536
+
cmd
[
3
]
*
256
+
cmd
[
4
]);
#endif
break
;
...
...
@@ -920,7 +1055,7 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
if
(
cmd
[
2
]
&
0x80
)
ltmp
=
0xff000000
;
ltmp
=
ltmp
|
(
cmd
[
2
]
<<
16
)
|
(
cmd
[
3
]
<<
8
)
|
cmd
[
4
];
printk
(
"st%d: Spacing tape backward
%d file
s.
\n
"
,
dev
,
(
-
ltmp
));
printk
(
"st%d: Spacing tape backward
over %d filemark
s.
\n
"
,
dev
,
(
-
ltmp
));
#endif
break
;
case
MTFSR
:
...
...
@@ -949,7 +1084,7 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
#endif
break
;
case
MTWEOF
:
if
(
scsi_tapes
[
dev
].
write_prot
)
if
(
STp
->
write_prot
)
return
(
-
EACCES
);
cmd
[
0
]
=
WRITE_FILEMARKS
;
cmd
[
2
]
=
(
arg
>>
16
);
...
...
@@ -1006,7 +1141,7 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
#endif
break
;
case
MTERASE
:
if
(
scsi_tapes
[
dev
].
write_prot
)
if
(
STp
->
write_prot
)
return
(
-
EACCES
);
cmd
[
0
]
=
ERASE
;
cmd
[
1
]
=
1
;
/* To the end of tape */
...
...
@@ -1015,7 +1150,7 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
#endif
break
;
case
MTSEEK
:
if
(
scsi_tapes
[
dev
].
device
->
scsi_level
<
SCSI_2
)
{
if
(
(
STp
->
device
)
->
scsi_level
<
SCSI_2
)
{
cmd
[
0
]
=
QFA_SEEK_BLOCK
;
cmd
[
2
]
=
(
arg
>>
16
);
cmd
[
3
]
=
(
arg
>>
8
);
...
...
@@ -1041,11 +1176,11 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
case
MTSETBLK
:
/* Set block length */
case
MTSETDENSITY
:
/* Set tape density */
case
MTSETDRVBUFFER
:
/* Set drive buffering */
if
(
scsi_tapes
[
dev
].
dirty
||
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
!=
0
)
if
(
STp
->
dirty
||
(
STp
->
buffer
)
->
buffer_bytes
!=
0
)
return
(
-
EIO
);
/* Not allowed if data in buffer */
if
(
cmd_in
==
MTSETBLK
&&
arg
!=
0
&&
(
arg
<
scsi_tapes
[
dev
].
min_block
||
arg
>
scsi_tapes
[
dev
].
max_block
||
(
arg
<
STp
->
min_block
||
arg
>
STp
->
max_block
||
arg
>
ST_BUFFER_SIZE
))
{
printk
(
"st%d: Illegal block size.
\n
"
,
dev
);
return
(
-
EINVAL
);
...
...
@@ -1053,37 +1188,37 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
cmd
[
0
]
=
MODE_SELECT
;
cmd
[
4
]
=
12
;
memset
(
scsi_tapes
[
dev
].
buffer
->
b_data
,
0
,
12
);
memset
(
(
STp
->
buffer
)
->
b_data
,
0
,
12
);
if
(
cmd_in
==
MTSETDRVBUFFER
)
scsi_tapes
[
dev
].
buffer
->
b_data
[
2
]
=
(
arg
&
7
)
<<
4
;
(
STp
->
buffer
)
->
b_data
[
2
]
=
(
arg
&
7
)
<<
4
;
else
scsi_tapes
[
dev
].
buffer
->
b_data
[
2
]
=
scsi_tapes
[
dev
].
drv_buffer
<<
4
;
scsi_tapes
[
dev
].
buffer
->
b_data
[
3
]
=
8
;
/* block descriptor length */
(
STp
->
buffer
)
->
b_data
[
2
]
=
STp
->
drv_buffer
<<
4
;
(
STp
->
buffer
)
->
b_data
[
3
]
=
8
;
/* block descriptor length */
if
(
cmd_in
==
MTSETDENSITY
)
scsi_tapes
[
dev
].
buffer
->
b_data
[
4
]
=
arg
;
(
STp
->
buffer
)
->
b_data
[
4
]
=
arg
;
else
scsi_tapes
[
dev
].
buffer
->
b_data
[
4
]
=
scsi_tapes
[
dev
].
density
;
(
STp
->
buffer
)
->
b_data
[
4
]
=
STp
->
density
;
if
(
cmd_in
==
MTSETBLK
)
ltmp
=
arg
;
else
ltmp
=
scsi_tapes
[
dev
].
block_size
;
scsi_tapes
[
dev
].
buffer
->
b_data
[
9
]
=
(
ltmp
>>
16
);
scsi_tapes
[
dev
].
buffer
->
b_data
[
10
]
=
(
ltmp
>>
8
);
scsi_tapes
[
dev
].
buffer
->
b_data
[
11
]
=
ltmp
;
ltmp
=
STp
->
block_size
;
(
STp
->
buffer
)
->
b_data
[
9
]
=
(
ltmp
>>
16
);
(
STp
->
buffer
)
->
b_data
[
10
]
=
(
ltmp
>>
8
);
(
STp
->
buffer
)
->
b_data
[
11
]
=
ltmp
;
timeout
=
ST_TIMEOUT
;
#ifdef DEBUG
if
(
cmd_in
==
MTSETBLK
)
printk
(
"st%d: Setting block size to %d bytes.
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
b_data
[
9
]
*
65536
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
10
]
*
256
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
11
]);
(
STp
->
buffer
)
->
b_data
[
9
]
*
65536
+
(
STp
->
buffer
)
->
b_data
[
10
]
*
256
+
(
STp
->
buffer
)
->
b_data
[
11
]);
else
if
(
cmd_in
==
MTSETDENSITY
)
printk
(
"st%d: Setting density code to %x.
\n
"
,
dev
,
scsi_tapes
[
dev
].
buffer
->
b_data
[
4
]);
(
STp
->
buffer
)
->
b_data
[
4
]);
else
printk
(
"st%d: Setting drive buffer code to %d.
\n
"
,
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
2
]
>>
4
)
&
7
);
printk
(
"st%d: Setting drive buffer code to %d.
\n
"
,
dev
,
(
(
STp
->
buffer
)
->
b_data
[
2
]
>>
4
)
&
7
);
#endif
break
;
default:
...
...
@@ -1091,16 +1226,16 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
return
(
-
ENOSYS
);
}
SCpnt
=
allocate_device
(
NULL
,
scsi_tapes
[
dev
].
device
->
index
,
1
);
SCpnt
=
allocate_device
(
NULL
,
(
STp
->
device
)
->
index
,
1
);
SCpnt
->
sense_buffer
[
0
]
=
0
;
SCpnt
->
request
.
dev
=
dev
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
(
void
*
)
scsi_tapes
[
dev
].
buffer
->
b_data
,
ST_BLOCK_SIZE
,
(
void
*
)
cmd
,
(
void
*
)
(
STp
->
buffer
)
->
b_data
,
ST_BLOCK_SIZE
,
st_sleep_done
,
timeout
,
MAX_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
ioctl_result
=
st_chk_result
(
SCpnt
)
;
ioctl_result
=
(
STp
->
buffer
)
->
last_result_fatal
;
SCpnt
->
request
.
dev
=
-
1
;
/* Mark as not busy */
...
...
@@ -1110,31 +1245,31 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
else
if
(
cmd_in
==
MTFSFM
)
ioctl_result
=
st_int_ioctl
(
inode
,
file
,
MTBSF
,
1
);
else
if
(
cmd_in
==
MTSETBLK
)
{
scsi_tapes
[
dev
].
block_size
=
arg
;
STp
->
block_size
=
arg
;
if
(
arg
!=
0
)
{
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
=
ST_BUFFER_SIZE
/
scsi_tapes
[
dev
].
block_size
;
scsi_tapes
[
dev
].
buffer
->
buffer_size
=
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
*
scsi_tapes
[
dev
].
block_size
;
(
STp
->
buffer
)
->
buffer_blocks
=
ST_BUFFER_SIZE
/
STp
->
block_size
;
(
STp
->
buffer
)
->
buffer_size
=
(
STp
->
buffer
)
->
buffer_blocks
*
STp
->
block_size
;
}
else
{
scsi_tapes
[
dev
].
buffer
->
buffer_blocks
=
1
;
scsi_tapes
[
dev
].
buffer
->
buffer_size
=
ST_BUFFER_SIZE
;
(
STp
->
buffer
)
->
buffer_blocks
=
1
;
(
STp
->
buffer
)
->
buffer_size
=
ST_BUFFER_SIZE
;
}
scsi_tapes
[
dev
].
buffer
->
buffer_bytes
=
scsi_tapes
[
dev
].
buffer
->
read_pointer
=
0
;
(
STp
->
buffer
)
->
buffer_bytes
=
(
STp
->
buffer
)
->
read_pointer
=
0
;
}
else
if
(
cmd_in
==
MTSETDRVBUFFER
)
scsi_tapes
[
dev
].
drv_buffer
=
arg
;
STp
->
drv_buffer
=
arg
;
else
if
(
cmd_in
==
MTSETDENSITY
)
scsi_tapes
[
dev
].
density
=
arg
;
STp
->
density
=
arg
;
if
(
cmd_in
==
MTEOM
||
cmd_in
==
MTWEOF
)
{
scsi_tapes
[
dev
].
eof
=
2
;
scsi_tapes
[
dev
].
eof_hit
=
0
;
STp
->
eof
=
ST_EOM_OK
;
STp
->
eof_hit
=
0
;
}
else
if
(
cmd_in
!=
MTSETBLK
&&
cmd_in
!=
MTNOP
)
{
scsi_tapes
[
dev
].
eof
=
0
;
scsi_tapes
[
dev
].
eof_hit
=
0
;
STp
->
eof
=
ST_NOEOF
;
STp
->
eof_hit
=
0
;
}
}
...
...
@@ -1144,7 +1279,8 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
/* The ioctl command */
static
int
st_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
static
int
st_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd_in
,
unsigned
long
arg
)
{
int
dev
=
MINOR
(
inode
->
i_rdev
);
...
...
@@ -1153,10 +1289,12 @@ static int st_ioctl(struct inode * inode,struct file * file,
struct
mtpos
mt_pos
;
unsigned
char
scmd
[
10
];
Scsi_Cmnd
*
SCpnt
;
Scsi_Tape
*
STp
;
dev
=
dev
&
127
;
STp
=
&
(
scsi_tapes
[
dev
]);
#ifdef DEBUG
if
(
!
scsi_tapes
[
dev
].
in_use
)
{
if
(
!
STp
->
in_use
)
{
printk
(
"st%d: Incorrect device.
\n
"
,
dev
);
return
(
-
EIO
);
}
...
...
@@ -1190,7 +1328,7 @@ static int st_ioctl(struct inode * inode,struct file * file,
if
(
i
)
return
i
;
memcpy_tofs
((
char
*
)
arg
,
(
char
*
)
scsi_tapes
[
dev
].
buffer
->
mt_status
,
memcpy_tofs
((
char
*
)
arg
,
(
char
*
)
(
STp
->
buffer
)
->
mt_status
,
sizeof
(
struct
mtget
));
return
0
;
}
...
...
@@ -1209,11 +1347,11 @@ static int st_ioctl(struct inode * inode,struct file * file,
if
(
i
)
return
i
;
SCpnt
=
allocate_device
(
NULL
,
scsi_tapes
[
dev
].
device
->
index
,
1
);
SCpnt
=
allocate_device
(
NULL
,
(
STp
->
device
)
->
index
,
1
);
SCpnt
->
sense_buffer
[
0
]
=
0
;
memset
(
scmd
,
0
,
10
);
if
(
scsi_tapes
[
dev
].
device
->
scsi_level
<
SCSI_2
)
{
if
(
(
STp
->
device
)
->
scsi_level
<
SCSI_2
)
{
scmd
[
0
]
=
QFA_REQUEST_BLOCK
;
scmd
[
4
]
=
3
;
}
...
...
@@ -1224,12 +1362,12 @@ static int st_ioctl(struct inode * inode,struct file * file,
SCpnt
->
request
.
dev
=
dev
;
SCpnt
->
sense_buffer
[
0
]
=
0
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
scmd
,
(
void
*
)
scsi_tapes
[
dev
].
buffer
->
b_data
,
(
void
*
)
scmd
,
(
void
*
)
(
STp
->
buffer
)
->
b_data
,
ST_BLOCK_SIZE
,
st_sleep_done
,
ST_TIMEOUT
,
MAX_READY_RETRIES
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
scsi_tapes
[
dev
].
waiting
);
if
(
SCpnt
->
request
.
dev
==
dev
)
sleep_on
(
&
(
STp
->
waiting
)
);
if
(
SCpnt
->
result
||
SCpnt
->
sense_buffer
[
0
]
)
{
if
(
(
STp
->
buffer
)
->
last_result_fatal
!=
0
)
{
mt_pos
.
mt_blkno
=
(
-
1
);
#ifdef DEBUG
printk
(
"st%d: Can't read tape position.
\n
"
,
dev
);
...
...
@@ -1238,15 +1376,15 @@ static int st_ioctl(struct inode * inode,struct file * file,
}
else
{
result
=
0
;
if
(
scsi_tapes
[
dev
].
device
->
scsi_level
<
SCSI_2
)
mt_pos
.
mt_blkno
=
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
0
]
<<
16
)
+
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
1
]
<<
8
)
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
2
];
if
(
(
STp
->
device
)
->
scsi_level
<
SCSI_2
)
mt_pos
.
mt_blkno
=
(
(
STp
->
buffer
)
->
b_data
[
0
]
<<
16
)
+
(
(
STp
->
buffer
)
->
b_data
[
1
]
<<
8
)
+
(
STp
->
buffer
)
->
b_data
[
2
];
else
mt_pos
.
mt_blkno
=
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
4
]
<<
24
)
+
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
5
]
<<
16
)
+
(
scsi_tapes
[
dev
].
buffer
->
b_data
[
6
]
<<
8
)
+
scsi_tapes
[
dev
].
buffer
->
b_data
[
7
];
mt_pos
.
mt_blkno
=
(
(
STp
->
buffer
)
->
b_data
[
4
]
<<
24
)
+
(
(
STp
->
buffer
)
->
b_data
[
5
]
<<
16
)
+
(
(
STp
->
buffer
)
->
b_data
[
6
]
<<
8
)
+
(
STp
->
buffer
)
->
b_data
[
7
];
}
...
...
@@ -1256,7 +1394,7 @@ static int st_ioctl(struct inode * inode,struct file * file,
return
result
;
}
else
return
scsi_ioctl
(
scsi_tapes
[
dev
].
device
,
cmd_in
,
(
void
*
)
arg
);
return
scsi_ioctl
(
STp
->
device
,
cmd_in
,
(
void
*
)
arg
);
}
...
...
@@ -1303,8 +1441,8 @@ unsigned long st_init(unsigned long mem_start, unsigned long mem_end)
for
(
i
=
0
;
i
<
NR_ST
;
++
i
)
{
scsi_tapes
[
i
].
capacity
=
0xfffff
;
scsi_tapes
[
i
].
dirty
=
0
;
scsi_tapes
[
i
].
rw
=
0
;
scsi_tapes
[
i
].
eof
=
0
;
scsi_tapes
[
i
].
rw
=
ST_IDLE
;
scsi_tapes
[
i
].
eof
=
ST_NOEOF
;
scsi_tapes
[
i
].
waiting
=
NULL
;
scsi_tapes
[
i
].
in_use
=
0
;
scsi_tapes
[
i
].
drv_buffer
=
1
;
/* Try buffering if no mode sense */
...
...
@@ -1320,7 +1458,7 @@ unsigned long st_init(unsigned long mem_start, unsigned long mem_end)
for
(
i
=
0
;
i
<
st_nbr_buffers
;
i
++
)
{
st_buffers
[
i
]
=
(
ST_buffer
*
)
mem_start
;
#ifdef DEBUG
printk
(
"st: Buffer address: %
x
\n
"
,
st_buffers
[
i
]);
printk
(
"st: Buffer address: %
p
\n
"
,
st_buffers
[
i
]);
#endif
mem_start
+=
sizeof
(
ST_buffer
)
-
1
+
ST_BUFFER_BLOCKS
*
ST_BLOCK_SIZE
;
st_buffers
[
i
]
->
mt_status
=
(
struct
mtget
*
)
mem_start
;
...
...
drivers/scsi/st.h
View file @
27c43263
...
...
@@ -18,6 +18,7 @@ typedef struct {
int
read_pointer
;
int
writing
;
int
last_result
;
int
last_result_fatal
;
unsigned
char
b_data
[
1
];
}
ST_buffer
;
...
...
@@ -37,9 +38,20 @@ typedef struct {
int
block_size
;
int
min_block
;
int
max_block
;
int
recover_count
;
Scsi_Cmnd
SCpnt
;
}
Scsi_Tape
;
/* Values of eof */
#define ST_NOEOF 0
#define ST_FM 1
#define ST_EOM_OK 2
#define ST_EOM_ERROR 3
/* Values of rw */
#define ST_IDLE 0
#define ST_READING 1
#define ST_WRITING 2
/* Positioning SCSI-commands for Tandberg, etc. drives */
#define QFA_REQUEST_BLOCK 0x02
...
...
fs/nfs/proc.c
View file @
27c43263
...
...
@@ -27,21 +27,38 @@
#include <linux/in.h>
#ifdef NFS_PROC_DEBUG
static
int
proc_debug
=
0
;
#define PRINTK if (proc_debug) printk
#else
#define PRINTK if (0) printk
#endif
#define PRINTK(format, args...) \
do { \
if (proc_debug) \
printk(format , ## args); \
} while (0)
#else
/* !NFS_PROC_DEBUG */
#define PRINTK(format, args...) do ; while (0)
#define PREP_PAGE_RPC(code) \
if (!(p0 = (int*)__get_free_page(GFP_KERNEL)))\
return NFSERR_IO;\
p=nfs_rpc_header(p0,code)
#endif
/* !NFS_PROC_DEBUG */
static
int
*
nfs_rpc_header
(
int
*
p
,
int
procedure
);
static
int
*
nfs_rpc_verify
(
int
*
p
);
static
int
nfs_stat_to_errno
(
int
stat
);
/*
* Our memory allocation and release functions.
*/
static
inline
int
*
nfs_rpc_alloc
(
void
)
{
return
(
int
*
)
__get_free_page
(
GFP_KERNEL
);
}
static
inline
void
nfs_rpc_free
(
int
*
p
)
{
free_page
((
long
)
p
);
}
/*
* Here are a bunch of xdr encode/decode functions that convert
* between machine dependent and xdr data formats.
...
...
@@ -166,6 +183,10 @@ static int *xdr_decode_fsinfo(int *p, struct nfs_fsinfo *res)
return
p
;
}
/*
* One function for each procedure in the NFS protocol.
*/
int
nfs_proc_getattr
(
struct
nfs_server
*
server
,
struct
nfs_fh
*
fhandle
,
struct
nfs_fattr
*
fattr
)
{
...
...
@@ -173,10 +194,12 @@ int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
int
status
;
PRINTK
(
"NFS call getattr
\n
"
);
PREP_PAGE_RPC
(
NFSPROC_GETATTR
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_GETATTR
);
p
=
xdr_encode_fhandle
(
p
,
fhandle
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -187,7 +210,7 @@ int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
}
else
PRINTK
(
"NFS reply getattr failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -198,11 +221,13 @@ int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
int
status
;
PRINTK
(
"NFS call setattr
\n
"
);
PREP_PAGE_RPC
(
NFSPROC_SETATTR
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_SETATTR
);
p
=
xdr_encode_fhandle
(
p
,
fhandle
);
p
=
xdr_encode_sattr
(
p
,
sattr
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -213,7 +238,7 @@ int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
}
else
PRINTK
(
"NFS reply setattr failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -228,11 +253,13 @@ int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *n
if
(
!
strcmp
(
name
,
"xyzzy"
))
proc_debug
=
1
-
proc_debug
;
#endif
PREP_PAGE_RPC
(
NFSPROC_LOOKUP
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_LOOKUP
);
p
=
xdr_encode_fhandle
(
p
,
dir
);
p
=
xdr_encode_string
(
p
,
name
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -244,7 +271,7 @@ int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *n
}
else
PRINTK
(
"NFS reply lookup failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -255,10 +282,12 @@ int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
int
status
;
PRINTK
(
"NFS call readlink
\n
"
);
PREP_PAGE_RPC
(
NFSPROC_READLINK
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_READLINK
);
p
=
xdr_encode_fhandle
(
p
,
fhandle
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -273,7 +302,7 @@ int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
}
else
PRINTK
(
"NFS reply readlink failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -285,13 +314,15 @@ int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
int
len
=
0
;
/* = 0 is for gcc */
PRINTK
(
"NFS call read %d @ %d
\n
"
,
count
,
offset
);
PREP_PAGE_RPC
(
NFSPROC_READ
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_READ
);
p
=
xdr_encode_fhandle
(
p
,
fhandle
);
*
p
++
=
htonl
(
offset
);
*
p
++
=
htonl
(
count
);
*
p
++
=
htonl
(
count
);
/* traditional, could be any value */
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -307,7 +338,7 @@ int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
}
else
PRINTK
(
"NFS reply read failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
(
status
==
NFS_OK
)
?
len
:
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -318,14 +349,16 @@ int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
int
status
;
PRINTK
(
"NFS call write %d @ %d
\n
"
,
count
,
offset
);
PREP_PAGE_RPC
(
NFSPROC_WRITE
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_WRITE
);
p
=
xdr_encode_fhandle
(
p
,
fhandle
);
*
p
++
=
htonl
(
offset
);
/* traditional, could be any value */
*
p
++
=
htonl
(
offset
);
*
p
++
=
htonl
(
count
);
/* traditional, could be any value */
p
=
xdr_encode_data
(
p
,
data
,
count
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -336,7 +369,7 @@ int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
}
else
PRINTK
(
"NFS reply write failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -348,12 +381,14 @@ int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
int
status
;
PRINTK
(
"NFS call create %s
\n
"
,
name
);
PREP_PAGE_RPC
(
NFSPROC_CREATE
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_CREATE
);
p
=
xdr_encode_fhandle
(
p
,
dir
);
p
=
xdr_encode_string
(
p
,
name
);
p
=
xdr_encode_sattr
(
p
,
sattr
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -365,7 +400,7 @@ int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
}
else
PRINTK
(
"NFS reply create failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -375,11 +410,13 @@ int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *n
int
status
;
PRINTK
(
"NFS call remove %s
\n
"
,
name
);
PREP_PAGE_RPC
(
NFSPROC_REMOVE
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_REMOVE
);
p
=
xdr_encode_fhandle
(
p
,
dir
);
p
=
xdr_encode_string
(
p
,
name
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -389,7 +426,7 @@ int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *n
}
else
PRINTK
(
"NFS reply remove failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -401,13 +438,15 @@ int nfs_proc_rename(struct nfs_server *server,
int
status
;
PRINTK
(
"NFS call rename %s -> %s
\n
"
,
old_name
,
new_name
);
PREP_PAGE_RPC
(
NFSPROC_RENAME
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_RENAME
);
p
=
xdr_encode_fhandle
(
p
,
old_dir
);
p
=
xdr_encode_string
(
p
,
old_name
);
p
=
xdr_encode_fhandle
(
p
,
new_dir
);
p
=
xdr_encode_string
(
p
,
new_name
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -417,7 +456,7 @@ int nfs_proc_rename(struct nfs_server *server,
}
else
PRINTK
(
"NFS reply rename failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -428,12 +467,14 @@ int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
int
status
;
PRINTK
(
"NFS call link %s
\n
"
,
name
);
PREP_PAGE_RPC
(
NFSPROC_LINK
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_LINK
);
p
=
xdr_encode_fhandle
(
p
,
fhandle
);
p
=
xdr_encode_fhandle
(
p
,
dir
);
p
=
xdr_encode_string
(
p
,
name
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -443,7 +484,7 @@ int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
}
else
PRINTK
(
"NFS reply link failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -454,13 +495,15 @@ int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
int
status
;
PRINTK
(
"NFS call symlink %s -> %s
\n
"
,
name
,
path
);
PREP_PAGE_RPC
(
NFSPROC_SYMLINK
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_SYMLINK
);
p
=
xdr_encode_fhandle
(
p
,
dir
);
p
=
xdr_encode_string
(
p
,
name
);
p
=
xdr_encode_string
(
p
,
path
);
p
=
xdr_encode_sattr
(
p
,
sattr
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -470,7 +513,7 @@ int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
}
else
PRINTK
(
"NFS reply symlink failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -482,12 +525,14 @@ int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
int
status
;
PRINTK
(
"NFS call mkdir %s
\n
"
,
name
);
PREP_PAGE_RPC
(
NFSPROC_MKDIR
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_MKDIR
);
p
=
xdr_encode_fhandle
(
p
,
dir
);
p
=
xdr_encode_string
(
p
,
name
);
p
=
xdr_encode_sattr
(
p
,
sattr
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -499,7 +544,7 @@ int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
}
else
PRINTK
(
"NFS reply mkdir failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -509,11 +554,13 @@ int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *na
int
status
;
PRINTK
(
"NFS call rmdir %s
\n
"
,
name
);
PREP_PAGE_RPC
(
NFSPROC_RMDIR
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_RMDIR
);
p
=
xdr_encode_fhandle
(
p
,
dir
);
p
=
xdr_encode_string
(
p
,
name
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -523,7 +570,7 @@ int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *na
}
else
PRINTK
(
"NFS reply rmdir failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -538,12 +585,14 @@ int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
PRINTK
(
"NFS call readdir %d @ %d
\n
"
,
count
,
cookie
);
size
=
server
->
rsize
;
PREP_PAGE_RPC
(
NFSPROC_READDIR
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_READDIR
);
p
=
xdr_encode_fhandle
(
p
,
fhandle
);
*
p
++
=
htonl
(
cookie
);
*
p
++
=
htonl
(
size
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -568,7 +617,7 @@ int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
}
else
PRINTK
(
"NFS reply readdir failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
(
status
==
NFS_OK
)
?
i
:
-
nfs_stat_to_errno
(
status
);
}
...
...
@@ -579,10 +628,12 @@ int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
int
status
;
PRINTK
(
"NFS call statfs
\n
"
);
PREP_PAGE_RPC
(
NFSPROC_STATFS
);
if
(
!
(
p0
=
nfs_rpc_alloc
()))
return
-
EIO
;
p
=
nfs_rpc_header
(
p0
,
NFSPROC_STATFS
);
p
=
xdr_encode_fhandle
(
p
,
fhandle
);
if
((
status
=
nfs_rpc_call
(
server
,
p0
,
p
))
<
0
)
{
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
status
;
}
if
(
!
(
p
=
nfs_rpc_verify
(
p0
)))
...
...
@@ -593,7 +644,7 @@ int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
}
else
PRINTK
(
"NFS reply statfs failed = %d
\n
"
,
status
);
free_page
((
long
)
p0
);
nfs_rpc_free
(
p0
);
return
-
nfs_stat_to_errno
(
status
);
}
...
...
include/linux/in.h
View file @
27c43263
...
...
@@ -132,6 +132,15 @@ __ntohl(unsigned long int x)
return
x
;
}
static
__inline__
unsigned
long
int
__constant_ntohl
(
unsigned
long
int
x
)
{
return
(((
x
&
0x000000ff
)
<<
24
)
|
((
x
&
0x0000ff00
)
<<
8
)
|
((
x
&
0x00ff0000
)
>>
8
)
|
((
x
&
0xff000000
)
>>
24
));
}
static
__inline__
unsigned
short
int
__ntohs
(
unsigned
short
int
x
)
{
...
...
@@ -141,31 +150,35 @@ __ntohs(unsigned short int x)
return
x
;
}
static
__inline__
unsigned
long
int
__htonl
(
unsigned
long
int
x
)
{
__asm__
(
"xchgb %b0,%h0
\n\t
"
/* swap lower bytes */
"rorl $16,%0
\n\t
"
/* swap words */
"xchgb %b0,%h0"
/* swap higher bytes */
:
"=q"
(
x
)
:
"0"
(
x
));
return
x
;
}
static
__inline__
unsigned
short
int
__
hton
s
(
unsigned
short
int
x
)
__
constant_ntoh
s
(
unsigned
short
int
x
)
{
__asm__
(
"xchgb %b0,%h0"
/* swap bytes */
:
"=q"
(
x
)
:
"0"
(
x
));
return
x
;
return
(((
x
&
0x00ff
)
<<
8
)
|
((
x
&
0xff00
)
>>
8
));
}
#define __htonl(x) __ntohl(x)
#define __htons(x) __ntohs(x)
#define __constant_htonl(x) __constant_ntohl(x)
#define __constant_htons(x) __constant_ntohs(x)
#ifdef __OPTIMIZE__
# define ntohl(x) __ntohl((x))
# define ntohs(x) __ntohs((x))
# define htonl(x) __htonl((x))
# define htons(x) __htons((x))
# define ntohl(x) \
(__builtin_constant_p((x)) ? \
__constant_ntohl((x)) : \
__ntohl((x)))
# define ntohs(x) \
(__builtin_constant_p((x)) ? \
__constant_ntohs((x)) : \
__ntohs((x)))
# define htonl(x) \
(__builtin_constant_p((x)) ? \
__constant_htonl((x)) : \
__htonl((x)))
# define htons(x) \
(__builtin_constant_p((x)) ? \
__constant_htons((x)) : \
__htons((x)))
#endif
#endif
/* _LINUX_IN_H */
ipc/msg.c
View file @
27c43263
...
...
@@ -20,7 +20,7 @@ static int findkey (key_t key);
static
struct
msqid_ds
*
msgque
[
MSGMNI
];
static
int
msgbytes
=
0
;
static
int
msghdrs
=
0
;
static
in
t
msg_seq
=
0
;
static
unsigned
shor
t
msg_seq
=
0
;
static
int
used_queues
=
0
;
static
int
max_msqid
=
0
;
static
struct
wait_queue
*
msg_lock
=
NULL
;
...
...
@@ -264,7 +264,7 @@ static int newque (key_t key, int msgflg)
used_queues
++
;
if
(
msg_lock
)
wake_up
(
&
msg_lock
);
return
msg_seq
*
MSGMNI
+
id
;
return
(
int
)
msg_seq
*
MSGMNI
+
id
;
}
int
sys_msgget
(
key_t
key
,
int
msgflg
)
...
...
@@ -295,8 +295,7 @@ static void freeque (int id)
struct
msg
*
msgp
,
*
msgh
;
msq
->
msg_perm
.
seq
++
;
if
((
int
)((
++
msg_seq
+
1
)
*
MSGMNI
)
<
0
)
msg_seq
=
0
;
msg_seq
++
;
msgbytes
-=
msq
->
msg_cbytes
;
if
(
id
==
max_msqid
)
while
(
max_msqid
&&
(
msgque
[
--
max_msqid
]
==
IPC_UNUSED
));
...
...
ipc/sem.c
View file @
27c43263
...
...
@@ -20,9 +20,10 @@ static void freeary (int id);
static
struct
semid_ds
*
semary
[
SEMMNI
];
static
int
used_sems
=
0
,
used_semids
=
0
;
static
struct
wait_queue
*
sem_lock
=
NULL
;
static
int
sem_seq
=
0
;
static
int
max_semid
=
0
;
static
unsigned
short
sem_seq
=
0
;
void
sem_init
(
void
)
{
int
i
=
0
;
...
...
@@ -95,7 +96,7 @@ static int newary (key_t key, int nsems, int semflg)
semary
[
id
]
=
sma
;
if
(
sem_lock
)
wake_up
(
&
sem_lock
);
return
sem_seq
*
SEMMNI
+
id
;
return
(
int
)
sem_seq
*
SEMMNI
+
id
;
}
int
sys_semget
(
key_t
key
,
int
nsems
,
int
semflg
)
...
...
@@ -128,8 +129,7 @@ static void freeary (int id)
struct
sem_undo
*
un
;
sma
->
sem_perm
.
seq
++
;
if
((
int
)((
++
sem_seq
+
1
)
*
SEMMNI
)
<
0
)
sem_seq
=
0
;
sem_seq
++
;
used_sems
-=
sma
->
sem_nsems
;
if
(
id
==
max_semid
)
while
(
max_semid
&&
(
semary
[
--
max_semid
]
==
IPC_UNUSED
));
...
...
ipc/shm.c
View file @
27c43263
...
...
@@ -23,11 +23,12 @@ static void killseg (int id);
static
int
shm_tot
=
0
;
/* total number of shared memory pages */
static
int
shm_rss
=
0
;
/* number of shared memory pages that are in memory */
static
int
shm_swp
=
0
;
/* number of shared memory pages that are in swap */
static
int
shm_seq
=
0
;
/* is incremented, for recognizing stale ids */
static
int
max_shmid
=
0
;
/* every used id is <= max_shmid */
static
struct
wait_queue
*
shm_lock
=
NULL
;
static
struct
shmid_ds
*
shm_segs
[
SHMMNI
];
static
unsigned
short
shm_seq
=
0
;
/* incremented, for recognizing stale ids */
/* some statistics */
static
ulong
swap_attempts
=
0
;
static
ulong
swap_successes
=
0
;
...
...
@@ -119,7 +120,7 @@ static int newseg (key_t key, int shmflg, int size)
used_segs
++
;
if
(
shm_lock
)
wake_up
(
&
shm_lock
);
return
id
+
shm_seq
*
SHMMNI
;
return
id
+
(
int
)
shm_seq
*
SHMMNI
;
}
int
sys_shmget
(
key_t
key
,
int
size
,
int
shmflg
)
...
...
@@ -165,8 +166,7 @@ static void killseg (int id)
}
shp
->
shm_perm
.
seq
++
;
/* for shmat */
numpages
=
shp
->
shm_npages
;
if
((
int
)((
++
shm_seq
+
1
)
*
SHMMNI
)
<
0
)
shm_seq
=
0
;
shm_seq
++
;
shm_segs
[
id
]
=
(
struct
shmid_ds
*
)
IPC_UNUSED
;
used_segs
--
;
if
(
id
==
max_shmid
)
...
...
kernel/printk.c
View file @
27c43263
...
...
@@ -88,9 +88,11 @@ asmlinkage int sys_syslog(int type, char * buf, int len)
log_start
++
;
log_size
--
;
log_start
&=
LOG_BUF_LEN
-
1
;
sti
();
put_fs_byte
(
c
,
buf
);
buf
++
;
i
++
;
cli
();
}
sti
();
return
i
;
...
...
net/inet/icmp.c
View file @
27c43263
...
...
@@ -210,11 +210,11 @@ icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
ip
=
iph
->
daddr
;
switch
(
icmph
->
code
&
7
)
{
case
ICMP_REDIR_NET
:
rt_add
((
RTF_DYNAMIC
|
RTF_MODIFIED
),
rt_add
((
RTF_DYNAMIC
|
RTF_MODIFIED
|
RTF_GATEWAY
),
ip
,
icmph
->
un
.
gateway
,
dev
);
break
;
case
ICMP_REDIR_HOST
:
rt_add
((
RTF_DYNAMIC
|
RTF_MODIFIED
|
RTF_HOST
),
rt_add
((
RTF_DYNAMIC
|
RTF_MODIFIED
|
RTF_HOST
|
RTF_GATEWAY
),
ip
,
icmph
->
un
.
gateway
,
dev
);
break
;
case
ICMP_REDIR_NETTOS
:
...
...
net/inet/inet.h
View file @
27c43263
...
...
@@ -59,7 +59,7 @@
#ifdef INET_DEBUG
# define DPRINTF(x) dprintf x
#else
# define DPRINTF(x)
/*zilch*/
# define DPRINTF(x)
do ; while (0)
#endif
/* Debug levels. One per module. */
...
...
net/inet/route.c
View file @
27c43263
...
...
@@ -112,6 +112,16 @@ void rt_flush(struct device *dev)
/*
* Used by 'rt_add()' when we can't get the netmask from the device..
*
* If the lower byte or two are zero, we guess the mask based on the
* number of zero 8-bit net numbers, otherwise we use the "default"
* masks judging by the destination address.
*
* We should really use masks everywhere, but the current system
* interface for adding routes doesn't even contain a netmask field.
* Similarly, ICMP redirect messages contain only the address to
* redirect.. Anyway, this function should give reasonable values
* for almost anything.
*/
static
unsigned
long
guess_mask
(
unsigned
long
dst
)
{
...
...
@@ -119,7 +129,29 @@ static unsigned long guess_mask(unsigned long dst)
while
(
mask
&
dst
)
mask
<<=
8
;
if
(
mask
)
return
~
mask
;
dst
=
ntohl
(
dst
);
if
(
IN_CLASSA
(
dst
))
return
htonl
(
IN_CLASSA_NET
);
if
(
IN_CLASSB
(
dst
))
return
htonl
(
IN_CLASSB_NET
);
return
htonl
(
IN_CLASSC_NET
);
}
static
inline
struct
device
*
get_gw_dev
(
unsigned
long
gw
)
{
struct
rtable
*
rt
;
for
(
rt
=
rt_base
;
rt
;
rt
=
rt
->
rt_next
)
{
if
((
gw
^
rt
->
rt_dst
)
&
rt
->
rt_mask
)
continue
;
/* gateways behind gateways are a no-no */
if
(
rt
->
rt_flags
&
RTF_GATEWAY
)
return
NULL
;
return
rt
->
rt_dev
;
}
return
NULL
;
}
/*
...
...
@@ -133,42 +165,40 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
unsigned
long
mask
;
unsigned
long
cpuflags
;
/* Allocate an entry. */
rt
=
(
struct
rtable
*
)
kmalloc
(
sizeof
(
struct
rtable
),
GFP_ATOMIC
);
if
(
rt
==
NULL
)
{
DPRINTF
((
DBG_RT
,
"RT: no memory for new route!
\n
"
));
return
;
}
/* Fill in the fields. */
memset
(
rt
,
0
,
sizeof
(
struct
rtable
));
rt
->
rt_flags
=
(
flags
|
RTF_UP
);
/*
* Gateway to our own interface is really direct
*/
if
(
gw
==
dev
->
pa_addr
||
gw
==
dst
)
{
gw
=
0
;
rt
->
rt_flags
&=~
RTF_GATEWAY
;
}
if
(
gw
!=
0
)
rt
->
rt_flags
|=
RTF_GATEWAY
;
rt
->
rt_dev
=
dev
;
rt
->
rt_gateway
=
gw
;
if
(
flags
&
RTF_HOST
)
{
mask
=
0xffffffff
;
rt
->
rt_dst
=
dst
;
}
else
{
if
(
!
((
dst
^
dev
->
pa_addr
)
&
dev
->
pa_mask
))
{
mask
=
dev
->
pa_mask
;
dst
&=
mask
;
flags
&=
~
RTF_GATEWAY
;
if
(
flags
&
RTF_DYNAMIC
)
{
kfree_s
(
rt
,
sizeof
(
struct
rtable
));
/*printk("Dynamic route to my own net rejected\n");*/
return
;
}
}
else
mask
=
guess_mask
(
dst
);
rt
->
rt_dst
=
dst
;
}
if
(
gw
==
dev
->
pa_addr
)
flags
&=
~
RTF_GATEWAY
;
if
(
flags
&
RTF_GATEWAY
)
{
/* don't try to add a gateway we can't reach.. */
if
(
dev
!=
get_gw_dev
(
gw
))
return
;
flags
|=
RTF_GATEWAY
;
}
else
gw
=
0
;
/* Allocate an entry. */
rt
=
(
struct
rtable
*
)
kmalloc
(
sizeof
(
struct
rtable
),
GFP_ATOMIC
);
if
(
rt
==
NULL
)
{
DPRINTF
((
DBG_RT
,
"RT: no memory for new route!
\n
"
));
return
;
}
memset
(
rt
,
0
,
sizeof
(
struct
rtable
));
rt
->
rt_flags
=
flags
|
RTF_UP
;
rt
->
rt_dst
=
dst
;
rt
->
rt_dev
=
dev
;
rt
->
rt_gateway
=
gw
;
rt
->
rt_mask
=
mask
;
rt_print
(
rt
);
/*
...
...
@@ -206,7 +236,6 @@ static int
rt_new
(
struct
rtentry
*
r
)
{
struct
device
*
dev
;
struct
rtable
*
rt
;
if
((
r
->
rt_dst
.
sa_family
!=
AF_INET
)
||
(
r
->
rt_gateway
.
sa_family
!=
AF_INET
))
{
...
...
@@ -226,11 +255,7 @@ rt_new(struct rtentry *r)
if
(
!
(
r
->
rt_flags
&
RTF_GATEWAY
))
dev
=
dev_check
(((
struct
sockaddr_in
*
)
&
r
->
rt_dst
)
->
sin_addr
.
s_addr
);
else
if
((
rt
=
rt_route
(((
struct
sockaddr_in
*
)
&
r
->
rt_gateway
)
->
sin_addr
.
s_addr
,
NULL
)))
dev
=
rt
->
rt_dev
;
else
dev
=
NULL
;
dev
=
get_gw_dev
(((
struct
sockaddr_in
*
)
&
r
->
rt_gateway
)
->
sin_addr
.
s_addr
);
DPRINTF
((
DBG_RT
,
"RT: dev for %s gw "
,
in_ntoa
((
*
(
struct
sockaddr_in
*
)
&
r
->
rt_dst
).
sin_addr
.
s_addr
)));
...
...
@@ -269,13 +294,14 @@ rt_get_info(char *buffer)
pos
=
buffer
;
pos
+=
sprintf
(
pos
,
"Iface
\t
Destination
\t
Gateway
\t
Flags
\t
RefCnt
\t
Use
\t
Metric
\n
"
);
"Iface
\t
Destination
\t
Gateway
\t
Flags
\t
RefCnt
\t
Use
\t
Metric
\
t
Mask
\
n
"
);
/* This isn't quite right -- r->rt_dst is a struct! */
for
(
r
=
rt_base
;
r
!=
NULL
;
r
=
r
->
rt_next
)
{
pos
+=
sprintf
(
pos
,
"%s
\t
%08lX
\t
%08lX
\t
%02X
\t
%d
\t
%lu
\t
%d
\n
"
,
pos
+=
sprintf
(
pos
,
"%s
\t
%08lX
\t
%08lX
\t
%02X
\t
%d
\t
%lu
\t
%d
\
t
%08lX
\
n
"
,
r
->
rt_dev
->
name
,
r
->
rt_dst
,
r
->
rt_gateway
,
r
->
rt_flags
,
r
->
rt_refcnt
,
r
->
rt_use
,
r
->
rt_metric
);
r
->
rt_flags
,
r
->
rt_refcnt
,
r
->
rt_use
,
r
->
rt_metric
,
r
->
rt_mask
);
}
return
(
pos
-
buffer
);
}
...
...
tools/build.c
View file @
27c43263
...
...
@@ -212,14 +212,16 @@ int main(int argc, char ** argv)
fprintf
(
stderr
,
"Unexpected EOF
\n
"
);
die
(
"Can't read 'system'"
);
}
write
(
1
,
buf
,
l
);
if
(
write
(
1
,
buf
,
l
)
!=
l
)
die
(
"Write failed"
);
sz
-=
l
;
}
close
(
id
);
if
(
lseek
(
1
,
500
,
0
)
==
500
)
{
buf
[
0
]
=
(
sys_size
&
0xff
);
buf
[
1
]
=
((
sys_size
>>
8
)
&
0xff
);
write
(
1
,
buf
,
2
);
if
(
write
(
1
,
buf
,
2
)
!=
2
)
die
(
"Write failed"
);
}
return
(
0
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment