diff options
author | Jan Kara <jack@suse.cz> | 2008-10-20 15:05:00 (GMT) |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 16:40:23 (GMT) |
commit | 12c77527e4138bc3b17d17b0e0c909e4fc84924f (patch) | |
tree | 2776bbc914ebf8db7bdc2e450abf6a1504f50abe | |
parent | 3d9ea253a0e73dccaa869888ec2ceb17ea76c810 (diff) | |
download | linux-12c77527e4138bc3b17d17b0e0c909e4fc84924f.tar.xz |
quota: Implement function for scanning active dquots
OCFS2 needs to scan all active dquots once in a while and sync quota
information among cluster nodes. Provide a helper function for it so
that it does not have to reimplement internally a list which VFS
already has. Moreover this function is probably going to be useful
for other clustered filesystems if they decide to use VFS quotas.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r-- | fs/dquot.c | 36 | ||||
-rw-r--r-- | include/linux/quotaops.h | 3 |
2 files changed, 39 insertions, 0 deletions
@@ -476,6 +476,41 @@ restart: spin_unlock(&dq_list_lock); } +/* Call callback for every active dquot on given filesystem */ +int dquot_scan_active(struct super_block *sb, + int (*fn)(struct dquot *dquot, unsigned long priv), + unsigned long priv) +{ + struct dquot *dquot, *old_dquot = NULL; + int ret = 0; + + mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); + spin_lock(&dq_list_lock); + list_for_each_entry(dquot, &inuse_list, dq_inuse) { + if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) + continue; + if (dquot->dq_sb != sb) + continue; + /* Now we have active dquot so we can just increase use count */ + atomic_inc(&dquot->dq_count); + dqstats.lookups++; + spin_unlock(&dq_list_lock); + dqput(old_dquot); + old_dquot = dquot; + ret = fn(dquot, priv); + if (ret < 0) + goto out; + spin_lock(&dq_list_lock); + /* We are safe to continue now because our dquot could not + * be moved out of the inuse list while we hold the reference */ + } + spin_unlock(&dq_list_lock); +out: + dqput(old_dquot); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); + return ret; +} + int vfs_quota_sync(struct super_block *sb, int type) { struct list_head *dirty; @@ -2318,6 +2353,7 @@ EXPORT_SYMBOL(vfs_quota_on_path); EXPORT_SYMBOL(vfs_quota_on_mount); EXPORT_SYMBOL(vfs_quota_disable); EXPORT_SYMBOL(vfs_quota_off); +EXPORT_SYMBOL(dquot_scan_active); EXPORT_SYMBOL(vfs_quota_sync); EXPORT_SYMBOL(vfs_get_dqinfo); EXPORT_SYMBOL(vfs_set_dqinfo); diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index e3a1027..f491394 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -28,6 +28,9 @@ int dquot_drop_locked(struct inode *inode); struct dquot *dqget(struct super_block *sb, unsigned int id, int type); void dqput(struct dquot *dquot); int dquot_is_cached(struct super_block *sb, unsigned int id, int type); +int dquot_scan_active(struct super_block *sb, + int (*fn)(struct dquot *dquot, unsigned long priv), + unsigned long priv); int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc); int dquot_alloc_inode(const struct inode *inode, qsize_t number); |