📄 tffsdrv26.c
字号:
*******************************************************************************/staticint socket_io_thread (void * arg) { SocketInfo * psoc = (SocketInfo *) arg; char name[32]; current->flags |= (PF_MEMALLOC | PF_NOFREEZE); sprintf (name, "%s%c", tffs_str, '0' + (char)psoc->bHandle); daemonize (name); /* we don't want to receive any signals */ spin_lock_irq (¤t->sighand->siglock); sigfillset (¤t->blocked); recalc_sigpending (); spin_unlock_irq (¤t->sighand->siglock); /* adjist thread's priority if necessary */ if (tffs_prio != 0) set_user_nice (current, tffs_prio); /* initially socket's request list is empty */ spin_lock_init (&psoc->request_list_lock); INIT_LIST_HEAD (&psoc->requestsList); /* If somebody is waiting for socket's I/O thread to start up and * get ready for processing I/O requests, let them know that we did. */ if (psoc->io_thread_state == 2) up (&psoc->threadSemaphore); /* socket's I/O thread is ready to receive I/O requests */ psoc->io_thread_state = 1; while (psoc->io_thread_state == 1) { /* wait 5 clock ticks for I/O requests to arrive */ wait_event_interruptible_timeout (psoc->waitQueueHead, requests_to_do(psoc), 5); /* handle all I/O requests (if any) in socket's request ist */ do_requests_list (psoc); } /* If somebody is waiting for socket's I/O thread to terminate, * let them know that it did. */ if (psoc->io_thread_state == 2) up (&psoc->threadSemaphore); /* socket's I/O thread terminated */ psoc->io_thread_state = 0; return 0;}/******************************************************************************* * * * d o _ r e q u e s t s _ l i s t * * * * This routine handles all requests in socket's request list. * * * * Parameters: * * psoc socket pointer * * * *******************************************************************************/staticvoid do_requests_list ( SocketInfo * psoc ){ struct request * r; struct gendisk * gd; DeviceInfo * pdisk; unsigned long flags; /* lock socket's request list */ spin_lock_irqsave (&psoc->request_list_lock, flags); /* if socket's request list isn't empty, process all requests there */ while( !(list_empty(&psoc->requestsList)) ) { /* take next request off socket's request list */ r = list_entry_rq (psoc->requestsList.next); list_del_init (&r->queuelist); /* unlock socket's request list */ spin_unlock_irqrestore (&psoc->request_list_lock, flags); /* Mark all non-filesystem request, and those filesystem requests * that don't pass sanity check, as not-uptodate (i.e. failed). */ if( !blk_fs_request(r) || ((gd = r->rq_disk) == NULL) || ((pdisk = gd->private_data) == NULL) || (pdisk->gd != gd) || (r->sector + r->nr_sectors > pdisk->dwSize) ) { end_that_request_first (r, /* failed */ 0, r->hard_cur_sectors); } else /* legitimate filesystem request; handle it */ { if (rq_data_dir(r) == WRITE) { write_requests++; do_write_request (r); } else /* READ request */ { do_read_request (r); } } /* mark this request as done */ spin_lock (&pdisk->rq_lock); end_that_request_last (r); spin_unlock (&pdisk->rq_lock); /* lock socket's request list */ spin_lock_irqsave (&psoc->request_list_lock, flags); } /* unlock socket's request list */ spin_unlock_irqrestore (&psoc->request_list_lock, flags);}/******************************************************************************* * * * d o _ w r i t e _ r e q u e s t * * * * This routine handles single WRITE request. * * * * Parameters: * * psoc socket pointer * * * * Returns: * * zero if I/O error was encountered, otherwise '1'. * * * *******************************************************************************/staticint do_write_request ( struct request * r ){ DeviceInfo * pdisk = (DeviceInfo *) r->rq_disk->private_data; struct bio * bio; struct gather_t gather; unsigned long total_sectors = r->nr_sectors; int success = 1; /* in case we are going to use gather buffer, mark it as empty */ if ((tffs_sg_bufsize > 0) && (tffs_sg_write != FALSE)) { gather.buf = gather.free = pdisk->pSocket->pCache; gather.size = gather.free_bytes = tffs_sg_bufsize; /* first disk sector # for this request */ gather.start_sector = r->sector; } /* do all bio's of this request */ rq_for_each_bio (bio, r) { if( write_bio(bio, &gather, pdisk) < 0) success = 0; /* I/O error */ } /* flush remaining data (if any) from gather buffer to disk */ if ((tffs_sg_bufsize > 0) && (tffs_sg_write != FALSE) && (gather.free > gather.buf)) { int ns = ((gather.free - gather.buf) >> 9); /* remaining sectors in buf */ if( TffsWrite (pdisk, gather.buf, gather.start_sector, ns) == 0 ) success = 0; /* I/O error */ } /* Note that if we encountered I/O error in the middle of * request processing, we mark the entire request as failed. * Not very smart but hopefully will do for now ... */ end_that_request_first (r, success, total_sectors); return success;}/******************************************************************************* * * * d o _ r e a d _ r e q u e s t * * * * This routine handles single READ request. * * * * Parameters: * * psoc socket pointer * * * * Returns: * * zero if I/O error was encountered, otherwise '1'. * * * *******************************************************************************/staticint do_read_request ( struct request * r ){ DeviceInfo * pdisk = (DeviceInfo *) r->rq_disk->private_data; struct bio * bio; struct scatter_t scatter; unsigned long total_sectors = r->nr_sectors; int success = 1; /* read in data from disk into scatter buffer */ if ((tffs_sg_bufsize > 0) && (tffs_sg_read != FALSE)) { int ns = _MIN(r->nr_sectors, (tffs_sg_bufsize >> 9)); scatter.buf = pdisk->pSocket->pCache; scatter.size = tffs_sg_bufsize; if( TffsRead (pdisk, scatter.buf, r->sector, ns) == 0 ) { success = 0; /* I/O error */ goto out; } scatter.pcurrent = scatter.buf; scatter.remaining_bytes = (ns << 9); scatter.sectors = r->nr_sectors - ns; scatter.start_sector = r->sector + ns; } /* do all bio's of this request */ rq_for_each_bio (bio, r) { if( read_bio(bio, &scatter, pdisk) < 0) success = 0; /* I/O error */ }out: /* Note that if we encountered I/O error in the middle of * request processing, we mark the entire request as failed. * Not very smart but hopefully will do for now ... */ end_that_request_first (r, success, total_sectors); return success;}/******************************************************************************* * * * w r i t e _ b i o * * * * This routine handles single 'struct bio' WRITE operation using gather * * buffer. * * * * Parameters: * * bio pointer to 'struct bio' to WRITE * * gather pointer to gather buffer * * pdisk disk pointer * * * * Returns: * * zero if success otherwise -EIO negative error code * * * *******************************************************************************/staticint write_bio ( struct bio * bio, struct gather_t * gather, DeviceInfo * pdisk ){ struct bio_vec * bv; int i, rc = 0; if ((tffs_sg_bufsize == 0) || (tffs_sg_write == FALSE)) { /* we don't use gather buffer; do one I/O segment at a time */ rc = rw_bio_no_sg (bio, pdisk, WRITE); } else /* use gather buffer */ { bio_for_each_segment (bv, bio, i) { unsigned int n = bv->bv_len; /* bytes in this I/O segment */ char * p, * p2; /* If segment's data resides in high memory, bounce it * down into the temporary low memory buffer. */ p2 = p = __bio_kmap_atomic (bio, i, KM_USER0); for (; n >= gather->free_bytes; ) { /* This I/O segment won't fit into the remaining space in * gather buffer. Copy the part that does fit into gather * buffer (making it full), then flush entire gather buffer * to disk. */ if (gather->free_bytes > 0) { memcpy (gather->free, p, gather->free_bytes); p += gather->free_bytes; n -= gather->free_bytes; } /* flush entire gather buffer to disk */ if( TffsWrite (pdisk, gather->buf, gather->start_sector, (gather->size >> 9)) == 0 ) rc = -EIO; /* I/O error */ /* gather buffer is empty */ gather->free = gather->buf; gather->free_bytes = gather->size; gather->start_sector += (gather->size >> 9); } /* remaining part of this segment fits into gather buffer */ if (n > 0) { memcpy (gather->free, p, n); gather->free += n; gather->free_bytes -= n; } __bio_kunmap_atomic (p2, KM_USER0); } } return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -