亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? shmem.c

?? ARM 嵌入式 系統 設計與實例開發 實驗教材 二源碼
?? C
?? 第 1 頁 / 共 3 頁
字號:
/* * Resizable virtual memory filesystem for Linux. * * Copyright (C) 2000 Linus Torvalds. *		 2000 Transmeta Corp. *		 2000-2001 Christoph Rohland *		 2000-2001 SAP AG *  * This file is released under the GPL. *//* * This virtual memory filesystem is heavily based on the ramfs. It * extends ramfs by the ability to use swap and honor resource limits * which makes it a completely usable filesystem. */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/devfs_fs_kernel.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/file.h>#include <linux/swap.h>#include <linux/pagemap.h>#include <linux/string.h>#include <linux/locks.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>/* This magic number is used in glibc for posix shared memory */#define TMPFS_MAGIC	0x01021994#define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))#define SHMEM_SB(sb) (&sb->u.shmem_sb)static struct super_operations shmem_ops;static struct address_space_operations shmem_aops;static struct file_operations shmem_file_operations;static struct inode_operations shmem_inode_operations;static struct file_operations shmem_dir_operations;static struct inode_operations shmem_dir_inode_operations;static struct vm_operations_struct shmem_vm_ops;LIST_HEAD (shmem_inodes);static spinlock_t shmem_ilock = SPIN_LOCK_UNLOCKED;atomic_t shmem_nrpages = ATOMIC_INIT(0); /* Not used right now */#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512)/* * shmem_recalc_inode - recalculate the size of an inode * * @inode: inode to recalc * @swap:  additional swap pages freed externally * * We have to calculate the free blocks since the mm can drop pages * behind our back * * But we know that normally * inodes->i_blocks/BLOCKS_PER_PAGE ==  * 			inode->i_mapping->nrpages + info->swapped * * So the mm freed  * inodes->i_blocks/BLOCKS_PER_PAGE -  * 			(inode->i_mapping->nrpages + info->swapped) * * It has to be called with the spinlock held. */static void shmem_recalc_inode(struct inode * inode){	unsigned long freed;	freed = (inode->i_blocks/BLOCKS_PER_PAGE) -		(inode->i_mapping->nrpages + SHMEM_I(inode)->swapped);	if (freed){		struct shmem_sb_info * sbinfo = SHMEM_SB(inode->i_sb);		inode->i_blocks -= freed*BLOCKS_PER_PAGE;		spin_lock (&sbinfo->stat_lock);		sbinfo->free_blocks += freed;		spin_unlock (&sbinfo->stat_lock);	}}/* * shmem_swp_entry - find the swap vector position in the info structure * * @info:  info structure for the inode * @index: index of the page to find * @page:  optional page to add to the structure. Has to be preset to *         all zeros * * If there is no space allocated yet it will return -ENOMEM when * page == 0 else it will use the page for the needed block. * * returns -EFBIG if the index is too big. * * * The swap vector is organized the following way: * * There are SHMEM_NR_DIRECT entries directly stored in the * shmem_inode_info structure. So small files do not need an addional * allocation. * * For pages with index > SHMEM_NR_DIRECT there is the pointer * i_indirect which points to a page which holds in the first half * doubly indirect blocks, in the second half triple indirect blocks: * * For an artificial ENTRIES_PER_PAGE = 4 this would lead to the * following layout (for SHMEM_NR_DIRECT == 16): * * i_indirect -> dir --> 16-19 * 	      |	     +-> 20-23 * 	      | * 	      +-->dir2 --> 24-27 * 	      |	       +-> 28-31 * 	      |	       +-> 32-35 * 	      |	       +-> 36-39 * 	      | * 	      +-->dir3 --> 40-43 * 	       	       +-> 44-47 * 	      	       +-> 48-51 * 	      	       +-> 52-55 */#define SHMEM_MAX_BLOCKS (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * ENTRIES_PER_PAGE/2*(ENTRIES_PER_PAGE+1))static swp_entry_t * shmem_swp_entry (struct shmem_inode_info *info, unsigned long index, unsigned long page) {	unsigned long offset;	void **dir;	if (index < SHMEM_NR_DIRECT)		return info->i_direct+index;	index -= SHMEM_NR_DIRECT;	offset = index % ENTRIES_PER_PAGE;	index /= ENTRIES_PER_PAGE;	if (!info->i_indirect) {		info->i_indirect = (void *) page;		return ERR_PTR(-ENOMEM);	}	dir = info->i_indirect + index;	if (index >= ENTRIES_PER_PAGE/2) {		index -= ENTRIES_PER_PAGE/2;		dir = info->i_indirect + ENTRIES_PER_PAGE/2 			+ index/ENTRIES_PER_PAGE;		index %= ENTRIES_PER_PAGE;		if(!*dir) {			*dir = (void *) page;			/* We return since we will need another page                           in the next step */			return ERR_PTR(-ENOMEM);		}		dir = ((void **)*dir) + index;	}	if (!*dir) {		if (!page)			return ERR_PTR(-ENOMEM);		*dir = (void *)page;	}	return ((swp_entry_t *)*dir) + offset;}/* * shmem_alloc_entry - get the position of the swap entry for the *                     page. If it does not exist allocate the entry * * @info:	info structure for the inode * @index:	index of the page to find */static inline swp_entry_t * shmem_alloc_entry (struct shmem_inode_info *info, unsigned long index){	unsigned long page = 0;	swp_entry_t * res;	if (index >= SHMEM_MAX_BLOCKS)		return ERR_PTR(-EFBIG);	if (info->next_index <= index)		info->next_index = index + 1;	while ((res = shmem_swp_entry(info,index,page)) == ERR_PTR(-ENOMEM)) {		page = get_zeroed_page(GFP_USER);		if (!page)			break;	}	return res;}/* * shmem_free_swp - free some swap entries in a directory * * @dir:   pointer to the directory * @count: number of entries to scan */static int shmem_free_swp(swp_entry_t *dir, unsigned int count){	swp_entry_t *ptr, entry;	int freed = 0;	for (ptr = dir; ptr < dir + count; ptr++) {		if (!ptr->val)			continue;		entry = *ptr;		*ptr = (swp_entry_t){0};		freed++;		free_swap_and_cache(entry);	}	return freed;}/* * shmem_truncate_direct - free the swap entries of a whole doubly *                         indirect block * * @dir:	pointer to the pointer to the block * @start:	offset to start from (in pages) * @len:	how many pages are stored in this block * * Returns the number of freed swap entries. */static inline unsigned long shmem_truncate_direct(swp_entry_t *** dir, unsigned long start, unsigned long len) {	swp_entry_t **last, **ptr;	unsigned long off, freed = 0; 	if (!*dir)		return 0;	last = *dir + (len + ENTRIES_PER_PAGE-1) / ENTRIES_PER_PAGE;	off = start % ENTRIES_PER_PAGE;	for (ptr = *dir + start/ENTRIES_PER_PAGE; ptr < last; ptr++) {		if (!*ptr) {			off = 0;			continue;		}		if (!off) {			freed += shmem_free_swp(*ptr, ENTRIES_PER_PAGE);			free_page ((unsigned long) *ptr);			*ptr = 0;		} else {			freed += shmem_free_swp(*ptr+off,ENTRIES_PER_PAGE-off);			off = 0;		}	}		if (!start) {		free_page((unsigned long) *dir);		*dir = 0;	}	return freed;}/* * shmem_truncate_indirect - truncate an inode * * @info:  the info structure of the inode * @index: the index to truncate * * This function locates the last doubly indirect block and calls * then shmem_truncate_direct to do the real work */static inline unsigned longshmem_truncate_indirect(struct shmem_inode_info *info, unsigned long index){	swp_entry_t ***base;	unsigned long baseidx, len, start;	unsigned long max = info->next_index-1;	if (max < SHMEM_NR_DIRECT) {		info->next_index = index;		return shmem_free_swp(info->i_direct + index,				      SHMEM_NR_DIRECT - index);	}	if (max < ENTRIES_PER_PAGE * ENTRIES_PER_PAGE/2 + SHMEM_NR_DIRECT) {		max -= SHMEM_NR_DIRECT;		base = (swp_entry_t ***) &info->i_indirect;		baseidx = SHMEM_NR_DIRECT;		len = max+1;	} else {		max -= ENTRIES_PER_PAGE*ENTRIES_PER_PAGE/2+SHMEM_NR_DIRECT;		if (max >= ENTRIES_PER_PAGE*ENTRIES_PER_PAGE*ENTRIES_PER_PAGE/2)			BUG();		baseidx = max & ~(ENTRIES_PER_PAGE*ENTRIES_PER_PAGE-1);		base = (swp_entry_t ***) info->i_indirect + ENTRIES_PER_PAGE/2 + baseidx/ENTRIES_PER_PAGE/ENTRIES_PER_PAGE ;		len = max - baseidx + 1;		baseidx += ENTRIES_PER_PAGE*ENTRIES_PER_PAGE/2+SHMEM_NR_DIRECT;	}	if (index > baseidx) {		info->next_index = index;		start = index - baseidx;	} else {		info->next_index = baseidx;		start = 0;	}	return shmem_truncate_direct(base, start, len);}static void shmem_truncate (struct inode * inode){	unsigned long index;	unsigned long freed = 0;	struct shmem_inode_info * info = SHMEM_I(inode);	down(&info->sem);	inode->i_ctime = inode->i_mtime = CURRENT_TIME;	spin_lock (&info->lock);	index = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;	while (index < info->next_index) 		freed += shmem_truncate_indirect(info, index);	info->swapped -= freed;	shmem_recalc_inode(inode);	spin_unlock (&info->lock);	up(&info->sem);}static void shmem_delete_inode(struct inode * inode){	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);	inode->i_size = 0;	if (inode->i_op->truncate == shmem_truncate){ 		spin_lock (&shmem_ilock);		list_del (&SHMEM_I(inode)->list);		spin_unlock (&shmem_ilock);		shmem_truncate (inode);	}	spin_lock (&sbinfo->stat_lock);	sbinfo->free_inodes++;	spin_unlock (&sbinfo->stat_lock);	clear_inode(inode);}static int shmem_clear_swp (swp_entry_t entry, swp_entry_t *ptr, int size) {	swp_entry_t *test;	for (test = ptr; test < ptr + size; test++) {		if (test->val == entry.val) {			swap_free (entry);			*test = (swp_entry_t) {0};			return test - ptr;		}	}	return -1;}static int shmem_unuse_inode (struct shmem_inode_info *info, swp_entry_t entry, struct page *page){	swp_entry_t *ptr;	unsigned long idx;	int offset;		idx = 0;	spin_lock (&info->lock);	offset = shmem_clear_swp (entry, info->i_direct, SHMEM_NR_DIRECT);	if (offset >= 0)		goto found;	for (idx = SHMEM_NR_DIRECT; idx < info->next_index; 	     idx += ENTRIES_PER_PAGE) {		ptr = shmem_swp_entry(info, idx, 0);		if (IS_ERR(ptr))			continue;		offset = shmem_clear_swp (entry, ptr, ENTRIES_PER_PAGE);		if (offset >= 0)			goto found;	}	spin_unlock (&info->lock);	return 0;found:	delete_from_swap_cache(page);	add_to_page_cache(page, info->inode->i_mapping, offset + idx);	SetPageDirty(page);	SetPageUptodate(page);	info->swapped--;	spin_unlock(&info->lock);	return 1;}/* * unuse_shmem() search for an eventually swapped out shmem page. */void shmem_unuse(swp_entry_t entry, struct page *page){	struct list_head *p;	struct shmem_inode_info * info;	spin_lock (&shmem_ilock);	list_for_each(p, &shmem_inodes) {		info = list_entry(p, struct shmem_inode_info, list);		if (shmem_unuse_inode(info, entry, page))			break;	}	spin_unlock (&shmem_ilock);}/* * Move the page from the page cache to the swap cache. * * The page lock prevents multiple occurences of shmem_writepage at * once.  We still need to guard against racing with * shmem_getpage_locked().   */static int shmem_writepage(struct page * page){	struct shmem_inode_info *info;	swp_entry_t *entry, swap;	struct address_space *mapping;	unsigned long index;	struct inode *inode;	if (!PageLocked(page))		BUG();	if (!PageLaunder(page))		return fail_writepage(page);	mapping = page->mapping;	index = page->index;	inode = mapping->host;	info = SHMEM_I(inode);	if (info->locked)		return fail_writepage(page);getswap:	swap = get_swap_page();	if (!swap.val)		return fail_writepage(page);	spin_lock(&info->lock);	entry = shmem_swp_entry(info, index, 0);	if (IS_ERR(entry))	/* this had been allocated on page allocation */		BUG();	shmem_recalc_inode(inode);	if (entry->val)		BUG();	/* Remove it from the page cache */	remove_inode_page(page);	page_cache_release(page);	/* Add it to the swap cache */	if (add_to_swap_cache(page, swap) != 0) {		/*		 * Raced with "speculative" read_swap_cache_async.		 * Add page back to page cache, unref swap, try again.		 */		add_to_page_cache_locked(page, mapping, index);		spin_unlock(&info->lock);		swap_free(swap);		goto getswap;	}	*entry = swap;	info->swapped++;	spin_unlock(&info->lock);	SetPageUptodate(page);	set_page_dirty(page);	UnlockPage(page);	return 0;}/* * shmem_getpage_locked - either get the page from swap or allocate a new one * * If we allocate a new one we do not mark it dirty. That's up to the * vm. If we swap it in we mark it dirty since we also free the swap * entry since a page cannot live in both the swap and page cache * * Called with the inode locked, so it cannot race with itself, but we * still need to guard against racing with shm_writepage(), which might * be trying to move the page to the swap cache as we run. */static struct page * shmem_getpage_locked(struct shmem_inode_info *info, struct inode * inode, unsigned long idx){	struct address_space * mapping = inode->i_mapping;	struct shmem_sb_info *sbinfo;	struct page * page;	swp_entry_t *entry;repeat:	page = find_lock_page(mapping, idx);	if (page)		return page;	entry = shmem_alloc_entry (info, idx);	if (IS_ERR(entry))		return (void *)entry;	spin_lock (&info->lock);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
久久精品一区二区三区四区| 国产精品亚洲第一| 欧美在线观看禁18| 亚洲国产精品久久久男人的天堂| 欧美美女视频在线观看| 日本在线不卡一区| 久久免费偷拍视频| 91丨九色porny丨蝌蚪| 一二三区精品视频| 精品捆绑美女sm三区| 国产激情精品久久久第一区二区 | 精品久久久久久久人人人人传媒| 激情综合一区二区三区| 久久精品夜夜夜夜久久| 91片黄在线观看| 日韩av电影一区| 国产精品日韩成人| 欧日韩精品视频| 激情都市一区二区| 亚洲欧洲综合另类在线| 3751色影院一区二区三区| 狠狠色丁香婷综合久久| 亚洲欧洲一区二区在线播放| 欧美日韩精品一区二区| 激情综合色丁香一区二区| 中文字幕日韩一区二区| 9191成人精品久久| 成人免费高清视频在线观看| 亚洲国产日韩av| 久久精品视频免费观看| 欧美色涩在线第一页| 国产一区二区免费视频| 亚洲国产成人av网| 国产日韩三级在线| 欧美日韩国产成人在线免费| 北条麻妃一区二区三区| 男女视频一区二区| 亚洲资源在线观看| 国产亚洲1区2区3区| 欧美日韩亚洲综合一区| 波多野结衣中文字幕一区| 免费国产亚洲视频| 亚洲一区二区免费视频| 国产欧美视频一区二区三区| 欧美日韩aaaaa| 97超碰欧美中文字幕| 久久99精品视频| 亚洲成人av电影| 中文字幕日韩av资源站| 久久久www免费人成精品| 欧美日韩午夜影院| 色哟哟欧美精品| 国产999精品久久久久久| 偷窥国产亚洲免费视频| 国产精品色呦呦| 久久亚洲春色中文字幕久久久| 欧美精品日韩一本| 欧美中文字幕久久| 91猫先生在线| 91一区二区在线| 97国产一区二区| 99久久婷婷国产综合精品| 国产91精品在线观看| 国产精品中文字幕一区二区三区| 男女性色大片免费观看一区二区 | 丝袜亚洲另类丝袜在线| 亚洲欧美激情小说另类| 国产精品三级av在线播放| 精品国一区二区三区| 日韩视频中午一区| 日韩欧美中文字幕公布| 在线不卡a资源高清| 欧美日韩一区视频| 欧美日韩精品欧美日韩精品| 欧美影片第一页| 欧美色区777第一页| 欧美性生活一区| 91麻豆精品国产91久久久资源速度| 欧美综合一区二区| 欧洲人成人精品| 欧美伦理影视网| 日韩一级黄色片| 久久久噜噜噜久久人人看| 国产亚洲欧美在线| 日本一区二区三级电影在线观看| 久久久亚洲精华液精华液精华液 | 亚洲欧美偷拍三级| 亚洲码国产岛国毛片在线| 亚洲欧美日韩国产一区二区三区| 亚洲人成人一区二区在线观看| 最新日韩在线视频| 亚洲精品中文字幕在线观看| 亚洲国产精品久久人人爱蜜臀| 日本成人在线网站| 国产在线精品一区二区不卡了| 国产精品自拍一区| 色菇凉天天综合网| 在线成人av网站| 精品1区2区在线观看| 日本一区二区免费在线观看视频 | 久久久久久久久99精品| 中文在线一区二区| 亚洲国产精品久久久男人的天堂 | 久久久精品黄色| 亚洲美女视频在线观看| 日韩电影一二三区| 大尺度一区二区| 欧美亚洲一区三区| 精品欧美一区二区久久| 国产精品伦理在线| 首页综合国产亚洲丝袜| 国产成人亚洲综合a∨猫咪| 色婷婷久久综合| 欧美变态口味重另类| 国产精品激情偷乱一区二区∴| 亚洲成av人片一区二区三区| 久久99久久久久久久久久久| 99久久精品国产毛片| 日韩三区在线观看| 亚洲人成亚洲人成在线观看图片 | 精品午夜久久福利影院| 色香色香欲天天天影视综合网 | 久久综合色之久久综合| 亚洲三级在线观看| 国产美女久久久久| 欧美日本免费一区二区三区| 国产精品情趣视频| 麻豆国产精品777777在线| 波多野结衣中文一区| 精品欧美久久久| 亚洲自拍偷拍麻豆| 成人精品电影在线观看| 日韩欧美色综合网站| 亚洲综合免费观看高清完整版 | 精品国产欧美一区二区| 一区二区激情小说| 成人性生交大合| 欧美成人精品高清在线播放| 一区二区三区蜜桃| 成熟亚洲日本毛茸茸凸凹| 欧美一区二区三区在| 亚洲黄色在线视频| 成人精品国产福利| 国产日韩欧美综合在线| 久久成人免费网站| 欧美另类z0zxhd电影| 亚洲精品视频一区| 99这里都是精品| 国产欧美日韩三级| 国产真实乱子伦精品视频| 91精品婷婷国产综合久久性色 | 亚洲国产欧美一区二区三区丁香婷| 国产一区二区三区四区五区入口 | 日韩一区国产二区欧美三区| 亚洲一二三四区不卡| 91在线视频播放地址| 欧美激情综合五月色丁香小说| 久久国内精品视频| 日韩一级二级三级| 看电影不卡的网站| 欧美一级一级性生活免费录像| 亚洲一区二区欧美激情| 在线视频你懂得一区| 亚洲一区成人在线| 欧美日韩国产精选| 亚洲国产精品久久人人爱| 欧美日韩性生活| 天天综合网天天综合色| 欧美日韩国产一级二级| 婷婷综合久久一区二区三区| 色一情一乱一乱一91av| 亚洲国产成人av好男人在线观看| 92精品国产成人观看免费| 亚洲免费视频中文字幕| 91在线视频18| 亚洲成国产人片在线观看| 欧美制服丝袜第一页| 婷婷开心久久网| 91精品一区二区三区在线观看| 捆绑调教一区二区三区| 久久嫩草精品久久久精品一| 国产美女精品一区二区三区| 国产亚洲欧美一区在线观看| 成人午夜免费视频| 综合欧美亚洲日本| 欧美三级一区二区| 麻豆国产91在线播放| 国产三区在线成人av| 成人精品一区二区三区中文字幕| 国产精品狼人久久影院观看方式| 成人国产视频在线观看| 亚洲一区在线观看免费| 日韩精品在线一区二区| 国产成人av影院| 亚洲欧美在线另类| 这里只有精品免费| 国产黄人亚洲片| 一区二区三区自拍| 日韩精品一区二区三区四区视频| 丁香激情综合国产|