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

📄 dquot.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 3 页
字号:
		inode->i_flags |= S_QUOTA;	}	/* NOBLOCK END */	/* Put quotas which we didn't use */	for (cnt = 0; cnt < MAXQUOTAS; cnt++)		if (dquot[cnt] != NODQUOT)			dqput(dquot[cnt]);}/* * Release all quota for the specified inode. * * Note: this is a blocking operation. */void dquot_drop(struct inode *inode){	struct dquot *dquot;	short cnt;	inode->i_flags &= ~S_QUOTA;	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		if (inode->i_dquot[cnt] == NODQUOT)			continue;		dquot = inode->i_dquot[cnt];		inode->i_dquot[cnt] = NODQUOT;		dqput(dquot);	}}/* * This operation can block, but only after everything is updated */int dquot_alloc_block(struct inode *inode, unsigned long number, char warn){	int cnt, ret = NO_QUOTA;	struct dquot *dquot[MAXQUOTAS];	char warntype[MAXQUOTAS];	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		dquot[cnt] = NODQUOT;		warntype[cnt] = NOWARN;	}	/* NOBLOCK Start */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		dquot[cnt] = dqduplicate(inode->i_dquot[cnt]);		if (dquot[cnt] == NODQUOT)			continue;		if (check_bdq(dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA)			goto warn_put_all;	}	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		if (dquot[cnt] == NODQUOT)			continue;		dquot_incr_blocks(dquot[cnt], number);	}	inode->i_blocks += number << (BLOCK_SIZE_BITS - 9);	/* NOBLOCK End */	ret = QUOTA_OK;warn_put_all:	flush_warnings(dquot, warntype);	for (cnt = 0; cnt < MAXQUOTAS; cnt++)		if (dquot[cnt] != NODQUOT)			dqput(dquot[cnt]);	return ret;}/* * This operation can block, but only after everything is updated */int dquot_alloc_inode(const struct inode *inode, unsigned long number){	int cnt, ret = NO_QUOTA;	struct dquot *dquot[MAXQUOTAS];	char warntype[MAXQUOTAS];	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		dquot[cnt] = NODQUOT;		warntype[cnt] = NOWARN;	}	/* NOBLOCK Start */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		dquot[cnt] = dqduplicate(inode -> i_dquot[cnt]);		if (dquot[cnt] == NODQUOT)			continue;		if (check_idq(dquot[cnt], number, warntype+cnt) == NO_QUOTA)			goto warn_put_all;	}	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		if (dquot[cnt] == NODQUOT)			continue;		dquot_incr_inodes(dquot[cnt], number);	}	/* NOBLOCK End */	ret = QUOTA_OK;warn_put_all:	flush_warnings(dquot, warntype);	for (cnt = 0; cnt < MAXQUOTAS; cnt++)		if (dquot[cnt] != NODQUOT)			dqput(dquot[cnt]);	return ret;}/* * This is a non-blocking operation. */void dquot_free_block(struct inode *inode, unsigned long number){	unsigned short cnt;	struct dquot *dquot;	/* NOBLOCK Start */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		dquot = dqduplicate(inode->i_dquot[cnt]);		if (dquot == NODQUOT)			continue;		dquot_decr_blocks(dquot, number);		dqput(dquot);	}	inode->i_blocks -= number << (BLOCK_SIZE_BITS - 9);	/* NOBLOCK End */}/* * This is a non-blocking operation. */void dquot_free_inode(const struct inode *inode, unsigned long number){	unsigned short cnt;	struct dquot *dquot;	/* NOBLOCK Start */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		dquot = dqduplicate(inode->i_dquot[cnt]);		if (dquot == NODQUOT)			continue;		dquot_decr_inodes(dquot, number);		dqput(dquot);	}	/* NOBLOCK End */}/* * Transfer the number of inode and blocks from one diskquota to an other. * * This operation can block, but only after everything is updated */int dquot_transfer(struct inode *inode, struct iattr *iattr){	unsigned long blocks;	struct dquot *transfer_from[MAXQUOTAS];	struct dquot *transfer_to[MAXQUOTAS];	int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid,	    chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid;	char warntype[MAXQUOTAS];	/* Clear the arrays */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		transfer_to[cnt] = transfer_from[cnt] = NODQUOT;		warntype[cnt] = NOWARN;	}	/* First build the transfer_to list - here we can block on reading of dquots... */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		if (!sb_has_quota_enabled(inode->i_sb, cnt))			continue;		switch (cnt) {			case USRQUOTA:				if (!chuid)					continue;				transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_uid, cnt);				break;			case GRPQUOTA:				if (!chgid)					continue;				transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_gid, cnt);				break;		}	}	/* NOBLOCK START: From now on we shouldn't block */	blocks = (inode->i_blocks >> 1);	/* Build the transfer_from list and check the limits */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		/* The second test can fail when quotaoff is in progress... */		if (transfer_to[cnt] == NODQUOT || !sb_has_quota_enabled(inode->i_sb, cnt))			continue;		transfer_from[cnt] = dqduplicate(inode->i_dquot[cnt]);		if (transfer_from[cnt] == NODQUOT)	/* Can happen on quotafiles (quota isn't initialized on them)... */			continue;		if (check_idq(transfer_to[cnt], 1, warntype+cnt) == NO_QUOTA ||		    check_bdq(transfer_to[cnt], blocks, 0, warntype+cnt) == NO_QUOTA)			goto warn_put_all;	}	/*	 * Finally perform the needed transfer from transfer_from to transfer_to	 */	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		/*		 * Skip changes for same uid or gid or for non-existing quota-type.		 */		if (transfer_from[cnt] == NODQUOT || transfer_to[cnt] == NODQUOT)			continue;		dquot_decr_inodes(transfer_from[cnt], 1);		dquot_decr_blocks(transfer_from[cnt], blocks);		dquot_incr_inodes(transfer_to[cnt], 1);		dquot_incr_blocks(transfer_to[cnt], blocks);		if (inode->i_dquot[cnt] == NODQUOT)			BUG();		inode->i_dquot[cnt] = transfer_to[cnt];		/*		 * We've got to release transfer_from[] twice - once for dquot_transfer() and		 * once for inode. We don't want to release transfer_to[] as it's now placed in inode		 */		transfer_to[cnt] = transfer_from[cnt];	}	/* NOBLOCK END. From now on we can block as we wish */	ret = QUOTA_OK;warn_put_all:	flush_warnings(transfer_to, warntype);	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		if (transfer_to[cnt] != NODQUOT)			dqput(transfer_to[cnt]);		if (transfer_from[cnt] != NODQUOT)			dqput(transfer_from[cnt]);	}	return ret;}static int __init dquot_init(void){	int i;	for (i = 0; i < NR_DQHASH; i++)		INIT_LIST_HEAD(dquot_hash + i);	printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);	return 0;}__initcall(dquot_init);/* * Definitions of diskquota operations. */struct dquot_operations dquot_operations = {	dquot_initialize,		/* mandatory */	dquot_drop,			/* mandatory */	dquot_alloc_block,	dquot_alloc_inode,	dquot_free_block,	dquot_free_inode,	dquot_transfer};static inline void set_enable_flags(struct quota_mount_options *dqopt, short type){	switch (type) {		case USRQUOTA:			dqopt->flags |= DQUOT_USR_ENABLED;			break;		case GRPQUOTA:			dqopt->flags |= DQUOT_GRP_ENABLED;			break;	}}static inline void reset_enable_flags(struct quota_mount_options *dqopt, short type){	switch (type) {		case USRQUOTA:			dqopt->flags &= ~DQUOT_USR_ENABLED;			break;		case GRPQUOTA:			dqopt->flags &= ~DQUOT_GRP_ENABLED;			break;	}}/* Function in inode.c - remove pointers to dquots in icache */extern void remove_dquot_ref(struct super_block *, short);/* * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) */int quota_off(struct super_block *sb, short type){	struct file *filp;	short cnt;	struct quota_mount_options *dqopt = sb_dqopt(sb);	lock_kernel();	if (!sb)		goto out;	/* We need to serialize quota_off() for device */	down(&dqopt->dqoff_sem);	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {		if (type != -1 && cnt != type)			continue;		if (!is_enabled(dqopt, cnt))			continue;		reset_enable_flags(dqopt, cnt);		/* Note: these are blocking operations */		remove_dquot_ref(sb, cnt);		invalidate_dquots(sb, cnt);		filp = dqopt->files[cnt];		dqopt->files[cnt] = (struct file *)NULL;		dqopt->inode_expire[cnt] = 0;		dqopt->block_expire[cnt] = 0;		fput(filp);	}		up(&dqopt->dqoff_sem);out:	unlock_kernel();	return 0;}static inline int check_quotafile_size(loff_t size){	ulong blocks = size >> BLOCK_SIZE_BITS;	size_t off = size & (BLOCK_SIZE - 1);	return !(((blocks % sizeof(struct dqblk)) * BLOCK_SIZE + off % sizeof(struct dqblk)) % sizeof(struct dqblk));}static int quota_on(struct super_block *sb, short type, char *path){	struct file *f;	struct inode *inode;	struct dquot *dquot;	struct quota_mount_options *dqopt = sb_dqopt(sb);	char *tmp;	int error;	if (is_enabled(dqopt, type))		return -EBUSY;	down(&dqopt->dqoff_sem);	tmp = getname(path);	error = PTR_ERR(tmp);	if (IS_ERR(tmp))		goto out_lock;	f = filp_open(tmp, O_RDWR, 0600);	putname(tmp);	error = PTR_ERR(f);	if (IS_ERR(f))		goto out_lock;	error = -EIO;	if (!f->f_op || !f->f_op->read || !f->f_op->write)		goto out_f;	inode = f->f_dentry->d_inode;	error = -EACCES;	if (!S_ISREG(inode->i_mode))		goto out_f;	error = -EINVAL;	if (inode->i_size == 0 || !check_quotafile_size(inode->i_size))		goto out_f;	/* We don't want quota on quota files */	dquot_drop(inode);	inode->i_flags |= S_NOQUOTA;	dqopt->files[type] = f;	sb->dq_op = &dquot_operations;	set_enable_flags(dqopt, type);	dquot = dqget(sb, 0, type);	dqopt->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME;	dqopt->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME;	dqput(dquot);	add_dquot_ref(sb, type);	up(&dqopt->dqoff_sem);	return 0;out_f:	filp_close(f, NULL);out_lock:	up(&dqopt->dqoff_sem);	return error; }/* * This is the system call interface. This communicates with * the user-level programs. Currently this only supports diskquota * calls. Maybe we need to add the process quotas etc. in the future, * but we probably should use rlimits for that. */asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr){	int cmds = 0, type = 0, flags = 0;	kdev_t dev;	struct super_block *sb = NULL;	int ret = -EINVAL;	lock_kernel();	cmds = cmd >> SUBCMDSHIFT;	type = cmd & SUBCMDMASK;	if ((u_int) type >= MAXQUOTAS)		goto out;	if (id & ~0xFFFF)		goto out;	ret = -EPERM;	switch (cmds) {		case Q_SYNC:		case Q_GETSTATS:			break;		case Q_GETQUOTA:			if (((type == USRQUOTA && current->euid != id) ||			     (type == GRPQUOTA && !in_egroup_p(id))) &&			    !capable(CAP_SYS_ADMIN))				goto out;			break;		default:			if (!capable(CAP_SYS_ADMIN))				goto out;	}	ret = -EINVAL;	dev = NODEV;	if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) {		mode_t mode;		struct nameidata nd;		ret = user_path_walk(special, &nd);		if (ret)			goto out;		dev = nd.dentry->d_inode->i_rdev;		mode = nd.dentry->d_inode->i_mode;		path_release(&nd);		ret = -ENOTBLK;		if (!S_ISBLK(mode))			goto out;		ret = -ENODEV;		sb = get_super(dev);		if (!sb)			goto out;	}	ret = -EINVAL;	switch (cmds) {		case Q_QUOTAON:			ret = quota_on(sb, type, (char *) addr);			goto out;		case Q_QUOTAOFF:			ret = quota_off(sb, type);			goto out;		case Q_GETQUOTA:			ret = get_quota(sb, id, type, (struct dqblk *) addr);			goto out;		case Q_SETQUOTA:			flags |= SET_QUOTA;			break;		case Q_SETUSE:			flags |= SET_USE;			break;		case Q_SETQLIM:			flags |= SET_QLIMIT;			break;		case Q_SYNC:			ret = sync_dquots(dev, type);			goto out;		case Q_GETSTATS:			ret = get_stats(addr);			goto out;		case Q_RSQUASH:			ret = quota_root_squash(sb, type, (int *) addr);			goto out;		default:			goto out;	}	ret = -NODEV;	if (sb && sb_has_quota_enabled(sb, type))		ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr);out:	if (sb)		drop_super(sb);	unlock_kernel();	return ret;}

⌨️ 快捷键说明

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