Hi Jan, I analyzed your patch. I don't think that is Ok for my purpose because the writing branch is fixed just at the creation time of the union. In any case, thanks a lot for your patience to reply me.
ciao luigi Jan Engelhardt ha scritto: > Index: linux-2.6.18_rc4/fs/unionfs/inode.c > =================================================================== > --- linux-2.6.18_rc4.orig/fs/unionfs/inode.c > +++ linux-2.6.18_rc4/fs/unionfs/inode.c > @@ -10,6 +10,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] gmx de> > * > * For specific licensing information, see the COPYING file distributed with > * this package. > @@ -30,6 +31,84 @@ extern int unionfs_readlink(struct dentr > extern void unionfs_put_link(struct dentry *dentry, struct nameidata *nd, > void *cookie); > > +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->s_root, &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) > { > @@ -38,13 +117,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); > 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); > Index: linux-2.6.18_rc4/fs/unionfs/main.c > =================================================================== > --- linux-2.6.18_rc4.orig/fs/unionfs/main.c > +++ linux-2.6.18_rc4/fs/unionfs/main.c > @@ -487,6 +487,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) { > @@ -581,6 +586,11 @@ static struct unionfs_dentry_info *union > err = -EINVAL; > goto out_error; > } > + if(stopd(sb)->usi_spread && !(MOUNT_FLAG(sb) & DELETE_ALL)) { > + printk(KERN_WARNING "unionfs: Using \"spread\" option requires > delete=all\n"); > + err = -EINVAL; > + goto out_error; > + } > goto out; > > out_error: > Index: linux-2.6.18_rc4/fs/unionfs/unionfs.h > =================================================================== > --- linux-2.6.18_rc4.orig/fs/unionfs/unionfs.h > +++ linux-2.6.18_rc4/fs/unionfs/unionfs.h > @@ -160,6 +160,7 @@ struct unionfs_sb_info { > int usi_firstputmap; > int usi_lastputmap; > struct putmap **usi_putmaps; > + int usi_spread; > > #ifdef UNIONFS_IMAP > int usi_persistent; > ##<<EOF>> > > -`J' > -- > ------------------------------------------------------------------------ > > _______________________________________________ > unionfs mailing list > unionfs@mail.fsl.cs.sunysb.edu > http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs _______________________________________________ unionfs mailing list unionfs@mail.fsl.cs.sunysb.edu http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs