Commit beadddbf authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.57

parent 95fda206
VERSION = 1 VERSION = 1
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 56 SUBLEVEL = 57
ARCH = i386 ARCH = i386
......
...@@ -314,17 +314,17 @@ static struct floppy_struct floppy_type[32] = { ...@@ -314,17 +314,17 @@ static struct floppy_struct floppy_type[32] = {
{ 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */ { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */
{ 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */ { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */
{ 1760,11,2,80,0,0x1C,0x09,0xCF,0x6C,"h880" }, /* 20 880KB 5.25" */ { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */
{ 2080,13,2,80,0,0x1C,0x01,0xCF,0x6C,"D1040" }, /* 21 1.04MB 3.5" */ { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */
{ 2240,14,2,80,0,0x1C,0x19,0xCF,0x6C,"D1120" }, /* 22 1.12MB 3.5" */ { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */
{ 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */ { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */
{ 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */ { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */
{ 3840,24,2,80,0,0x1C,0x20,0xCF,0x6C,"H1920" }, /* 25 1.92MB 3.5" */ { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */
{ 6400,40,2,80,0,0x25,0x5B,0xCF,0x6C,"E3200" }, /* 26 3.20MB 3.5" */ { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */
{ 7040,44,2,80,0,0x25,0x5B,0xCF,0x6C,"E3520" }, /* 27 3.52MB 3.5" */ { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */
{ 7680,48,2,80,0,0x25,0x63,0xCF,0x6C,"E3840" }, /* 28 3.84MB 3.5" */ { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */
{ 3680,23,2,80,0,0x1C,0x10,0xCF,0x6C,"H1840" }, /* 29 1.84MB 3.5" */ { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */
{ 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */ { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */
{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
}; };
...@@ -499,6 +499,9 @@ static inline void debugt(char *message) ...@@ -499,6 +499,9 @@ static inline void debugt(char *message)
static int disk_change(int drive) static int disk_change(int drive)
{ {
if(jiffies < DP->select_delay + DRS->select_date)
udelay(20000);
if(inb_p(FD_DIR) & 0x80){ if(inb_p(FD_DIR) & 0x80){
UDRS->flags |= FD_VERIFY; /* verify write protection */ UDRS->flags |= FD_VERIFY; /* verify write protection */
...@@ -526,12 +529,12 @@ static int disk_change(int drive) ...@@ -526,12 +529,12 @@ static int disk_change(int drive)
} }
} }
static int locked=0;
static int set_dor(int fdc, char mask, char data) static int set_dor(int fdc, char mask, char data)
{ {
register unsigned char drive, unit, newdor,olddor; register unsigned char drive, unit, newdor,olddor;
cli(); locked=1;
olddor = FDCS->dor; olddor = FDCS->dor;
newdor = (olddor & mask) | data; newdor = (olddor & mask) | data;
if ( newdor != olddor ){ if ( newdor != olddor ){
...@@ -542,7 +545,7 @@ static int set_dor(int fdc, char mask, char data) ...@@ -542,7 +545,7 @@ static int set_dor(int fdc, char mask, char data)
FDCS->dor = newdor; FDCS->dor = newdor;
outb_p( newdor, FD_DOR); outb_p( newdor, FD_DOR);
} }
sti(); locked=0;
return olddor; return olddor;
} }
...@@ -636,7 +639,10 @@ static void motor_off_callback(unsigned long nr) ...@@ -636,7 +639,10 @@ static void motor_off_callback(unsigned long nr)
{ {
unsigned char mask = ~(0x10 << UNIT(nr)); unsigned char mask = ~(0x10 << UNIT(nr));
set_dor( FDC(nr), mask, 0 ); if(locked)
floppy_off(nr);
else
set_dor( FDC(nr), mask, 0 );
} }
static struct timer_list motor_off_timer[N_DRIVE] = { static struct timer_list motor_off_timer[N_DRIVE] = {
...@@ -657,6 +663,10 @@ static struct timer_list motor_off_timer[N_DRIVE] = { ...@@ -657,6 +663,10 @@ static struct timer_list motor_off_timer[N_DRIVE] = {
static void floppy_off(unsigned int nr) static void floppy_off(unsigned int nr)
{ {
unsigned long volatile delta; unsigned long volatile delta;
register int fdc=FDC(nr);
if( !(FDCS->dor & ( 0x10 << UNIT(nr))))
return;
del_timer(motor_off_timer+nr); del_timer(motor_off_timer+nr);
...@@ -1175,6 +1185,7 @@ static void seek_interrupt(void) ...@@ -1175,6 +1185,7 @@ static void seek_interrupt(void)
) )
DRS->flags &= ~FD_DISK_NEWCHANGE; /* effective seek */ DRS->flags &= ~FD_DISK_NEWCHANGE; /* effective seek */
DRS->track = ST1; DRS->track = ST1;
DRS->select_date = jiffies;
seek_floppy(); seek_floppy();
} }
...@@ -1466,7 +1477,8 @@ static void start_motor(void) ...@@ -1466,7 +1477,8 @@ static void start_motor(void)
mask = 0xfc; mask = 0xfc;
data = UNIT(current_drive); data = UNIT(current_drive);
if ( (FDCS->dor & 0x03) != UNIT(current_drive) ) if ( (FDCS->dor & 0x03) != UNIT(current_drive) ||
!(FDCS->dor & ( 0x10 << UNIT(current_drive) ) ))
/* notes select time if floppy is not yet selected */ /* notes select time if floppy is not yet selected */
DRS->select_date = jiffies; DRS->select_date = jiffies;
...@@ -1489,9 +1501,7 @@ static void start_motor(void) ...@@ -1489,9 +1501,7 @@ static void start_motor(void)
if( raw_cmd.flags & FD_RAW_NO_MOTOR) if( raw_cmd.flags & FD_RAW_NO_MOTOR)
return; return;
if(disk_change(current_drive)) disk_change(current_drive);
twaddle(); /* this clears the dcl on certain drive/controller
* combinations */
return; return;
} }
...@@ -1929,17 +1939,12 @@ static int buffer_chain_size(void) ...@@ -1929,17 +1939,12 @@ static int buffer_chain_size(void)
size = CURRENT->current_nr_sectors << 9; size = CURRENT->current_nr_sectors << 9;
bh = CURRENT->bh; bh = CURRENT->bh;
#ifdef SANITY if(bh){
if ( !bh ){
DPRINT("null request in buffer_chain_size\n");
return size >> 9;
}
#endif
bh = bh->b_reqnext;
while ( bh && bh->b_data == base + size ){
size += bh->b_size;
bh = bh->b_reqnext; bh = bh->b_reqnext;
while ( bh && bh->b_data == base + size ){
size += bh->b_size;
bh = bh->b_reqnext;
}
} }
return size >> 9; return size >> 9;
} }
...@@ -2008,10 +2013,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) ...@@ -2008,10 +2013,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
if ( size > remaining ) if ( size > remaining )
size = remaining; size = remaining;
#ifdef SANITY #ifdef SANITY
if (!bh){
DPRINT("bh=null in copy buffer before copy\n");
break;
}
if (dma_buffer + size > if (dma_buffer + size >
floppy_track_buffer + (max_buffer_sectors << 10) || floppy_track_buffer + (max_buffer_sectors << 10) ||
dma_buffer < floppy_track_buffer ){ dma_buffer < floppy_track_buffer ){
...@@ -2355,8 +2356,6 @@ static void redo_fd_request(void) ...@@ -2355,8 +2356,6 @@ static void redo_fd_request(void)
continue; continue;
} }
if ( DRS->flags & FD_NEED_TWADDLE )
twaddle();
floppy_tq.routine = (void *)(void *) floppy_start; floppy_tq.routine = (void *)(void *) floppy_start;
queue_task(&floppy_tq, &tq_timer); queue_task(&floppy_tq, &tq_timer);
#ifdef DEBUGT #ifdef DEBUGT
...@@ -2506,7 +2505,7 @@ static int raw_cmd_ioctl(int drive, void *param) ...@@ -2506,7 +2505,7 @@ static int raw_cmd_ioctl(int drive, void *param)
current_addr = floppy_track_buffer; current_addr = floppy_track_buffer;
cont = &raw_cmd_cont; cont = &raw_cmd_cont;
CALL(ret=wait_til_done(floppy_start,1)); CALL(ret=wait_til_done(floppy_start,1));
if( inb_p(FD_DIR) & 0x80 ) if( disk_change(current_drive) )
raw_cmd.flags |= FD_RAW_DISK_CHANGE; raw_cmd.flags |= FD_RAW_DISK_CHANGE;
else else
raw_cmd.flags &= ~FD_RAW_DISK_CHANGE; raw_cmd.flags &= ~FD_RAW_DISK_CHANGE;
...@@ -3123,12 +3122,21 @@ void floppy_init(void) ...@@ -3123,12 +3122,21 @@ void floppy_init(void)
static int floppy_grab_irq_and_dma(void) static int floppy_grab_irq_and_dma(void)
{ {
int i;
cli(); cli();
if (usage_count++){ if (usage_count++){
sti(); sti();
return 0; return 0;
} }
sti(); sti();
for(i=0; i< N_FDC; i++){
fdc = i;
reset_fdc_info(1);
outb_p( FDCS->dor, FD_DOR);
}
set_dor(0, ~0, 8); /* avoid immediate interrupt */
if (request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT, "floppy")) { if (request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT, "floppy")) {
DPRINT1("Unable to grab IRQ%d for the floppy driver\n", DPRINT1("Unable to grab IRQ%d for the floppy driver\n",
FLOPPY_IRQ); FLOPPY_IRQ);
...@@ -3146,6 +3154,7 @@ static int floppy_grab_irq_and_dma(void) ...@@ -3146,6 +3154,7 @@ static int floppy_grab_irq_and_dma(void)
static void floppy_release_irq_and_dma(void) static void floppy_release_irq_and_dma(void)
{ {
int i;
cli(); cli();
if (--usage_count){ if (--usage_count){
sti(); sti();
...@@ -3156,10 +3165,7 @@ static void floppy_release_irq_and_dma(void) ...@@ -3156,10 +3165,7 @@ static void floppy_release_irq_and_dma(void)
free_dma(FLOPPY_DMA); free_dma(FLOPPY_DMA);
disable_irq(FLOPPY_IRQ); disable_irq(FLOPPY_IRQ);
free_irq(FLOPPY_IRQ); free_irq(FLOPPY_IRQ);
#ifdef HAVE_2_CONTROLLERS /* switch off dma gates */
/* switch on first controller. for(i=0; i< N_FDC; i++)
* This saves us trouble on the next reboot. */ set_dor(i, ~8, 0);
set_dor(0, ~0, 8 );
set_dor(1, ~8, 0 );
#endif
} }
...@@ -305,7 +305,8 @@ static void identify_intr(void) ...@@ -305,7 +305,8 @@ static void identify_intr(void)
if (unmask_intr[dev]) if (unmask_intr[dev])
sti(); sti();
if (stat & (BUSY_STAT|ERR_STAT)) { if (stat & (BUSY_STAT|ERR_STAT)) {
printk (" hd%c: non-IDE device, CHS=%d/%d/%d\n", dev+'a', printk (" hd%c: non-IDE device, %dMB, CHS=%d/%d/%d\n", dev+'a',
hd_info[dev].cyl*hd_info[dev].head*hd_info[dev].sect / 2048,
hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect); hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect);
if (id != NULL) { if (id != NULL) {
hd_ident_info[dev] = NULL; hd_ident_info[dev] = NULL;
...@@ -796,6 +797,7 @@ static int hd_ioctl(struct inode * inode, struct file * file, ...@@ -796,6 +797,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
{ {
struct hd_geometry *loc = (struct hd_geometry *) arg; struct hd_geometry *loc = (struct hd_geometry *) arg;
int dev, err; int dev, err;
unsigned long flags;
if ((!inode) || (!inode->i_rdev)) if ((!inode) || (!inode->i_rdev))
return -EINVAL; return -EINVAL;
...@@ -845,17 +847,22 @@ static int hd_ioctl(struct inode * inode, struct file * file, ...@@ -845,17 +847,22 @@ static int hd_ioctl(struct inode * inode, struct file * file,
case BLKRRPART: /* Re-read partition tables */ case BLKRRPART: /* Re-read partition tables */
return revalidate_hddisk(inode->i_rdev, 1); return revalidate_hddisk(inode->i_rdev, 1);
case HDIO_SETUNMASKINTR: case HDIO_SETUNMASKINTR: /* obsolete */
if (!suser()) return -EACCES; printk("hd: obsolete syscall: HDIO_SETUNMASKINTR\n");
if (!arg) return -EINVAL; if (!arg) return -EINVAL;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
err = verify_area(VERIFY_READ, (long *) arg, sizeof(long)); err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
if (err) if (err)
return err; return err;
unmask_intr[dev] = get_fs_long((long *) arg); arg = get_fs_long((long *) arg);
/* drop into HDIO_SET_UNMASKINTR */
case HDIO_SET_UNMASKINTR:
if (!suser()) return -EACCES;
if ((arg > 1) || (MINOR(inode->i_rdev) & 0x3F))
return -EINVAL;
unmask_intr[dev] = arg;
return 0; return 0;
case HDIO_GETUNMASKINTR: case HDIO_GET_UNMASKINTR:
if (!arg) return -EINVAL; if (!arg) return -EINVAL;
err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
if (err) if (err)
...@@ -863,7 +870,7 @@ static int hd_ioctl(struct inode * inode, struct file * file, ...@@ -863,7 +870,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
put_fs_long(unmask_intr[dev], (long *) arg); put_fs_long(unmask_intr[dev], (long *) arg);
return 0; return 0;
case HDIO_GETMULTCOUNT: case HDIO_GET_MULTCOUNT:
if (!arg) return -EINVAL; if (!arg) return -EINVAL;
err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
if (err) if (err)
...@@ -871,16 +878,17 @@ static int hd_ioctl(struct inode * inode, struct file * file, ...@@ -871,16 +878,17 @@ static int hd_ioctl(struct inode * inode, struct file * file,
put_fs_long(mult_count[dev], (long *) arg); put_fs_long(mult_count[dev], (long *) arg);
return 0; return 0;
case HDIO_SETMULTCOUNT: case HDIO_SETMULTCOUNT: /* obsolete */
{ printk("hd: obsolete syscall: HDIO_SETMULTCOUNT\n");
unsigned long flags;
if (!suser()) return -EACCES;
if (!arg) return -EINVAL; if (!arg) return -EINVAL;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
err = verify_area(VERIFY_READ, (long *) arg, sizeof(long)); err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
if (err) if (err)
return err; return err;
arg = get_fs_long((long *) arg); arg = get_fs_long((long *) arg);
/* drop into HDIO_SET_MULTCOUNT */
case HDIO_SET_MULTCOUNT:
if (!suser()) return -EACCES;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
save_flags(flags); save_flags(flags);
cli(); /* a prior request might still be in progress */ cli(); /* a prior request might still be in progress */
if (arg > max_mult[dev]) if (arg > max_mult[dev])
...@@ -895,8 +903,8 @@ static int hd_ioctl(struct inode * inode, struct file * file, ...@@ -895,8 +903,8 @@ static int hd_ioctl(struct inode * inode, struct file * file,
} }
restore_flags(flags); restore_flags(flags);
return err; return err;
}
case HDIO_GETIDENTITY: case HDIO_GET_IDENTITY:
if (!arg) return -EINVAL; if (!arg) return -EINVAL;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL; if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
if (hd_ident_info[dev] == NULL) return -ENOMSG; if (hd_ident_info[dev] == NULL) return -ENOMSG;
......
...@@ -126,7 +126,6 @@ int is_read_only(int dev) ...@@ -126,7 +126,6 @@ int is_read_only(int dev)
major = MAJOR(dev); major = MAJOR(dev);
minor = MINOR(dev); minor = MINOR(dev);
if ( major == FLOPPY_MAJOR && floppy_is_wp( minor) ) return 1;
if (major < 0 || major >= MAX_BLKDEV) return 0; if (major < 0 || major >= MAX_BLKDEV) return 0;
return ro_bits[major][minor >> 5] & (1 << (minor & 31)); return ro_bits[major][minor >> 5] & (1 << (minor & 31));
} }
......
...@@ -1106,11 +1106,6 @@ static inline unsigned long try_to_share_buffers(unsigned long address, ...@@ -1106,11 +1106,6 @@ static inline unsigned long try_to_share_buffers(unsigned long address,
return try_to_load_aligned(address, dev, b, size); return try_to_load_aligned(address, dev, b, size);
} }
#define COPYBLK(size,from,to) \
__asm__ __volatile__("rep ; movsl": \
:"c" (((unsigned long) size) >> 2),"S" (from),"D" (to) \
:"cx","di","si")
/* /*
* bread_page reads four buffers into memory at the desired address. It's * bread_page reads four buffers into memory at the desired address. It's
* a function of its own, as there is some speed to be got by reading them * a function of its own, as there is some speed to be got by reading them
...@@ -1140,7 +1135,7 @@ unsigned long bread_page(unsigned long address, dev_t dev, int b[], int size, in ...@@ -1140,7 +1135,7 @@ unsigned long bread_page(unsigned long address, dev_t dev, int b[], int size, in
for (i=0, j=0; j<PAGE_SIZE ; i++, j += size, where += size) { for (i=0, j=0; j<PAGE_SIZE ; i++, j += size, where += size) {
if (bh[i]) { if (bh[i]) {
if (bh[i]->b_uptodate) if (bh[i]->b_uptodate)
COPYBLK(size, (unsigned long) bh[i]->b_data, where); memcpy((void *) where, bh[i]->b_data, size);
brelse(bh[i]); brelse(bh[i]);
} }
} }
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/locks.h> #include <linux/locks.h>
#define clear_block(addr) \
__asm__("cld\n\t" \
"rep\n\t" \
"stosl" \
: \
:"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
void ext_free_block(struct super_block * sb, int block) void ext_free_block(struct super_block * sb, int block)
{ {
struct buffer_head * bh; struct buffer_head * bh;
...@@ -133,7 +126,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next); ...@@ -133,7 +126,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next);
printk("new_block: cannot get block"); printk("new_block: cannot get block");
return 0; return 0;
} }
clear_block(bh->b_data); memset(bh->b_data, 0, BLOCK_SIZE);
bh->b_uptodate = 1; bh->b_uptodate = 1;
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
brelse(bh); brelse(bh);
......
...@@ -55,23 +55,14 @@ ...@@ -55,23 +55,14 @@
*/ */
static int ext_match(int len,const char * name,struct ext_dir_entry * de) static int ext_match(int len,const char * name,struct ext_dir_entry * de)
{ {
register int same;
if (!de || !de->inode || len > EXT_NAME_LEN) if (!de || !de->inode || len > EXT_NAME_LEN)
return 0; return 0;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */ /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
if (!len && (de->name[0]=='.') && (de->name[1]=='\0')) if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
return 1; return 1;
if (len < EXT_NAME_LEN && len != de->name_len) if (len != de->name_len)
return 0; return 0;
__asm__ __volatile__( return !memcmp(name, de->name, len);
"cld\n\t"
"repe ; cmpsb\n\t"
"setz %%al"
:"=a" (same)
:"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
:"cx","di","si");
return same;
} }
/* /*
......
...@@ -233,6 +233,59 @@ static void read_inode(struct inode * inode) ...@@ -233,6 +233,59 @@ static void read_inode(struct inode * inode)
unlock_inode(inode); unlock_inode(inode);
} }
/* POSIX UID/GID verification for setting inode attributes */
int inode_change_ok(struct inode *inode, struct iattr *attr)
{
/* Make sure a caller can chown */
if ((attr->ia_valid & ATTR_UID) &&
(current->fsuid != inode->i_uid ||
attr->ia_uid != inode->i_uid) && !fsuser())
return -EPERM;
/* Make sure caller can chgrp */
if ((attr->ia_valid & ATTR_GID) &&
(!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
!fsuser())
return -EPERM;
/* Make sure a caller can chmod */
if (attr->ia_valid & ATTR_MODE) {
if ((current->fsuid != inode->i_uid) && !fsuser())
return -EPERM;
/* Also check the setgid bit! */
if (!fsuser() && !in_group_p((attr->ia_valid & ATTR_GID) ? attr->ia_gid :
inode->i_gid))
attr->ia_mode &= ~S_ISGID;
}
return 0;
}
/*
* Set the appropriate attributes from an attribute structure into
* the inode structure.
*/
void inode_setattr(struct inode *inode, struct iattr *attr)
{
if (attr->ia_valid & ATTR_UID)
inode->i_uid = attr->ia_uid;
if (attr->ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (attr->ia_valid & ATTR_SIZE)
inode->i_size = attr->ia_size;
if (attr->ia_valid & ATTR_ATIME)
inode->i_atime = attr->ia_atime;
if (attr->ia_valid & ATTR_MTIME)
inode->i_mtime = attr->ia_mtime;
if (attr->ia_valid & ATTR_CTIME)
inode->i_ctime = attr->ia_ctime;
if (attr->ia_valid & ATTR_MODE) {
inode->i_mode = attr->ia_mode;
if (!fsuser() && !in_group_p(inode->i_gid))
inode->i_mode &= ~S_ISGID;
}
}
/* /*
* notify_change is called for inode-changing operations such as * notify_change is called for inode-changing operations such as
* chown, chmod, utime, and truncate. It is guaranteed (unlike * chown, chmod, utime, and truncate. It is guaranteed (unlike
...@@ -241,11 +294,18 @@ static void read_inode(struct inode * inode) ...@@ -241,11 +294,18 @@ static void read_inode(struct inode * inode)
* NFS uses this to get the authentication correct. -- jrs * NFS uses this to get the authentication correct. -- jrs
*/ */
int notify_change(int flags, struct inode * inode) int notify_change(struct inode * inode, struct iattr *attr)
{ {
int retval;
if (inode->i_sb && inode->i_sb->s_op && if (inode->i_sb && inode->i_sb->s_op &&
inode->i_sb->s_op->notify_change) inode->i_sb->s_op->notify_change)
return inode->i_sb->s_op->notify_change(flags, inode); return inode->i_sb->s_op->notify_change(inode, attr);
if ((retval = inode_change_ok(inode, attr)) != 0)
return retval;
inode_setattr(inode, attr);
return 0; return 0;
} }
......
...@@ -26,33 +26,28 @@ ...@@ -26,33 +26,28 @@
*/ */
static int isofs_match(int len,const char * name, char * compare, int dlen) static int isofs_match(int len,const char * name, char * compare, int dlen)
{ {
register int same; if (!compare)
return 0;
if (!compare) return 0;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */ /* check special "." and ".." files */
if (!len && (compare[0]==0) && (dlen==1)) if (dlen == 1) {
return 1; /* "." */
if (compare[0] = 0) {
if (compare[0]==0 && dlen==1 && len == 1) if (!len)
compare = "."; return 1;
if (compare[0]==1 && dlen==1 && len == 2) { compare = ".";
compare = ".."; } else if (compare[0] == 1) {
dlen = 2; compare = "..";
}; dlen = 2;
}
}
#if 0 #if 0
if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen); if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen);
#endif #endif
if (dlen != len) if (dlen != len)
return 0; return 0;
__asm__ __volatile__( return !memcmp(name, compare, len);
"cld\n\t"
"repe ; cmpsb\n\t"
"setz %%al"
:"=a" (same)
:"0" (0),"S" ((long) name),"D" ((long) compare),"c" (len)
:"cx","di","si");
return same;
} }
/* /*
......
...@@ -14,28 +14,6 @@ ...@@ -14,28 +14,6 @@
#include <asm/bitops.h> #include <asm/bitops.h>
#define clear_block(addr) \
__asm__("cld\n\t" \
"rep\n\t" \
"stosl" \
: \
:"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
#define find_first_zero(addr) ({ \
int __res; \
__asm__("cld\n" \
"1:\tlodsl\n\t" \
"notl %%eax\n\t" \
"bsfl %%eax,%%edx\n\t" \
"jne 2f\n\t" \
"addl $32,%%ecx\n\t" \
"cmpl $8192,%%ecx\n\t" \
"jl 1b\n\t" \
"xorl %%edx,%%edx\n" \
"2:\taddl %%edx,%%ecx" \
:"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
__res;})
static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }; static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
static unsigned long count_used(struct buffer_head *map[], unsigned numblocks, static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
...@@ -110,7 +88,7 @@ int minix_new_block(struct super_block * sb) ...@@ -110,7 +88,7 @@ int minix_new_block(struct super_block * sb)
j = 8192; j = 8192;
for (i=0 ; i<8 ; i++) for (i=0 ; i<8 ; i++)
if ((bh=sb->u.minix_sb.s_zmap[i]) != NULL) if ((bh=sb->u.minix_sb.s_zmap[i]) != NULL)
if ((j=find_first_zero(bh->b_data))<8192) if ((j=find_first_zero_bit(bh->b_data, 8192)) < 8192)
break; break;
if (i>=8 || !bh || j>=8192) if (i>=8 || !bh || j>=8192)
return 0; return 0;
...@@ -127,7 +105,7 @@ int minix_new_block(struct super_block * sb) ...@@ -127,7 +105,7 @@ int minix_new_block(struct super_block * sb)
printk("new_block: cannot get block"); printk("new_block: cannot get block");
return 0; return 0;
} }
clear_block(bh->b_data); memset(bh->b_data, 0, BLOCK_SIZE);
bh->b_uptodate = 1; bh->b_uptodate = 1;
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
brelse(bh); brelse(bh);
...@@ -193,7 +171,7 @@ struct inode * minix_new_inode(const struct inode * dir) ...@@ -193,7 +171,7 @@ struct inode * minix_new_inode(const struct inode * dir)
j = 8192; j = 8192;
for (i=0 ; i<8 ; i++) for (i=0 ; i<8 ; i++)
if ((bh = inode->i_sb->u.minix_sb.s_imap[i]) != NULL) if ((bh = inode->i_sb->u.minix_sb.s_imap[i]) != NULL)
if ((j=find_first_zero(bh->b_data))<8192) if ((j=find_first_zero_bit(bh->b_data, 8192)) < 8192)
break; break;
if (!bh || j >= 8192) { if (!bh || j >= 8192) {
iput(inode); iput(inode);
......
...@@ -86,13 +86,13 @@ static int minix_readdir(struct inode * inode, struct file * filp, ...@@ -86,13 +86,13 @@ static int minix_readdir(struct inode * inode, struct file * filp,
filp->f_pos += info->s_dirsize; filp->f_pos += info->s_dirsize;
retry: retry:
if (de->inode) { if (de->inode) {
version = inode->i_version;
for (i = 0; i < info->s_namelen; i++) for (i = 0; i < info->s_namelen; i++)
if ((c = de->name[i]) != 0) if ((c = de->name[i]) != 0)
put_fs_byte(c,i+dirent->d_name); put_fs_byte(c,i+dirent->d_name);
else else
break; break;
if (i) { if (i) {
version = inode->i_version;
put_fs_long(de->inode,&dirent->d_ino); put_fs_long(de->inode,&dirent->d_ino);
put_fs_byte(0,i+dirent->d_name); put_fs_byte(0,i+dirent->d_name);
put_fs_word(i,&dirent->d_reclen); put_fs_word(i,&dirent->d_reclen);
......
...@@ -23,15 +23,11 @@ ...@@ -23,15 +23,11 @@
static inline int namecompare(int len, int maxlen, static inline int namecompare(int len, int maxlen,
const char * name, const char * buffer) const char * name, const char * buffer)
{ {
if (len >= maxlen || !buffer[len]) { if (len > maxlen)
unsigned char same; return 0;
__asm__("repe ; cmpsb ; setz %0" if (len < maxlen && buffer[len])
:"=q" (same) return 0;
:"S" ((long) name),"D" ((long) buffer),"c" (len) return !memcmp(name, buffer, len);
:"cx","di","si");
return same;
}
return 0;
} }
/* /*
......
...@@ -420,28 +420,34 @@ void msdos_write_inode(struct inode *inode) ...@@ -420,28 +420,34 @@ void msdos_write_inode(struct inode *inode)
} }
int msdos_notify_change(int flags,struct inode *inode) int msdos_notify_change(struct inode * inode,struct iattr * attr)
{ {
int error; int error;
error = 0; error = inode_change_ok(inode, attr);
if ((flags & NOTIFY_UIDGID) && (inode->i_uid != MSDOS_SB(inode->i_sb)-> if (error)
fs_uid || inode->i_gid != MSDOS_SB(inode->i_sb)->fs_gid)) { return error;
inode->i_uid = MSDOS_SB(inode->i_sb)->fs_uid;
inode->i_gid = MSDOS_SB(inode->i_sb)->fs_gid; if (((attr->ia_valid & ATTR_UID) &&
(attr->ia_uid != MSDOS_SB(inode->i_sb)->fs_uid)) ||
((attr->ia_valid & ATTR_GID) &&
(attr->ia_gid != MSDOS_SB(inode->i_sb)->fs_gid)) ||
((attr->ia_valid & ATTR_MODE) &&
(attr->ia_mode & ~MSDOS_VALID_MODE)))
error = -EPERM; error = -EPERM;
}
if (!(flags & NOTIFY_MODE)) if (error)
return MSDOS_SB(inode->i_sb)->quiet ? 0 : error; return MSDOS_SB(inode->i_sb)->quiet ? 0 : error;
if (inode->i_mode & ~MSDOS_VALID_MODE) {
inode->i_mode &= MSDOS_VALID_MODE; inode_setattr(inode, attr);
error = -EPERM;
}
if (IS_NOEXEC(inode) && !S_ISDIR(inode->i_mode)) if (IS_NOEXEC(inode) && !S_ISDIR(inode->i_mode))
inode->i_mode &= S_IFMT | S_IRUGO | S_IWUGO; inode->i_mode &= S_IFMT | S_IRUGO | S_IWUGO;
else inode->i_mode |= S_IXUGO; else
inode->i_mode |= S_IXUGO;
inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU
& ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) & & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
~MSDOS_SB(inode->i_sb)->fs_umask; ~MSDOS_SB(inode->i_sb)->fs_umask;
return MSDOS_SB(inode->i_sb)->quiet ? 0 : error; return 0;
} }
...@@ -373,6 +373,7 @@ int open_namei(const char * pathname, int flag, int mode, ...@@ -373,6 +373,7 @@ int open_namei(const char * pathname, int flag, int mode,
iput(inode); iput(inode);
return -EACCES; return -EACCES;
} }
flag &= ~O_TRUNC;
} else { } else {
if (IS_RDONLY(inode) && (flag & 2)) { if (IS_RDONLY(inode) && (flag & 2)) {
iput(inode); iput(inode);
...@@ -404,14 +405,18 @@ int open_namei(const char * pathname, int flag, int mode, ...@@ -404,14 +405,18 @@ int open_namei(const char * pathname, int flag, int mode,
return -EPERM; return -EPERM;
} }
if (flag & O_TRUNC) { if (flag & O_TRUNC) {
inode->i_size = 0; struct iattr newattrs;
if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode); newattrs.ia_size = 0;
if ((error = notify_change(NOTIFY_SIZE, inode))) { newattrs.ia_valid = ATTR_SIZE;
iput(inode); if ((error = notify_change(inode, &newattrs))) {
return error; iput(inode);
} return error;
inode->i_dirt = 1; }
inode->i_size = 0;
if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode);
inode->i_dirt = 1;
} }
*res_inode = inode; *res_inode = inode;
return 0; return 0;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
extern int close_fp(struct file *filp, unsigned int fd); extern int close_fp(struct file *filp, unsigned int fd);
static int nfs_notify_change(int, struct inode *); static int nfs_notify_change(struct inode *, struct iattr *);
static void nfs_put_inode(struct inode *); static void nfs_put_inode(struct inode *);
static void nfs_put_super(struct super_block *); static void nfs_put_super(struct super_block *);
static void nfs_statfs(struct super_block *, struct statfs *); static void nfs_statfs(struct super_block *, struct statfs *);
...@@ -193,36 +193,44 @@ struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle, ...@@ -193,36 +193,44 @@ struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
return inode; return inode;
} }
int nfs_notify_change(int flags, struct inode *inode) int nfs_notify_change(struct inode *inode, struct iattr *attr)
{ {
struct nfs_sattr sattr; struct nfs_sattr sattr;
struct nfs_fattr fattr; struct nfs_fattr fattr;
int error; int error;
if (flags & NOTIFY_MODE) if (attr->ia_valid & ATTR_MODE)
sattr.mode = inode->i_mode; sattr.mode = attr->ia_mode;
else else
sattr.mode = (unsigned) -1; sattr.mode = (unsigned) -1;
if (flags & NOTIFY_UIDGID) {
sattr.uid = inode->i_uid; if (attr->ia_valid & ATTR_UID)
sattr.gid = inode->i_gid; sattr.uid = attr->ia_uid;
}
else else
sattr.uid = sattr.gid = (unsigned) -1; sattr.uid = (unsigned) -1;
if (flags & NOTIFY_SIZE)
sattr.size = S_ISREG(inode->i_mode) ? inode->i_size : -1; if (attr->ia_valid & ATTR_GID)
sattr.gid = attr->ia_gid;
else
sattr.gid = (unsigned) -1;
if (attr->ia_valid & ATTR_SIZE)
sattr.size = S_ISREG(inode->i_mode) ? attr->ia_size : -1;
else else
sattr.size = (unsigned) -1; sattr.size = (unsigned) -1;
if (flags & NOTIFY_TIME) {
sattr.mtime.seconds = inode->i_mtime; if (attr->ia_valid & ATTR_MTIME) {
sattr.mtime.seconds = attr->ia_mtime;
sattr.mtime.useconds = 0; sattr.mtime.useconds = 0;
sattr.atime.seconds = inode->i_atime; } else
sattr.atime.useconds = 0;
}
else {
sattr.mtime.seconds = sattr.mtime.useconds = (unsigned) -1; sattr.mtime.seconds = sattr.mtime.useconds = (unsigned) -1;
if (attr->ia_valid & ATTR_ATIME) {
sattr.atime.seconds = attr->ia_atime;
sattr.atime.useconds = 0;
} else
sattr.atime.seconds = sattr.atime.useconds = (unsigned) -1; sattr.atime.seconds = sattr.atime.useconds = (unsigned) -1;
}
error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode), error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode),
&sattr, &fattr); &sattr, &fattr);
if (!error) if (!error)
...@@ -230,4 +238,3 @@ int nfs_notify_change(int flags, struct inode *inode) ...@@ -230,4 +238,3 @@ int nfs_notify_change(int flags, struct inode *inode)
inode->i_dirt = 0; inode->i_dirt = 0;
return error; return error;
} }
...@@ -69,6 +69,7 @@ asmlinkage int sys_truncate(const char * path, unsigned int length) ...@@ -69,6 +69,7 @@ asmlinkage int sys_truncate(const char * path, unsigned int length)
{ {
struct inode * inode; struct inode * inode;
int error; int error;
struct iattr newattrs;
error = namei(path,&inode); error = namei(path,&inode);
if (error) if (error)
...@@ -85,12 +86,13 @@ asmlinkage int sys_truncate(const char * path, unsigned int length) ...@@ -85,12 +86,13 @@ asmlinkage int sys_truncate(const char * path, unsigned int length)
iput(inode); iput(inode);
return -EPERM; return -EPERM;
} }
inode->i_size = length; inode->i_size = newattrs.ia_size = length;
if (inode->i_op && inode->i_op->truncate) if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode); inode->i_op->truncate(inode);
inode->i_ctime = inode->i_mtime = CURRENT_TIME; newattrs.ia_ctime = newattrs.ia_mtime = CURRENT_TIME;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME;
inode->i_dirt = 1; inode->i_dirt = 1;
error = notify_change(NOTIFY_SIZE, inode); error = notify_change(inode, &newattrs);
iput(inode); iput(inode);
return error; return error;
} }
...@@ -99,6 +101,7 @@ asmlinkage int sys_ftruncate(unsigned int fd, unsigned int length) ...@@ -99,6 +101,7 @@ asmlinkage int sys_ftruncate(unsigned int fd, unsigned int length)
{ {
struct inode * inode; struct inode * inode;
struct file * file; struct file * file;
struct iattr newattrs;
if (fd >= NR_OPEN || !(file = current->files->fd[fd])) if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF; return -EBADF;
...@@ -108,12 +111,13 @@ asmlinkage int sys_ftruncate(unsigned int fd, unsigned int length) ...@@ -108,12 +111,13 @@ asmlinkage int sys_ftruncate(unsigned int fd, unsigned int length)
return -EACCES; return -EACCES;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return -EPERM; return -EPERM;
inode->i_size = length; inode->i_size = newattrs.ia_size = length;
if (inode->i_op && inode->i_op->truncate) if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode); inode->i_op->truncate(inode);
inode->i_ctime = inode->i_mtime = CURRENT_TIME; newattrs.ia_ctime = newattrs.ia_mtime = CURRENT_TIME;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME;
inode->i_dirt = 1; inode->i_dirt = 1;
return notify_change(NOTIFY_SIZE, inode); return notify_change(inode, &newattrs);
} }
/* If times==NULL, set access and modification to current time, /* If times==NULL, set access and modification to current time,
...@@ -125,6 +129,7 @@ asmlinkage int sys_utime(char * filename, struct utimbuf * times) ...@@ -125,6 +129,7 @@ asmlinkage int sys_utime(char * filename, struct utimbuf * times)
struct inode * inode; struct inode * inode;
long actime,modtime; long actime,modtime;
int error; int error;
struct iattr newattrs;
error = namei(filename,&inode); error = namei(filename,&inode);
if (error) if (error)
...@@ -140,19 +145,20 @@ asmlinkage int sys_utime(char * filename, struct utimbuf * times) ...@@ -140,19 +145,20 @@ asmlinkage int sys_utime(char * filename, struct utimbuf * times)
} }
actime = get_fs_long((unsigned long *) &times->actime); actime = get_fs_long((unsigned long *) &times->actime);
modtime = get_fs_long((unsigned long *) &times->modtime); modtime = get_fs_long((unsigned long *) &times->modtime);
inode->i_ctime = CURRENT_TIME; newattrs.ia_ctime = CURRENT_TIME;
} else { } else {
if ((current->fsuid != inode->i_uid) && if ((current->fsuid != inode->i_uid) &&
!permission(inode,MAY_WRITE)) { !permission(inode,MAY_WRITE)) {
iput(inode); iput(inode);
return -EACCES; return -EACCES;
} }
actime = modtime = inode->i_ctime = CURRENT_TIME; actime = modtime = newattrs.ia_ctime = CURRENT_TIME;
} }
inode->i_atime = actime; newattrs.ia_atime = actime;
inode->i_mtime = modtime; newattrs.ia_mtime = modtime;
newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
inode->i_dirt = 1; inode->i_dirt = 1;
error = notify_change(NOTIFY_TIME, inode); error = notify_change(inode, &newattrs);
iput(inode); iput(inode);
return error; return error;
} }
...@@ -249,49 +255,43 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode) ...@@ -249,49 +255,43 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
{ {
struct inode * inode; struct inode * inode;
struct file * file; struct file * file;
struct iattr newattrs;
if (fd >= NR_OPEN || !(file = current->files->fd[fd])) if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF; return -EBADF;
if (!(inode = file->f_inode)) if (!(inode = file->f_inode))
return -ENOENT; return -ENOENT;
if ((current->fsuid != inode->i_uid) && !fsuser())
return -EPERM;
if (IS_RDONLY(inode)) if (IS_RDONLY(inode))
return -EROFS; return -EROFS;
if (mode == (mode_t) -1) if (mode == (mode_t) -1)
mode = inode->i_mode; mode = inode->i_mode;
inode->i_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
if (!fsuser() && !in_group_p(inode->i_gid)) newattrs.ia_ctime = CURRENT_TIME;
inode->i_mode &= ~S_ISGID; newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1; inode->i_dirt = 1;
return notify_change(NOTIFY_MODE, inode); return notify_change(inode, &newattrs);
} }
asmlinkage int sys_chmod(const char * filename, mode_t mode) asmlinkage int sys_chmod(const char * filename, mode_t mode)
{ {
struct inode * inode; struct inode * inode;
int error; int error;
struct iattr newattrs;
error = namei(filename,&inode); error = namei(filename,&inode);
if (error) if (error)
return error; return error;
if ((current->fsuid != inode->i_uid) && !fsuser()) {
iput(inode);
return -EPERM;
}
if (IS_RDONLY(inode)) { if (IS_RDONLY(inode)) {
iput(inode); iput(inode);
return -EROFS; return -EROFS;
} }
if (mode == (mode_t) -1) if (mode == (mode_t) -1)
mode = inode->i_mode; mode = inode->i_mode;
inode->i_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
if (!fsuser() && !in_group_p(inode->i_gid)) newattrs.ia_ctime = CURRENT_TIME;
inode->i_mode &= ~S_ISGID; newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1; inode->i_dirt = 1;
error = notify_change(NOTIFY_MODE, inode); error = notify_change(inode, &newattrs);
iput(inode); iput(inode);
return error; return error;
} }
...@@ -300,9 +300,7 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group) ...@@ -300,9 +300,7 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
{ {
struct inode * inode; struct inode * inode;
struct file * file; struct file * file;
uid_t old_user; struct iattr newattrs;
gid_t old_group;
int notify_flag = 0;
if (fd >= NR_OPEN || !(file = current->files->fd[fd])) if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF; return -EBADF;
...@@ -310,45 +308,37 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group) ...@@ -310,45 +308,37 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
return -ENOENT; return -ENOENT;
if (IS_RDONLY(inode)) if (IS_RDONLY(inode))
return -EROFS; return -EROFS;
old_user = inode->i_uid;
old_group = inode->i_gid;
if (user == (uid_t) -1) if (user == (uid_t) -1)
user = inode->i_uid; user = inode->i_uid;
if (group == (gid_t) -1) if (group == (gid_t) -1)
group = inode->i_gid; group = inode->i_gid;
if ((current->fsuid == inode->i_uid && user == inode->i_uid && newattrs.ia_uid = user;
(in_group_p(group) || group == inode->i_gid)) || newattrs.ia_gid = group;
fsuser()) { newattrs.ia_ctime = CURRENT_TIME;
inode->i_uid = user; newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
inode->i_gid = group; /*
/* * If the owner has been changed, remove the setuid bit
* If the owner has been changed, remove the setuid bit */
*/ if (user != inode->i_uid && inode->i_mode & S_ISUID) {
if (old_user != inode->i_uid && inode->i_mode & S_ISUID) { newattrs.ia_mode = inode->i_mode & ~S_ISUID;
inode->i_mode &= ~S_ISUID; newattrs.ia_valid |= ATTR_MODE;
notify_flag = NOTIFY_MODE; }
} /*
/* * If the group has been changed, remove the setgid bit
* If the group has been changed, remove the setgid bit */
*/ if (group != inode->i_gid && inode->i_mode & S_ISGID) {
if (old_group != inode->i_gid && inode->i_mode & S_ISGID) { newattrs.ia_mode = inode->i_mode & ~S_ISGID;
inode->i_mode &= ~S_ISGID; newattrs.ia_valid |= ATTR_MODE;
notify_flag = NOTIFY_MODE;
}
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
return notify_change(notify_flag | NOTIFY_UIDGID, inode);
} }
return -EPERM; inode->i_dirt = 1;
return notify_change(inode, &newattrs);
} }
asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group) asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
{ {
struct inode * inode; struct inode * inode;
int error; int error;
uid_t old_user; struct iattr newattrs;
gid_t old_group;
int notify_flag = 0;
error = lnamei(filename,&inode); error = lnamei(filename,&inode);
if (error) if (error)
...@@ -357,39 +347,32 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group) ...@@ -357,39 +347,32 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
iput(inode); iput(inode);
return -EROFS; return -EROFS;
} }
old_user = inode->i_uid;
old_group = inode->i_uid;
if (user == (uid_t) -1) if (user == (uid_t) -1)
user = inode->i_uid; user = inode->i_uid;
if (group == (gid_t) -1) if (group == (gid_t) -1)
group = inode->i_gid; group = inode->i_gid;
if ((current->fsuid == inode->i_uid && user == inode->i_uid && newattrs.ia_uid = user;
(in_group_p(group) || group == inode->i_gid)) || newattrs.ia_gid = group;
fsuser()) { newattrs.ia_ctime = CURRENT_TIME;
inode->i_uid = user; newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
inode->i_gid = group; /*
/* * If the owner has been changed, remove the setuid bit
* If the owner has been changed, remove the setuid bit */
*/ if (user != inode->i_uid && inode->i_mode & S_ISUID) {
if (old_user != inode->i_uid && inode->i_mode & S_ISUID) { newattrs.ia_mode = inode->i_mode & ~S_ISUID;
inode->i_mode &= ~S_ISUID; newattrs.ia_valid |= ATTR_MODE;
notify_flag = NOTIFY_MODE; }
} /*
/* * If the group has been changed, remove the setgid bit
* If the group has been changed, remove the setgid bit */
*/ if (group != inode->i_gid && inode->i_mode & S_ISGID) {
if (old_group != inode->i_gid && inode->i_mode & S_ISGID) { newattrs.ia_mode = inode->i_mode & ~S_ISGID;
inode->i_mode &= ~S_ISGID; newattrs.ia_valid |= ATTR_MODE;
notify_flag = NOTIFY_MODE;
}
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
error = notify_change(notify_flag | NOTIFY_UIDGID, inode);
iput(inode);
return error;
} }
inode->i_dirt = 1;
error = notify_change(inode, &newattrs);
iput(inode); iput(inode);
return -EPERM; return(error);
} }
/* /*
......
...@@ -69,8 +69,6 @@ static struct proc_dir_entry base_dir[] = { ...@@ -69,8 +69,6 @@ static struct proc_dir_entry base_dir[] = {
int proc_match(int len,const char * name,struct proc_dir_entry * de) int proc_match(int len,const char * name,struct proc_dir_entry * de)
{ {
register int same;
if (!de || !de->low_ino) if (!de || !de->low_ino)
return 0; return 0;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */ /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
...@@ -78,14 +76,7 @@ int proc_match(int len,const char * name,struct proc_dir_entry * de) ...@@ -78,14 +76,7 @@ int proc_match(int len,const char * name,struct proc_dir_entry * de)
return 1; return 1;
if (de->namelen != len) if (de->namelen != len)
return 0; return 0;
__asm__ __volatile__( return !memcmp(name, de->name, len);
"cld\n\t"
"repe ; cmpsb\n\t"
"setz %%al"
:"=a" (same)
:"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
:"cx","di","si");
return same;
} }
static int proc_lookupbase(struct inode * dir,const char * name, int len, static int proc_lookupbase(struct inode * dir,const char * name, int len,
......
...@@ -159,8 +159,10 @@ asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count) ...@@ -159,8 +159,10 @@ asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count)
* the setgid bits * the setgid bits
*/ */
if (written > 0 && !suser() && (inode->i_mode & (S_ISUID | S_ISGID))) { if (written > 0 && !suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
inode->i_mode &= ~(S_ISUID | S_ISGID); struct iattr newattrs;
notify_change (NOTIFY_MODE, inode); newattrs.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
newattrs.ia_valid = ATTR_MODE;
notify_change(inode, &newattrs);
} }
return written; return written;
} }
...@@ -29,16 +29,6 @@ ...@@ -29,16 +29,6 @@
sb->sv_sbd->s_tfree = *sb->sv_sb_total_free_blocks sb->sv_sbd->s_tfree = *sb->sv_sb_total_free_blocks
but we nevertheless keep it up to date. */ but we nevertheless keep it up to date. */
extern inline void memzero (void * s, size_t count)
{
__asm__("cld\n\t"
"rep\n\t"
"stosl"
:
:"a" (0),"D" (s),"c" (count/4)
:"cx","di","memory");
}
void sysv_free_block(struct super_block * sb, unsigned int block) void sysv_free_block(struct super_block * sb, unsigned int block)
{ {
struct buffer_head * bh; struct buffer_head * bh;
...@@ -115,7 +105,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block) ...@@ -115,7 +105,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block)
return; return;
} }
bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits); bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
memzero(bh_data, sb->sv_block_size); memset(bh_data, 0, sb->sv_block_size);
/* this implies ((struct ..._freelist_chunk *) bh_data)->flc_count = 0; */ /* this implies ((struct ..._freelist_chunk *) bh_data)->flc_count = 0; */
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
bh->b_uptodate = 1; bh->b_uptodate = 1;
...@@ -228,7 +218,7 @@ int sysv_new_block(struct super_block * sb) ...@@ -228,7 +218,7 @@ int sysv_new_block(struct super_block * sb)
unlock_super(sb); unlock_super(sb);
return 0; return 0;
} }
memzero(bh_data,sb->sv_block_size); memset(bh_data, 0, sb->sv_block_size);
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
bh->b_uptodate = 1; bh->b_uptodate = 1;
brelse(bh); brelse(bh);
......
...@@ -715,9 +715,16 @@ void sysv_read_inode(struct inode * inode) ...@@ -715,9 +715,16 @@ void sysv_read_inode(struct inode * inode)
} }
/* To avoid inconsistencies between inodes in memory and inodes on disk. */ /* To avoid inconsistencies between inodes in memory and inodes on disk. */
extern int sysv_notify_change(int flags, struct inode *inode) extern int sysv_notify_change(struct inode *inode, struct iattr *attr)
{ {
if (flags & NOTIFY_MODE) int error;
if ((error = inode_change_ok(inode, attr)) != 0)
return error;
inode_setattr(inode, attr);
if (attr->ia_valid & ATTR_MODE)
if (inode->i_sb->sv_kludge_symlinks) if (inode->i_sb->sv_kludge_symlinks)
if (inode->i_mode == COH_KLUDGE_SYMLINK_MODE) { if (inode->i_mode == COH_KLUDGE_SYMLINK_MODE) {
inode->i_mode = COH_KLUDGE_NOT_SYMLINK; inode->i_mode = COH_KLUDGE_NOT_SYMLINK;
......
...@@ -25,16 +25,11 @@ ...@@ -25,16 +25,11 @@
static inline int namecompare(int len, int maxlen, static inline int namecompare(int len, int maxlen,
const char * name, const char * buffer) const char * name, const char * buffer)
{ {
if (len >= maxlen || !buffer[len]) { if (len > maxlen)
unsigned char same; return 0;
__asm__("repe ; cmpsb ; setz %0" if (len < maxlen && buffer[len])
:"=q" (same) return 0;
:"S" ((long) name),"D" ((long) buffer),"c" (len) return !memcmp(name, buffer, len);
:"cx","di","si");
return same;
}
/* if (len<maxlen && buffer[len]) then buffer is longer than name */
return 0;
} }
/* /*
......
...@@ -257,13 +257,24 @@ void UMSDOS_read_inode(struct inode *inode) ...@@ -257,13 +257,24 @@ void UMSDOS_read_inode(struct inode *inode)
*/ */
void UMSDOS_write_inode(struct inode *inode) void UMSDOS_write_inode(struct inode *inode)
{ {
struct iattr newattrs;
PRINTK (("UMSDOS_write_inode emd %d\n",inode->u.umsdos_i.i_emd_owner)); PRINTK (("UMSDOS_write_inode emd %d\n",inode->u.umsdos_i.i_emd_owner));
msdos_write_inode(inode); msdos_write_inode(inode);
UMSDOS_notify_change (NOTIFY_TIME,inode); newattrs.ia_mtime = inode->i_mtime;
newattrs.ia_atime = inode->i_atime;
newattrs.ia_ctime = inode->i_ctime;
newattrs.ia_valid = ATTR_MTIME | ATTR_ATIME | ATTR_CTIME;
UMSDOS_notify_change (inode, &newattrs);
} }
int UMSDOS_notify_change (int flags, struct inode *inode)
int UMSDOS_notify_change(struct inode *inode, struct iattr *attr)
{ {
int ret = 0; int ret = 0;
if ((ret = inode_change_ok(inode, attr)) != 0)
return ret;
if (inode->i_nlink > 0){ if (inode->i_nlink > 0){
/* #Specification: notify_change / i_nlink > 0 /* #Specification: notify_change / i_nlink > 0
notify change is only done for inode with nlink > 0. An inode notify change is only done for inode with nlink > 0. An inode
...@@ -306,25 +317,24 @@ int UMSDOS_notify_change (int flags, struct inode *inode) ...@@ -306,25 +317,24 @@ int UMSDOS_notify_change (int flags, struct inode *inode)
ret = umsdos_emd_dir_read (emd_owner,&filp,(char*)&entry ret = umsdos_emd_dir_read (emd_owner,&filp,(char*)&entry
,UMSDOS_REC_SIZE); ,UMSDOS_REC_SIZE);
if (ret == 0){ if (ret == 0){
if (flags & NOTIFY_UIDGID){ if (attr->ia_valid & ATTR_UID)
entry.uid = inode->i_uid; entry.uid = attr->ia_uid;
entry.gid = inode->i_gid; if (attr->ia_valid & ATTR_GID)
/* Remove those flags msdos don't like */ entry.gid = attr->ia_gid;
flags &= ~NOTIFY_UIDGID; if (attr->ia_valid & ATTR_MODE)
} entry.mode = attr->ia_mode;
if (flags & NOTIFY_MODE){ if (attr->ia_valid & ATTR_ATIME)
entry.mode = inode->i_mode; entry.atime = attr->ia_atime;
flags &= ~NOTIFY_MODE; if (attr->ia_valid & ATTR_MTIME)
} entry.mtime = attr->ia_mtime;
if (flags & NOTIFY_TIME){ if (attr->ia_valid & ATTR_CTIME)
entry.atime = inode->i_atime; entry.ctime = attr->ia_ctime;
entry.mtime = inode->i_mtime;
entry.ctime = inode->i_ctime;
}
entry.nlink = inode->i_nlink; entry.nlink = inode->i_nlink;
filp.f_pos = inode->u.umsdos_i.pos; filp.f_pos = inode->u.umsdos_i.pos;
ret = umsdos_emd_dir_write (emd_owner,&filp,(char*)&entry ret = umsdos_emd_dir_write (emd_owner,&filp,(char*)&entry
,UMSDOS_REC_SIZE); ,UMSDOS_REC_SIZE);
PRINTK (("notify pos %d ret %d nlink %d " PRINTK (("notify pos %d ret %d nlink %d "
,inode->u.umsdos_i.pos ,inode->u.umsdos_i.pos
,ret,entry.nlink)); ,ret,entry.nlink));
...@@ -332,20 +342,14 @@ int UMSDOS_notify_change (int flags, struct inode *inode) ...@@ -332,20 +342,14 @@ int UMSDOS_notify_change (int flags, struct inode *inode)
notify_change operation are done only on the notify_change operation are done only on the
EMD file. The msdos fs is not even called. EMD file. The msdos fs is not even called.
*/ */
#if 0
if (ret == 0
&& (S_ISDIR(inode->i_mode)
|| S_ISREG(inode->i_mode))){
ret = msdos_notify_change(flags, inode);
printk ("msdos_notify %x %d",inode,ret);
}
#endif
} }
iput (emd_owner); iput (emd_owner);
} }
PRINTK (("\n")); PRINTK (("\n"));
} }
} }
if (ret == 0)
inode_setattr(inode, attr);
return ret; return ret;
} }
......
...@@ -618,7 +618,7 @@ int UMSDOS_link ( ...@@ -618,7 +618,7 @@ int UMSDOS_link (
} }
if (ret == 0){ if (ret == 0){
oldinode->i_nlink++; oldinode->i_nlink++;
ret = UMSDOS_notify_change (0,oldinode); ret = UMSDOS_notify_change (0,NULL,oldinode);
} }
iput (oldinode); iput (oldinode);
iput (dir); iput (dir);
...@@ -923,7 +923,7 @@ int UMSDOS_unlink ( ...@@ -923,7 +923,7 @@ int UMSDOS_unlink (
iput (hdir); iput (hdir);
} }
}else{ }else{
ret = UMSDOS_notify_change (0,inode); ret = UMSDOS_notify_change (0,NULL,inode);
} }
iput (inode); iput (inode);
} }
......
...@@ -18,14 +18,10 @@ ...@@ -18,14 +18,10 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include "xiafs_mac.h" #include <asm/bitops.h>
#include "xiafs_mac.h"
#define clear_bit(nr,addr) ({\
char res; \
__asm__ __volatile__("btrl %1,%2\n\tsetnb %0": \
"=q" (res):"r" (nr),"m" (*(addr))); \
res;})
char internal_error_message[]="XIA-FS: internal error %s %d\n"; char internal_error_message[]="XIA-FS: internal error %s %d\n";
...@@ -59,9 +55,7 @@ static int find_first_zero(struct buffer_head *bh, int start_bit, int end_bit) ...@@ -59,9 +55,7 @@ static int find_first_zero(struct buffer_head *bh, int start_bit, int end_bit)
for (j=0; j < 32; j++) for (j=0; j < 32; j++)
if (tmp & (1 << j)) if (tmp & (1 << j))
break; break;
__asm__ ("btsl %1,%2\n\tsetb %0": \ if (set_bit(j,bmap+i)) {
"=q" (res):"r" (j),"m" (bmap[i]));
if (res) {
start_bit=j + (i << 5) + 1; start_bit=j + (i << 5) + 1;
goto repeat; goto repeat;
} }
...@@ -241,7 +235,7 @@ void xiafs_free_zone(struct super_block * sb, int d_addr) ...@@ -241,7 +235,7 @@ void xiafs_free_zone(struct super_block * sb, int d_addr)
if (!bh) if (!bh)
return; return;
offset = bit & (XIAFS_BITS_PER_Z(sb) -1); offset = bit & (XIAFS_BITS_PER_Z(sb) -1);
if (clear_bit(offset, bh->b_data)) if (!clear_bit(offset, bh->b_data))
printk("XIA-FS: dev %04x" printk("XIA-FS: dev %04x"
" block bit %u (0x%x) already cleared (%s %d)\n", " block bit %u (0x%x) already cleared (%s %d)\n",
sb->s_dev, bit, bit, WHERE_ERR); sb->s_dev, bit, bit, WHERE_ERR);
...@@ -301,7 +295,7 @@ void xiafs_free_inode(struct inode * inode) ...@@ -301,7 +295,7 @@ void xiafs_free_inode(struct inode * inode)
if (!bh) if (!bh)
return; return;
clear_inode(inode); clear_inode(inode);
if (clear_bit(ino & (XIAFS_BITS_PER_Z(sb)-1), bh->b_data)) if (!clear_bit(ino & (XIAFS_BITS_PER_Z(sb)-1), bh->b_data))
printk("XIA-FS: dev %04x" printk("XIA-FS: dev %04x"
"inode bit %ld (0x%lx) already cleared (%s %d)\n", "inode bit %ld (0x%lx) already cleared (%s %d)\n",
inode->i_dev, ino, ino, WHERE_ERR); inode->i_dev, ino, ino, WHERE_ERR);
......
#ifndef _ALPHA_BITOPS_H
#define _ALPHA_BITOPS_H
/*
* Copyright 1994, Linus Torvalds.
*/
/*
* These have to be done with inline assembly: that way the bit-setting
* is guaranteed to be atomic. All bit operations return 0 if the bit
* was cleared before the operation and != 0 if it was not.
*
* bit 0 is the LSB of addr; bit 64 is the LSB of (addr+1).
*/
extern __inline__ unsigned long set_bit(unsigned long nr, void * addr)
{
unsigned long oldbit;
unsigned long temp;
__asm__ __volatile__(
"\n1:\t"
"ldq_l %0,%1\n\t"
"and %0,%3,%2\n\t"
"bne %2,2f\n\t"
"xor %0,%3,%0\n\t"
"stq_c %0,%1\n\t"
"beq %0,1b\n"
"2:"
:"=&r" (temp),
"=m" (((unsigned long *) addr)[nr >> 6]),
"=&r" (oldbit)
:"r" (1UL << (nr & 63)),
"m" (((unsigned long *) addr)[nr >> 6]));
return oldbit;
}
extern __inline__ unsigned long clear_bit(unsigned long nr, void * addr)
{
unsigned long oldbit;
unsigned long temp;
__asm__ __volatile__(
"\n1:\t"
"ldq_l %0,%1\n\t"
"and %0,%3,%2\n\t"
"beq %2,2f\n\t"
"xor %0,%3,%0\n\t"
"stq_c %0,%1\n\t"
"beq %0,1b\n"
"2:"
:"=&r" (temp),
"=m" (((unsigned long *) addr)[nr >> 6]),
"=&r" (oldbit)
:"r" (1UL << (nr & 63)),
"m" (((unsigned long *) addr)[nr >> 6]));
return oldbit;
}
extern __inline__ unsigned long change_bit(unsigned long nr, void * addr)
{
unsigned long oldbit;
unsigned long temp;
__asm__ __volatile__(
"\n1:\t"
"ldq_l %0,%1\n\t"
"and %0,%3,%2\n\t"
"xor %0,%3,%0\n\t"
"stq_c %0,%1\n\t"
"beq %0,1b\n"
:"=&r" (temp),
"=m" (((unsigned long *) addr)[nr >> 6]),
"=&r" (oldbit)
:"r" (1UL << (nr & 63)),
"m" (((unsigned long *) addr)[nr >> 6]));
return oldbit;
}
extern __inline__ unsigned long test_bit(int nr, void * addr)
{
return (1UL << (nr & 63)) & ((unsigned long *) addr)[nr >> 6];
}
#endif /* _ALPHA_BITOPS_H */
...@@ -127,13 +127,6 @@ extern unsigned long name_cache_init(unsigned long start, unsigned long end); ...@@ -127,13 +127,6 @@ extern unsigned long name_cache_init(unsigned long start, unsigned long end);
#define FIBMAP 1 /* bmap access */ #define FIBMAP 1 /* bmap access */
#define FIGETBSZ 2 /* get the block size used for bmap */ #define FIGETBSZ 2 /* get the block size used for bmap */
/* these flags tell notify_change what is being changed */
#define NOTIFY_SIZE 1
#define NOTIFY_MODE 2
#define NOTIFY_TIME 4
#define NOTIFY_UIDGID 8
typedef char buffer_block[BLOCK_SIZE]; typedef char buffer_block[BLOCK_SIZE];
struct buffer_head { struct buffer_head {
...@@ -174,6 +167,38 @@ struct buffer_head { ...@@ -174,6 +167,38 @@ struct buffer_head {
#ifdef __KERNEL__ #ifdef __KERNEL__
/*
* Attribute flags. These should be or-ed together to figure out what
* has been changed!
*/
#define ATTR_MODE 1
#define ATTR_UID 2
#define ATTR_GID 4
#define ATTR_SIZE 8
#define ATTR_ATIME 16
#define ATTR_MTIME 32
#define ATTR_CTIME 64
/*
* This is the Inode Attributes structure, used for notify_change(). It
* uses the above definitions as flags, to know which values have changed.
* Also, in this manner, a Filesystem can look at only the values it cares
* about. Basically, these are the attributes that the VFS layer can
* request to change from the FS layer.
*
* Derek Atkins <warlord@MIT.EDU> 94-10-20
*/
struct iattr {
unsigned int ia_valid;
umode_t ia_mode;
uid_t ia_uid;
gid_t ia_gid;
off_t ia_size;
time_t ia_atime;
time_t ia_mtime;
time_t ia_ctime;
};
struct inode { struct inode {
dev_t i_dev; dev_t i_dev;
unsigned long i_ino; unsigned long i_ino;
...@@ -331,7 +356,7 @@ struct inode_operations { ...@@ -331,7 +356,7 @@ struct inode_operations {
struct super_operations { struct super_operations {
void (*read_inode) (struct inode *); void (*read_inode) (struct inode *);
int (*notify_change) (int flags, struct inode *); int (*notify_change) (struct inode *, struct iattr *);
void (*write_inode) (struct inode *); void (*write_inode) (struct inode *);
void (*put_inode) (struct inode *); void (*put_inode) (struct inode *);
void (*put_super) (struct super_block *); void (*put_super) (struct super_block *);
...@@ -435,7 +460,7 @@ extern void sync_dev(dev_t dev); ...@@ -435,7 +460,7 @@ extern void sync_dev(dev_t dev);
extern int fsync_dev(dev_t dev); extern int fsync_dev(dev_t dev);
extern void sync_supers(dev_t dev); extern void sync_supers(dev_t dev);
extern int bmap(struct inode * inode,int block); extern int bmap(struct inode * inode,int block);
extern int notify_change(int flags, struct inode * inode); extern int notify_change(struct inode *, struct iattr *);
extern int namei(const char * pathname, struct inode ** res_inode); extern int namei(const char * pathname, struct inode ** res_inode);
extern int lnamei(const char * pathname, struct inode ** res_inode); extern int lnamei(const char * pathname, struct inode ** res_inode);
extern int permission(struct inode * inode,int mask); extern int permission(struct inode * inode,int mask);
...@@ -483,6 +508,9 @@ extern int file_fsync(struct inode *, struct file *); ...@@ -483,6 +508,9 @@ extern int file_fsync(struct inode *, struct file *);
extern void dcache_add(struct inode *, const char *, int, unsigned long); extern void dcache_add(struct inode *, const char *, int, unsigned long);
extern int dcache_lookup(struct inode *, const char *, int, unsigned long *); extern int dcache_lookup(struct inode *, const char *, int, unsigned long *);
extern int inode_change_ok(struct inode *, struct iattr *);
extern void inode_setattr(struct inode *, struct iattr *);
extern inline struct inode * iget(struct super_block * sb,int nr) extern inline struct inode * iget(struct super_block * sb,int nr)
{ {
return __iget(sb,nr,1); return __iget(sb,nr,1);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
*/ */
/* Hd controller regs. Ref: IBM AT Bios-listing */ /* Hd controller regs. Ref: IBM AT Bios-listing */
/* For a second IDE interface, xor all addresses with 0x80 */
#define HD_DATA 0x1f0 /* _CTL when writing */ #define HD_DATA 0x1f0 /* _CTL when writing */
#define HD_ERROR 0x1f1 /* see err-bits */ #define HD_ERROR 0x1f1 /* see err-bits */
#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */ #define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
...@@ -16,10 +17,12 @@ ...@@ -16,10 +17,12 @@
#define HD_HCYL 0x1f5 /* high byte of starting cyl */ #define HD_HCYL 0x1f5 /* high byte of starting cyl */
#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */ #define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
#define HD_STATUS 0x1f7 /* see status-bits */ #define HD_STATUS 0x1f7 /* see status-bits */
#define HD_PRECOMP HD_ERROR /* same io address, read=error, write=precomp */ #define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */ #define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
#define HD_CMD 0x3f6 #define HD_CMD 0x3f6 /* used for resets */
#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
/* Bits of HD_STATUS */ /* Bits of HD_STATUS */
#define ERR_STAT 0x01 #define ERR_STAT 0x01
...@@ -41,7 +44,9 @@ ...@@ -41,7 +44,9 @@
#define WIN_SEEK 0x70 #define WIN_SEEK 0x70
#define WIN_DIAGNOSE 0x90 #define WIN_DIAGNOSE 0x90
#define WIN_SPECIFY 0x91 #define WIN_SPECIFY 0x91
#define WIN_SETIDLE 0x97
#define WIN_PIDENTIFY 0xA1 /* identify ATA-PI device */
#define WIN_MULTREAD 0xC4 /* read multiple sectors */ #define WIN_MULTREAD 0xC4 /* read multiple sectors */
#define WIN_MULTWRITE 0xC5 /* write multiple sectors */ #define WIN_MULTWRITE 0xC5 /* write multiple sectors */
#define WIN_SETMULT 0xC6 /* enable read multiple */ #define WIN_SETMULT 0xC6 /* enable read multiple */
...@@ -56,25 +61,29 @@ ...@@ -56,25 +61,29 @@
#define ECC_ERR 0x40 /* Uncorrectable ECC error */ #define ECC_ERR 0x40 /* Uncorrectable ECC error */
#define BBD_ERR 0x80 /* block marked bad */ #define BBD_ERR 0x80 /* block marked bad */
/* HDIO_GETGEO is the preferred choice - HDIO_REQ will be removed at some
later date */
#define HDIO_REQ 0x301
#define HDIO_GETGEO 0x301
struct hd_geometry { struct hd_geometry {
unsigned char heads; unsigned char heads;
unsigned char sectors; unsigned char sectors;
unsigned short cylinders; unsigned short cylinders;
unsigned long start; unsigned long start;
}; };
#define HDIO_GETUNMASKINTR 0x302
#define HDIO_SETUNMASKINTR 0x303
#define HDIO_GETMULTCOUNT 0x304
#define HDIO_SETMULTCOUNT 0x305
#define HDIO_GETIDENTITY 0x307
#endif
/* structure returned by HDIO_GETIDENTITY, as per ASC X3T9.2 rev 4a */ /* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x30n/0x31n */
#define HDIO_GETGEO 0x301 /* get device geometry */
#define HDIO_REQ HDIO_GETGEO /* obsolete, use HDIO_GETGEO */
#define HDIO_GET_UNMASKINTR 0x302 /* get current unmask setting */
#define HDIO_SETUNMASKINTR 0x303 /* obsolete */
#define HDIO_GET_MULTCOUNT 0x304 /* get current IDE blockmode setting */
#define HDIO_SETMULTCOUNT 0x305 /* obsolete */
#define HDIO_GET_IDENTITY 0x307 /* get IDE identification info */
/* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x32n/0x33n */
#define HDIO_SET_MULTCOUNT 0x321 /* set IDE blockmode */
#define HDIO_SET_UNMASKINTR 0x322 /* permit other irqs during I/O */
#define HDIO_SET_KEEPSETTINGS 0x323 /* keep ioctl settings on reset */
#define HDIO_SET_XFERMODE 0x324 /* set IDE transfer mode */
/* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
struct hd_driveid { struct hd_driveid {
unsigned short config; /* lots of obsolete bit flags */ unsigned short config; /* lots of obsolete bit flags */
unsigned short cyls; /* "physical" cyls */ unsigned short cyls; /* "physical" cyls */
...@@ -124,3 +133,4 @@ struct hd_driveid { ...@@ -124,3 +133,4 @@ struct hd_driveid {
/* unsigned short vendor7 [32];*/ /* vendor unique (words 128-159) */ /* unsigned short vendor7 [32];*/ /* vendor unique (words 128-159) */
/* unsigned short reservedyy[96];*/ /* reserved (words 160-255) */ /* unsigned short reservedyy[96];*/ /* reserved (words 160-255) */
}; };
#endif
...@@ -175,7 +175,7 @@ extern void msdos_statfs(struct super_block *sb,struct statfs *buf); ...@@ -175,7 +175,7 @@ extern void msdos_statfs(struct super_block *sb,struct statfs *buf);
extern int msdos_bmap(struct inode *inode,int block); extern int msdos_bmap(struct inode *inode,int block);
extern void msdos_read_inode(struct inode *inode); extern void msdos_read_inode(struct inode *inode);
extern void msdos_write_inode(struct inode *inode); extern void msdos_write_inode(struct inode *inode);
extern int msdos_notify_change(int flags,struct inode *inode); extern int msdos_notify_change(struct inode *,struct iattr *);
/* dir.c */ /* dir.c */
......
...@@ -421,7 +421,7 @@ extern void sysv_put_super(struct super_block *); ...@@ -421,7 +421,7 @@ extern void sysv_put_super(struct super_block *);
extern struct super_block *sysv_read_super(struct super_block *,void *,int); extern struct super_block *sysv_read_super(struct super_block *,void *,int);
extern void sysv_write_super(struct super_block *); extern void sysv_write_super(struct super_block *);
extern void sysv_read_inode(struct inode *); extern void sysv_read_inode(struct inode *);
extern int sysv_notify_change(int,struct inode *); extern int sysv_notify_change(struct inode *, struct iattr *);
extern void sysv_write_inode(struct inode *); extern void sysv_write_inode(struct inode *);
extern void sysv_put_inode(struct inode *); extern void sysv_put_inode(struct inode *);
extern void sysv_statfs(struct super_block *, struct statfs *); extern void sysv_statfs(struct super_block *, struct statfs *);
......
...@@ -77,7 +77,7 @@ void umsdos_patch_inode (struct inode *inode, ...@@ -77,7 +77,7 @@ void umsdos_patch_inode (struct inode *inode,
int umsdos_get_dirowner (struct inode *inode, struct inode **result); int umsdos_get_dirowner (struct inode *inode, struct inode **result);
void UMSDOS_read_inode (struct inode *inode); void UMSDOS_read_inode (struct inode *inode);
void UMSDOS_write_inode (struct inode *inode); void UMSDOS_write_inode (struct inode *inode);
int UMSDOS_notify_change (int flags, struct inode *inode); int UMSDOS_notify_change (struct inode *inode, struct iattr *attr);
struct super_block *UMSDOS_read_super (struct super_block *s, struct super_block *UMSDOS_read_super (struct super_block *s,
void *data, void *data,
int silent); int silent);
......
...@@ -157,7 +157,7 @@ static char fpu_error = 0; ...@@ -157,7 +157,7 @@ static char fpu_error = 0;
static char command_line[COMMAND_LINE_SIZE] = { 0, }; static char command_line[COMMAND_LINE_SIZE] = { 0, };
char *get_options(char *str, int *ints) char *get_options(char *str, int *ints)
{ {
char *cur = str; char *cur = str;
int i=1; int i=1;
...@@ -253,6 +253,11 @@ static void calibrate_delay(void) ...@@ -253,6 +253,11 @@ static void calibrate_delay(void)
printk("Calibrating delay loop.. "); printk("Calibrating delay loop.. ");
while (loops_per_sec <<= 1) { while (loops_per_sec <<= 1) {
/* wait for "start of" clock tick */
ticks = jiffies;
while (ticks == jiffies)
/* nothing */;
/* Go .. */
ticks = jiffies; ticks = jiffies;
__delay(loops_per_sec); __delay(loops_per_sec);
ticks = jiffies - ticks; ticks = jiffies - ticks;
...@@ -271,7 +276,7 @@ static void calibrate_delay(void) ...@@ -271,7 +276,7 @@ static void calibrate_delay(void)
} }
printk("failed\n"); printk("failed\n");
} }
/* /*
* This is a simple kernel command line parsing function: it parses * This is a simple kernel command line parsing function: it parses
...@@ -347,7 +352,7 @@ static void parse_options(char *line) ...@@ -347,7 +352,7 @@ static void parse_options(char *line)
/* /*
* Then check if it's an environment variable or * Then check if it's an environment variable or
* an option. * an option.
*/ */
if (strchr(line,'=')) { if (strchr(line,'=')) {
if (envs >= MAX_INIT_ENVS) if (envs >= MAX_INIT_ENVS)
break; break;
...@@ -459,7 +464,7 @@ asmlinkage void start_kernel(void) ...@@ -459,7 +464,7 @@ asmlinkage void start_kernel(void)
ipc_init(); ipc_init();
#endif #endif
sti(); sti();
/* /*
* check if exception 16 works correctly.. This is truly evil * check if exception 16 works correctly.. This is truly evil
* code: it disables the high 8 interrupts to make sure that * code: it disables the high 8 interrupts to make sure that
......
...@@ -45,8 +45,8 @@ ...@@ -45,8 +45,8 @@
#define set_flags(X,new,mask) \ #define set_flags(X,new,mask) \
((X) = ((X) & ~(mask)) | ((new) & (mask))) ((X) = ((X) & ~(mask)) | ((new) & (mask)))
#define SAFE_MASK (0x40DD5) #define SAFE_MASK (0xDD5)
#define RETURN_MASK (0x40DFF) #define RETURN_MASK (0xDFF)
asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs) asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs)
{ {
......
...@@ -234,7 +234,7 @@ int vsprintf(char *buf, const char *fmt, va_list args) ...@@ -234,7 +234,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
case 'p': case 'p':
if (field_width == -1) { if (field_width == -1) {
field_width = 8; field_width = 2*sizeof(void *);
flags |= ZEROPAD; flags |= ZEROPAD;
} }
str = number(str, str = number(str,
......
...@@ -240,7 +240,7 @@ int copy_page_tables(struct task_struct * tsk) ...@@ -240,7 +240,7 @@ int copy_page_tables(struct task_struct * tsk)
continue; continue;
if (old_pg_table >= high_memory || !(old_pg_table & PAGE_PRESENT)) { if (old_pg_table >= high_memory || !(old_pg_table & PAGE_PRESENT)) {
printk("copy_page_tables: bad page table: " printk("copy_page_tables: bad page table: "
"probable memory corruption"); "probable memory corruption\n");
*old_page_dir = 0; *old_page_dir = 0;
continue; continue;
} }
......
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