diff options
Diffstat (limited to 'fs/ext2')
-rw-r--r-- | fs/ext2/dir.c | 4 | ||||
-rw-r--r-- | fs/ext2/file.c | 9 | ||||
-rw-r--r-- | fs/ext2/fsync.c | 39 | ||||
-rw-r--r-- | fs/ext2/inode.c | 86 | ||||
-rw-r--r-- | fs/ext2/ioctl.c | 25 | ||||
-rw-r--r-- | fs/ext2/super.c | 69 | ||||
-rw-r--r-- | fs/ext2/symlink.c | 12 |
7 files changed, 102 insertions, 142 deletions
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 7de729e4b..fce6fc4c8 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -39,7 +39,7 @@ static struct file_operations ext2_dir_operations = { ext2_dir_read, /* read */ NULL, /* write - bad */ ext2_readdir, /* readdir */ - NULL, /* select - default */ + NULL, /* poll - default */ ext2_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ @@ -211,7 +211,7 @@ revalidate: offset = 0; brelse (bh); } - if (!IS_RDONLY(inode)) { + if (DO_UPDATE_ATIME(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; } diff --git a/fs/ext2/file.c b/fs/ext2/file.c index c336a5ba6..274dc31fd 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -38,7 +38,7 @@ static long long ext2_file_lseek(struct inode *, struct file *, long long, int); static long ext2_file_write (struct inode *, struct file *, const char *, unsigned long); -static void ext2_release_file (struct inode *, struct file *); +static int ext2_release_file (struct inode *, struct file *); /* * We have mostly NULL's here: the current defaults are ok for @@ -49,7 +49,7 @@ static struct file_operations ext2_file_operations = { generic_file_read, /* read */ ext2_file_write, /* write */ NULL, /* readdir - bad */ - NULL, /* select - default */ + NULL, /* poll - default */ ext2_ioctl, /* ioctl */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ @@ -120,7 +120,7 @@ static inline void remove_suid(struct inode *inode) /* was any of the uid bits set? */ mode &= inode->i_mode; - if (mode && suser()) { + if (mode && !suser()) { inode->i_mode &= ~mode; inode->i_dirt = 1; } @@ -260,8 +260,9 @@ static long ext2_file_write (struct inode * inode, struct file * filp, * from ext2_open: open gets called at every open, but release * gets called only when /all/ the files are closed. */ -static void ext2_release_file (struct inode * inode, struct file * filp) +static int ext2_release_file (struct inode * inode, struct file * filp) { if (filp->f_mode & 2) ext2_discard_prealloc (inode); + return 0; } diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c index 1d608d07d..9993af1a6 100644 --- a/fs/ext2/fsync.c +++ b/fs/ext2/fsync.c @@ -13,10 +13,15 @@ * * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 + * + * Removed unnecessary code duplication for little endian machines + * and excessive __inline__s. + * Andi Kleen, 1997 */ #include <asm/uaccess.h> #include <asm/system.h> +#include <asm/byteorder.h> #include <linux/errno.h> #include <linux/fs.h> @@ -30,7 +35,7 @@ #define blocksize (EXT2_BLOCK_SIZE(inode->i_sb)) #define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb)) -static __inline__ int sync_block (struct inode * inode, u32 * block, int wait) +static int sync_block (struct inode * inode, u32 * block, int wait) { struct buffer_head * bh; int tmp; @@ -58,7 +63,8 @@ static __inline__ int sync_block (struct inode * inode, u32 * block, int wait) return 0; } -static __inline__ int sync_block_swab32 (struct inode * inode, u32 * block, int wait) +#ifndef __LITTLE_ENDIAN +static int sync_block_swab32 (struct inode * inode, u32 * block, int wait) { struct buffer_head * bh; int tmp; @@ -85,8 +91,12 @@ static __inline__ int sync_block_swab32 (struct inode * inode, u32 * block, int bh->b_count--; return 0; } +#else +#define sync_block_swab32 sync_block +#endif + -static __inline__ int sync_iblock (struct inode * inode, u32 * iblock, +static int sync_iblock (struct inode * inode, u32 * iblock, struct buffer_head ** bh, int wait) { int rc, tmp; @@ -109,7 +119,8 @@ static __inline__ int sync_iblock (struct inode * inode, u32 * iblock, return 0; } -static __inline__ int sync_iblock_swab32 (struct inode * inode, u32 * iblock, +#ifndef __LITTLE_ENDIAN +static int sync_iblock_swab32 (struct inode * inode, u32 * iblock, struct buffer_head ** bh, int wait) { int rc, tmp; @@ -131,9 +142,11 @@ static __inline__ int sync_iblock_swab32 (struct inode * inode, u32 * iblock, return -1; return 0; } +#else +#define sync_iblock_swab32 sync_iblock +#endif - -static __inline__ int sync_direct (struct inode * inode, int wait) +static int sync_direct (struct inode * inode, int wait) { int i; int rc, err = 0; @@ -148,7 +161,7 @@ static __inline__ int sync_direct (struct inode * inode, int wait) return err; } -static __inline__ int sync_indirect (struct inode * inode, u32 * iblock, int wait) +static int sync_indirect (struct inode * inode, u32 * iblock, int wait) { int i; struct buffer_head * ind_bh; @@ -171,6 +184,7 @@ static __inline__ int sync_indirect (struct inode * inode, u32 * iblock, int wai return err; } +#ifndef __LITTLE_ENDIAN static __inline__ int sync_indirect_swab32 (struct inode * inode, u32 * iblock, int wait) { int i; @@ -193,8 +207,11 @@ static __inline__ int sync_indirect_swab32 (struct inode * inode, u32 * iblock, brelse (ind_bh); return err; } +#else +#define sync_indirect_swab32 sync_indirect +#endif -static __inline__ int sync_dindirect (struct inode * inode, u32 * diblock, int wait) +static int sync_dindirect (struct inode * inode, u32 * diblock, int wait) { int i; struct buffer_head * dind_bh; @@ -217,6 +234,7 @@ static __inline__ int sync_dindirect (struct inode * inode, u32 * diblock, int w return err; } +#ifndef __LITTLE_ENDIAN static __inline__ int sync_dindirect_swab32 (struct inode * inode, u32 * diblock, int wait) { int i; @@ -239,8 +257,11 @@ static __inline__ int sync_dindirect_swab32 (struct inode * inode, u32 * diblock brelse (dind_bh); return err; } +#else +#define sync_dindirect_swab32 sync_dindirect +#endif -static __inline__ int sync_tindirect (struct inode * inode, u32 * tiblock, int wait) +static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait) { int i; struct buffer_head * tind_bh; diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index eddcc5ab5..5a876261e 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -329,42 +329,6 @@ repeat: return result; } -static int block_getcluster (struct inode * inode, struct buffer_head * bh, - int nr, - int blocksize) -{ - u32 * p; - int firstblock = 0; - int result = 0; - int i; - - /* Check to see if clustering possible here. */ - - if(!bh) return 0; - - if((nr & ((PAGE_SIZE >> EXT2_BLOCK_SIZE_BITS(inode->i_sb)) - 1)) != 0) - goto out; - if(nr + 3 > EXT2_ADDR_PER_BLOCK(inode->i_sb)) goto out; - - for(i=0; i< (PAGE_SIZE >> EXT2_BLOCK_SIZE_BITS(inode->i_sb)); i++) { - p = (u32 *) bh->b_data + nr + i; - - /* All blocks in cluster must already be allocated */ - if(le32_to_cpu(*p) == 0) goto out; - - /* See if aligned correctly */ - if(i==0) firstblock = le32_to_cpu(*p); - else if(le32_to_cpu(*p) != firstblock + i) goto out; - } - - p = (u32 *) bh->b_data + nr; - result = generate_cluster_swab32(bh->b_dev, (int *) p, blocksize); - - out: - brelse(bh); - return result; -} - struct buffer_head * ext2_getblk (struct inode * inode, long block, int create, int * err) { @@ -427,56 +391,6 @@ struct buffer_head * ext2_getblk (struct inode * inode, long block, inode->i_sb->s_blocksize, b, err); } -int ext2_getcluster (struct inode * inode, long block) -{ - struct buffer_head * bh; - int err, create; - unsigned long b; - unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); - int addr_per_block_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); - - create = 0; - err = -EIO; - if (block < 0) { - ext2_warning (inode->i_sb, "ext2_getblk", "block < 0"); - return 0; - } - if (block > EXT2_NDIR_BLOCKS + addr_per_block + - (1 << (addr_per_block_bits * 2)) + - ((1 << (addr_per_block_bits * 2)) << addr_per_block_bits)) { - ext2_warning (inode->i_sb, "ext2_getblk", "block > big"); - return 0; - } - - err = -ENOSPC; - b = block; - if (block < EXT2_NDIR_BLOCKS) return 0; - - block -= EXT2_NDIR_BLOCKS; - - if (block < addr_per_block) { - bh = inode_getblk (inode, EXT2_IND_BLOCK, create, b, &err); - return block_getcluster (inode, bh, block, - inode->i_sb->s_blocksize); - } - block -= addr_per_block; - if (block < (1 << (addr_per_block_bits * 2))) { - bh = inode_getblk (inode, EXT2_DIND_BLOCK, create, b, &err); - bh = block_getblk (inode, bh, block >> addr_per_block_bits, - create, inode->i_sb->s_blocksize, b, &err); - return block_getcluster (inode, bh, block & (addr_per_block - 1), - inode->i_sb->s_blocksize); - } - block -= (1 << (addr_per_block_bits * 2)); - bh = inode_getblk (inode, EXT2_TIND_BLOCK, create, b, &err); - bh = block_getblk (inode, bh, block >> (addr_per_block_bits * 2), - create, inode->i_sb->s_blocksize, b, &err); - bh = block_getblk (inode, bh, (block >> addr_per_block_bits) & (addr_per_block - 1), - create, inode->i_sb->s_blocksize, b, &err); - return block_getcluster (inode, bh, block & (addr_per_block - 1), - inode->i_sb->s_blocksize); -} - struct buffer_head * ext2_bread (struct inode * inode, int block, int create, int *err) { diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index 8235a6301..0892ce79f 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -19,23 +19,16 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { - int err; unsigned long flags; ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); switch (cmd) { case EXT2_IOC_GETFLAGS: - err = verify_area(VERIFY_WRITE, (int *) arg, sizeof(int)); - if (err) - return err; - put_user(inode->u.ext2_i.i_flags, (int *) arg); - return 0; + return put_user(inode->u.ext2_i.i_flags, (int *) arg); case EXT2_IOC_SETFLAGS: - err = verify_area(VERIFY_READ, (int *) arg, sizeof(int)); - if (err) - return err; - get_user(flags, (int *) arg); + if (get_user(flags, (int *) arg)) + return -EFAULT; /* * The IMMUTABLE and APPEND_ONLY flags can only be changed by * the super user when the security level is zero. @@ -64,20 +57,14 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, inode->i_dirt = 1; return 0; case EXT2_IOC_GETVERSION: - err = verify_area(VERIFY_WRITE, (int *) arg, sizeof(int)); - if (err) - return err; - put_user(inode->u.ext2_i.i_version, (int *) arg); - return 0; + return put_user(inode->u.ext2_i.i_version, (int *) arg); case EXT2_IOC_SETVERSION: if ((current->fsuid != inode->i_uid) && !fsuser()) return -EPERM; if (IS_RDONLY(inode)) return -EROFS; - err = verify_area(VERIFY_READ, (int *) arg, sizeof(int)); - if (err) - return err; - get_user(inode->u.ext2_i.i_version, (int *) arg); + if (get_user(inode->u.ext2_i.i_version, (int *) arg)) + return -EFAULT; inode->i_ctime = CURRENT_TIME; inode->i_dirt = 1; return 0; diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 6bcdb5e20..26e18852e 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -32,6 +32,8 @@ #include <linux/stat.h> #include <linux/string.h> #include <linux/locks.h> +#include <linux/blkdev.h> +#include <linux/init.h> static char error_buf[1024]; @@ -129,7 +131,7 @@ void ext2_put_super (struct super_block * sb) return; } -static struct super_operations ext2_sops = { +static struct super_operations ext2_sops = { ext2_read_inode, NULL, ext2_write_inode, @@ -377,10 +379,26 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, unsigned short resuid = EXT2_DEF_RESUID; unsigned short resgid = EXT2_DEF_RESGID; unsigned long logic_sb_block = 1; + unsigned long offset = 0; kdev_t dev = sb->s_dev; + int blocksize = BLOCK_SIZE; + int hblock; int db_count; int i, j; + /* + * See what the current blocksize for the device is, and + * use that as the blocksize. Otherwise (or if the blocksize + * is smaller than the default) use the default. + * This is important for devices that have a hardware + * sectorsize that is larger than the default. + */ + blocksize = get_hardblocksize(dev); + if( blocksize == 0 || blocksize < BLOCK_SIZE ) + { + blocksize = BLOCK_SIZE; + } + sb->u.ext2_sb.s_mount_opt = 0; set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL); if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, @@ -391,8 +409,19 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, MOD_INC_USE_COUNT; lock_super (sb); - set_blocksize (dev, BLOCK_SIZE); - if (!(bh = bread (dev, sb_block, BLOCK_SIZE))) { + set_blocksize (dev, blocksize); + + /* + * If the superblock doesn't start on a sector boundary, + * calculate the offset. FIXME(eric) this doesn't make sense + * that we would have to do this. + */ + if (blocksize != BLOCK_SIZE) { + logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize; + offset = (sb_block*BLOCK_SIZE) % blocksize; + } + + if (!(bh = bread (dev, logic_sb_block, blocksize))) { sb->s_dev = 0; unlock_super (sb); printk ("EXT2-fs: unable to read superblock\n"); @@ -403,7 +432,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, * Note: s_es must be initialized s_es as soon as possible because * some ext2 macro-instructions depend on its value */ - es = (struct ext2_super_block *) bh->b_data; + es = (struct ext2_super_block *) (((char *)bh->b_data) + offset); sb->u.ext2_sb.s_es = es; sb->s_magic = le16_to_cpu(es->s_magic); if (sb->s_magic != EXT2_SUPER_MAGIC) { @@ -421,24 +450,34 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) { if (le32_to_cpu(es->s_feature_incompat) & ~EXT2_FEATURE_INCOMPAT_SUPP) { printk("EXT2-fs: %s: couldn't mount because of " - "unsupported optional features.\n", + "unsupported optional features.\n", kdevname(dev)); goto failed_mount; } if (!(sb->s_flags & MS_RDONLY) && (le32_to_cpu(es->s_feature_ro_compat) & ~EXT2_FEATURE_RO_COMPAT_SUPP)) { printk("EXT2-fs: %s: couldn't mount RDWR because of " - "unsupported optional features.\n", + "unsupported optional features.\n", kdevname(dev)); goto failed_mount; } } sb->s_blocksize_bits = le32_to_cpu(sb->u.ext2_sb.s_es->s_log_block_size) + 10; sb->s_blocksize = 1 << sb->s_blocksize_bits; - if (sb->s_blocksize != BLOCK_SIZE && - (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 || + if (sb->s_blocksize != BLOCK_SIZE && + (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 || sb->s_blocksize == 4096)) { - unsigned long offset; + /* + * Make sure the blocksize for the filesystem is larger + * than the hardware sectorsize for the machine. + */ + hblock = get_hardblocksize(dev); + if( (hblock != 0) + && (sb->s_blocksize < hblock) ) + { + printk("EXT2-fs: blocksize too small for device.\n"); + goto failed_mount; + } brelse (bh); set_blocksize (dev, sb->s_blocksize); @@ -675,7 +714,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data) else { /* * Mounting a RDONLY partition read-write, so reread and - * store the current valid flag. (It may have been changed + * store the current valid flag. (It may have been changed * by e2fsck since we originally mounted the partition.) */ sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state); @@ -689,19 +728,17 @@ static struct file_system_type ext2_fs_type = { ext2_read_super, "ext2", 1, NULL }; -int init_ext2_fs(void) +__initfunc(int init_ext2_fs(void)) { return register_filesystem(&ext2_fs_type); } #ifdef MODULE +EXPORT_NO_SYMBOLS; + int init_module(void) { - int status; - - if ((status = init_ext2_fs()) == 0) - register_symtab(0); - return status; + return init_ext2_fs(); } void cleanup_module(void) diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index 461e038c2..31f8276b0 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -87,7 +87,7 @@ static int ext2_follow_link(struct inode * dir, struct inode * inode, link = bh->b_data; } else link = (char *) inode->u.ext2_i.i_data; - if (!IS_RDONLY(inode)) { + if (DO_UPDATE_ATIME(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; } @@ -105,7 +105,6 @@ static int ext2_readlink (struct inode * inode, char * buffer, int buflen) struct buffer_head * bh = NULL; char * link; int i, err; - char c; if (!S_ISLNK(inode->i_mode)) { iput (inode); @@ -123,12 +122,13 @@ static int ext2_readlink (struct inode * inode, char * buffer, int buflen) } else link = (char *) inode->u.ext2_i.i_data; + i = 0; - while (i < buflen && (c = link[i])) { + while (i < buflen && link[i]) i++; - put_user (c, buffer++); - } - if (!IS_RDONLY(inode)) { + if (copy_to_user(buffer, link, i)) + i = -EFAULT; + if (DO_UPDATE_ATIME(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; } |