📄 stram.c
字号:
}/* * free a reserved region in ST-RAM swap space */static void free_stram_region( unsigned long offset, unsigned long n_pages ){ unsigned short *map = stram_swap_info->swap_map; DPRINTK( "free_stram_region(offset=%lu,n_pages=%lu)\n", offset, n_pages ); if (offset < 1 || offset + n_pages > stram_swap_info->max) { printk( KERN_ERR "free_stram_region: Trying to free non-ST-RAM\n" ); return; } swap_list_lock(); swap_device_lock(stram_swap_info); /* un-reserve the freed pages */ for( ; n_pages > 0; ++offset, --n_pages ) { if (map[offset] != SWAP_MAP_BAD) printk( KERN_ERR "free_stram_region: Swap page %lu was not " "reserved\n", offset ); map[offset] = 0; } /* update swapping meta-data */ if (offset < stram_swap_info->lowest_bit) stram_swap_info->lowest_bit = offset; if (offset+n_pages-1 > stram_swap_info->highest_bit) stram_swap_info->highest_bit = offset+n_pages-1; if (stram_swap_info->prio > swap_info[swap_list.next].prio) swap_list.next = swap_list.head; nr_swap_pages += n_pages; swap_device_unlock(stram_swap_info); swap_list_unlock();}/* ------------------------------------------------------------------------ *//* Utility Functions for Swapping *//* ------------------------------------------------------------------------ *//* is addr in some of the allocated regions? */static int in_some_region(void *addr){ BLOCK *p; for( p = alloc_list; p; p = p->next ) { if (p->start <= addr && addr < p->start + p->size) return( 1 ); } return( 0 );}static unsigned long find_free_region(unsigned long n_pages, unsigned long *total_free, unsigned long *region_free){ unsigned short *map = stram_swap_info->swap_map; unsigned long max = stram_swap_info->max; unsigned long head, tail, max_start; long nfree, max_free; /* first scan the swap space for a suitable place for the allocation */ head = 1; max_start = 0; max_free = -1; *total_free = 0; start_over: /* increment tail until final window size reached, and count free pages */ nfree = 0; for( tail = head; tail-head < n_pages && tail < max; ++tail ) { if (map[tail] == SWAP_MAP_BAD) { head = tail+1; goto start_over; } if (!map[tail]) { ++nfree; ++*total_free; } } if (tail-head < n_pages) goto out; if (nfree > max_free) { max_start = head; max_free = nfree; if (max_free >= n_pages) /* don't need more free pages... :-) */ goto out; } /* now shift the window and look for the area where as much pages as * possible are free */ while( tail < max ) { nfree -= (map[head++] == 0); if (map[tail] == SWAP_MAP_BAD) { head = tail+1; goto start_over; } if (!map[tail]) { ++nfree; ++*total_free; } ++tail; if (nfree > max_free) { max_start = head; max_free = nfree; if (max_free >= n_pages) /* don't need more free pages... :-) */ goto out; } } out: if (max_free < 0) { printk( KERN_NOTICE "get_stram_region: ST-RAM too full or fragmented " "-- can't allocate %lu pages\n", n_pages ); return( 0 ); } *region_free = max_free; return( max_start );}/* setup parameters from command line */void __init stram_swap_setup(char *str, int *ints){ if (ints[0] >= 1) max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK;}/* ------------------------------------------------------------------------ *//* ST-RAM device *//* ------------------------------------------------------------------------ */static int stram_blocksizes[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4096 };static int stram_sizes[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };static int refcnt = 0;static void do_stram_request(request_queue_t *q){ void *start; unsigned long len; while (1) { INIT_REQUEST; start = swap_start + (CURRENT->sector << 9); len = CURRENT->current_nr_sectors << 9; if ((start + len) > swap_end) { printk( KERN_ERR "stram: bad access beyond end of device: " "block=%ld, count=%ld\n", CURRENT->sector, CURRENT->current_nr_sectors ); end_request( 0 ); continue; } if (CURRENT->cmd == READ) { memcpy(CURRENT->buffer, start, len);#ifdef DO_PROC stat_swap_read += N_PAGES(len);#endif } else { memcpy(start, CURRENT->buffer, len);#ifdef DO_PROC stat_swap_write += N_PAGES(len);#endif } end_request( 1 ); }}static int stram_open( struct inode *inode, struct file *filp ){ if (filp != MAGIC_FILE_P) { printk( KERN_NOTICE "Only kernel can open ST-RAM device\n" ); return( -EPERM ); } if (MINOR(inode->i_rdev) != STRAM_MINOR) return( -ENXIO ); if (refcnt) return( -EBUSY ); ++refcnt; return( 0 );}static int stram_release( struct inode *inode, struct file *filp ){ if (filp != MAGIC_FILE_P) { printk( KERN_NOTICE "Only kernel can close ST-RAM device\n" ); return( -EPERM ); } if (refcnt > 0) --refcnt; return( 0 );}static struct block_device_operations stram_fops = { open: stram_open, release: stram_release,};int __init stram_device_init(void){ if (!MACH_IS_ATARI) /* no point in initializing this, I hope */ return( -ENXIO ); if (!max_swap_size) /* swapping not enabled */ return( -ENXIO ); if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) { printk( KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR ); return( -ENXIO ); } blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request); blksize_size[STRAM_MAJOR] = stram_blocksizes; stram_sizes[STRAM_MINOR] = (swap_end - swap_start)/1024; blk_size[STRAM_MAJOR] = stram_sizes; register_disk(NULL, MKDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops, (swap_end-swap_start)>>9); return( 0 );}#endif /* CONFIG_STRAM_SWAP *//* ------------------------------------------------------------------------ *//* Misc Utility Functions *//* ------------------------------------------------------------------------ *//* reserve a range of pages */static void reserve_region(void *start, void *end){ reserve_bootmem (virt_to_phys(start), end - start);}/* ------------------------------------------------------------------------ *//* Region Management *//* ------------------------------------------------------------------------ *//* insert a region into the alloced list (sorted) */static BLOCK *add_region( void *addr, unsigned long size ){ BLOCK **p, *n = NULL; int i; for( i = 0; i < N_STATIC_BLOCKS; ++i ) { if (static_blocks[i].flags & BLOCK_FREE) { n = &static_blocks[i]; n->flags = 0; break; } } if (!n && mem_init_done) { /* if statics block pool exhausted and we can call kmalloc() already * (after mem_init()), try that */ n = kmalloc( sizeof(BLOCK), GFP_KERNEL ); if (n) n->flags = BLOCK_KMALLOCED; } if (!n) { printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" ); return( NULL ); } n->start = addr; n->size = size; for( p = &alloc_list; *p; p = &((*p)->next) ) if ((*p)->start > addr) break; n->next = *p; *p = n; return( n );}/* find a region (by start addr) in the alloced list */static BLOCK *find_region( void *addr ){ BLOCK *p; for( p = alloc_list; p; p = p->next ) { if (p->start == addr) return( p ); if (p->start > addr) break; } return( NULL );}/* remove a block from the alloced list */static int remove_region( BLOCK *block ){ BLOCK **p; for( p = &alloc_list; *p; p = &((*p)->next) ) if (*p == block) break; if (!*p) return( 0 ); *p = block->next; if (block->flags & BLOCK_KMALLOCED) kfree( block ); else block->flags |= BLOCK_FREE; return( 1 );}/* ------------------------------------------------------------------------ *//* /proc statistics file stuff *//* ------------------------------------------------------------------------ */#ifdef DO_PROC#define PRINT_PROC(fmt,args...) len += sprintf( buf+len, fmt, ##args )int get_stram_list( char *buf ){ int len = 0; BLOCK *p;#ifdef CONFIG_STRAM_SWAP int i; unsigned short *map = stram_swap_info->swap_map; unsigned long max = stram_swap_info->max; unsigned free = 0, used = 0, rsvd = 0;#endif#ifdef CONFIG_STRAM_SWAP if (max_swap_size) { for( i = 1; i < max; ++i ) { if (!map[i]) ++free; else if (map[i] == SWAP_MAP_BAD) ++rsvd; else ++used; } PRINT_PROC( "Total ST-RAM: %8u kB\n" "Total ST-RAM swap: %8lu kB\n" "Free swap: %8u kB\n" "Used swap: %8u kB\n" "Allocated swap: %8u kB\n" "Swap Reads: %8u\n" "Swap Writes: %8u\n" "Swap Forced Reads: %8u\n", (stram_end - stram_start) >> 10, (max-1) << (PAGE_SHIFT-10), free << (PAGE_SHIFT-10), used << (PAGE_SHIFT-10), rsvd << (PAGE_SHIFT-10), stat_swap_read, stat_swap_write, stat_swap_force ); } else {#endif PRINT_PROC( "ST-RAM swapping disabled\n" ); PRINT_PROC("Total ST-RAM: %8u kB\n", (stram_end - stram_start) >> 10);#ifdef CONFIG_STRAM_SWAP }#endif PRINT_PROC( "Allocated regions:\n" ); for( p = alloc_list; p; p = p->next ) { if (len + 50 >= PAGE_SIZE) break; PRINT_PROC("0x%08lx-0x%08lx: %s (", virt_to_phys(p->start), virt_to_phys(p->start+p->size-1), p->owner); if (p->flags & BLOCK_GFP) PRINT_PROC( "page-alloced)\n" ); else if (p->flags & BLOCK_INSWAP) PRINT_PROC( "in swap)\n" ); else PRINT_PROC( "??)\n" ); } return( len );}#endif/* * Local variables: * c-indent-level: 4 * tab-width: 4 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -