From: Abhijith Das <adas@redhat.com> Subject: [RHEL5.1 PATCH 2/2] GFS2: BZ 201011 - quotas non-functional Date: Mon, 04 Jun 2007 17:18:06 -0500 Bugzilla: 201011 Message-Id: <46648F9E.4000309@redhat.com> Changelog: [gfs2] quotas non-functional This patch fixes an error in the quota code where a 'struct gfs2_quota_lvb*' was being passed to gfs2_adjust_quota() instead of a 'struct gfs2_quota_data*'. Also moved 'struct gfs2_quota_lvb' from fs/gfs2/incore.h to include/linux/gfs2_ondisk.h as per Steve's suggestion. Also fixes a bug where gfs2 was writing update quota usage information to the wrong location in the quota file. Signed-off-by: Abhijith Das <adas@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com> Upstream: http://git.kernel.org/?p=linux/kernel/git/steve/gfs2-2.6-nmw.git Index: linux-rhel51-quilt/fs/gfs2/incore.h =================================================================== --- linux-rhel51-quilt.orig/fs/gfs2/incore.h 2007-06-04 16:57:47.000000000 -0500 +++ linux-rhel51-quilt/fs/gfs2/incore.h 2007-06-04 17:03:43.000000000 -0500 @@ -275,14 +275,6 @@ QDF_LOCKED = 2, }; -struct gfs2_quota_lvb { - __be32 qb_magic; - u32 __pad; - __be64 qb_limit; /* Hard limit of # blocks to alloc */ - __be64 qb_warn; /* Warn user when alloc is above this # */ - __be64 qb_value; /* Current # blocks allocated */ -}; - struct gfs2_quota_data { struct list_head qd_list; unsigned int qd_count; Index: linux-rhel51-quilt/fs/gfs2/ondisk.c =================================================================== --- linux-rhel51-quilt.orig/fs/gfs2/ondisk.c 2007-06-04 16:57:47.000000000 -0500 +++ linux-rhel51-quilt/fs/gfs2/ondisk.c 2007-06-04 17:04:02.000000000 -0500 @@ -121,6 +121,16 @@ qu->qu_value = be64_to_cpu(str->qu_value); } +void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf) +{ + struct gfs2_quota *str = buf; + + str->qu_limit = cpu_to_be64(qu->qu_limit); + str->qu_warn = cpu_to_be64(qu->qu_warn); + str->qu_value = cpu_to_be64(qu->qu_value); + memset(&str->qu_reserved, 0, sizeof(str->qu_reserved)); +} + void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) { const struct gfs2_dinode_host *di = &ip->i_di; Index: linux-rhel51-quilt/fs/gfs2/quota.c =================================================================== --- linux-rhel51-quilt.orig/fs/gfs2/quota.c 2007-06-04 16:42:03.000000000 -0500 +++ linux-rhel51-quilt/fs/gfs2/quota.c 2007-06-04 17:04:02.000000000 -0500 @@ -573,12 +573,13 @@ struct inode *inode = &ip->i_inode; struct address_space *mapping = inode->i_mapping; unsigned long index = loc >> PAGE_CACHE_SHIFT; - unsigned offset = loc & (PAGE_CACHE_SHIFT - 1); + unsigned offset = loc & (PAGE_CACHE_SIZE - 1); unsigned blocksize, iblock, pos; struct buffer_head *bh; struct page *page; void *kaddr; - __be64 *ptr; + char *ptr; + struct gfs2_quota_host qp; s64 value; int err = -EIO; @@ -620,13 +621,17 @@ kaddr = kmap_atomic(page, KM_USER0); ptr = kaddr + offset; - value = (s64)be64_to_cpu(*ptr) + change; - *ptr = cpu_to_be64(value); + gfs2_quota_in(&qp, ptr); + qp.qu_value += change; + value = qp.qu_value; + gfs2_quota_out(&qp, ptr); flush_dcache_page(page); kunmap_atomic(kaddr, KM_USER0); err = 0; qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC); qd->qd_qb.qb_value = cpu_to_be64(value); + ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC); + ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value); unlock: unlock_page(page); page_cache_release(page); @@ -709,7 +714,7 @@ offset = qd2offset(qd); error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, (struct gfs2_quota_data *) - qd->qd_gl->gl_lvb); + qd); if (error) goto out_end_trans; Index: linux-rhel51-quilt/include/linux/gfs2_ondisk.h =================================================================== --- linux-rhel51-quilt.orig/include/linux/gfs2_ondisk.h 2007-06-04 16:57:47.000000000 -0500 +++ linux-rhel51-quilt/include/linux/gfs2_ondisk.h 2007-06-04 17:04:02.000000000 -0500 @@ -500,6 +500,14 @@ __u32 qc_id; }; +struct gfs2_quota_lvb { + __be32 qb_magic; + __u32 __pad; + __be64 qb_limit; /* Hard limit of # blocks to alloc */ + __be64 qb_warn; /* Warn user when alloc is above this # */ + __be64 qb_value; /* Current # blocks allocated */ +}; + #ifdef __KERNEL__ /* Translation functions */ struct gfs2_inode; @@ -511,6 +519,7 @@ extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf); extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf); extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf); +extern void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf); struct gfs2_inode; extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf);