From 2029867510c1556deeedfeb03ed052bbbaaf6d88 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Sun, 2 Jun 2013 15:33:51 -0700 Subject: [PATCH] folder redirection: made changes to read/write routines to avoid race conditions --- sesman/chansrv/chansrv_fuse.c | 4 ++-- sesman/chansrv/devredir.c | 44 +++++++++++++++++++++++++++++------ sesman/chansrv/devredir.h | 2 +- sesman/chansrv/irp.c | 29 +++++++++++++++++++++++ sesman/chansrv/irp.h | 1 + 5 files changed, 70 insertions(+), 10 deletions(-) diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index 70dd12af..3d6e3e3c 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -259,7 +259,7 @@ int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path); int dev_redir_file_open(void *fusep, tui32 device_id, char *path, int mode, int type, char *gen_buf); -int dev_redir_file_read(void *fusep, tui32 device_id, tui32 FileId, +int devredir_file_read(void *fusep, tui32 device_id, tui32 FileId, tui32 Length, tui64 Offset); int dev_redir_file_write(void *fusep, tui32 device_id, tui32 FileId, @@ -2865,7 +2865,7 @@ static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size, fusep->device_id = fh->DeviceId; fusep->fi = fi; - dev_redir_file_read(fusep, fh->DeviceId, fh->FileId, size, off); + devredir_file_read(fusep, fh->DeviceId, fh->FileId, size, off); } /** diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index 08f28a0d..77f1569f 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -775,16 +775,24 @@ void dev_redir_proc_device_iocompletion(struct stream *s) log_debug("got CID_READ"); xstream_rd_u32_le(s, Length); fuse_data = devredir_fuse_data_dequeue(irp); + if (fuse_data == NULL) log_error("fuse_data is NULL"); + xfuse_devredir_cb_read_file(fuse_data->data_ptr, s->p, Length); + devredir_irp_delete(irp); break; case CID_WRITE: log_debug("got CID_WRITE"); xstream_rd_u32_le(s, Length); fuse_data = devredir_fuse_data_dequeue(irp); + + if (fuse_data == NULL) + log_error("fuse_data is NULL"); + xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length); + devredir_irp_delete(irp); break; case CID_CLOSE: @@ -1172,11 +1180,12 @@ int devredir_rmdir_or_file(void *fusep, tui32 device_id, char *path, int mode) * @return 0 on success, -1 on failure *****************************************************************************/ -int dev_redir_file_read(void *fusep, tui32 DeviceId, tui32 FileId, +int devredir_file_read(void *fusep, tui32 DeviceId, tui32 FileId, tui32 Length, tui64 Offset) { struct stream *s; IRP *irp; + IRP *new_irp; int bytes; xstream_new(s, 1024); @@ -1188,12 +1197,22 @@ int dev_redir_file_read(void *fusep, tui32 DeviceId, tui32 FileId, return -1; } - irp->completion_type = CID_READ; - devredir_fuse_data_enqueue(irp, fusep); + /* create a new IRP for this request */ + if ((new_irp = devredir_irp_clone(irp)) == NULL) + { + /* system out of memory */ + xfuse_devredir_cb_read_file(fusep, NULL, 0); + return -1; + } + new_irp->FileId = 0; + new_irp->completion_type = CID_READ; + new_irp->CompletionId = g_completion_id++; + devredir_fuse_data_enqueue(new_irp, fusep); + devredir_insert_DeviceIoRequest(s, DeviceId, FileId, - irp->CompletionId, + new_irp->CompletionId, IRP_MJ_READ, 0); @@ -1214,6 +1233,7 @@ int dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId, { struct stream *s; IRP *irp; + IRP *new_irp; int bytes; log_debug("DeviceId=%d FileId=%d Length=%d Offset=%lld", @@ -1228,12 +1248,22 @@ int dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId, return -1; } - irp->completion_type = CID_WRITE; - devredir_fuse_data_enqueue(irp, fusep); + /* create a new IRP for this request */ + if ((new_irp = devredir_irp_clone(irp)) == NULL) + { + /* system out of memory */ + xfuse_devredir_cb_write_file(fusep, NULL, 0); + return -1; + } + new_irp->FileId = 0; + new_irp->completion_type = CID_WRITE; + new_irp->CompletionId = g_completion_id++; + devredir_fuse_data_enqueue(new_irp, fusep); + devredir_insert_DeviceIoRequest(s, DeviceId, FileId, - irp->CompletionId, + new_irp->CompletionId, IRP_MJ_WRITE, 0); diff --git a/sesman/chansrv/devredir.h b/sesman/chansrv/devredir.h index da49350b..5a402c9c 100644 --- a/sesman/chansrv/devredir.h +++ b/sesman/chansrv/devredir.h @@ -101,7 +101,7 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path, int devredir_file_close(void *fusep, tui32 device_id, tui32 file_id); -int dev_redir_file_read(void *fusep, tui32 device_id, tui32 FileId, +int devredir_file_read(void *fusep, tui32 device_id, tui32 FileId, tui32 Length, tui64 Offset); int send_channel_data(int chan_id, char *data, int size); diff --git a/sesman/chansrv/irp.c b/sesman/chansrv/irp.c index 5c21fe0f..fcf3e537 100644 --- a/sesman/chansrv/irp.c +++ b/sesman/chansrv/irp.c @@ -99,6 +99,35 @@ IRP * devredir_irp_new() return irp; } +/** + * Clone specified IRP + * + * @return new IRP or NULL on error + *****************************************************************************/ + +IRP * devredir_irp_clone(IRP *irp) +{ + IRP *new_irp; + IRP *prev; + IRP *next; + + if ((new_irp = devredir_irp_new()) == NULL) + return NULL; + + /* save link pointers */ + prev = new_irp->prev; + next = new_irp->next; + + /* copy all members */ + memcpy(new_irp, irp, sizeof(IRP)); + + /* restore link pointers */ + new_irp->prev = prev; + new_irp->next = next; + + return new_irp; +} + /** * Delete specified IRP from linked list * diff --git a/sesman/chansrv/irp.h b/sesman/chansrv/irp.h index ccab5801..64cbac93 100644 --- a/sesman/chansrv/irp.h +++ b/sesman/chansrv/irp.h @@ -55,6 +55,7 @@ struct irp }; IRP * devredir_irp_new(); +IRP * devredir_irp_clone(IRP *irp); int devredir_irp_delete(IRP *irp); IRP * devredir_irp_find(tui32 completion_id); IRP * devredir_irp_find_by_fileid(tui32 FileId);