Re: [RFC PATCH 26/32] ide-tape: remove packet command and struct request memory buffers
On Sunday 27 January 2008, Borislav Petkov wrote: From: Borislav Petkov [EMAIL PROTECTED] Bart, this one is rather intrusive so please doublecheck it wrt to kzalloc/kfree balancing on all the codepaths so that we don't leak memory all over the place. I free all the alloc'd pc's and rq's in idetape_end_request() which is called from the callback idetape_pc_callback() registered with the packet command struct when creating the respective ATAPI cmd. I was hoping for re-using requests from the request queue for this purpose (with help of blk_get_request()/blk_put_request()). Jens, is this OK? This approach wouldn't have a problem with out-of-memory situations (because blk_get_request() can wait until free request is available), needs less code and provides additional benefits (like NUMA-friendly allocations). When it comes to pc-s: long-term it should be possible to use only request structure and get rid off them. --- These buffers were always statically allocated during driver initialization no matter what. Remove them by allocating GFP_ATOMIC memory on demand. In the case of allocation error, we only issue error msg in the *alloc_{pc,rq} thus postponing the final error handling and cleanup in their callers. Packet command and request memory is freed in idetape_end_request() which is at the end of the request path entered from all the callbacks. Signed-off-by: Borislav Petkov [EMAIL PROTECTED] --- drivers/ide/ide-tape.c | 122 ++- 1 files changed, 57 insertions(+), 65 deletions(-) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 041edcd..3c1a7db 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -105,13 +105,6 @@ enum { #define IDETAPE_PC_BUFFER_SIZE 256 /* - * In various places in the driver, we need to allocate storage - * for packet commands and requests, which will remain valid while - * we leave the driver to wait for an interrupt or a timeout event. - */ -#define IDETAPE_PC_STACK (10 + IDETAPE_MAX_PC_RETRIES) - -/* * Some drives (for example, Seagate STT3401A Travan) require a very long * timeout, because they don't return an interrupt or clear their busy bit * until after the command completes (even retension commands). @@ -271,13 +264,6 @@ typedef struct ide_tape_obj { */ idetape_pc_t *failed_pc; - idetape_pc_t pc_stack[IDETAPE_PC_STACK]; - /* Next free packet command storage space */ - int pc_stack_idx; - struct request rq_stack[IDETAPE_PC_STACK]; - /* We implement a circular array */ - int rq_stack_idx; - /* * DSC polling variables. * @@ -669,45 +655,32 @@ static void idetape_update_buffers (idetape_pc_t *pc) pc-bh = bh; } -/* - * idetape_next_pc_storage returns a pointer to a place in which we can - * safely store a packet command, even though we intend to leave the - * driver. A storage space for a maximum of IDETAPE_PC_STACK packet - * commands is allocated at initialization time. - */ -static idetape_pc_t *idetape_next_pc_storage (ide_drive_t *drive) +static idetape_pc_t *ide_tape_alloc_pc(void) { - idetape_tape_t *tape = drive-driver_data; + idetape_pc_t *pc; - debug_log(DBG_PCRQ_STACK, pc_stack_index=%d\n, tape-pc_stack_idx); + pc = kzalloc(sizeof(idetape_pc_t), GFP_ATOMIC); + if (!pc) + printk(KERN_ERR ide-tape: %s: memory allocation error., + __func__); - if (tape-pc_stack_idx == IDETAPE_PC_STACK) - tape-pc_stack_idx = 0; - return (tape-pc_stack[tape-pc_stack_idx++]); + return pc; } /* - * idetape_next_rq_storage is used along with idetape_next_pc_storage. - * Since we queue packet commands in the request queue, we need to - * allocate a request, along with the allocation of a packet command. + * Since we queue packet commands in the request queue, we need to allocate a + * request, along with a packet command. */ - -/** - ** - * This should get fixed to use kmalloc(.., GFP_ATOMIC) * - * followed later on by kfree(). -ml * - ** - **/ - -static struct request *idetape_next_rq_storage (ide_drive_t *drive) +static struct request *ide_tape_alloc_rq(void) { - idetape_tape_t *tape = drive-driver_data; + struct request *rq; - debug_log(DBG_PCRQ_STACK, rq_stack_index=%d\n, tape-rq_stack_idx); + rq = kzalloc(sizeof(struct request), GFP_ATOMIC); + if (!rq) + printk(KERN_ERR ide-tape: %s: memory allocation error., + __func__); - if (tape-rq_stack_idx
[RFC PATCH 26/32] ide-tape: remove packet command and struct request memory buffers
From: Borislav Petkov [EMAIL PROTECTED] Bart, this one is rather intrusive so please doublecheck it wrt to kzalloc/kfree balancing on all the codepaths so that we don't leak memory all over the place. I free all the alloc'd pc's and rq's in idetape_end_request() which is called from the callback idetape_pc_callback() registered with the packet command struct when creating the respective ATAPI cmd. --- These buffers were always statically allocated during driver initialization no matter what. Remove them by allocating GFP_ATOMIC memory on demand. In the case of allocation error, we only issue error msg in the *alloc_{pc,rq} thus postponing the final error handling and cleanup in their callers. Packet command and request memory is freed in idetape_end_request() which is at the end of the request path entered from all the callbacks. Signed-off-by: Borislav Petkov [EMAIL PROTECTED] --- drivers/ide/ide-tape.c | 122 ++- 1 files changed, 57 insertions(+), 65 deletions(-) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 041edcd..3c1a7db 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -105,13 +105,6 @@ enum { #define IDETAPE_PC_BUFFER_SIZE 256 /* - * In various places in the driver, we need to allocate storage - * for packet commands and requests, which will remain valid while - * we leave the driver to wait for an interrupt or a timeout event. - */ -#define IDETAPE_PC_STACK (10 + IDETAPE_MAX_PC_RETRIES) - -/* * Some drives (for example, Seagate STT3401A Travan) require a very long * timeout, because they don't return an interrupt or clear their busy bit * until after the command completes (even retension commands). @@ -271,13 +264,6 @@ typedef struct ide_tape_obj { */ idetape_pc_t *failed_pc; - idetape_pc_t pc_stack[IDETAPE_PC_STACK]; - /* Next free packet command storage space */ - int pc_stack_idx; - struct request rq_stack[IDETAPE_PC_STACK]; - /* We implement a circular array */ - int rq_stack_idx; - /* * DSC polling variables. * @@ -669,45 +655,32 @@ static void idetape_update_buffers (idetape_pc_t *pc) pc-bh = bh; } -/* - * idetape_next_pc_storage returns a pointer to a place in which we can - * safely store a packet command, even though we intend to leave the - * driver. A storage space for a maximum of IDETAPE_PC_STACK packet - * commands is allocated at initialization time. - */ -static idetape_pc_t *idetape_next_pc_storage (ide_drive_t *drive) +static idetape_pc_t *ide_tape_alloc_pc(void) { - idetape_tape_t *tape = drive-driver_data; + idetape_pc_t *pc; - debug_log(DBG_PCRQ_STACK, pc_stack_index=%d\n, tape-pc_stack_idx); + pc = kzalloc(sizeof(idetape_pc_t), GFP_ATOMIC); + if (!pc) + printk(KERN_ERR ide-tape: %s: memory allocation error., + __func__); - if (tape-pc_stack_idx == IDETAPE_PC_STACK) - tape-pc_stack_idx = 0; - return (tape-pc_stack[tape-pc_stack_idx++]); + return pc; } /* - * idetape_next_rq_storage is used along with idetape_next_pc_storage. - * Since we queue packet commands in the request queue, we need to - * allocate a request, along with the allocation of a packet command. + * Since we queue packet commands in the request queue, we need to allocate a + * request, along with a packet command. */ - -/** - ** - * This should get fixed to use kmalloc(.., GFP_ATOMIC) * - * followed later on by kfree(). -ml * - ** - **/ - -static struct request *idetape_next_rq_storage (ide_drive_t *drive) +static struct request *ide_tape_alloc_rq(void) { - idetape_tape_t *tape = drive-driver_data; + struct request *rq; - debug_log(DBG_PCRQ_STACK, rq_stack_index=%d\n, tape-rq_stack_idx); + rq = kzalloc(sizeof(struct request), GFP_ATOMIC); + if (!rq) + printk(KERN_ERR ide-tape: %s: memory allocation error., + __func__); - if (tape-rq_stack_idx == IDETAPE_PC_STACK) - tape-rq_stack_idx = 0; - return (tape-rq_stack[tape-rq_stack_idx++]); + return rq; } /* @@ -981,9 +954,8 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) } } ide_end_drive_cmd(drive, 0, 0); -// blkdev_dequeue_request(rq); -// drive-rq = NULL; -// end_that_request_last(rq); + kfree(tape-pc); + kfree(rq); if (remove_stage) idetape_remove_stage_head(drive); @@ -1032,13 +1004,9 @@ static void