[RFC][PATCH] - lseek()

Manfred Spraul (manfreds@colorfullife.com)
Fri, 20 Aug 1999 22:38:39 +0200


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/