From d8d9b8f76f22b7a16a83e261e64f89ee611f49df Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 1 Jun 1997 03:16:17 +0000 Subject: Initial revision --- fs/affs/Changes | 95 +++++++++++++++++++++++ fs/affs/amigaffs.c | 96 +++++++++++++++-------- fs/affs/bitmap.c | 52 ++++++------- fs/affs/dir.c | 25 +++--- fs/affs/file.c | 99 +++++++++++++----------- fs/affs/inode.c | 201 ++++++++++++++++++++++++++++++------------------ fs/affs/namei.c | 37 +++++---- fs/affs/symlink.c | 4 +- fs/autofs/.cvsignore | 1 + fs/autofs/Makefile | 29 +++++-- fs/autofs/autofs_i.h | 175 +++++++++++++++++++++++++++++++++++++++++ fs/autofs/dir.c | 2 +- fs/autofs/dirhash.c | 49 +++++++++++- fs/autofs/init.c | 27 ++++--- fs/autofs/inode.c | 11 ++- fs/autofs/root.c | 106 +++++++++++++++++++++---- fs/autofs/symlink.c | 2 +- fs/autofs/waitq.c | 18 +++-- fs/binfmt_elf.c | 104 +++++++++++++++---------- fs/buffer.c | 28 +++---- fs/dcache.c | 15 +++- fs/dquot.c | 3 +- fs/exec.c | 10 +-- fs/ext2/balloc.c | 55 ++++++++++--- fs/ext2/inode.c | 77 ++++++++++++++++++- fs/ext2/ioctl.c | 8 ++ fs/ext2/namei.c | 2 +- fs/ext2/super.c | 3 + fs/fcntl.c | 6 +- fs/file_table.c | 179 +++++++++++++++++------------------------- fs/inode.c | 12 +-- fs/isofs/dir.c | 5 ++ fs/isofs/inode.c | 8 +- fs/isofs/namei.c | 26 +------ fs/isofs/rock.c | 43 ++--------- fs/lockd/.cvsignore | 1 + fs/lockd/svcsubs.c | 8 +- fs/locks.c | 108 ++++++++++++++++++-------- fs/msdos/msdosfs_syms.c | 2 +- fs/namei.c | 22 ++---- fs/ncpfs/inode.c | 5 +- fs/nfs/nfsroot.c | 25 +++++- fs/nfs/write.c | 8 +- fs/nfsd/.cvsignore | 1 + fs/nfsd/vfs.c | 4 + fs/open.c | 2 +- fs/pipe.c | 11 ++- fs/proc/array.c | 87 +++++++++------------ fs/proc/base.c | 13 ++-- fs/proc/fd.c | 30 ++++---- fs/proc/inode.c | 21 +++-- fs/proc/link.c | 9 +-- fs/proc/mem.c | 18 ++--- fs/proc/root.c | 54 +++++++------ fs/romfs/.cvsignore | 1 + fs/smbfs/inode.c | 5 +- fs/super.c | 11 ++- fs/umsdos/namei.c | 3 + fs/vfat/namei.c | 2 + 59 files changed, 1344 insertions(+), 720 deletions(-) create mode 100644 fs/affs/Changes create mode 100644 fs/autofs/.cvsignore create mode 100644 fs/autofs/autofs_i.h create mode 100644 fs/lockd/.cvsignore create mode 100644 fs/nfsd/.cvsignore create mode 100644 fs/romfs/.cvsignore (limited to 'fs') diff --git a/fs/affs/Changes b/fs/affs/Changes new file mode 100644 index 000000000..a65dc326a --- /dev/null +++ b/fs/affs/Changes @@ -0,0 +1,95 @@ +(Note: I consider version numbers as cheap. That means +that I do not like numbers like 0.1 and the like for +things that can be used since quite some time. But +then, 3.1 doesn't mean 'perfectly stable', too.) + +Known bugs: +----------- + +- Doesn't work on the alpha. The only 64/32-bit + problem that I'm aware of (pointer/int conversion + in readdir()) gives compiler warnings but is + apparently not causing the failure, as directory + reads basically work (but all files are of size 0). + Alas, I've got no alpha to debug. :-( +- If an affs mounted filesystem is exported via + nfs, it cannot be written to. No networking to + test that, either. :-( + +Please direct bug reports to: hjw@zvw.de + +Version 3.4 +----------- + +- Hash chains are now sorted by block numbers. + (Thanks to Kars de Jong for finding this.) +- Removed all unnecessary external symbols. + +Version 3.3 +----------- + +- Tried to make all types 'correct' and consistent. +- Errors and warnings are now reported via a + function. They are all prefixed by a severity + and have the same appearance: + "AFFS: : " + (There's one exception to this, as in that function + is no pointer to the super block available.) +- The filesystem is remounted read-only after an + error. +- The names of newly created filesystem objects are + now checked for validity. +- Minor cleanups in comments. +- Added this Changes file. At last! + +Version 3.2 +----------- + +- Extension block cache: Reading/writing of huge files + (several MB) is much faster (of course the added + overhead slows down opening, but this is hardly + noticeable). +- The same get_block()-routine can now be used for + both OFS and FFS. +- The super block is now searched in the block that + was calculated and in the one following. This + should remedy the round-off error introduced by + the 1-k blocks that Linux uses. +- Minor changes to adhere to the new VFS interface. +- The number of used blocks is now also calculated + if the filesystem is mounted read-only. +- Prefixed some constants with AFFS_ to avoid name + clashes. +- Removed 'EXPERIMENTAL' status. + +Version 3.1 +----------- + +- Fixed a nasty bug which didn't allow read-only + mounts. +- Allow dir-cache filesystems to be mounted + read only. +- OFS support. +- Several other changes I just cannot remember + any more. + +Version 3.0 +----------- + +- Almost complete rewrite for the new VFS + interface in Linux 1.3. +- Write support. +- Support for hard and symbolic links. +- Lots of things I remeber even less ... + +Version 2.0 +----------- + +- Fixed a few things to get it compiled. +- Automatic root block calculation. +- Partition checker for genhd.c + +======================================== + +Let's just call Ray Burr's original affs +'Version 1.0'. diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 63d76a86e..4afd66e49 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -5,8 +5,10 @@ * * (C) 1993 Ray Burr - Amiga FFS filesystem. * + * Please send bug reports to: hjw@zvw.de */ +#include #include #include #include @@ -17,6 +19,8 @@ extern struct timezone sys_tz; +static char ErrorBuffer[256]; + /* * Functions for accessing Amiga-FFS structures. * @@ -28,7 +32,7 @@ extern struct timezone sys_tz; 0 is returned. Otherwise, the key number in the next used hash slot is returned. */ -int +static int affs_find_next_hash_entry(int hsize, void *dir_data, int *hash_pos) { struct dir_front *dir_front = dir_data; @@ -54,24 +58,23 @@ affs_get_file_name(int bsize, void *fh_data, char **name) file_end = GET_END_PTR(struct file_end, fh_data, bsize); if (file_end->file_name[0] == 0 || file_end->file_name[0] > 30) { - printk ("affs_get_file_name: OOPS! bad filename\n"); - printk (" file_end->file_name[0] = %d\n", + printk(KERN_WARNING "AFFS: bad filename (length=%d chars)\n", file_end->file_name[0]); *name = "***BAD_FILE***"; return 14; } - *name = (char *) &file_end->file_name[1]; + *name = (char *)&file_end->file_name[1]; return file_end->file_name[0]; } /* Find the predecessor in the hash chain */ int -affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey) +affs_fix_hash_pred(struct inode *startino, int startoffset, s32 key, s32 newkey) { struct buffer_head *bh = NULL; - int nextkey; - int ptype, stype; + s32 nextkey; + s32 ptype, stype; int retval; nextkey = startino->i_ino; @@ -87,14 +90,14 @@ affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey) || ptype != T_SHORT || (stype != ST_FILE && stype != ST_USERDIR && stype != ST_LINKFILE && stype != ST_LINKDIR && stype != ST_ROOT && stype != ST_SOFTLINK)) { - printk("AFFS: bad block found in link chain (ptype=%d, stype=%d)\n", - ptype,stype); + affs_error(startino->i_sb,"affs_fix_hash_pred", + "Bad block in link chain (ptype=%d, stype=%d)",ptype,stype); affs_brelse(bh); break; } - nextkey = htonl(((__u32 *)bh->b_data)[startoffset]); + nextkey = htonl(((s32 *)bh->b_data)[startoffset]); if (nextkey == key) { - ((__u32 *)bh->b_data)[startoffset] = newkey; + ((s32 *)bh->b_data)[startoffset] = newkey; affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5); mark_buffer_dirty(bh,1); affs_brelse(bh); @@ -112,13 +115,13 @@ affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey) /* Remove inode from link chain */ int -affs_fix_link_pred(struct inode *startino, int key, int newkey) +affs_fix_link_pred(struct inode *startino, s32 key, s32 newkey) { struct buffer_head *bh = NULL; - int nextkey; + s32 nextkey; int offset; - int etype = 0; - int ptype, stype; + s32 etype = 0; + s32 ptype, stype; int retval; offset = AFFS_I2BSIZE(startino) / 4 - 10; @@ -150,7 +153,7 @@ affs_fix_link_pred(struct inode *startino, int key, int newkey) retval = -EPERM; break; } - nextkey = htonl(((__u32 *)bh->b_data)[offset]); + nextkey = htonl(((s32 *)bh->b_data)[offset]); if (nextkey == key) { FILE_END(bh->b_data,startino)->link_chain = newkey; affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5); @@ -172,17 +175,17 @@ affs_fix_link_pred(struct inode *startino, int key, int newkey) (which lets us calculate the block size). Returns non-zero if the block is not consistent. */ -__u32 -affs_checksum_block(int bsize, void *data, int *ptype, int *stype) +u32 +affs_checksum_block(int bsize, void *data, s32 *ptype, s32 *stype) { - __u32 sum; - __u32 *p; + u32 sum; + u32 *p; bsize /= 4; if (ptype) - *ptype = htonl(((__s32 *)data)[0]); + *ptype = htonl(((s32 *)data)[0]); if (stype) - *stype = htonl(((__s32 *)data)[bsize - 1]); + *stype = htonl(((s32 *)data)[bsize - 1]); sum = 0; p = data; @@ -194,20 +197,20 @@ affs_checksum_block(int bsize, void *data, int *ptype, int *stype) void affs_fix_checksum(int bsize, void *data, int cspos) { - __u32 ocs; - __u32 cs; + u32 ocs; + u32 cs; cs = affs_checksum_block(bsize,data,NULL,NULL); - ocs = htonl (((__u32 *)data)[cspos]); + ocs = htonl (((u32 *)data)[cspos]); ocs -= cs; - ((__u32 *)data)[cspos] = htonl(ocs); + ((u32 *)data)[cspos] = htonl(ocs); } void -secs_to_datestamp(int secs, struct DateStamp *ds) +secs_to_datestamp(time_t secs, struct DateStamp *ds) { - __u32 days; - __u32 minute; + u32 days; + u32 minute; secs -= sys_tz.tz_minuteswest * 60 +((8 * 365 + 2) * 24 * 60 * 60); if (secs < 0) @@ -223,7 +226,7 @@ secs_to_datestamp(int secs, struct DateStamp *ds) } int -prot_to_mode(__u32 prot) +prot_to_mode(u32 prot) { int mode = 0; @@ -249,10 +252,10 @@ prot_to_mode(__u32 prot) return mode; } -unsigned int +u32 mode_to_prot(int mode) { - unsigned int prot = 0; + u32 prot = 0; if (mode & S_IXUSR) prot |= FIBF_SCRIPT; @@ -271,3 +274,32 @@ mode_to_prot(int mode) return prot; } + +void +affs_error(struct super_block *sb, const char *function, const char *fmt, ...) +{ + va_list args; + + va_start(args,fmt); + vsprintf(ErrorBuffer,fmt,args); + va_end(args); + + printk(KERN_CRIT "AFFS error (device %s): %s(): %s\n",kdevname(sb->s_dev), + function,ErrorBuffer); + if (!(sb->s_flags & MS_RDONLY)) + printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n"); + sb->s_flags |= MS_RDONLY; +} + +void +affs_warning(struct super_block *sb, const char *function, const char *fmt, ...) +{ + va_list args; + + va_start(args,fmt); + vsprintf(ErrorBuffer,fmt,args); + va_end(args); + + printk(KERN_WARNING "AFFS error (device %s): %s(): %s\n",kdevname(sb->s_dev), + function,ErrorBuffer); +} diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index 1d69d5a3d..a7382db4c 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c @@ -3,7 +3,6 @@ * * (c) 1996 Hans-Joachim Widmaier * - * * bitmap.c contains the code that handles all bitmap related stuff - * block allocation, deallocation, calculation of free space. */ @@ -54,7 +53,7 @@ affs_count_free_blocks(struct super_block *s) } void -affs_free_block(struct super_block *sb, int block) +affs_free_block(struct super_block *sb, s32 block) { int bmap; int bit; @@ -70,7 +69,7 @@ affs_free_block(struct super_block *sb, int block) zone_no = (bmap << (sb->s_blocksize_bits - 7)) + bit / 1024; bm = &sb->u.affs_sb.s_bitmap[bmap]; if (bmap >= sb->u.affs_sb.s_bm_count) { - printk("AFFS: free_block(): block %d outside partition.\n",block); + affs_error(sb,"affs_free_block","Block %d outside partition",block); return; } blk = 0; @@ -83,15 +82,16 @@ affs_free_block(struct super_block *sb, int block) if (!bm->bm_bh) { bm->bm_count--; unlock_super(sb); - printk("AFFS: free_block(): Cannot read bitmap block %d\n",bm->bm_key); + affs_error(sb,"affs_free_block","Cannot read bitmap block %d",bm->bm_key); return; } } - if (set_bit(bit ^ BO_EXBITS,bm->bm_bh->b_data + 4)) - printk("AFFS: free_block(): block %d is already free.\n",block); + if (test_and_set_bit(bit ^ BO_EXBITS,bm->bm_bh->b_data + 4)) + affs_warning(sb,"affs_free_block","Trying to free block %d which is already free", + block); else { sb->u.affs_sb.s_alloc[zone_no].az_free++; - ((__u32 *)bm->bm_bh->b_data)[0] = ntohl(htonl(((__u32 *)bm->bm_bh->b_data)[0]) - blk); + ((u32 *)bm->bm_bh->b_data)[0] = ntohl(htonl(((u32 *)bm->bm_bh->b_data)[0]) - blk); mark_buffer_dirty(bm->bm_bh,1); sb->s_dirt = 1; } @@ -102,15 +102,15 @@ affs_free_block(struct super_block *sb, int block) unlock_super(sb); } -static int +static s32 affs_balloc(struct inode *inode, int zone_no) { - __u32 w; - __u32 *bm; + u32 w; + u32 *bm; int fb; int i; int fwb; - int block; + s32 block; struct affs_zone *zone; struct affs_alloc_zone *az; struct super_block *sb; @@ -124,7 +124,7 @@ affs_balloc(struct inode *inode, int zone_no) pr_debug("AFFS: balloc(inode=%lu,zone=%d)\n",inode->i_ino,zone_no); az = &sb->u.affs_sb.s_alloc[zone->z_az_no]; - bm = (__u32 *)zone->z_bm->bm_bh->b_data; + bm = (u32 *)zone->z_bm->bm_bh->b_data; repeat: for (i = zone->z_start; i < zone->z_end; i++) { if (bm[i]) @@ -138,9 +138,9 @@ found: zone->z_start = i; w = ~htonl(bm[i]); fb = find_first_zero_bit(&w,32); - if (fb > 31 || !clear_bit(fb ^ BO_EXBITS,&bm[i])) { + if (fb > 31 || !test_and_clear_bit(fb ^ BO_EXBITS,&bm[i])) { unlock_super(sb); - printk("AFFS: balloc(): empty block disappeared somehow\n"); + affs_warning(sb,"balloc","Empty block disappeared somehow"); goto repeat; } block = fwb + fb; @@ -153,8 +153,8 @@ found: fb = find_next_zero_bit(&w,32,fb); if (fb > 31) break; - if (!clear_bit(fb ^ BO_EXBITS,&bm[i])) { - printk("AFFS: balloc(): empty block disappeared\n"); + if (!test_and_clear_bit(fb ^ BO_EXBITS,&bm[i])) { + affs_warning(sb,"balloc","Empty block disappeared somehow"); break; } inode->u.affs_i.i_data[inode->u.affs_i.i_pa_last++] = fwb + fb; @@ -204,7 +204,7 @@ affs_find_new_zone(struct super_block *sb, int zone_no) if (az->az_count) az->az_count--; else - printk("AFFS: find_new_zone(): az_count=0, but bm used\n"); + affs_error(sb,"find_new_zone","az_count=0, but bm used"); } while (1) { @@ -247,7 +247,7 @@ affs_find_new_zone(struct super_block *sb, int zone_no) bm->bm_count--; az->az_count--; unlock_super(sb); - printk("AFFS: find_new_zone(): Cannot read bitmap\n"); + affs_error(sb,"find_new_zone","Cannot read bitmap"); return 0; } zone->z_bm = bm; @@ -261,16 +261,16 @@ affs_find_new_zone(struct super_block *sb, int zone_no) return az->az_free; } -int +s32 affs_new_header(struct inode *inode) { - int block; + s32 block; struct buffer_head *bh; pr_debug("AFFS: new_header(ino=%lu)\n",inode->i_ino); if (!(block = affs_balloc(inode,0))) { - while(affs_find_new_zone(inode->i_sb,0)) { + while (affs_find_new_zone(inode->i_sb,0)) { if ((block = affs_balloc(inode,0))) goto init_block; schedule(); @@ -279,7 +279,7 @@ affs_new_header(struct inode *inode) } init_block: if (!(bh = getblk(inode->i_dev,block,AFFS_I2BSIZE(inode)))) { - printk("AFFS: balloc(): cannot read block %d\n",block); + affs_error(inode->i_sb,"new_header","Cannot read block %d",block); return 0; } memset(bh->b_data,0,AFFS_I2BSIZE(inode)); @@ -290,7 +290,7 @@ init_block: return block; } -int +s32 affs_new_data(struct inode *inode) { int empty, old; @@ -299,7 +299,7 @@ affs_new_data(struct inode *inode) struct super_block *sb; struct buffer_head *bh; int i = 0; - int block; + s32 block; pr_debug("AFFS: new_data(ino=%lu)\n",inode->i_ino); @@ -345,7 +345,7 @@ affs_new_data(struct inode *inode) found: zone = &sb->u.affs_sb.s_zones[i]; if (!(block = affs_balloc(inode,i))) { /* No data zones left */ - while(affs_find_new_zone(sb,i)) { + while (affs_find_new_zone(sb,i)) { if ((block = affs_balloc(inode,i))) goto init_block; schedule(); @@ -357,7 +357,7 @@ found: init_block: if (!(bh = getblk(inode->i_dev,block,sb->s_blocksize))) { - printk("AFFS: balloc(): cannot read block %u\n",block); + affs_error(inode->i_sb,"new_data","Cannot read block %d",block); return 0; } memset(bh->b_data,0,sb->s_blocksize); diff --git a/fs/affs/dir.c b/fs/affs/dir.c index f7ec42ede..8ae71e5bd 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -64,7 +64,7 @@ struct inode_operations affs_dir_inode_operations = { }; static long -affs_dir_read(struct inode * inode, struct file * filp, char * buf, unsigned long count) +affs_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count) { return -EISDIR; } @@ -73,19 +73,18 @@ static int affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t filldir) { int j, namelen; - int i; + s32 i; int hash_pos; int chain_pos; unsigned long ino; unsigned long old; - int stored; - char *name; - struct buffer_head *dir_bh; - struct buffer_head *fh_bh; - struct inode *dir; + int stored; + char *name; + struct buffer_head *dir_bh; + struct buffer_head *fh_bh; + struct inode *dir; pr_debug("AFFS: readdir(ino=%ld,f_pos=%lu)\n",inode->i_ino,filp->f_pos); - if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; @@ -122,7 +121,7 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t fil chain_pos = (filp->f_pos - 2) & 0xffff; hash_pos = (filp->f_pos - 2) >> 16; if (chain_pos == 0xffff) { - printk("AFFS: more than 65535 entries in chain\n"); + affs_warning(inode->i_sb,"readdir","More than 65535 entries in chain"); chain_pos = 0; hash_pos++; filp->f_pos = ((hash_pos << 16) | chain_pos) + 2; @@ -143,15 +142,15 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t fil * we can jump directly to where we left off. */ if (filp->private_data && filp->f_version == dir->i_version) { - i = (int)filp->private_data; + i = (s32)filp->private_data; j = 0; pr_debug("AFFS: readdir() left off=%d\n",i); } filp->f_version = dir->i_version; - pr_debug("AFFS: hash_pos=%lu chain_pos=%lu\n", hash_pos, chain_pos); + pr_debug("AFFS: hash_pos=%d chain_pos=%d\n",hash_pos,chain_pos); while (i) { if (!(fh_bh = affs_bread(inode->i_dev,i,AFFS_I2BSIZE(inode)))) { - printk("AFFS: readdir: Can't get block %d\n",i); + affs_error(inode->i_sb,"readdir","Cannot read block %d",i); goto readdir_done; } ino = i; @@ -164,7 +163,7 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t fil } if (fh_bh) { namelen = affs_get_file_name(AFFS_I2BSIZE(inode),fh_bh->b_data,&name); - pr_debug("AFFS: readdir(): filldir(..,\"%.*s\",ino=%lu), i=%lu\n", + pr_debug("AFFS: readdir(): filldir(..,\"%.*s\",ino=%lu), i=%d\n", namelen,name,ino,i); filp->private_data = (void *)ino; if (filldir(dirent,name,namelen,filp->f_pos,ino) < 0) diff --git a/fs/affs/file.c b/fs/affs/file.c index a450dffce..0fffbf41e 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -35,6 +35,8 @@ #error PAGE_SIZE must be at least 4096 #endif +static int affs_bmap(struct inode *inode, int block); +static struct buffer_head * affs_getblock(struct inode *inode, s32 block); static long affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned long count); static long affs_file_write(struct inode *inode, struct file *filp, const char *buf, @@ -200,7 +202,7 @@ index_to_seqnum(int index) return 128 + 192 * 2 + 128 * 4 + 64 * 16 + 32 * 64 + 64 * 256 + (index << 9); } -static int __inline__ +static s32 __inline__ calc_key(struct inode *inode, int *ext) { int index; @@ -226,28 +228,30 @@ calc_key(struct inode *inode, int *ext) return inode->u.affs_i.i_ec->ec[index]; } -int +static int affs_bmap(struct inode *inode, int block) { struct buffer_head *bh; - int ext, key, nkey; - int ptype, stype; + s32 key, nkey; + s32 ptype, stype; + int ext; int index; int keycount; struct key_cache *kc; struct key_cache *tkc; struct timeval tv; - __s32 *keyp; + s32 *keyp; int i; pr_debug("AFFS: bmap(%lu,%d)\n",inode->i_ino,block); if (block < 0) { - printk("affs_bmap: block < 0\n"); + affs_error(inode->i_sb,"bmap","Block < 0"); return 0; } if (!inode->u.affs_i.i_ec) { - printk("affs_bmap(): No ext_cache!?\n"); + affs_error(inode->i_sb,"bmap","No extension cache for open file (inode=%lu)", + inode->i_ino); return 0; } @@ -334,14 +338,14 @@ affs_bmap(struct inode *inode, int block) return key; } -struct buffer_head * -affs_getblock(struct inode *inode, int block) +static struct buffer_head * +affs_getblock(struct inode *inode, s32 block) { struct buffer_head *bh; struct buffer_head *ebh; struct buffer_head *pbh; struct key_cache *kc; - int key, nkey; + s32 key, nkey; int ext; int cf, j, pt; int index; @@ -372,7 +376,7 @@ affs_getblock(struct inode *inode, int block) return NULL; if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cf,&j) || cf != pt || j != ST_FILE) { - printk("AFFS: getblock(): inode %d is not a valid %s\n",key, + affs_error(inode->i_sb,"getblock","Inode %d is not a valid %s",key, pt == T_SHORT ? "file header" : "extension block"); affs_brelse(bh); return NULL; @@ -387,7 +391,8 @@ affs_getblock(struct inode *inode, int block) else pbh = affs_getblock(inode,inode->u.affs_i.i_lastblock); if (!pbh) { - printk("AFFS: getblock(): cannot get last block in file\n"); + affs_error(inode->i_sb,"getblock", + "Cannot get last block in file"); break; } } @@ -397,7 +402,7 @@ affs_getblock(struct inode *inode, int block) lock_super(inode->i_sb); if (AFFS_BLOCK(bh->b_data,inode,j)) { unlock_super(inode->i_sb); - printk("AFFS: getblock(): block already allocated\n"); + affs_warning(inode->i_sb,"getblock","Block already allocated"); affs_free_block(inode->i_sb,nkey); j++; continue; @@ -407,7 +412,8 @@ affs_getblock(struct inode *inode, int block) if (ofs) { ebh = affs_bread(inode->i_dev,nkey,AFFS_I2BSIZE(inode)); if (!ebh) { - printk("AFFS: getblock(): cannot get block %d\n",nkey); + affs_error(inode->i_sb,"getblock", + "Cannot get block %d",nkey); affs_free_block(inode->i_sb,nkey); AFFS_BLOCK(bh->b_data,inode,j) = 0; break; @@ -492,10 +498,6 @@ affs_getblock(struct inode *inode, int block) return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); } -/* This could be made static, regardless of what the former comment said. - * You cannot directly read affs directories. - */ - static long affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned long count) { @@ -508,12 +510,12 @@ affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned l pr_debug("AFFS: file_read_ofs(ino=%lu,pos=%lu,%d)\n",inode->i_ino,(long)filp->f_pos,count); if (!inode) { - printk("affs_file_read: inode = NULL\n"); + affs_error(inode->i_sb,"file_read_ofs","Inode = NULL"); return -EINVAL; } blocksize = AFFS_I2BSIZE(inode) - 24; if (!(S_ISREG(inode->i_mode))) { - pr_debug("affs_file_read: mode = %07o\n",inode->i_mode); + pr_debug("affs_file_read: mode = %07o",inode->i_mode); return -EINVAL; } if (filp->f_pos >= inode->i_size || count <= 0) @@ -524,10 +526,10 @@ affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned l left = MIN (inode->i_size - filp->f_pos,count - (buf - start)); if (!left) break; - sector = affs_bmap(inode,(__u32)filp->f_pos / blocksize); + sector = affs_bmap(inode,(u32)filp->f_pos / blocksize); if (!sector) break; - offset = (__u32)filp->f_pos % blocksize; + offset = (u32)filp->f_pos % blocksize; bh = affs_bread(inode->i_dev,sector,AFFS_I2BSIZE(inode)); if (!bh) break; @@ -554,25 +556,31 @@ affs_file_write(struct inode *inode, struct file *filp, const char *buf, unsigne struct inode *ino; char *p; + /* Not that I wanted to be POSIX compliant ... */ + if (!count) + return 0; pr_debug("AFFS: file_write(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino, (unsigned long)filp->f_pos,count); ino = NULL; if (!inode) { - printk("AFFS: file_write(): inode=NULL\n"); + affs_error(inode->i_sb,"file_write","Inode = NULL"); return -EINVAL; } if (inode->u.affs_i.i_original) { ino = iget(inode->i_sb,inode->u.affs_i.i_original); if (!ino) { - printk("AFFS: could not follow link from inode %lu to %d\n", - inode->i_ino,inode->u.affs_i.i_original); + affs_error(inode->i_sb,"file_write", + "Could not follow link from inode %lu to %d", + inode->i_ino,inode->u.affs_i.i_original); return -EINVAL; } inode = ino; } if (!S_ISREG(inode->i_mode)) { - printk("AFFS: file_write(): mode=%07o\n",inode->i_mode); + affs_error(inode->i_sb,"file_write", + "Trying to write to non-regular file (mode=%07o)", + inode->i_mode); iput(inode); return -EINVAL; } @@ -636,22 +644,27 @@ affs_file_write_ofs(struct inode *inode, struct file *filp, const char *buf, uns pr_debug("AFFS: file_write_ofs(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino, (unsigned long)filp->f_pos,count); + if (!count) + return 0; if (!inode) { - printk("AFFS: file_write_ofs(): inode=NULL\n"); + affs_error(inode->i_sb,"file_write_ofs","Inode = NULL"); return -EINVAL; } ino = NULL; if (inode->u.affs_i.i_original) { ino = iget(inode->i_sb,inode->u.affs_i.i_original); if (!ino) { - printk("AFFS: could not follow link from inode %lu to %d\n", - inode->i_ino,inode->u.affs_i.i_original); + affs_error(inode->i_sb,"file_write_ofs", + "Could not follow link from inode %lu to %d", + inode->i_ino,inode->u.affs_i.i_original); return -EINVAL; } inode = ino; } if (!S_ISREG(inode->i_mode)) { - printk("AFFS: file_write_ofs(): mode=%07o\n",inode->i_mode); + affs_error(inode->i_sb,"file_write_ofs", + "Trying to write to non-regular file (mode=%07o)", + inode->i_mode); iput(inode); return -EINVAL; } @@ -714,10 +727,10 @@ affs_truncate(struct inode *inode) struct affs_zone *zone; int first; int block; - int key; - int *keyp; - int ekey; - int ptype, stype; + s32 key; + s32 *keyp; + s32 ekey; + s32 ptype, stype; int freethis; int blocksize; int rem; @@ -729,8 +742,8 @@ affs_truncate(struct inode *inode) if (inode->u.affs_i.i_original) { ino = iget(inode->i_sb,inode->u.affs_i.i_original); if (!ino) { - printk("AFFS: truncate(): cannot follow link from %lu to %u\n", - inode->i_ino,inode->u.affs_i.i_original); + affs_error(inode->i_sb,"truncate","Cannot follow link from %lu to %d", + inode->i_ino,inode->u.affs_i.i_original); return; } inode = ino; @@ -754,7 +767,7 @@ affs_truncate(struct inode *inode) unlock_super(inode->i_sb); } if (!bh) { - printk("AFFS: truncate(): Cannot extend file\n"); + affs_error(inode->i_sb,"truncate","Cannot extend file"); inode->i_size = blocksize * (inode->u.affs_i.i_lastblock + 1); } else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) { rem = inode->i_size % blocksize; @@ -771,7 +784,7 @@ affs_truncate(struct inode *inode) while (ekey) { if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) { - printk("AFFS: truncate(): Can't read block %d\n",ekey); + affs_error(inode->i_sb,"truncate","Cannot read block %d",ekey); break; } ptype = htonl(((struct file_front *)bh->b_data)->primary_type); @@ -783,14 +796,14 @@ affs_truncate(struct inode *inode) break; } if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) { - printk("AFFS: truncate(): bad block (ptype=%d, stype=%d)\n", - ptype,stype); + affs_error(inode->i_sb,"truncate","Bad block (ptype=%d, stype=%d)", + ptype,stype); affs_brelse(bh); break; } /* Do not throw away file header */ freethis = first == 0 && ekey != inode->i_ino; - for ( block = first; block < AFFS_I2HSIZE(inode); block++) { + for (block = first; block < AFFS_I2HSIZE(inode); block++) { keyp = &AFFS_BLOCK(bh->b_data,inode,block); key = htonl(*keyp); if (key) { @@ -853,7 +866,7 @@ static int affs_open_file(struct inode *inode, struct file *filp) { int error; - int key; + u32 key; int i; pr_debug("AFFS: open_file(ino=%lu)\n",inode->i_ino); @@ -864,7 +877,7 @@ affs_open_file(struct inode *inode, struct file *filp) if (!inode->u.affs_i.i_ec) { inode->u.affs_i.i_ec = (struct ext_cache *)get_free_page(GFP_KERNEL); if (!inode->u.affs_i.i_ec) { - printk("AFFS: cache allocation failed\n"); + affs_error(inode->i_sb,"open_file","Cache allocation failed"); error = ENOMEM; } else { /* We only have to initialize non-zero values. diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 9b6626f7d..654a8ca61 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -30,12 +30,26 @@ #include #include +/* AmigaOS allows file names with up to 30 characters length. + * Names longer than that will be silently truncated. If you + * want to disallow this, comment out the following #define. + * Creating filesystem objects with longer names will then + * result in an error (ENAMETOOLONG). + */ +/*#define NO_TRUNCATE */ + extern int *blk_size[]; extern struct timezone sys_tz; #define MIN(a,b) (((a)<(b))?(a):(b)) -void +static int affs_notify_change(struct inode *inode, struct iattr *attr); +static void affs_put_inode(struct inode *inode); +static void affs_read_inode(struct inode *inode); +static void affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static void affs_write_inode(struct inode *inode); + +static void affs_put_super(struct super_block *sb) { int i; @@ -110,13 +124,13 @@ static struct super_operations affs_sops = { NULL /* remount */ }; -int +unsigned long affs_parent_ino(struct inode *dir) { int root_ino = (dir->i_sb->u.affs_sb.s_root_block); if (!S_ISDIR (dir->i_mode)) { - printk ("affs_parent_ino: argument is not a directory\n"); + affs_error(dir->i_sb,"parent_ino","Trying to get parent of non-directory"); return root_ino; } if (dir->i_ino == root_ino) @@ -125,7 +139,7 @@ affs_parent_ino(struct inode *dir) } static int -parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, int *root, +parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root, int *blocksize, char **prefix, char *volume, unsigned long *mount_opts) { char *this_char, *value; @@ -150,14 +164,14 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i *value++ = 0; if (!strcmp(this_char,"protect")) { if (value) { - printk("AFFS: option protect does not take an argument\n"); + printk("AFFS: Option protect does not take an argument\n"); return 0; } *mount_opts |= SF_IMMUTABLE; } else if (!strcmp(this_char,"verbose")) { if (value) { - printk("AFFS: option verbose does not take an argument\n"); + printk("AFFS: Option verbose does not take an argument\n"); return 0; } *mount_opts |= SF_VERBOSE; @@ -166,7 +180,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i if (!value) *uid = current->uid; else if (!*value) { - printk("AFFS: argument for uid option missing\n"); + printk("AFFS: Argument for uid option missing\n"); return 0; } else { *uid = simple_strtoul(value,&value,0); @@ -180,7 +194,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i if (!value) *gid = current->gid; else if (!*value) { - printk("AFFS: argument for gid option missing\n"); + printk("AFFS: Argument for gid option missing\n"); return 0; } else { *gid = simple_strtoul(value,&value,0); @@ -248,7 +262,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i return 0; if (*blocksize != 512 && *blocksize != 1024 && *blocksize != 2048 && *blocksize != 4096) { - printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed).\n"); + printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); return 0; } } @@ -270,21 +284,21 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i * hopefully have the guts to do so. Until then: sorry for the mess. */ -struct super_block * +static struct super_block * affs_read_super(struct super_block *s,void *data, int silent) { struct buffer_head *bh = NULL; struct buffer_head *bb; kdev_t dev = s->s_dev; - int root_block; + s32 root_block; int size; - __u32 chksum; - __u32 *bm; - int ptype, stype; + u32 chksum; + u32 *bm; + s32 ptype, stype; int mapidx; int num_bm; int i, j; - int key; + s32 key; int blocksize; uid_t uid; gid_t gid; @@ -300,7 +314,7 @@ affs_read_super(struct super_block *s,void *data, int silent) if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, &blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) { s->s_dev = 0; - printk("AFFS: error parsing options.\n"); + printk(KERN_ERR "AFFS: Error parsing options\n"); MOD_DEC_USE_COUNT; return NULL; } @@ -324,13 +338,13 @@ affs_read_super(struct super_block *s,void *data, int silent) if (size == 0) { s->s_dev = 0; unlock_super(s); - printk("affs_read_super: could not determine device size\n"); + printk(KERN_ERR "AFFS: Could not determine device size\n"); goto out; } s->u.affs_sb.s_partition_size = size; s->u.affs_sb.s_reserved = reserved; - /* Try to find root block. Its location may depend on the block size. */ + /* Try to find root block. Its location depends on the block size. */ s->u.affs_sb.s_hashsize = 0; if (blocksize > 0) { @@ -358,12 +372,12 @@ affs_read_super(struct super_block *s,void *data, int silent) * block behind the calculated one. So we check this one, too. */ for (num_bm = 0; num_bm < 2; num_bm++) { - pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %d, " + pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %u, " "size=%d blocks, %d reserved\n",kdevname(dev),blocksize, s->u.affs_sb.s_root_block + num_bm,size,reserved); bh = affs_bread(dev,s->u.affs_sb.s_root_block + num_bm,blocksize); if (!bh) { - printk("AFFS: unable to read root block\n"); + printk(KERN_ERR "AFFS: Cannot read root block\n"); goto out; } if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) && @@ -383,7 +397,8 @@ affs_read_super(struct super_block *s,void *data, int silent) if (!key) { affs_brelse(bh); if (!silent) - printk("AFFS: Can't find a valid root block on device %s\n",kdevname(dev)); + printk(KERN_ERR "AFFS: Cannot find a valid root block on device %s\n", + kdevname(dev)); goto out; } root_block = s->u.affs_sb.s_root_block; @@ -396,7 +411,7 @@ affs_read_super(struct super_block *s,void *data, int silent) /* Find out which kind of FS we have */ bb = affs_bread(dev,0,s->s_blocksize); if (bb) { - chksum = htonl(*(__u32 *)bb->b_data); + chksum = htonl(*(u32 *)bb->b_data); /* Dircache filesystems are compatible with non-dircache ones * when reading. As long as they aren't supported, writing is @@ -404,7 +419,8 @@ affs_read_super(struct super_block *s,void *data, int silent) */ if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) { - printk("AFFS: Dircache FS - mounting %s read only.\n",kdevname(dev)); + printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", + kdevname(dev)); s->s_flags |= MS_RDONLY; } switch (chksum) { @@ -436,22 +452,22 @@ affs_read_super(struct super_block *s,void *data, int silent) s->u.affs_sb.s_flags |= SF_INTL | SF_OFS; break; default: - printk("AFFS: Unknown filesystem on device %s: %08X\n", - kdevname(dev),chksum); + printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n", + kdevname(dev),chksum); affs_brelse(bb); goto out; } affs_brelse(bb); } else { - printk("AFFS: Can't get boot block.\n"); + printk(KERN_ERR "AFFS: Cannot read boot block\n"); goto out; } if (mount_flags & SF_VERBOSE) { chksum = ntohl(chksum); - printk("AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", - GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0], - &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1], - (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); + printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", + GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0], + &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1], + (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); } s->s_magic = AFFS_SUPER_MAGIC; @@ -459,7 +475,7 @@ affs_read_super(struct super_block *s,void *data, int silent) /* Keep super block in cache */ if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) { - printk("AFFS: Can't read root block a second time\n"); + printk(KERN_ERR "AFFS: Cannot read root block\n"); goto out; } @@ -473,7 +489,7 @@ affs_read_super(struct super_block *s,void *data, int silent) MAX_ZONES * sizeof(struct affs_zone); pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype); if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype,GFP_KERNEL))) { - printk("AFFS: Not enough memory.\n"); + printk(KERN_ERR "AFFS: Not enough memory\n"); goto out; } memset(s->u.affs_sb.s_bitmap,0,ptype); @@ -486,7 +502,8 @@ affs_read_super(struct super_block *s,void *data, int silent) if (ROOT_END_S(bh->b_data,s)->bm_flag == 0) { if (!(s->s_flags & MS_RDONLY)) { - printk("AFFS: Bitmap invalid - mounting %s read only.\n",kdevname(dev)); + printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n", + kdevname(dev)); s->s_flags |= MS_RDONLY; } affs_brelse(bh); @@ -504,17 +521,17 @@ affs_read_super(struct super_block *s,void *data, int silent) offset = s->u.affs_sb.s_reserved; az_no = 0; while (bh) { - bm = (__u32 *)bh->b_data; + bm = (u32 *)bh->b_data; for (i = ptype; i < stype && bm[i]; i++, mapidx++) { if (mapidx >= num_bm) { - printk("AFFS: Not enough bitmap space!?\n"); + printk(KERN_ERR "AFFS: Not enough bitmap space!?\n"); goto out; } bb = affs_bread(s->s_dev,htonl(bm[i]),s->s_blocksize); if (bb) { if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) && !(s->s_flags & MS_RDONLY)) { - printk("AFFS: Bitmap (%d,key=%lu) invalid - " + printk(KERN_WARNING "AFFS: Bitmap (%d,key=%lu) invalid - " "mounting %s read only.\n",mapidx,htonl(bm[i]), kdevname(dev)); s->s_flags |= MS_RDONLY; @@ -525,7 +542,7 @@ affs_read_super(struct super_block *s,void *data, int silent) key = size & 0x1F; /* used bits */ if (key) { chksum = ntohl(0x7FFFFFFF >> (31 - key)); - ((__u32 *)bb->b_data)[ptype] &= chksum; + ((u32 *)bb->b_data)[ptype] &= chksum; affs_fix_checksum(s->s_blocksize,bb->b_data,0); mark_buffer_dirty(bb,1); } @@ -551,7 +568,7 @@ affs_read_super(struct super_block *s,void *data, int silent) } affs_brelse(bb); } else { - printk("AFFS: Can't read bitmap.\n"); + printk(KERN_ERR "AFFS: Cannot read bitmap\n"); goto out; } } @@ -561,14 +578,14 @@ affs_read_super(struct super_block *s,void *data, int silent) affs_brelse(bh); if (key) { if (!(bh = affs_bread(s->s_dev,key,s->s_blocksize))) { - printk("AFFS: Can't read bitmap extension.\n"); + printk(KERN_ERR "AFFS: Cannot read bitmap extension\n"); goto out; } } else bh = NULL; } if (mapidx != num_bm) { - printk("AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm); + printk(KERN_ERR "AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm); goto out; } nobitmap: @@ -584,7 +601,7 @@ nobitmap: if (!(s->s_mounted)) { s->s_dev = 0; - printk("AFFS: get root inode failed\n"); + printk(KERN_ERR "AFFS: get root inode failed\n"); MOD_DEC_USE_COUNT; return NULL; } @@ -615,7 +632,7 @@ nobitmap: return NULL; } -void +static void affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { int free; @@ -635,15 +652,15 @@ affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) copy_to_user(buf,&tmp,bufsiz); } -void +static void affs_read_inode(struct inode *inode) { struct buffer_head *bh, *lbh; struct file_front *file_front; struct file_end *file_end; - int block; + s32 block; unsigned long prot; - int ptype, stype; + s32 ptype, stype; unsigned short id; pr_debug("AFFS: read_inode(%lu)\n",inode->i_ino); @@ -651,12 +668,12 @@ affs_read_inode(struct inode *inode) lbh = NULL; block = inode->i_ino; if (!(bh = affs_bread(inode->i_dev,block,AFFS_I2BSIZE(inode)))) { - printk("AFFS: unable to read i-node block %d\n",block); + affs_error(inode->i_sb,"read_inode","Cannot read block %d",block); return; } if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) || ptype != T_SHORT) { - printk("AFFS: read_inode(): checksum or type (ptype=%d) error on inode %d\n", - ptype,block); + affs_error(inode->i_sb,"read_inode", + "Checksum or type (ptype=%d) error on inode %d",ptype,block); affs_brelse(bh); return; } @@ -735,7 +752,8 @@ affs_read_inode(struct inode *inode) if (!(lbh = affs_bread(inode->i_dev,inode->u.affs_i.i_original, AFFS_I2BSIZE(inode)))) { affs_brelse(bh); - printk("AFFS: unable to read i-node block %ld\n",inode->i_ino); + affs_error(inode->i_sb,"read_inode","Cannot read block %lu", + inode->i_ino); return; } file_end = GET_END_PTR(struct file_end,lbh->b_data,AFFS_I2BSIZE(inode)); @@ -776,12 +794,13 @@ affs_read_inode(struct inode *inode) inode->i_op = &affs_symlink_inode_operations; } -void +static void affs_write_inode(struct inode *inode) { - struct buffer_head *bh; - struct file_end *file_end; - short uid, gid; + struct buffer_head *bh; + struct file_end *file_end; + uid_t uid; + gid_t gid; pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino); @@ -789,8 +808,7 @@ affs_write_inode(struct inode *inode) if (!inode->i_nlink) return; if (!(bh = bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)))) { - printk("AFFS: Unable to read block of inode %ld on %s\n", - inode->i_ino,kdevname(inode->i_dev)); + affs_error(inode->i_sb,"write_inode","Cannot read block %lu",inode->i_ino); return; } file_end = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode)); @@ -820,7 +838,7 @@ affs_write_inode(struct inode *inode) brelse(bh); } -int +static int affs_notify_change(struct inode *inode, struct iattr *attr) { int error; @@ -848,7 +866,7 @@ affs_notify_change(struct inode *inode, struct iattr *attr) return 0; } -void +static void affs_put_inode(struct inode *inode) { pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",inode->i_ino,inode->i_nlink); @@ -867,7 +885,7 @@ affs_new_inode(const struct inode *dir) { struct inode *inode; struct super_block *sb; - int block; + s32 block; if (!dir || !(inode = get_empty_inode())) return NULL; @@ -918,7 +936,10 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, struct buffer_head *dir_bh; struct buffer_head *inode_bh; struct buffer_head *link_bh; - int hash; + struct buffer_head *ibh; + int retval; + int i; + s32 next; pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%d\n",dir->i_ino,inode->i_ino, len,name,type); @@ -926,34 +947,60 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, dir_bh = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir)); inode_bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)); link_bh = NULL; - if (!dir_bh || !inode_bh) { - affs_brelse(dir_bh); - affs_brelse(inode_bh); - return -ENOSPC; - } + retval = -EIO; + if (!dir_bh || !inode_bh) + goto addentry_done; if (link) { link_bh = affs_bread(link->i_dev,link->i_ino,AFFS_I2BSIZE(link)); - if (!link_bh) { - affs_brelse(dir_bh); - affs_brelse(inode_bh); - return -EINVAL; - } + if (!link_bh) + goto addentry_done; } ((struct dir_front *)inode_bh->b_data)->primary_type = ntohl(T_SHORT); ((struct dir_front *)inode_bh->b_data)->own_key = ntohl(inode->i_ino); - if (len > 30) /* truncate name quietly */ + retval = -ENAMETOOLONG; + if (len > 30) +#ifdef NO_TRUNCATE + goto addentry_done; +#else len = 30; +#endif + + /* Check if name is valid */ + retval = -EINVAL; + for (i = 0; i < len; i++) { + if (name[i] < ' ' || name[i] == ':' + || ((unsigned char)name[i] > 0x7e && (unsigned char)name[i] < 0xa0)) + goto addentry_done; + } + retval = 0; DIR_END(inode_bh->b_data,inode)->dir_name[0] = len; strncpy(DIR_END(inode_bh->b_data,inode)->dir_name + 1,name,len); DIR_END(inode_bh->b_data,inode)->secondary_type = ntohl(type); DIR_END(inode_bh->b_data,inode)->parent = ntohl(dir->i_ino); - hash = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir)); + + i = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir)) + 6; + next = dir->i_ino; + + /* Alas, we have to search the insertion point with a locked sb */ lock_super(inode->i_sb); - DIR_END(inode_bh->b_data,inode)->hash_chain = - ((struct dir_front *)dir_bh->b_data)->hashtable[hash]; - ((struct dir_front *)dir_bh->b_data)->hashtable[hash] = ntohl(inode->i_ino); + while (1) { + if (!(ibh = affs_bread(dir->i_dev,next,AFFS_I2BSIZE(dir)))) + goto addentry_done; + next = htonl(((s32 *)ibh->b_data)[i]); + if (!next || next > inode->i_ino) + break; + i = AFFS_I2BSIZE(dir) / 4 - 4; + affs_brelse(ibh); + } + + DIR_END(inode_bh->b_data,inode)->hash_chain = next; + ((s32 *)ibh->b_data)[i] = ntohl(inode->i_ino); + affs_fix_checksum(AFFS_I2BSIZE(dir),ibh->b_data,5); + mark_buffer_dirty(ibh,1); + affs_brelse(ibh); + if (link_bh) { LINK_END(inode_bh->b_data,inode)->original = ntohl(link->i_ino); LINK_END(inode_bh->b_data,inode)->link_chain = @@ -974,11 +1021,13 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, inode->i_dirt = 1; mark_buffer_dirty(dir_bh,1); mark_buffer_dirty(inode_bh,1); + +addentry_done: affs_brelse(dir_bh); affs_brelse(inode_bh); affs_brelse(link_bh); - return 0; + return retval; } static struct file_system_type affs_fs_type = { @@ -999,7 +1048,7 @@ EXPORT_NO_SYMBOLS; int init_module(void) { - return init_affs_fs(); + return register_filesystem(&affs_fs_type); } void diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 0f4bced43..6a9b02bac 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -20,6 +20,8 @@ #include +static int affs_fixup(struct buffer_head *bh, struct inode *inode); + /* Simple toupper() for DOS\1 */ static inline unsigned int @@ -100,7 +102,7 @@ affs_find_entry(struct inode *dir, const char *name, int namelen, { struct buffer_head *bh; int intl; - int key; + s32 key; pr_debug("AFFS: find_entry(%.*s)=\n",namelen,name); @@ -222,9 +224,7 @@ affs_create(struct inode *dir, const char *name, int len, int mode, struct inode pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir->i_ino,len,name,mode); - *result = NULL; - if (!dir || !dir->i_sb) { iput(dir); return -EINVAL; @@ -472,7 +472,7 @@ affs_link(struct inode *oldinode, struct inode *dir, const char *name, int len) iput(oldinode); oldinode = iget(dir->i_sb,i); if (!oldinode) { - printk("AFFS: link(): original does not exist.\n"); + affs_error(oldinode->i_sb,"link","Cannot get original from link"); iput(dir); return -ENOENT; } @@ -507,7 +507,7 @@ affs_link(struct inode *oldinode, struct inode *dir, const char *name, int len) } static int -subdir(struct inode * new_inode, struct inode * old_inode) +subdir(struct inode *new_inode, struct inode *old_inode) { int ino; int result; @@ -650,11 +650,11 @@ end_rename: return retval; } -int +static int affs_fixup(struct buffer_head *bh, struct inode *inode) { - int key, link_key; - int type; + s32 key, link_key; + s32 type; struct buffer_head *nbh; struct inode *ofinode; @@ -663,7 +663,8 @@ affs_fixup(struct buffer_head *bh, struct inode *inode) key = htonl(LINK_END(bh->b_data,inode)->original); LINK_END(bh->b_data,inode)->original = 0; if (!key) { - printk("AFFS: fixup(): hard link without original: ino=%lu\n",inode->i_ino); + affs_error(inode->i_sb,"fixup","Hard link without original: ino=%lu", + inode->i_ino); return -ENOENT; } if (!(ofinode = iget(inode->i_sb,key))) @@ -676,17 +677,18 @@ affs_fixup(struct buffer_head *bh, struct inode *inode) if ((key = htonl(FILE_END(bh->b_data,inode)->link_chain))) { /* Get first link, turn it to a file */ if (!(ofinode = iget(inode->i_sb,key))) { - printk("AFFS: fixup(): cannot read inode %u\n",key); + affs_error(inode->i_sb,"fixup","Cannot read block %d",key); return -ENOENT; } if (!ofinode->u.affs_i.i_hlink) { - printk("AFFS: fixup(): first link to %lu (%u) is not a link?\n", - inode->i_ino,key); + affs_error(inode->i_sb,"fixup", + "First link to %lu (%d) is not a link", + inode->i_ino,key); iput(ofinode); return -ENOENT; } if (!(nbh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)))) { - printk("AFFS: fixup(): cannot read block %u\n",key); + affs_error(inode->i_sb,"fixup","Cannot read block %d",key); iput(ofinode); return -ENOENT; } @@ -719,13 +721,14 @@ affs_fixup(struct buffer_head *bh, struct inode *inode) break; if ((ofinode = iget(inode->i_sb,key))) { if (!ofinode->u.affs_i.i_hlink) - printk("AFFS: fixup() inode %u in link chain is " - "not a link\n",key); + affs_error(inode->i_sb,"fixup", + "Inode %d in link chain is not a link", + key); ofinode->u.affs_i.i_original = link_key; ofinode->i_dirt = 1; FILE_END(nbh->b_data,inode)->original = htonl(link_key); } else - printk("AFFS: fixup(): cannot get inode %u\n",key); + affs_error(inode->i_sb,"fixup","Cannot read block %d",key); } /* Turn old inode to a link */ inode->u.affs_i.i_hlink = 1; @@ -735,7 +738,7 @@ affs_fixup(struct buffer_head *bh, struct inode *inode) } else if (type == ST_SOFTLINK) { return 0; } else { - printk("AFFS: fixup(): secondary type=%d\n",type); + affs_error(inode->i_sb,"fixup","Bad secondary type (%d)",type); return -EBADF; } } diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index 734df0780..de93eac5c 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -82,7 +82,7 @@ affs_follow_link(struct inode *dir, struct inode *inode, int flag, int mode, i = 0; j = 0; if (!bh) { - printk("AFFS: unable to read i-node block %lu\n",inode->i_ino); + affs_error(inode->i_sb,"follow_link","Cannot read block %lu\n",inode->i_ino); kfree(buffer); iput(inode); iput(dir); @@ -138,7 +138,7 @@ affs_readlink(struct inode *inode, char *buffer, int buflen) i = 0; j = 0; if (!bh) { - printk("AFFS: unable to read i-node block %lu\n",inode->i_ino); + affs_error(inode->i_sb,"readlink","Cannot read block %lu\n",inode->i_ino); goto symlink_end; } lf = (struct slink_front *)bh->b_data; diff --git a/fs/autofs/.cvsignore b/fs/autofs/.cvsignore new file mode 100644 index 000000000..4671378ae --- /dev/null +++ b/fs/autofs/.cvsignore @@ -0,0 +1 @@ +.depend diff --git a/fs/autofs/Makefile b/fs/autofs/Makefile index 12f302635..1681c3d31 100644 --- a/fs/autofs/Makefile +++ b/fs/autofs/Makefile @@ -1,11 +1,7 @@ # # Makefile for the linux autofs-filesystem routines. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... +# We can build this either out of the kernel tree or the autofs tools tree. # O_TARGET := autofs.o @@ -13,4 +9,27 @@ O_OBJS := dir.o dirhash.o init.o inode.o root.o symlink.o waitq.o M_OBJS := $(O_TARGET) +ifdef TOPDIR +# +# Part of the kernel code +# include $(TOPDIR)/Rules.make +else +# +# Standalone (handy for development) +# +include ../Makefile.rules + +CFLAGS += -D__KERNEL__ -DMODULE $(KFLAGS) -I../include -I$(KINCLUDE) $(MODFLAGS) + +all: $(O_TARGET) + +$(O_TARGET): $(O_OBJS) + $(LD) -r -o $(O_TARGET) $(O_OBJS) + +install: $(O_TARGET) + install -c $(O_TARGET) /lib/modules/`uname -r`/fs + +clean: + rm -f *.o *.s +endif diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h new file mode 100644 index 000000000..d3b6e484f --- /dev/null +++ b/fs/autofs/autofs_i.h @@ -0,0 +1,175 @@ +/* -*- linux-c -*- ------------------------------------------------------- * + * + * linux/fs/autofs/autofs_i.h + * + * Copyright 1997 Transmeta Corporation - All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* Internal header file for autofs */ + +#include + +/* This is the range of ioctl() numbers we claim as ours */ +#define AUTOFS_IOC_FIRST AUTOFS_IOC_READY +#define AUTOFS_IOC_COUNT 32 + +#include +#include +#include +#include +#include + +#define kver(a,b,c) (((a) << 16) + ((b) << 8) + (c)) + +#if LINUX_VERSION_CODE < kver(2,1,0) + +/* Segmentation stuff for pre-2.1 kernels */ +#include + +static inline int copy_to_user(void *dst, void *src, unsigned long len) +{ + int rv = verify_area(VERIFY_WRITE, dst, len); + if ( rv ) + return -1; + memcpy_tofs(dst,src,len); + return 0; +} + +static inline int copy_from_user(void *dst, void *src, unsigned long len) +{ + int rv = verify_area(VERIFY_READ, src, len); + if ( rv ) + return -1; + memcpy_fromfs(dst,src,len); + return 0; +} + +#else + +/* Segmentation stuff for post-2.1 kernels */ +#include +#define register_symtab(x) ((void)0) + +#endif + +#ifdef DEBUG +#define DPRINTK(D) printk D; +#else +#define DPRINTK(D) +#endif + +#define AUTOFS_SUPER_MAGIC 0x0187 + +/* Structures associated with the root directory hash */ + +#define AUTOFS_HASH_SIZE 67 + +typedef u32 autofs_hash_t; /* Type returned by autofs_hash() */ + +struct autofs_dir_ent { + autofs_hash_t hash; + struct autofs_dir_ent *next; + struct autofs_dir_ent **back; + char *name; + int len; + ino_t ino; + /* The following entries are for the expiry system */ + unsigned long last_usage; + struct autofs_dir_ent *exp_next; + struct autofs_dir_ent *exp_prev; +}; + +struct autofs_dirhash { + struct autofs_dir_ent *h[AUTOFS_HASH_SIZE]; + struct autofs_dir_ent expiry_head; +}; + +struct autofs_wait_queue { + unsigned long wait_queue_token; + struct wait_queue *queue; + struct autofs_wait_queue *next; + /* We use the following to see what we are waiting for */ + autofs_hash_t hash; + int len; + char *name; + /* This is for status reporting upon return */ + int status; + int wait_ctr; +}; + +struct autofs_symlink { + int len; + char *data; + time_t mtime; +}; + +#define AUTOFS_MAX_SYMLINKS 256 + +#define AUTOFS_ROOT_INO 1 +#define AUTOFS_FIRST_SYMLINK 2 +#define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS) + +#define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32) + +#ifndef END_OF_TIME +#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1)) +#endif + +struct autofs_sb_info { + struct file *pipe; + pid_t oz_pgrp; + int catatonic; + unsigned long exp_timeout; + ino_t next_dir_ino; + struct autofs_wait_queue *queues; /* Wait queue pointer */ + struct autofs_dirhash dirhash; /* Root directory hash */ + struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS]; + u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; +}; + +/* autofs_oz_mode(): do we see the man behind the curtain? */ +static inline int autofs_oz_mode(struct autofs_sb_info *sbi) { + return sbi->catatonic || current->pgrp == sbi->oz_pgrp; +} + +/* Hash operations */ + +autofs_hash_t autofs_hash(const char *,int); +void autofs_initialize_hash(struct autofs_dirhash *); +struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,autofs_hash_t,const char *,int); +void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *); +void autofs_hash_delete(struct autofs_dir_ent *); +struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *); +void autofs_hash_nuke(struct autofs_dirhash *); + +/* Expiration-handling functions */ + +void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *); +struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *,unsigned long); + +/* Operations structures */ + +extern struct inode_operations autofs_root_inode_operations; +extern struct inode_operations autofs_symlink_inode_operations; +extern struct inode_operations autofs_dir_inode_operations; + +/* Initializing function */ + +struct super_block *autofs_read_super(struct super_block *, void *,int); + +/* Queue management functions */ + +int autofs_wait(struct autofs_sb_info *,autofs_hash_t,const char *,int); +int autofs_wait_release(struct autofs_sb_info *,unsigned long,int); +void autofs_catatonic_mode(struct autofs_sb_info *); + +#ifdef DEBUG +void autofs_say(const char *name, int len); +#else +#define autofs_say(n,l) +#endif diff --git a/fs/autofs/dir.c b/fs/autofs/dir.c index 22081d1a7..461688e9f 100644 --- a/fs/autofs/dir.c +++ b/fs/autofs/dir.c @@ -10,7 +10,7 @@ * * ------------------------------------------------------------------------- */ -#include +#include "autofs_i.h" static int autofs_dir_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t filldir) diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c index 8ea5325c4..90c18695a 100644 --- a/fs/autofs/dirhash.c +++ b/fs/autofs/dirhash.c @@ -10,9 +10,43 @@ * * ------------------------------------------------------------------------- */ -#include -#include -#include +#include "autofs_i.h" + +/* Functions for maintenance of expiry queue */ + +static void autofs_init_usage(struct autofs_dirhash *dh, + struct autofs_dir_ent *ent) +{ + ent->exp_next = &dh->expiry_head; + ent->exp_prev = dh->expiry_head.exp_prev; + dh->expiry_head.exp_prev->exp_next = ent; + dh->expiry_head.exp_prev = ent; + ent->last_usage = jiffies; +} + +static void autofs_delete_usage(struct autofs_dir_ent *ent) +{ + ent->exp_prev->exp_next = ent->exp_next; + ent->exp_next->exp_prev = ent->exp_prev; +} + +void autofs_update_usage(struct autofs_dirhash *dh, + struct autofs_dir_ent *ent) +{ + autofs_delete_usage(ent); /* Unlink from current position */ + autofs_init_usage(dh,ent); /* Relink at queue tail */ +} + +struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *dh, + unsigned long timeout) +{ + struct autofs_dir_ent *ent; + + ent = dh->expiry_head.exp_next; + + if ( ent == &(dh->expiry_head) ) return NULL; + return (jiffies - ent->last_usage >= timeout) ? ent : NULL; +} /* Adapted from the Dragon Book, page 436 */ /* This particular hashing algorithm requires autofs_hash_t == u32 */ @@ -28,6 +62,8 @@ autofs_hash_t autofs_hash(const char *name, int len) void autofs_initialize_hash(struct autofs_dirhash *dh) { memset(&dh->h, 0, AUTOFS_HASH_SIZE*sizeof(struct autofs_dir_ent *)); + dh->expiry_head.exp_next = dh->expiry_head.exp_prev = + &dh->expiry_head; } struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh, autofs_hash_t hash, const char *name, int len) @@ -54,6 +90,8 @@ void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent) DPRINTK(("autofs_hash_insert: hash = 0x%08x, name = ", ent->hash)); autofs_say(ent->name,ent->len); + autofs_init_usage(dh,ent); + dhnp = &dh->h[ent->hash % AUTOFS_HASH_SIZE]; ent->next = *dhnp; ent->back = dhnp; @@ -63,6 +101,9 @@ void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent) void autofs_hash_delete(struct autofs_dir_ent *ent) { *(ent->back) = ent->next; + + autofs_delete_usage(ent); + kfree(ent->name); kfree(ent); } @@ -114,6 +155,8 @@ struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *dh, off_t * return ent; } +/* Delete everything. This is used on filesystem destruction, so we + make no attempt to keep the pointers valid */ void autofs_hash_nuke(struct autofs_dirhash *dh) { int i; diff --git a/fs/autofs/init.c b/fs/autofs/init.c index a4857cb99..1b3f6f165 100644 --- a/fs/autofs/init.c +++ b/fs/autofs/init.c @@ -11,23 +11,24 @@ * ------------------------------------------------------------------------- */ #include -#include +#include "autofs_i.h" -struct file_system_type autofs_fs_type = { +#if LINUX_VERSION_CODE < kver(2,1,36) +#define __initfunc(X) X +#else +#include +#endif + +static struct file_system_type autofs_fs_type = { autofs_read_super, "autofs", 0, NULL }; -int init_autofs_fs(void) -{ - return register_filesystem(&autofs_fs_type); -} - #ifdef MODULE int init_module(void) { int status; - if ((status = init_autofs_fs()) == 0) + if ((status = register_filesystem(&autofs_fs_type)) == 0) register_symtab(0); return status; } @@ -36,7 +37,15 @@ void cleanup_module(void) { unregister_filesystem(&autofs_fs_type); } -#endif + +#else /* MODULE */ + +__initfunc(int init_autofs_fs(void)) +{ + return register_filesystem(&autofs_fs_type); +} + +#endif /* !MODULE */ #ifdef DEBUG void autofs_say(const char *name, int len) diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 60b805a07..a8c176a02 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include "autofs_i.h" #define __NO_VERSION__ #include @@ -28,17 +28,19 @@ static void autofs_put_inode(struct inode *inode) static void autofs_put_super(struct super_block *sb) { - struct autofs_sb_info *sbi; + struct autofs_sb_info *sbi = + (struct autofs_sb_info *) sb->u.generic_sbp; unsigned int n; + if ( !sbi->catatonic ) + autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ + lock_super(sb); - sbi = (struct autofs_sb_info *) sb->u.generic_sbp; autofs_hash_nuke(&sbi->dirhash); for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) { if ( test_bit(n, sbi->symlink_bitmap) ) kfree(sbi->symlink[n].data); } - fput(sbi->pipe, sbi->pipe->f_inode); sb->s_dev = 0; kfree(sb->u.generic_sbp); @@ -149,6 +151,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data, s->u.generic_sbp = sbi; sbi->catatonic = 0; + sbi->exp_timeout = 0; sbi->oz_pgrp = current->pgrp; autofs_initialize_hash(&sbi->dirhash); sbi->queues = NULL; diff --git a/fs/autofs/root.c b/fs/autofs/root.c index d9056dcb1..57449e816 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -12,9 +12,8 @@ #include #include -#include -#include -#include +#include +#include "autofs_i.h" static int autofs_root_readdir(struct inode *,struct file *,void *,filldir_t); static int autofs_root_lookup(struct inode *,const char *,int,struct inode **); @@ -171,7 +170,8 @@ static int autofs_root_lookup(struct inode *dir, const char *name, int len, } } } while(!res); - + autofs_update_usage(&sbi->dirhash,ent); + *result = res; iput(dir); return 0; @@ -229,7 +229,6 @@ static int autofs_root_symlink(struct inode *dir, const char *name, int len, con ent->ino = AUTOFS_FIRST_SYMLINK + n; ent->hash = hash; memcpy(ent->name,name,ent->len = len); - ent->expiry = END_OF_TIME; autofs_hash_insert(dh,ent); @@ -322,7 +321,6 @@ static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int m ent->hash = hash; memcpy(ent->name, name, ent->len = len); ent->ino = sbi->next_dir_ino++; - ent->expiry = END_OF_TIME; autofs_hash_insert(dh,ent); dir->i_nlink++; iput(dir); @@ -330,6 +328,75 @@ static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int m return 0; } +/* Get/set timeout ioctl() operation */ +static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi, + unsigned long *p) +{ + int rv; + unsigned long ntimeout; + +#if LINUX_VERSION_CODE < kver(2,1,0) + if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(unsigned long))) ) + return rv; + ntimeout = get_user(p); + put_user(sbi->exp_timeout/HZ, p); +#else + if ( (rv = get_user(ntimeout, p)) || + (rv = put_user(sbi->exp_timeout/HZ, p)) ) + return rv; +#endif + + if ( ntimeout > ULONG_MAX/HZ ) + sbi->exp_timeout = 0; + else + sbi->exp_timeout = ntimeout * HZ; + + return 0; +} + +/* Return protocol version */ +static inline int autofs_get_protover(int *p) +{ +#if LINUX_VERSION_CODE < kver(2,1,0) + int rv; + if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(int))) ) + return rv; + put_user(AUTOFS_PROTO_VERSION, p); + return 0; +#else + return put_user(AUTOFS_PROTO_VERSION, p); +#endif +} + +/* Perform an expiry operation */ +static inline int autofs_expire_run(struct autofs_sb_info *sbi, + struct autofs_packet_expire *pkt_p) +{ + struct autofs_dir_ent *ent; + struct autofs_packet_expire pkt; + struct autofs_dirhash *dh = &(sbi->dirhash); + + memset(&pkt,0,sizeof pkt); + + pkt.hdr.proto_version = AUTOFS_PROTO_VERSION; + pkt.hdr.type = autofs_ptype_expire; + + if ( !sbi->exp_timeout || + !(ent = autofs_expire(dh,sbi->exp_timeout)) ) + return -EAGAIN; + + pkt.len = ent->len; + memcpy(pkt.name, ent->name, pkt.len); + pkt.name[pkt.len] = '\0'; + + if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) ) + return -EFAULT; + + autofs_update_usage(dh,ent); + + return 0; +} + /* * ioctl()'s on the root directory is the chief method for the daemon to * generate kernel reactions @@ -337,26 +404,33 @@ static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int m static int autofs_root_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *)inode->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = + (struct autofs_sb_info *)inode->i_sb->u.generic_sbp; - DPRINTK(("autofs_ioctl: cmd = %04x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); + DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); + if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || + _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT ) + return -ENOTTY; + + if ( !autofs_oz_mode(sbi) && !fsuser() ) + return -EPERM; + switch(cmd) { case AUTOFS_IOC_READY: /* Wait queue: go ahead and retry */ - if ( !autofs_oz_mode(sbi) && !fsuser() ) - return -EPERM; return autofs_wait_release(sbi,arg,0); case AUTOFS_IOC_FAIL: /* Wait queue: fail with ENOENT */ - /* Optional: add to failure cache */ - if ( !autofs_oz_mode(sbi) && !fsuser() ) - return -EPERM; return autofs_wait_release(sbi,arg,-ENOENT); case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */ - if ( !autofs_oz_mode(sbi) && !fsuser() ) - return -EPERM; autofs_catatonic_mode(sbi); return 0; + case AUTOFS_IOC_PROTOVER: /* Get protocol version */ + return autofs_get_protover((int *)arg); + case AUTOFS_IOC_SETTIMEOUT: + return autofs_get_set_timeout(sbi,(unsigned long *)arg); + case AUTOFS_IOC_EXPIRE: + return autofs_expire_run(sbi,(struct autofs_packet_expire *)arg); default: - return -ENOTTY; /* Should this be ENOSYS? */ + return -ENOSYS; } } diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c index 0e932c169..46c333103 100644 --- a/fs/autofs/symlink.c +++ b/fs/autofs/symlink.c @@ -12,7 +12,7 @@ #include #include -#include +#include "autofs_i.h" static int autofs_follow_link(struct inode *dir, struct inode *inode, int flag, int mode, struct inode **res_inode) diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c index 6dc6d0b13..b37745f19 100644 --- a/fs/autofs/waitq.c +++ b/fs/autofs/waitq.c @@ -11,9 +11,10 @@ * ------------------------------------------------------------------------- */ #include -#include #include -#include +#include +#include +#include "autofs_i.h" /* We make this a static variable rather than a part of the superblock; it is better if we don't reassign numbers easily even across filesystems */ @@ -36,6 +37,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi) wake_up(&wq->queue); wq = nwq; } + fput(sbi->pipe, sbi->pipe->f_inode); /* Close the pipe */ } static int autofs_write(struct file *file, const void *addr, int bytes) @@ -43,7 +45,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes) unsigned short fs; unsigned long old_signal; const char *data = (const char *)addr; - int written; + int written = 0; /** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/ @@ -75,6 +77,8 @@ static void autofs_notify_daemon(struct autofs_sb_info *sbi, struct autofs_wait_ DPRINTK(("autofs_wait: wait id = 0x%08lx, name = ", wq->wait_queue_token)); autofs_say(wq->name,wq->len); + memset(&pkt,0,sizeof pkt); /* For security reasons */ + pkt.hdr.proto_version = AUTOFS_PROTO_VERSION; pkt.hdr.type = autofs_ptype_missing; pkt.wait_queue_token = wq->wait_queue_token; @@ -94,7 +98,7 @@ int autofs_wait(struct autofs_sb_info *sbi, autofs_hash_t hash, const char *name for ( wq = sbi->queues ; wq ; wq = wq->next ) { if ( wq->hash == hash && wq->len == len && - !memcmp(wq->name,name,len) ) + wq->name && !memcmp(wq->name,name,len) ) break; } @@ -113,12 +117,13 @@ int autofs_wait(struct autofs_sb_info *sbi, autofs_hash_t hash, const char *name init_waitqueue(&wq->queue); wq->hash = hash; wq->len = len; + wq->status = -EINTR; /* Status return if interrupted */ memcpy(wq->name, name, len); wq->next = sbi->queues; sbi->queues = wq; /* autofs_notify_daemon() may block */ - wq->wait_ctr++; + wq->wait_ctr = 1; autofs_notify_daemon(sbi,wq); } else wq->wait_ctr++; @@ -130,7 +135,8 @@ int autofs_wait(struct autofs_sb_info *sbi, autofs_hash_t hash, const char *name DPRINTK(("autofs_wait: skipped sleeping\n")); } - status = (current->signal & ~current->blocked) ? -EINTR : wq->status; + status = wq->status; + if ( ! --wq->wait_ctr ) /* Are we the last process to need status? */ kfree(wq); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 587c44f8f..f12d89ef3 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -49,6 +49,11 @@ extern void dump_thread(struct pt_regs *, struct user *); extern unsigned long get_unmapped_area(unsigned long addr, unsigned long len); #endif +#ifndef elf_addr_t +#define elf_addr_t unsigned long +#define elf_caddr_t char * +#endif + /* * If we don't support core dumping, then supply a NULL so we * don't even try. @@ -61,6 +66,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs); #define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_EXEC_PAGESIZE-1)) #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_EXEC_PAGESIZE-1)) +#define ELF_PAGEALIGN(_v) (((_v) + ELF_EXEC_PAGESIZE - 1) & ~(ELF_EXEC_PAGESIZE - 1)) static struct linux_binfmt elf_format = { #ifndef MODULE @@ -93,8 +99,8 @@ static void print_elf_p_type(Elf32_Word p_type) static void set_brk(unsigned long start, unsigned long end) { - start = PAGE_ALIGN(start); - end = PAGE_ALIGN(end); + start = ELF_PAGEALIGN(start); + end = ELF_PAGEALIGN(end); if (end <= start) return; do_mmap(NULL, start, end - start, @@ -113,28 +119,30 @@ static void padzero(unsigned long elf_bss) { unsigned long nbyte; - nbyte = elf_bss & (PAGE_SIZE-1); + nbyte = ELF_PAGEOFFSET(elf_bss); if (nbyte) { - nbyte = PAGE_SIZE - nbyte; + nbyte = ELF_EXEC_PAGESIZE - nbyte; clear_user((void *) elf_bss, nbyte); } } -unsigned long * create_elf_tables(char *p, int argc, int envc, - struct elfhdr * exec, - unsigned long load_addr, - unsigned long interp_load_addr, int ibcs) +static elf_addr_t * +create_elf_tables(char *p, int argc, int envc, + struct elfhdr * exec, + unsigned long load_addr, + unsigned long interp_load_addr, int ibcs) { - char **argv, **envp; - unsigned long *sp; + elf_caddr_t *argv; + elf_caddr_t *envp; + elf_addr_t *sp; /* * Force 16 byte alignment here for generality. */ - sp = (unsigned long *) (~15UL & (unsigned long) p); + sp = (elf_addr_t *) (~15UL & (unsigned long) p); #if defined(__mips__) || defined(__sparc__) { - unsigned long *csp; + elf_addr_t *csp; csp = sp; csp -= exec ? DLINFO_ITEMS*2 : 2; csp -= envc+1; @@ -160,36 +168,36 @@ unsigned long * create_elf_tables(char *p, int argc, int envc, NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff); NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr)); NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum); - NEW_AUX_ENT (3, AT_PAGESZ, PAGE_SIZE); + NEW_AUX_ENT (3, AT_PAGESZ, ELF_EXEC_PAGESIZE); NEW_AUX_ENT (4, AT_BASE, interp_load_addr); NEW_AUX_ENT (5, AT_FLAGS, 0); - NEW_AUX_ENT (6, AT_ENTRY, (unsigned long) exec->e_entry); - NEW_AUX_ENT (7, AT_UID, (unsigned long) current->uid); - NEW_AUX_ENT (8, AT_EUID, (unsigned long) current->euid); - NEW_AUX_ENT (9, AT_GID, (unsigned long) current->gid); - NEW_AUX_ENT (10, AT_EGID, (unsigned long) current->egid); + NEW_AUX_ENT (6, AT_ENTRY, (elf_addr_t) exec->e_entry); + NEW_AUX_ENT (7, AT_UID, (elf_addr_t) current->uid); + NEW_AUX_ENT (8, AT_EUID, (elf_addr_t) current->euid); + NEW_AUX_ENT (9, AT_GID, (elf_addr_t) current->gid); + NEW_AUX_ENT (10, AT_EGID, (elf_addr_t) current->egid); } #undef NEW_AUX_ENT sp -= envc+1; - envp = (char **) sp; + envp = (elf_caddr_t *) sp; sp -= argc+1; - argv = (char **) sp; + argv = (elf_caddr_t *) sp; if (!ibcs) { - __put_user((unsigned long) envp,--sp); - __put_user((unsigned long) argv,--sp); + __put_user((elf_addr_t)(unsigned long) envp,--sp); + __put_user((elf_addr_t)(unsigned long) argv,--sp); } - __put_user((unsigned long)argc,--sp); + __put_user((elf_addr_t)argc,--sp); current->mm->arg_start = (unsigned long) p; while (argc-->0) { - __put_user(p,argv++); + __put_user((elf_caddr_t)(unsigned long)p,argv++); p += strlen_user(p); } __put_user(NULL, argv); current->mm->arg_end = current->mm->env_start = (unsigned long) p; while (envc-->0) { - __put_user(p,envp++); + __put_user((elf_caddr_t)(unsigned long)p,envp++); p += strlen_user(p); } __put_user(NULL, envp); @@ -236,14 +244,16 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, /* Now read in all of the header information */ - if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) + if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > ELF_EXEC_PAGESIZE) { return ~0UL; + } elf_phdata = (struct elf_phdr *) kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); - if (!elf_phdata) + if (!elf_phdata) { return ~0UL; + } /* * If the size of this structure has changed, then punt, since @@ -389,7 +399,9 @@ static unsigned long load_aout_interp(struct exec * interp_ex, interp_ex->a_bss, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); - if (retval < 0) return ~0UL; + if (retval < 0) { + return ~0UL; + } return elf_entry; } @@ -611,6 +623,9 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) /* Do this so that we can load the interpreter, if need be. We will change some of these later */ current->mm->rss = 0; +#ifdef ELF_FLAGS_INIT + ELF_FLAGS_INIT; +#endif bprm->p = setup_arg_pages(bprm->p, bprm); current->mm->start_stack = bprm->p; @@ -828,7 +843,7 @@ do_load_elf_library(int fd){ /* Now read in all of the header information */ - if (sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) + if (sizeof(struct elf_phdr) * elf_ex.e_phnum > ELF_EXEC_PAGESIZE) return -ENOEXEC; elf_phdata = (struct elf_phdr *) @@ -932,6 +947,10 @@ static inline int maydump(struct vm_area_struct *vma) { if (!(vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC))) return 0; + + /* Do not dump I/O mapped devices! -DaveM */ + if(vma->vm_flags & VM_IO) + return 0; #if 1 if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN)) return 1; @@ -1041,7 +1060,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs) elf_fpregset_t fpu; /* NT_PRFPREG */ struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ - if (!current->dumpable || limit < PAGE_SIZE || current->mm->count != 1) + if (!current->dumpable || limit < ELF_EXEC_PAGESIZE || current->mm->count != 1) return 0; current->dumpable = 0; @@ -1143,14 +1162,14 @@ static int elf_core_dump(long signr, struct pt_regs * regs) psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid; psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp; psinfo.pr_sid = prstatus.pr_sid = current->session; - prstatus.pr_utime.tv_sec = CT_TO_SECS(current->utime); - prstatus.pr_utime.tv_usec = CT_TO_USECS(current->utime); - prstatus.pr_stime.tv_sec = CT_TO_SECS(current->stime); - prstatus.pr_stime.tv_usec = CT_TO_USECS(current->stime); - prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->cutime); - prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->cutime); - prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->cstime); - prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->cstime); + prstatus.pr_utime.tv_sec = CT_TO_SECS(current->times.tms_utime); + prstatus.pr_utime.tv_usec = CT_TO_USECS(current->times.tms_utime); + prstatus.pr_stime.tv_sec = CT_TO_SECS(current->times.tms_stime); + prstatus.pr_stime.tv_usec = CT_TO_USECS(current->times.tms_stime); + prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->times.tms_cutime); + prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->times.tms_cutime); + prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->times.tms_cstime); + prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->times.tms_cstime); /* * This transfers the registers from regs into the standard @@ -1162,7 +1181,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs) if (sizeof(elf_gregset_t) != sizeof(struct pt_regs)) { printk("sizeof(elf_gregset_t) (%ld) != sizeof(struct pt_regs) (%ld)\n", - sizeof(elf_gregset_t), sizeof(struct pt_regs)); + (long)sizeof(elf_gregset_t), (long)sizeof(struct pt_regs)); } else *(struct pt_regs *)&prstatus.pr_reg = *regs; @@ -1190,7 +1209,8 @@ static int elf_core_dump(long signr, struct pt_regs * regs) set_fs(fs); len = current->mm->arg_end - current->mm->arg_start; - len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len; + if (len >= ELF_PRARGSZ) + len = ELF_PRARGSZ-1; copy_from_user(&psinfo.pr_psargs, (const char *)current->mm->arg_start, len); for(i = 0; i < len; i++) @@ -1243,7 +1263,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs) } /* Page-align dumped data */ - dataoff = offset = roundup(offset, PAGE_SIZE); + dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); /* Write program headers for segments dump */ for(vma = current->mm->mmap, i = 0; @@ -1265,7 +1285,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs) phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W; if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X; - phdr.p_align = PAGE_SIZE; + phdr.p_align = ELF_EXEC_PAGESIZE; DUMP_WRITE(&phdr, sizeof(phdr)); } diff --git a/fs/buffer.c b/fs/buffer.c index 27950290a..0b35d6e00 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -591,8 +591,9 @@ void set_blocksize(kdev_t dev, int size) continue; if (bh->b_size == size) continue; - + bhnext->b_count++; wait_on_buffer(bh); + bhnext->b_count--; if (bh->b_dev == dev && bh->b_size != size) { clear_bit(BH_Dirty, &bh->b_state); clear_bit(BH_Uptodate, &bh->b_state); @@ -612,8 +613,7 @@ static inline int can_reclaim(struct buffer_head *bh, int size) buffer_locked(bh)) return 0; - if (atomic_read(&mem_map[MAP_NR((unsigned long) bh->b_data)].count) != 1 || - buffer_dirty(bh)) { + if (buffer_dirty(bh)) { refile_buffer(bh); return 0; } @@ -644,8 +644,7 @@ static struct buffer_head *find_candidate(struct buffer_head *list, continue; } - if (buffer_locked(bh) && - (bh->b_list == BUF_LOCKED || bh->b_list == BUF_LOCKED1)) { + if (buffer_locked(bh) && bh->b_list == BUF_LOCKED) { /* Buffers are written in the order they are placed * on the locked list. If we encounter a locked * buffer here, this means that the rest of them @@ -845,9 +844,6 @@ void refile_buffer(struct buffer_head * buf) if(dispose != buf->b_list) { if(dispose == BUF_DIRTY) buf->b_lru_time = jiffies; - if(dispose == BUF_LOCKED && - (buf->b_flushtime - buf->b_lru_time) <= bdf_prm.b_un.age_super) - dispose = BUF_LOCKED1; remove_from_queues(buf); buf->b_list = dispose; insert_into_queues(buf); @@ -1120,11 +1116,11 @@ no_grow: /* Run the hooks that have to be done when a page I/O has completed. */ static inline void after_unlock_page (struct page * page) { - if (clear_bit(PG_decr_after, &page->flags)) + if (test_and_clear_bit(PG_decr_after, &page->flags)) atomic_dec(&nr_async_pages); - if (clear_bit(PG_free_after, &page->flags)) + if (test_and_clear_bit(PG_free_after, &page->flags)) __free_page(page); - if (clear_bit(PG_swap_unlock_after, &page->flags)) + if (test_and_clear_bit(PG_swap_unlock_after, &page->flags)) swap_after_unlock_page(page->swap_unlock_entry); } @@ -1467,7 +1463,7 @@ int try_to_free_buffer(struct buffer_head * bh, struct buffer_head ** bhp, buffermem -= PAGE_SIZE; mem_map[MAP_NR(page)].buffers = NULL; free_page(page); - return !atomic_read(&mem_map[MAP_NR(page)].count); + return 1; } /* ================== Debugging =================== */ @@ -1478,7 +1474,7 @@ void show_buffers(void) int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0; int protected = 0; int nlist; - static char *buf_types[NR_LIST] = {"CLEAN","LOCKED","LOCKED1","DIRTY"}; + static char *buf_types[NR_LIST] = {"CLEAN","LOCKED","DIRTY"}; printk("Buffer memory: %6dkB\n",buffermem>>10); printk("Buffer heads: %6d\n",nr_buffer_heads); @@ -1526,7 +1522,7 @@ void buffer_init(void) bh_cachep = kmem_cache_create("buffer_head", sizeof(struct buffer_head), - sizeof(unsigned long) * 4, + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if(!bh_cachep) panic("Cannot create buffer head SLAB cache\n"); @@ -1611,6 +1607,7 @@ asmlinkage int sync_old_buffers(void) ndirty++; if(bh->b_flushtime > jiffies) continue; nwritten++; + next->b_count++; bh->b_count++; bh->b_flushtime = 0; #ifdef DEBUG @@ -1618,6 +1615,7 @@ asmlinkage int sync_old_buffers(void) #endif ll_rw_block(WRITE, 1, &bh); bh->b_count--; + next->b_count--; } } #ifdef DEBUG @@ -1756,6 +1754,7 @@ int bdflush(void * unused) currently dirty buffers are not shared, so it does not matter */ if (refilled && major == LOOP_MAJOR) continue; + next->b_count++; bh->b_count++; ndirty++; bh->b_flushtime = 0; @@ -1771,6 +1770,7 @@ int bdflush(void * unused) if(nlist != BUF_DIRTY) ncount++; #endif bh->b_count--; + next->b_count--; } } #ifdef DEBUG diff --git a/fs/dcache.c b/fs/dcache.c index 2dc317aad..f6ab04693 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -153,17 +153,24 @@ static inline void add_hash(struct dir_cache_entry * de, struct dir_cache_entry /* * Find a directory cache entry given all the necessary info. */ -static inline struct dir_cache_entry * find_entry(struct inode * dir, const char * name, int len, struct dir_cache_entry ** hash) +static inline struct dir_cache_entry * find_entry(struct inode * dir, const char * name, unsigned char len, struct dir_cache_entry ** hash) { struct dir_cache_entry *de; - for(de = *hash; de; de = de->next) + de = *hash; + goto inside; + for (;;) { + de = de->next; +inside: + if (!de) + break; if((de->name_len == (unsigned char) len) && (de->dc_dev == dir->i_dev) && (de->dir == dir->i_ino) && (de->version == dir->i_version) && (!memcmp(de->name, name, len))) break; + } return de; } @@ -195,7 +202,7 @@ int dcache_lookup(struct inode * dir, const char * name, int len, unsigned long struct dir_cache_entry *de; spin_lock(&dcache_lock); - de = find_entry(dir, name, len, hash); + de = find_entry(dir, name, (unsigned char) len, hash); if(de) { *ino = de->ino; move_to_level2(de, hash); @@ -213,7 +220,7 @@ void dcache_add(struct inode * dir, const char * name, int len, unsigned long in struct dir_cache_entry *de; spin_lock(&dcache_lock); - de = find_entry(dir, name, len, hash); + de = find_entry(dir, name, (unsigned char) len, hash); if (de) { de->ino = ino; update_lru(de); diff --git a/fs/dquot.c b/fs/dquot.c index 5236ed38e..dda3f642a 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -989,7 +990,7 @@ int quota_on(kdev_t dev, short type, char *path) } } else error = -EIO; - filp->f_count--; + put_filp(filp); } else error = -EMFILE; iput(inode); diff --git a/fs/exec.c b/fs/exec.c index 9817bd67d..3a3bfb1bc 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -152,7 +152,7 @@ int open_inode(struct inode * inode, int mode) if (f->f_op->open) { int error = f->f_op->open(inode,f); if (error) { - f->f_count--; + put_filp(f); put_unused_fd(fd); return error; } @@ -388,7 +388,7 @@ static void exec_mmap(void) * (the oom is wrong there, too, IMHO) */ if (current->mm->count > 1) { - struct mm_struct *mm = kmalloc(sizeof(*mm), GFP_KERNEL); + struct mm_struct *mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL); if (!mm) { /* this is wrong, I think. */ oom(current); @@ -397,9 +397,9 @@ static void exec_mmap(void) *mm = *current->mm; init_new_context(mm); mm->def_flags = 0; /* should future lockings be kept? */ + mm->cpu_vm_mask = (1 << smp_processor_id()); mm->count = 1; - mm->mmap = NULL; - mm->mmap_avl = NULL; + mm->mmap = mm->mmap_cache = NULL; mm->total_vm = 0; mm->rss = 0; current->mm->count--; diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 61b5b1a39..171de1cf5 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -177,6 +177,7 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block, unsigned long bit; unsigned long i; int bitmap_nr; + unsigned long overflow; struct super_block * sb; struct ext2_group_desc * gdp; struct ext2_super_block * es; @@ -199,14 +200,20 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block, ext2_debug ("freeing block %lu\n", block); +do_more: + overflow = 0; block_group = (block - le32_to_cpu(es->s_first_data_block)) / EXT2_BLOCKS_PER_GROUP(sb); - bit = (block - le32_to_cpu(es->s_first_data_block)) % EXT2_BLOCKS_PER_GROUP(sb); - if (bit + count > EXT2_BLOCKS_PER_GROUP(sb)) - ext2_panic (sb, "ext2_free_blocks", - "Freeing blocks across group boundary - " - "Block = %lu, count = %lu", - block, count); + bit = (block - le32_to_cpu(es->s_first_data_block)) % + EXT2_BLOCKS_PER_GROUP(sb); + /* + * Check to see if we are freeing blocks across a group + * boundary. + */ + if (bit + count > EXT2_BLOCKS_PER_GROUP(sb)) { + overflow = bit + count - EXT2_BLOCKS_PER_GROUP(sb); + count -= overflow; + } bitmap_nr = load_block_bitmap (sb, block_group); bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr]; gdp = get_group_desc (sb, block_group, &bh2); @@ -246,6 +253,11 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block, ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } + if (overflow) { + block += count; + count = overflow; + goto do_more; + } sb->s_dirt = 1; unlock_super (sb); return; @@ -546,6 +558,19 @@ static inline int block_in_use (unsigned long block, EXT2_BLOCKS_PER_GROUP(sb), map); } +static int test_root(int a, int b) +{ + if (a == 0) + return 1; + while (1) { + if (a == 1) + return 1; + if (a % b) + return 0; + a = a / b; + } +} + void ext2_check_blocks_bitmap (struct super_block * sb) { struct buffer_head * bh; @@ -569,15 +594,21 @@ void ext2_check_blocks_bitmap (struct super_block * sb) bitmap_nr = load_block_bitmap (sb, i); bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr]; - if (!ext2_test_bit (0, bh->b_data)) - ext2_error (sb, "ext2_check_blocks_bitmap", - "Superblock in group %d is marked free", i); - - for (j = 0; j < desc_blocks; j++) - if (!ext2_test_bit (j + 1, bh->b_data)) + if (!(sb->u.ext2_sb.s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) || + (test_root(i, 3) || test_root(i, 5) || test_root(i, 7))) { + if (!ext2_test_bit (0, bh->b_data)) ext2_error (sb, "ext2_check_blocks_bitmap", + "Superblock in group %d " + "is marked free", i); + + for (j = 0; j < desc_blocks; j++) + if (!ext2_test_bit (j + 1, bh->b_data)) + ext2_error (sb, + "ext2_check_blocks_bitmap", "Descriptor block #%d in group " "%d is marked free", j, i); + } if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), sb, bh->b_data)) ext2_error (sb, "ext2_check_blocks_bitmap", diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 5a876261e..f2dbff2d1 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -503,12 +503,23 @@ void ext2_read_inode (struct inode * inode) inode->i_op = &blkdev_inode_operations; else if (S_ISFIFO(inode->i_mode)) init_fifo(inode); - if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) + inode->i_attr_flags = 0; + if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) { + inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; inode->i_flags |= MS_SYNCHRONOUS; - if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL) + } + if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL) { + inode->i_attr_flags |= ATTR_FLAG_APPEND; inode->i_flags |= S_APPEND; - if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) + } + if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) { + inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE; inode->i_flags |= S_IMMUTABLE; + } + if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) { + inode->i_attr_flags |= ATTR_FLAG_NOATIME; + inode->i_flags |= MS_NOATIME; + } } static int ext2_update_inode(struct inode * inode, int do_sync) @@ -597,11 +608,71 @@ static int ext2_update_inode(struct inode * inode, int do_sync) void ext2_write_inode (struct inode * inode) { +#if 0 + printk("ext2_write(%04x:%06d)...", inode->i_dev, inode->i_ino); +#endif ext2_update_inode (inode, 0); } int ext2_sync_inode (struct inode *inode) { +#if 0 + printk("ext2_sync(%04x:%06d)...", inode->i_dev, inode->i_ino); +#endif return ext2_update_inode (inode, 1); } +int ext2_notify_change(struct inode *inode, struct iattr *iattr) +{ + int retval; + unsigned int flags; + + if ((iattr->ia_attr_flags & + (ATTR_FLAG_APPEND | ATTR_FLAG_IMMUTABLE)) ^ + (inode->u.ext2_i.i_flags & + (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) { + if (!fsuser() || securelevel > 0) + return -EPERM; + } else + if ((current->fsuid != inode->i_uid) && !fsuser()) + return -EPERM; + + if ((retval = inode_change_ok(inode, iattr)) != 0) + return retval; + + inode_setattr(inode, iattr); + + flags = iattr->ia_attr_flags; + if (flags & ATTR_FLAG_SYNCRONOUS) { + inode->i_flags |= MS_SYNCHRONOUS; + inode->u.ext2_i.i_flags = EXT2_SYNC_FL; + } else { + inode->i_flags &= ~MS_SYNCHRONOUS; + inode->u.ext2_i.i_flags &= ~EXT2_SYNC_FL; + } + if (flags & ATTR_FLAG_NOATIME) { + inode->i_flags |= MS_NOATIME; + inode->u.ext2_i.i_flags = EXT2_NOATIME_FL; + } else { + inode->i_flags &= ~MS_NOATIME; + inode->u.ext2_i.i_flags &= ~EXT2_NOATIME_FL; + } + if (flags & ATTR_FLAG_APPEND) { + inode->i_flags |= S_APPEND; + inode->u.ext2_i.i_flags = EXT2_APPEND_FL; + } else { + inode->i_flags &= ~S_APPEND; + inode->u.ext2_i.i_flags &= ~EXT2_APPEND_FL; + } + if (flags & ATTR_FLAG_IMMUTABLE) { + inode->i_flags |= S_IMMUTABLE; + inode->u.ext2_i.i_flags = EXT2_IMMUTABLE_FL; + } else { + inode->i_flags &= ~S_IMMUTABLE; + inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL; + } + inode->i_dirt = 1; + + return 0; +} + diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index 0892ce79f..387600bbf 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -45,6 +45,10 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, if (IS_RDONLY(inode)) return -EROFS; inode->u.ext2_i.i_flags = flags; + if (flags & EXT2_SYNC_FL) + inode->i_flags |= MS_SYNCHRONOUS; + else + inode->i_flags &= ~MS_SYNCHRONOUS; if (flags & EXT2_APPEND_FL) inode->i_flags |= S_APPEND; else @@ -53,6 +57,10 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, inode->i_flags |= S_IMMUTABLE; else inode->i_flags &= ~S_IMMUTABLE; + if (flags & EXT2_NOATIME_FL) + inode->i_flags |= MS_NOATIME; + else + inode->i_flags &= ~MS_NOATIME; inode->i_ctime = CURRENT_TIME; inode->i_dirt = 1; return 0; diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index e48fc8706..39716678a 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -583,7 +583,7 @@ static int empty_dir (struct inode * inode) offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); de = (struct ext2_dir_entry *) ((char *) de1 + le16_to_cpu(de1->rec_len)); while (offset < inode->i_size ) { - if ((void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { + if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { brelse (bh); bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &err); if (!bh) { diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 26e18852e..5885e3067 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -508,6 +508,9 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, goto failed_mount; } } + sb->u.ext2_sb.s_feature_compat = es->s_feature_compat; + sb->u.ext2_sb.s_feature_incompat = es->s_feature_incompat; + sb->u.ext2_sb.s_feature_ro_compat = es->s_feature_ro_compat; sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE << (__s32) le32_to_cpu(es->s_log_frag_size); if (sb->u.ext2_sb.s_frag_size) diff --git a/fs/fcntl.c b/fs/fcntl.c index bedc02e89..6418a5d83 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -163,6 +163,7 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) if (current->pgrp == -arg || current->pid == arg) goto fasync_ok; + read_lock(&tasklist_lock); for_each_task(p) { if ((p->pid == arg) || (p->pid == -arg) || (p->pgrp == -arg)) { @@ -171,11 +172,14 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) if ((p->session != current->session) && (p->uid != current->uid) && (p->euid != current->euid) && - !suser()) + !suser()) { + read_unlock(&tasklist_lock); goto out; + } break; } } + read_unlock(&tasklist_lock); err = -EINVAL; if ((task_found == 0) && !suser()) break; diff --git a/fs/file_table.c b/fs/file_table.c index 17a670f59..b8c8d4155 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -2,143 +2,104 @@ * linux/fs/file_table.c * * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ #include +#include +#include #include +#include #include #include +#include -/* - * first_file points to a doubly linked list of all file structures in - * the system. - * nr_files holds the length of this list. - */ -struct file * first_file = NULL; +/* SLAB cache for filp's. */ +static kmem_cache_t *filp_cache; + +/* sysctl tunables... */ int nr_files = 0; int max_files = NR_FILE; -/* - * Insert a new file structure at the head of the list of available ones. - */ -static inline void insert_file_free(struct file *file) -{ - struct file *next, *prev; - - next = first_file; - first_file = file; - file->f_count = 0; - prev = next->f_prev; - file->f_next = next; - next->f_prev = file; - file->f_prev = prev; - prev->f_next = file; -} +/* Free list management, if you are here you must have f_count == 0 */ +static struct file * free_filps = NULL; -/* - * Remove a file structure from the list of available ones. - */ -static inline void remove_file_free(struct file *file) +void insert_file_free(struct file *file) { - struct file *next, *prev; - - next = file->f_next; - prev = file->f_prev; - file->f_next = file->f_prev = NULL; - if (first_file == file) - first_file = next; - next->f_prev = prev; - prev->f_next = next; + if((file->f_next = free_filps) != NULL) + free_filps->f_pprev = &file->f_next; + free_filps = file; + file->f_pprev = &free_filps; } -/* - * Insert a file structure at the end of the list of available ones. - */ -static inline void put_last_free(struct file *file) +/* The list of in-use filp's must be exported (ugh...) */ +struct file *inuse_filps = NULL; + +static inline void put_inuse(struct file *file) { - struct file *next, *prev; - - next = first_file; - file->f_next = next; - prev = next->f_prev; - next->f_prev = file; - file->f_prev = prev; - prev->f_next = file; + if((file->f_next = inuse_filps) != NULL) + inuse_filps->f_pprev = &file->f_next; + inuse_filps = file; + file->f_pprev = &inuse_filps; } -/* - * Allocate a new memory page for file structures and - * insert the new structures into the global list. - * Returns 0, if there is no more memory, 1 otherwise. - */ +/* Get more free filp's. */ static int grow_files(void) { - struct file * file; - int i; - - /* - * We don't have to clear the page because we only look into - * f_count, f_prev and f_next and they get initialized in - * insert_file_free. The rest of the file structure is cleared - * by get_empty_filp before it is returned. - */ - file = (struct file *) __get_free_page(GFP_KERNEL); - - if (!file) - return 0; - - nr_files += i = PAGE_SIZE/sizeof(struct file); - - if (!first_file) - file->f_count = 0, - file->f_next = file->f_prev = first_file = file++, - i--; - - for (; i ; i--) - insert_file_free(file++); + int i = 16; + + while(i--) { + struct file * file = kmem_cache_alloc(filp_cache, SLAB_KERNEL); + if(!file) { + if(i == 15) + return 0; + goto got_some; + } + insert_file_free(file); + nr_files++; + } +got_some: return 1; } -unsigned long file_table_init(unsigned long start, unsigned long end) +void file_table_init(void) { - return start; + filp_cache = kmem_cache_create("filp", sizeof(struct file), + 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if(!filp_cache) + panic("VFS: Cannot alloc filp SLAB cache."); } -/* - * Find an unused file structure and return a pointer to it. +/* Find an unused file structure and return a pointer to it. * Returns NULL, if there are no more free file structures or * we run out of memory. */ struct file * get_empty_filp(void) { - int i; - int max = max_files; struct file * f; - /* - * Reserve a few files for the super-user.. - */ - if (current->euid) - max -= 10; - - /* if the return is taken, we are in deep trouble */ - if (!first_file && !grow_files()) - return NULL; - - do { - for (f = first_file, i=0; i < nr_files; i++, f = f->f_next) - if (!f->f_count) { - remove_file_free(f); - memset(f,0,sizeof(*f)); - put_last_free(f); - f->f_count = 1; - f->f_version = ++event; - return f; - } - } while (nr_files < max && grow_files()); - - return NULL; +again: + if((f = free_filps) != NULL) { + remove_filp(f); + memset(f, 0, sizeof(*f)); + f->f_count = 1; + f->f_version = ++event; + put_inuse(f); + } else { + int max = max_files; + + /* Reserve a few files for the super-user.. */ + if (current->euid) + max -= 10; + + if (nr_files < max && grow_files()) + goto again; + + /* Big problems... */ + } + return f; } #ifdef CONFIG_QUOTA @@ -146,10 +107,9 @@ struct file * get_empty_filp(void) void add_dquot_ref(kdev_t dev, short type) { struct file *filp; - int cnt; - for (filp = first_file, cnt = 0; cnt < nr_files; cnt++, filp = filp->f_next) { - if (!filp->f_count || !filp->f_inode || filp->f_inode->i_dev != dev) + for (filp = inuse_filps; filp; filp = filp->f_next) { + if (!filp->f_inode || filp->f_inode->i_dev != dev) continue; if (filp->f_mode & FMODE_WRITE && filp->f_inode->i_sb->dq_op) { filp->f_inode->i_sb->dq_op->initialize(filp->f_inode, type); @@ -161,10 +121,9 @@ void add_dquot_ref(kdev_t dev, short type) void reset_dquot_ptrs(kdev_t dev, short type) { struct file *filp; - int cnt; - for (filp = first_file, cnt = 0; cnt < nr_files; cnt++, filp = filp->f_next) { - if (!filp->f_count || !filp->f_inode || filp->f_inode->i_dev != dev) + for (filp = inuse_filps; filp; filp = filp->f_next) { + if (!filp->f_inode || filp->f_inode->i_dev != dev) continue; if (IS_WRITABLE(filp->f_inode)) { filp->f_inode->i_dquot[type] = NODQUOT; diff --git a/fs/inode.c b/fs/inode.c index b1d9bda4e..307b76063 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -232,12 +232,10 @@ repeat: int fs_may_remount_ro(kdev_t dev) { struct file * file; - int i; /* Check that no files are currently opened for writing. */ - for (file = first_file, i=0; if_next) { - if (!file->f_count || !file->f_inode || - file->f_inode->i_dev != dev) + for (file = inuse_filps; file; file = file->f_next) { + if (!file->f_inode || file->f_inode->i_dev != dev) continue; if (S_ISREG(file->f_inode->i_mode) && (file->f_mode & 2)) return 0; @@ -288,7 +286,7 @@ int inode_change_ok(struct inode *inode, struct iattr *attr) ((attr->ia_valid & ATTR_GID) && (!in_group_p(attr->ia_gid) && - (attr->ia_gid != inode->i_gid))) || + (attr->ia_gid != inode->i_gid)) && not_fsuser) || ((attr->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)) && (fsuid != iuid) && not_fsuser)) @@ -325,6 +323,8 @@ void inode_setattr(struct inode *inode, struct iattr *attr) if (!fsuser() && !in_group_p(inode->i_gid)) inode->i_mode &= ~S_ISGID; } + if (attr->ia_valid & ATTR_ATTR_FLAG) + inode->i_attr_flags = attr->ia_attr_flags; inode->i_dirt = 1; } @@ -647,7 +647,7 @@ void inode_init(void) int i; inode_cachep = kmem_cache_create("inode", sizeof(struct inode), - sizeof(unsigned long) * 4, + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if(!inode_cachep) panic("Cannot create inode SLAB cache\n"); diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 7a4943ede..30d0bf4c4 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -121,6 +121,11 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, char *name; struct iso_directory_record *de; + if( filp->f_pos >= inode->i_size ) { + return 0; + + } + offset = filp->f_pos & (bufsize - 1); block = isofs_bmap(inode, filp->f_pos >> bufbits); diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 8d9ce9d96..708198a00 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -138,13 +138,7 @@ static int parse_options(char *options, struct iso9660_options * popt) !strcmp(this_char,"uid") || !strcmp(this_char,"gid"))) { char * vpnt = value; - unsigned int ivalue; - ivalue = 0; - while(*vpnt){ - if(*vpnt < '0' || *vpnt > '9') break; - ivalue = ivalue * 10 + (*vpnt - '0'); - vpnt++; - } + unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0); if (*vpnt) return 0; switch(*this_char) { case 'b': diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 71f816b47..06ccfde5c 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -65,7 +65,6 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, unsigned char bufbits = ISOFS_BUFFER_BITS(dir); unsigned int block, i, f_pos, offset, inode_number; struct buffer_head * bh; - void * cpnt = NULL; unsigned int old_offset; unsigned int backlink; int dlen, rrflag, match; @@ -117,21 +116,8 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, /* Handle case where the directory entry spans two blocks. Usually 1024 byte boundaries */ if (offset >= bufsize) { - unsigned int frag1; - frag1 = bufsize - old_offset; - cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL); - if (!cpnt) return 0; - memcpy(cpnt, bh->b_data + old_offset, frag1); - - de = (struct iso_directory_record *) cpnt; - brelse(bh); - offset = f_pos & (bufsize - 1); - block = isofs_bmap(dir,f_pos>>bufbits); - if (!block || !(bh = bread(dir->i_dev,block,bufsize))) { - kfree(cpnt); - return 0; - }; - memcpy((char *)cpnt+frag1, bh->b_data, offset); + printk("Directory entry extends past end of iso9660 block\n"); + return 0; } /* Handle the '.' case */ @@ -190,12 +176,6 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, match = isofs_match(namelen,name,dpnt,dlen); } - if (cpnt) - { - kfree(cpnt); - cpnt = NULL; - } - if(rrflag) kfree(dpnt); if (match) { if(inode_number == -1) { @@ -217,8 +197,6 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, } } out: - if (cpnt) - kfree(cpnt); brelse(bh); return NULL; } diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 6f4539045..a9bb95f52 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -60,21 +60,6 @@ block = cont_extent; \ offset = cont_offset; \ offset1 = 0; \ - if(ISOFS_BUFFER_SIZE(DEV) == 1024) { \ - block <<= 1; \ - if (offset >= 1024) block++; \ - offset &= 1023; \ - if(offset + cont_size >= 1024) { \ - bh = bread(DEV->i_dev, block++, ISOFS_BUFFER_SIZE(DEV)); \ - if(!bh) {printk("Unable to read continuation Rock Ridge record\n"); \ - kfree(buffer); \ - buffer = NULL; } else { \ - memcpy(buffer, bh->b_data + offset, 1024 - offset); \ - brelse(bh); \ - offset1 = 1024 - offset; \ - offset = 0;} \ - } \ - }; \ if(buffer) { \ bh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \ if(bh){ \ @@ -429,7 +414,6 @@ char * get_rock_ridge_symlink(struct inode * inode) unsigned char bufbits = ISOFS_BUFFER_BITS(inode); struct buffer_head * bh; unsigned char * pnt; - void * cpnt = NULL; char * rpnt; struct iso_directory_record * raw_inode; CONTINUE_DECLS; @@ -455,24 +439,12 @@ char * get_rock_ridge_symlink(struct inode * inode) raw_inode = ((struct iso_directory_record *) pnt); + /* + * If we go past the end of the buffer, there is some sort of error. + */ if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){ - int frag1, offset; - - offset = (inode->i_ino & (bufsize - 1)); - frag1 = bufsize - offset; - cpnt = kmalloc(*pnt,GFP_KERNEL); - if(!cpnt) return NULL; - memcpy(cpnt, bh->b_data + offset, frag1); - brelse(bh); - if (!(bh = bread(inode->i_dev,++block, bufsize))) { - kfree(cpnt); - printk("unable to read i-node block"); - return NULL; - }; - offset += *pnt - bufsize; - memcpy((char *)cpnt+frag1, bh->b_data, offset); - pnt = ((unsigned char *) cpnt); - raw_inode = ((struct iso_directory_record *) pnt); + printk("symlink spans iso9660 blocks\n"); + return NULL; }; /* Now test for possible Rock Ridge extensions which will override some of @@ -558,11 +530,6 @@ char * get_rock_ridge_symlink(struct inode * inode) MAYBE_CONTINUE(repeat,inode); brelse(bh); - if (cpnt) { - kfree(cpnt); - cpnt = NULL; - }; - return rpnt; out: if(buffer) kfree(buffer); diff --git a/fs/lockd/.cvsignore b/fs/lockd/.cvsignore new file mode 100644 index 000000000..4671378ae --- /dev/null +++ b/fs/lockd/.cvsignore @@ -0,0 +1 @@ +.depend diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 24093a615..afc3fb2f0 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -228,12 +228,12 @@ nlm_release_file(struct nlm_file *file) down(&nlm_file_sema); /* If there are no more locks etc, delete the file */ - if (--(file->f_count) == 0 - && !nlm_inspect_file(NULL, file, NLM_ACT_CHECK)) - nlm_delete_file(file); + if(--file->f_count == 0) { + if(!nlm_inspect_file(NULL, file, NLM_ACT_CHECK)) + nlm_delete_file(file); + } up(&nlm_file_sema); - return; } /* diff --git a/fs/locks.c b/fs/locks.c index 3aa530897..8ca8aa183 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -100,6 +100,9 @@ * * Some adaptations for NFS support. * Olaf Kirch (okir@monad.swb.de), Dec 1996, + * + * Fixed /proc/locks interface so that we can't overrun the buffer we are handed. + * Andy Walker (andy@lysaker.kvaerner.no), May 12, 1997. */ #include @@ -132,7 +135,7 @@ static int posix_locks_deadlock(struct file_lock *caller, static struct file_lock *locks_alloc_lock(struct file_lock *fl); static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl); static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait); -static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx); +static char *lock_get_status(struct file_lock *fl, int id, char *pfx); static void locks_insert_block(struct file_lock *blocker, struct file_lock *waiter); static void locks_delete_block(struct file_lock *blocker, struct file_lock *waiter); @@ -227,6 +230,7 @@ void posix_block_lock(struct file_lock *blocker, struct file_lock *waiter) { locks_insert_block(blocker, waiter); + return; } void @@ -234,6 +238,7 @@ posix_unblock_lock(struct file_lock *waiter) { if (waiter->fl_prevblock) locks_delete_block(waiter->fl_prevblock, waiter); + return; } /* Wake up processes blocked waiting for blocker. @@ -269,20 +274,20 @@ asmlinkage int sys_flock(unsigned int fd, unsigned int cmd) { struct file_lock file_lock; struct file *filp; - int err; + int error; lock_kernel(); if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd])) - err = -EBADF; + error = -EBADF; else if (!flock_make_lock(filp, &file_lock, cmd)) - err = -EINVAL; + error = -EINVAL; else if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3)) - err = -EBADF; + error = -EBADF; else - err = flock_lock_file(filp, &file_lock, - (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1); + error = flock_lock_file(filp, &file_lock, + (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1); unlock_kernel(); - return err; + return (error); } /* Report the first existing lock that would conflict with l. @@ -298,7 +303,7 @@ int fcntl_getlk(unsigned int fd, struct flock *l) if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd])) return (-EBADF); if (copy_from_user(&flock, l, sizeof(flock))) - return -EFAULT; + return (-EFAULT); if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK)) return (-EINVAL); @@ -308,9 +313,9 @@ int fcntl_getlk(unsigned int fd, struct flock *l) if (filp->f_op->lock) { error = filp->f_op->lock(filp->f_inode, filp, - F_GETLK, &file_lock); + F_GETLK, &file_lock); if (error < 0) - return error; + return (error); fl = &file_lock; } else { fl = posix_test_lock(filp, &file_lock); @@ -323,12 +328,12 @@ int fcntl_getlk(unsigned int fd, struct flock *l) fl->fl_end - fl->fl_start + 1; flock.l_whence = 0; flock.l_type = fl->fl_type; - return copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0; + return (copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0); } else { flock.l_type = F_UNLCK; } - return copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0; + return (copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0); } /* Apply the lock described by l to an open file descriptor. @@ -361,12 +366,11 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) do { if (vma->vm_flags & VM_MAYSHARE) return (-EAGAIN); - vma = vma->vm_next_share; - } while (vma != inode->i_mmap); + } while ((vma = vma->vm_next_share) != NULL); } if (copy_from_user(&flock, l, sizeof(flock))) - return -EFAULT; + return (-EFAULT); if (!posix_make_lock(filp, &file_lock, &flock)) return (-EINVAL); @@ -399,13 +403,13 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) break; #endif default: - return -EINVAL; + return (-EINVAL); } if (filp->f_op->lock != NULL) { error = filp->f_op->lock(filp->f_inode, filp, cmd, &file_lock); if (error < 0) - return error; + return (error); } return (posix_lock_file(filp, &file_lock, cmd == F_SETLKW)); @@ -457,7 +461,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl) break; } - return cfl; + return (cfl); } int locks_verify_locked(struct inode *inode) @@ -1044,16 +1048,18 @@ static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) } -static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx) +static char *lock_get_status(struct file_lock *fl, int id, char *pfx) { + static char temp[129]; + char *p = temp; struct inode *inode; inode = fl->fl_file->f_inode; p += sprintf(p, "%d:%s ", id, pfx); if (fl->fl_flags & FL_POSIX) { - p += sprintf(p, "%s %s ", - (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX", + p += sprintf(p, "%6s %s ", + (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ", (IS_MANDLOCK(inode) && (inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ? "MANDATORY" : "ADVISORY "); @@ -1066,28 +1072,68 @@ static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx) fl->fl_pid, kdevname(inode->i_dev), inode->i_ino, fl->fl_start, fl->fl_end); - p += sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n", - (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink, - (long)fl->fl_next, (long)fl->fl_nextblock); - return (p); + sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n", + (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink, + (long)fl->fl_next, (long)fl->fl_nextblock); + return (temp); } -int get_locks_status(char *buf) +static inline int copy_lock_status(char *p, char **q, off_t pos, int len, + off_t offset, int length) +{ + int i; + + i = pos - offset; + if (i > 0) { + if (i >= length) { + i = len + length - i; + memcpy(*q, p, i); + *q += i; + return (0); + } + if (i < len) { + p += len - i; + } + else + i = len; + memcpy(*q, p, i); + *q += i; + } + + return (1); +} + +int get_locks_status(char *buffer, char **start, off_t offset, int length) { struct file_lock *fl; struct file_lock *bfl; char *p; + char *q = buffer; int i; + int len; + off_t pos = 0; - p = buf; for (fl = file_lock_table, i = 1; fl != NULL; fl = fl->fl_nextlink, i++) { - p = lock_get_status(fl, p, i, ""); + p = lock_get_status(fl, i, ""); + len = strlen(p); + pos += len; + if (!copy_lock_status(p, &q, pos, len, offset, length)) + goto done; if ((bfl = fl->fl_nextblock) == NULL) continue; do { - p = lock_get_status(bfl, p, i, " ->"); + p = lock_get_status(bfl, i, " ->"); + len = strlen(p); + pos += len; + if (!copy_lock_status(p, &q, pos, len, offset, length)) + goto done; } while ((bfl = bfl->fl_nextblock) != fl); } - return (p - buf); +done: + if (q != buffer) + *start = buffer; + return (q - buffer); } + + diff --git a/fs/msdos/msdosfs_syms.c b/fs/msdos/msdosfs_syms.c index 914a178a9..9e2c26bd6 100644 --- a/fs/msdos/msdosfs_syms.c +++ b/fs/msdos/msdosfs_syms.c @@ -30,7 +30,7 @@ EXPORT_SYMBOL(msdos_read_super); EXPORT_SYMBOL(msdos_put_super); -static struct file_system_type msdos_fs_type = { +struct file_system_type msdos_fs_type = { msdos_read_super, "msdos", 1, NULL }; diff --git a/fs/namei.c b/fs/namei.c index aeaca8f45..35ebbd4f4 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -124,24 +124,16 @@ int permission(struct inode * inode,int mask) * put_write_access() releases this write permission. * This is used for regular files. * We cannot support write (and maybe mmap read-write shared) accesses and - * MAP_DENYWRITE mmappings simultaneously. + * MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode + * can have the following values: + * 0: no writers, no VM_DENYWRITE mappings + * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist + * > 0: (i_writecount) users are writing to the file. */ int get_write_access(struct inode * inode) { - struct task_struct * p; - - if ((inode->i_count > 1) && S_ISREG(inode->i_mode)) /* shortcut */ - for_each_task(p) { - struct vm_area_struct * mpnt; - if (!p->mm) - continue; - for(mpnt = p->mm->mmap; mpnt; mpnt = mpnt->vm_next) { - if (inode != mpnt->vm_inode) - continue; - if (mpnt->vm_flags & VM_DENYWRITE) - return -ETXTBSY; - } - } + if (inode->i_writecount < 0) + return -ETXTBSY; inode->i_writecount++; return 0; } diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 1db0dcc78..4cf65f8a9 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -177,7 +178,7 @@ struct super_block * printk("ncp_read_super: could not alloc ncp_server\n"); return NULL; } - ncp_filp->f_count += 1; + ncp_filp->f_count++; lock_super(sb); @@ -256,7 +257,7 @@ struct super_block * ncp_unlock_server(server); ncp_kfree_s(server->packet, server->packet_size); fail: - ncp_filp->f_count -= 1; + put_filp(ncp_filp); ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); return NULL; } diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 732874d7f..d68dca70d 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -228,6 +228,8 @@ root_dev_chg_route(int op, struct device *dev, __u32 dest, __u32 mask, __u32 gw) unsigned long oldfs; int err; + memset(&route, 0, sizeof(struct rtentry)); /* or else! */ + route.rt_dev = dev->name; route.rt_mtu = dev->mtu; route.rt_flags = RTF_UP; @@ -247,9 +249,15 @@ root_dev_chg_route(int op, struct device *dev, __u32 dest, __u32 mask, __u32 gw) set_fs(KERNEL_DS); err = ip_rt_ioctl(op, &route); set_fs(oldfs); - printk(KERN_NOTICE "%s route %s %s %s: res %d\n", - (op == SIOCADDRT? "add" : "del"), - in_ntoa(dest), in_ntoa(mask), in_ntoa(gw), err); + + /* in_ntoa in ipv4/utils.c uses a single static buffer, so + * must make multiple printk calls, one for each in_ntoa + * invocation... + */ + printk(KERN_NOTICE "%s route ", (op == SIOCADDRT ? "addr" : "del")); + printk("%s ", in_ntoa(dest)); + printk("%s ", in_ntoa(mask)); + printk("%s: res %d\n", in_ntoa(gw), err); return err; } @@ -280,8 +288,10 @@ static void root_dev_close(void) nextp = openp->next; openp->next = NULL; if (openp->dev != root_dev) { - if (!(openp->old_flags & IFF_UP)) + if (!(openp->old_flags & IFF_UP)) { dev_close(openp->dev); + } + openp->dev->flags = openp->old_flags; } kfree_s(openp, sizeof(struct open_dev)); @@ -1323,6 +1333,13 @@ static int root_nfs_setup(void) root_dev->pa_brdaddr = root_dev->pa_addr | ~root_dev->pa_mask; root_dev->pa_dstaddr = 0; + /* Sticky situation, but it has a solution. We opened it earlier, + * but before we knew what pa_addr etc. to give to it, thus the + * routing code did not add a RTF_LOCAL route for it (how could + * it?) so we send the pseudo device state change event now. -DaveM + */ + ip_rt_event(NETDEV_CHANGE, root_dev); + /* * Now add a route to the server. If there is no gateway given, * the server is on the same subnet, so we establish only a route to diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f48df4571..3c17b6eec 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -130,9 +130,9 @@ nfs_unlock_page(struct page *page) #ifdef CONFIG_NFS_SWAP /* async swap-out support */ - if (clear_bit(PG_decr_after, &page->flags)) + if (test_and_clear_bit(PG_decr_after, &page->flags)) atomic_dec(&page->count); - if (clear_bit(PG_swap_unlock_after, &page->flags)) + if (test_and_clear_bit(PG_swap_unlock_after, &page->flags)) swap_after_unlock_page(page->swap_unlock_entry); #endif } @@ -530,7 +530,7 @@ nfs_flush_request(struct nfs_wreq *req) page->offset); req->wb_flags |= NFS_WRITE_WANTLOCK; - if (!set_bit(PG_locked, &page->flags)) { + if (!test_and_set_bit(PG_locked, &page->flags)) { transfer_page_lock(req); } else { printk(KERN_WARNING "NFS oops in %s: can't lock page!\n", @@ -719,7 +719,7 @@ nfs_wback_lock(struct rpc_task *task) if (!WB_HAVELOCK(req)) req->wb_flags |= NFS_WRITE_WANTLOCK; - if (WB_WANTLOCK(req) && set_bit(PG_locked, &page->flags)) { + if (WB_WANTLOCK(req) && test_and_set_bit(PG_locked, &page->flags)) { dprintk("NFS: page already locked in writeback_lock!\n"); task->tk_timeout = 2 * HZ; rpc_sleep_on(&write_queue, task, NULL, NULL); diff --git a/fs/nfsd/.cvsignore b/fs/nfsd/.cvsignore new file mode 100644 index 000000000..4671378ae --- /dev/null +++ b/fs/nfsd/.cvsignore @@ -0,0 +1 @@ +.depend diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index ecec8a22b..6327cee48 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -285,6 +285,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, if (err) { if (wflag) put_write_access(inode); + + /* I nearly added put_filp() call here, but this filp + * is really on callers stack frame. -DaveM + */ filp->f_count--; return nfserrno(-err); } diff --git a/fs/open.c b/fs/open.c index e81c5fbf5..a6a51799a 100644 --- a/fs/open.c +++ b/fs/open.c @@ -605,7 +605,7 @@ cleanup_all: cleanup_inode: iput(inode); cleanup_file: - f->f_count--; + put_filp(f); return error; } diff --git a/fs/pipe.c b/fs/pipe.c index 9cf3c7a6d..5fa5d6e91 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -74,7 +75,10 @@ static long pipe_read(struct inode * inode, struct file * filp, PIPE_LOCK(*inode)--; wake_up_interruptible(&PIPE_WAIT(*inode)); if (read) { - inode->i_atime = CURRENT_TIME; + if (DO_UPDATE_ATIME(inode)) { + inode->i_atime = CURRENT_TIME; + inode->i_dirt = 1; + } return read; } if (PIPE_WRITERS(*inode)) @@ -128,6 +132,7 @@ static long pipe_write(struct inode * inode, struct file * filp, free = 1; } inode->i_ctime = inode->i_mtime = CURRENT_TIME; + inode->i_dirt = 1; return written; } @@ -440,9 +445,9 @@ close_f12_inode: inode->i_count--; iput(inode); close_f12: - f2->f_count--; + put_filp(f2); close_f1: - f1->f_count--; + put_filp(f1); no_files: return error; } diff --git a/fs/proc/array.c b/fs/proc/array.c index 4671f1a98..f8d5d3464 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -154,9 +154,7 @@ static long read_profile(struct inode *inode, struct file *file, return read; } -#ifdef __SMP__ -extern int setup_profiling_timer (unsigned int multiplier); /* * Writing to /proc/profile resets the counters @@ -168,6 +166,8 @@ static long write_profile(struct inode * inode, struct file * file, const char * buf, unsigned long count) { int i=prof_len; +#ifdef __SMP__ + extern int setup_profiling_timer (unsigned int multiplier); if (count==sizeof(int)) { unsigned int multiplier; @@ -178,14 +178,12 @@ static long write_profile(struct inode * inode, struct file * file, if (setup_profiling_timer(multiplier)) return -EINVAL; } +#endif while (i--) prof_buffer[i]=0UL; return count; } -#else -#define write_profile NULL -#endif static struct file_operations proc_profile_operations = { NULL, /* lseek */ @@ -270,7 +268,7 @@ static int get_uptime(char * buffer) unsigned long idle; uptime = jiffies; - idle = task[0]->utime + task[0]->stime; + idle = task[0]->times.tms_utime + task[0]->times.tms_stime; /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but that would overflow about every five days at HZ == 100. @@ -344,18 +342,6 @@ static int get_cmdline(char * buffer) return sprintf(buffer, "%s\n", saved_command_line); } -static struct task_struct ** get_task(pid_t pid) -{ - struct task_struct ** p; - - p = task; - while (++p < task+NR_TASKS) { - if (*p && (*p)->pid == pid) - return p; - } - return NULL; -} - static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr) { pgd_t *page_dir; @@ -386,7 +372,7 @@ static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr) return pte_page(pte) + (ptr & ~PAGE_MASK); } -static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer) +static int get_array(struct task_struct *p, unsigned long start, unsigned long end, char * buffer) { unsigned long addr; int size = 0, result = 0; @@ -395,7 +381,7 @@ static int get_array(struct task_struct ** p, unsigned long start, unsigned long if (start >= end) return result; for (;;) { - addr = get_phys_addr(*p, start); + addr = get_phys_addr(p, start); if (!addr) return result; do { @@ -417,20 +403,20 @@ static int get_array(struct task_struct ** p, unsigned long start, unsigned long static int get_env(int pid, char * buffer) { - struct task_struct ** p = get_task(pid); + struct task_struct *p = find_task_by_pid(pid); - if (!p || !*p || !(*p)->mm) + if (!p || !p->mm) return 0; - return get_array(p, (*p)->mm->env_start, (*p)->mm->env_end, buffer); + return get_array(p, p->mm->env_start, p->mm->env_end, buffer); } static int get_arg(int pid, char * buffer) { - struct task_struct ** p = get_task(pid); + struct task_struct *p = find_task_by_pid(pid); - if (!p || !*p || !(*p)->mm) + if (!p || !p->mm) return 0; - return get_array(p, (*p)->mm->arg_start, (*p)->mm->arg_end, buffer); + return get_array(p, p->mm->arg_start, p->mm->arg_end, buffer); } static unsigned long get_wchan(struct task_struct *p) @@ -443,7 +429,7 @@ static unsigned long get_wchan(struct task_struct *p) unsigned long stack_page; int count = 0; - stack_page = p->kernel_stack_page; + stack_page = 4096 + (unsigned long)p; if (!stack_page) return 0; ebp = p->tss.ebp; @@ -523,15 +509,16 @@ static unsigned long get_wchan(struct task_struct *p) } #if defined(__i386__) -# define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019]) -# define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1022]) +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) #elif defined(__alpha__) /* * See arch/alpha/kernel/ptrace.c for details. */ # define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + (long)&((struct pt_regs *)0)->reg) -# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc))) +# define KSTK_EIP(tsk) \ + (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk))) # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) #elif defined(__mc68000__) #define KSTK_EIP(tsk) \ @@ -702,9 +689,9 @@ static inline char * task_sig(struct task_struct *p, char *buffer) static int get_status(int pid, char * buffer) { char * orig = buffer; - struct task_struct ** p = get_task(pid), *tsk; + struct task_struct *tsk = find_task_by_pid(pid); - if (!p || (tsk = *p) == NULL) + if (!tsk) return 0; buffer = task_name(tsk, buffer); buffer = task_state(tsk, buffer); @@ -715,14 +702,14 @@ static int get_status(int pid, char * buffer) static int get_stat(int pid, char * buffer) { - struct task_struct ** p = get_task(pid), *tsk; + struct task_struct *tsk = find_task_by_pid(pid); unsigned long sigignore=0, sigcatch=0, wchan; unsigned long vsize, eip, esp; long priority, nice; int i,tty_pgrp; char state; - if (!p || (tsk = *p) == NULL) + if (!tsk) return 0; if (tsk->state < 0 || tsk->state > 5) state = '.'; @@ -735,10 +722,8 @@ static int get_stat(int pid, char * buffer) vsize += vma->vm_end - vma->vm_start; vma = vma->vm_next; } - if (tsk->kernel_stack_page) { - eip = KSTK_EIP(tsk); - esp = KSTK_ESP(tsk); - } + eip = KSTK_EIP(tsk); + esp = KSTK_ESP(tsk); } wchan = get_wchan(tsk); if (tsk->sig) { @@ -784,10 +769,10 @@ static int get_stat(int pid, char * buffer) tsk->cmin_flt, tsk->maj_flt, tsk->cmaj_flt, - tsk->utime, - tsk->stime, - tsk->cutime, - tsk->cstime, + tsk->times.tms_utime, + tsk->times.tms_stime, + tsk->times.tms_cutime, + tsk->times.tms_cstime, priority, nice, tsk->timeout, @@ -885,10 +870,10 @@ static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long en static int get_statm(int pid, char * buffer) { - struct task_struct ** p = get_task(pid), *tsk; + struct task_struct *tsk = find_task_by_pid(pid); int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0; - if (!p || (tsk = *p) == NULL) + if (!tsk) return 0; if (tsk->mm && tsk->mm != &init_mm) { struct vm_area_struct * vma = tsk->mm->mmap; @@ -953,17 +938,17 @@ static int get_statm(int pid, char * buffer) static long read_maps (int pid, struct file * file, char * buf, unsigned long count) { - struct task_struct ** p = get_task(pid); + struct task_struct *p = find_task_by_pid(pid); char * destptr; loff_t lineno; int column; struct vm_area_struct * map; int i; - if (!p || !*p) + if (!p) return -EINVAL; - if (!(*p)->mm || (*p)->mm == &init_mm || count == 0) + if (!p->mm || p->mm == &init_mm || count == 0) return 0; /* decode f_pos */ @@ -971,7 +956,7 @@ static long read_maps (int pid, struct file * file, column = file->f_pos & (MAPS_LINE_LENGTH-1); /* quickly go to line lineno */ - for (map = (*p)->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++) + for (map = p->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++) continue; destptr = buf; @@ -1032,7 +1017,7 @@ static long read_maps (int pid, struct file * file, /* By writing to user space, we might have slept. * Stop the loop, to avoid a race condition. */ - if (*p != current) + if (p != current) break; } @@ -1055,7 +1040,7 @@ extern int get_cpuinfo(char *); extern int get_pci_list(char*); extern int get_md_status (char *); extern int get_rtc_status (char *); -extern int get_locks_status (char *); +extern int get_locks_status (char *, char **, off_t, int); extern int get_swaparea_info (char *); #ifdef __SMP_PROF__ extern int get_smp_prof_list(char *); @@ -1142,7 +1127,7 @@ static long get_root_array(char * page, int type, char **start, return get_rtc_status(page); #endif case PROC_LOCKS: - return get_locks_status(page); + return get_locks_status(page, start, offset, length); #ifdef CONFIG_ZORRO case PROC_ZORRO: return zorro_get_list(page); diff --git a/fs/proc/base.c b/fs/proc/base.c index 28cd61f5f..7e9a65e08 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -52,17 +52,14 @@ static struct inode_operations proc_base_inode_operations = { static void proc_pid_fill_inode(struct inode * inode) { - struct task_struct * p; + struct task_struct *p; int pid = inode->i_ino >> 16; int ino = inode->i_ino & 0xffff; - for_each_task(p) { - if (p->pid == pid) { - if (p->dumpable || ino == PROC_PID_INO) { - inode->i_uid = p->euid; - inode->i_gid = p->gid; - } - return; + if ((p = find_task_by_pid(pid)) != NULL) { + if (p->dumpable || ino == PROC_PID_INO) { + inode->i_uid = p->euid; + inode->i_gid = p->gid; } } } diff --git a/fs/proc/fd.c b/fs/proc/fd.c index e5e4fd9a8..fd262bc9d 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -58,7 +58,6 @@ static int proc_lookupfd(struct inode * dir, const char * name, int len, unsigned int ino, pid, fd, c; struct task_struct * p; struct super_block * sb; - int i; *result = NULL; ino = dir->i_ino; @@ -100,10 +99,8 @@ static int proc_lookupfd(struct inode * dir, const char * name, int len, break; } } - for (i = 0 ; i < NR_TASKS ; i++) - if ((p = task[i]) && p->pid == pid) - break; - if (!pid || i >= NR_TASKS) + p = find_task_by_pid(pid); + if (!pid || !p) return -ENOENT; /* @@ -112,8 +109,11 @@ static int proc_lookupfd(struct inode * dir, const char * name, int len, * is NULL */ - if (fd >= NR_OPEN || !p->files || !p->files->fd[fd] || !p->files->fd[fd]->f_inode) - return -ENOENT; + if (fd >= NR_OPEN || + !p->files || + !p->files->fd[fd] || + !p->files->fd[fd]->f_inode) + return -ENOENT; ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd; @@ -128,8 +128,7 @@ static int proc_readfd(struct inode * inode, struct file * filp, void * dirent, filldir_t filldir) { char buf[NUMBUF]; - int task_nr; - struct task_struct * p; + struct task_struct * p, **tarrayp; unsigned int fd, pid, ino; unsigned long i,j; @@ -149,13 +148,10 @@ static int proc_readfd(struct inode * inode, struct file * filp, return 0; } - task_nr = 1; - for (;;) { - if ((p = task[task_nr]) && p->pid == pid) - break; - if (++task_nr >= NR_TASKS) - return 0; - } + p = find_task_by_pid(pid); + if(!p) + return 0; + tarrayp = p->tarray_ptr; for (fd -= 2 ; fd < NR_OPEN; fd++, filp->f_pos++) { if (!p->files) @@ -176,7 +172,7 @@ static int proc_readfd(struct inode * inode, struct file * filp, break; /* filldir() might have slept, so we must re-validate "p" */ - if (p != task[task_nr] || p->pid != pid) + if (p != *tarrayp || p->pid != pid) break; } return 0; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 0ff6a4f5c..943137bf4 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -81,7 +81,6 @@ static int parse_options(char *options,uid_t *uid,gid_t *gid) struct inode * proc_get_inode(struct super_block * s, int ino, struct proc_dir_entry * de) { struct inode * inode = iget(s, ino); - struct task_struct *p; #ifdef CONFIG_SUN_OPENPROMFS_MODULE if ((inode->i_ino >= PROC_OPENPROM_FIRST) @@ -111,9 +110,14 @@ struct inode * proc_get_inode(struct super_block * s, int ino, struct proc_dir_e * Fixup the root inode's nlink value */ if (inode->i_ino == PROC_ROOT_INO) { - for_each_task(p) - if (p && p->pid) + struct task_struct *p; + + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->pid) inode->i_nlink++; + } + read_unlock(&tasklist_lock); } return inode; } @@ -155,7 +159,6 @@ void proc_read_inode(struct inode * inode) { unsigned long ino, pid; struct task_struct * p; - int i; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = 0; @@ -170,13 +173,8 @@ void proc_read_inode(struct inode * inode) inode->i_nlink = 1; inode->i_size = 0; pid = ino >> 16; - if (!pid) - return; - p = task[0]; - for (i = 0; i < NR_TASKS ; i++) - if ((p = task[i]) && (p->pid == pid)) - break; - if (!p || i >= NR_TASKS) + + if (!pid || ((p = find_task_by_pid(pid)) == NULL)) return; ino &= 0x0000ffff; @@ -198,7 +196,6 @@ void proc_read_inode(struct inode * inode) inode->i_mode |= S_IWUSR | S_IXUSR; return; } - return; } void proc_write_inode(struct inode * inode) diff --git a/fs/proc/link.c b/fs/proc/link.c index bbaab7c41..d5c08eafd 100644 --- a/fs/proc/link.c +++ b/fs/proc/link.c @@ -68,7 +68,7 @@ static int proc_follow_link(struct inode * dir, struct inode * inode, unsigned int pid, ino; struct task_struct * p; struct inode * new_inode; - int i, error; + int error; *res_inode = NULL; if (dir) @@ -82,10 +82,9 @@ static int proc_follow_link(struct inode * dir, struct inode * inode, ino = inode->i_ino; pid = ino >> 16; ino &= 0x0000ffff; - for (i = 0 ; i < NR_TASKS ; i++) - if ((p = task[i]) && p->pid == pid) - break; - if (i >= NR_TASKS) { + + p = find_task_by_pid(pid); + if (!p) { iput(inode); return -ENOENT; } diff --git a/fs/proc/mem.c b/fs/proc/mem.c index ccd67566f..97acb5ee8 100644 --- a/fs/proc/mem.c +++ b/fs/proc/mem.c @@ -55,16 +55,10 @@ static struct task_struct * get_task(int pid) struct task_struct * tsk = current; if (pid != tsk->pid) { - int i; - tsk = NULL; - for (i = 1 ; i < NR_TASKS ; i++) - if (task[i] && task[i]->pid == pid) { - tsk = task[i]; - break; - } - /* - * allow accesses only under the same circumstances - * that we would allow ptrace to work + tsk = find_task_by_pid(pid); + + /* Allow accesses only under the same circumstances + * that we would allow ptrace to work. */ if (tsk) { if (!(tsk->flags & PF_PTRACED) @@ -291,10 +285,10 @@ int mem_mmap(struct inode * inode, struct file * file, return -ENOMEM; if (!pte_present(*src_table)) - do_no_page(tsk, src_vma, stmp, 1); + handle_mm_fault(tsk, src_vma, stmp, 1); if ((vma->vm_flags & VM_WRITE) && !pte_write(*src_table)) - do_wp_page(tsk, src_vma, stmp, 1); + handle_mm_fault(tsk, src_vma, stmp, 1); set_pte(src_table, pte_mkdirty(*src_table)); set_pte(dest_table, *src_table); diff --git a/fs/proc/root.c b/fs/proc/root.c index e5bb9d51b..11c27699a 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -683,16 +683,20 @@ static int proc_root_lookup(struct inode * dir,const char * name, int len, struct inode ** result) { unsigned int pid, c; - int i, ino, retval; + int ino, retval; struct task_struct *p; dir->i_count++; if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */ dir->i_nlink = proc_root.nlink; - for_each_task(p) - if (p && p->pid) + + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->pid) dir->i_nlink++; + } + read_unlock(&tasklist_lock); } retval = proc_lookup(dir, name, len, result); @@ -716,10 +720,8 @@ static int proc_root_lookup(struct inode * dir,const char * name, int len, break; } } - for (i = 0 ; i < NR_TASKS ; i++) - if (task[i] && task[i]->pid == pid) - break; - if (!pid || i >= NR_TASKS) { + p = find_task_by_pid(pid); + if (!pid || !p) { iput(dir); return -ENOENT; } @@ -796,34 +798,40 @@ int proc_readdir(struct inode * inode, struct file * filp, static int proc_root_readdir(struct inode * inode, struct file * filp, void * dirent, filldir_t filldir) { + struct task_struct *p; char buf[NUMBUF]; - unsigned int nr,pid; - unsigned long i,j; + unsigned int nr = filp->f_pos; - nr = filp->f_pos; if (nr < FIRST_PROCESS_ENTRY) { int error = proc_readdir(inode, filp, dirent, filldir); if (error <= 0) return error; - filp->f_pos = nr = FIRST_PROCESS_ENTRY; + filp->f_pos = FIRST_PROCESS_ENTRY; } + nr = FIRST_PROCESS_ENTRY; - for (nr -= FIRST_PROCESS_ENTRY; nr < NR_TASKS; nr++, filp->f_pos++) { - struct task_struct * p = task[nr]; + read_lock(&tasklist_lock); + for_each_task(p) { + unsigned int pid; - if (!p || !(pid = p->pid)) + if(nr++ < filp->f_pos) continue; - j = NUMBUF; - i = pid; - do { - j--; - buf[j] = '0' + (i % 10); - i /= 10; - } while (i); + if((pid = p->pid) != 0) { + unsigned long j = NUMBUF, i = pid; - if (filldir(dirent, buf+j, NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) - break; + do { + j--; + buf[j] = '0' + (i % 10); + i /= 10; + } while (i); + + if (filldir(dirent, buf+j, NUMBUF-j, + filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) + break; + } + filp->f_pos++; } + read_unlock(&tasklist_lock); return 0; } diff --git a/fs/romfs/.cvsignore b/fs/romfs/.cvsignore new file mode 100644 index 000000000..4671378ae --- /dev/null +++ b/fs/romfs/.cvsignore @@ -0,0 +1 @@ +.depend diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 7ab7d15ff..1943045bb 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -242,7 +243,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent) printk("smb_read_super: could not alloc smb_sb_info\n"); return NULL; } - filp->f_count += 1; + filp->f_count++; lock_super(sb); @@ -319,7 +320,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent) smb_vfree(server->packet); server->packet = NULL; } - filp->f_count -= 1; + put_filp(filp); smb_dont_catch_keepalive(server); smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info)); return NULL; diff --git a/fs/super.c b/fs/super.c index 053c6321a..d24776cca 100644 --- a/fs/super.c +++ b/fs/super.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -552,7 +553,7 @@ kdev_t get_unnamed_dev(void) int i; for (i = 1; i < 256; i++) { - if (!set_bit(i,unnamed_dev_in_use)) + if (!test_and_set_bit(i,unnamed_dev_in_use)) return MKDEV(UNNAMED_MAJOR, i); } return 0; @@ -562,7 +563,7 @@ void put_unnamed_dev(kdev_t dev) { if (!dev || MAJOR(dev) != UNNAMED_MAJOR) return; - if (clear_bit(MINOR(dev), unnamed_dev_in_use)) + if (test_and_clear_bit(MINOR(dev), unnamed_dev_in_use)) return; printk("VFS: put_unnamed_dev: freeing unused device %s\n", kdevname(dev)); @@ -937,7 +938,11 @@ out: return retval; } +#ifdef CONFIG_BLK_DEV_INITRD static void do_mount_root(void) +#else +__initfunc(static void do_mount_root(void)) +#endif { struct file_system_type * fs_type; struct super_block * sb; @@ -1046,7 +1051,7 @@ static void do_mount_root(void) } -void mount_root(void) +__initfunc(void mount_root(void)) { memset(super_blocks, 0, sizeof(super_blocks)); do_mount_root(); diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c index 51cfb0809..c4c9e73ba 100644 --- a/fs/umsdos/namei.c +++ b/fs/umsdos/namei.c @@ -301,6 +301,9 @@ static void umsdos_ren_init( ,*(unsigned long *)current->kernel_stack_page \ ,__LINE__); \ } + +#undef chkstk +#define chkstk() do { } while (0) /* Rename a file (move) in the file system. diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index badb6c7e2..e3db004cc 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -174,10 +174,12 @@ check_stack(const char *fname, int lineno) printk("------- vfat kstack ok in %s line %d: SL=%d\n", fname, lineno, stack_level); #endif +#if 0 if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) { printk("******* vfat stack corruption detected in %s at line %d\n", fname, lineno); } +#endif } static int debug = 0; -- cgit v1.2.3