diff options
| author | Alexander Viro <viro@parcelfarce.linux.theplanet.co.uk> | 2004-07-13 19:37:04 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-07-13 19:37:04 -0700 |
| commit | 790d43fd412fbb30bfb61504250e88ece790f485 (patch) | |
| tree | d129747d615470a10c45d2ada3386f593e66b5dd | |
| parent | c659d1a85a24500b775390a0d5f6a2fe06d6cbf4 (diff) | |
[PATCH] sparse: read_descriptor_t annotation
We have a fun situation with read_descriptor_t - all its instances end
up passed to some actor; these actors use desc->buf as their private
data; there are 5 of them and they expect resp:
struct lo_read_data *
struct svc_rqst *
struct file *
struct rpc_xprt *
char __user *
IOW, there is no type safety whatsoever; the field is essentially untyped,
we rely on the fact that actor is chosen by the same code that sets ->buf
and expect it to put something of the right type there.
Right now desc->buf is declared as char __user *. Moreover, the last
argument of ->sendfile() (what should be stored in ->buf) is void __user *,
even though it's actually _never_ a userland pointer.
If nothing else, ->sendfile() should take void * instead; that alone removes
a bunch of bogus warnings. I went further and replaced desc->buf with a
union of void * and char __user *.
| -rw-r--r-- | drivers/block/loop.c | 2 | ||||
| -rw-r--r-- | fs/nfs/file.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 2 | ||||
| -rw-r--r-- | fs/smbfs/file.c | 2 | ||||
| -rw-r--r-- | include/linux/fs.h | 9 | ||||
| -rw-r--r-- | mm/filemap.c | 16 | ||||
| -rw-r--r-- | mm/shmem.c | 6 | ||||
| -rw-r--r-- | net/sunrpc/xprt.c | 4 |
8 files changed, 24 insertions, 21 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index f1250943c167..946742912a9f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -293,7 +293,7 @@ lo_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset, unsigned long size) { unsigned long count = desc->count; - struct lo_read_data *p = (struct lo_read_data*)desc->buf; + struct lo_read_data *p = desc->arg.data; struct loop_device *lo = p->lo; sector_t IV; diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 1ea93c580a03..02deae074c6f 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -38,7 +38,7 @@ static long nfs_file_fcntl(int fd, unsigned int cmd, static int nfs_file_open(struct inode *, struct file *); static int nfs_file_release(struct inode *, struct file *); static int nfs_file_mmap(struct file *, struct vm_area_struct *); -static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void __user *); +static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t); static int nfs_file_flush(struct file *); @@ -171,7 +171,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos) static ssize_t nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count, - read_actor_t actor, void __user *target) + read_actor_t actor, void *target) { struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index f7ac90d15961..a6a05c3b247c 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -611,7 +611,7 @@ static int nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size) { unsigned long count = desc->count; - struct svc_rqst *rqstp = (struct svc_rqst *)desc->buf; + struct svc_rqst *rqstp = desc->arg.data; if (size > count) size = count; diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index b28f42e3bf08..e97fc5807cab 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -261,7 +261,7 @@ out: static ssize_t smb_file_sendfile(struct file *file, loff_t *ppos, - size_t count, read_actor_t actor, void __user *target) + size_t count, read_actor_t actor, void *target) { struct dentry *dentry = file->f_dentry; ssize_t status; diff --git a/include/linux/fs.h b/include/linux/fs.h index 3d24beb4ac36..819e67e3a95b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -852,7 +852,10 @@ struct block_device_operations { typedef struct { size_t written; size_t count; - char __user * buf; + union { + char __user * buf; + void *data; + } arg; int error; } read_descriptor_t; @@ -883,7 +886,7 @@ struct file_operations { int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); - ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void __user *); + ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); long (*fcntl)(int fd, unsigned int cmd, @@ -1410,7 +1413,7 @@ extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, lof extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *ppos); -extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void __user *); +extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); extern void do_generic_mapping_read(struct address_space *mapping, struct file_ra_state *, struct file *, loff_t *, read_descriptor_t *, read_actor_t); diff --git a/mm/filemap.c b/mm/filemap.c index 087e0525b967..cb3a40145c86 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -836,9 +836,9 @@ int file_read_actor(read_descriptor_t *desc, struct page *page, * Faults on the destination of a read are common, so do it before * taking the kmap. */ - if (!fault_in_pages_writeable(desc->buf, size)) { + if (!fault_in_pages_writeable(desc->arg.buf, size)) { kaddr = kmap_atomic(page, KM_USER0); - left = __copy_to_user(desc->buf, kaddr + offset, size); + left = __copy_to_user(desc->arg.buf, kaddr + offset, size); kunmap_atomic(kaddr, KM_USER0); if (left == 0) goto success; @@ -846,7 +846,7 @@ int file_read_actor(read_descriptor_t *desc, struct page *page, /* Do it the slow way */ kaddr = kmap(page); - left = __copy_to_user(desc->buf, kaddr + offset, size); + left = __copy_to_user(desc->arg.buf, kaddr + offset, size); kunmap(page); if (left) { @@ -856,7 +856,7 @@ int file_read_actor(read_descriptor_t *desc, struct page *page, success: desc->count = count - size; desc->written += size; - desc->buf += size; + desc->arg.buf += size; return size; } @@ -923,7 +923,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, read_descriptor_t desc; desc.written = 0; - desc.buf = iov[seg].iov_base; + desc.arg.buf = iov[seg].iov_base; desc.count = iov[seg].iov_len; if (desc.count == 0) continue; @@ -973,7 +973,7 @@ int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long o { ssize_t written; unsigned long count = desc->count; - struct file *file = (struct file *) desc->buf; + struct file *file = desc->arg.data; if (size > count) size = count; @@ -990,7 +990,7 @@ int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long o } ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos, - size_t count, read_actor_t actor, void __user *target) + size_t count, read_actor_t actor, void *target) { read_descriptor_t desc; @@ -999,7 +999,7 @@ ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos, desc.written = 0; desc.count = count; - desc.buf = target; + desc.arg.data = target; desc.error = 0; do_generic_file_read(in_file, ppos, &desc, actor); diff --git a/mm/shmem.c b/mm/shmem.c index 6581c5d6e4f2..ee0d0e774695 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1474,7 +1474,7 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count desc.written = 0; desc.count = count; - desc.buf = buf; + desc.arg.buf = buf; desc.error = 0; do_shmem_file_read(filp, ppos, &desc, file_read_actor); @@ -1484,7 +1484,7 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count } static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos, - size_t count, read_actor_t actor, void __user *target) + size_t count, read_actor_t actor, void *target) { read_descriptor_t desc; @@ -1493,7 +1493,7 @@ static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos, desc.written = 0; desc.count = count; - desc.buf = target; + desc.arg.data = target; desc.error = 0; do_shmem_file_read(in_file, ppos, &desc, actor); diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index cf4cf02bc35e..5fbbe608b14f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -973,7 +973,7 @@ static int tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len) { - struct rpc_xprt *xprt = (struct rpc_xprt *)rd_desc->buf; + struct rpc_xprt *xprt = rd_desc->arg.data; skb_reader_t desc = { .skb = skb, .offset = offset, @@ -1021,7 +1021,7 @@ static void tcp_data_ready(struct sock *sk, int bytes) goto out; /* We use rd_desc to pass struct xprt to tcp_data_recv */ - rd_desc.buf = (char *)xprt; + rd_desc.arg.data = xprt; rd_desc.count = 65536; tcp_read_sock(sk, &rd_desc, tcp_data_recv); out: |
