Commit 17eb4a37 authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.17 dquota punishment

Transform new quota code to use sysctl instead of /proc/fs.
parent ace2dc79
...@@ -118,11 +118,11 @@ static void put_quota_format(struct quota_format_type *fmt) ...@@ -118,11 +118,11 @@ static void put_quota_format(struct quota_format_type *fmt)
* list is used for the sync and invalidate operations, which must look * list is used for the sync and invalidate operations, which must look
* at every dquot. * at every dquot.
* *
* Unused dquots (dq_count == 0) are added to the free_dquots list when * Unused dquots (dq_count == 0) are added to the free_dquots list when freed,
* freed, and this list is searched whenever we need an available dquot. * and this list is searched whenever we need an available dquot. Dquots are
* Dquots are removed from the list as soon as they are used again, and * removed from the list as soon as they are used again, and
* nr_free_dquots gives the number of dquots on the list. When dquot is * dqstats_array[DQSTATS_FREE] gives the number of dquots on the list. When
* invalidated it's completely released from memory. * dquot is invalidated it's completely released from memory.
* *
* Dquots with a specific identity (device, type and id) are placed on * Dquots with a specific identity (device, type and id) are placed on
* one of the dquot_hash[] hash chains. The provides an efficient search * one of the dquot_hash[] hash chains. The provides an efficient search
...@@ -148,7 +148,7 @@ static LIST_HEAD(inuse_list); ...@@ -148,7 +148,7 @@ static LIST_HEAD(inuse_list);
static LIST_HEAD(free_dquots); static LIST_HEAD(free_dquots);
static struct list_head dquot_hash[NR_DQHASH]; static struct list_head dquot_hash[NR_DQHASH];
struct dqstats dqstats; __u32 dqstats_array[DQSTATS_SIZE];
static void dqput(struct dquot *); static void dqput(struct dquot *);
static struct dquot *dqduplicate(struct dquot *); static struct dquot *dqduplicate(struct dquot *);
...@@ -207,14 +207,14 @@ static inline struct dquot *find_dquot(unsigned int hashent, struct super_block ...@@ -207,14 +207,14 @@ static inline struct dquot *find_dquot(unsigned int hashent, struct super_block
static inline void put_dquot_head(struct dquot *dquot) static inline void put_dquot_head(struct dquot *dquot)
{ {
list_add(&dquot->dq_free, &free_dquots); list_add(&dquot->dq_free, &free_dquots);
nr_free_dquots++; ++dqstats_array[DQSTATS_FREE];
} }
/* Add a dquot to the tail of the free list */ /* Add a dquot to the tail of the free list */
static inline void put_dquot_last(struct dquot *dquot) static inline void put_dquot_last(struct dquot *dquot)
{ {
list_add(&dquot->dq_free, free_dquots.prev); list_add(&dquot->dq_free, free_dquots.prev);
nr_free_dquots++; ++dqstats_array[DQSTATS_FREE];
} }
/* Move dquot to the head of free list (it must be already on it) */ /* Move dquot to the head of free list (it must be already on it) */
...@@ -230,7 +230,7 @@ static inline void remove_free_dquot(struct dquot *dquot) ...@@ -230,7 +230,7 @@ static inline void remove_free_dquot(struct dquot *dquot)
return; return;
list_del(&dquot->dq_free); list_del(&dquot->dq_free);
INIT_LIST_HEAD(&dquot->dq_free); INIT_LIST_HEAD(&dquot->dq_free);
nr_free_dquots--; --dqstats_array[DQSTATS_FREE];
} }
static inline void put_inuse(struct dquot *dquot) static inline void put_inuse(struct dquot *dquot)
...@@ -238,12 +238,12 @@ static inline void put_inuse(struct dquot *dquot) ...@@ -238,12 +238,12 @@ static inline void put_inuse(struct dquot *dquot)
/* We add to the back of inuse list so we don't have to restart /* We add to the back of inuse list so we don't have to restart
* when traversing this list and we block */ * when traversing this list and we block */
list_add(&dquot->dq_inuse, inuse_list.prev); list_add(&dquot->dq_inuse, inuse_list.prev);
nr_dquots++; ++dqstats_array[DQSTATS_ALLOCATED];
} }
static inline void remove_inuse(struct dquot *dquot) static inline void remove_inuse(struct dquot *dquot)
{ {
nr_dquots--; --dqstats_array[DQSTATS_ALLOCATED];
list_del(&dquot->dq_inuse); list_del(&dquot->dq_inuse);
} }
...@@ -403,7 +403,8 @@ static int vfs_quota_sync(struct super_block *sb, int type) ...@@ -403,7 +403,8 @@ static int vfs_quota_sync(struct super_block *sb, int type)
for (cnt = 0; cnt < MAXQUOTAS; cnt++) for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt) && info_dirty(&dqopt->info[cnt])) if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt) && info_dirty(&dqopt->info[cnt]))
dqopt->ops[cnt]->write_file_info(sb, cnt); dqopt->ops[cnt]->write_file_info(sb, cnt);
dqstats.syncs++; ++dqstats_array[DQSTATS_SYNCS];
return 0; return 0;
} }
...@@ -490,7 +491,7 @@ int shrink_dqcache_memory(int priority, unsigned int gfp_mask) ...@@ -490,7 +491,7 @@ int shrink_dqcache_memory(int priority, unsigned int gfp_mask)
int count = 0; int count = 0;
lock_kernel(); lock_kernel();
count = nr_free_dquots / priority; count = dqstats_array[DQSTATS_FREE] / priority;
prune_dqcache(count); prune_dqcache(count);
unlock_kernel(); unlock_kernel();
kmem_cache_shrink(dquot_cachep); kmem_cache_shrink(dquot_cachep);
...@@ -516,7 +517,7 @@ static void dqput(struct dquot *dquot) ...@@ -516,7 +517,7 @@ static void dqput(struct dquot *dquot)
} }
#endif #endif
dqstats.drops++; ++dqstats_array[DQSTATS_DROPS];
we_slept: we_slept:
if (dquot->dq_dup_ref && dquot->dq_count - dquot->dq_dup_ref <= 1) { /* Last unduplicated reference? */ if (dquot->dq_dup_ref && dquot->dq_count - dquot->dq_dup_ref <= 1) { /* Last unduplicated reference? */
__wait_dup_drop(dquot); __wait_dup_drop(dquot);
...@@ -588,15 +589,15 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, int type) ...@@ -588,15 +589,15 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
goto we_slept; goto we_slept;
} }
dquot = empty; dquot = empty;
dquot->dq_id = id; dquot->dq_id = id;
/* hash it first so it can be found */ /* hash it first so it can be found */
insert_dquot_hash(dquot); insert_dquot_hash(dquot);
read_dqblk(dquot); read_dqblk(dquot);
} else { } else {
if (!dquot->dq_count) if (!dquot->dq_count)
remove_free_dquot(dquot); remove_free_dquot(dquot);
get_dquot_ref(dquot); get_dquot_ref(dquot);
dqstats.cache_hits++; ++dqstats_array[DQSTATS_CACHE_HITS];
wait_on_dquot(dquot); wait_on_dquot(dquot);
if (empty) if (empty)
dqput(empty); dqput(empty);
...@@ -607,8 +608,8 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, int type) ...@@ -607,8 +608,8 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
dqput(dquot); dqput(dquot);
return NODQUOT; return NODQUOT;
} }
dquot->dq_referenced++; ++dquot->dq_referenced;
dqstats.lookups++; ++dqstats_array[DQSTATS_LOOKUPS];
return dquot; return dquot;
} }
...@@ -628,7 +629,8 @@ static struct dquot *dqduplicate(struct dquot *dquot) ...@@ -628,7 +629,8 @@ static struct dquot *dqduplicate(struct dquot *dquot)
printk(KERN_ERR "VFS: dqduplicate(): Locked quota to be duplicated!\n"); printk(KERN_ERR "VFS: dqduplicate(): Locked quota to be duplicated!\n");
get_dquot_dup_ref(dquot); get_dquot_dup_ref(dquot);
dquot->dq_referenced++; dquot->dq_referenced++;
dqstats.lookups++; ++dqstats_array[DQSTATS_LOOKUPS];
return dquot; return dquot;
} }
...@@ -643,7 +645,7 @@ static void dqputduplicate(struct dquot *dquot) ...@@ -643,7 +645,7 @@ static void dqputduplicate(struct dquot *dquot)
if (!dquot->dq_dup_ref) if (!dquot->dq_dup_ref)
wake_up(&dquot->dq_wait_free); wake_up(&dquot->dq_wait_free);
put_dquot_ref(dquot); put_dquot_ref(dquot);
dqstats.drops++; ++dqstats_array[DQSTATS_DROPS];
} }
static int dqinit_needed(struct inode *inode, int type) static int dqinit_needed(struct inode *inode, int type)
...@@ -1277,7 +1279,7 @@ int vfs_quota_off(struct super_block *sb, int type) ...@@ -1277,7 +1279,7 @@ int vfs_quota_off(struct super_block *sb, int type)
dqopt->info[cnt].dqi_igrace = 0; dqopt->info[cnt].dqi_igrace = 0;
dqopt->info[cnt].dqi_bgrace = 0; dqopt->info[cnt].dqi_bgrace = 0;
dqopt->ops[cnt] = NULL; dqopt->ops[cnt] = NULL;
} }
up(&dqopt->dqoff_sem); up(&dqopt->dqoff_sem);
out: out:
unlock_kernel(); unlock_kernel();
...@@ -1461,41 +1463,6 @@ int vfs_set_info(struct super_block *sb, int type, struct if_dqinfo *ii) ...@@ -1461,41 +1463,6 @@ int vfs_set_info(struct super_block *sb, int type, struct if_dqinfo *ii)
return 0; return 0;
} }
#ifdef CONFIG_PROC_FS
static int read_stats(char *buffer, char **start, off_t offset, int count, int *eof, void *data)
{
int len;
struct quota_format_type *actqf;
dqstats.allocated_dquots = nr_dquots;
dqstats.free_dquots = nr_free_dquots;
len = sprintf(buffer, "Version %u\n", __DQUOT_NUM_VERSION__);
len += sprintf(buffer + len, "Formats");
lock_kernel();
for (actqf = quota_formats; actqf; actqf = actqf->qf_next)
len += sprintf(buffer + len, " %u", actqf->qf_fmt_id);
unlock_kernel();
len += sprintf(buffer + len, "\n%u %u %u %u %u %u %u %u\n",
dqstats.lookups, dqstats.drops,
dqstats.reads, dqstats.writes,
dqstats.cache_hits, dqstats.allocated_dquots,
dqstats.free_dquots, dqstats.syncs);
if (offset >= len) {
*start = buffer;
*eof = 1;
return 0;
}
*start = buffer + offset;
if ((len -= offset) > count)
return count;
*eof = 1;
return len;
}
#endif
struct quotactl_ops vfs_quotactl_ops = { struct quotactl_ops vfs_quotactl_ops = {
quota_on: vfs_quota_on, quota_on: vfs_quota_on,
quota_off: vfs_quota_off, quota_off: vfs_quota_off,
...@@ -1507,8 +1474,7 @@ struct quotactl_ops vfs_quotactl_ops = { ...@@ -1507,8 +1474,7 @@ struct quotactl_ops vfs_quotactl_ops = {
}; };
static ctl_table fs_table[] = { static ctl_table fs_table[] = {
{FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int), {FS_DQSTATS, "dqstats", dqstats_array, sizeof(dqstats_array), 0444, NULL, &proc_dointvec},
0444, NULL, &proc_dointvec},
{}, {},
}; };
...@@ -1524,14 +1490,12 @@ static int __init dquot_init(void) ...@@ -1524,14 +1490,12 @@ static int __init dquot_init(void)
register_sysctl_table(dquot_table, 0); register_sysctl_table(dquot_table, 0);
for (i = 0; i < NR_DQHASH; i++) for (i = 0; i < NR_DQHASH; i++)
INIT_LIST_HEAD(dquot_hash + i); INIT_LIST_HEAD(dquot_hash + i);
printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__); printk(KERN_NOTICE "VFS: Disk quotas v%s\n", __DQUOT_VERSION__);
#ifdef CONFIG_PROC_FS
create_proc_read_entry("fs/quota", 0, 0, read_stats, NULL);
#endif
return 0; return 0;
} }
__initcall(dquot_init); __initcall(dquot_init);
EXPORT_SYMBOL(register_quota_format); EXPORT_SYMBOL(register_quota_format);
EXPORT_SYMBOL(unregister_quota_format); EXPORT_SYMBOL(unregister_quota_format);
EXPORT_SYMBOL(dqstats); EXPORT_SYMBOL(dqstats_array);
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
#endif #endif
int nr_dquots, nr_free_dquots;
/* Check validity of quotactl */ /* Check validity of quotactl */
static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
{ {
...@@ -411,7 +409,7 @@ static int v1_set_dqblk(struct super_block *sb, int type, int cmd, qid_t id, str ...@@ -411,7 +409,7 @@ static int v1_set_dqblk(struct super_block *sb, int type, int cmd, qid_t id, str
static void v1_get_stats(struct v1c_dqstats *dst) static void v1_get_stats(struct v1c_dqstats *dst)
{ {
memcpy(dst, &dqstats, sizeof(dqstats)); memcpy(dst, &dqstats_array, sizeof(dqstats_array));
} }
#endif #endif
...@@ -490,7 +488,7 @@ static int v2_set_dqblk(struct super_block *sb, int type, int cmd, qid_t id, str ...@@ -490,7 +488,7 @@ static int v2_set_dqblk(struct super_block *sb, int type, int cmd, qid_t id, str
static void v2_get_stats(struct v2c_dqstats *dst) static void v2_get_stats(struct v2c_dqstats *dst)
{ {
memcpy(dst, &dqstats, sizeof(dqstats)); memcpy(dst, &dqstats_array, sizeof(dqstats_array));
dst->version = __DQUOT_NUM_VERSION__; dst->version = __DQUOT_NUM_VERSION__;
} }
#endif #endif
......
...@@ -57,7 +57,8 @@ static int v1_read_dqblk(struct dquot *dquot) ...@@ -57,7 +57,8 @@ static int v1_read_dqblk(struct dquot *dquot)
if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 && if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&
dquot->dq_dqb.dqb_ihardlimit == 0 && dquot->dq_dqb.dqb_isoftlimit == 0) dquot->dq_dqb.dqb_ihardlimit == 0 && dquot->dq_dqb.dqb_isoftlimit == 0)
dquot->dq_flags |= DQ_FAKE; dquot->dq_flags |= DQ_FAKE;
dqstats.reads++; ++dqstats_array[DQSTATS_READS];
return 0; return 0;
} }
...@@ -100,7 +101,8 @@ static int v1_commit_dqblk(struct dquot *dquot) ...@@ -100,7 +101,8 @@ static int v1_commit_dqblk(struct dquot *dquot)
out: out:
set_fs(fs); set_fs(fs);
dqstats.writes++; ++dqstats_array[DQSTATS_WRITES];
return ret; return ret;
} }
......
...@@ -430,7 +430,8 @@ static int v2_write_dquot(struct dquot *dquot) ...@@ -430,7 +430,8 @@ static int v2_write_dquot(struct dquot *dquot)
} }
else else
ret = 0; ret = 0;
dqstats.writes++; ++dqstats_array[DQSTATS_WRITES];
return ret; return ret;
} }
...@@ -644,7 +645,8 @@ static int v2_read_dquot(struct dquot *dquot) ...@@ -644,7 +645,8 @@ static int v2_read_dquot(struct dquot *dquot)
set_fs(fs); set_fs(fs);
disk2memdqb(&dquot->dq_dqb, &ddquot); disk2memdqb(&dquot->dq_dqb, &ddquot);
} }
dqstats.reads++; ++dqstats_array[DQSTATS_READS];
return ret; return ret;
} }
......
...@@ -184,20 +184,22 @@ extern inline void mark_info_dirty(struct mem_dqinfo *info) ...@@ -184,20 +184,22 @@ extern inline void mark_info_dirty(struct mem_dqinfo *info)
#define sb_dqopt(sb) (&(sb)->s_dquot) #define sb_dqopt(sb) (&(sb)->s_dquot)
extern int nr_dquots, nr_free_dquots; /*
* Statistics about disc quota.
struct dqstats { */
__u32 lookups; enum {
__u32 drops; DQSTATS_LOOKUPS,
__u32 reads; DQSTATS_DROPS,
__u32 writes; DQSTATS_READS,
__u32 cache_hits; DQSTATS_WRITES,
__u32 allocated_dquots; DQSTATS_CACHE_HITS,
__u32 free_dquots; DQSTATS_ALLOCATED,
__u32 syncs; DQSTATS_FREE,
DQSTATS_SYNCS,
DQSTATS_SIZE
}; };
extern struct dqstats dqstats; extern __u32 dqstats_array[DQSTATS_SIZE];
#define NR_DQHASH 43 /* Just an arbitrary number */ #define NR_DQHASH 43 /* Just an arbitrary number */
......
...@@ -544,6 +544,7 @@ enum ...@@ -544,6 +544,7 @@ enum
FS_LEASES=13, /* int: leases enabled */ FS_LEASES=13, /* int: leases enabled */
FS_DIR_NOTIFY=14, /* int: directory notification enabled */ FS_DIR_NOTIFY=14, /* int: directory notification enabled */
FS_LEASE_TIME=15, /* int: maximum time to wait for a lease break */ FS_LEASE_TIME=15, /* int: maximum time to wait for a lease break */
FS_DQSTATS=16, /* int: disc quota suage statistics */
}; };
/* CTL_DEBUG names: */ /* CTL_DEBUG names: */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment