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/