Tomas M:
> The 'umount /squashfs' part sometimes causes the error message
> "VFS: Busy inodes after unmount loop* ... etc", so I _think_ the loop
        :::

About this problem, please test this patch.


> Hm it's hard :) My problem is that I usually can't reproduce it in a
> normal Linux environment, I'm still finding these things in Slax, which
> is a chrooted OS and makes things hard to debug.
> 
> Nevertheless, you can download Slax from here
> http://www.slax.org/dl/slax6broken.iso

I will try after your uploading completes.


> >> I tried the patch you sent me, but it does nothing, or I can't see any 
> >> output in dmesg after remount,del, I'm sorry.
> > 
> > And EBUSY error returned?
> > Then it means,
> > - one or more files were opened on that branch.
> 
> This is possible but i'm unable to say, I don't know.
> I hope the feature to see this info through /sys
> will be implemented soon :)

Basically, /sys/fs/aufs/xxxx/opened_files will be equivalent to lsof.
And then EBUSY is not depends upon only the opened files. 
You wrote that lsof reported /dev/initctl was opened.
Are your sure that the device file is NOT inside aufs?
If a process (init or something) invoked before you over-mount /dev, the
process still refers the device file.


Junjiro Okajima

----------------------------------------------------------------------
diff -x CVS -x RCS -x .pdiff -rup ../../aufs.anon/aufs/fs/aufs/opts.c 
./fs/aufs/opts.c
--- ../../aufs.anon/aufs/fs/aufs/opts.c 2007-06-18 10:51:10.000000000 +0900
+++ ./fs/aufs/opts.c    2007-06-19 15:24:33.679360152 +0900
@@ -764,7 +764,7 @@ static int au_do_opt_simple(struct super
  * minus: error
  */
 static int au_do_opt_br(struct super_block *sb, struct opt *opt, int remount,
-                       int *do_refresh)
+                       int *do_refresh, int *deleted)
 {
        int err;
 
@@ -790,7 +790,7 @@ static int au_do_opt_br(struct super_blo
        case Opt_idel:
                err = br_del(sb, &opt->del, remount);
                if (!err)
-                       *do_refresh = err = 1;
+                       *deleted = *do_refresh = err = 1;
                break;
 
        case Opt_mod:
@@ -906,7 +906,7 @@ static int verify_opts(struct super_bloc
 
 int au_do_opts_mount(struct super_block *sb, struct opts *opts)
 {
-       int err, do_refresh;
+       int err, do_refresh, deleted;
        struct inode *dir;
        struct opt *opt;
        unsigned int flags, given;
@@ -935,10 +935,11 @@ int au_do_opts_mount(struct super_block 
        au_flag_clr(sb, AuFlag_XINO | AuFlag_DLGT);
        udba_set(sb, AuFlag_UDBA_REVAL);
 
-       do_refresh = 0;
+       deleted = do_refresh = 0;
        opt = opts->opt;
        while (err >= 0 && opt->type != Opt_tail)
-               err = au_do_opt_br(sb, opt++, /*remount*/0, &do_refresh);
+               err = au_do_opt_br(sb, opt++, /*remount*/0, &do_refresh,
+                                  &deleted);
        if (err > 0)
                err = 0;
        else if (unlikely(err < 0))
@@ -996,7 +997,7 @@ int au_do_opts_mount(struct super_block 
 }
 
 int au_do_opts_remount(struct super_block *sb, struct opts *opts,
-                      int *do_refresh, unsigned int *given)
+                      int *do_refresh, unsigned int *given, int *deleted)
 {
        int err, rerr;
        struct inode *dir;
@@ -1012,7 +1013,7 @@ int au_do_opts_remount(struct super_bloc
        //AuDebugOn(au_flag_test(sb, AuFlag_UDBA_INOTIFY));
 
        err = 0;
-       *do_refresh = 0;
+       *deleted = *do_refresh = 0;
        *given = 0;
        dlgt = au_flag_test(sb, AuFlag_DLGT);
        opt_xino = NULL;
@@ -1025,7 +1026,8 @@ int au_do_opts_remount(struct super_bloc
                au_flag_clr(sb, AuFlag_DLGT);
 
                if (!err)
-                       err = au_do_opt_br(sb, opt, /*remount*/1, do_refresh);
+                       err = au_do_opt_br(sb, opt, /*remount*/1, do_refresh,
+                                          deleted);
                if (!err)
                        err = au_do_opt_xino(sb, opt, /*remount*/1, &opt_xino);
 
diff -x CVS -x RCS -x .pdiff -rup ../../aufs.anon/aufs/fs/aufs/opts.h 
./fs/aufs/opts.h
--- ../../aufs.anon/aufs/fs/aufs/opts.h 2007-06-18 10:51:10.000000000 +0900
+++ ./fs/aufs/opts.h    2007-06-19 15:38:47.967488616 +0900
@@ -90,7 +90,7 @@ void au_free_opts(struct opts *opts);
 int au_parse_opts(struct super_block *sb, char *str, struct opts *opts);
 int au_do_opts_mount(struct super_block *sb, struct opts *opts);
 int au_do_opts_remount(struct super_block *sb, struct opts *opts,
-                      int *do_refresh, unsigned int *given);
+                      int *do_refresh, unsigned int *given, int *deleted);
 
 #endif /* __KERNEL__ */
 #endif /* __AUFS_OPTS_H__ */
diff -x CVS -x RCS -x .pdiff -rup ../../aufs.anon/aufs/fs/aufs/super.c 
./fs/aufs/super.c
--- ../../aufs.anon/aufs/fs/aufs/super.c        2007-06-18 10:53:21.000000000 
+0900
+++ ./fs/aufs/super.c   2007-06-19 15:40:42.172126872 +0900
@@ -432,6 +432,66 @@ static int refresh_dir(struct dentry *ro
        return err;
 }
 
+static int test_nondir(struct dentry *dentry, void *arg)
+{
+       return !S_ISDIR(dentry->d_inode->i_mode);
+}
+
+static int refresh_nondir(struct dentry *root, int sgen)
+{
+       int err, i, j, ndentry;
+       struct au_dcsub_pages dpages;
+       struct au_dpage *dpage;
+       struct dentry **dentries;
+       struct dentry *parent;
+       struct inode *inode;
+
+       LKTRTrace("sgen %d\n", sgen);
+       SiMustWriteLock(root->d_sb);
+       AuDebugOn(au_digen(root) != sgen);
+       DiMustWriteLock(root);
+
+       err = au_dpages_init(&dpages, GFP_KERNEL);
+       if (unlikely(err))
+               goto out;
+       err = au_dcsub_pages(&dpages, root, test_nondir, NULL);
+       if (unlikely(err))
+               goto out_dpages;
+
+       for (i = 0; !err && i < dpages.ndpage; i++) {
+               dpage = dpages.dpages + i;
+               dentries = dpage->dentries;
+               ndentry = dpage->ndentry;
+               for (j = 0; !err && j < ndentry; j++) {
+                       struct dentry *d;
+                       d = dentries[j];
+                       if (d->d_inode && au_digen(d) != sgen) {
+                               di_write_lock_child(d);
+                               inode = d->d_inode;
+                               parent = dget_parent(d);
+                               AuDebugOn(S_ISDIR(inode->i_mode)
+                                         || au_digen(parent) != sgen);
+                               di_read_lock_parent(parent, AUFS_I_RLOCK);
+                               /* returns a number of positive dentries */
+                               err = au_refresh_hdentry(d, inode->i_mode & 
S_IFMT);
+                               //err = -1;
+                               if (err >= 0)
+                                       err = au_refresh_hinode(inode, d);
+                               //err = -1;
+                               di_read_unlock(parent, AUFS_I_RLOCK);
+                               dput(parent);
+                               di_write_unlock(d);
+                       }
+               }
+       }
+
+ out_dpages:
+       au_dpages_free(&dpages);
+ out:
+       TraceErr(err);
+       return err;
+}
+
 /* stop extra interpretation of errno in mount(8), and strange error messages 
*/
 static int cvt_err(int err)
 {
@@ -450,7 +510,7 @@ static int cvt_err(int err)
 /* protected by s_umount */
 static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
 {
-       int err, do_refresh;
+       int err, do_refresh, deleted;
        struct dentry *root;
        struct inode *inode;
        struct opts opts;
@@ -498,9 +558,9 @@ static int aufs_remount_fs(struct super_
        //DbgSleep(3);
 
        /* au_do_opts() may return an error */
-       do_refresh = 0;
+       deleted = do_refresh = 0;
        given = 0;
-       err = au_do_opts_remount(sb, &opts, &do_refresh, &given);
+       err = au_do_opts_remount(sb, &opts, &do_refresh, &given, &deleted);
        //if (LktrCond) err = -1;
        au_free_opts(&opts);
 
@@ -513,7 +573,14 @@ static int aufs_remount_fs(struct super_
                au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
                sbinfo->si_failed_refresh_dirs = 0;
                rerr = refresh_dir(root, au_sigen(sb));
-               if (unlikely(rerr)) {
+               if (!rerr) {
+                       if (unlikely(deleted)) {
+                               rerr = refresh_nondir(root, au_sigen(sb));
+                               if (unlikely(rerr))
+                                       Warn("Refreshing non-directories 
failed,"
+                                            " ignores (%d)\n", rerr);
+                       }
+               } else {
                        sbinfo->si_failed_refresh_dirs = 1;
                        Warn("Refreshing directories failed, ignores (%d)\n",
                             rerr);

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

Reply via email to