brintos

brintos / linux-shallow public Read only

0
0
Text · 21.5 KiB · afceef3 Raw
854 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *	vfsv0 quota IO operations on file4 */5 6#include <linux/errno.h>7#include <linux/fs.h>8#include <linux/mount.h>9#include <linux/dqblk_v2.h>10#include <linux/kernel.h>11#include <linux/init.h>12#include <linux/module.h>13#include <linux/slab.h>14#include <linux/quotaops.h>15 16#include <asm/byteorder.h>17 18#include "quota_tree.h"19 20MODULE_AUTHOR("Jan Kara");21MODULE_DESCRIPTION("Quota trie support");22MODULE_LICENSE("GPL");23 24/*25 * Maximum quota tree depth we support. Only to limit recursion when working26 * with the tree.27 */28#define MAX_QTREE_DEPTH 629 30#define __QUOTA_QT_PARANOIA31 32static int __get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth)33{34	unsigned int epb = info->dqi_usable_bs >> 2;35 36	depth = info->dqi_qtree_depth - depth - 1;37	while (depth--)38		id /= epb;39	return id % epb;40}41 42static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth)43{44	qid_t id = from_kqid(&init_user_ns, qid);45 46	return __get_index(info, id, depth);47}48 49/* Number of entries in one blocks */50static int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)51{52	return (info->dqi_usable_bs - sizeof(struct qt_disk_dqdbheader))53	       / info->dqi_entry_size;54}55 56static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)57{58	struct super_block *sb = info->dqi_sb;59 60	memset(buf, 0, info->dqi_usable_bs);61	return sb->s_op->quota_read(sb, info->dqi_type, buf,62	       info->dqi_usable_bs, (loff_t)blk << info->dqi_blocksize_bits);63}64 65static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)66{67	struct super_block *sb = info->dqi_sb;68	ssize_t ret;69 70	ret = sb->s_op->quota_write(sb, info->dqi_type, buf,71	       info->dqi_usable_bs, (loff_t)blk << info->dqi_blocksize_bits);72	if (ret != info->dqi_usable_bs) {73		quota_error(sb, "dquota write failed");74		if (ret >= 0)75			ret = -EIO;76	}77	return ret;78}79 80static inline int do_check_range(struct super_block *sb, const char *val_name,81				 uint val, uint min_val, uint max_val)82{83	if (val < min_val || val > max_val) {84		quota_error(sb, "Getting %s %u out of range %u-%u",85			    val_name, val, min_val, max_val);86		return -EUCLEAN;87	}88 89	return 0;90}91 92static int check_dquot_block_header(struct qtree_mem_dqinfo *info,93				    struct qt_disk_dqdbheader *dh)94{95	int err = 0;96 97	err = do_check_range(info->dqi_sb, "dqdh_next_free",98			     le32_to_cpu(dh->dqdh_next_free), 0,99			     info->dqi_blocks - 1);100	if (err)101		return err;102	err = do_check_range(info->dqi_sb, "dqdh_prev_free",103			     le32_to_cpu(dh->dqdh_prev_free), 0,104			     info->dqi_blocks - 1);105	if (err)106		return err;107	err = do_check_range(info->dqi_sb, "dqdh_entries",108			     le16_to_cpu(dh->dqdh_entries), 0,109			     qtree_dqstr_in_blk(info));110 111	return err;112}113 114/* Remove empty block from list and return it */115static int get_free_dqblk(struct qtree_mem_dqinfo *info)116{117	char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);118	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;119	int ret, blk;120 121	if (!buf)122		return -ENOMEM;123	if (info->dqi_free_blk) {124		blk = info->dqi_free_blk;125		ret = read_blk(info, blk, buf);126		if (ret < 0)127			goto out_buf;128		ret = check_dquot_block_header(info, dh);129		if (ret)130			goto out_buf;131		info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);132	}133	else {134		memset(buf, 0, info->dqi_usable_bs);135		/* Assure block allocation... */136		ret = write_blk(info, info->dqi_blocks, buf);137		if (ret < 0)138			goto out_buf;139		blk = info->dqi_blocks++;140	}141	mark_info_dirty(info->dqi_sb, info->dqi_type);142	ret = blk;143out_buf:144	kfree(buf);145	return ret;146}147 148/* Insert empty block to the list */149static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk)150{151	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;152	int err;153 154	dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk);155	dh->dqdh_prev_free = cpu_to_le32(0);156	dh->dqdh_entries = cpu_to_le16(0);157	err = write_blk(info, blk, buf);158	if (err < 0)159		return err;160	info->dqi_free_blk = blk;161	mark_info_dirty(info->dqi_sb, info->dqi_type);162	return 0;163}164 165/* Remove given block from the list of blocks with free entries */166static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf,167			       uint blk)168{169	char *tmpbuf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);170	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;171	uint nextblk = le32_to_cpu(dh->dqdh_next_free);172	uint prevblk = le32_to_cpu(dh->dqdh_prev_free);173	int err;174 175	if (!tmpbuf)176		return -ENOMEM;177	if (nextblk) {178		err = read_blk(info, nextblk, tmpbuf);179		if (err < 0)180			goto out_buf;181		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =182							dh->dqdh_prev_free;183		err = write_blk(info, nextblk, tmpbuf);184		if (err < 0)185			goto out_buf;186	}187	if (prevblk) {188		err = read_blk(info, prevblk, tmpbuf);189		if (err < 0)190			goto out_buf;191		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_next_free =192							dh->dqdh_next_free;193		err = write_blk(info, prevblk, tmpbuf);194		if (err < 0)195			goto out_buf;196	} else {197		info->dqi_free_entry = nextblk;198		mark_info_dirty(info->dqi_sb, info->dqi_type);199	}200	kfree(tmpbuf);201	dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);202	/* No matter whether write succeeds block is out of list */203	if (write_blk(info, blk, buf) < 0)204		quota_error(info->dqi_sb, "Can't write block (%u) "205			    "with free entries", blk);206	return 0;207out_buf:208	kfree(tmpbuf);209	return err;210}211 212/* Insert given block to the beginning of list with free entries */213static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf,214			       uint blk)215{216	char *tmpbuf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);217	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;218	int err;219 220	if (!tmpbuf)221		return -ENOMEM;222	dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry);223	dh->dqdh_prev_free = cpu_to_le32(0);224	err = write_blk(info, blk, buf);225	if (err < 0)226		goto out_buf;227	if (info->dqi_free_entry) {228		err = read_blk(info, info->dqi_free_entry, tmpbuf);229		if (err < 0)230			goto out_buf;231		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =232							cpu_to_le32(blk);233		err = write_blk(info, info->dqi_free_entry, tmpbuf);234		if (err < 0)235			goto out_buf;236	}237	kfree(tmpbuf);238	info->dqi_free_entry = blk;239	mark_info_dirty(info->dqi_sb, info->dqi_type);240	return 0;241out_buf:242	kfree(tmpbuf);243	return err;244}245 246/* Is the entry in the block free? */247int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk)248{249	int i;250 251	for (i = 0; i < info->dqi_entry_size; i++)252		if (disk[i])253			return 0;254	return 1;255}256EXPORT_SYMBOL(qtree_entry_unused);257 258/* Find space for dquot */259static uint find_free_dqentry(struct qtree_mem_dqinfo *info,260			      struct dquot *dquot, int *err)261{262	uint blk, i;263	struct qt_disk_dqdbheader *dh;264	char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);265	char *ddquot;266 267	*err = 0;268	if (!buf) {269		*err = -ENOMEM;270		return 0;271	}272	dh = (struct qt_disk_dqdbheader *)buf;273	if (info->dqi_free_entry) {274		blk = info->dqi_free_entry;275		*err = read_blk(info, blk, buf);276		if (*err < 0)277			goto out_buf;278		*err = check_dquot_block_header(info, dh);279		if (*err)280			goto out_buf;281	} else {282		blk = get_free_dqblk(info);283		if ((int)blk < 0) {284			*err = blk;285			kfree(buf);286			return 0;287		}288		memset(buf, 0, info->dqi_usable_bs);289		/* This is enough as the block is already zeroed and the entry290		 * list is empty... */291		info->dqi_free_entry = blk;292		mark_info_dirty(dquot->dq_sb, dquot->dq_id.type);293	}294	/* Block will be full? */295	if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) {296		*err = remove_free_dqentry(info, buf, blk);297		if (*err < 0) {298			quota_error(dquot->dq_sb, "Can't remove block (%u) "299				    "from entry free list", blk);300			goto out_buf;301		}302	}303	le16_add_cpu(&dh->dqdh_entries, 1);304	/* Find free structure in block */305	ddquot = buf + sizeof(struct qt_disk_dqdbheader);306	for (i = 0; i < qtree_dqstr_in_blk(info); i++) {307		if (qtree_entry_unused(info, ddquot))308			break;309		ddquot += info->dqi_entry_size;310	}311#ifdef __QUOTA_QT_PARANOIA312	if (i == qtree_dqstr_in_blk(info)) {313		quota_error(dquot->dq_sb, "Data block full but it shouldn't");314		*err = -EIO;315		goto out_buf;316	}317#endif318	*err = write_blk(info, blk, buf);319	if (*err < 0) {320		quota_error(dquot->dq_sb, "Can't write quota data block %u",321			    blk);322		goto out_buf;323	}324	dquot->dq_off = ((loff_t)blk << info->dqi_blocksize_bits) +325			sizeof(struct qt_disk_dqdbheader) +326			i * info->dqi_entry_size;327	kfree(buf);328	return blk;329out_buf:330	kfree(buf);331	return 0;332}333 334/* Insert reference to structure into the trie */335static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,336			  uint *blks, int depth)337{338	char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);339	int ret = 0, newson = 0, newact = 0;340	__le32 *ref;341	uint newblk;342	int i;343 344	if (!buf)345		return -ENOMEM;346	if (!blks[depth]) {347		ret = get_free_dqblk(info);348		if (ret < 0)349			goto out_buf;350		for (i = 0; i < depth; i++)351			if (ret == blks[i]) {352				quota_error(dquot->dq_sb,353					"Free block already used in tree: block %u",354					ret);355				ret = -EIO;356				goto out_buf;357			}358		blks[depth] = ret;359		memset(buf, 0, info->dqi_usable_bs);360		newact = 1;361	} else {362		ret = read_blk(info, blks[depth], buf);363		if (ret < 0) {364			quota_error(dquot->dq_sb, "Can't read tree quota "365				    "block %u", blks[depth]);366			goto out_buf;367		}368	}369	ref = (__le32 *)buf;370	newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);371	ret = do_check_range(dquot->dq_sb, "block", newblk, 0,372			     info->dqi_blocks - 1);373	if (ret)374		goto out_buf;375	if (!newblk) {376		newson = 1;377	} else {378		for (i = 0; i <= depth; i++)379			if (newblk == blks[i]) {380				quota_error(dquot->dq_sb,381					"Cycle in quota tree detected: block %u index %u",382					blks[depth],383					get_index(info, dquot->dq_id, depth));384				ret = -EIO;385				goto out_buf;386			}387	}388	blks[depth + 1] = newblk;389	if (depth == info->dqi_qtree_depth - 1) {390#ifdef __QUOTA_QT_PARANOIA391		if (newblk) {392			quota_error(dquot->dq_sb, "Inserting already present "393				    "quota entry (block %u)",394				    le32_to_cpu(ref[get_index(info,395						dquot->dq_id, depth)]));396			ret = -EIO;397			goto out_buf;398		}399#endif400		blks[depth + 1] = find_free_dqentry(info, dquot, &ret);401	} else {402		ret = do_insert_tree(info, dquot, blks, depth + 1);403	}404	if (newson && ret >= 0) {405		ref[get_index(info, dquot->dq_id, depth)] =406						cpu_to_le32(blks[depth + 1]);407		ret = write_blk(info, blks[depth], buf);408	} else if (newact && ret < 0) {409		put_free_dqblk(info, buf, blks[depth]);410	}411out_buf:412	kfree(buf);413	return ret;414}415 416/* Wrapper for inserting quota structure into tree */417static inline int dq_insert_tree(struct qtree_mem_dqinfo *info,418				 struct dquot *dquot)419{420	uint blks[MAX_QTREE_DEPTH] = { QT_TREEOFF };421 422#ifdef __QUOTA_QT_PARANOIA423	if (info->dqi_blocks <= QT_TREEOFF) {424		quota_error(dquot->dq_sb, "Quota tree root isn't allocated!");425		return -EIO;426	}427#endif428	if (info->dqi_qtree_depth >= MAX_QTREE_DEPTH) {429		quota_error(dquot->dq_sb, "Quota tree depth too big!");430		return -EIO;431	}432	return do_insert_tree(info, dquot, blks, 0);433}434 435/*436 * We don't have to be afraid of deadlocks as we never have quotas on quota437 * files...438 */439int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)440{441	int type = dquot->dq_id.type;442	struct super_block *sb = dquot->dq_sb;443	ssize_t ret;444	char *ddquot = kmalloc(info->dqi_entry_size, GFP_KERNEL);445 446	if (!ddquot)447		return -ENOMEM;448 449	/* dq_off is guarded by dqio_sem */450	if (!dquot->dq_off) {451		ret = dq_insert_tree(info, dquot);452		if (ret < 0) {453			quota_error(sb, "Error %zd occurred while creating "454				    "quota", ret);455			kfree(ddquot);456			return ret;457		}458	}459	spin_lock(&dquot->dq_dqb_lock);460	info->dqi_ops->mem2disk_dqblk(ddquot, dquot);461	spin_unlock(&dquot->dq_dqb_lock);462	ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size,463				    dquot->dq_off);464	if (ret != info->dqi_entry_size) {465		quota_error(sb, "dquota write failed");466		if (ret >= 0)467			ret = -ENOSPC;468	} else {469		ret = 0;470	}471	dqstats_inc(DQST_WRITES);472	kfree(ddquot);473 474	return ret;475}476EXPORT_SYMBOL(qtree_write_dquot);477 478/* Free dquot entry in data block */479static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot,480			uint blk)481{482	struct qt_disk_dqdbheader *dh;483	char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);484	int ret = 0;485 486	if (!buf)487		return -ENOMEM;488	if (dquot->dq_off >> info->dqi_blocksize_bits != blk) {489		quota_error(dquot->dq_sb, "Quota structure has offset to "490			"other block (%u) than it should (%u)", blk,491			(uint)(dquot->dq_off >> info->dqi_blocksize_bits));492		ret = -EIO;493		goto out_buf;494	}495	ret = read_blk(info, blk, buf);496	if (ret < 0) {497		quota_error(dquot->dq_sb, "Can't read quota data block %u",498			    blk);499		goto out_buf;500	}501	dh = (struct qt_disk_dqdbheader *)buf;502	ret = check_dquot_block_header(info, dh);503	if (ret)504		goto out_buf;505	le16_add_cpu(&dh->dqdh_entries, -1);506	if (!le16_to_cpu(dh->dqdh_entries)) {	/* Block got free? */507		ret = remove_free_dqentry(info, buf, blk);508		if (ret >= 0)509			ret = put_free_dqblk(info, buf, blk);510		if (ret < 0) {511			quota_error(dquot->dq_sb, "Can't move quota data block "512				    "(%u) to free list", blk);513			goto out_buf;514		}515	} else {516		memset(buf +517		       (dquot->dq_off & ((1 << info->dqi_blocksize_bits) - 1)),518		       0, info->dqi_entry_size);519		if (le16_to_cpu(dh->dqdh_entries) ==520		    qtree_dqstr_in_blk(info) - 1) {521			/* Insert will write block itself */522			ret = insert_free_dqentry(info, buf, blk);523			if (ret < 0) {524				quota_error(dquot->dq_sb, "Can't insert quota "525				    "data block (%u) to free entry list", blk);526				goto out_buf;527			}528		} else {529			ret = write_blk(info, blk, buf);530			if (ret < 0) {531				quota_error(dquot->dq_sb, "Can't write quota "532					    "data block %u", blk);533				goto out_buf;534			}535		}536	}537	dquot->dq_off = 0;	/* Quota is now unattached */538out_buf:539	kfree(buf);540	return ret;541}542 543/* Remove reference to dquot from tree */544static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,545		       uint *blks, int depth)546{547	char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);548	int ret = 0;549	uint newblk;550	__le32 *ref = (__le32 *)buf;551	int i;552 553	if (!buf)554		return -ENOMEM;555	ret = read_blk(info, blks[depth], buf);556	if (ret < 0) {557		quota_error(dquot->dq_sb, "Can't read quota data block %u",558			    blks[depth]);559		goto out_buf;560	}561	newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);562	ret = do_check_range(dquot->dq_sb, "block", newblk, QT_TREEOFF,563			     info->dqi_blocks - 1);564	if (ret)565		goto out_buf;566 567	for (i = 0; i <= depth; i++)568		if (newblk == blks[i]) {569			quota_error(dquot->dq_sb,570				"Cycle in quota tree detected: block %u index %u",571				blks[depth],572				get_index(info, dquot->dq_id, depth));573			ret = -EIO;574			goto out_buf;575		}576	if (depth == info->dqi_qtree_depth - 1) {577		ret = free_dqentry(info, dquot, newblk);578		blks[depth + 1] = 0;579	} else {580		blks[depth + 1] = newblk;581		ret = remove_tree(info, dquot, blks, depth + 1);582	}583	if (ret >= 0 && !blks[depth + 1]) {584		ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0);585		/* Block got empty? */586		for (i = 0; i < (info->dqi_usable_bs >> 2) && !ref[i]; i++)587			;588		/* Don't put the root block into the free block list */589		if (i == (info->dqi_usable_bs >> 2)590		    && blks[depth] != QT_TREEOFF) {591			put_free_dqblk(info, buf, blks[depth]);592			blks[depth] = 0;593		} else {594			ret = write_blk(info, blks[depth], buf);595			if (ret < 0)596				quota_error(dquot->dq_sb,597					    "Can't write quota tree block %u",598					    blks[depth]);599		}600	}601out_buf:602	kfree(buf);603	return ret;604}605 606/* Delete dquot from tree */607int qtree_delete_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)608{609	uint blks[MAX_QTREE_DEPTH] = { QT_TREEOFF };610 611	if (!dquot->dq_off)	/* Even not allocated? */612		return 0;613	if (info->dqi_qtree_depth >= MAX_QTREE_DEPTH) {614		quota_error(dquot->dq_sb, "Quota tree depth too big!");615		return -EIO;616	}617	return remove_tree(info, dquot, blks, 0);618}619EXPORT_SYMBOL(qtree_delete_dquot);620 621/* Find entry in block */622static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,623				 struct dquot *dquot, uint blk)624{625	char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);626	loff_t ret = 0;627	int i;628	char *ddquot;629 630	if (!buf)631		return -ENOMEM;632	ret = read_blk(info, blk, buf);633	if (ret < 0) {634		quota_error(dquot->dq_sb, "Can't read quota tree "635			    "block %u", blk);636		goto out_buf;637	}638	ddquot = buf + sizeof(struct qt_disk_dqdbheader);639	for (i = 0; i < qtree_dqstr_in_blk(info); i++) {640		if (info->dqi_ops->is_id(ddquot, dquot))641			break;642		ddquot += info->dqi_entry_size;643	}644	if (i == qtree_dqstr_in_blk(info)) {645		quota_error(dquot->dq_sb,646			    "Quota for id %u referenced but not present",647			    from_kqid(&init_user_ns, dquot->dq_id));648		ret = -EIO;649		goto out_buf;650	} else {651		ret = ((loff_t)blk << info->dqi_blocksize_bits) + sizeof(struct652		  qt_disk_dqdbheader) + i * info->dqi_entry_size;653	}654out_buf:655	kfree(buf);656	return ret;657}658 659/* Find entry for given id in the tree */660static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,661				struct dquot *dquot, uint *blks, int depth)662{663	char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);664	loff_t ret = 0;665	__le32 *ref = (__le32 *)buf;666	uint blk;667	int i;668 669	if (!buf)670		return -ENOMEM;671	ret = read_blk(info, blks[depth], buf);672	if (ret < 0) {673		quota_error(dquot->dq_sb, "Can't read quota tree block %u",674			    blks[depth]);675		goto out_buf;676	}677	ret = 0;678	blk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);679	if (!blk)	/* No reference? */680		goto out_buf;681	ret = do_check_range(dquot->dq_sb, "block", blk, QT_TREEOFF,682			     info->dqi_blocks - 1);683	if (ret)684		goto out_buf;685 686	/* Check for cycles in the tree */687	for (i = 0; i <= depth; i++)688		if (blk == blks[i]) {689			quota_error(dquot->dq_sb,690				"Cycle in quota tree detected: block %u index %u",691				blks[depth],692				get_index(info, dquot->dq_id, depth));693			ret = -EIO;694			goto out_buf;695		}696	blks[depth + 1] = blk;697	if (depth < info->dqi_qtree_depth - 1)698		ret = find_tree_dqentry(info, dquot, blks, depth + 1);699	else700		ret = find_block_dqentry(info, dquot, blk);701out_buf:702	kfree(buf);703	return ret;704}705 706/* Find entry for given id in the tree - wrapper function */707static inline loff_t find_dqentry(struct qtree_mem_dqinfo *info,708				  struct dquot *dquot)709{710	uint blks[MAX_QTREE_DEPTH] = { QT_TREEOFF };711 712	if (info->dqi_qtree_depth >= MAX_QTREE_DEPTH) {713		quota_error(dquot->dq_sb, "Quota tree depth too big!");714		return -EIO;715	}716	return find_tree_dqentry(info, dquot, blks, 0);717}718 719int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)720{721	int type = dquot->dq_id.type;722	struct super_block *sb = dquot->dq_sb;723	loff_t offset;724	char *ddquot;725	int ret = 0;726 727#ifdef __QUOTA_QT_PARANOIA728	/* Invalidated quota? */729	if (!sb_dqopt(dquot->dq_sb)->files[type]) {730		quota_error(sb, "Quota invalidated while reading!");731		return -EIO;732	}733#endif734	/* Do we know offset of the dquot entry in the quota file? */735	if (!dquot->dq_off) {736		offset = find_dqentry(info, dquot);737		if (offset <= 0) {	/* Entry not present? */738			if (offset < 0)739				quota_error(sb,"Can't read quota structure "740					    "for id %u",741					    from_kqid(&init_user_ns,742						      dquot->dq_id));743			dquot->dq_off = 0;744			set_bit(DQ_FAKE_B, &dquot->dq_flags);745			memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));746			ret = offset;747			goto out;748		}749		dquot->dq_off = offset;750	}751	ddquot = kmalloc(info->dqi_entry_size, GFP_KERNEL);752	if (!ddquot)753		return -ENOMEM;754	ret = sb->s_op->quota_read(sb, type, ddquot, info->dqi_entry_size,755				   dquot->dq_off);756	if (ret != info->dqi_entry_size) {757		if (ret >= 0)758			ret = -EIO;759		quota_error(sb, "Error while reading quota structure for id %u",760			    from_kqid(&init_user_ns, dquot->dq_id));761		set_bit(DQ_FAKE_B, &dquot->dq_flags);762		memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));763		kfree(ddquot);764		goto out;765	}766	spin_lock(&dquot->dq_dqb_lock);767	info->dqi_ops->disk2mem_dqblk(dquot, ddquot);768	if (!dquot->dq_dqb.dqb_bhardlimit &&769	    !dquot->dq_dqb.dqb_bsoftlimit &&770	    !dquot->dq_dqb.dqb_ihardlimit &&771	    !dquot->dq_dqb.dqb_isoftlimit)772		set_bit(DQ_FAKE_B, &dquot->dq_flags);773	spin_unlock(&dquot->dq_dqb_lock);774	kfree(ddquot);775out:776	dqstats_inc(DQST_READS);777	return ret;778}779EXPORT_SYMBOL(qtree_read_dquot);780 781/* Check whether dquot should not be deleted. We know we are782 * the only one operating on dquot (thanks to dq_lock) */783int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)784{785	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) &&786	    !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))787		return qtree_delete_dquot(info, dquot);788	return 0;789}790EXPORT_SYMBOL(qtree_release_dquot);791 792static int find_next_id(struct qtree_mem_dqinfo *info, qid_t *id,793			unsigned int blk, int depth)794{795	char *buf = kmalloc(info->dqi_usable_bs, GFP_KERNEL);796	__le32 *ref = (__le32 *)buf;797	ssize_t ret;798	unsigned int epb = info->dqi_usable_bs >> 2;799	unsigned int level_inc = 1;800	int i;801 802	if (!buf)803		return -ENOMEM;804 805	for (i = depth; i < info->dqi_qtree_depth - 1; i++)806		level_inc *= epb;807 808	ret = read_blk(info, blk, buf);809	if (ret < 0) {810		quota_error(info->dqi_sb,811			    "Can't read quota tree block %u", blk);812		goto out_buf;813	}814	for (i = __get_index(info, *id, depth); i < epb; i++) {815		uint blk_no = le32_to_cpu(ref[i]);816 817		if (blk_no == 0) {818			*id += level_inc;819			continue;820		}821		ret = do_check_range(info->dqi_sb, "block", blk_no, 0,822				     info->dqi_blocks - 1);823		if (ret)824			goto out_buf;825		if (depth == info->dqi_qtree_depth - 1) {826			ret = 0;827			goto out_buf;828		}829		ret = find_next_id(info, id, blk_no, depth + 1);830		if (ret != -ENOENT)831			break;832	}833	if (i == epb) {834		ret = -ENOENT;835		goto out_buf;836	}837out_buf:838	kfree(buf);839	return ret;840}841 842int qtree_get_next_id(struct qtree_mem_dqinfo *info, struct kqid *qid)843{844	qid_t id = from_kqid(&init_user_ns, *qid);845	int ret;846 847	ret = find_next_id(info, &id, QT_TREEOFF, 0);848	if (ret < 0)849		return ret;850	*qid = make_kqid(&init_user_ns, qid->type, id);851	return 0;852}853EXPORT_SYMBOL(qtree_get_next_id);854