lkml.org 
[lkml]   [1999]   [Aug]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[RFC][PATCH] - lseek()
    I'm merging default_llseek() and ext2_file_lseek(), because everything
    that's current done by ext2_file_lseek() is {required,superflous} for
    all filesystems, and thus belongs into VFS.
    Currently,

    default_llseek():
    * allows 32-bit overflows
    * allows file pointers larger than supported by the filesystem.
    * prevents negativ file pointers

    ext2_file_lseek() is the exact opposite:
    * prevents 32-bit overflows.
    * prevents files offsets larger than supported by the fs.
    * allows negativ values on 64-bit platforms.
    * doesn't allow negativ values on 32-bit platform.

    What's by other OS'es, what's required by SUS/POSIX?

    --
    Manfred
    PS: Here is my current (alpha) patch:
    >>>>>>>>>>>>>>>>>>
    // Kernel Version:
    // VERSION = 2
    // PATCHLEVEL = 3
    // SUBLEVEL = 14
    // EXTRAVERSION =
    diff -r -u -P -x CVS -x *,v 2.3/fs/ext2/file.c build-2.3/fs/ext2/file.c
    --- 2.3/fs/ext2/file.c Thu Jul 1 14:11:44 1999
    +++ build-2.3/fs/ext2/file.c Fri Aug 20 20:53:13 1999
    @@ -37,58 +37,9 @@
    #define MIN(a,b) (((a)<(b))?(a):(b))
    #define MAX(a,b) (((a)>(b))?(a):(b))

    -static long long ext2_file_lseek(struct file *, long long, int);
    #if BITS_PER_LONG < 64
    static int ext2_open_file (struct inode *, struct file *);
    -
    -#else
    -
    -#define
    EXT2_MAX_SIZE(bits) \
    - (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2))
    + \
    - (1LL << (bits - 2)) * (1LL << (bits - 2))
    + \
    - (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits -
    2))) * \
    - (1LL << bits)) - 1)
    -
    -static long long ext2_max_sizes[] = {
    -0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    -EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12),
    EXT2_MAX_SIZE(13)
    -};
    -
    -#endif
    -
    -
    -/*
    - * Make sure the offset never goes beyond the 32-bit mark..
    - */
    -static long long ext2_file_lseek(
    - struct file *file,
    - long long offset,
    - int origin)
    -{
    - struct inode *inode = file->f_dentry->d_inode;
    -
    - switch (origin) {
    - case 2:
    - offset += inode->i_size;
    - break;
    - case 1:
    - offset += file->f_pos;
    - }
    - if (((unsigned long long) offset >> 32) != 0) {
    -#if BITS_PER_LONG < 64
    - return -EINVAL;
    -#else
    - if (offset >
    ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)])
    - return -EINVAL;
    #endif
    - }
    - if (offset != file->f_pos) {
    - file->f_pos = offset;
    - file->f_reada = 0;
    - file->f_version = ++event;
    - }
    - return offset;
    -}

    static inline void remove_suid(struct inode *inode)
    {
    @@ -154,7 +105,7 @@
    * the ext2 filesystem.
    */
    static struct file_operations ext2_file_operations = {
    - ext2_file_lseek, /* lseek */
    + NULL, /* lseek */
    generic_file_read, /* read */
    ext2_file_write, /* write */
    NULL, /* readdir - bad */
    diff -r -u -P -x CVS -x *,v 2.3/fs/ext2/super.c
    build-2.3/fs/ext2/super.c
    --- 2.3/fs/ext2/super.c Tue Jun 15 20:15:05 1999
    +++ build-2.3/fs/ext2/super.c Fri Aug 20 20:52:10 1999
    @@ -376,6 +376,18 @@

    #define log2(n) ffz(~(n))

    +#define
    EXT2_MAX_SIZE(bits) \
    + (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2))
    + \
    + (1LL << (bits - 2)) * (1LL << (bits - 2))
    + \
    + (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits -
    2))) * \
    + (1LL << bits)) - 1)
    +
    +static long long ext2_max_sizes[] = {
    +0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    +EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12),
    EXT2_MAX_SIZE(13)
    +};
    +
    +
    struct super_block * ext2_read_super (struct super_block * sb, void *
    data,
    int silent)
    {
    @@ -470,6 +482,7 @@
    }
    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;
    + sb->s_maxfilesize = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)];
    if (sb->s_blocksize != BLOCK_SIZE &&
    (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||
    sb->s_blocksize == 4096)) {
    diff -r -u -P -x CVS -x *,v 2.3/fs/read_write.c
    build-2.3/fs/read_write.c
    --- 2.3/fs/read_write.c Thu Jul 1 14:11:46 1999
    +++ build-2.3/fs/read_write.c Fri Aug 20 21:53:29 1999
    @@ -16,6 +16,7 @@
    static loff_t default_llseek(struct file *file, loff_t offset, int
    origin)
    {
    long long retval;
    + long long max;

    switch (origin) {
    case 2:
    @@ -24,8 +25,18 @@
    case 1:
    offset += file->f_pos;
    }
    + max = ((long long)(~0ULL>>1));
    + if(S_ISREG(file->f_dentry->d_inode->i_mode) &&
    file->f_dentry->d_inode->i_sb)
    + {
    + if(file->f_dentry->d_inode->i_sb->s_maxfilesize!=0)
    + max =
    file->f_dentry->d_inode->i_sb->s_maxfilesize;
    + }
    +#if BITS_PER_LONG < 64
    + if(max > INT_MAX)
    + max = INT_MAX;
    +#endif
    retval = -EINVAL;
    - if (offset >= 0) {
    + if (offset >= 0 && offset <= max) {
    if (offset != file->f_pos) {
    file->f_pos = offset;
    file->f_reada = 0;
    diff -r -u -P -x CVS -x *,v 2.3/include/linux/fs.h
    build-2.3/include/linux/fs.h
    --- 2.3/include/linux/fs.h Mon Aug 9 23:58:27 1999
    +++ build-2.3/include/linux/fs.h Fri Aug 20 19:35:54 1999
    @@ -519,6 +519,7 @@
    kdev_t s_dev;
    unsigned long s_blocksize;
    unsigned char s_blocksize_bits;
    + loff_t s_maxfilesize;
    unsigned char s_lock;
    unsigned char s_rd_only;
    unsigned char s_dirt;
    <<<<<<<<<<<<<<<<<<

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.rutgers.edu
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:53    [W:3.519 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site