summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-06-01 03:16:17 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-06-01 03:16:17 +0000
commitd8d9b8f76f22b7a16a83e261e64f89ee611f49df (patch)
tree3067bc130b80d52808e6390c9fc7fc087ec1e33c /fs
parent19c9bba94152148523ba0f7ef7cffe3d45656b11 (diff)
Initial revision
Diffstat (limited to 'fs')
-rw-r--r--fs/affs/Changes95
-rw-r--r--fs/affs/amigaffs.c96
-rw-r--r--fs/affs/bitmap.c52
-rw-r--r--fs/affs/dir.c25
-rw-r--r--fs/affs/file.c99
-rw-r--r--fs/affs/inode.c201
-rw-r--r--fs/affs/namei.c37
-rw-r--r--fs/affs/symlink.c4
-rw-r--r--fs/autofs/.cvsignore1
-rw-r--r--fs/autofs/Makefile29
-rw-r--r--fs/autofs/autofs_i.h175
-rw-r--r--fs/autofs/dir.c2
-rw-r--r--fs/autofs/dirhash.c49
-rw-r--r--fs/autofs/init.c27
-rw-r--r--fs/autofs/inode.c11
-rw-r--r--fs/autofs/root.c106
-rw-r--r--fs/autofs/symlink.c2
-rw-r--r--fs/autofs/waitq.c18
-rw-r--r--fs/binfmt_elf.c104
-rw-r--r--fs/buffer.c28
-rw-r--r--fs/dcache.c15
-rw-r--r--fs/dquot.c3
-rw-r--r--fs/exec.c10
-rw-r--r--fs/ext2/balloc.c55
-rw-r--r--fs/ext2/inode.c77
-rw-r--r--fs/ext2/ioctl.c8
-rw-r--r--fs/ext2/namei.c2
-rw-r--r--fs/ext2/super.c3
-rw-r--r--fs/fcntl.c6
-rw-r--r--fs/file_table.c179
-rw-r--r--fs/inode.c12
-rw-r--r--fs/isofs/dir.c5
-rw-r--r--fs/isofs/inode.c8
-rw-r--r--fs/isofs/namei.c26
-rw-r--r--fs/isofs/rock.c43
-rw-r--r--fs/lockd/.cvsignore1
-rw-r--r--fs/lockd/svcsubs.c8
-rw-r--r--fs/locks.c108
-rw-r--r--fs/msdos/msdosfs_syms.c2
-rw-r--r--fs/namei.c22
-rw-r--r--fs/ncpfs/inode.c5
-rw-r--r--fs/nfs/nfsroot.c25
-rw-r--r--fs/nfs/write.c8
-rw-r--r--fs/nfsd/.cvsignore1
-rw-r--r--fs/nfsd/vfs.c4
-rw-r--r--fs/open.c2
-rw-r--r--fs/pipe.c11
-rw-r--r--fs/proc/array.c87
-rw-r--r--fs/proc/base.c13
-rw-r--r--fs/proc/fd.c30
-rw-r--r--fs/proc/inode.c21
-rw-r--r--fs/proc/link.c9
-rw-r--r--fs/proc/mem.c18
-rw-r--r--fs/proc/root.c54
-rw-r--r--fs/romfs/.cvsignore1
-rw-r--r--fs/smbfs/inode.c5
-rw-r--r--fs/super.c11
-rw-r--r--fs/umsdos/namei.c3
-rw-r--r--fs/vfat/namei.c2
59 files changed, 1344 insertions, 720 deletions
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: <function>: <error message>"
+ (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 <stdarg.h>
#include <linux/stat.h>
#include <linux/sched.h>
#include <linux/affs_fs.h>
@@ -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 <asm/system.h>
#include <asm/uaccess.h>
+/* 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 <linux/errno.h>
+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 <linux/auto_fs.h>
+
+/* This is the range of ioctl() numbers we claim as ours */
+#define AUTOFS_IOC_FIRST AUTOFS_IOC_READY
+#define AUTOFS_IOC_COUNT 32
+
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+
+#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 <asm/segment.h>
+
+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 <asm/uaccess.h>
+#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 <linux/auto_fs.h>
+#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 <linux/string.h>
-#include <linux/malloc.h>
-#include <linux/auto_fs.h>
+#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 <linux/module.h>
-#include <linux/auto_fs.h>
+#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 <linux/init.h>
+#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 <linux/file.h>
#include <linux/locks.h>
#include <asm/bitops.h>
-#include <linux/auto_fs.h>
+#include "autofs_i.h"
#define __NO_VERSION__
#include <linux/module.h>
@@ -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 <linux/errno.h>
#include <linux/stat.h>
-#include <linux/malloc.h>
-#include <linux/ioctl.h>
-#include <linux/auto_fs.h>
+#include <linux/param.h>
+#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 <linux/string.h>
#include <linux/sched.h>
-#include <linux/auto_fs.h>
+#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 <linux/malloc.h>
-#include <linux/signal.h>
#include <linux/sched.h>
-#include <linux/auto_fs.h>
+#include <linux/signal.h>
+#include <linux/file.h>
+#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 <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/tty.h>
+#include <linux/file.h>
#include <linux/malloc.h>
#include <linux/mount.h>
#include <linux/smp.h>
@@ -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 <linux/kernel.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/file.h>
#include <linux/mman.h>
#include <linux/a.out.h>
#include <linux/errno.h>
@@ -36,7 +37,6 @@
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/user.h>
-#include <linux/malloc.h>
#include <linux/binfmts.h>
#include <linux/personality.h>
#include <linux/smp.h>
@@ -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 <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/fs.h>
+#include <linux/file.h>
#include <linux/string.h>
#include <linux/mm.h>
+#include <linux/slab.h>
-/*
- * 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; i<nr_files; i++, file=file->f_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 <linux/malloc.h>
@@ -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 <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
+#include <linux/file.h>
#include <linux/fcntl.h>
#include <linux/malloc.h>
#include <linux/init.h>
@@ -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 <linux/fcntl.h>
#include <linux/termios.h>
#include <linux/mm.h>
+#include <linux/file.h>
#include <asm/poll.h>
#include <asm/uaccess.h>
@@ -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 <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
+#include <linux/file.h>
#include <linux/fcntl.h>
#include <linux/malloc.h>
#include <linux/init.h>
@@ -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 <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/fd.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -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;