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

📄 truncate.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
字号:
/* *  linux/fs/ext/truncate.c * *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr) * *  from * *  linux/fs/minix/truncate.c * *  Copyright (C) 1991, 1992  Linus Torvalds */#include <linux/sched.h>#include <linux/ext_fs.h>#include <linux/stat.h>#include <linux/fcntl.h>#include <linux/errno.h>/* * Truncate has the most races in the whole filesystem: coding it is * a pain in the a**. Especially as I don't do any locking... * * The code may look a bit weird, but that's just because I've tried to * handle things like file-size changes in a somewhat graceful manner. * Anyway, truncating a file at the same time somebody else writes to it * is likely to result in pretty weird behaviour... * * The new code handles normal truncates (size = 0) as well as the more * general case (size = XXX). I hope. */static int trunc_direct(struct inode * inode){	int i, tmp;	unsigned long * p;	struct buffer_head * bh;	int retry = 0;#define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)repeat:	for (i = DIRECT_BLOCK ; i < 9 ; i++) {		p = inode->u.ext_i.i_data+i;		if (!(tmp = *p))			continue;		bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);		if (i < DIRECT_BLOCK) {			brelse(bh);			goto repeat;		}		if ((bh && bh->b_count != 1) || tmp != *p) {			retry = 1;			brelse(bh);			continue;		}		*p = 0;		inode->i_dirt = 1;		brelse(bh);		ext_free_block(inode->i_sb,tmp);	}	return retry;}static int trunc_indirect(struct inode * inode, int offset, unsigned long * p){	int i, tmp;	struct buffer_head * bh;	struct buffer_head * ind_bh;	unsigned long * ind;	int retry = 0;#define INDIRECT_BLOCK (DIRECT_BLOCK-offset)	tmp = *p;	if (!tmp)		return 0;	ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);	if (tmp != *p) {		brelse(ind_bh);		return 1;	}	if (!ind_bh) {		*p = 0;		return 0;	}repeat:	for (i = INDIRECT_BLOCK ; i < 256 ; i++) {		if (i < 0)			i = 0;		if (i < INDIRECT_BLOCK)			goto repeat;		ind = i+(unsigned long *) ind_bh->b_data;		tmp = *ind;		if (!tmp)			continue;		bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);		if (i < INDIRECT_BLOCK) {			brelse(bh);			goto repeat;		}		if ((bh && bh->b_count != 1) || tmp != *ind) {			retry = 1;			brelse(bh);			continue;		}		*ind = 0;		ind_bh->b_dirt = 1;		brelse(bh);		ext_free_block(inode->i_sb,tmp);	}	ind = (unsigned long *) ind_bh->b_data;	for (i = 0; i < 256; i++)		if (*(ind++))			break;	if (i >= 256)		if (ind_bh->b_count != 1)			retry = 1;		else {			tmp = *p;			*p = 0;			inode->i_dirt = 1;			ext_free_block(inode->i_sb,tmp);		}	brelse(ind_bh);	return retry;}static int trunc_dindirect(struct inode * inode, int offset, unsigned long * p){	int i,tmp;	struct buffer_head * dind_bh;	unsigned long * dind;	int retry = 0;#define DINDIRECT_BLOCK ((DIRECT_BLOCK-offset)>>8)	tmp = *p;	if (!tmp)		return 0;	dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);	if (tmp != *p) {		brelse(dind_bh);		return 1;	}	if (!dind_bh) {		*p = 0;		return 0;	}repeat:	for (i = DINDIRECT_BLOCK ; i < 256 ; i ++) {		if (i < 0)			i = 0;		if (i < DINDIRECT_BLOCK)			goto repeat;		dind = i+(unsigned long *) dind_bh->b_data;		tmp = *dind;		if (!tmp)			continue;		retry |= trunc_indirect(inode,offset+(i<<8),dind);		dind_bh->b_dirt = 1;	}	dind = (unsigned long *) dind_bh->b_data;	for (i = 0; i < 256; i++)		if (*(dind++))			break;	if (i >= 256)		if (dind_bh->b_count != 1)			retry = 1;		else {			tmp = *p;			*p = 0;			inode->i_dirt = 1;			ext_free_block(inode->i_sb,tmp);		}	brelse(dind_bh);	return retry;}static int trunc_tindirect(struct inode * inode){	int i,tmp;	struct buffer_head * tind_bh;	unsigned long * tind, * p;	int retry = 0;#define TINDIRECT_BLOCK ((DIRECT_BLOCK-(256*256+256+9))>>16)	p = inode->u.ext_i.i_data+11;	if (!(tmp = *p))		return 0;	tind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);	if (tmp != *p) {		brelse(tind_bh);		return 1;	}	if (!tind_bh) {		*p = 0;		return 0;	}repeat:	for (i = TINDIRECT_BLOCK ; i < 256 ; i ++) {		if (i < 0)			i = 0;		if (i < TINDIRECT_BLOCK)			goto repeat;		tind = i+(unsigned long *) tind_bh->b_data;		retry |= trunc_dindirect(inode,9+256+256*256+(i<<16),tind);		tind_bh->b_dirt = 1;	}	tind = (unsigned long *) tind_bh->b_data;	for (i = 0; i < 256; i++)		if (*(tind++))			break;	if (i >= 256)		if (tind_bh->b_count != 1)			retry = 1;		else {			tmp = *p;			*p = 0;			inode->i_dirt = 1;			ext_free_block(inode->i_sb,tmp);		}	brelse(tind_bh);	return retry;}void ext_truncate(struct inode * inode){	int retry;	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||	     S_ISLNK(inode->i_mode)))		return;	while (1) {		retry = trunc_direct(inode);		retry |= trunc_indirect(inode,9,inode->u.ext_i.i_data+9);		retry |= trunc_dindirect(inode,9+256,inode->u.ext_i.i_data+10);		retry |= trunc_tindirect(inode);		if (!retry)			break;		current->counter = 0;		schedule();	}	inode->i_mtime = inode->i_ctime = CURRENT_TIME;	inode->i_dirt = 1;}/* * Called when a inode is released. Note that this is different * from ext_open: open gets called at every open, but release * gets called only when /all/ the files are closed. */void ext_release(struct inode * inode, struct file * filp){	printk("ext_release not implemented\n");}

⌨️ 快捷键说明

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