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

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

?? inode.c

?? linux 下的文件管理的程序
?? C
?? 第 1 頁 / 共 3 頁
字號:
/*
 *  linux/fs/ext2/inode.c
 *
 * Copyright (C) 1992, 1993, 1994, 1995
 * Remy Card (card@masi.ibp.fr)
 * Laboratoire MASI - Institut Blaise Pascal
 * Universite Pierre et Marie Curie (Paris VI)
 *
 *  from
 *
 *  linux/fs/minix/inode.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  Goal-directed block allocation by Stephen Tweedie
 * 	(sct@dcs.ed.ac.uk), 1993, 1998
 *  Big-endian to little-endian byte-swapping/bitmaps by
 *        David S. Miller (davem@caip.rutgers.edu), 1995
 *  64-bit file support on 64-bit platforms by Jakub Jelinek
 * 	(jj@sunsite.ms.mff.cuni.cz)
 *
 *  Assorted race fixes, rewrite of ext2_get_block() by Al Viro, 2000
 */

#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
#include <linux/sched.h>
#include <linux/highuid.h>

static int ext2_update_inode(struct inode * inode, int do_sync);

/*
 * Called at each iput()
 */
void ext2_put_inode (struct inode * inode)
{
	ext2_discard_prealloc (inode);
}

/*
 * Called at the last iput() if i_nlink is zero.
 */
void ext2_delete_inode (struct inode * inode)
{
	lock_kernel();

	if (is_bad_inode(inode) ||
	    inode->i_ino == EXT2_ACL_IDX_INO ||
	    inode->i_ino == EXT2_ACL_DATA_INO)
		goto no_delete;
	inode->u.ext2_i.i_dtime	= CURRENT_TIME;
	mark_inode_dirty(inode);
	ext2_update_inode(inode, IS_SYNC(inode));
	inode->i_size = 0;
	if (inode->i_blocks)
		ext2_truncate (inode);
	ext2_free_inode (inode);

	unlock_kernel();
	return;
no_delete:
	unlock_kernel();
	clear_inode(inode);	/* We must guarantee clearing of inode... */
}

void ext2_discard_prealloc (struct inode * inode)
{
#ifdef EXT2_PREALLOCATE
	lock_kernel();
	/* Writer: ->i_prealloc* */
	if (inode->u.ext2_i.i_prealloc_count) {
		unsigned short total = inode->u.ext2_i.i_prealloc_count;
		unsigned long block = inode->u.ext2_i.i_prealloc_block;
		inode->u.ext2_i.i_prealloc_count = 0;
		inode->u.ext2_i.i_prealloc_block = 0;
		/* Writer: end */
		ext2_free_blocks (inode, block, total);
	}
	unlock_kernel();
#endif
}

static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err)
{
#ifdef EXT2FS_DEBUG
	static unsigned long alloc_hits = 0, alloc_attempts = 0;
#endif
	unsigned long result;


#ifdef EXT2_PREALLOCATE
	/* Writer: ->i_prealloc* */
	if (inode->u.ext2_i.i_prealloc_count &&
	    (goal == inode->u.ext2_i.i_prealloc_block ||
	     goal + 1 == inode->u.ext2_i.i_prealloc_block))
	{		
		result = inode->u.ext2_i.i_prealloc_block++;
		inode->u.ext2_i.i_prealloc_count--;
		/* Writer: end */
#ifdef EXT2FS_DEBUG
		ext2_debug ("preallocation hit (%lu/%lu).\n",
			    ++alloc_hits, ++alloc_attempts);
#endif
	} else {
		ext2_discard_prealloc (inode);
#ifdef EXT2FS_DEBUG
		ext2_debug ("preallocation miss (%lu/%lu).\n",
			    alloc_hits, ++alloc_attempts);
#endif
		if (S_ISREG(inode->i_mode))
			result = ext2_new_block (inode, goal, 
				 &inode->u.ext2_i.i_prealloc_count,
				 &inode->u.ext2_i.i_prealloc_block, err);
		else
			result = ext2_new_block (inode, goal, 0, 0, err);
	}
#else
	result = ext2_new_block (inode, goal, 0, 0, err);
#endif
	return result;
}

typedef struct {
	u32	*p;
	u32	key;
	struct buffer_head *bh;
} Indirect;

static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
{
	p->key = *(p->p = v);
	p->bh = bh;
}

static inline int verify_chain(Indirect *from, Indirect *to)
{
	while (from <= to && from->key == *from->p)
		from++;
	return (from > to);
}

/**
 *	ext2_block_to_path - parse the block number into array of offsets
 *	@inode: inode in question (we are only interested in its superblock)
 *	@i_block: block number to be parsed
 *	@offsets: array to store the offsets in
 *
 *	To store the locations of file's data ext2 uses a data structure common
 *	for UNIX filesystems - tree of pointers anchored in the inode, with
 *	data blocks at leaves and indirect blocks in intermediate nodes.
 *	This function translates the block number into path in that tree -
 *	return value is the path length and @offsets[n] is the offset of
 *	pointer to (n+1)th node in the nth one. If @block is out of range
 *	(negative or too large) warning is printed and zero returned.
 *
 *	Note: function doesn't find node addresses, so no IO is needed. All
 *	we need to know is the capacity of indirect blocks (taken from the
 *	inode->i_sb).
 */

/*
 * Portability note: the last comparison (check that we fit into triple
 * indirect block) is spelled differently, because otherwise on an
 * architecture with 32-bit longs and 8Kb pages we might get into trouble
 * if our filesystem had 8Kb blocks. We might use long long, but that would
 * kill us on x86. Oh, well, at least the sign propagation does not matter -
 * i_block would have to be negative in the very beginning, so we would not
 * get there at all.
 */

static int ext2_block_to_path(struct inode *inode, long i_block, int offsets[4])
{
	int ptrs = EXT2_ADDR_PER_BLOCK(inode->i_sb);
	int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb);
	const long direct_blocks = EXT2_NDIR_BLOCKS,
		indirect_blocks = ptrs,
		double_blocks = (1 << (ptrs_bits * 2));
	int n = 0;

	if (i_block < 0) {
		ext2_warning (inode->i_sb, "ext2_block_to_path", "block < 0");
	} else if (i_block < direct_blocks) {
		offsets[n++] = i_block;
	} else if ( (i_block -= direct_blocks) < indirect_blocks) {
		offsets[n++] = EXT2_IND_BLOCK;
		offsets[n++] = i_block;
	} else if ((i_block -= indirect_blocks) < double_blocks) {
		offsets[n++] = EXT2_DIND_BLOCK;
		offsets[n++] = i_block >> ptrs_bits;
		offsets[n++] = i_block & (ptrs - 1);
	} else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
		offsets[n++] = EXT2_TIND_BLOCK;
		offsets[n++] = i_block >> (ptrs_bits * 2);
		offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
		offsets[n++] = i_block & (ptrs - 1);
	} else {
		ext2_warning (inode->i_sb, "ext2_block_to_path", "block > big");
	}
	return n;
}

/**
 *	ext2_get_branch - read the chain of indirect blocks leading to data
 *	@inode: inode in question
 *	@depth: depth of the chain (1 - direct pointer, etc.)
 *	@offsets: offsets of pointers in inode/indirect blocks
 *	@chain: place to store the result
 *	@err: here we store the error value
 *
 *	Function fills the array of triples <key, p, bh> and returns %NULL
 *	if everything went OK or the pointer to the last filled triple
 *	(incomplete one) otherwise. Upon the return chain[i].key contains
 *	the number of (i+1)-th block in the chain (as it is stored in memory,
 *	i.e. little-endian 32-bit), chain[i].p contains the address of that
 *	number (it points into struct inode for i==0 and into the bh->b_data
 *	for i>0) and chain[i].bh points to the buffer_head of i-th indirect
 *	block for i>0 and NULL for i==0. In other words, it holds the block
 *	numbers of the chain, addresses they were taken from (and where we can
 *	verify that chain did not change) and buffer_heads hosting these
 *	numbers.
 *
 *	Function stops when it stumbles upon zero pointer (absent block)
 *		(pointer to last triple returned, *@err == 0)
 *	or when it gets an IO error reading an indirect block
 *		(ditto, *@err == -EIO)
 *	or when it notices that chain had been changed while it was reading
 *		(ditto, *@err == -EAGAIN)
 *	or when it reads all @depth-1 indirect blocks successfully and finds
 *	the whole chain, all way to the data (returns %NULL, *err == 0).
 */
static inline Indirect *ext2_get_branch(struct inode *inode,
					int depth,
					int *offsets,
					Indirect chain[4],
					int *err)
{
	kdev_t dev = inode->i_dev;
	int size = inode->i_sb->s_blocksize;
	Indirect *p = chain;
	struct buffer_head *bh;

	*err = 0;
	/* i_data is not going away, no lock needed */
	add_chain (chain, NULL, inode->u.ext2_i.i_data + *offsets);
	if (!p->key)
		goto no_block;
	while (--depth) {
		bh = bread(dev, le32_to_cpu(p->key), size);
		if (!bh)
			goto failure;
		/* Reader: pointers */
		if (!verify_chain(chain, p))
			goto changed;
		add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
		/* Reader: end */
		if (!p->key)
			goto no_block;
	}
	return NULL;

changed:
	*err = -EAGAIN;
	goto no_block;
failure:
	*err = -EIO;
no_block:
	return p;
}

/**
 *	ext2_find_near - find a place for allocation with sufficient locality
 *	@inode: owner
 *	@ind: descriptor of indirect block.
 *
 *	This function returns the prefered place for block allocation.
 *	It is used when heuristic for sequential allocation fails.
 *	Rules are:
 *	  + if there is a block to the left of our position - allocate near it.
 *	  + if pointer will live in indirect block - allocate near that block.
 *	  + if pointer will live in inode - allocate in the same cylinder group.
 *	Caller must make sure that @ind is valid and will stay that way.
 */

static inline unsigned long ext2_find_near(struct inode *inode, Indirect *ind)
{
	u32 *start = ind->bh ? (u32*) ind->bh->b_data : inode->u.ext2_i.i_data;
	u32 *p;

	/* Try to find previous block */
	for (p = ind->p - 1; p >= start; p--)
		if (*p)
			return le32_to_cpu(*p);

	/* No such thing, so let's try location of indirect block */
	if (ind->bh)
		return ind->bh->b_blocknr;

	/*
	 * It is going to be refered from inode itself? OK, just put it into
	 * the same cylinder group then.
	 */
	return (inode->u.ext2_i.i_block_group * 
		EXT2_BLOCKS_PER_GROUP(inode->i_sb)) +
	       le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_first_data_block);
}

/**
 *	ext2_find_goal - find a prefered place for allocation.
 *	@inode: owner
 *	@block:  block we want
 *	@chain:  chain of indirect blocks
 *	@partial: pointer to the last triple within a chain
 *	@goal:	place to store the result.
 *
 *	Normally this function find the prefered place for block allocation,
 *	stores it in *@goal and returns zero. If the branch had been changed
 *	under us we return -EAGAIN.
 */

static inline int ext2_find_goal(struct inode *inode,
				 long block,
				 Indirect chain[4],
				 Indirect *partial,
				 unsigned long *goal)
{
	/* Writer: ->i_next_alloc* */
	if (block == inode->u.ext2_i.i_next_alloc_block + 1) {
		inode->u.ext2_i.i_next_alloc_block++;
		inode->u.ext2_i.i_next_alloc_goal++;
	} 
	/* Writer: end */
	/* Reader: pointers, ->i_next_alloc* */
	if (verify_chain(chain, partial)) {
		/*
		 * try the heuristic for sequential allocation,
		 * failing that at least try to get decent locality.
		 */
		if (block == inode->u.ext2_i.i_next_alloc_block)
			*goal = inode->u.ext2_i.i_next_alloc_goal;
		if (!*goal)
			*goal = ext2_find_near(inode, partial);
		return 0;
	}
	/* Reader: end */
	return -EAGAIN;
}

/**
 *	ext2_alloc_branch - allocate and set up a chain of blocks.
 *	@inode: owner
 *	@num: depth of the chain (number of blocks to allocate)
 *	@offsets: offsets (in the blocks) to store the pointers to next.
 *	@branch: place to store the chain in.
 *
 *	This function allocates @num blocks, zeroes out all but the last one,
 *	links them into chain and (if we are synchronous) writes them to disk.
 *	In other words, it prepares a branch that can be spliced onto the
 *	inode. It stores the information about that chain in the branch[], in
 *	the same format as ext2_get_branch() would do. We are calling it after
 *	we had read the existing part of chain and partial points to the last
 *	triple of that (one with zero ->key). Upon the exit we have the same
 *	picture as after the successful ext2_get_block(), excpet that in one
 *	place chain is disconnected - *branch->p is still zero (we did not
 *	set the last link), but branch->key contains the number that should
 *	be placed into *branch->p to fill that gap.
 *
 *	If allocation fails we free all blocks we've allocated (and forget
 *	ther buffer_heads) and return the error value the from failed
 *	ext2_alloc_block() (normally -ENOSPC). Otherwise we set the chain
 *	as described above and return 0.
 */

static int ext2_alloc_branch(struct inode *inode,
			     int num,
			     unsigned long goal,
			     int *offsets,
			     Indirect *branch)
{
	int blocksize = inode->i_sb->s_blocksize;
	int n = 0;
	int err;
	int i;
	int parent = ext2_alloc_block(inode, goal, &err);

	branch[0].key = cpu_to_le32(parent);
	if (parent) for (n = 1; n < num; n++) {
		struct buffer_head *bh;
		/* Allocate the next block */
		int nr = ext2_alloc_block(inode, parent, &err);
		if (!nr)
			break;
		branch[n].key = cpu_to_le32(nr);
		/*
		 * Get buffer_head for parent block, zero it out and set 
		 * the pointer to new one, then send parent to disk.
		 */
		bh = getblk(inode->i_dev, parent, blocksize);
		if (!buffer_uptodate(bh))
			wait_on_buffer(bh);
		memset(bh->b_data, 0, blocksize);
		branch[n].bh = bh;
		branch[n].p = (u32*) bh->b_data + offsets[n];
		*branch[n].p = branch[n].key;
		mark_buffer_uptodate(bh, 1);
		mark_buffer_dirty_inode(bh, inode);
		if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {
			ll_rw_block (WRITE, 1, &bh);
			wait_on_buffer (bh);
		}
		parent = nr;
	}
	if (n == num)
		return 0;

	/* Allocation failed, free what we already allocated */
	for (i = 1; i < n; i++)
		bforget(branch[i].bh);
	for (i = 0; i < n; i++)
		ext2_free_blocks(inode, le32_to_cpu(branch[i].key), 1);
	return err;
}

/**
 *	ext2_splice_branch - splice the allocated branch onto inode.
 *	@inode: owner
 *	@block: (logical) number of block we are adding
 *	@chain: chain of indirect blocks (with a missing link - see
 *		ext2_alloc_branch)
 *	@where: location of missing link
 *	@num:   number of blocks we are adding
 *

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
久久男人中文字幕资源站| 夜夜揉揉日日人人青青一国产精品| 高清不卡一二三区| 亚洲午夜久久久| 国产欧美日韩麻豆91| 欧美日韩二区三区| 亚洲一二三区在线观看| 在线播放亚洲一区| 成人h版在线观看| 美女视频黄频大全不卡视频在线播放| 亚洲欧洲99久久| 欧美va日韩va| 这里只有精品电影| 色国产精品一区在线观看| 国产风韵犹存在线视精品| 午夜精品久久久久久| 亚洲国产成人私人影院tom| 日韩欧美一二三| 欧美日韩精品一区二区在线播放| www.在线成人| 丁香另类激情小说| 91麻豆免费看| 一区二区三区四区五区视频在线观看 | 亚洲日本韩国一区| 成人精品视频一区二区三区| 欧美日韩国产在线播放网站| av在线播放一区二区三区| 国产精品白丝在线| 亚洲综合一二区| 国产亚洲精品7777| 26uuu亚洲婷婷狠狠天堂| 欧美日韩另类一区| 欧美怡红院视频| 91香蕉国产在线观看软件| 成人视屏免费看| 粉嫩蜜臀av国产精品网站| 免费在线观看一区| 日韩av在线发布| 青草av.久久免费一区| 午夜电影一区二区三区| 午夜av区久久| 亚洲第一综合色| 亚洲国产精品尤物yw在线观看| 亚洲精品日韩一| 中文字幕av一区 二区| 欧美三级电影精品| 91九色02白丝porn| 91久久精品日日躁夜夜躁欧美| 成人av网在线| av在线播放成人| 在线观看日韩精品| 欧美色图在线观看| 欧美日本免费一区二区三区| 在线不卡免费av| 日韩欧美视频在线| 欧美草草影院在线视频| 一本色道亚洲精品aⅴ| 天天综合网 天天综合色| 丝袜亚洲精品中文字幕一区| 三级成人在线视频| 免费一级片91| 国产美女精品在线| 91偷拍与自偷拍精品| 91福利国产精品| 欧美丰满美乳xxx高潮www| 欧美一级高清大全免费观看| 欧美高清视频在线高清观看mv色露露十八| 久久精品久久99精品久久| 日韩av在线发布| 久久新电视剧免费观看| 亚洲精品一区二区三区蜜桃下载 | 国产精品色在线观看| 日韩美女主播在线视频一区二区三区| 成人爽a毛片一区二区免费| 日本aⅴ亚洲精品中文乱码| 久久69国产一区二区蜜臀| 国产东北露脸精品视频| 91婷婷韩国欧美一区二区| 欧美久久久一区| 日韩美女天天操| 亚洲国产精品成人综合色在线婷婷| 国产精品第一页第二页第三页| 亚洲国产成人av好男人在线观看| 久久精品免费看| 风间由美一区二区av101 | 欧洲视频一区二区| 欧美一区二区三区视频免费播放| 欧美一区二区三区日韩| 一区二区三区在线观看动漫| 美日韩黄色大片| 成人性生交大片免费看中文| 欧美人妇做爰xxxⅹ性高电影 | 777久久久精品| 国产精品卡一卡二卡三| 日韩av在线发布| 欧美一区二区在线免费播放| 国产精品视频yy9299一区| 亚洲午夜精品17c| 国产中文字幕精品| 日韩理论片中文av| 亚洲va国产天堂va久久en| 激情丁香综合五月| av一区二区三区在线| 制服.丝袜.亚洲.中文.综合| **网站欧美大片在线观看| 日韩制服丝袜av| 国产一区二区三区四| 欧美综合色免费| 国产精品嫩草影院com| 午夜精品国产更新| 在线视频综合导航| 中文字幕中文在线不卡住| 蜜桃久久av一区| 欧美色综合天天久久综合精品| 久久久不卡影院| 国产精品456露脸| 26uuu亚洲| 国产成人av影院| 51精品秘密在线观看| 精品三级在线看| 一区二区三区色| 91免费观看视频在线| 亚洲天堂av老司机| 精品国产一二三| 2017欧美狠狠色| 五月综合激情日本mⅴ| 国产成人在线影院| 日韩精品影音先锋| 日韩激情视频网站| 91高清视频在线| 中文字幕一区二区5566日韩| 国产一区二区网址| 精品福利一区二区三区免费视频| 三级欧美在线一区| 日韩精品一级中文字幕精品视频免费观看 | 精品视频在线免费| 亚洲图片欧美色图| 日韩一区二区高清| 91在线观看免费视频| 国产亚洲欧美激情| 亚洲综合在线五月| 色八戒一区二区三区| 亚洲视频一区在线| www.视频一区| 亚洲人123区| www.日韩精品| 亚洲人精品午夜| 色婷婷综合久久久中文一区二区| 日韩一区日韩二区| 色噜噜偷拍精品综合在线| 亚洲精品视频观看| 欧美日韩国产综合草草| 天天操天天干天天综合网| 7777精品伊人久久久大香线蕉完整版 | 国产一区二区三区精品视频| 久久久91精品国产一区二区精品 | 欧洲另类一二三四区| 亚洲电影视频在线| 日韩欧美视频一区| 国产精品夜夜嗨| 1区2区3区精品视频| 欧美曰成人黄网| 日韩高清不卡一区二区三区| 7777女厕盗摄久久久| 国内精品伊人久久久久av影院| 久久久久久影视| 91蜜桃婷婷狠狠久久综合9色| 亚洲女人****多毛耸耸8| 欧美精品日日鲁夜夜添| 蜜臀精品一区二区三区在线观看 | 偷拍与自拍一区| 精品国产青草久久久久福利| 大美女一区二区三区| 一区二区三区在线视频观看58 | 日韩欧美的一区| 懂色av一区二区夜夜嗨| 亚洲男人都懂的| 欧美一区二区视频免费观看| 国产一区二区精品久久91| 自拍偷自拍亚洲精品播放| 337p亚洲精品色噜噜| 国产成人在线电影| 亚洲一区二区三区中文字幕在线 | 亚洲精选一二三| 91麻豆精品国产| 丁香婷婷综合网| 一片黄亚洲嫩模| 欧美成人三级在线| 91在线国产观看| 老汉av免费一区二区三区| 国产精品传媒视频| 欧美电视剧在线观看完整版| 99麻豆久久久国产精品免费| 日韩高清不卡在线| 亚洲日本护士毛茸茸| 欧美成人精品二区三区99精品| 色综合久久中文字幕综合网| 激情综合色播激情啊| 亚洲激情av在线| 国产色综合久久|