Jacek Caban : server: Introduced iosb struct for server-side IO_STATUS_BLOCK representation and use it in irp_call.

Alexandre Julliard julliard at winehq.org
Tue Dec 6 16:27:43 CST 2016


Module: wine
Branch: master
Commit: d2b3c6c3f9e42cdb49225fbabc4db7e61f3c119b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d2b3c6c3f9e42cdb49225fbabc4db7e61f3c119b

Author: Jacek Caban <jacek at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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 */




More information about the wine-cvs mailing list