diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
commit | beb116954b9b7f3bb56412b2494b562f02b864b1 (patch) | |
tree | 120e997879884e1b9d93b265221b939d2ef1ade1 /fs/sysv | |
parent | 908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff) |
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'fs/sysv')
-rw-r--r-- | fs/sysv/Makefile | 29 | ||||
-rw-r--r-- | fs/sysv/README | 37 | ||||
-rw-r--r-- | fs/sysv/balloc.c | 12 | ||||
-rw-r--r-- | fs/sysv/dir.c | 20 | ||||
-rw-r--r-- | fs/sysv/file.c | 46 | ||||
-rw-r--r-- | fs/sysv/fsync.c | 8 | ||||
-rw-r--r-- | fs/sysv/ialloc.c | 7 | ||||
-rw-r--r-- | fs/sysv/inode.c | 98 | ||||
-rw-r--r-- | fs/sysv/mmap.c | 85 | ||||
-rw-r--r-- | fs/sysv/namei.c | 23 | ||||
-rw-r--r-- | fs/sysv/symlink.c | 12 | ||||
-rw-r--r-- | fs/sysv/truncate.c | 14 |
12 files changed, 127 insertions, 264 deletions
diff --git a/fs/sysv/Makefile b/fs/sysv/Makefile index 4ef1cddcd..b5801e994 100644 --- a/fs/sysv/Makefile +++ b/fs/sysv/Makefile @@ -7,28 +7,9 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -.c.s: - $(CC) $(CFLAGS) -S $< -.c.o: - $(CC) $(CFLAGS) -c $< -.s.o: - $(AS) -o $*.o $< +O_TARGET := sysv.o +O_OBJS := ialloc.o balloc.o inode.o file.o dir.o symlink.o namei.o \ + fsync.o truncate.o +M_OBJS := $(O_TARGET) -OBJS= ialloc.o balloc.o inode.o file.o dir.o symlink.o namei.o \ - fsync.o truncate.o - -sysv.o: $(OBJS) - $(LD) -r -o sysv.o $(OBJS) - -modules: sysv.o - ln -sf ../fs/sysv/sysv.o $(TOPDIR)/modules - -dep: - $(CPP) -M *.c > .depend - -# -# include a dependency file if one exists -# -ifeq (.depend,$(wildcard .depend)) -include .depend -endif +include $(TOPDIR)/Rules.make diff --git a/fs/sysv/README b/fs/sysv/README deleted file mode 100644 index d318eb64b..000000000 --- a/fs/sysv/README +++ /dev/null @@ -1,37 +0,0 @@ -This is the implementation of the SystemV/Coherent filesystem for Linux. -It implements all of - - Xenix FS, - - SystemV/386 FS, - - Coherent FS. - -This is version beta 4. - -To install: -* Answer the 'System V and Coherent filesystem support' question with 'y' - when configuring the kernel. -* To mount a disk or a partition, use - mount [-r] -t sysv device mountpoint - The file system type names - -t sysv - -t xenix - -t coherent - may be used interchangeably, but the last two will eventually disappear. - -Bugs in the present implementation: -- Coherent FS: - - The "free list interleave" n:m is currently ignored. - - Only file systems with no filesystem name and no pack name are recognized. - (See Coherent "man mkfs" for a description of these features.) -- SystemV Release 2 FS: - The superblock is only searched in the blocks 9, 15, 18, which corresponds to the - beginning of track 1 on floppy disks. No support for this FS on hard disk yet. - - -Please report any bugs and suggestions to - Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhde.de> or - Pascal Haible <haible@izfm.uni-stuttgart.de> . - - -Bruno Haible -<haible@ma2s2.mathematik.uni-karlsruhe.de> - diff --git a/fs/sysv/balloc.c b/fs/sysv/balloc.c index eddbb0bea..5fa82929b 100644 --- a/fs/sysv/balloc.c +++ b/fs/sysv/balloc.c @@ -19,10 +19,6 @@ * This file contains code for allocating/freeing blocks. */ -#ifdef MODULE -#include <linux/module.h> -#endif - #include <linux/kernel.h> #include <linux/fs.h> #include <linux/sysv_fs.h> @@ -88,7 +84,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block) *flc_count = *sb->sv_sb_flc_count; /* = sb->sv_flc_size */ memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t)); mark_buffer_dirty(bh, 1); - bh->b_uptodate = 1; + mark_buffer_uptodate(bh, 1); brelse(bh); *sb->sv_sb_flc_count = 0; } else @@ -105,14 +101,14 @@ void sysv_free_block(struct super_block * sb, unsigned int block) memset(bh->b_data, 0, sb->sv_block_size); /* this implies ((struct ..._freelist_chunk *) bh->b_data)->flc_count = 0; */ mark_buffer_dirty(bh, 1); - bh->b_uptodate = 1; + mark_buffer_uptodate(bh, 1); brelse(bh); /* still *sb->sv_sb_flc_count = 0 */ } else { /* Throw away block's contents */ bh = sv_get_hash_table(sb, sb->s_dev, block); if (bh) - bh->b_dirt = 0; + mark_buffer_clean(bh); brelse(bh); } if (sb->sv_convert) @@ -212,7 +208,7 @@ int sysv_new_block(struct super_block * sb) } memset(bh->b_data, 0, sb->sv_block_size); mark_buffer_dirty(bh, 1); - bh->b_uptodate = 1; + mark_buffer_uptodate(bh, 1); brelse(bh); if (sb->sv_convert) *sb->sv_sb_total_free_blocks = diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index cfd85993e..52515b4f9 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c @@ -13,18 +13,16 @@ * SystemV/Coherent directory handling functions */ -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/segment.h> - #include <linux/errno.h> #include <linux/fs.h> #include <linux/sysv_fs.h> #include <linux/stat.h> +#include <linux/string.h> + +#include <asm/uaccess.h> -static int sysv_dir_read(struct inode * inode, struct file * filp, char * buf, int count) +static long sysv_dir_read(struct inode * inode, struct file * filp, + char * buf, unsigned long count) { return -EISDIR; } @@ -60,6 +58,8 @@ struct inode_operations sysv_dir_inode_operations = { sysv_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ NULL, /* bmap */ sysv_truncate, /* truncate */ NULL /* permission */ @@ -95,8 +95,10 @@ static int sysv_readdir(struct inode * inode, struct file * filp, memcpy(&sde, de, sizeof(struct sysv_dir_entry)); if (sde.inode > inode->i_sb->sv_ninodes) - printk("sysv_readdir: Bad inode number on dev 0x%04x, ino %ld, offset 0x%04lx: %d is out of range\n", - inode->i_dev, inode->i_ino, (off_t) filp->f_pos, sde.inode); + printk("sysv_readdir: Bad inode number on dev " + "%s, ino %ld, offset 0x%04lx: %d is out of range\n", + kdevname(inode->i_dev), + inode->i_ino, (off_t) filp->f_pos, sde.inode); i = strnlen(sde.name, SYSV_NAMELEN); if (filldir(dirent, sde.name, i, filp->f_pos, sde.inode) < 0) { diff --git a/fs/sysv/file.c b/fs/sysv/file.c index f098af6b6..6029051d8 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c @@ -13,12 +13,6 @@ * SystemV/Coherent regular file handling primitives */ -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/segment.h> - #include <linux/kernel.h> #include <linux/fs.h> #include <linux/sysv_fs.h> @@ -27,6 +21,9 @@ #include <linux/stat.h> #include <linux/string.h> #include <linux/locks.h> +#include <linux/pagemap.h> + +#include <asm/uaccess.h> #define NBUF 32 @@ -36,7 +33,7 @@ #include <linux/fs.h> #include <linux/sysv_fs.h> -static int sysv_file_write(struct inode *, struct file *, char *, int); +static long sysv_file_write(struct inode *, struct file *, const char *, unsigned long); /* * We have mostly NULL's here: the current defaults are ok for @@ -49,7 +46,7 @@ static struct file_operations sysv_file_operations = { NULL, /* readdir - bad */ NULL, /* select - default */ NULL, /* ioctl - default */ - generic_mmap, /* mmap */ + generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ NULL, /* release */ sysv_sync_file /* fsync */ @@ -68,12 +65,15 @@ struct inode_operations sysv_file_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + generic_readpage, /* readpage */ + NULL, /* writepage */ sysv_bmap, /* bmap */ sysv_truncate, /* truncate */ NULL /* permission */ }; -int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int count) +long sysv_file_read(struct inode * inode, struct file * filp, + char * buf, unsigned long count) { struct super_block * sb = inode->i_sb; int read,left,chars; @@ -115,9 +115,9 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou blocks = size - block; } - /* We do this in a two stage process. We first try and request + /* We do this in a two stage process. We first try to request as many blocks as we can, then we wait for the first one to - complete, and then we try and wrap up as many as are actually + complete, and then we try to wrap up as many as are actually done. This routine is rather generic, in that it can be used in a filesystem by substituting the appropriate function in for getblk. @@ -132,7 +132,7 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou while (blocks) { --blocks; *bhb = sysv_getblk(inode, block++, 0); - if (*bhb && !(*bhb)->b_uptodate) { + if (*bhb && !buffer_uptodate(*bhb)) { uptodate = 0; bhreq[bhrequest++] = *bhb; } @@ -155,7 +155,7 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou do { /* Finish off all I/O that has actually completed */ if (*bhe) { wait_on_buffer(*bhe); - if (!(*bhe)->b_uptodate) { /* read error? */ + if (!buffer_uptodate(*bhe)) { /* read error? */ brelse(*bhe); if (++bhe == &buflist[NBUF]) bhe = buflist; @@ -171,17 +171,17 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou left -= chars; read += chars; if (*bhe) { - memcpy_tofs(buf,offset+(*bhe)->b_data,chars); + copy_to_user(buf,offset+(*bhe)->b_data,chars); brelse(*bhe); buf += chars; } else { while (chars-- > 0) - put_fs_byte(0,buf++); + put_user(0,buf++); } offset = 0; if (++bhe == &buflist[NBUF]) bhe = buflist; - } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock)); + } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe))); } while (left > 0); /* Release the read-ahead blocks */ @@ -200,7 +200,8 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou return read; } -static int sysv_file_write(struct inode * inode, struct file * filp, char * buf, int count) +static long sysv_file_write(struct inode * inode, struct file * filp, + const char * buf, unsigned long count) { struct super_block * sb = inode->i_sb; off_t pos; @@ -238,27 +239,28 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf, c = sb->sv_block_size - (pos & sb->sv_block_size_1); if (c > count-written) c = count-written; - if (c != sb->sv_block_size && !bh->b_uptodate) { + if (c != sb->sv_block_size && !buffer_uptodate(bh)) { ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); - if (!bh->b_uptodate) { + if (!buffer_uptodate(bh)) { brelse(bh); if (!written) written = -EIO; break; } } - /* now either c==sb->sv_block_size or bh->b_uptodate */ + /* now either c==sb->sv_block_size or buffer_uptodate(bh) */ p = (pos & sb->sv_block_size_1) + bh->b_data; + copy_from_user(p, buf, c); + update_vm_cache(inode, pos, p, c); pos += c; if (pos > inode->i_size) { inode->i_size = pos; inode->i_dirt = 1; } written += c; - memcpy_fromfs(p,buf,c); buf += c; - bh->b_uptodate = 1; + mark_buffer_uptodate(bh, 1); mark_buffer_dirty(bh, 0); brelse(bh); } diff --git a/fs/sysv/fsync.c b/fs/sysv/fsync.c index af1218fca..df3b948df 100644 --- a/fs/sysv/fsync.c +++ b/fs/sysv/fsync.c @@ -14,10 +14,6 @@ * SystemV/Coherent fsync primitive */ -#ifdef MODULE -#include <linux/module.h> -#endif - #include <linux/errno.h> #include <linux/stat.h> @@ -49,11 +45,11 @@ static int sync_block (struct inode * inode, unsigned long * blockp, int convert brelse (bh); return 1; } - if (wait && bh->b_req && !bh->b_uptodate) { + if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { brelse(bh); return -1; } - if (wait || !bh->b_uptodate || !bh->b_dirt) { + if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { brelse(bh); return 0; } diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c index 98883c22c..85ba640d1 100644 --- a/fs/sysv/ialloc.c +++ b/fs/sysv/ialloc.c @@ -19,10 +19,6 @@ * This file contains code for allocating/freeing inodes. */ -#ifdef MODULE -#include <linux/module.h> -#endif - #include <linux/sched.h> #include <linux/kernel.h> #include <linux/fs.h> @@ -84,7 +80,8 @@ void sysv_free_inode(struct inode * inode) return; } if (!(bh = sv_bread(sb, inode->i_dev, sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits)))) { - printk("sysv_free_inode: unable to read inode block on device %d/%d\n",MAJOR(inode->i_dev),MINOR(inode->i_dev)); + printk("sysv_free_inode: unable to read inode block on device " + "%s\n", kdevname(inode->i_dev)); clear_inode(inode); return; } diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 4aa0932cb..4e14cb35e 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -20,13 +20,7 @@ * the superblock. */ -#ifdef MODULE #include <linux/module.h> -#include <linux/version.h> -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif #include <linux/sched.h> #include <linux/kernel.h> @@ -36,7 +30,7 @@ #include <linux/string.h> #include <linux/locks.h> -#include <asm/segment.h> +#include <asm/uaccess.h> void sysv_put_inode(struct inode *inode) { @@ -347,7 +341,7 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, { struct buffer_head *bh; const char *found; - int dev = sb->s_dev; + kdev_t dev = sb->s_dev; if (1024 != sizeof (struct xenix_super_block)) panic("Xenix FS: bad super-block size"); @@ -397,10 +391,11 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, brelse(bh); } } - sb->s_dev=0; + sb->s_dev = 0; unlock_super(sb); if (!silent) - printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device %d/%d\n",MAJOR(dev),MINOR(dev)); + printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device " + "%s\n", kdevname(dev)); failed: MOD_DEC_USE_COUNT; return NULL; @@ -477,7 +472,8 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, } sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone) << sb->sv_inodes_per_block_bits; if (!silent) - printk("VFS: Found a %s FS (block size = %d) on device %d/%d\n",found,sb->sv_block_size,MAJOR(dev),MINOR(dev)); + printk("VFS: Found a %s FS (block size = %d) on device %s\n", + found, sb->sv_block_size, kdevname(dev)); sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type; /* The buffer code now supports block size 512 as well as 1024. */ sb->s_blocksize = sb->sv_block_size; @@ -502,7 +498,7 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, void sysv_write_super (struct super_block *sb) { lock_super(sb); - if (sb->sv_bh1->b_dirt || sb->sv_bh2->b_dirt) { + if (buffer_dirty(sb->sv_bh1) || buffer_dirty(sb->sv_bh2)) { /* If we are going to write out the super block, then attach current time stamp. But if the filesystem was marked clean, keep it clean. */ @@ -540,15 +536,16 @@ void sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { struct statfs tmp; - tmp.f_type = sb->s_magic; - tmp.f_bsize = sb->sv_block_size; - tmp.f_blocks = sb->sv_ndatazones; - tmp.f_bfree = sysv_count_free_blocks(sb); - tmp.f_bavail = tmp.f_bfree; - tmp.f_files = sb->sv_ninodes; - tmp.f_ffree = sysv_count_free_inodes(sb); + tmp.f_type = sb->s_magic; /* type of filesystem */ + tmp.f_bsize = sb->sv_block_size; /* block size */ + tmp.f_blocks = sb->sv_ndatazones; /* total data blocks in file system */ + tmp.f_bfree = sysv_count_free_blocks(sb); /* free blocks in fs */ + tmp.f_bavail = tmp.f_bfree; /* free blocks available to non-superuser */ + tmp.f_files = sb->sv_ninodes; /* total file nodes in file system */ + tmp.f_ffree = sysv_count_free_inodes(sb); /* free file nodes in fs */ tmp.f_namelen = SYSV_NAMELEN; - memcpy_tofs(buf, &tmp, bufsiz); + /* Don't know what value to put in tmp.f_fsid */ /* file system id */ + copy_to_user(buf, &tmp, bufsiz); } @@ -682,10 +679,10 @@ static struct buffer_head * block_getblk(struct inode * inode, if (!bh) return NULL; - if (!bh->b_uptodate) { + if (!buffer_uptodate(bh)) { ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); - if (!bh->b_uptodate) { + if (!buffer_uptodate(bh)) { brelse(bh); return NULL; } @@ -764,11 +761,11 @@ struct buffer_head * sysv_file_bread(struct inode * inode, int block, int create struct buffer_head * bh; bh = sysv_getblk(inode,block,create); - if (!bh || bh->b_uptodate) + if (!bh || buffer_uptodate(bh)) return bh; ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); - if (bh->b_uptodate) + if (buffer_uptodate(bh)) return bh; brelse(bh); return NULL; @@ -811,14 +808,16 @@ void sysv_read_inode(struct inode * inode) inode->i_op = NULL; inode->i_mode = 0; if (!ino || ino > sb->sv_ninodes) { - printk("Bad inode number on dev 0x%04x: %d is out of range\n", - inode->i_dev, ino); + printk("Bad inode number on dev %s" + ": %d is out of range\n", + kdevname(inode->i_dev), ino); return; } block = sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits); if (!(bh = sv_bread(sb,inode->i_dev,block))) { - printk("Major problem: unable to read inode from dev 0x%04x\n", - inode->i_dev); + printk("Major problem: unable to read inode from dev " + "%s\n", + kdevname(inode->i_dev)); return; } raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1); @@ -843,7 +842,7 @@ void sysv_read_inode(struct inode * inode) } inode->i_blocks = inode->i_blksize = 0; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - inode->i_rdev = raw_inode->i_a.i_rdev; + inode->i_rdev = to_kdev_t(raw_inode->i_a.i_rdev); else if (sb->sv_convert) for (block = 0; block < 10+1+1+1; block++) @@ -896,8 +895,9 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) ino = inode->i_ino; if (!ino || ino > sb->sv_ninodes) { - printk("Bad inode number on dev 0x%04x: %d is out of range\n", - inode->i_dev, ino); + printk("Bad inode number on dev %s" + ": %d is out of range\n", + kdevname(inode->i_dev), ino); inode->i_dirt = 0; return 0; } @@ -927,7 +927,7 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) raw_inode->i_ctime = inode->i_ctime; } if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_a.i_rdev = inode->i_rdev; /* write 2 or 3 bytes ?? */ + raw_inode->i_a.i_rdev = kdev_t_to_nr(inode->i_rdev); /* write 2 or 3 bytes ?? */ else if (sb->sv_convert) for (block = 0; block < 10+1+1+1; block++) @@ -953,13 +953,14 @@ int sysv_sync_inode(struct inode * inode) struct buffer_head *bh; bh = sysv_update_inode(inode); - if (bh && bh->b_dirt) { + if (bh && buffer_dirty(bh)) { ll_rw_block(WRITE, 1, &bh); wait_on_buffer(bh); - if (bh->b_req && !bh->b_uptodate) + if (buffer_req(bh) && !buffer_uptodate(bh)) { - printk ("IO error syncing sysv inode [%04x:%08lx]\n", - inode->i_dev, inode->i_ino); + printk ("IO error syncing sysv inode [" + "%s:%08lx]\n", + kdevname(inode->i_dev), inode->i_ino); err = -1; } } @@ -969,26 +970,34 @@ int sysv_sync_inode(struct inode * inode) return err; } -#ifdef MODULE - /* Every kernel module contains stuff like this. */ -char kernel_version[] = UTS_RELEASE; - static struct file_system_type sysv_fs_type[3] = { {sysv_read_super, "xenix", 1, NULL}, {sysv_read_super, "sysv", 1, NULL}, {sysv_read_super, "coherent", 1, NULL} }; -int init_module(void) +int init_sysv_fs(void) { int i; + int ouch; - for (i = 0; i < 3; i++) - register_filesystem(&sysv_fs_type[i]); + for (i = 0; i < 3; i++) { + if ((ouch = register_filesystem(&sysv_fs_type[i])) != 0) + return ouch; + } + return ouch; +} - return 0; +#ifdef MODULE +int init_module(void) +{ + int status; + + if ((status = init_sysv_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) @@ -996,6 +1005,7 @@ void cleanup_module(void) int i; for (i = 0; i < 3; i++) + /* No error message if this breaks... that's OK... */ unregister_filesystem(&sysv_fs_type[i]); } diff --git a/fs/sysv/mmap.c b/fs/sysv/mmap.c deleted file mode 100644 index 3ec3867a9..000000000 --- a/fs/sysv/mmap.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * linux/fs/sysv/mmap.c - * - * mm/memory.c, mm/mmap.c - * Copyright (C) 1991, 1992, 1993 Linus Torvalds - * - * nfs/mmap.c - * Copyright (C) 1993 Jon Tombs - * - * fs/msdos/mmap.c - * Copyright (C) 1994 Jacques Gelinas - * - * fs/sysv/mmap.c - * Copyright (C) 1994 Bruno Haible - * - * SystemV/Coherent mmap handling - */ - -#include <asm/segment.h> - -#include <linux/fs.h> -#include <linux/sysv_fs.h> -#include <linux/mm.h> -#include <linux/string.h> -#include <linux/stat.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/malloc.h> - -/* - * Fill in the supplied page for mmap - */ -static unsigned long sysv_file_mmap_nopage (struct vm_area_struct * area, - unsigned long address, unsigned long page, int no_share) -{ - int remaining, count, old_fs; - struct file filp; - - address &= PAGE_MASK; - /* prepare a file pointer */ - filp.f_pos = address - area->vm_start + area->vm_offset; - filp.f_reada = 0; - remaining = area->vm_end - address; - if (remaining > PAGE_SIZE) - remaining = PAGE_SIZE; - /* read from the file. page is in kernel space, not user space. */ - old_fs = get_fs(); set_fs(get_ds()); - count = sysv_file_read (area->vm_inode, &filp, (char *)page, remaining); - set_fs(old_fs); - if (count < 0) - count = 0; /* do nothing on I/O error ?? */ - else - remaining -= count; - if (remaining > 0) - memset((char *)page + count, 0, remaining); - return page; -} - -static struct vm_operations_struct sysv_file_mmap = { - NULL, /* open */ - NULL, /* close */ - sysv_file_mmap_nopage, /* nopage */ - NULL, /* wppage */ - NULL, /* share */ - NULL, /* unmap */ -}; - -int sysv_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) -{ - if (vma->vm_page_prot & PAGE_RW) /* only PAGE_COW or read-only supported right now */ - return -EINVAL; - if (vma->vm_offset & (inode->i_sb->s_blocksize - 1)) - return -EINVAL; - if (!inode->i_sb || !S_ISREG(inode->i_mode)) - return -EACCES; - if (!IS_RDONLY(inode)) { - inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - } - - vma->vm_inode = inode; - inode->i_count++; - vma->vm_ops = &sysv_file_mmap; - return 0; -} diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index 8d245d38e..735d158d4 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -11,10 +11,6 @@ * Copyright (C) 1993 Bruno Haible */ -#ifdef MODULE -#include <linux/module.h> -#endif - #include <linux/sched.h> #include <linux/kernel.h> #include <linux/fs.h> @@ -279,7 +275,7 @@ int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rde else if (S_ISFIFO(inode->i_mode)) init_fifo(inode); if (S_ISBLK(mode) || S_ISCHR(mode)) - inode->i_rdev = rdev; + inode->i_rdev = to_kdev_t(rdev); inode->i_dirt = 1; error = sysv_add_entry(dir, name, len, &bh, &de); if (error) { @@ -418,7 +414,8 @@ static int empty_dir(struct inode * inode) return 1; bad_dir: brelse(bh); - printk("Bad directory on device %04x\n",inode->i_dev); + printk("Bad directory on device %s\n", + kdevname(inode->i_dev)); return 1; } @@ -512,8 +509,9 @@ repeat: goto end_unlink; } if (!inode->i_nlink) { - printk("Deleting nonexistent file (%04x:%lu), %d\n", - inode->i_dev,inode->i_ino,inode->i_nlink); + printk("Deleting nonexistent file (%s:%lu), %d\n", + kdevname(inode->i_dev), + inode->i_ino, inode->i_nlink); inode->i_nlink=1; } de->inode = 0; @@ -670,7 +668,7 @@ static int subdir(struct inode * new_inode, struct inode * old_inode) * higher-level routines. */ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old_len, - struct inode * new_dir, const char * new_name, int new_len) + struct inode * new_dir, const char * new_name, int new_len, int must_be_dir) { struct inode * old_inode, * new_inode; struct buffer_head * old_bh, * new_bh, * dir_bh; @@ -696,6 +694,8 @@ start_up: old_inode = __iget(old_dir->i_sb, old_de->inode, 0); /* don't cross mnt-points */ if (!old_inode) goto end_rename; + if (must_be_dir && !S_ISDIR(old_inode->i_mode)) + goto end_rename; retval = -EPERM; if ((old_dir->i_mode & S_ISVTX) && current->fsuid != old_inode->i_uid && @@ -810,7 +810,8 @@ end_rename: * as they are on different partitions. */ int sysv_rename(struct inode * old_dir, const char * old_name, int old_len, - struct inode * new_dir, const char * new_name, int new_len) + struct inode * new_dir, const char * new_name, int new_len, + int must_be_dir) { static struct wait_queue * wait = NULL; static int lock = 0; @@ -820,7 +821,7 @@ int sysv_rename(struct inode * old_dir, const char * old_name, int old_len, sleep_on(&wait); lock = 1; result = do_sysv_rename(old_dir, old_name, old_len, - new_dir, new_name, new_len); + new_dir, new_name, new_len, must_be_dir); lock = 0; wake_up(&wait); return result; diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c index c4e7d5bf5..9a33d9fab 100644 --- a/fs/sysv/symlink.c +++ b/fs/sysv/symlink.c @@ -13,17 +13,13 @@ * SystemV/Coherent symlink handling code */ -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/segment.h> - #include <linux/errno.h> #include <linux/sched.h> #include <linux/sysv_fs.h> #include <linux/stat.h> +#include <asm/uaccess.h> + static int sysv_readlink(struct inode *, char *, int); static int sysv_follow_link(struct inode *, struct inode *, int, int, struct inode **); @@ -43,6 +39,8 @@ struct inode_operations sysv_symlink_inode_operations = { NULL, /* rename */ sysv_readlink, /* readlink */ sysv_follow_link, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ NULL /* permission */ @@ -107,7 +105,7 @@ static int sysv_readlink(struct inode * inode, char * buffer, int buflen) i = 0; while (i<buflen && (c = bh_data[i])) { i++; - put_fs_byte(c,buffer++); + put_user(c,buffer++); } brelse(bh); return i; diff --git a/fs/sysv/truncate.c b/fs/sysv/truncate.c index 6de370ebd..0eeb10d30 100644 --- a/fs/sysv/truncate.c +++ b/fs/sysv/truncate.c @@ -11,10 +11,6 @@ * Copyright (C) 1993 Bruno Haible */ -#ifdef MODULE -#include <linux/module.h> -#endif - #include <linux/sched.h> #include <linux/fs.h> #include <linux/sysv_fs.h> @@ -175,13 +171,16 @@ static int trunc_dindirect(struct inode * inode, unsigned long offset, unsigned else i = (inode->i_size - offset + sb->sv_ind_per_block_block_size_1) >> sb->sv_ind_per_block_block_size_bits; for (; i < sb->sv_ind_per_block; i++) { + unsigned char dirty = 0; ind = ((sysv_zone_t *) indbh->b_data) + i; block = tmp = *ind; if (sb->sv_convert) block = from_coh_ulong(block); if (!block) continue; - retry |= trunc_indirect(inode,offset+(i<<sb->sv_ind_per_block_bits),ind,sb->sv_convert,&indbh->b_dirt); + retry |= trunc_indirect(inode,offset+(i<<sb->sv_ind_per_block_bits),ind,sb->sv_convert,&dirty); + if (dirty) + mark_buffer_dirty(indbh, 1); } for (i = 0; i < sb->sv_ind_per_block; i++) if (((sysv_zone_t *) indbh->b_data)[i]) @@ -229,13 +228,16 @@ static int trunc_tindirect(struct inode * inode, unsigned long offset, unsigned else i = (inode->i_size - offset + sb->sv_ind_per_block_2_block_size_1) >> sb->sv_ind_per_block_2_block_size_bits; for (; i < sb->sv_ind_per_block; i++) { + unsigned char dirty = 0; ind = ((sysv_zone_t *) indbh->b_data) + i; block = tmp = *ind; if (sb->sv_convert) block = from_coh_ulong(block); if (!block) continue; - retry |= trunc_dindirect(inode,offset+(i<<sb->sv_ind_per_block_2_bits),ind,sb->sv_convert,&indbh->b_dirt); + retry |= trunc_dindirect(inode,offset+(i<<sb->sv_ind_per_block_2_bits),ind,sb->sv_convert,&dirty); + if (dirty) + mark_buffer_dirty(indbh, 1); } for (i = 0; i < sb->sv_ind_per_block; i++) if (((sysv_zone_t *) indbh->b_data)[i]) |