diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/drivers/block/vroot.c linux-2.6.16-vs2.1.x-cq0.01/drivers/block/vroot.c --- linux-2.6.16-vs2.1.1-rc16.2/drivers/block/vroot.c 2006-03-24 04:43:22 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/drivers/block/vroot.c 2006-04-15 23:42:19 +0200 @@ -60,7 +60,7 @@ static int vroot_set_dev( } else goto out_fput; - vxdprintk(VXD_CBIT(misc, 0), + vxdprintk(VXD_CBIT(quota, 1), "vroot[%d]_set_dev: dev=" VXF_DEV, vr->vr_number, VXD_DEV(real_bdev)); @@ -87,7 +87,7 @@ static int vroot_clr_dev( real_bdev = vr->vr_device; - vxdprintk(VXD_CBIT(misc, 0), + vxdprintk(VXD_CBIT(quota, 1), "vroot[%d]_clr_dev: dev=" VXF_DEV, vr->vr_number, VXD_DEV(real_bdev)); @@ -157,7 +157,7 @@ struct block_device *__vroot_get_real_bd vr = &vroot_dev[minor]; real_bdev = vr->vr_device; - vxdprintk(VXD_CBIT(misc, 0), + vxdprintk(VXD_CBIT(quota, 1), "vroot[%d]_get_real_bdev: dev=" VXF_DEV, vr->vr_number, VXD_DEV(real_bdev)); diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/fs/buffer.c linux-2.6.16-vs2.1.x-cq0.01/fs/buffer.c --- linux-2.6.16-vs2.1.1-rc16.2/fs/buffer.c 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/fs/buffer.c 2006-04-15 23:42:19 +0200 @@ -168,7 +168,7 @@ EXPORT_SYMBOL(sync_blockdev); int fsync_super(struct super_block *sb) { sync_inodes_sb(sb, 0); - DQUOT_SYNC(sb->s_dqh); + DQUOT_SYNC_ALL(sb); lock_super(sb); if (sb->s_dirt && sb->s_op->write_super) sb->s_op->write_super(sb); @@ -217,7 +217,7 @@ struct super_block *freeze_bdev(struct b smp_wmb(); sync_inodes_sb(sb, 0); - DQUOT_SYNC(sb->s_dqh); + DQUOT_SYNC_ALL(sb); lock_super(sb); if (sb->s_dirt && sb->s_op->write_super) @@ -276,7 +276,7 @@ static void do_sync(unsigned long wait) { wakeup_pdflush(0); sync_inodes(0); /* All mappings, inodes and their blockdevs */ - DQUOT_SYNC(NULL); + DQUOT_SYNC_ALL(NULL); sync_supers(); /* Write the superblocks */ sync_filesystems(0); /* Start syncing the filesystems */ sync_filesystems(wait); /* Waitingly sync the filesystems */ diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/fs/dquot.c linux-2.6.16-vs2.1.x-cq0.01/fs/dquot.c --- linux-2.6.16-vs2.1.1-rc16.2/fs/dquot.c 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/fs/dquot.c 2006-04-15 23:42:19 +0200 @@ -446,7 +446,7 @@ static void invalidate_dquots(struct dqh static LIST_HEAD(dqhash_list); -struct dqhash *new_dqhash(struct super_block *sb, unsigned int id) +struct dqhash *dqh_create(struct super_block *sb, tag_t tag) { struct dqhash *hash; int err; @@ -457,10 +457,11 @@ struct dqhash *new_dqhash(struct super_b goto out; memset(hash, 0, sizeof(struct dqhash)); - hash->dqh_id = id; + hash->dqh_tag = tag; atomic_set(&hash->dqh_count, 1); INIT_LIST_HEAD(&hash->dqh_list); + INIT_LIST_HEAD(&hash->dqh_sblist); sema_init(&hash->dqh_dqopt.dqio_sem, 1); sema_init(&hash->dqh_dqopt.dqonoff_sem, 1); @@ -471,23 +472,24 @@ struct dqhash *new_dqhash(struct super_b lock_kernel(); list_add(&hash->dqh_list, &dqhash_list); + list_add(&hash->dqh_sblist, &sb->s_dqhs); unlock_kernel(); - vxdprintk(VXD_CBIT(misc, 0), - "new_dqhash: %p [#0x%08x]", hash, hash->dqh_id); + vxdprintk(VXD_CBIT(quota, 0), + "dqh_create: %p [%p,#%u]", hash, + hash->dqh_sb, hash->dqh_tag); return hash; - - // kfree(hash); out: return ERR_PTR(err); } -void destroy_dqhash(struct dqhash *hash) +void dqh_destroy(struct dqhash *hash) { int cnt; - vxdprintk(VXD_CBIT(misc, 0), - "destroy_dqhash: %p [#0x%08x] c=%d", - hash, hash->dqh_id, atomic_read(&hash->dqh_count)); + vxdprintk(VXD_CBIT(quota, 0), + "dqh_destroy: %p [%p,#%u] c=%d", + hash, hash->dqh_sb, hash->dqh_tag, + atomic_read(&hash->dqh_count)); lock_kernel(); list_del_init(&hash->dqh_list); unlock_kernel(); @@ -496,24 +498,22 @@ void destroy_dqhash(struct dqhash *hash) kfree(hash); } - -struct dqhash *find_dqhash(unsigned int id) +struct dqhash *dqh_locate(struct super_block *sb, tag_t tag) { - struct list_head *head; - struct dqhash *hash; + struct dqhash *hash, *tmp; lock_kernel(); - list_for_each(head, &dqhash_list) { - hash = list_entry(head, struct dqhash, dqh_list); - if (hash->dqh_id == id) + list_for_each_entry_safe(hash, tmp, &sb->s_dqhs, dqh_sblist) { + if (hash->dqh_tag == tag) goto dqh_found; } unlock_kernel(); return NULL; dqh_found: + dqhget(hash); unlock_kernel(); - return dqhget(hash); + return hash; } @@ -1255,7 +1255,7 @@ int dquot_transfer(struct inode *inode, qsize_t space; struct dquot *transfer_from[MAXQUOTAS]; struct dquot *transfer_to[MAXQUOTAS]; - struct dqhash *dqh = inode->i_sb->s_dqh; + struct dqhash *dqh = inode->i_dqh; 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]; diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/fs/ext3/super.c linux-2.6.16-vs2.1.x-cq0.01/fs/ext3/super.c --- linux-2.6.16-vs2.1.1-rc16.2/fs/ext3/super.c 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/fs/ext3/super.c 2006-04-15 23:42:19 +0200 @@ -911,7 +911,7 @@ static int parse_options (char *options, case Opt_grpjquota: qtype = GRPQUOTA; set_qf_name: - if (dqh_any_quota_enabled(sb->s_dqh)) { + if (any_quota_enabled(sb)) { printk(KERN_ERR "EXT3-fs: Cannot change journalled " "quota options when quota turned on.\n"); @@ -949,7 +949,7 @@ set_qf_name: case Opt_offgrpjquota: qtype = GRPQUOTA; clear_qf_name: - if (dqh_any_quota_enabled(sb->s_dqh)) { + if (any_quota_enabled(sb)) { printk(KERN_ERR "EXT3-fs: Cannot change " "journalled quota options when " "quota turned on.\n"); @@ -977,7 +977,7 @@ clear_qf_name: set_opt(sbi->s_mount_opt, GRPQUOTA); break; case Opt_noquota: - if (dqh_any_quota_enabled(sb->s_dqh)) { + if (any_quota_enabled(sb)) { printk(KERN_ERR "EXT3-fs: Cannot change quota " "options when quota turned on.\n"); return 0; @@ -1249,7 +1249,7 @@ static void ext3_orphan_cleanup (struct /* Turn on quotas so that they are updated correctly */ for (i = 0; i < MAXQUOTAS; i++) { if (EXT3_SB(sb)->s_qf_names[i]) { - int ret = ext3_quota_on_mount(sb->s_dqh, i); + int ret = ext3_quota_on_mount(sb, i); if (ret < 0) printk(KERN_ERR "EXT3-fs: Cannot turn on journalled " diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/fs/inode.c linux-2.6.16-vs2.1.x-cq0.01/fs/inode.c --- linux-2.6.16-vs2.1.1-rc16.2/fs/inode.c 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/fs/inode.c 2006-04-15 23:42:19 +0200 @@ -131,7 +131,7 @@ static struct inode *alloc_inode(struct inode->i_bytes = 0; inode->i_generation = 0; #ifdef CONFIG_QUOTA - inode->i_dqh = dqhget(sb->s_dqh); + inode->i_dqh = dqh_locate(sb, 0); memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); #endif inode->i_pipe = NULL; diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/fs/namespace.c linux-2.6.16-vs2.1.x-cq0.01/fs/namespace.c --- linux-2.6.16-vs2.1.1-rc16.2/fs/namespace.c 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/fs/namespace.c 2006-04-15 23:42:19 +0200 @@ -627,7 +627,7 @@ static int do_umount(struct vfsmount *mn down_write(&sb->s_umount); if (!(sb->s_flags & MS_RDONLY)) { lock_kernel(); - DQUOT_OFF(sb->s_dqh); + DQUOT_OFF_ALL(sb); retval = do_remount_sb(sb, MS_RDONLY, NULL, 0); unlock_kernel(); } diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/fs/quota.c linux-2.6.16-vs2.1.x-cq0.01/fs/quota.c --- linux-2.6.16-vs2.1.1-rc16.2/fs/quota.c 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/fs/quota.c 2006-04-15 23:42:19 +0200 @@ -19,6 +19,7 @@ #include #include #include +#include #include /* Check validity of generic quotactl commands */ @@ -191,7 +192,7 @@ static void quota_sync_dqh(struct dqhash continue; if (!dqh_has_quota_enabled(hash, cnt)) continue; - vxdprintk(VXD_CBIT(quota, 0), + vxdprintk(VXD_CBIT(quota, 1), "quota_sync_dqh(%p,%d) discard inode %p", hash, type, dqh_dqopt(hash)->files[cnt]); discard[cnt] = igrab(dqh_dqopt(hash)->files[cnt]); @@ -414,7 +415,7 @@ asmlinkage long sys_quotactl(unsigned in if (vroot_get_real_bdev) bdnew = vroot_get_real_bdev(bdev); else - vxdprintk(VXD_CBIT(misc, 0), + vxdprintk(VXD_CBIT(quota, 1), "vroot_get_real_bdev not set"); bdput(bdev); @@ -429,7 +430,7 @@ asmlinkage long sys_quotactl(unsigned in return -ENODEV; } if (sb) - dqh = sb->s_dqh; + dqh = dqh_locate(sb, dx_current_tag()); ret = check_quotactl_valid(dqh, type, cmds, id); if (ret >= 0) ret = do_quotactl(dqh, type, cmds, id, addr); diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/fs/super.c linux-2.6.16-vs2.1.x-cq0.01/fs/super.c --- linux-2.6.16-vs2.1.1-rc16.2/fs/super.c 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/fs/super.c 2006-04-15 23:42:19 +0200 @@ -49,6 +49,18 @@ struct file_system_type *get_fs_type(con LIST_HEAD(super_blocks); DEFINE_SPINLOCK(sb_lock); + +static inline void dqh_destroy_all(struct super_block *sb) +{ + struct dqhash *hash, *tmp; + + list_for_each_entry_safe(hash, tmp, &sb->s_dqhs, dqh_sblist) { + list_del(&hash->dqh_sblist); + dqh_destroy(hash); + } +} + + /** * alloc_super - create new superblock * @@ -85,8 +97,8 @@ static struct super_block *alloc_super(v s->s_qcop = sb_quotactl_ops; s->s_op = &default_op; s->s_time_gran = 1000000000; - /* quick hack to make dqhash id unique, sufficient for now */ - s->s_dqh = new_dqhash(s, (unsigned long)s); + INIT_LIST_HEAD(&s->s_dqhs); + dqh_create(s, 0); } out: return s; @@ -101,7 +113,7 @@ out: static inline void destroy_super(struct super_block *s) { security_sb_free(s); - dqhput(s->s_dqh); + dqh_destroy_all(s); kfree(s); } @@ -173,7 +185,7 @@ void deactivate_super(struct super_block if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { s->s_count -= S_BIAS-1; spin_unlock(&sb_lock); - DQUOT_OFF(s->s_dqh); + DQUOT_OFF_ALL(s); down_write(&s->s_umount); fs->kill_sb(s); put_filesystem(fs); diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/include/linux/fs.h linux-2.6.16-vs2.1.x-cq0.01/include/linux/fs.h --- linux-2.6.16-vs2.1.1-rc16.2/include/linux/fs.h 2006-03-27 20:01:57 +0200 +++ linux-2.6.16-vs2.1.x-cq0.01/include/linux/fs.h 2006-04-15 23:42:19 +0200 @@ -855,7 +855,7 @@ struct super_block { struct block_device *s_bdev; struct list_head s_instances; - struct dqhash *s_dqh; /* Diskquota hash */ + struct list_head s_dqhs; /* Diskquota hashes */ int s_frozen; wait_queue_head_t s_wait_unfrozen; diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/include/linux/quota.h linux-2.6.16-vs2.1.x-cq0.01/include/linux/quota.h --- linux-2.6.16-vs2.1.1-rc16.2/include/linux/quota.h 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/include/linux/quota.h 2006-04-15 23:42:19 +0200 @@ -56,6 +56,7 @@ extern spinlock_t dq_data_lock; #define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10)) #define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS) +#define HANDLE_DQHASH_NULL /* are NULL dqhash ptrs valid? */ #ifdef HANDLE_DQHASH_NULL #define dqhash_valid(hash) ((hash) != NULL) @@ -327,7 +328,8 @@ struct quota_module_name { struct dqhash { struct list_head dqh_list; /* List of all quota hashes */ - unsigned int dqh_id; /* ID for hash */ + struct list_head dqh_sblist; /* super block list */ + tag_t dqh_tag; /* tagging */ atomic_t dqh_count; /* Use count */ struct quota_info dqh_dqopt; /* Diskquota specific options */ struct dquot_operations *dqh_qop; @@ -341,15 +343,15 @@ struct dqhash { #if defined(CONFIG_QUOTA) -struct dqhash *new_dqhash(struct super_block *, unsigned int); -void destroy_dqhash(struct dqhash *); -struct dqhash *find_dqhash(unsigned int); +struct dqhash *dqh_create(struct super_block *, unsigned int); +struct dqhash *dqh_locate(struct super_block *, unsigned int); +void dqh_destroy(struct dqhash *); static inline void dqhput(struct dqhash *hash) { if (dqhash_valid(hash)) if (atomic_dec_and_test(&hash->dqh_count)) - destroy_dqhash(hash); + dqh_destroy(hash); } static inline struct dqhash *dqhget(struct dqhash *hash) @@ -361,9 +363,9 @@ static inline struct dqhash *dqhget(stru #else /* CONFIG_QUOTA */ -#define new_dqhash(sb, dqdom) (0) -#define find_dqhash(dqdom) (0) -#define destroy_dqhash(hash) do { } while(0) +#define dqh_create(sb, tag) (NULL) +#define dqh_locate(sb, tag) (NULL) +#define dqh_destroy(hash) do { } while(0) #define dqhput(hash) do { } while(0) #define dqhget(hash) (hash) diff -NurpP --minimal linux-2.6.16-vs2.1.1-rc16.2/include/linux/quotaops.h linux-2.6.16-vs2.1.x-cq0.01/include/linux/quotaops.h --- linux-2.6.16-vs2.1.1-rc16.2/include/linux/quotaops.h 2006-03-20 18:09:05 +0100 +++ linux-2.6.16-vs2.1.x-cq0.01/include/linux/quotaops.h 2006-04-15 23:42:19 +0200 @@ -177,6 +177,19 @@ static __inline__ int DQUOT_TRANSFER(str /* The following two functions cannot be called inside a transaction */ #define DQUOT_SYNC(hash) sync_dquots(hash, -1) +static __inline__ void DQUOT_SYNC_ALL(struct super_block *sb) +{ + struct dqhash *dqh, *tmp; + + if (!sb) + return; + + /* lock sb */ + list_for_each_entry_safe(dqh, tmp, &sb->s_dqhs, dqh_sblist) + DQUOT_SYNC(dqh); + /* unlock sb */ +} + static __inline__ int DQUOT_OFF(struct dqhash *hash) { int ret = -ENOSYS; @@ -187,6 +200,24 @@ static __inline__ int DQUOT_OFF(struct d return ret; } +static __inline__ int DQUOT_OFF_ALL(struct super_block *sb) +{ + struct dqhash *dqh, *tmp; + int ret = -ENOSYS; + + if (list_empty(&sb->s_dqhs)) + goto out; + /* lock sb */ + list_for_each_entry_safe(dqh, tmp, &sb->s_dqhs, dqh_sblist) { + ret = DQUOT_OFF(dqh); + if (ret) + break; + } + /* unlock sb */ +out: + return ret; +} + #else /* @@ -198,7 +229,9 @@ static __inline__ int DQUOT_OFF(struct d #define DQUOT_DROP(inode) do { } while(0) #define DQUOT_ALLOC_INODE(inode) (0) #define DQUOT_FREE_INODE(inode) do { } while(0) +#define DQUOT_SYNC_ALL(sb) do { } while(0) #define DQUOT_SYNC(hash) do { } while(0) +#define DQUOT_OFF_ALL(sb) do { } while(0) #define DQUOT_OFF(hash) do { } while(0) #define DQUOT_TRANSFER(inode, iattr) (0) static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)