⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swapfile.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	int i, j, prev;	int error;	static int least_priority = 0;	union swap_header *swap_header = 0;	int swap_header_version;	int nr_good_pages = 0;	unsigned long maxpages = 1;	int swapfilesize;	struct block_device *bdev = NULL;	unsigned short *swap_map;		if (!capable(CAP_SYS_ADMIN))		return -EPERM;	lock_kernel();	swap_list_lock();	p = swap_info;	for (type = 0 ; type < nr_swapfiles ; type++,p++)		if (!(p->flags & SWP_USED))			break;	error = -EPERM;	if (type >= MAX_SWAPFILES) {		swap_list_unlock();		goto out;	}	if (type >= nr_swapfiles)		nr_swapfiles = type+1;	p->flags = SWP_USED;	p->swap_file = NULL;	p->swap_vfsmnt = NULL;	p->swap_device = 0;	p->swap_map = NULL;	p->lowest_bit = 0;	p->highest_bit = 0;	p->cluster_nr = 0;	p->sdev_lock = SPIN_LOCK_UNLOCKED;	p->next = -1;	if (swap_flags & SWAP_FLAG_PREFER) {		p->prio =		  (swap_flags & SWAP_FLAG_PRIO_MASK)>>SWAP_FLAG_PRIO_SHIFT;	} else {		p->prio = --least_priority;	}	swap_list_unlock();	error = user_path_walk(specialfile, &nd);	if (error)		goto bad_swap_2;	p->swap_file = nd.dentry;	p->swap_vfsmnt = nd.mnt;	swap_inode = nd.dentry->d_inode;	error = -EINVAL;	if (S_ISBLK(swap_inode->i_mode)) {		kdev_t dev = swap_inode->i_rdev;		struct block_device_operations *bdops;		devfs_handle_t de;		p->swap_device = dev;		set_blocksize(dev, PAGE_SIZE);				bd_acquire(swap_inode);		bdev = swap_inode->i_bdev;		de = devfs_get_handle_from_inode(swap_inode);		bdops = devfs_get_ops(de);  /*  Increments module use count  */		if (bdops) bdev->bd_op = bdops;		error = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_SWAP);		devfs_put_ops(de);/*Decrement module use count now we're safe*/		if (error)			goto bad_swap_2;		set_blocksize(dev, PAGE_SIZE);		error = -ENODEV;		if (!dev || (blk_size[MAJOR(dev)] &&		     !blk_size[MAJOR(dev)][MINOR(dev)]))			goto bad_swap;		swapfilesize = 0;		if (blk_size[MAJOR(dev)])			swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]				>> (PAGE_SHIFT - 10);	} else if (S_ISREG(swap_inode->i_mode))		swapfilesize = swap_inode->i_size >> PAGE_SHIFT;	else		goto bad_swap;	error = -EBUSY;	for (i = 0 ; i < nr_swapfiles ; i++) {		struct swap_info_struct *q = &swap_info[i];		if (i == type || !q->swap_file)			continue;		if (swap_inode->i_mapping == q->swap_file->d_inode->i_mapping)			goto bad_swap;	}	swap_header = (void *) __get_free_page(GFP_USER);	if (!swap_header) {		printk("Unable to start swapping: out of memory :-)\n");		error = -ENOMEM;		goto bad_swap;	}	lock_page(virt_to_page(swap_header));	rw_swap_page_nolock(READ, SWP_ENTRY(type,0), (char *) swap_header);	if (!memcmp("SWAP-SPACE",swap_header->magic.magic,10))		swap_header_version = 1;	else if (!memcmp("SWAPSPACE2",swap_header->magic.magic,10))		swap_header_version = 2;	else {		printk("Unable to find swap-space signature\n");		error = -EINVAL;		goto bad_swap;	}		switch (swap_header_version) {	case 1:		memset(((char *) swap_header)+PAGE_SIZE-10,0,10);		j = 0;		p->lowest_bit = 0;		p->highest_bit = 0;		for (i = 1 ; i < 8*PAGE_SIZE ; i++) {			if (test_bit(i,(char *) swap_header)) {				if (!p->lowest_bit)					p->lowest_bit = i;				p->highest_bit = i;				maxpages = i+1;				j++;			}		}		nr_good_pages = j;		p->swap_map = vmalloc(maxpages * sizeof(short));		if (!p->swap_map) {			error = -ENOMEM;					goto bad_swap;		}		for (i = 1 ; i < maxpages ; i++) {			if (test_bit(i,(char *) swap_header))				p->swap_map[i] = 0;			else				p->swap_map[i] = SWAP_MAP_BAD;		}		break;	case 2:		/* Check the swap header's sub-version and the size of                   the swap file and bad block lists */		if (swap_header->info.version != 1) {			printk(KERN_WARNING			       "Unable to handle swap header version %d\n",			       swap_header->info.version);			error = -EINVAL;			goto bad_swap;		}		p->lowest_bit  = 1;		maxpages = SWP_OFFSET(SWP_ENTRY(0,~0UL)) - 1;		if (maxpages > swap_header->info.last_page)			maxpages = swap_header->info.last_page;		p->highest_bit = maxpages - 1;		error = -EINVAL;		if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES)			goto bad_swap;				/* OK, set up the swap map and apply the bad block list */		if (!(p->swap_map = vmalloc(maxpages * sizeof(short)))) {			error = -ENOMEM;			goto bad_swap;		}		error = 0;		memset(p->swap_map, 0, maxpages * sizeof(short));		for (i=0; i<swap_header->info.nr_badpages; i++) {			int page = swap_header->info.badpages[i];			if (page <= 0 || page >= swap_header->info.last_page)				error = -EINVAL;			else				p->swap_map[page] = SWAP_MAP_BAD;		}		nr_good_pages = swap_header->info.last_page -				swap_header->info.nr_badpages -				1 /* header page */;		if (error) 			goto bad_swap;	}		if (swapfilesize && maxpages > swapfilesize) {		printk(KERN_WARNING		       "Swap area shorter than signature indicates\n");		error = -EINVAL;		goto bad_swap;	}	if (!nr_good_pages) {		printk(KERN_WARNING "Empty swap-file\n");		error = -EINVAL;		goto bad_swap;	}	p->swap_map[0] = SWAP_MAP_BAD;	swap_list_lock();	swap_device_lock(p);	p->max = maxpages;	p->flags = SWP_WRITEOK;	p->pages = nr_good_pages;	nr_swap_pages += nr_good_pages;	total_swap_pages += nr_good_pages;	printk(KERN_INFO "Adding Swap: %dk swap-space (priority %d)\n",	       nr_good_pages<<(PAGE_SHIFT-10), p->prio);	/* insert swap space into swap_list: */	prev = -1;	for (i = swap_list.head; i >= 0; i = swap_info[i].next) {		if (p->prio >= swap_info[i].prio) {			break;		}		prev = i;	}	p->next = i;	if (prev < 0) {		swap_list.head = swap_list.next = p - swap_info;	} else {		swap_info[prev].next = p - swap_info;	}	swap_device_unlock(p);	swap_list_unlock();	error = 0;	goto out;bad_swap:	if (bdev)		blkdev_put(bdev, BDEV_SWAP);bad_swap_2:	swap_list_lock();	swap_map = p->swap_map;	nd.mnt = p->swap_vfsmnt;	nd.dentry = p->swap_file;	p->swap_device = 0;	p->swap_file = NULL;	p->swap_vfsmnt = NULL;	p->swap_map = NULL;	p->flags = 0;	if (!(swap_flags & SWAP_FLAG_PREFER))		++least_priority;	swap_list_unlock();	if (swap_map)		vfree(swap_map);	path_release(&nd);out:	if (swap_header)		free_page((long) swap_header);	unlock_kernel();	return error;}void si_swapinfo(struct sysinfo *val){	unsigned int i;	unsigned long nr_to_be_unused = 0;	swap_list_lock();	for (i = 0; i < nr_swapfiles; i++) {		unsigned int j;		if (swap_info[i].flags != SWP_USED)			continue;		for (j = 0; j < swap_info[i].max; ++j) {			switch (swap_info[i].swap_map[j]) {				case 0:				case SWAP_MAP_BAD:					continue;				default:					nr_to_be_unused++;			}		}	}	val->freeswap = nr_swap_pages + nr_to_be_unused;	val->totalswap = total_swap_pages + nr_to_be_unused;	swap_list_unlock();}/* * Verify that a swap entry is valid and increment its swap map count. * * Note: if swap_map[] reaches SWAP_MAP_MAX the entries are treated as * "permanent", but will be reclaimed by the next swapoff. */int swap_duplicate(swp_entry_t entry){	struct swap_info_struct * p;	unsigned long offset, type;	int result = 0;	type = SWP_TYPE(entry);	if (type >= nr_swapfiles)		goto bad_file;	p = type + swap_info;	offset = SWP_OFFSET(entry);	swap_device_lock(p);	if (offset < p->max && p->swap_map[offset]) {		if (p->swap_map[offset] < SWAP_MAP_MAX - 1) {			p->swap_map[offset]++;			result = 1;		} else if (p->swap_map[offset] <= SWAP_MAP_MAX) {			if (swap_overflow++ < 5)				printk(KERN_WARNING "swap_dup: swap entry overflow\n");			p->swap_map[offset] = SWAP_MAP_MAX;			result = 1;		}	}	swap_device_unlock(p);out:	return result;bad_file:	printk(KERN_ERR "swap_dup: %s%08lx\n", Bad_file, entry.val);	goto out;}/* * Page lock needs to be held in all cases to prevent races with * swap file deletion. */int swap_count(struct page *page){	struct swap_info_struct * p;	unsigned long offset, type;	swp_entry_t entry;	int retval = 0;	entry.val = page->index;	if (!entry.val)		goto bad_entry;	type = SWP_TYPE(entry);	if (type >= nr_swapfiles)		goto bad_file;	p = type + swap_info;	offset = SWP_OFFSET(entry);	if (offset >= p->max)		goto bad_offset;	if (!p->swap_map[offset])		goto bad_unused;	retval = p->swap_map[offset];out:	return retval;bad_entry:	printk(KERN_ERR "swap_count: null entry!\n");	goto out;bad_file:	printk(KERN_ERR "swap_count: %s%08lx\n", Bad_file, entry.val);	goto out;bad_offset:	printk(KERN_ERR "swap_count: %s%08lx\n", Bad_offset, entry.val);	goto out;bad_unused:	printk(KERN_ERR "swap_count: %s%08lx\n", Unused_offset, entry.val);	goto out;}/* * Prior swap_duplicate protects against swap device deletion. */void get_swaphandle_info(swp_entry_t entry, unsigned long *offset, 			kdev_t *dev, struct inode **swapf){	unsigned long type;	struct swap_info_struct *p;	type = SWP_TYPE(entry);	if (type >= nr_swapfiles) {		printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_file, entry.val);		return;	}	p = &swap_info[type];	*offset = SWP_OFFSET(entry);	if (*offset >= p->max && *offset != 0) {		printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_offset, entry.val);		return;	}	if (p->swap_map && !p->swap_map[*offset]) {		printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_offset, entry.val);		return;	}	if (!(p->flags & SWP_USED)) {		printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_file, entry.val);		return;	}	if (p->swap_device) {		*dev = p->swap_device;	} else if (p->swap_file) {		*swapf = p->swap_file->d_inode;	} else {		printk(KERN_ERR "rw_swap_page: no swap file or device\n");	}	return;}/* * swap_device_lock prevents swap_map being freed. Don't grab an extra * reference on the swaphandle, it doesn't matter if it becomes unused. */int valid_swaphandles(swp_entry_t entry, unsigned long *offset){	int ret = 0, i = 1 << page_cluster;	unsigned long toff;	struct swap_info_struct *swapdev = SWP_TYPE(entry) + swap_info;	if (!page_cluster)	/* no readahead */		return 0;	toff = (SWP_OFFSET(entry) >> page_cluster) << page_cluster;	if (!toff)		/* first page is swap header */		toff++, i--;	*offset = toff;	swap_device_lock(swapdev);	do {		/* Don't read-ahead past the end of the swap area */		if (toff >= swapdev->max)			break;		/* Don't read in free or bad pages */		if (!swapdev->swap_map[toff])			break;		if (swapdev->swap_map[toff] == SWAP_MAP_BAD)			break;		toff++;		ret++;	} while (--i);	swap_device_unlock(swapdev);	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -