From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Message-ID: <433B82E8.1010309@altlinux.com> Date: Thu, 29 Sep 2005 10:00:08 +0400 From: Anton Farygin User-Agent: Mozilla Thunderbird 1.0.2 (X11/20050512) X-Accept-Language: en-us, en MIME-Version: 1.0 To: devel@altlinux.ru Content-Type: multipart/mixed; boundary="------------080501090105010706030702" Subject: [devel] [Fwd: [Unionfs] Spread Patch for unionfs-InsertWhackyDateHere (20050923)] X-BeenThere: devel@altlinux.ru X-Mailman-Version: 2.1.5 Precedence: list Reply-To: ALT Devel discussion list List-Id: ALT Devel discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Sep 2005 06:03:35 -0000 Archived-At: List-Archive: List-Post: This is a multi-part message in MIME format. --------------080501090105010706030702 Content-Type: text/plain; charset=KOI8-R; format=flowed Content-Transfer-Encoding: 8bit Мне думается что кому-то данный патч покажется интересным. Rgds, Rider --------------080501090105010706030702 Content-Type: message/rfc822; name="[Unionfs] Spread Patch for unionfs-InsertWhackyDateHere (20050923)" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="[Unionfs] Spread Patch for unionfs-InsertWhackyDateHere (20050923)" Return-Path: X-Original-To: rider@altlinux.com Delivered-To: rider@master.altlinux.org Received: from filer.fsl.cs.sunysb.edu (filer.fsl.cs.sunysb.edu [130.245.126.2]) by master.altlinux.org (Postfix) with ESMTP id 3D6A5E31DC for ; Thu, 29 Sep 2005 01:57:04 +0400 (MSD) Received: from filer.fsl.cs.sunysb.edu (IDENT:X5HHAkHsmPE5wL/kuYrDxrTWywlVCukx@localhost.localdomain [127.0.0.1]) by filer.fsl.cs.sunysb.edu (8.12.8/8.12.8) with ESMTP id j8SLus9R007215; Wed, 28 Sep 2005 17:56:58 -0400 Received: from linux01.gwdg.de (root@linux01.gwdg.de [134.76.13.21]) by filer.fsl.cs.sunysb.edu (8.12.8/8.12.8) with ESMTP id j8SLup9P007211 for ; Wed, 28 Sep 2005 17:56:52 -0400 Received: from linux01.gwdg.de (localhost [127.0.0.1]) by linux01.gwdg.de (8.13.3/8.13.3/SuSE Linux 0.7) with ESMTP id j8SLusXx025535 for ; Wed, 28 Sep 2005 23:56:56 +0200 Received: from localhost (jengelh@localhost) by linux01.gwdg.de (8.13.3/8.13.3/Submit) with ESMTP id j8SLuscd025529 for ; Wed, 28 Sep 2005 23:56:54 +0200 Date: Wed, 28 Sep 2005 23:56:53 +0200 (MEST) From: Jan Engelhardt To: Unionfs mailing list Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Cc: Subject: [Unionfs] Spread Patch for unionfs-InsertWhackyDateHere (20050923) X-BeenThere: unionfs@mail.fsl.cs.sunysb.edu X-Mailman-Version: 2.1.5 Precedence: list List-Id: Unionfs users mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: unionfs-bounces@fsl.cs.sunysb.edu Errors-To: unionfs-bounces@fsl.cs.sunysb.edu Hi, here goes the spreader patch (formerly "balance patch" or no-name) which distributes a file at the time of creation into the branch with the lowest used disk space, making it a little "stripe" like you know from RAID. Of course, since we cannot know how big a file will eventually become in the future, this is not a true striper like it is with RAID or raiffs. As has been before, I do not know why files do net always get correctly spread. Assuming that I have a union with 3 branches (B1, B2, B3) each having the same amount of free space, and if I now copy a 3MB ogg file to the union, it gets put into the top branch (B1). Surprisingly, if I now copy a small text file to the union, it also gets put into the top branch rather than the next lower one (B2 or B3, depending on implementation). The branches move/rotate and the next 4MB ogg file correctly gets into the now-top branch B2. Yet, the next 6MB ogg file also gets into B2, which is more than just strange. So it looks like the move (branch_move()) is done too late -- i.e. after the file has already been created, but that can't be, since we just entered unionfs_create() so there is no new file yet. So by the time we reach "/* We start out in the leftmost branch. */" the leftmost branch is already the one with the most free space. (The ideal case, but it does not seem so, according to above.) Solutions welcome. Jan Engelhardt -- | Alphagate Systems, http://alphagate.hopto.org/ | jengelh's site, http://jengelh.hopto.org/ It is lacking a doc, but let's keep it short: branch_wmaxspc() returns the branch number of the branch with the most free space according to kstat(), which also `df` uses. branch_move(SB, N) puts branch N at the top (or in FS.CSL.SUNYSB.EDU parlance: left). 'Nuff said. diff -dpru unionfs-20050923-1803~/inode.c unionfs-20050923-1803/inode.c --- unionfs-20050923-1803~/inode.c 2005-09-28 23:25:09.000000000 +0200 +++ unionfs-20050923-1803/inode.c 2005-09-28 23:36:36.000000000 +0200 @@ -21,6 +21,83 @@ #include "fist.h" #include "unionfs.h" +static int branch_wmaxspc(struct super_block *); +static void branch_move(struct super_block *, int); + +static int branch_wmaxspc(struct super_block *sb) { + 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) { + 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) { @@ -29,13 +106,18 @@ 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 -dpru unionfs-20050923-1803~/main.c unionfs-20050923-1803/main.c --- unionfs-20050923-1803~/main.c 2005-09-24 00:03:15.000000000 +0200 +++ unionfs-20050923-1803/main.c 2005-09-28 23:37:36.000000000 +0200 @@ -402,6 +402,11 @@ struct unionfs_dentry_info *unionfs_pars *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) { @@ -513,6 +518,11 @@ struct unionfs_dentry_info *unionfs_pars 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 -dpru unionfs-20050923-1803~/unionfs.h unionfs-20050923-1803/unionfs.h --- unionfs-20050923-1803~/unionfs.h 2005-09-24 00:03:15.000000000 +0200 +++ unionfs-20050923-1803/unionfs.h 2005-09-28 23:36:02.000000000 +0200 @@ -129,6 +129,7 @@ struct unionfs_sb_info { unsigned long usi_mount_flag; int usi_persistent; + int usi_spread; /* These are the pointers to our various objects. */ struct super_block *usi_sb_i[UNIONFS_INLINE_OBJECTS]; # eof _______________________________________________ unionfs mailing list unionfs@mail.fsl.cs.sunysb.edu http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs --------------080501090105010706030702--