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

📄 dquot.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 3 页
字号:
				schedule();	/* Try to wait for a moment... */			goto we_slept;		}		dquot = empty;        	dquot->dq_id = id;        	dquot->dq_type = type;        	dquot->dq_dev = sb->s_dev;        	dquot->dq_sb = sb;		/* hash it first so it can be found */		insert_dquot_hash(dquot);        	read_dquot(dquot);	} else {		if (!dquot->dq_count++)			remove_free_dquot(dquot);		dqstats.cache_hits++;		wait_on_dquot(dquot);		if (empty)			dqput(empty);	}	if (!dquot->dq_sb) {	/* Has somebody invalidated entry under us? */		printk(KERN_ERR "VFS: dqget(): Quota invalidated in dqget()!\n");		dqput(dquot);		return NODQUOT;	}	dquot->dq_referenced++;	dqstats.lookups++;	return dquot;}static struct dquot *dqduplicate(struct dquot *dquot){	if (dquot == NODQUOT)		return NODQUOT;	dquot->dq_count++;	if (!dquot->dq_sb) {		printk(KERN_ERR "VFS: dqduplicate(): Invalidated quota to be duplicated!\n");		dquot->dq_count--;		return NODQUOT;	}	if (dquot->dq_flags & DQ_LOCKED)		printk(KERN_ERR "VFS: dqduplicate(): Locked quota to be duplicated!\n");	dquot->dq_referenced++;	dqstats.lookups++;	return dquot;}static int dqinit_needed(struct inode *inode, short type){	int cnt;	if (IS_NOQUOTA(inode))		return 0;	if (type != -1)		return inode->i_dquot[type] == NODQUOT;	for (cnt = 0; cnt < MAXQUOTAS; cnt++)		if (inode->i_dquot[cnt] == NODQUOT)			return 1;	return 0;}static void add_dquot_ref(struct super_block *sb, short type){	struct list_head *p;	if (!sb->dq_op)		return;	/* nothing to do */restart:	file_list_lock();	for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {		struct file *filp = list_entry(p, struct file, f_list);		struct inode *inode = filp->f_dentry->d_inode;		if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {			struct vfsmount *mnt = mntget(filp->f_vfsmnt);			struct dentry *dentry = dget(filp->f_dentry);			file_list_unlock();			sb->dq_op->initialize(inode, type);			dput(dentry);			mntput(mnt);			/* As we may have blocked we had better restart... */			goto restart;		}	}	file_list_unlock();}/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */static inline int dqput_blocks(struct dquot *dquot){	if (dquot->dq_count == 1)		return 1;	return 0;}/* Remove references to dquots from inode - add dquot to list for freeing if needed */int remove_inode_dquot_ref(struct inode *inode, short type, struct list_head *tofree_head){	struct dquot *dquot = inode->i_dquot[type];	int cnt;	inode->i_dquot[type] = NODQUOT;	/* any other quota in use? */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		if (inode->i_dquot[cnt] != NODQUOT)			goto put_it;	}	inode->i_flags &= ~S_QUOTA;put_it:	if (dquot != NODQUOT) {		if (dqput_blocks(dquot)) {			if (dquot->dq_count != 1)				printk(KERN_WARNING "VFS: Adding dquot with dq_count %d to dispose list.\n", dquot->dq_count);			list_add(&dquot->dq_free, tofree_head);	/* As dquot must have currently users it can't be on the free list... */			return 1;		}		else			dqput(dquot);   /* We have guaranteed we won't block */	}	return 0;}/* Free list of dquots - called from inode.c */void put_dquot_list(struct list_head *tofree_head){	struct list_head *act_head;	struct dquot *dquot;	lock_kernel();	act_head = tofree_head->next;	/* So now we have dquots on the list... Just free them */	while (act_head != tofree_head) {		dquot = list_entry(act_head, struct dquot, dq_free);		act_head = act_head->next;		list_del(&dquot->dq_free);	/* Remove dquot from the list so we won't have problems... */		INIT_LIST_HEAD(&dquot->dq_free);		dqput(dquot);	}	unlock_kernel();}static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number){	dquot->dq_curinodes += number;	dquot->dq_flags |= DQ_MOD;}static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number){	dquot->dq_curblocks += number;	dquot->dq_flags |= DQ_MOD;}static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number){	if (dquot->dq_curinodes > number)		dquot->dq_curinodes -= number;	else		dquot->dq_curinodes = 0;	if (dquot->dq_curinodes < dquot->dq_isoftlimit)		dquot->dq_itime = (time_t) 0;	dquot->dq_flags &= ~DQ_INODES;	dquot->dq_flags |= DQ_MOD;}static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number){	if (dquot->dq_curblocks > number)		dquot->dq_curblocks -= number;	else		dquot->dq_curblocks = 0;	if (dquot->dq_curblocks < dquot->dq_bsoftlimit)		dquot->dq_btime = (time_t) 0;	dquot->dq_flags &= ~DQ_BLKS;	dquot->dq_flags |= DQ_MOD;}static inline int need_print_warning(struct dquot *dquot, int flag){	switch (dquot->dq_type) {		case USRQUOTA:			return current->fsuid == dquot->dq_id && !(dquot->dq_flags & flag);		case GRPQUOTA:			return in_group_p(dquot->dq_id) && !(dquot->dq_flags & flag);	}	return 0;}/* Values of warnings */#define NOWARN 0#define IHARDWARN 1#define ISOFTLONGWARN 2#define ISOFTWARN 3#define BHARDWARN 4#define BSOFTLONGWARN 5#define BSOFTWARN 6/* Print warning to user which exceeded quota */static void print_warning(struct dquot *dquot, const char warntype){	char *msg = NULL;	int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS :	  ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES : 0);	if (!need_print_warning(dquot, flag))		return;	dquot->dq_flags |= flag;	tty_write_message(current->tty, (char *)bdevname(dquot->dq_sb->s_dev));	if (warntype == ISOFTWARN || warntype == BSOFTWARN)		tty_write_message(current->tty, ": warning, ");	else		tty_write_message(current->tty, ": write failed, ");	tty_write_message(current->tty, quotatypes[dquot->dq_type]);	switch (warntype) {		case IHARDWARN:			msg = " file limit reached.\n";			break;		case ISOFTLONGWARN:			msg = " file quota exceeded too long.\n";			break;		case ISOFTWARN:			msg = " file quota exceeded.\n";			break;		case BHARDWARN:			msg = " block limit reached.\n";			break;		case BSOFTLONGWARN:			msg = " block quota exceeded too long.\n";			break;		case BSOFTWARN:			msg = " block quota exceeded.\n";			break;	}	tty_write_message(current->tty, msg);}static inline void flush_warnings(struct dquot **dquots, char *warntype){	int i;	for (i = 0; i < MAXQUOTAS; i++)		if (dquots[i] != NODQUOT && warntype[i] != NOWARN)			print_warning(dquots[i], warntype[i]);}static inline char ignore_hardlimit(struct dquot *dquot){	return capable(CAP_SYS_RESOURCE) && !dquot->dq_sb->s_dquot.rsquash[dquot->dq_type];}static int check_idq(struct dquot *dquot, ulong inodes, char *warntype){	*warntype = NOWARN;	if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)		return QUOTA_OK;	if (dquot->dq_ihardlimit &&	   (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit &&            !ignore_hardlimit(dquot)) {		*warntype = IHARDWARN;		return NO_QUOTA;	}	if (dquot->dq_isoftlimit &&	   (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&	    dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime &&            !ignore_hardlimit(dquot)) {		*warntype = ISOFTLONGWARN;		return NO_QUOTA;	}	if (dquot->dq_isoftlimit &&	   (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&	    dquot->dq_itime == 0) {		*warntype = ISOFTWARN;		dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[dquot->dq_type];	}	return QUOTA_OK;}static int check_bdq(struct dquot *dquot, ulong blocks, char prealloc, char *warntype){	*warntype = 0;	if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)		return QUOTA_OK;	if (dquot->dq_bhardlimit &&	   (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit &&            !ignore_hardlimit(dquot)) {		if (!prealloc)			*warntype = BHARDWARN;		return NO_QUOTA;	}	if (dquot->dq_bsoftlimit &&	   (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&	    dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime &&            !ignore_hardlimit(dquot)) {		if (!prealloc)			*warntype = BSOFTLONGWARN;		return NO_QUOTA;	}	if (dquot->dq_bsoftlimit &&	   (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&	    dquot->dq_btime == 0) {		if (!prealloc) {			*warntype = BSOFTWARN;			dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[dquot->dq_type];		}		else			/*			 * We don't allow preallocation to exceed softlimit so exceeding will			 * be always printed			 */			return NO_QUOTA;	}	return QUOTA_OK;}/* * Initialize a dquot-struct with new quota info. This is used by the * system call interface functions. */ static int set_dqblk(struct super_block *sb, int id, short type, int flags, struct dqblk *dqblk){	struct dquot *dquot;	int error = -EFAULT;	struct dqblk dq_dqblk;	if (copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk)))		return error;	if (sb && (dquot = dqget(sb, id, type)) != NODQUOT) {		/* We can't block while changing quota structure... */		if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {			dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit;			dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit;			dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit;			dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit;		}		if ((flags & SET_QUOTA) || (flags & SET_USE)) {			if (dquot->dq_isoftlimit &&			    dquot->dq_curinodes < dquot->dq_isoftlimit &&			    dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)				dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[type];			dquot->dq_curinodes = dq_dqblk.dqb_curinodes;			if (dquot->dq_curinodes < dquot->dq_isoftlimit)				dquot->dq_flags &= ~DQ_INODES;			if (dquot->dq_bsoftlimit &&			    dquot->dq_curblocks < dquot->dq_bsoftlimit &&			    dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)				dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[type];			dquot->dq_curblocks = dq_dqblk.dqb_curblocks;			if (dquot->dq_curblocks < dquot->dq_bsoftlimit)				dquot->dq_flags &= ~DQ_BLKS;		}		if (id == 0) {			dquot->dq_sb->s_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime;			dquot->dq_sb->s_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime;		}		if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&		    dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)			dquot->dq_flags |= DQ_FAKE;		else			dquot->dq_flags &= ~DQ_FAKE;		dquot->dq_flags |= DQ_MOD;		dqput(dquot);	}	return 0;}static int get_quota(struct super_block *sb, int id, short type, struct dqblk *dqblk){	struct dquot *dquot;	struct dqblk data;	int error = -ESRCH;	if (!sb || !sb_has_quota_enabled(sb, type))		goto out;	dquot = dqget(sb, id, type);	if (dquot == NODQUOT)		goto out;	memcpy(&data, &dquot->dq_dqb, sizeof(struct dqblk));        /* We copy data to preserve them from changing */	dqput(dquot);	error = -EFAULT;	if (dqblk && !copy_to_user(dqblk, &data, sizeof(struct dqblk)))		error = 0;out:	return error;}static int get_stats(caddr_t addr){	int error = -EFAULT;	struct dqstats stats;	dqstats.allocated_dquots = nr_dquots;	dqstats.free_dquots = nr_free_dquots;	/* make a copy, in case we page-fault in user space */	memcpy(&stats, &dqstats, sizeof(struct dqstats));	if (!copy_to_user(addr, &stats, sizeof(struct dqstats)))		error = 0;	return error;}static int quota_root_squash(struct super_block *sb, short type, int *addr){	int new_value, error;	if (!sb)		return(-ENODEV);	error = -EFAULT;	if (!copy_from_user(&new_value, addr, sizeof(int))) {		sb_dqopt(sb)->rsquash[type] = new_value;		error = 0;	}	return error;}#if 0	/* We are not going to support filesystems without i_blocks... *//* * This is a simple algorithm that calculates the size of a file in blocks. * This is only used on filesystems that do not have an i_blocks count. */static u_long isize_to_blocks(loff_t isize, size_t blksize_bits){	u_long blocks;	u_long indirect;	if (!blksize_bits)		blksize_bits = BLOCK_SIZE_BITS;	blocks = (isize >> blksize_bits) + ((isize & ~((1 << blksize_bits)-1)) ? 1 : 0);	if (blocks > 10) {		indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */		if (blocks > (10 + 256)) {			indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */			if (blocks > (10 + 256 + (256 << 8)))				indirect++; /* triple indirect blocks */		}		blocks += indirect;	}	return blocks;}#endif/* * Externally referenced functions through dquot_operations in inode. * * Note: this is a blocking operation. */void dquot_initialize(struct inode *inode, short type){	struct dquot *dquot[MAXQUOTAS];	unsigned int id = 0;	short cnt;	if (IS_NOQUOTA(inode))		return;	/* Build list of quotas to initialize... We can block here */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		dquot[cnt] = NODQUOT;		if (type != -1 && cnt != type)			continue;		if (!sb_has_quota_enabled(inode->i_sb, cnt))			continue;		if (inode->i_dquot[cnt] == NODQUOT) {			switch (cnt) {				case USRQUOTA:					id = inode->i_uid;					break;				case GRPQUOTA:					id = inode->i_gid;					break;			}			dquot[cnt] = dqget(inode->i_sb, id, cnt);		}	}	/* NOBLOCK START: Here we shouldn't block */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		if (dquot[cnt] == NODQUOT || !sb_has_quota_enabled(inode->i_sb, cnt) || inode->i_dquot[cnt] != NODQUOT)			continue;		inode->i_dquot[cnt] = dquot[cnt];		dquot[cnt] = NODQUOT;

⌨️ 快捷键说明

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