Commit 2fbc2376 authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.15g

parent 9e11983a
......@@ -158,7 +158,7 @@ function int () {
eval "$2=$ans"
}
CONFIG=.config~
CONFIG=.tmpconfig
CONFIG_H=include/linux/autoconf.h
trap "rm -f $CONFIG $CONFIG_H config.new ; exit 1" 1 2
......
VERSION = 0.99
PATCHLEVEL = 15
ALPHA = f
ALPHA = g
all: Version zImage
......@@ -116,10 +116,10 @@ Version: dummy
config:
$(CONFIG_SHELL) Configure $(OPTS) < config.in
@if grep -s '^CONFIG_SOUND' .config~ ; then \
@if grep -s '^CONFIG_SOUND' .tmpconfig ; then \
$(MAKE) -C drivers/sound config; \
else : ; fi
mv .config~ .config
mv .tmpconfig .config
linuxsubdirs: dummy
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
......@@ -229,7 +229,7 @@ clean:
rm -f zImage zSystem.map tools/zSystem tools/system
rm -f Image System.map boot/bootsect boot/setup
rm -f zBoot/zSystem zBoot/xtract zBoot/piggyback
rm -f drivers/sound/configure
rm -f .tmp* drivers/sound/configure
rm -f init/*.o tools/build boot/*.o tools/*.o
mrproper: clean
......@@ -246,11 +246,11 @@ backup: mrproper
depend dep:
touch tools/version.h
for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done > .depend~
for i in tools/*.c;do echo -n "tools/";$(CPP) -M $$i;done >> .depend~
for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done > .tmpdepend
for i in tools/*.c;do echo -n "tools/";$(CPP) -M $$i;done >> .tmpdepend
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i dep; done
rm -f tools/version.h
mv .depend~ .depend
mv .tmpdepend .depend
ifdef CONFIGURATION
..$(CONFIGURATION):
......
......@@ -84,17 +84,21 @@ void emu_printall()
RE_ENTRANT_CHECK_OFF;
/* No need to verify_area(), we have previously fetched these bytes. */
printk("At %p: ", (void *) address);
printk("At %p:", (void *) address);
#define MAX_PRINTED_BYTES 20
for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
{
byte1 = get_fs_byte((unsigned char *) address);
if ( (byte1 & 0xf8) == 0xd8 ) break;
printk("[%02x]", byte1);
if ( (byte1 & 0xf8) == 0xd8 )
{
printk(" %02x", byte1);
break;
}
printk(" [%02x]", byte1);
address++;
}
if ( i == MAX_PRINTED_BYTES ) printk("[more..]");
printk("%02x ", byte1);
if ( i == MAX_PRINTED_BYTES ) printk(" [more..]");
printk("\n");
FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
partial_status = status_word();
......
......@@ -144,6 +144,7 @@ static int valid_prefix(unsigned char *Byte, unsigned char **fpu_eip,
asmlinkage void math_emulate(long arg)
{
unsigned char FPU_modrm, byte1;
unsigned short code;
fpu_addr_modes addr_modes;
int unmasked;
......@@ -250,7 +251,7 @@ asmlinkage void math_emulate(long arg)
but a real 80486 uses the following instructions:
fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
*/
unsigned short code = (FPU_modrm << 8) | byte1;
code = (FPU_modrm << 8) | byte1;
if ( ! ( (((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
(((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv,
fnstsw */
......
......@@ -259,8 +259,10 @@ void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops)
flush_input(tty);
flush_output(tty);
wake_up_interruptible(&tty->secondary.proc_list);
if (tty->session > 0)
if (tty->session > 0) {
kill_sl(tty->session,SIGHUP,1);
kill_sl(tty->session,SIGCONT,1);
}
tty->session = 0;
tty->pgrp = -1;
for_each_task(p) {
......@@ -297,7 +299,7 @@ int tty_hung_up_p(struct file * filp)
* it wants to dissassociate itself from its controlling tty.
*
* It performs the following functions:
* (1) Sends a SIGHUP to the foreground process group
* (1) Sends a SIGHUP and SIGCONT to the foreground process group
* (2) Clears the tty from being controlling the session
* (3) Clears the controlling tty for all processes in the
* session group.
......@@ -310,8 +312,10 @@ void disassociate_ctty(int priv)
if (current->tty >= 0) {
tty = tty_table[current->tty];
if (tty) {
if (tty->pgrp > 0)
if (tty->pgrp > 0) {
kill_pg(tty->pgrp, SIGHUP, priv);
kill_pg(tty->pgrp, SIGCONT, priv);
}
tty->session = 0;
tty->pgrp = -1;
} else
......
......@@ -232,6 +232,13 @@ static void sl_changedmtu(struct slip *sl)
sl->mtu=dev->mtu;
l=(dev->mtu *2);
/*
* allow for arrival of larger UDP packets, even if we say not to
* also fixes a bug in which SunOS sends 512-byte packets even with
* an MSS of 128
*/
if (l < (576 * 2))
l = 576 * 2;
DPRINTF((DBG_SLIP,"SLIP: mtu changed!\n"));
......@@ -655,6 +662,14 @@ sl_open(struct device *dev)
* rmem_start Start of RECV frame buffer
*/
l = (dev->mtu * 2);
/*
* allow for arrival of larger UDP packets, even if we say not to
* also fixes a bug in which SunOS sends 512-byte packets even with
* an MSS of 128
*/
if (l < (576 * 2))
l = 576 * 2;
p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
if (p == NULL) {
DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP XMIT buffer!\n"));
......
......@@ -277,6 +277,10 @@ static void ext2_setup_super (struct super_block * sb,
es->s_mnt_count >= (unsigned short) es->s_max_mnt_count)
printk ("EXT2-fs warning: maximal mount count reached, "
"running e2fsck is recommended\n");
else if (es->s_checkinterval &&
(es->s_lastcheck + es->s_checkinterval <= CURRENT_TIME))
printk ("EXT2-fs warning: checktime reached, "
"running e2fsck is recommended\n");
if (!(sb->s_flags & MS_RDONLY)) {
es->s_state &= ~EXT2_VALID_FS;
if (!es->s_max_mnt_count)
......
......@@ -380,7 +380,7 @@ static int do_remount(const char *dir,int flags,char *data)
return retval;
}
static int copy_mount_options (char * data, unsigned long *where)
static int copy_mount_options (const void * data, unsigned long *where)
{
int i;
unsigned long page;
......
......@@ -262,6 +262,7 @@ struct ext2_inode {
* Maximal mount counts between two filesystem checks
*/
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
/*
* Behaviour when detecting errors
......@@ -294,7 +295,9 @@ struct ext2_super_block {
unsigned short s_state; /* File system state */
unsigned short s_errors; /* Behaviour when detecting errors */
unsigned short s_pad;
unsigned long s_reserved[240]; /* Padding to the end of the block */
unsigned long s_lastcheck; /* time of last check */
unsigned long s_checkinterval; /* max. time between checks */
unsigned long s_reserved[238]; /* Padding to the end of the block */
};
/*
......
......@@ -969,49 +969,53 @@ dev_ioctl(unsigned int cmd, void *arg)
int ret;
switch(cmd) {
case IP_SET_DEV:
printk("Your network configuration program needs upgrading.\n");
return -EINVAL;
case IP_SET_DEV:
printk("Your network configuration program needs upgrading.\n");
return -EINVAL;
case SIOCGIFCONF:
(void) dev_ifconf((char *) arg);
ret = 0;
break;
return 0;
case SIOCGIFFLAGS:
case SIOCSIFFLAGS:
case SIOCGIFADDR:
case SIOCSIFADDR:
case SIOCGIFDSTADDR:
case SIOCSIFDSTADDR:
case SIOCGIFBRDADDR:
case SIOCSIFBRDADDR:
case SIOCGIFNETMASK:
case SIOCSIFNETMASK:
case SIOCGIFMETRIC:
case SIOCSIFMETRIC:
case SIOCGIFMTU:
case SIOCSIFMTU:
case SIOCGIFMEM:
case SIOCSIFMEM:
case SIOCGIFHWADDR:
if (!suser()) return(-EPERM);
ret = dev_ifsioc(arg, cmd);
break;
return dev_ifsioc(arg, cmd);
case SIOCSIFFLAGS:
case SIOCSIFADDR:
case SIOCSIFDSTADDR:
case SIOCSIFBRDADDR:
case SIOCSIFNETMASK:
case SIOCSIFMETRIC:
case SIOCSIFMTU:
case SIOCSIFMEM:
if (!suser())
return -EPERM;
return dev_ifsioc(arg, cmd);
case SIOCSIFLINK:
if (!suser()) return(-EPERM);
if (!suser())
return -EPERM;
memcpy_fromfs(&iflink, arg, sizeof(iflink));
dev = ddi_map(iflink.id);
if (dev == NULL) return(-EINVAL);
if (dev == NULL)
return -EINVAL;
/* Now allocate an interface and connect it. */
printk("AF_INET: DDI \"%s\" linked to stream \"%s\"\n",
dev->name, iflink.stream);
ret = 0;
break;
return 0;
default:
ret = -EINVAL;
return -EINVAL;
}
return(ret);
}
......
......@@ -497,7 +497,7 @@ static int inet_setsockopt(struct socket *sock, int level, int optname,
static int inet_getsockopt(struct socket *sock, int level, int optname,
char *optval, int *optlen)
{
struct sock *sk = sock->data;
struct sock *sk = (struct sock *) sock->data;
if (level == SOL_SOCKET)
return sock_getsockopt(sk,level,optname,optval,optlen);
if(sk->prot->getsockopt==NULL)
......
......@@ -60,6 +60,7 @@
* Charles Hedrick : TCP fixes
* Toomas Tamm : TCP window fixes
* Alan Cox : Small URG fix to rlogin ^C ack fight
* Linus : Rewrote URG handling completely
*
*
* To Fix:
......@@ -350,8 +351,8 @@ tcp_readable(struct sock *sk)
if (amount && skb->h.th->psh) break;
skb =(struct sk_buff *)skb->next; /* Move along */
} while(skb != sk->rqueue);
if (sk->urg_data &&
(sk->urg_seq - sk->copied_seq) < (counted - sk->copied_seq))
if (amount && !sk->urginline && sk->urg_data &&
(sk->urg_seq - sk->copied_seq) <= (counted - sk->copied_seq))
amount--; /* don't count urg data */
restore_flags(flags);
DPRINTF((DBG_TCP, "tcp readable returning %d bytes\n", amount));
......@@ -442,7 +443,7 @@ tcp_select(struct sock *sk, int sel_type, select_table *wait)
return(0);
case SEL_EX:
select_wait(sk->sleep,wait);
if (sk->err) {
if (sk->err || sk->urg_data) {
release_sock(sk);
return(1);
}
......@@ -486,17 +487,11 @@ tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
}
case SIOCATMARK:
{
int answ = 0;
int answ = sk->urg_data && sk->urg_seq == sk->copied_seq+1;
/*
* Try to figure out if we need to read
* some urgent data.
*/
if (sk->urg_data && sk->copied_seq+1 == sk->urg_seq)
answ = 1;
err=verify_area(VERIFY_WRITE,(void *) arg,
err = verify_area(VERIFY_WRITE,(void *) arg,
sizeof(unsigned long));
if(err)
if (err)
return err;
put_fs_long(answ,(int *) arg);
return(0);
......@@ -1250,7 +1245,9 @@ tcp_read_urg(struct sock * sk, int nonblock,
struct wait_queue wait = { current, NULL };
while (len > 0) {
if (sk->urg_data && sk->urg_data != URG_READ) {
if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ)
return -EINVAL;
if (sk->urg_data & URG_VALID) {
char c = sk->urg_data;
if (!(flags & MSG_PEEK))
sk->urg_data = URG_READ;
......@@ -1285,8 +1282,8 @@ tcp_read_urg(struct sock * sk, int nonblock,
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(sk->sleep, &wait);
if ((!sk->urg_data || sk->urg_data == URG_READ) &&
sk->err == 0 && !(sk->shutdown & RCV_SHUTDOWN))
if ((sk->urg_data & URG_NOTYET) && sk->err == 0 &&
!(sk->shutdown & RCV_SHUTDOWN))
schedule();
remove_wait_queue(sk->sleep, &wait);
current->state = TASK_RUNNING;
......@@ -1302,7 +1299,9 @@ tcp_read(struct sock *sk, unsigned char *to,
{
int copied = 0; /* will be used to say how much has been copied. */
struct sk_buff *skb;
unsigned long peek_seq;
unsigned long offset;
unsigned long *seq;
int err;
if (len == 0)
......@@ -1310,11 +1309,11 @@ tcp_read(struct sock *sk, unsigned char *to,
if (len < 0)
return -EINVAL;
err=verify_area(VERIFY_WRITE,to,len);
if(err)
if (err)
return err;
/* This error should be checked. */
if (sk->state == TCP_LISTEN)
return -ENOTCONN;
......@@ -1327,6 +1326,11 @@ tcp_read(struct sock *sk, unsigned char *to,
sk->inuse = 1;
skb=skb_peek(&sk->rqueue);
peek_seq = sk->copied_seq;
seq = &sk->copied_seq;
if (flags & MSG_PEEK)
seq = &peek_seq;
DPRINTF((DBG_TCP, "tcp_read(sk=%X, to=%X, len=%d, nonblock=%d, flags=%X)\n",
sk, to, len, nonblock, flags));
......@@ -1334,7 +1338,7 @@ tcp_read(struct sock *sk, unsigned char *to,
/* skb->used just checks to see if we've gone all the way around. */
/* While no data, or first data indicates some is missing, or data is used */
while(skb == NULL || skb->used || before(sk->copied_seq+1, skb->h.th->seq)) {
while(skb == NULL || skb->used || before(1+*seq, skb->h.th->seq)) {
DPRINTF((DBG_TCP, "skb = %X:\n", skb));
cleanup_rbuf(sk);
if (sk->err)
......@@ -1413,7 +1417,7 @@ tcp_read(struct sock *sk, unsigned char *to,
}
skb = skb_peek(&sk->rqueue);
if (skb == NULL || before(sk->copied_seq+1, skb->h.th->seq)) {
if (skb == NULL || before(1+*seq, skb->h.th->seq)) {
if(sk->debug)
printk("Read wait sleep\n");
interruptible_sleep_on(sk->sleep);
......@@ -1439,30 +1443,18 @@ tcp_read(struct sock *sk, unsigned char *to,
}
/*
* are we at urgent data?
* are we at urgent data? Stop if we have read anything.
*/
if (sk->urg_data && sk->copied_seq+1 == sk->urg_seq) {
if (sk->urg_data == URG_READ) {
if (copied || (flags & MSG_PEEK)) {
release_sock(sk);
return copied;
}
sk->urg_data = 0;
sk->copied_seq++;
} else {
release_sock(sk);
if (copied)
return copied;
send_sig(SIGURG, current, 0);
return -EINTR;
}
if (copied && sk->urg_data && sk->urg_seq == 1+*seq) {
release_sock(sk);
return copied;
}
/*
* Copy anything from the current block that needs
* to go into the user buffer.
*/
offset = sk->copied_seq+1 - skb->h.th->seq;
offset = *seq - skb->h.th->seq + 1;
if (skb->h.th->syn) offset--;
......@@ -1473,18 +1465,28 @@ tcp_read(struct sock *sk, unsigned char *to,
if (len < used)
used = len;
/* do we have urgent data here? */
if (sk->urg_data && sk->urg_seq - (sk->copied_seq+1) < used)
used = sk->urg_seq - (sk->copied_seq+1);
if (sk->urg_data) {
unsigned long urg_offset = sk->urg_seq - (1 + *seq);
if (urg_offset < used) {
if (!urg_offset) {
if (!(flags & MSG_PEEK))
sk->urg_data = 0;
if (!sk->urginline) {
++*seq;
offset++;
used--;
}
} else
used = offset;
}
}
/* Copy it */
memcpy_tofs(to,((unsigned char *)skb->h.th) +
skb->h.th->doff*4 + offset, used);
copied += used;
len -= used;
to += used;
/* If we were reading the data is 'eaten' */
if (!(flags & MSG_PEEK))
sk->copied_seq += used;
*seq += used;
/*
* Mark this data used if we are really reading it, and we
......@@ -1495,7 +1497,8 @@ tcp_read(struct sock *sk, unsigned char *to,
}
else
{ /* already used this data, must be a retransmit */
skb->used = 1;
if (!(flags & MSG_PEEK))
skb->used = 1;
}
/* Move along a packet */
skb =(struct sk_buff *)skb->next;
......@@ -2717,8 +2720,16 @@ tcp_data(struct sk_buff *skb, struct sock *sk,
/* Now figure out if we can ack anything. */
if ((!dup_dumped && (skb1 == NULL || skb1->acked)) || before(th->seq, sk->acked_seq+1)) {
if (before(th->seq, sk->acked_seq+1)) {
if (after(th->ack_seq, sk->acked_seq))
sk->acked_seq = th->ack_seq;
int newwindow;
if (after(th->ack_seq, sk->acked_seq)) {
newwindow = sk->window -
(th->ack_seq - sk->acked_seq);
if (newwindow < 0)
newwindow = 0;
sk->window = newwindow;
sk->acked_seq = th->ack_seq;
}
skb->acked = 1;
/* When we ack the fin, we turn on the RCV_SHUTDOWN flag. */
......@@ -2733,16 +2744,12 @@ tcp_data(struct sk_buff *skb, struct sock *sk,
if (before(skb2->h.th->seq, sk->acked_seq+1)) {
if (after(skb2->h.th->ack_seq, sk->acked_seq))
{
long old_acked_seq = sk->acked_seq;
newwindow = sk->window -
(skb2->h.th->ack_seq - sk->acked_seq);
if (newwindow < 0)
newwindow = 0;
sk->window = newwindow;
sk->acked_seq = skb2->h.th->ack_seq;
if((int)(sk->acked_seq - old_acked_seq) >0)
{
int new_window=sk->window-sk->acked_seq+
old_acked_seq;
if(new_window<0)
new_window=0;
sk->window = new_window;
}
}
skb2->acked = 1;
......@@ -2845,54 +2852,56 @@ tcp_data(struct sk_buff *skb, struct sock *sk,
}
static int
tcp_urg(struct sock *sk, struct tcphdr *th, unsigned long saddr, unsigned long len)
static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
{
unsigned long ptr;
extern int kill_pg(int pg, int sig, int priv);
extern int kill_proc(int pid, int sig, int priv);
if (!sk->dead)
sk->data_ready(sk,0);
if (sk->urginline) {
th->urg = 0;
th->psh = 1;
return 0;
}
unsigned long ptr = ntohs(th->urg_ptr);
ptr = ntohs(th->urg_ptr);
if (ptr)
ptr--;
ptr += th->seq;
/* is the urgent data in this packet at all? */
if (th->doff*4 + ptr >= len)
return 0;
/* have we already seen and read this? */
if (after(sk->copied_seq+1, th->seq+ptr))
return 0;
/* ignore urgent data that we've already seen and read */
if (after(sk->copied_seq+1, ptr))
return;
/* is this a duplicate? */
if (sk->urg_data && sk->urg_seq == th->seq+ptr)
return 0;
/* do we already have a newer (or duplicate) urgent pointer? */
if (sk->urg_data && !after(ptr, sk->urg_seq))
return;
/*
* We signal the user only for the first urgent data: if urgent
* data already exists, no signal is sent
*/
if (!sk->urg_data || sk->urg_data == URG_READ) {
if (sk->proc != 0) {
if (sk->proc > 0) {
kill_proc(sk->proc, SIGURG, 1);
} else {
kill_pg(-sk->proc, SIGURG, 1);
}
/* tell the world about our new urgent pointer */
if (sk->proc != 0) {
if (sk->proc > 0) {
kill_proc(sk->proc, SIGURG, 1);
} else {
kill_pg(-sk->proc, SIGURG, 1);
}
}
sk->urg_data = URG_NOTYET;
sk->urg_seq = ptr;
}
static inline int tcp_urg(struct sock *sk, struct tcphdr *th,
unsigned long saddr, unsigned long len)
{
unsigned long ptr;
/* check if we get a new urgent pointer */
if (th->urg)
tcp_check_urg(sk,th);
sk->urg_data = 0x100 | *(ptr + th->doff*4 + (unsigned char *) th);
sk->urg_seq = th->seq + ptr;
/* do we wait for any urgent data? */
if (sk->urg_data != URG_NOTYET)
return 0;
/* is the urgent pointer pointing into this packet? */
ptr = sk->urg_seq - th->seq + th->doff*4;
if (ptr >= len)
return 0;
/* ok, got the correct packet, update info */
sk->urg_data = URG_VALID | *(ptr + (unsigned char *) th);
if (!sk->dead)
wake_up_interruptible(sk->sleep);
return 0;
}
......@@ -3389,12 +3398,11 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
return(0);
}
}
if (th->urg) {
if (tcp_urg(sk, th, saddr, len)) {
kfree_skb(skb, FREE_READ);
release_sock(sk);
return(0);
}
if (tcp_urg(sk, th, saddr, len)) {
kfree_skb(skb, FREE_READ);
release_sock(sk);
return(0);
}
if (tcp_data(skb, sk, saddr, len)) {
......
......@@ -30,8 +30,10 @@
#define MIN_WRITE_SPACE 2048
#define TCP_WINDOW_DIFF 2048
/* marks the urg_data as read */
#define URG_READ 0xdeadbeef
/* urg_data states */
#define URG_VALID 0x0100
#define URG_NOTYET 0x0200
#define URG_READ 0x0400
#define TCP_RETR1 7 /*
* This is howmany retries it does before it
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment