Module: wine Branch: master Commit: d2b3c6c3f9e42cdb49225fbabc4db7e61f3c119b URL: http://source.winehq.org/git/wine.git/?a=commit;h=d2b3c6c3f9e42cdb49225fbabc...
Author: Jacek Caban jacek@codeweavers.com Date: Sun Dec 4 21:21:25 2016 +0100
server: Introduced iosb struct for server-side IO_STATUS_BLOCK representation and use it in irp_call.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
server/async.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ server/device.c | 58 +++++++++++++++++++++++------------------------------ server/file.h | 13 ++++++++++++ 3 files changed, 100 insertions(+), 33 deletions(-)
diff --git a/server/async.c b/server/async.c index 70ebf95..568b440 100644 --- a/server/async.c +++ b/server/async.c @@ -389,6 +389,68 @@ void async_wake_up( struct async_queue *queue, unsigned int status ) } }
+static void iosb_dump( struct object *obj, int verbose ); +static void iosb_destroy( struct object *obj ); + +static const struct object_ops iosb_ops = +{ + sizeof(struct iosb), /* size */ + iosb_dump, /* dump */ + no_get_type, /* get_type */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + no_map_access, /* map_access */ + default_get_sd, /* get_sd */ + default_set_sd, /* set_sd */ + no_lookup_name, /* lookup_name */ + no_link_name, /* link_name */ + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_close_handle, /* close_handle */ + iosb_destroy /* destroy */ +}; + +static void iosb_dump( struct object *obj, int verbose ) +{ + assert( obj->ops == &iosb_ops ); + fprintf( stderr, "I/O status block\n" ); +} + +static void iosb_destroy( struct object *obj ) +{ + struct iosb *iosb = (struct iosb *)obj; + + free( iosb->in_data ); + free( iosb->out_data ); +} + +/* allocate iosb struct */ +struct iosb *create_iosb( const void *in_data, data_size_t in_size, data_size_t out_size ) +{ + struct iosb *iosb; + + if (!(iosb = alloc_object( &iosb_ops ))) return NULL; + + iosb->status = STATUS_PENDING; + iosb->result = 0; + iosb->in_size = in_size; + iosb->in_data = NULL; + iosb->out_size = out_size; + iosb->out_data = NULL; + + if (in_size && !(iosb->in_data = memdup( in_data, in_size ))) + { + release_object( iosb ); + iosb = NULL; + } + + return iosb; +} + /* cancels all async I/O */ DECL_HANDLER(cancel_async) { diff --git a/server/device.c b/server/device.c index 2a34cfb..99d5204 100644 --- a/server/device.c +++ b/server/device.c @@ -50,13 +50,8 @@ struct irp_call struct thread *thread; /* thread that queued the irp */ client_ptr_t user_arg; /* user arg used to identify the request */ struct async *async; /* pending async op */ - unsigned int status; /* resulting status (or STATUS_PENDING) */ irp_params_t params; /* irp parameters */ - data_size_t result; /* size of result (input or output depending on the type) */ - data_size_t in_size; /* size of input data */ - void *in_data; /* input data */ - data_size_t out_size; /* size of output data */ - void *out_data; /* output data */ + struct iosb *iosb; /* I/O status block */ };
static void irp_call_dump( struct object *obj, int verbose ); @@ -241,13 +236,12 @@ static void irp_call_destroy( struct object *obj ) { struct irp_call *irp = (struct irp_call *)obj;
- free( irp->in_data ); - free( irp->out_data ); if (irp->async) { async_terminate( irp->async, STATUS_CANCELLED ); release_object( irp->async ); } + if (irp->iosb) release_object( irp->iosb ); if (irp->file) release_object( irp->file ); if (irp->thread) release_object( irp->thread ); } @@ -269,14 +263,8 @@ static struct irp_call *create_irp( struct device_file *file, const irp_params_t irp->thread = NULL; irp->async = NULL; irp->params = *params; - irp->status = STATUS_PENDING; - irp->result = 0; - irp->in_size = in_size; - irp->in_data = NULL; - irp->out_size = out_size; - irp->out_data = NULL; - - if (irp->in_size && !(irp->in_data = memdup( in_data, in_size ))) + + if (!(irp->iosb = create_iosb( in_data, in_size, out_size ))) { release_object( irp ); irp = NULL; @@ -289,15 +277,16 @@ static void set_irp_result( struct irp_call *irp, unsigned int status, const void *out_data, data_size_t out_size, data_size_t result ) { struct device_file *file = irp->file; + struct iosb *iosb = irp->iosb;
if (!file) return; /* already finished */
/* FIXME: handle the STATUS_PENDING case */ - irp->status = status; - irp->result = result; - irp->out_size = min( irp->out_size, out_size ); - if (irp->out_size && !(irp->out_data = memdup( out_data, irp->out_size ))) - irp->out_size = 0; + iosb->status = status; + iosb->result = result; + iosb->out_size = min( iosb->out_size, out_size ); + if (iosb->out_size && !(iosb->out_data = memdup( out_data, iosb->out_size ))) + iosb->out_size = 0; irp->file = NULL; if (irp->async) { @@ -761,6 +750,7 @@ DECL_HANDLER(get_next_device_request) struct irp_call *irp; struct device_manager *manager; struct list *ptr; + struct iosb *iosb;
reply->params.major = IRP_MJ_MAXIMUM_FUNCTION + 1;
@@ -788,14 +778,15 @@ DECL_HANDLER(get_next_device_request) reply->client_tid = get_thread_id( irp->thread ); } reply->params = irp->params; - reply->in_size = irp->in_size; - reply->out_size = irp->out_size; - if (irp->in_size > get_reply_max_size()) set_error( STATUS_BUFFER_OVERFLOW ); + iosb = irp->iosb; + reply->in_size = iosb->in_size; + reply->out_size = iosb->out_size; + if (iosb->in_size > get_reply_max_size()) set_error( STATUS_BUFFER_OVERFLOW ); else if ((reply->next = alloc_handle( current->process, irp, 0, 0 ))) { - set_reply_data_ptr( irp->in_data, irp->in_size ); - irp->in_data = NULL; - irp->in_size = 0; + set_reply_data_ptr( iosb->in_data, iosb->in_size ); + iosb->in_data = NULL; + iosb->in_size = 0; list_remove( &irp->mgr_entry ); list_init( &irp->mgr_entry ); } @@ -833,17 +824,18 @@ DECL_HANDLER(get_irp_result)
if ((irp = find_irp_call( file, current, req->user_arg ))) { - if (irp->out_data) + struct iosb *iosb = irp->iosb; + if (iosb->out_data) { - data_size_t size = min( irp->out_size, get_reply_max_size() ); + data_size_t size = min( iosb->out_size, get_reply_max_size() ); if (size) { - set_reply_data_ptr( irp->out_data, size ); - irp->out_data = NULL; + set_reply_data_ptr( iosb->out_data, size ); + iosb->out_data = NULL; } } - reply->size = irp->result; - set_error( irp->status ); + reply->size = iosb->result; + set_error( iosb->status ); list_remove( &irp->dev_entry ); release_object( irp ); /* no longer on the device queue */ } diff --git a/server/file.h b/server/file.h index fb2e905..0a144ee 100644 --- a/server/file.h +++ b/server/file.h @@ -53,6 +53,18 @@ struct fd_ops void (*reselect_async)( struct fd *, struct async_queue *queue ); };
+/* server-side representation of I/O status block */ +struct iosb +{ + struct object obj; /* object header */ + unsigned int status; /* resulting status (or STATUS_PENDING) */ + data_size_t result; /* size of result (input or output depending on the type) */ + data_size_t in_size; /* size of input data */ + void *in_data; /* input data */ + data_size_t out_size; /* size of output data */ + void *out_data; /* output data */ +}; + /* file descriptor functions */
extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *user, @@ -175,6 +187,7 @@ extern void async_terminate( struct async *async, unsigned int status ); extern void async_wake_up( struct async_queue *queue, unsigned int status ); extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key ); extern void fd_copy_completion( struct fd *src, struct fd *dst ); +extern struct iosb *create_iosb( const void *in_data, data_size_t in_size, data_size_t out_size ); extern void cancel_process_asyncs( struct process *process );
/* access rights that require Unix read permission */