Hi,
here is the unionfs file spreader (aka: fakeraid) patch updated to
unionfs-20060111. I post it for list readers; a merge into the unionfs
tree is not planned, but welcome anytime.
Signed-off-by: Jan Engelhardt <[EMAIL PROTECTED]>
diff --fast -Ndpru linux-2.6.15~/fs/unionfs/inode.c
linux-2.6.15/fs/unionfs/inode.c
--- linux-2.6.15~/fs/unionfs/inode.c 2006-01-10 02:55:01.000000000 +0100
+++ linux-2.6.15/fs/unionfs/inode.c 2006-01-14 18:26:49.413054000 +0100
@@ -9,6 +9,7 @@
* Copyright (c) 2003 Harikesavan Krishnan
* Copyright (c) 2003-2006 Stony Brook University
* Copyright (c) 2003-2006 The Research Foundation of State University of New
York
+ * Copyright © 2005-2006 Jan Engelhardt <jengelh [at] linux01 gwdg de>
*
* For specific licensing information, see the COPYING file distributed with
* this package.
@@ -34,6 +35,84 @@ extern void unionfs_put_link(struct dent
void *cookie);
#endif
+static int branch_wmaxspc(struct super_block *);
+static void branch_move(struct super_block *, int);
+
+//-----------------------------------------------------------------------------
+static int branch_wmaxspc(struct super_block *sb) {
+ // Returns the number of the read-write branch with the most free space
+ int bstart = sbstart(sb), bend = sbmax(sb), bindex;
+ struct super_block *hidden_sb;
+ struct kstatfs statbuf = {};
+ sector_t best_free = 0;
+ int best_branch = 0;
+
+ for(bindex = bstart; bindex < bend; ++bindex) {
+ int bindex1, sb_dup = 0;
+
+ if(!(branchperms(sb, bindex) & MAY_WRITE))
+ continue;
+
+ hidden_sb = stohs_index(sb, bindex);
+ for(bindex1 = bstart; bindex1 < bindex; ++bindex1) {
+ if(hidden_sb == stohs_index(sb, bindex1)) {
+ sb_dup = 1;
+ break;
+ }
+ }
+ if(sb_dup || vfs_statfs(hidden_sb, &statbuf) != 0)
+ continue;
+ if(statbuf.f_bfree > best_free) {
+ best_free = statbuf.f_bfree;
+ best_branch = bindex;
+ }
+ }
+
+ return best_branch;
+}
+
+static void branch_move(struct super_block *sb, int chosen) {
+ // Move the CHOSEN branch into first place
+ struct dentry *hdentry, *sroot = sb->s_root;
+ struct inode *hinode, *sinode = sroot->d_inode;
+ struct super_block *hsb;
+ struct vfsmount *hmount;
+ int count, perms, gen, i;
+
+ lock_super(sb);
+ atomic_inc(&stopd(sb)->usi_generation);
+ gen = atomic_read(&stopd(sb)->usi_generation);
+ atomic_set(&dtopd(sroot)->udi_generation, gen);
+ atomic_set(&itopd(sinode)->uii_generation, gen);
+
+ count = branch_count(sb, chosen);
+ perms = branchperms(sb, chosen);
+ hmount = stohiddenmnt_index(sb, chosen);
+ hsb = stohs_index(sb, chosen);
+ hdentry = dtohd_index(sroot, chosen);
+ hinode = itohi_index(sinode, chosen);
+
+ for(i = chosen; i > 0; --i) {
+ int prev = i - 1;
+ set_branch_count(sb, i, branch_count(sb, prev));
+ set_branchperms(sb, i, branchperms(sb, prev));
+ set_stohiddenmnt_index(sb, i, stohiddenmnt_index(sb, prev));
+ set_stohs_index(sb, i, stohs_index(sb, prev));
+ set_dtohd_index(sroot, i, dtohd_index(sroot, prev));
+ set_itohi_index(sinode, i, itohi_index(sinode, prev));
+ }
+
+ set_branch_count(sb, 0, count);
+ set_branchperms(sb, 0, perms);
+ set_stohiddenmnt_index(sb, 0, hmount);
+ set_stohs_index(sb, 0, hsb);
+ set_dtohd_index(sroot, 0, hdentry);
+ set_itohi_index(sinode, 0, hinode);
+
+ unlock_super(sb);
+ return;
+}
+
static int unionfs_create(struct inode *parent, struct dentry *dentry,
int mode, struct nameidata *nd)
{
@@ -42,13 +121,17 @@ static int unionfs_create(struct inode *
struct dentry *whiteout_dentry = NULL;
struct dentry *new_hidden_dentry;
struct dentry *hidden_parent_dentry = NULL;
- int bindex = 0, bstart;
+ int bindex = 0, bstart, mx;
char *name = NULL;
print_entry_location();
lock_dentry(dentry);
fist_print_dentry("IN unionfs_create", dentry);
+ if(stopd(dentry->d_sb)->usi_spread &&
+ (mx = branch_wmaxspc(dentry->d_sb)) != 0)
+ branch_move(dentry->d_sb, mx);
+
/* We start out in the leftmost branch. */
bstart = dbstart(dentry);
hidden_dentry = dtohd(dentry);
diff --fast -Ndpru linux-2.6.15~/fs/unionfs/main.c
linux-2.6.15/fs/unionfs/main.c
--- linux-2.6.15~/fs/unionfs/main.c 2006-01-10 02:55:01.000000000 +0100
+++ linux-2.6.15/fs/unionfs/main.c 2006-01-14 18:23:22.043054000 +0100
@@ -461,6 +461,11 @@ static struct unionfs_dentry_info *union
*optarg++ = '\0';
}
+ if(strcmp(optname, "spread") == 0) {
+ stopd(sb)->usi_spread = 1;
+ continue;
+ }
+
/* All of our options take an argument now. Insert ones that
* don't, above this check. */
if (!optarg) {
@@ -572,6 +577,11 @@ static struct unionfs_dentry_info *union
err = -EINVAL;
goto out_error;
}
+ if(stopd(sb)->usi_spread && (MOUNT_FLAG(sb) & DELETE_WHITEOUT)) {
+ printk(KERN_WARNING "unionfs: Using \"spread\" option requires
delete=all\n");
+ err = -EINVAL;
+ goto out_error;
+ }
if (mounter_f && !(copyupuid_f && copyupgid_f && copyupmode_f)) {
printk(KERN_WARNING
"unionfs: "
diff --fast -Ndpru linux-2.6.15~/fs/unionfs/unionfs.h
linux-2.6.15/fs/unionfs/unionfs.h
--- linux-2.6.15~/fs/unionfs/unionfs.h 2006-01-10 02:55:01.000000000 +0100
+++ linux-2.6.15/fs/unionfs/unionfs.h 2006-01-14 18:23:22.043054000 +0100
@@ -131,6 +131,7 @@ struct unionfs_sb_info {
struct rw_semaphore usi_rwsem;
int usi_persistent;
+ int usi_spread;
/* These are the pointers to our various objects. */
struct super_block *usi_sb_i[UNIONFS_INLINE_OBJECTS];
#<<eof>>
Jan Engelhardt
--
| Alphagate Systems, http://alphagate.hopto.org/
| jengelh's site, http://jengelh.hopto.org/_______________________________________________
unionfs mailing list
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs