Commit beadddbf authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.57

parent 95fda206
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 56
SUBLEVEL = 57
ARCH = i386
......
......@@ -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" */
{ 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" */
{ 2080,13,2,80,0,0x1C,0x01,0xCF,0x6C,"D1040" }, /* 21 1.04MB 3.5" */
{ 2240,14,2,80,0,0x1C,0x19,0xCF,0x6C,"D1120" }, /* 22 1.12MB 3.5" */
{ 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */
{ 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 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" */
{ 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" */
{ 6400,40,2,80,0,0x25,0x5B,0xCF,0x6C,"E3200" }, /* 26 3.20MB 3.5" */
{ 7040,44,2,80,0,0x25,0x5B,0xCF,0x6C,"E3520" }, /* 27 3.52MB 3.5" */
{ 7680,48,2,80,0,0x25,0x63,0xCF,0x6C,"E3840" }, /* 28 3.84MB 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,0x00,"E3200" }, /* 26 3.20MB 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,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" */
{ 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)
static int disk_change(int drive)
{
if(jiffies < DP->select_delay + DRS->select_date)
udelay(20000);
if(inb_p(FD_DIR) & 0x80){
UDRS->flags |= FD_VERIFY; /* verify write protection */
......@@ -526,12 +529,12 @@ static int disk_change(int drive)
}
}
static int locked=0;
static int set_dor(int fdc, char mask, char data)
{
register unsigned char drive, unit, newdor,olddor;
cli();
locked=1;
olddor = FDCS->dor;
newdor = (olddor & mask) | data;
if ( newdor != olddor ){
......@@ -542,7 +545,7 @@ static int set_dor(int fdc, char mask, char data)
FDCS->dor = newdor;
outb_p( newdor, FD_DOR);
}
sti();
locked=0;
return olddor;
}
......@@ -636,7 +639,10 @@ static void motor_off_callback(unsigned long 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] = {
......@@ -657,6 +663,10 @@ static struct timer_list motor_off_timer[N_DRIVE] = {
static void floppy_off(unsigned int nr)
{
unsigned long volatile delta;
register int fdc=FDC(nr);
if( !(FDCS->dor & ( 0x10 << UNIT(nr))))
return;
del_timer(motor_off_timer+nr);
......@@ -1175,6 +1185,7 @@ static void seek_interrupt(void)
)
DRS->flags &= ~FD_DISK_NEWCHANGE; /* effective seek */
DRS->track = ST1;
DRS->select_date = jiffies;
seek_floppy();
}
......@@ -1466,7 +1477,8 @@ static void start_motor(void)
mask = 0xfc;
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 */
DRS->select_date = jiffies;
......@@ -1489,9 +1501,7 @@ static void start_motor(void)
if( raw_cmd.flags & FD_RAW_NO_MOTOR)
return;
if(disk_change(current_drive))
twaddle(); /* this clears the dcl on certain drive/controller
* combinations */
disk_change(current_drive);
return;
}
......@@ -1929,17 +1939,12 @@ static int buffer_chain_size(void)
size = CURRENT->current_nr_sectors << 9;
bh = CURRENT->bh;
#ifdef SANITY
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;
if(bh){
bh = bh->b_reqnext;
while ( bh && bh->b_data == base + size ){
size += bh->b_size;
bh = bh->b_reqnext;
}
}
return size >> 9;
}
......@@ -2008,10 +2013,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
if ( size > remaining )
size = remaining;
#ifdef SANITY
if (!bh){
DPRINT("bh=null in copy buffer before copy\n");
break;
}
if (dma_buffer + size >
floppy_track_buffer + (max_buffer_sectors << 10) ||
dma_buffer < floppy_track_buffer ){
......@@ -2355,8 +2356,6 @@ static void redo_fd_request(void)
continue;
}
if ( DRS->flags & FD_NEED_TWADDLE )
twaddle();
floppy_tq.routine = (void *)(void *) floppy_start;
queue_task(&floppy_tq, &tq_timer);
#ifdef DEBUGT
......@@ -2506,7 +2505,7 @@ static int raw_cmd_ioctl(int drive, void *param)
current_addr = floppy_track_buffer;
cont = &raw_cmd_cont;
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;
else
raw_cmd.flags &= ~FD_RAW_DISK_CHANGE;
......@@ -3123,12 +3122,21 @@ void floppy_init(void)
static int floppy_grab_irq_and_dma(void)
{
int i;
cli();
if (usage_count++){
sti();
return 0;
}
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")) {
DPRINT1("Unable to grab IRQ%d for the floppy driver\n",
FLOPPY_IRQ);
......@@ -3146,6 +3154,7 @@ static int floppy_grab_irq_and_dma(void)
static void floppy_release_irq_and_dma(void)
{
int i;
cli();
if (--usage_count){
sti();
......@@ -3156,10 +3165,7 @@ static void floppy_release_irq_and_dma(void)
free_dma(FLOPPY_DMA);
disable_irq(FLOPPY_IRQ);
free_irq(FLOPPY_IRQ);
#ifdef HAVE_2_CONTROLLERS
/* switch on first controller.
* This saves us trouble on the next reboot. */
set_dor(0, ~0, 8 );
set_dor(1, ~8, 0 );
#endif
/* switch off dma gates */
for(i=0; i< N_FDC; i++)
set_dor(i, ~8, 0);
}
......@@ -305,7 +305,8 @@ static void identify_intr(void)
if (unmask_intr[dev])
sti();
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);
if (id != NULL) {
hd_ident_info[dev] = NULL;
......@@ -796,6 +797,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
{
struct hd_geometry *loc = (struct hd_geometry *) arg;
int dev, err;
unsigned long flags;
if ((!inode) || (!inode->i_rdev))
return -EINVAL;
......@@ -845,17 +847,22 @@ static int hd_ioctl(struct inode * inode, struct file * file,
case BLKRRPART: /* Re-read partition tables */
return revalidate_hddisk(inode->i_rdev, 1);
case HDIO_SETUNMASKINTR:
if (!suser()) return -EACCES;
case HDIO_SETUNMASKINTR: /* obsolete */
printk("hd: obsolete syscall: HDIO_SETUNMASKINTR\n");
if (!arg) return -EINVAL;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
if (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;
case HDIO_GETUNMASKINTR:
case HDIO_GET_UNMASKINTR:
if (!arg) return -EINVAL;
err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
if (err)
......@@ -863,7 +870,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
put_fs_long(unmask_intr[dev], (long *) arg);
return 0;
case HDIO_GETMULTCOUNT:
case HDIO_GET_MULTCOUNT:
if (!arg) return -EINVAL;
err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
if (err)
......@@ -871,16 +878,17 @@ static int hd_ioctl(struct inode * inode, struct file * file,
put_fs_long(mult_count[dev], (long *) arg);
return 0;
case HDIO_SETMULTCOUNT:
{
unsigned long flags;
if (!suser()) return -EACCES;
case HDIO_SETMULTCOUNT: /* obsolete */
printk("hd: obsolete syscall: HDIO_SETMULTCOUNT\n");
if (!arg) return -EINVAL;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
if (err)
return err;
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);
cli(); /* a prior request might still be in progress */
if (arg > max_mult[dev])
......@@ -895,8 +903,8 @@ static int hd_ioctl(struct inode * inode, struct file * file,
}
restore_flags(flags);
return err;
}
case HDIO_GETIDENTITY:
case HDIO_GET_IDENTITY:
if (!arg) return -EINVAL;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
if (hd_ident_info[dev] == NULL) return -ENOMSG;
......
......@@ -126,7 +126,6 @@ int is_read_only(int dev)
major = MAJOR(dev);
minor = MINOR(dev);
if ( major == FLOPPY_MAJOR && floppy_is_wp( minor) ) return 1;
if (major < 0 || major >= MAX_BLKDEV) return 0;
return ro_bits[major][minor >> 5] & (1 << (minor & 31));
}
......
......@@ -1106,11 +1106,6 @@ static inline unsigned long try_to_share_buffers(unsigned long address,
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
* 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
for (i=0, j=0; j<PAGE_SIZE ; i++, j += size, where += size) {
if (bh[i]) {
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]);
}
}
......
......@@ -37,13 +37,6 @@
#include <linux/string.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)
{
struct buffer_head * bh;
......@@ -133,7 +126,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next);
printk("new_block: cannot get block");
return 0;
}
clear_block(bh->b_data);
memset(bh->b_data, 0, BLOCK_SIZE);
bh->b_uptodate = 1;
mark_buffer_dirty(bh, 1);
brelse(bh);
......
......@@ -55,23 +55,14 @@
*/
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)
return 0;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
return 1;
if (len < EXT_NAME_LEN && len != de->name_len)
if (len != de->name_len)
return 0;
__asm__ __volatile__(
"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;
return !memcmp(name, de->name, len);
}
/*
......
......@@ -233,6 +233,59 @@ static void read_inode(struct 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
* chown, chmod, utime, and truncate. It is guaranteed (unlike
......@@ -241,11 +294,18 @@ static void read_inode(struct inode * inode)
* 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 &&
inode->i_sb->s_op->notify_change)
return inode->i_sb->s_op->notify_change(flags, inode);
inode->i_sb->s_op->notify_change)
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;
}
......
......@@ -26,33 +26,28 @@
*/
static int isofs_match(int len,const char * name, char * compare, int dlen)
{
register int same;
if (!compare) return 0;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
if (!len && (compare[0]==0) && (dlen==1))
return 1;
if (compare[0]==0 && dlen==1 && len == 1)
compare = ".";
if (compare[0]==1 && dlen==1 && len == 2) {
compare = "..";
dlen = 2;
};
if (!compare)
return 0;
/* check special "." and ".." files */
if (dlen == 1) {
/* "." */
if (compare[0] = 0) {
if (!len)
return 1;
compare = ".";
} else if (compare[0] == 1) {
compare = "..";
dlen = 2;
}
}
#if 0
if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen);
#endif
if (dlen != len)
return 0;
__asm__ __volatile__(
"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;
return !memcmp(name, compare, len);
}
/*
......
......@@ -14,28 +14,6 @@
#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 unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
......@@ -110,7 +88,7 @@ int minix_new_block(struct super_block * sb)
j = 8192;
for (i=0 ; i<8 ; i++)
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;
if (i>=8 || !bh || j>=8192)
return 0;
......@@ -127,7 +105,7 @@ int minix_new_block(struct super_block * sb)
printk("new_block: cannot get block");
return 0;
}
clear_block(bh->b_data);
memset(bh->b_data, 0, BLOCK_SIZE);
bh->b_uptodate = 1;
mark_buffer_dirty(bh, 1);
brelse(bh);
......@@ -193,7 +171,7 @@ struct inode * minix_new_inode(const struct inode * dir)
j = 8192;
for (i=0 ; i<8 ; i++)
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;
if (!bh || j >= 8192) {
iput(inode);
......
......@@ -86,13 +86,13 @@ static int minix_readdir(struct inode * inode, struct file * filp,
filp->f_pos += info->s_dirsize;
retry:
if (de->inode) {
version = inode->i_version;
for (i = 0; i < info->s_namelen; i++)
if ((c = de->name[i]) != 0)
put_fs_byte(c,i+dirent->d_name);
else
break;
if (i) {
version = inode->i_version;
put_fs_long(de->inode,&dirent->d_ino);
put_fs_byte(0,i+dirent->d_name);
put_fs_word(i,&dirent->d_reclen);
......
......@@ -23,15 +23,11 @@
static inline int namecompare(int len, int maxlen,
const char * name, const char * buffer)
{
if (len >= maxlen || !buffer[len]) {
unsigned char same;
__asm__("repe ; cmpsb ; setz %0"
:"=q" (same)
:"S" ((long) name),"D" ((long) buffer),"c" (len)
:"cx","di","si");
return same;
}
return 0;
if (len > maxlen)
return 0;
if (len < maxlen && buffer[len])
return 0;
return !memcmp(name, buffer, len);
}
/*
......
......@@ -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;
error = 0;
if ((flags & NOTIFY_UIDGID) && (inode->i_uid != MSDOS_SB(inode->i_sb)->
fs_uid || inode->i_gid != MSDOS_SB(inode->i_sb)->fs_gid)) {
inode->i_uid = MSDOS_SB(inode->i_sb)->fs_uid;
inode->i_gid = MSDOS_SB(inode->i_sb)->fs_gid;
error = inode_change_ok(inode, attr);
if (error)
return error;
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;
}
if (!(flags & NOTIFY_MODE))
if (error)
return MSDOS_SB(inode->i_sb)->quiet ? 0 : error;
if (inode->i_mode & ~MSDOS_VALID_MODE) {
inode->i_mode &= MSDOS_VALID_MODE;
error = -EPERM;
}
inode_setattr(inode, attr);
if (IS_NOEXEC(inode) && !S_ISDIR(inode->i_mode))
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
& ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
~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,
iput(inode);
return -EACCES;
}
flag &= ~O_TRUNC;
} else {
if (IS_RDONLY(inode) && (flag & 2)) {
iput(inode);
......@@ -404,14 +405,18 @@ int open_namei(const char * pathname, int flag, int mode,
return -EPERM;
}
if (flag & O_TRUNC) {
inode->i_size = 0;
if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode);
if ((error = notify_change(NOTIFY_SIZE, inode))) {
iput(inode);
return error;
}
inode->i_dirt = 1;
struct iattr newattrs;
newattrs.ia_size = 0;
newattrs.ia_valid = ATTR_SIZE;
if ((error = notify_change(inode, &newattrs))) {
iput(inode);
return error;
}
inode->i_size = 0;
if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode);
inode->i_dirt = 1;
}
*res_inode = inode;
return 0;
......
......@@ -20,7 +20,7 @@
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_super(struct super_block *);
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,
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_fattr fattr;
int error;
if (flags & NOTIFY_MODE)
sattr.mode = inode->i_mode;
if (attr->ia_valid & ATTR_MODE)
sattr.mode = attr->ia_mode;
else
sattr.mode = (unsigned) -1;
if (flags & NOTIFY_UIDGID) {
sattr.uid = inode->i_uid;
sattr.gid = inode->i_gid;
}
if (attr->ia_valid & ATTR_UID)
sattr.uid = attr->ia_uid;
else
sattr.uid = sattr.gid = (unsigned) -1;
if (flags & NOTIFY_SIZE)
sattr.size = S_ISREG(inode->i_mode) ? inode->i_size : -1;
sattr.uid = (unsigned) -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
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.atime.seconds = inode->i_atime;
sattr.atime.useconds = 0;
}
else {
} else
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;
}
error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode),
&sattr, &fattr);
if (!error)
......@@ -230,4 +238,3 @@ int nfs_notify_change(int flags, struct inode *inode)
inode->i_dirt = 0;
return error;
}
......@@ -69,6 +69,7 @@ asmlinkage int sys_truncate(const char * path, unsigned int length)
{
struct inode * inode;
int error;
struct iattr newattrs;
error = namei(path,&inode);
if (error)
......@@ -85,12 +86,13 @@ asmlinkage int sys_truncate(const char * path, unsigned int length)
iput(inode);
return -EPERM;
}
inode->i_size = length;
inode->i_size = newattrs.ia_size = length;
if (inode->i_op && inode->i_op->truncate)
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;
error = notify_change(NOTIFY_SIZE, inode);
error = notify_change(inode, &newattrs);
iput(inode);
return error;
}
......@@ -99,6 +101,7 @@ asmlinkage int sys_ftruncate(unsigned int fd, unsigned int length)
{
struct inode * inode;
struct file * file;
struct iattr newattrs;
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF;
......@@ -108,12 +111,13 @@ asmlinkage int sys_ftruncate(unsigned int fd, unsigned int length)
return -EACCES;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return -EPERM;
inode->i_size = length;
inode->i_size = newattrs.ia_size = length;
if (inode->i_op && inode->i_op->truncate)
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;
return notify_change(NOTIFY_SIZE, inode);
return notify_change(inode, &newattrs);
}
/* If times==NULL, set access and modification to current time,
......@@ -125,6 +129,7 @@ asmlinkage int sys_utime(char * filename, struct utimbuf * times)
struct inode * inode;
long actime,modtime;
int error;
struct iattr newattrs;
error = namei(filename,&inode);
if (error)
......@@ -140,19 +145,20 @@ asmlinkage int sys_utime(char * filename, struct utimbuf * times)
}
actime = get_fs_long((unsigned long *) &times->actime);
modtime = get_fs_long((unsigned long *) &times->modtime);
inode->i_ctime = CURRENT_TIME;
newattrs.ia_ctime = CURRENT_TIME;
} else {
if ((current->fsuid != inode->i_uid) &&
!permission(inode,MAY_WRITE)) {
iput(inode);
return -EACCES;
}
actime = modtime = inode->i_ctime = CURRENT_TIME;
actime = modtime = newattrs.ia_ctime = CURRENT_TIME;
}
inode->i_atime = actime;
inode->i_mtime = modtime;
newattrs.ia_atime = actime;
newattrs.ia_mtime = modtime;
newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
inode->i_dirt = 1;
error = notify_change(NOTIFY_TIME, inode);
error = notify_change(inode, &newattrs);
iput(inode);
return error;
}
......@@ -249,49 +255,43 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
{
struct inode * inode;
struct file * file;
struct iattr newattrs;
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF;
if (!(inode = file->f_inode))
return -ENOENT;
if ((current->fsuid != inode->i_uid) && !fsuser())
return -EPERM;
if (IS_RDONLY(inode))
return -EROFS;
if (mode == (mode_t) -1)
mode = inode->i_mode;
inode->i_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
if (!fsuser() && !in_group_p(inode->i_gid))
inode->i_mode &= ~S_ISGID;
inode->i_ctime = CURRENT_TIME;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_ctime = CURRENT_TIME;
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
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)
{
struct inode * inode;
int error;
struct iattr newattrs;
error = namei(filename,&inode);
if (error)
return error;
if ((current->fsuid != inode->i_uid) && !fsuser()) {
iput(inode);
return -EPERM;
}
if (IS_RDONLY(inode)) {
iput(inode);
return -EROFS;
}
if (mode == (mode_t) -1)
mode = inode->i_mode;
inode->i_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
if (!fsuser() && !in_group_p(inode->i_gid))
inode->i_mode &= ~S_ISGID;
inode->i_ctime = CURRENT_TIME;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_ctime = CURRENT_TIME;
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
inode->i_dirt = 1;
error = notify_change(NOTIFY_MODE, inode);
error = notify_change(inode, &newattrs);
iput(inode);
return error;
}
......@@ -300,9 +300,7 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
{
struct inode * inode;
struct file * file;
uid_t old_user;
gid_t old_group;
int notify_flag = 0;
struct iattr newattrs;
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF;
......@@ -310,45 +308,37 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
return -ENOENT;
if (IS_RDONLY(inode))
return -EROFS;
old_user = inode->i_uid;
old_group = inode->i_gid;
if (user == (uid_t) -1)
user = inode->i_uid;
if (group == (gid_t) -1)
group = inode->i_gid;
if ((current->fsuid == inode->i_uid && user == inode->i_uid &&
(in_group_p(group) || group == inode->i_gid)) ||
fsuser()) {
inode->i_uid = user;
inode->i_gid = group;
/*
* If the owner has been changed, remove the setuid bit
*/
if (old_user != inode->i_uid && inode->i_mode & S_ISUID) {
inode->i_mode &= ~S_ISUID;
notify_flag = NOTIFY_MODE;
}
/*
* If the group has been changed, remove the setgid bit
*/
if (old_group != inode->i_gid && inode->i_mode & S_ISGID) {
inode->i_mode &= ~S_ISGID;
notify_flag = NOTIFY_MODE;
}
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
return notify_change(notify_flag | NOTIFY_UIDGID, inode);
newattrs.ia_uid = user;
newattrs.ia_gid = group;
newattrs.ia_ctime = CURRENT_TIME;
newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
/*
* If the owner has been changed, remove the setuid bit
*/
if (user != inode->i_uid && inode->i_mode & S_ISUID) {
newattrs.ia_mode = inode->i_mode & ~S_ISUID;
newattrs.ia_valid |= ATTR_MODE;
}
/*
* If the group has been changed, remove the setgid bit
*/
if (group != inode->i_gid && inode->i_mode & S_ISGID) {
newattrs.ia_mode = inode->i_mode & ~S_ISGID;
newattrs.ia_valid |= ATTR_MODE;
}
return -EPERM;
inode->i_dirt = 1;
return notify_change(inode, &newattrs);
}
asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
{
struct inode * inode;
int error;
uid_t old_user;
gid_t old_group;
int notify_flag = 0;
struct iattr newattrs;
error = lnamei(filename,&inode);
if (error)
......@@ -357,39 +347,32 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
iput(inode);
return -EROFS;
}
old_user = inode->i_uid;
old_group = inode->i_uid;
if (user == (uid_t) -1)
user = inode->i_uid;
if (group == (gid_t) -1)
group = inode->i_gid;
if ((current->fsuid == inode->i_uid && user == inode->i_uid &&
(in_group_p(group) || group == inode->i_gid)) ||
fsuser()) {
inode->i_uid = user;
inode->i_gid = group;
/*
* If the owner has been changed, remove the setuid bit
*/
if (old_user != inode->i_uid && inode->i_mode & S_ISUID) {
inode->i_mode &= ~S_ISUID;
notify_flag = NOTIFY_MODE;
}
/*
* If the group has been changed, remove the setgid bit
*/
if (old_group != inode->i_gid && inode->i_mode & S_ISGID) {
inode->i_mode &= ~S_ISGID;
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;
newattrs.ia_uid = user;
newattrs.ia_gid = group;
newattrs.ia_ctime = CURRENT_TIME;
newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
/*
* If the owner has been changed, remove the setuid bit
*/
if (user != inode->i_uid && inode->i_mode & S_ISUID) {
newattrs.ia_mode = inode->i_mode & ~S_ISUID;
newattrs.ia_valid |= ATTR_MODE;
}
/*
* If the group has been changed, remove the setgid bit
*/
if (group != inode->i_gid && inode->i_mode & S_ISGID) {
newattrs.ia_mode = inode->i_mode & ~S_ISGID;
newattrs.ia_valid |= ATTR_MODE;
}
inode->i_dirt = 1;
error = notify_change(inode, &newattrs);
iput(inode);
return -EPERM;
return(error);
}
/*
......
......@@ -69,8 +69,6 @@ static struct proc_dir_entry base_dir[] = {
int proc_match(int len,const char * name,struct proc_dir_entry * de)
{
register int same;
if (!de || !de->low_ino)
return 0;
/* "" 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)
return 1;
if (de->namelen != len)
return 0;
__asm__ __volatile__(
"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;
return !memcmp(name, de->name, 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)
* the setgid bits
*/
if (written > 0 && !suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
inode->i_mode &= ~(S_ISUID | S_ISGID);
notify_change (NOTIFY_MODE, inode);
struct iattr newattrs;
newattrs.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
newattrs.ia_valid = ATTR_MODE;
notify_change(inode, &newattrs);
}
return written;
}
......@@ -29,16 +29,6 @@
sb->sv_sbd->s_tfree = *sb->sv_sb_total_free_blocks
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)
{
struct buffer_head * bh;
......@@ -115,7 +105,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block)
return;
}
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; */
mark_buffer_dirty(bh, 1);
bh->b_uptodate = 1;
......@@ -228,7 +218,7 @@ int sysv_new_block(struct super_block * sb)
unlock_super(sb);
return 0;
}
memzero(bh_data,sb->sv_block_size);
memset(bh_data, 0, sb->sv_block_size);
mark_buffer_dirty(bh, 1);
bh->b_uptodate = 1;
brelse(bh);
......
......@@ -715,9 +715,16 @@ void sysv_read_inode(struct inode * inode)
}
/* 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_mode == COH_KLUDGE_SYMLINK_MODE) {
inode->i_mode = COH_KLUDGE_NOT_SYMLINK;
......
......@@ -25,16 +25,11 @@
static inline int namecompare(int len, int maxlen,
const char * name, const char * buffer)
{
if (len >= maxlen || !buffer[len]) {
unsigned char same;
__asm__("repe ; cmpsb ; setz %0"
:"=q" (same)
:"S" ((long) name),"D" ((long) buffer),"c" (len)
:"cx","di","si");
return same;
}
/* if (len<maxlen && buffer[len]) then buffer is longer than name */
return 0;
if (len > maxlen)
return 0;
if (len < maxlen && buffer[len])
return 0;
return !memcmp(name, buffer, len);
}
/*
......
......@@ -257,13 +257,24 @@ void UMSDOS_read_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));
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;
if ((ret = inode_change_ok(inode, attr)) != 0)
return ret;
if (inode->i_nlink > 0){
/* #Specification: notify_change / i_nlink > 0
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)
ret = umsdos_emd_dir_read (emd_owner,&filp,(char*)&entry
,UMSDOS_REC_SIZE);
if (ret == 0){
if (flags & NOTIFY_UIDGID){
entry.uid = inode->i_uid;
entry.gid = inode->i_gid;
/* Remove those flags msdos don't like */
flags &= ~NOTIFY_UIDGID;
}
if (flags & NOTIFY_MODE){
entry.mode = inode->i_mode;
flags &= ~NOTIFY_MODE;
}
if (flags & NOTIFY_TIME){
entry.atime = inode->i_atime;
entry.mtime = inode->i_mtime;
entry.ctime = inode->i_ctime;
}
if (attr->ia_valid & ATTR_UID)
entry.uid = attr->ia_uid;
if (attr->ia_valid & ATTR_GID)
entry.gid = attr->ia_gid;
if (attr->ia_valid & ATTR_MODE)
entry.mode = attr->ia_mode;
if (attr->ia_valid & ATTR_ATIME)
entry.atime = attr->ia_atime;
if (attr->ia_valid & ATTR_MTIME)
entry.mtime = attr->ia_mtime;
if (attr->ia_valid & ATTR_CTIME)
entry.ctime = attr->ia_ctime;
entry.nlink = inode->i_nlink;
filp.f_pos = inode->u.umsdos_i.pos;
ret = umsdos_emd_dir_write (emd_owner,&filp,(char*)&entry
,UMSDOS_REC_SIZE);
PRINTK (("notify pos %d ret %d nlink %d "
,inode->u.umsdos_i.pos
,ret,entry.nlink));
......@@ -332,20 +342,14 @@ int UMSDOS_notify_change (int flags, struct inode *inode)
notify_change operation are done only on the
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);
}
PRINTK (("\n"));
}
}
if (ret == 0)
inode_setattr(inode, attr);
return ret;
}
......
......@@ -618,7 +618,7 @@ int UMSDOS_link (
}
if (ret == 0){
oldinode->i_nlink++;
ret = UMSDOS_notify_change (0,oldinode);
ret = UMSDOS_notify_change (0,NULL,oldinode);
}
iput (oldinode);
iput (dir);
......@@ -923,7 +923,7 @@ int UMSDOS_unlink (
iput (hdir);
}
}else{
ret = UMSDOS_notify_change (0,inode);
ret = UMSDOS_notify_change (0,NULL,inode);
}
iput (inode);
}
......
......@@ -18,14 +18,10 @@
#include <linux/kernel.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";
......@@ -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++)
if (tmp & (1 << j))
break;
__asm__ ("btsl %1,%2\n\tsetb %0": \
"=q" (res):"r" (j),"m" (bmap[i]));
if (res) {
if (set_bit(j,bmap+i)) {
start_bit=j + (i << 5) + 1;
goto repeat;
}
......@@ -241,7 +235,7 @@ void xiafs_free_zone(struct super_block * sb, int d_addr)
if (!bh)
return;
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"
" block bit %u (0x%x) already cleared (%s %d)\n",
sb->s_dev, bit, bit, WHERE_ERR);
......@@ -301,7 +295,7 @@ void xiafs_free_inode(struct inode * inode)
if (!bh)
return;
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"
"inode bit %ld (0x%lx) already cleared (%s %d)\n",
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);
#define FIBMAP 1 /* bmap access */
#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];
struct buffer_head {
......@@ -174,6 +167,38 @@ struct buffer_head {
#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 {
dev_t i_dev;
unsigned long i_ino;
......@@ -331,7 +356,7 @@ struct inode_operations {
struct super_operations {
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 (*put_inode) (struct inode *);
void (*put_super) (struct super_block *);
......@@ -435,7 +460,7 @@ extern void sync_dev(dev_t dev);
extern int fsync_dev(dev_t dev);
extern void sync_supers(dev_t dev);
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 lnamei(const char * pathname, struct inode ** res_inode);
extern int permission(struct inode * inode,int mask);
......@@ -483,6 +508,9 @@ extern int file_fsync(struct inode *, struct file *);
extern void dcache_add(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)
{
return __iget(sb,nr,1);
......
......@@ -8,6 +8,7 @@
*/
/* 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_ERROR 0x1f1 /* see err-bits */
#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
......@@ -16,10 +17,12 @@
#define HD_HCYL 0x1f5 /* high byte of starting cyl */
#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
#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_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 */
#define ERR_STAT 0x01
......@@ -41,7 +44,9 @@
#define WIN_SEEK 0x70
#define WIN_DIAGNOSE 0x90
#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_MULTWRITE 0xC5 /* write multiple sectors */
#define WIN_SETMULT 0xC6 /* enable read multiple */
......@@ -56,25 +61,29 @@
#define ECC_ERR 0x40 /* Uncorrectable ECC error */
#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 {
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
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 {
unsigned short config; /* lots of obsolete bit flags */
unsigned short cyls; /* "physical" cyls */
......@@ -124,3 +133,4 @@ struct hd_driveid {
/* unsigned short vendor7 [32];*/ /* vendor unique (words 128-159) */
/* unsigned short reservedyy[96];*/ /* reserved (words 160-255) */
};
#endif
......@@ -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 void msdos_read_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 */
......
......@@ -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 void sysv_write_super(struct super_block *);
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_put_inode(struct inode *);
extern void sysv_statfs(struct super_block *, struct statfs *);
......
......@@ -77,7 +77,7 @@ void umsdos_patch_inode (struct inode *inode,
int umsdos_get_dirowner (struct inode *inode, struct inode **result);
void UMSDOS_read_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,
void *data,
int silent);
......
......@@ -157,7 +157,7 @@ static char fpu_error = 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;
int i=1;
......@@ -253,6 +253,11 @@ static void calibrate_delay(void)
printk("Calibrating delay loop.. ");
while (loops_per_sec <<= 1) {
/* wait for "start of" clock tick */
ticks = jiffies;
while (ticks == jiffies)
/* nothing */;
/* Go .. */
ticks = jiffies;
__delay(loops_per_sec);
ticks = jiffies - ticks;
......@@ -271,7 +276,7 @@ static void calibrate_delay(void)
}
printk("failed\n");
}
/*
* This is a simple kernel command line parsing function: it parses
......@@ -347,7 +352,7 @@ static void parse_options(char *line)
/*
* Then check if it's an environment variable or
* an option.
*/
*/
if (strchr(line,'=')) {
if (envs >= MAX_INIT_ENVS)
break;
......@@ -459,7 +464,7 @@ asmlinkage void start_kernel(void)
ipc_init();
#endif
sti();
/*
* check if exception 16 works correctly.. This is truly evil
* code: it disables the high 8 interrupts to make sure that
......
......@@ -45,8 +45,8 @@
#define set_flags(X,new,mask) \
((X) = ((X) & ~(mask)) | ((new) & (mask)))
#define SAFE_MASK (0x40DD5)
#define RETURN_MASK (0x40DFF)
#define SAFE_MASK (0xDD5)
#define RETURN_MASK (0xDFF)
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)
case 'p':
if (field_width == -1) {
field_width = 8;
field_width = 2*sizeof(void *);
flags |= ZEROPAD;
}
str = number(str,
......
......@@ -240,7 +240,7 @@ int copy_page_tables(struct task_struct * tsk)
continue;
if (old_pg_table >= high_memory || !(old_pg_table & PAGE_PRESENT)) {
printk("copy_page_tables: bad page table: "
"probable memory corruption");
"probable memory corruption\n");
*old_page_dir = 0;
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