Jan Kara
2009-Oct-14 18:08 UTC
[Ocfs2-devel] [PATCH 0/5] Quota support for disabling inline-data feature (v2) and a fix
Hi, here is a new version of the patch to implement quota support for disabling inline-data feature. Now, main functions for changing quotas are implemented in libocfs2 as Joel asked and used from tunefs.ocfs2. Disabling of sparse feature is changed to use these functions as well. Finally, the series contains a fix to not load quota information from disk when it's already in memory (happens when tunefs is asked to do several operations at once) and a rebased patch to do not account for space used by sparse system files when disabling sparse feature. Honza
Jan Kara
2009-Oct-14 18:08 UTC
[Ocfs2-devel] [PATCH 1/5] Do not reinitialize already initialized quota info
Tunefs can call ocfs2_init_fs_quota_info() and ocfs2_read_global_quota_info() several times when several features are to be enabled / disabled. Check whether we haven't already initialized the info / read the info from disk and don't do anything in such case so that we don't lose references to inodes or even overwrite cached information in memory with an old one from disk. Signed-off-by: Jan Kara <jack at suse.cz> --- include/ocfs2/ocfs2.h | 1 + libocfs2/quota.c | 8 ++++++++ tunefs.ocfs2/feature_quota.c | 2 +- 3 files changed, 10 insertions(+), 1 deletions(-) diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h index 992d2f2..d7be734 100644 --- a/include/ocfs2/ocfs2.h +++ b/include/ocfs2/ocfs2.h @@ -129,6 +129,7 @@ /* Flags for global quotafile info */ #define OCFS2_QF_INFO_DIRTY 1 +#define OCFS2_QF_INFO_LOADED 2 typedef void (*ocfs2_chb_notify)(int state, char *progress, void *data); diff --git a/libocfs2/quota.c b/libocfs2/quota.c index a995b41..e36b12f 100644 --- a/libocfs2/quota.c +++ b/libocfs2/quota.c @@ -508,6 +508,9 @@ errcode_t ocfs2_init_fs_quota_info(ocfs2_filesys *fs, int type) char fname[OCFS2_MAX_FILENAME_LEN]; errcode_t ret; + if (fs->qinfo[type].qi_inode) + return 0; + ocfs2_sprintf_system_inode_name(fname, sizeof(fname), global_type, 0); ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, fname, strlen(fname), @@ -563,6 +566,9 @@ errcode_t ocfs2_read_global_quota_info(ocfs2_filesys *fs, int type) errcode_t ret; struct ocfs2_global_disk_dqinfo *info; + if (fs->qinfo[type].flags & OCFS2_QF_INFO_LOADED) + return 0; + ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) return ret; @@ -574,6 +580,8 @@ errcode_t ocfs2_read_global_quota_info(ocfs2_filesys *fs, int type) ocfs2_swap_quota_global_info(info); memcpy(&(fs->qinfo[type].qi_info), info, sizeof(struct ocfs2_global_disk_dqinfo)); + fs->qinfo[type].flags |= OCFS2_QF_INFO_LOADED; + return 0; } diff --git a/tunefs.ocfs2/feature_quota.c b/tunefs.ocfs2/feature_quota.c index b734d49..2da3cbe 100644 --- a/tunefs.ocfs2/feature_quota.c +++ b/tunefs.ocfs2/feature_quota.c @@ -101,7 +101,7 @@ static errcode_t create_quota_files(ocfs2_filesys *fs, int type, type2name(type)); return ret; } - fs->qinfo[type].flags = 0; + fs->qinfo[type].flags = OCFS2_QF_INFO_LOADED; fs->qinfo[type].qi_info.dqi_syncms = OCFS2_DEF_QUOTA_SYNC; fs->qinfo[type].qi_info.dqi_bgrace = OCFS2_DEF_BLOCK_GRACE; fs->qinfo[type].qi_info.dqi_igrace = OCFS2_DEF_INODE_GRACE; -- 1.6.0.2
Jan Kara
2009-Oct-14 18:08 UTC
[Ocfs2-devel] [PATCH 2/5] Implement support for quota changes in libocfs2
Implement some common functions for changing quotas in libocfs2 so that they don't have to be reimplemented in several users. Signed-off-by: Jan Kara <jack at suse.cz> --- include/ocfs2/ocfs2.h | 16 ++++++ libocfs2/quota.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 0 deletions(-) diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h index d7be734..bf64fa0 100644 --- a/include/ocfs2/ocfs2.h +++ b/include/ocfs2/ocfs2.h @@ -685,6 +685,7 @@ int ocfs2_qtree_entry_unused(struct ocfs2_global_disk_dqblk *ddquot); errcode_t ocfs2_init_global_quota_file(ocfs2_filesys *fs, int type); errcode_t ocfs2_init_fs_quota_info(ocfs2_filesys *fs, int type); errcode_t ocfs2_read_global_quota_info(ocfs2_filesys *fs, int type); +errcode_t ocfs2_load_fs_quota_info(ocfs2_filesys *fs); errcode_t ocfs2_write_global_quota_info(ocfs2_filesys *fs, int type); errcode_t ocfs2_write_dquot(ocfs2_filesys *fs, int type, ocfs2_cached_dquot *dquot); @@ -702,9 +703,24 @@ errcode_t ocfs2_find_quota_hash(ocfs2_quota_hash *hash, qid_t id, ocfs2_cached_dquot **dquotp); errcode_t ocfs2_find_create_quota_hash(ocfs2_quota_hash *hash, qid_t id, ocfs2_cached_dquot **dquotp); +errcode_t ocfs2_find_read_quota_hash(ocfs2_filesys *fs, ocfs2_quota_hash *hash, + int type, qid_t id, + ocfs2_cached_dquot **dquotp); errcode_t ocfs2_compute_quota_usage(ocfs2_filesys *fs, ocfs2_quota_hash *usr_hash, ocfs2_quota_hash *grp_hash); +errcode_t ocfs2_init_quota_change(ocfs2_filesys *fs, + ocfs2_quota_hash **usrhash, + ocfs2_quota_hash **grphash); +errcode_t ocfs2_finish_quota_change(ocfs2_filesys *fs, + ocfs2_quota_hash *usrhash, + ocfs2_quota_hash *grphash); +errcode_t ocfs2_apply_quota_change(ocfs2_filesys *fs, + ocfs2_quota_hash *usrhash, + ocfs2_quota_hash *grphash, + uid_t uid, gid_t gid, + int64_t space_change, + int64_t inode_change); errcode_t ocfs2_iterate_quota_hash(ocfs2_quota_hash *hash, errcode_t (*f)(ocfs2_cached_dquot *, void *), void *data); diff --git a/libocfs2/quota.c b/libocfs2/quota.c index e36b12f..9e0ca33 100644 --- a/libocfs2/quota.c +++ b/libocfs2/quota.c @@ -229,6 +229,30 @@ errcode_t ocfs2_find_create_quota_hash(ocfs2_quota_hash *hash, qid_t id, return 0; } +errcode_t ocfs2_find_read_quota_hash(ocfs2_filesys *fs, ocfs2_quota_hash *hash, + int type, qid_t id, + ocfs2_cached_dquot **dquotp) +{ + errcode_t err; + + err = ocfs2_find_quota_hash(hash, id, dquotp); + if (err) + return err; + if (*dquotp) + return 0; + + err = ocfs2_read_dquot(fs, type, id, dquotp); + if (err) + return err; + + err = ocfs2_insert_quota_hash(hash, *dquotp); + if (err) { + ocfs2_free(dquotp); + return err; + } + return 0; +} + errcode_t ocfs2_compute_quota_usage(ocfs2_filesys *fs, ocfs2_quota_hash *usr_hash, ocfs2_quota_hash *grp_hash) @@ -296,6 +320,84 @@ out: return err; } +errcode_t ocfs2_init_quota_change(ocfs2_filesys *fs, + ocfs2_quota_hash **usrhash, + ocfs2_quota_hash **grphash) +{ + errcode_t err; + + if (OCFS2_HAS_RO_COMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super), + OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) { + err = ocfs2_new_quota_hash(usrhash); + if (err) + return err; + } + if (OCFS2_HAS_RO_COMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super), + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) { + err = ocfs2_new_quota_hash(grphash); + if (err) { + ocfs2_free_quota_hash(*usrhash); + return err; + } + } + return 0; +} + +errcode_t ocfs2_finish_quota_change(ocfs2_filesys *fs, + ocfs2_quota_hash *usrhash, + ocfs2_quota_hash *grphash) +{ + errcode_t ret = 0, err; + + if (usrhash) { + err = ocfs2_write_release_dquots(fs, USRQUOTA, usrhash); + if (!ret) + ret = err; + err = ocfs2_free_quota_hash(usrhash); + if (!ret) + ret = err; + } + if (grphash) { + err = ocfs2_write_release_dquots(fs, GRPQUOTA, grphash); + if (!ret) + ret = err; + err = ocfs2_free_quota_hash(grphash); + if (!ret) + ret = err; + } + + return ret; +} + +errcode_t ocfs2_apply_quota_change(ocfs2_filesys *fs, + ocfs2_quota_hash *usrhash, + ocfs2_quota_hash *grphash, + uid_t uid, gid_t gid, + int64_t space_change, + int64_t inode_change) +{ + ocfs2_cached_dquot *dquot; + errcode_t err; + + if (usrhash) { + err = ocfs2_find_read_quota_hash(fs, usrhash, USRQUOTA, uid, + &dquot); + if (err) + return err; + dquot->d_ddquot.dqb_curspace += space_change; + dquot->d_ddquot.dqb_curinodes += inode_change; + } + if (grphash) { + err = ocfs2_find_read_quota_hash(fs, grphash, GRPQUOTA, gid, + &dquot); + if (err) + return err; + dquot->d_ddquot.dqb_curspace += space_change; + dquot->d_ddquot.dqb_curinodes += inode_change; + } + return 0; +} + errcode_t ocfs2_iterate_quota_hash(ocfs2_quota_hash *hash, errcode_t (*f)(ocfs2_cached_dquot *, void *), void *data) @@ -614,6 +716,31 @@ bail: return ret; } +errcode_t ocfs2_load_fs_quota_info(ocfs2_filesys *fs) +{ + errcode_t err; + + if (OCFS2_HAS_RO_COMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super), + OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) { + err = ocfs2_init_fs_quota_info(fs, USRQUOTA); + if (err) + return err; + err = ocfs2_read_global_quota_info(fs, USRQUOTA); + if (err) + return err; + } + if (OCFS2_HAS_RO_COMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super), + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) { + err = ocfs2_init_fs_quota_info(fs, GRPQUOTA); + if (err) + return err; + err = ocfs2_read_global_quota_info(fs, GRPQUOTA); + if (err) + return err; + } + return 0; +} + #define OCFS2_GLOBAL_QF_INIT_BLOCKS 2 errcode_t ocfs2_init_global_quota_file(ocfs2_filesys *fs, int type) -- 1.6.0.2
Jan Kara
2009-Oct-14 18:08 UTC
[Ocfs2-devel] [PATCH 3/5] Quota support for disabling inline-data feature
When disabling inline-data feature, space occupied by files changes and thus we have to update quota information accordingly. Signed-off-by: Jan Kara <jack at suse.cz> --- tunefs.ocfs2/feature_inline_data.c | 42 +++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/tunefs.ocfs2/feature_inline_data.c b/tunefs.ocfs2/feature_inline_data.c index 77ddb42..9e1d07f 100644 --- a/tunefs.ocfs2/feature_inline_data.c +++ b/tunefs.ocfs2/feature_inline_data.c @@ -170,31 +170,63 @@ static void empty_inline_data_context(struct inline_data_context *ctxt) static errcode_t expand_inline_data(ocfs2_filesys *fs, struct inline_data_context *ctxt) { - errcode_t ret = 0; + errcode_t ret = 0, err; struct list_head *pos; struct inline_data_inode *idi; ocfs2_cached_inode *ci = NULL; struct tools_progress *prog; + struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super); + ocfs2_quota_hash *usrhash = NULL, *grphash = NULL; + uint32_t uid, gid; + long long change; prog = tools_progress_start("Expanding inline files", "expanding", ctxt->more_clusters); if (!ctxt->prog) return TUNEFS_ET_NO_MEMORY; + ret = ocfs2_load_fs_quota_info(fs); + if (ret) + goto out; + + ret = ocfs2_init_quota_change(fs, &usrhash, &grphash); + if (ret) + goto out; + list_for_each(pos, &ctxt->inodes) { idi = list_entry(pos, struct inline_data_inode, list); ret = ocfs2_read_cached_inode(fs, idi->blkno, &ci); - if (!ret) { - ret = ocfs2_convert_inline_data_to_extents(ci); + if (ret) + break; + + ret = ocfs2_convert_inline_data_to_extents(ci); + if (ret) { ocfs2_free_cached_inode(fs, ci); + break; } - + if (ci->ci_inode->i_flags & OCFS2_SYSTEM_FL && + idi->blkno != super->s_root_blkno) { + ocfs2_free_cached_inode(fs, ci); + goto next; + } + change = ocfs2_clusters_to_bytes(fs, + ci->ci_inode->i_clusters); + uid = ci->ci_inode->i_uid; + gid = ci->ci_inode->i_gid; + ocfs2_free_cached_inode(fs, ci); + + ret = ocfs2_apply_quota_change(fs, usrhash, grphash, uid, gid, + change, 0); if (ret) break; - +next: tools_progress_step(prog, 1); } +out: + err = ocfs2_finish_quota_change(fs, usrhash, grphash); + if (!ret) + ret = err; tools_progress_stop(prog); -- 1.6.0.2
Jan Kara
2009-Oct-14 18:08 UTC
[Ocfs2-devel] [PATCH 4/5] Convert disabling of sparse feature to use new code in libocfs2
Make code handling update of quota information when disabling sparse feature use new generic code in libocfs2. Signed-off-by: Jan Kara <jack at suse.cz> --- tunefs.ocfs2/feature_sparse_files.c | 100 ++++++---------------------------- 1 files changed, 18 insertions(+), 82 deletions(-) diff --git a/tunefs.ocfs2/feature_sparse_files.c b/tunefs.ocfs2/feature_sparse_files.c index d4dff34..4f8c0db 100644 --- a/tunefs.ocfs2/feature_sparse_files.c +++ b/tunefs.ocfs2/feature_sparse_files.c @@ -448,8 +448,6 @@ static errcode_t fill_sparse_files(ocfs2_filesys *fs, struct list_head *pos; struct sparse_file *file; struct tools_progress *prog; - struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super); - int has_usrquota, has_grpquota; ocfs2_quota_hash *usrhash = NULL, *grphash = NULL; prog = tools_progress_start("Filling holes", "filling", @@ -459,32 +457,14 @@ static errcode_t fill_sparse_files(ocfs2_filesys *fs, goto out; } - has_usrquota = OCFS2_HAS_RO_COMPAT_FEATURE(super, - OCFS2_FEATURE_RO_COMPAT_USRQUOTA); - has_grpquota = OCFS2_HAS_RO_COMPAT_FEATURE(super, - OCFS2_FEATURE_RO_COMPAT_GRPQUOTA); - if (has_usrquota) { - ret = ocfs2_init_fs_quota_info(fs, USRQUOTA); - if (ret) - goto out; - ret = ocfs2_read_global_quota_info(fs, USRQUOTA); - if (ret) - goto out; - ret = ocfs2_new_quota_hash(&usrhash); - if (ret) - goto out; - } - if (has_grpquota) { - ret = ocfs2_init_fs_quota_info(fs, GRPQUOTA); - if (ret) - goto out; - ret = ocfs2_read_global_quota_info(fs, GRPQUOTA); - if (ret) - goto out; - ret = ocfs2_new_quota_hash(&grphash); - if (ret) - goto out; - } + + ret = ocfs2_load_fs_quota_info(fs); + if (ret) + goto out; + + ret = ocfs2_init_quota_change(fs, &usrhash, &grphash); + if (ret) + goto out; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) @@ -497,7 +477,7 @@ static errcode_t fill_sparse_files(ocfs2_filesys *fs, if (ret) break; - if (!file->truncate && !has_usrquota && !has_grpquota) + if (!file->truncate && !usrhash && !grphash) continue; ret = ocfs2_read_inode(fs, file->blkno, buf); @@ -511,7 +491,6 @@ static errcode_t fill_sparse_files(ocfs2_filesys *fs, } if (di->i_clusters != file->old_clusters) { long long change; - ocfs2_cached_dquot *udquot = NULL, *gdquot = NULL; if (di->i_clusters > file->old_clusters) { change = ocfs2_clusters_to_bytes(fs, @@ -521,64 +500,21 @@ static errcode_t fill_sparse_files(ocfs2_filesys *fs, file->old_clusters - di->i_clusters); } - if (has_usrquota) { - ret = ocfs2_find_quota_hash(usrhash, di->i_uid, - &udquot); - if (ret) - break; - if (!udquot) { - ret = ocfs2_read_dquot(fs, USRQUOTA, - di->i_uid, - &udquot); - if (ret) - break; - ret = ocfs2_insert_quota_hash(usrhash, - udquot); - if (ret) - break; - } - udquot->d_ddquot.dqb_curspace += change; - } - if (has_grpquota) { - ret = ocfs2_find_quota_hash(grphash, di->i_gid, - &gdquot); - if (ret) - break; - if (!gdquot) { - ret = ocfs2_read_dquot(fs, GRPQUOTA, - di->i_gid, - &gdquot); - if (ret) - break; - ret = ocfs2_insert_quota_hash(grphash, - gdquot); - if (ret) - break; - } - gdquot->d_ddquot.dqb_curspace += change; - } + ret = ocfs2_apply_quota_change(fs, usrhash, grphash, + di->i_uid, di->i_gid, + change, 0); + if (ret) + break; } } ocfs2_free(&buf); out: - if (usrhash) { - err = ocfs2_write_release_dquots(fs, USRQUOTA, usrhash); - if (!ret) - ret = err; - err = ocfs2_free_quota_hash(usrhash); - if (!ret) - ret = err; - } - if (grphash) { - err = ocfs2_write_release_dquots(fs, GRPQUOTA, grphash); - if (!ret) - ret = err; - err = ocfs2_free_quota_hash(grphash); - if (!ret) - ret = err; - } + err = ocfs2_finish_quota_change(fs, usrhash, grphash); + if (!ret) + ret = err; + if (prog) tools_progress_stop(prog); -- 1.6.0.2
Jan Kara
2009-Oct-14 18:08 UTC
[Ocfs2-devel] [PATCH 5/5] Don't account space used for system files when disabling sparse feature
System files (except for root directory) are not accounted in quota. So we should not add the space used to fill holes in them when disabling sparse feature. Signed-off-by: Jan Kara <jack at suse.cz> --- tunefs.ocfs2/feature_sparse_files.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/tunefs.ocfs2/feature_sparse_files.c b/tunefs.ocfs2/feature_sparse_files.c index 4f8c0db..a8e8b7b 100644 --- a/tunefs.ocfs2/feature_sparse_files.c +++ b/tunefs.ocfs2/feature_sparse_files.c @@ -489,7 +489,9 @@ static errcode_t fill_sparse_files(ocfs2_filesys *fs, if (ret) break; } - if (di->i_clusters != file->old_clusters) { + if (di->i_clusters != file->old_clusters && + (!(di->i_flags & OCFS2_SYSTEM_FL) || + file->blkno == super->s_root_blkno)) { long long change; if (di->i_clusters > file->old_clusters) { -- 1.6.0.2
Joel Becker
2009-Oct-14 20:04 UTC
[Ocfs2-devel] [PATCH 0/5] Quota support for disabling inline-data feature (v2) and a fix
On Wed, Oct 14, 2009 at 08:08:54PM +0200, Jan Kara wrote:> here is a new version of the patch to implement quota support for disabling > inline-data feature. Now, main functions for changing quotas are implemented > in libocfs2 as Joel asked and used from tunefs.ocfs2. Disabling of sparse > feature is changed to use these functions as well. > Finally, the series contains a fix to not load quota information from disk > when it's already in memory (happens when tunefs is asked to do several > operations at once) and a rebased patch to do not account for space used > by sparse system files when disabling sparse feature. > > HonzaAny chance you can resend these to ocfs2-tools-devel? I just want to make sure folks involved in tools work get to see them. Thanks! Joel -- "Same dancers in the same old shoes. You get too careful with the steps you choose. You don't care about winning but you don't want to lose After the thrill is gone." Joel Becker Principal Software Developer Oracle E-mail: joel.becker at oracle.com Phone: (650) 506-8127
Tristan
2009-Oct-19 07:06 UTC
[Ocfs2-devel] [PATCH 0/5] Quota support for disabling inline-data feature (v2) and a fix
Jan, Other than an error I've pointed out in patch 4, this patch series can be very much alive from my quota-tools-test. Tested-By Tristan. Jan Kara wrote:> Hi, > > here is a new version of the patch to implement quota support for disabling > inline-data feature. Now, main functions for changing quotas are implemented > in libocfs2 as Joel asked and used from tunefs.ocfs2. Disabling of sparse > feature is changed to use these functions as well. > Finally, the series contains a fix to not load quota information from disk > when it's already in memory (happens when tunefs is asked to do several > operations at once) and a rebased patch to do not account for space used > by sparse system files when disabling sparse feature. > > Honza >