commit 3e58adda5417a9759a9a7ab69da525eac889ba85
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date: Tue May 29 20:41:43 2007 -0400
cleanup thread to clean until both blocks and inodes are below threshhold
added new cleanup flags
diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index 83b006d..a424789 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -53,7 +53,7 @@ struct unionfs_rdutil_callback {
struct unionfs_cleanup_callback {
int err;
int filldir_called;
- int reclaim;
+ int mode;
struct dentry *dir;
struct vfsmount *mnt;
struct dentry_stack *stack;
@@ -61,6 +61,11 @@ struct unionfs_cleanup_callback {
u64 inodes;
};
+/* modes for cleanup_callback - what type of dir we are cleaning */
+#define CLN_IC 0 /* /odf/ic */
+#define CLN_RC 1 /* /odf/reclaim */
+#define CLN_SR 2 /* /odf/sr */
+
/* odf_cleanup callback */
static int cleanup_util_callback(void *dirent, const char *name, int namelen,
loff_t offset, u64 ino, unsigned int d_type)
@@ -77,8 +82,10 @@ static int cleanup_util_callback(void *dirent, const char
*name, int namelen,
(namelen == 1 || (name[1] == '.' && namelen == 2)))
goto out;
- /* remove dir cache files or all if files if cleaning /reclaim */
- if ((d_type == DT_REG && buf->reclaim) ||
+ /* remove dir cache files or all if files if cleaning
+ * /odf/reclaim nad /odf/sr
+ */
+ if ((d_type == DT_REG && buf->mode != CLN_IC) ||
(namelen == ODF_CONTENT_LEN &&
!strncmp(name, ODF_CONTENT, namelen))) {
@@ -542,24 +549,26 @@ out:
* First cleans up the dir caches in odf/ic and then everything
* in odf/reclaim. It stops once the requested blocks/inodes
* were freed.
- * size contains the requested amount of inodes/blocks to be freed
- * MULTIPLIED BY 100
- * Modes :
- * ODF_CLEAN_ALL: cleans all the dir caches and odf/reclaim
- * ODF_CLEAN_CACHE: cleans all the dir caches and odf/sr
- * ODF_CLEAN_BLOCKS: clean until size blocks are freed
- * ODF_CLEAN_INODES: clean until size inodes are freed
+ *
+ * b_to_free and i_to_free contains the requested amount of blocks
+ * and inodes to be freed MULTIPLIED BY 100
+ *
+ * Flags :
+ * ODF_CLEAN_DEFAULT: clean all caches but /odf/sr
+ * ODF_CLEAN_SR: clean /odf/sr
+ * ODF_CLEAN_FULL: clean /odf/ic and /odf/reclaim ignoring
+ thresholds
* Returns 1 if it manages to bring inodes/block below requested,
* threshold and 0 if not.
*/
-int odf_cleanup(struct odf_sb_info *odf, int mode, u64 size)
+int odf_cleanup(struct odf_sb_info *odf, int mode, u64 b_to_free, u64
i_to_free)
{
int err = 0;
struct file *file;
struct unionfs_cleanup_callback *buf = NULL;
struct dentry *dentry;
struct dentry_stack stack;
- int success = 0, reclaim = 0;
+ int success = 0;
loff_t bytes, isize;
int blocks;
@@ -568,7 +577,6 @@ int odf_cleanup(struct odf_sb_info *odf, int mode, u64 size)
err = -ENOMEM;
goto out;
}
-
buf = kmalloc(sizeof(struct unionfs_cleanup_callback), GFP_KERNEL);
if (!buf) {
err = -ENOMEM;
@@ -576,7 +584,7 @@ int odf_cleanup(struct odf_sb_info *odf, int mode, u64 size)
}
buf->err = 0;
buf->mnt = odf->mnt;
- buf->reclaim = reclaim;
+ buf->mode = CLN_IC;
buf->blocks = 0;
buf->inodes = 0;
buf->stack = &stack;
@@ -585,7 +593,6 @@ int odf_cleanup(struct odf_sb_info *odf, int mode, u64 size)
dget(odf->ic);
stack.item[stack.n++] = odf->ic;
-
cleanup_loop:
/* The cleanup loop pops a dentry off the stack, reads all
* its entries, unlinking dir cache files and files in
@@ -594,10 +601,10 @@ cleanup_loop:
while (err >= 0 && stack.n > 0 && !success) {
dentry = __ds_pop(&stack);
- /* we need to dget /reclaim dirs again since we need
- * them after we close the file
+ /* we need to dget /odf/reclaim and /odf/sr dirs again since
+ * we need them after we close the file
*/
- if (reclaim)
+ if (buf->mode != CLN_IC)
dget(dentry);
mntget(odf->mnt);
@@ -617,7 +624,7 @@ cleanup_loop:
} while ((err >= 0) && buf->filldir_called);
fput(file);
- if (!err && reclaim) {
+ if (!err && buf->mode != CLN_IC) {
/* remove all directories in odf/reclaim or odf/sr
* This assumes that the odf/reclaim dir structure
* is entirely flat, ie only odf/reclaim contains
@@ -640,42 +647,39 @@ cleanup_loop:
}
/* check if we have reached the threshold */
- if (mode == ODF_CLEAN_BLOCKS && buf->blocks * 100 >= size)
- success = 1;
- else if (mode == ODF_CLEAN_INODES && buf->inodes * 100 >= size)
+ if ((mode & ODF_CLEAN_DEFAULT) &&
+ (buf->blocks * 100 >= b_to_free) &&
+ (buf->inodes * 100 >= i_to_free))
success = 1;
}
if (err < 0)
goto out;
- if (mode == ODF_CLEAN_CACHE && !reclaim) {
- /* cleanup odf/sr as well */
- reclaim = 1;
- buf->reclaim = 1;
- dget(odf->sr);
- stack.item[stack.n++] = odf->sr;
- goto cleanup_loop;
- }
- else if (mode == ODF_CLEAN_CACHE && reclaim)
- success = 1;
-
- if (!success) {
+ if (!success && ((mode & ODF_CLEAN_DEFAULT) || (mode &
ODF_CLEAN_FULL))) {
BUG_ON(stack.n);
/* if we did not succeed, clean up odf/reclaim as well */
- if (!reclaim) {
- reclaim = 1;
- buf->reclaim = 1;
+ if (buf->mode == CLN_IC) {
+ buf->mode = CLN_RC;
dget(odf->rc);
stack.item[stack.n++] = odf->rc;
goto cleanup_loop;
}
}
- if (mode == ODF_CLEAN_ALL)
- success = 1;
+ /* cleanup /odf/sr */
+ if ((mode & ODF_CLEAN_SR) && (buf->mode != CLN_SR)) {
+ buf->mode = CLN_SR;
+ dget(odf->sr);
+ stack.item[stack.n++] = odf->sr;
+ goto cleanup_loop;
+ }
+ if (mode & ODF_CLEAN_DEFAULT)
+ err = success;
+ else
+ err = 1;
out:
BUG_ON(stack.n < 0);
while(stack.n)
@@ -683,7 +687,5 @@ out:
kfree(buf);
kfree(stack.item);
- if (!err)
- err = success;
return err;
}
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index 70ddb22..79ceae7 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -482,7 +482,7 @@ static struct unionfs_dentry_info *unionfs_parse_options(
*optarg++ = '\0';
/* taken care of in odf_parse_options */
- if (!strcmp("odfforce", optname))
+ if (!strcmp("odf_keepcache", optname))
continue;
/*
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 2a7791d..18b88ff 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -184,7 +184,8 @@ int odf_read_super(struct super_block *sb, char *data)
}
sioa->cleanup.odf = osi;
sioa->cleanup.attr = get_attributes();
- sioa->cleanup.force = !(options & ODF_OPT_KEEPCACHE);
+ sioa->cleanup.flags = (options & ODF_OPT_KEEPCACHE)?
+ ODF_CLEAN_DEFAULT:ODF_CLEAN_SR|ODF_CLEAN_FULL;
osi->cleanup = sioa;
osi->mnt = nd.mnt;
mntget(osi->mnt);
@@ -222,6 +223,10 @@ void odf_put_super(struct odf_sb_info *osi)
{
struct dentry *odf_root = NULL;
+ if (osi->cleanup)
+ complete_sioa(osi->cleanup);
+ kfree(osi->cleanup);
+
if (osi->sb)
odf_root = osi->sb->d_parent;
@@ -242,9 +247,6 @@ void odf_put_super(struct odf_sb_info *osi)
dput(odf_root);
mntput(osi->mnt);
- if (osi->cleanup)
- complete_sioa(osi->cleanup);
- kfree(osi->cleanup);
}
/*
@@ -305,6 +307,7 @@ int odf_parse_options(const char *options, char **odf_path)
goto out_error;
}
err |= ODF_OPT_KEEPCACHE;
+ continue;
}
if (!optarg) {
@@ -1971,9 +1974,8 @@ void __odf_cleanup(void *args)
struct sioa_args *sioa_args = args;
struct cleanup_args *cl = &sioa_args->cleanup;
struct kstatfs stat;
- int cleanup = 0;
- u64 size = 0;
- int err = 0;
+ u64 b_size = 0, i_size = 0;
+ int cleanup = 0, err = 0;
/* update timeout */
sioa_args->timeout = msecs_to_jiffies(cl->attr->timeout->val * 1000);
@@ -1981,33 +1983,37 @@ void __odf_cleanup(void *args)
/* LOCK: need to lock ic/reclaim/sr? */
vfs_statfs(cl->odf->sb, &stat);
- if (cl->force) {
- cl->force = 0;
- cleanup = ODF_CLEAN_CACHE;
- }
- else if (stat.f_bavail * 100 < stat.f_blocks * (100 -
cl->attr->thresh_b_high->val)) {
- cleanup = ODF_CLEAN_BLOCKS;
- size = stat.f_blocks * (100 - cl->attr->thresh_b_low->val) -
- (stat.f_bavail * 100);
- }
- else if (stat.f_ffree * 100 < stat.f_files * (100 -
cl->attr->thresh_i_high->val)) {
- cleanup = ODF_CLEAN_INODES;
- size = stat.f_files * (100 - cl->attr->thresh_i_low->val) -
+ if (cl->flags & ODF_CLEAN_DEFAULT) {
+
+ /* check if blocks is above threshold */
+ if (stat.f_bavail * 100 < stat.f_blocks
+ * (100 - cl->attr->thresh_b_high->val)) {
+ cleanup = 1;
+ b_size = stat.f_blocks *
+ (100 - cl->attr->thresh_b_low->val) -
+ (stat.f_bavail * 100);
+ }
+
+ /* check if inodes is above threshold */
+ if (stat.f_ffree * 100 < stat.f_files
+ * (100 - cl->attr->thresh_i_high->val)) {
+ cleanup = 1;
+ i_size = stat.f_files *
+ (100 - cl->attr->thresh_i_low->val) -
(stat.f_ffree * 100);
+ }
}
+
+ if (cl->flags & ODF_CLEAN_FULL || cl->flags & ODF_CLEAN_SR)
+ cleanup = 1;
+
if (cleanup)
- err = odf_cleanup(cl->odf, cleanup, size);
+ err = odf_cleanup(cl->odf, cl->flags, b_size, i_size);
if (err < 0)
printk(KERN_WARNING "unionfs cleanup thread: error %d\n", err);
- else {
- if (err == 0 && cl->success == 1) {
- if (cleanup == ODF_CLEAN_BLOCKS)
- printk(KERN_WARNING
- "unionfs: failed to bring free odf data
blocks below threshold\n");
- else if (cleanup == ODF_CLEAN_INODES)
- printk(KERN_WARNING
- "unionfs: failed to bring free odf
inodes below threshold\n");
- }
- cl->success = err;
- }
+ else if (err == 0 && cl->success == 1)
+ printk(KERN_WARNING
+ "unionfs: cleanup failed to bring odf below
threshold\n");
+ cl->success = err;
+ cl->flags = ODF_CLEAN_DEFAULT;
}
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index 29d1f9e..cca6c48 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -33,10 +33,10 @@
#define ODF_DIRENT_MAGIC 0x0DFD1300
-#define ODF_CLEAN_ALL 1
-#define ODF_CLEAN_CACHE 2
-#define ODF_CLEAN_INODES 3
-#define ODF_CLEAN_BLOCKS 4
+/* cleanup thread flags */
+#define ODF_CLEAN_DEFAULT 0x01
+#define ODF_CLEAN_SR 0x02
+#define ODF_CLEAN_FULL 0x04
/* Options flags */
#define ODF_OPT_KEEPCACHE 0x01
@@ -97,7 +97,7 @@ int __odf_set_opaque(struct dentry *d, int branch);
/* cleanup thread functions */
extern void __odf_cleanup(void *args);
-int odf_cleanup(struct odf_sb_info *odf, int mode, u64 size);
+int odf_cleanup(struct odf_sb_info *odf, int mode, u64 b_to_free, u64
i_to_free);
extern void generate_random_uuid(unsigned char uuid_out[16]);
diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
index bc80a8a..f618840 100644
--- a/fs/unionfs/sioq.h
+++ b/fs/unionfs/sioq.h
@@ -54,7 +54,7 @@ struct unlink_args {
struct cleanup_args {
struct odf_sb_info *odf;
struct unionfs_attributes *attr;
- int force;
+ int flags;
int success;
};
diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
index 38fbb7b..f62d2e6 100644
--- a/fs/unionfs/super.c
+++ b/fs/unionfs/super.c
@@ -425,7 +425,7 @@ static int unionfs_remount_fs(struct super_block *sb, int
*flags,
struct inode **new_lower_inodes = NULL;
int new_high_branch_id; /* new high branch ID */
struct odf_sb_info *odf = &UNIONFS_SB(sb)->odf;
- int odfforce = 0 ; /* whether the odfforce option was provided */
+ int odf_keepcache = 0 ; /* whether the odf_keepcache option was
provided */
int old_ibstart, old_ibend;
int size; /* memory allocation size, temp var */
@@ -558,13 +558,13 @@ static int unionfs_remount_fs(struct super_block *sb, int
*flags,
goto out_no_change;
}
- if (!strcmp("odfforce", optname)) {
+ if (!strcmp("odf_keepcache", optname)) {
if (optarg) {
printk("unionfs: %s does not take an
argument\n", optname);
err = -EINVAL;
goto out_release;
}
- odfforce = 1;
+ odf_keepcache = 1;
continue;
}
@@ -693,11 +693,11 @@ out_no_change:
goto out_release;
odf->opaque_branch_id = new_data[0].branch_id;
- /* if odfforce is not set, wake up the cleanup thread and force it to
- * cleanup everything
+ /* if odf_keepcache is not set, wake up the cleanup thread and force
+ * it to cleanup everything
*/
- if (!odfforce) {
- odf->cleanup->cleanup.force = 1;
+ if (!odf_keepcache) {
+ odf->cleanup->cleanup.flags = ODF_CLEAN_FULL;
wake_up_and_wait_sioa(odf->cleanup);
}
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs