Re: [RFC] quota: 64-bit limits with vfs, updated

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun 16-03-08 14:21:17, Andrew Perepechko wrote:
> Introduce 64-bit quota limits support with QFMT_VFS_V0. 
> 
> This patch is incremental to quota-do-not-allow-setting-of-quota-limits-to-too-high-values.patch included in -mm tree.
> 
> Signed-off-by: Andrew Perepechko <andrew.perepechko@xxxxxxx>
  Nice, I like the patch. Do you have patches for quota tools so that we
can also create files in the format with the new revision? I ask mainly
because I'd like to test it a bit before submitting ;).

								Honza

> 
> ---
> 
>  fs/quota_v2.c              |  263 ++++++++++++++++++++++++++++++++-------------
>  include/linux/dqblk_v2.h   |    1
>  include/linux/quota.h      |   10 -
>  include/linux/quotaio_v2.h |   34 ++++-
>  4 files changed, 222 insertions(+), 86 deletions(-)
> 
> diff -rNpu linux.2.6.24.3.old/fs/quota_v2.c linux-2.6.24.3/fs/quota_v2.c
> --- linux.2.6.24.3.old/fs/quota_v2.c	2008-03-14 15:34:16.000000000 +0300
> +++ linux-2.6.24.3/fs/quota_v2.c	2008-03-16 13:46:01.000000000 +0300
> @@ -23,26 +23,64 @@ MODULE_LICENSE("GPL");
>  typedef char *dqbuf_t;
>  
>  #define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
> -#define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
> +#define GETENTRIES(buf) ((union v2_disk_dqblk *)(((char *)buf) + \
> +			 sizeof(struct v2_disk_dqdbheader)))
> +#define REV_ASSERT(r) BUG_ON((rev) != 0 && (rev) != 1)
>  
> -/* Check whether given file is really vfsv0 quotafile */
> -static int v2_check_quota_file(struct super_block *sb, int type)
> +static const union v2_disk_dqblk emptydquot;
> +static const union v2_disk_dqblk fakedquot[2] = {
> +	{.r0 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} },
> +	{.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} }
> +};
> +
> +static inline uint v2_dqblksz(uint rev)
> +{
> +	uint sz;
> +
> +	REV_ASSERT(rev);
> +
> +	if (rev == 0)
> +		sz = sizeof(struct v2_disk_dqblk_r0);
> +	else
> +		sz = sizeof(struct v2_disk_dqblk_r1);
> +
> +	return sz;
> +}
> +
> +/* Number of quota entries in a block */
> +static inline int v2_dqstrinblk(uint rev)
> +{
> +	return (V2_DQBLKSIZE-sizeof(struct v2_disk_dqdbheader))/v2_dqblksz(rev);
> +}
> +
> +/* Get revision of a quota file, -1 if it does not look a quota file */
> +static int v2_quota_file_revision(struct super_block *sb, int type)
>  {
>  	struct v2_disk_dqheader dqhead;
>  	ssize_t size;
>  	static const uint quota_magics[] = V2_INITQMAGICS;
> -	static const uint quota_versions[] = V2_INITQVERSIONS;
> +	static const uint quota_versions_r0[] = V2_INITQVERSIONS_R0;
> +	static const uint quota_versions_r1[] = V2_INITQVERSIONS_R1;
>   
>  	size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
>  	if (size != sizeof(struct v2_disk_dqheader)) {
>  		printk("quota_v2: failed read expected=%zd got=%zd\n",
>  			sizeof(struct v2_disk_dqheader), size);
> -		return 0;
> +		return -1;
>  	}
> -	if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
> -	    le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
> -		return 0;
> -	return 1;
> +	if (le32_to_cpu(dqhead.dqh_magic) == quota_magics[type]) {
> +		if (le32_to_cpu(dqhead.dqh_version) == quota_versions_r0[type])
> +			return 0;
> +		if (le32_to_cpu(dqhead.dqh_version) == quota_versions_r1[type])
> +			return 1;
> +	}
> +	return -1;
> +}
> +
> +/* Check whether given file is really vfsv0 quotafile */
> +static inline int v2_check_quota_file(struct super_block *sb, int type)
> +{
> +	return v2_quota_file_revision(sb, type) != -1;
>  }
>  
>  /* Read information header from quota file */
> @@ -51,6 +89,13 @@ static int v2_read_file_info(struct supe
>  	struct v2_disk_dqinfo dinfo;
>  	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
>  	ssize_t size;
> +	int rev;
> +
> +	rev = v2_quota_file_revision(sb, type);
> +	if (rev < 0) {
> +		printk(KERN_WARNING "Second quota file check failed.\n");
> +		return -1;
> +	}
>  
>  	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
>  	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
> @@ -59,15 +104,22 @@ static int v2_read_file_info(struct supe
>  			sb->s_id);
>  		return -1;
>  	}
> -	/* limits are stored as unsigned 32-bit data */
> -	info->dqi_maxblimit = 0xffffffff;
> -	info->dqi_maxilimit = 0xffffffff;
>  	info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
>  	info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
>  	info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
>  	info->u.v2_i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
>  	info->u.v2_i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
>  	info->u.v2_i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
> +
> +	info->u.v2_i.dqi_revision = rev;
> +	if (rev == 0) {
> +		info->dqi_maxblimit = 0xffffffffULL;
> +		info->dqi_maxilimit = 0xffffffffULL;
> +	} else {
> +		info->dqi_maxblimit = 0xffffffffffffffffULL;
> +		info->dqi_maxilimit = 0xffffffffffffffffULL;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -97,29 +149,61 @@ static int v2_write_file_info(struct sup
>  	return 0;
>  }
>  
> -static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
> +static void disk2memdqb(struct mem_dqblk *m, union v2_disk_dqblk *d, uint rev)
>  {
> -	m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
> -	m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
> -	m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
> -	m->dqb_itime = le64_to_cpu(d->dqb_itime);
> -	m->dqb_bhardlimit = le32_to_cpu(d->dqb_bhardlimit);
> -	m->dqb_bsoftlimit = le32_to_cpu(d->dqb_bsoftlimit);
> -	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
> -	m->dqb_btime = le64_to_cpu(d->dqb_btime);
> -}
> -
> -static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
> -{
> -	d->dqb_ihardlimit = cpu_to_le32((u32)m->dqb_ihardlimit);
> -	d->dqb_isoftlimit = cpu_to_le32((u32)m->dqb_isoftlimit);
> -	d->dqb_curinodes = cpu_to_le32((u32)m->dqb_curinodes);
> -	d->dqb_itime = cpu_to_le64(m->dqb_itime);
> -	d->dqb_bhardlimit = cpu_to_le32((u32)m->dqb_bhardlimit);
> -	d->dqb_bsoftlimit = cpu_to_le32((u32)m->dqb_bsoftlimit);
> -	d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
> -	d->dqb_btime = cpu_to_le64(m->dqb_btime);
> -	d->dqb_id = cpu_to_le32(id);
> +	REV_ASSERT(rev);
> +
> +	if (rev == 0) {
> +		struct v2_disk_dqblk_r0 *ddqblk = &d->r0;
> +		m->dqb_ihardlimit = le32_to_cpu(ddqblk->dqb_ihardlimit);
> +		m->dqb_isoftlimit = le32_to_cpu(ddqblk->dqb_isoftlimit);
> +		m->dqb_curinodes = le32_to_cpu(ddqblk->dqb_curinodes);
> +		m->dqb_itime = le64_to_cpu(ddqblk->dqb_itime);
> +		m->dqb_bhardlimit = le32_to_cpu(ddqblk->dqb_bhardlimit);
> +		m->dqb_bsoftlimit = le32_to_cpu(ddqblk->dqb_bsoftlimit);
> +		m->dqb_curspace = le64_to_cpu(ddqblk->dqb_curspace);
> +		m->dqb_btime = le64_to_cpu(ddqblk->dqb_btime);
> +	} else {
> +		struct v2_disk_dqblk_r1 *ddqblk = &d->r1;
> +		m->dqb_ihardlimit = le64_to_cpu(ddqblk->dqb_ihardlimit);
> +		m->dqb_isoftlimit = le64_to_cpu(ddqblk->dqb_isoftlimit);
> +		m->dqb_curinodes = le64_to_cpu(ddqblk->dqb_curinodes);
> +		m->dqb_itime = le64_to_cpu(ddqblk->dqb_itime);
> +		m->dqb_bhardlimit = le64_to_cpu(ddqblk->dqb_bhardlimit);
> +		m->dqb_bsoftlimit = le64_to_cpu(ddqblk->dqb_bsoftlimit);
> +		m->dqb_curspace = le64_to_cpu(ddqblk->dqb_curspace);
> +		m->dqb_btime = le64_to_cpu(ddqblk->dqb_btime);
> +	}
> +}
> +
> +static void mem2diskdqb(union v2_disk_dqblk *d, struct mem_dqblk *m,
> +			qid_t id, uint rev)
> +{
> +	REV_ASSERT(rev);
> +
> +	if (rev == 0) {
> +		struct v2_disk_dqblk_r0 *ddqblk = &d->r0;
> +		ddqblk->dqb_id = cpu_to_le32(id);
> +		ddqblk->dqb_ihardlimit = cpu_to_le32((__u32)m->dqb_ihardlimit);
> +		ddqblk->dqb_isoftlimit = cpu_to_le32((__u32)m->dqb_isoftlimit);
> +		ddqblk->dqb_curinodes = cpu_to_le32((__u32)m->dqb_curinodes);
> +		ddqblk->dqb_itime = cpu_to_le64(m->dqb_itime);
> +		ddqblk->dqb_bhardlimit = cpu_to_le32((__u32)m->dqb_bhardlimit);
> +		ddqblk->dqb_bsoftlimit = cpu_to_le32((__u32)m->dqb_bsoftlimit);
> +		ddqblk->dqb_curspace = cpu_to_le64(m->dqb_curspace);
> +		ddqblk->dqb_btime = cpu_to_le64(ddqblk->dqb_btime);
> +	} else {
> +		struct v2_disk_dqblk_r1 *ddqblk = &d->r1;
> +		ddqblk->dqb_id = cpu_to_le32(id);
> +		ddqblk->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
> +		ddqblk->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
> +		ddqblk->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
> +		ddqblk->dqb_itime = cpu_to_le64(m->dqb_itime);
> +		ddqblk->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
> +		ddqblk->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
> +		ddqblk->dqb_curspace = cpu_to_le64(m->dqb_curspace);
> +		ddqblk->dqb_btime = cpu_to_le64(ddqblk->dqb_btime);
> +	}
>  }
>  
>  static dqbuf_t getdqbuf(void)
> @@ -271,10 +355,10 @@ static uint find_free_dqentry(struct dqu
>  {
>  	struct super_block *sb = dquot->dq_sb;
>  	struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
> -	uint blk, i;
> +	uint blk, i, rev = info->u.v2_i.dqi_revision;
> +	uint dqblksz = v2_dqblksz(rev), dqstrinblk = v2_dqstrinblk(rev);
>  	struct v2_disk_dqdbheader *dh;
> -	struct v2_disk_dqblk *ddquot;
> -	struct v2_disk_dqblk fakedquot;
> +	union v2_disk_dqblk *ddquot;
>  	dqbuf_t buf;
>  
>  	*err = 0;
> @@ -301,17 +385,18 @@ static uint find_free_dqentry(struct dqu
>  		info->u.v2_i.dqi_free_entry = blk;
>  		mark_info_dirty(sb, dquot->dq_type);
>  	}
> -	if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK)	/* Block will be full? */
> +	/* Block will be full? */
> +	if (le16_to_cpu(dh->dqdh_entries)+1 >= dqstrinblk)
>  		if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
>  			printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
>  			goto out_buf;
>  		}
>  	dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)+1);
> -	memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
>  	/* Find free structure in block */
> -	for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
> +	for (i = 0; i < dqstrinblk && memcmp(&emptydquot, ddquot, dqblksz);
> +	     i++, ddquot++);
>  #ifdef __QUOTA_V2_PARANOIA
> -	if (i == V2_DQSTRINBLK) {
> +	if (i == dqstrinblk) {
>  		printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
>  		*err = -EIO;
>  		goto out_buf;
> @@ -321,7 +406,8 @@ static uint find_free_dqentry(struct dqu
>  		printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
>  		goto out_buf;
>  	}
> -	dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+sizeof(struct v2_disk_dqdbheader)+i*sizeof(struct v2_disk_dqblk);
> +	dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+
> +			((char *)ddquot - (char *)buf);
>  	freedqbuf(buf);
>  	return blk;
>  out_buf:
> @@ -395,7 +481,9 @@ static int v2_write_dquot(struct dquot *
>  {
>  	int type = dquot->dq_type;
>  	ssize_t ret;
> -	struct v2_disk_dqblk ddquot, empty;
> +	union v2_disk_dqblk ddquot;
> +	uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.dqi_revision;
> +	uint dqblksz = v2_dqblksz(rev);
>  
>  	/* dq_off is guarded by dqio_mutex */
>  	if (!dquot->dq_off)
> @@ -404,18 +492,22 @@ static int v2_write_dquot(struct dquot *
>  			return ret;
>  		}
>  	spin_lock(&dq_data_lock);
> -	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
> +	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id, rev);
>  	/* Argh... We may need to write structure full of zeroes but that would be
>  	 * treated as an empty place by the rest of the code. Format change would
>  	 * be definitely cleaner but the problems probably are not worth it */
> -	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
> -	if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
> -		ddquot.dqb_itime = cpu_to_le64(1);
> +	if (!memcmp(&emptydquot, &ddquot, dqblksz)) {
> +		if (rev == 0)
> +			ddquot.r0.dqb_itime = cpu_to_le64(1);
> +		else
> +			ddquot.r1.dqb_itime = cpu_to_le64(1);
> +	}
>  	spin_unlock(&dq_data_lock);
>  	ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
> -	      (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
> -	if (ret != sizeof(struct v2_disk_dqblk)) {
> -		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
> +	      (char *)&ddquot, dqblksz, dquot->dq_off);
> +	if (ret != dqblksz) {
> +		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
> +			dquot->dq_sb->s_id);
>  		if (ret >= 0)
>  			ret = -ENOSPC;
>  	}
> @@ -434,6 +526,7 @@ static int free_dqentry(struct dquot *dq
>  	struct v2_disk_dqdbheader *dh;
>  	dqbuf_t buf = getdqbuf();
>  	int ret = 0;
> +	uint rev = sb_dqopt(sb)->info[type].u.v2_i.dqi_revision;
>  
>  	if (!buf)
>  		return -ENOMEM;
> @@ -459,8 +552,8 @@ static int free_dqentry(struct dquot *dq
>  	}
>  	else {
>  		memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
> -		  sizeof(struct v2_disk_dqblk));
> -		if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
> +		  v2_dqblksz(rev));
> +		if (le16_to_cpu(dh->dqdh_entries) == v2_dqstrinblk(rev)-1) {
>  			/* Insert will write block itself */
>  			if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
>  				printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
> @@ -532,41 +625,56 @@ static int v2_delete_dquot(struct dquot
>  	return remove_tree(dquot, &tmp, 0);
>  }
>  
> +static inline __u32 dqid(union v2_disk_dqblk *ddquot, uint rev)
> +{
> +	__u32 dq_id;
> +
> +	REV_ASSERT(rev);
> +
> +	if (rev == 0)
> +		dq_id = le32_to_cpu(ddquot->r0.dqb_id);
> +	else
> +		dq_id = le32_to_cpu(ddquot->r1.dqb_id);
> +
> +	return dq_id;
> +}
> +
>  /* Find entry in block */
>  static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
>  {
>  	dqbuf_t buf = getdqbuf();
>  	loff_t ret = 0;
>  	int i;
> -	struct v2_disk_dqblk *ddquot = GETENTRIES(buf);
> +	union v2_disk_dqblk *ddquot = GETENTRIES(buf);
> +	int type = dquot->dq_type;
> +	uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.dqi_revision;
> +	uint dqblksz = v2_dqblksz(rev), dqstrinblk = v2_dqstrinblk(rev);
>  
>  	if (!buf)
>  		return -ENOMEM;
> -	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
> +
> +	ret = read_blk(dquot->dq_sb, type, blk, buf);
> +	if (ret < 0) {
>  		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
>  		goto out_buf;
>  	}
>  	if (dquot->dq_id)
> -		for (i = 0; i < V2_DQSTRINBLK &&
> -		     le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
> +		for (i = 0; i < dqstrinblk && dqid(ddquot, rev) != dquot->dq_id;
> +		     i++, ddquot++);
>  	else {	/* ID 0 as a bit more complicated searching... */
> -		struct v2_disk_dqblk fakedquot;
> -
> -		memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
> -		for (i = 0; i < V2_DQSTRINBLK; i++)
> -			if (!le32_to_cpu(ddquot[i].dqb_id) &&
> -			    memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
> +		for (i = 0; i < dqstrinblk; i++, ddquot++)
> +			if (!dqid(ddquot, rev) &&
> +			    memcmp(&emptydquot, ddquot, dqblksz))
>  				break;
>  	}
> -	if (i == V2_DQSTRINBLK) {
> +	if (i == dqstrinblk) {
>  		printk(KERN_ERR "VFS: Quota for id %u referenced "
>  		  "but not present.\n", dquot->dq_id);
>  		ret = -EIO;
>  		goto out_buf;
>  	}
>  	else
> -		ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
> -		  v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
> +		ret = (blk << V2_DQBLKSIZE_BITS)+((char *)ddquot-(char *)buf);
>  out_buf:
>  	freedqbuf(buf);
>  	return ret;
> @@ -608,7 +716,7 @@ static int v2_read_dquot(struct dquot *d
>  {
>  	int type = dquot->dq_type;
>  	loff_t offset;
> -	struct v2_disk_dqblk ddquot, empty;
> +	union v2_disk_dqblk ddquot;
>  	int ret = 0;
>  
>  #ifdef __QUOTA_V2_PARANOIA
> @@ -629,25 +737,30 @@ static int v2_read_dquot(struct dquot *d
>  		ret = offset;
>  	}
>  	else {
> +		uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.
> +			   dqi_revision;
> +		uint  dqblksz = v2_dqblksz(rev);
>  		dquot->dq_off = offset;
> -		if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
> -		    (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
> -		    != sizeof(struct v2_disk_dqblk)) {
> +		ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
> +					   (char *)&ddquot, dqblksz, offset);
> +		if (ret != dqblksz) {
>  			if (ret >= 0)
>  				ret = -EIO;
>  			printk(KERN_ERR "VFS: Error while reading quota "
>  			  "structure for id %u.\n", dquot->dq_id);
> -			memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
> +			memset(&ddquot, 0, dqblksz);
>  		}
>  		else {
>  			ret = 0;
>  			/* We need to escape back all-zero structure */
> -			memset(&empty, 0, sizeof(struct v2_disk_dqblk));
> -			empty.dqb_itime = cpu_to_le64(1);
> -			if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
> -				ddquot.dqb_itime = 0;
> +			if (!memcmp(&fakedquot[rev], &ddquot, dqblksz)) {
> +				if (rev == 0)
> +					ddquot.r0.dqb_itime = cpu_to_le64(0);
> +				else
> +					ddquot.r1.dqb_itime = cpu_to_le64(0);
> +			}
>  		}
> -		disk2memdqb(&dquot->dq_dqb, &ddquot);
> +		disk2memdqb(&dquot->dq_dqb, &ddquot, rev);
>  		if (!dquot->dq_dqb.dqb_bhardlimit &&
>  			!dquot->dq_dqb.dqb_bsoftlimit &&
>  			!dquot->dq_dqb.dqb_ihardlimit &&
> diff -rNpu linux.2.6.24.3.old/include/linux/dqblk_v2.h linux-2.6.24.3/include/linux/dqblk_v2.h
> --- linux.2.6.24.3.old/include/linux/dqblk_v2.h	2008-02-26 03:20:20.000000000 +0300
> +++ linux-2.6.24.3/include/linux/dqblk_v2.h	2008-03-13 22:01:48.000000000 +0300
> @@ -21,6 +21,7 @@ struct v2_mem_dqinfo {
>  	unsigned int dqi_blocks;
>  	unsigned int dqi_free_blk;
>  	unsigned int dqi_free_entry;
> +	unsigned int dqi_revision;
>  };
>  
>  #endif /* _LINUX_DQBLK_V2_H */
> diff -rNpu linux.2.6.24.3.old/include/linux/quota.h linux-2.6.24.3/include/linux/quota.h
> --- linux.2.6.24.3.old/include/linux/quota.h	2008-03-14 15:34:16.000000000 +0300
> +++ linux-2.6.24.3/include/linux/quota.h	2008-03-13 22:01:48.000000000 +0300
> @@ -181,12 +181,12 @@ extern spinlock_t dq_data_lock;
>   * Data for one user/group kept in memory
>   */
>  struct mem_dqblk {
> -	__u32 dqb_bhardlimit;	/* absolute limit on disk blks alloc */
> -	__u32 dqb_bsoftlimit;	/* preferred limit on disk blks */
> +	qsize_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */
> +	qsize_t dqb_bsoftlimit;	/* preferred limit on disk blks */
>  	qsize_t dqb_curspace;	/* current used space */
> -	__u32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
> -	__u32 dqb_isoftlimit;	/* preferred inode limit */
> -	__u32 dqb_curinodes;	/* current # allocated inodes */
> +	qsize_t dqb_ihardlimit;	/* absolute limit on allocated inodes */
> +	qsize_t dqb_isoftlimit;	/* preferred inode limit */
> +	qsize_t dqb_curinodes;	/* current # allocated inodes */
>  	time_t dqb_btime;	/* time limit for excessive disk use */
>  	time_t dqb_itime;	/* time limit for excessive inode use */
>  };
> diff -rNpu linux.2.6.24.3.old/include/linux/quotaio_v2.h linux-2.6.24.3/include/linux/quotaio_v2.h
> --- linux.2.6.24.3.old/include/linux/quotaio_v2.h	2008-02-26 03:20:20.000000000 +0300
> +++ linux-2.6.24.3/include/linux/quotaio_v2.h	2008-03-16 13:46:47.000000000 +0300
> @@ -16,28 +16,51 @@
>  	0xd9c01927	/* GRPQUOTA */\
>  }
>  
> -#define V2_INITQVERSIONS {\
> +#define V2_INITQVERSIONS_R0 {\
>  	0,		/* USRQUOTA */\
>  	0		/* GRPQUOTA */\
>  }
>  
> +#define V2_INITQVERSIONS_R1 {\
> +	1,		/* USRQUOTA */\
> +	1		/* GRPQUOTA */\
> +}
> +
>  /*
>   * The following structure defines the format of the disk quota file
>   * (as it appears on disk) - the file is a radix tree whose leaves point
>   * to blocks of these structures.
>   */
> -struct v2_disk_dqblk {
> +struct v2_disk_dqblk_r0 {
>  	__le32 dqb_id;		/* id this quota applies to */
>  	__le32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
>  	__le32 dqb_isoftlimit;	/* preferred inode limit */
>  	__le32 dqb_curinodes;	/* current # allocated inodes */
> -	__le32 dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
> -	__le32 dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
> +	__le32 dqb_bhardlimit;	/* absolute limit on disk space */
> +	__le32 dqb_bsoftlimit;	/* preferred limit on disk space */
> +	__le64 dqb_curspace;	/* current space occupied (in bytes) */
> +	__le64 dqb_btime;	/* time limit for excessive disk use */
> +	__le64 dqb_itime;	/* time limit for excessive inode use */
> +};
> +
> +struct v2_disk_dqblk_r1 {
> +	__le32 dqb_id;		/* id this quota applies to */
> +	__le32 dqb_padding;	/* padding field */
> +	__le64 dqb_ihardlimit;	/* absolute limit on allocated inodes */
> +	__le64 dqb_isoftlimit;	/* preferred inode limit */
> +	__le64 dqb_curinodes;	/* current # allocated inodes */
> +	__le64 dqb_bhardlimit;	/* absolute limit on disk space */
> +	__le64 dqb_bsoftlimit;	/* preferred limit on disk space */
>  	__le64 dqb_curspace;	/* current space occupied (in bytes) */
>  	__le64 dqb_btime;	/* time limit for excessive disk use */
>  	__le64 dqb_itime;	/* time limit for excessive inode use */
>  };
>  
> +union v2_disk_dqblk {
> +	struct v2_disk_dqblk_r0 r0;
> +	struct v2_disk_dqblk_r1 r1;
> +};
> +
>  /*
>   * Here are header structures as written on disk and their in-memory copies
>   */
> @@ -59,7 +82,7 @@ struct v2_disk_dqinfo {
>  
>  /*
>   *  Structure of header of block with quota structures. It is padded to 16 bytes so
> - *  there will be space for exactly 21 quota-entries in a block
> + *  there will be space for exactly 21 (r0) or 14 (r1) quota-entries in a block
>   */
>  struct v2_disk_dqdbheader {
>  	__le32 dqdh_next_free;	/* Number of next block with free entry */
> @@ -74,6 +97,5 @@ struct v2_disk_dqdbheader {
>  #define V2_DQBLKSIZE	(1 << V2_DQBLKSIZE_BITS)	/* Size of block with quota structures */
>  #define V2_DQTREEOFF	1		/* Offset of tree in file in blocks */
>  #define V2_DQTREEDEPTH	4		/* Depth of quota tree */
> -#define V2_DQSTRINBLK	((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk))	/* Number of entries in one blocks */
>  
>  #endif /* _LINUX_QUOTAIO_V2_H */
>  
-- 
Jan Kara <jack@xxxxxxx>
SUSE Labs, CR
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux