Re: [PATCH] Suppress deprecated f_maxcount in 'struct file'

Peter Staubach
2005-08-22T21:45:25Z

[-- Attachment #1: Type: text/plain, Size: 1651 bytes --]

Eric Dumazet wrote:

> Andrew Morton a écrit :
>
>> Eric Dumazet <dada1@cosmosbay.com> wrote:
>>
>>> Considering :
>>>
>>> [root@dada1 linux-2.6.13-rc6]# find .|xargs grep f_maxcount
>>> ./fs/file_table.c: f->f_maxcount = INT_MAX;
>>> ./fs/read_write.c: if (unlikely(count > file->f_maxcount))
>>> ./include/linux/fs.h: size_t f_maxcount;
>>>
>>>
>>> I was wondering if f_maxcount has a real use these days...
>>
>>
>>
>> No, I guess we can just stick a hard-wired INT_MAX in there.
>>
>>
>
> OK here is a patch doing the hard wiring then :)
>
> * struct file cleanup : f_maxcount has an unique value (INT_MAX). Just
> use the hard-wired value.
>
> Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
>
>------------------------------------------------------------------------
>diff -Nru linux-2.6.13-rc6/fs/read_write.c linux-2.6.13-rc6-ed/fs/read_write.c
>--- linux-2.6.13-rc6/fs/read_write.c 2005-08-07 20:18:56.000000000 +0200
>+++ linux-2.6.13-rc6-ed/fs/read_write.c 2005-08-19 23:51:20.000000000 +0200
>@@ -188,7 +188,7 @@
> struct inode *inode;
> loff_t pos;
>
>- if (unlikely(count > file->f_maxcount))
>+ if (unlikely(count > INT_MAX))
> goto Einval;
> pos = *ppos;
> if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
>

And depending upon how you feel about read(2) and write(2) returning larger
than can be represented by a ssize_t, you can get rid of this test too and
apply the attached patch to prevent failures occuring in the direct-io
subsystem.

Limiting i/o requests to INT_MAX is starting to seem a little small.

Thanx...

ps

Signed-off-by: Peter Staubach <staubach@redhat.com>

[-- Attachment #2: devel --]
[-- Type: text/plain, Size: 2212 bytes --]

--- linux-2.6.12/fs/direct-io.c.org 2005-08-22 08:56:40.000000000 -0400
+++ linux-2.6.12/fs/direct-io.c 2005-08-22 08:59:49.000000000 -0400
@@ -1139,6 +1139,12 @@ direct_io_worker(int rw, struct kiocb *i
}

/*
+ * The maximum size of an i/o request which can handled by block
+ * devices.
+ */
+#define MAX_DIO_SIZE ((u32)INT_MAX + 1)
+
+/*
* This is a library function for use by filesystem drivers.
* The locking rules are governed by the dio_lock_type parameter.
*
@@ -1174,6 +1180,12 @@ __blockdev_direct_IO(int rw, struct kioc
loff_t end = offset;
struct dio *dio;
int reader_with_isem = (rw == READ && dio_lock_type == DIO_OWN_LOCKING);
+ int nseg;
+ unsigned long segs_reqd;
+ struct iovec *niov = NULL;
+ int asegs;
+ caddr_t nbase;
+ size_t nlen;

if (rw & WRITE)
current->flags |= PF_SYNCWRITE;
@@ -1189,6 +1201,44 @@ __blockdev_direct_IO(int rw, struct kioc
goto out;
}

+ /*
+ * Check to see if any individual segment is larger than
+ * 2G. If so, then break it up into 2G sized chunks.
+ */
+ segs_reqd = 0;
+ for (seg = 0; seg < nr_segs; seg++)
+ segs_reqd += ((iov[seg].iov_len - 1) / MAX_DIO_SIZE) + 1;
+ if (segs_reqd != nr_segs) {
+ if (segs_reqd > UIO_MAXIOV) {
+ retval = -EINVAL;
+ goto out;
+ }
+ niov = kmalloc(sizeof(*niov) * segs_reqd, GFP_KERNEL);
+ if (!niov) {
+ retval = -ENOMEM;
+ goto out;
+ }
+ nseg = 0;
+ for (seg = 0; seg < nr_segs; seg++) {
+ nbase = iov[seg].iov_base;
+ nlen = iov[seg].iov_len;
+ asegs = (iov[seg].iov_len - 1) / MAX_DIO_SIZE;
+ while (asegs > 0) {
+ niov[nseg].iov_base = nbase;
+ niov[nseg].iov_len = MAX_DIO_SIZE;
+ nbase += MAX_DIO_SIZE;
+ nlen -= MAX_DIO_SIZE;
+ nseg++;
+ asegs--;
+ }
+ niov[nseg].iov_base = nbase;
+ niov[nseg].iov_len = nlen;
+ nseg++;
+ }
+ iov = niov;
+ nr_segs = segs_reqd;
+ }
+
/* Check the memory alignment. Blocks cannot straddle pages */
for (seg = 0; seg < nr_segs; seg++) {
addr = (unsigned long)iov[seg].iov_base;
@@ -1265,6 +1315,8 @@ __blockdev_direct_IO(int rw, struct kioc
out:
if (reader_with_isem)
up(&inode->i_sem);
+ if (niov)
+ kfree(niov);
if (rw & WRITE)
current->flags &= ~PF_SYNCWRITE;
return retval;