VERSION = 1
PATCHLEVEL = 1
-SUBLEVEL = 56
+SUBLEVEL = 57
ARCH = i386
{ 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" */
};
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 */
}
}
-
+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 ){
FDCS->dor = newdor;
outb_p( newdor, FD_DOR);
}
- sti();
+ locked=0;
return olddor;
}
{
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 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);
)
DRS->flags &= ~FD_DISK_NEWCHANGE; /* effective seek */
DRS->track = ST1;
+ DRS->select_date = jiffies;
seek_floppy();
}
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;
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;
}
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;
}
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 ){
continue;
}
- if ( DRS->flags & FD_NEED_TWADDLE )
- twaddle();
floppy_tq.routine = (void *)(void *) floppy_start;
queue_task(&floppy_tq, &tq_timer);
#ifdef DEBUGT
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;
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);
static void floppy_release_irq_and_dma(void)
{
+ int i;
cli();
if (--usage_count){
sti();
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);
}
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;
{
struct hd_geometry *loc = (struct hd_geometry *) arg;
int dev, err;
+ unsigned long flags;
if ((!inode) || (!inode->i_rdev))
return -EINVAL;
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)
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)
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])
}
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;
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));
}
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
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]);
}
}
#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;
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);
*/
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);
}
/*
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
* 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;
}
*/
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);
}
/*
#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,
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;
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);
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);
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);
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);
}
/*
}
-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;
}
iput(inode);
return -EACCES;
}
+ flag &= ~O_TRUNC;
} else {
if (IS_RDONLY(inode) && (flag & 2)) {
iput(inode);
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;
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 *);
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)
inode->i_dirt = 0;
return error;
}
-
{
struct inode * inode;
int error;
+ struct iattr newattrs;
error = namei(path,&inode);
if (error)
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;
}
{
struct inode * inode;
struct file * file;
+ struct iattr newattrs;
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF;
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,
struct inode * inode;
long actime,modtime;
int error;
+ struct iattr newattrs;
error = namei(filename,&inode);
if (error)
}
actime = get_fs_long((unsigned long *) ×->actime);
modtime = get_fs_long((unsigned long *) ×->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;
}
{
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;
}
{
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;
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)
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);
}
/*
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 */
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,
* 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;
}
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;
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;
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);
}
/* 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;
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);
}
/*
*/
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
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));
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;
}
}
if (ret == 0){
oldinode->i_nlink++;
- ret = UMSDOS_notify_change (0,oldinode);
+ ret = UMSDOS_notify_change (0,NULL,oldinode);
}
iput (oldinode);
iput (dir);
iput (hdir);
}
}else{
- ret = UMSDOS_notify_change (0,inode);
+ ret = UMSDOS_notify_change (0,NULL,inode);
}
iput (inode);
}
#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";
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;
}
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);
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);
--- /dev/null
+#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 */
#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 {
#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;
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 *);
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);
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);
*/
/* 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 */
#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
#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 */
#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 */
/* unsigned short vendor7 [32];*/ /* vendor unique (words 128-159) */
/* unsigned short reservedyy[96];*/ /* reserved (words 160-255) */
};
+#endif
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 */
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 *);
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);
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;
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;
}
printk("failed\n");
}
-
+
/*
* This is a simple kernel command line parsing function: it parses
/*
* Then check if it's an environment variable or
* an option.
- */
+ */
if (strchr(line,'=')) {
if (envs >= MAX_INIT_ENVS)
break;
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
#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)
{
case 'p':
if (field_width == -1) {
- field_width = 8;
+ field_width = 2*sizeof(void *);
flags |= ZEROPAD;
}
str = number(str,
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;
}