diff options
| -rw-r--r-- | fs/mount.h | 1 | ||||
| -rw-r--r-- | fs/namespace.c | 2 | ||||
| -rw-r--r-- | fs/super.c | 2 | ||||
| -rw-r--r-- | include/linux/acct.h | 6 | ||||
| -rw-r--r-- | include/linux/fs.h | 1 | ||||
| -rw-r--r-- | kernel/acct.c | 135 | 
6 files changed, 62 insertions, 85 deletions
diff --git a/fs/mount.h b/fs/mount.h index d55297f2fa05..0a2d1458681f 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -56,6 +56,7 @@ struct mount {  	int mnt_group_id;		/* peer group identifier */  	int mnt_expiry_mark;		/* true if marked for expiry */  	int mnt_pinned; +	struct hlist_head mnt_pins;  	struct path mnt_ex_mountpoint;  }; diff --git a/fs/namespace.c b/fs/namespace.c index 182bc41cd887..22e530addfaf 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -956,7 +956,7 @@ put_again:  		mnt->mnt_pinned = 0;  		rcu_read_unlock();  		unlock_mount_hash(); -		acct_auto_close_mnt(&mnt->mnt); +		acct_auto_close_mnt(&mnt->mnt_pins);  		goto put_again;  	}  	if (unlikely(mnt->mnt.mnt_flags & MNT_DOOMED)) { diff --git a/fs/super.c b/fs/super.c index d20d5b11dedf..52ed93eb63df 100644 --- a/fs/super.c +++ b/fs/super.c @@ -703,7 +703,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)  #endif  	if (flags & MS_RDONLY) -		acct_auto_close(sb); +		acct_auto_close(&sb->s_pins);  	shrink_dcache_sb(sb);  	remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY); diff --git a/include/linux/acct.h b/include/linux/acct.h index 4a5b7cb56079..65a4f889182e 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h @@ -24,14 +24,14 @@ struct super_block;  struct pacct_struct;  struct pid_namespace;  extern int acct_parm[]; /* for sysctl */ -extern void acct_auto_close_mnt(struct vfsmount *m); -extern void acct_auto_close(struct super_block *sb); +extern void acct_auto_close(struct hlist_head *); +extern void acct_auto_close_mnt(struct hlist_head *);  extern void acct_collect(long exitcode, int group_dead);  extern void acct_process(void);  extern void acct_exit_ns(struct pid_namespace *);  #else -#define acct_auto_close_mnt(x)	do { } while (0)  #define acct_auto_close(x)	do { } while (0) +#define acct_auto_close_mnt(x)	do { } while (0)  #define acct_collect(x,y)	do { } while (0)  #define acct_process()		do { } while (0)  #define acct_exit_ns(ns)	do { } while (0) diff --git a/include/linux/fs.h b/include/linux/fs.h index 4b7d57cf7863..17f70872a4a5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1250,6 +1250,7 @@ struct super_block {  	/* AIO completions deferred from interrupt context */  	struct workqueue_struct *s_dio_done_wq; +	struct hlist_head s_pins;  	/*  	 * Keep the lru lists last in the structure so they always sit on their diff --git a/kernel/acct.c b/kernel/acct.c index 019f012a3c6f..21fbb3c27c2a 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -59,6 +59,7 @@  #include <asm/div64.h>  #include <linux/blkdev.h> /* sector_div */  #include <linux/pid_namespace.h> +#include <../fs/mount.h>	/* will go away when we refactor */  /*   * These constants control the amount of freespace that suspend and @@ -79,16 +80,16 @@ static void do_acct_process(struct bsd_acct_struct *acct);  struct bsd_acct_struct {  	long			count; +	struct hlist_node	s_list; +	struct hlist_node	m_list;  	struct mutex		lock;  	int			active;  	unsigned long		needcheck;  	struct file		*file;  	struct pid_namespace	*ns; -	struct list_head	list;  };  static DEFINE_SPINLOCK(acct_lock); -static LIST_HEAD(acct_list);  /*   * Check the amount of free space and suspend/resume accordingly. @@ -133,25 +134,33 @@ static void acct_put(struct bsd_acct_struct *p)  	spin_unlock(&acct_lock);  } -static struct bsd_acct_struct *acct_get(struct bsd_acct_struct **p) +static struct bsd_acct_struct *__acct_get(struct bsd_acct_struct *res) +{ +	res->count++; +	spin_unlock(&acct_lock); +	mutex_lock(&res->lock); +	if (!res->ns) { +		mutex_unlock(&res->lock); +		spin_lock(&acct_lock); +		if (!--res->count) +			kfree(res); +		return NULL; +	} +	return res; +} + +static struct bsd_acct_struct *acct_get(struct pid_namespace *ns)  {  	struct bsd_acct_struct *res;  	spin_lock(&acct_lock);  again: -	res = *p; -	if (res) -		res->count++; -	spin_unlock(&acct_lock); -	if (res) { -		mutex_lock(&res->lock); -		if (!res->ns) { -			mutex_unlock(&res->lock); -			spin_lock(&acct_lock); -			if (!--res->count) -				kfree(res); -			goto again; -		} +	if (!ns->bacct) { +		spin_unlock(&acct_lock); +		return NULL;  	} +	res = __acct_get(ns->bacct); +	if (!res) +		goto again;  	return res;  } @@ -162,7 +171,8 @@ static void acct_kill(struct bsd_acct_struct *acct,  		struct file *file = acct->file;  		struct pid_namespace *ns = acct->ns;  		spin_lock(&acct_lock); -		list_del(&acct->list); +		hlist_del(&acct->m_list); +		hlist_del(&acct->s_list);  		mnt_unpin(file->f_path.mnt);  		spin_unlock(&acct_lock);  		do_acct_process(acct); @@ -170,8 +180,10 @@ static void acct_kill(struct bsd_acct_struct *acct,  		spin_lock(&acct_lock);  		ns->bacct = new;  		if (new) { -			mnt_pin(new->file->f_path.mnt); -			list_add(&new->list, &acct_list); +			struct vfsmount *m = new->file->f_path.mnt; +			mnt_pin(m); +			hlist_add_head(&new->s_list, &m->mnt_sb->s_pins); +			hlist_add_head(&new->m_list, &real_mount(m)->mnt_pins);  		}  		acct->ns = NULL;  		mutex_unlock(&acct->lock); @@ -218,14 +230,15 @@ static int acct_on(struct filename *pathname)  	mutex_init(&acct->lock);  	mnt = file->f_path.mnt; -	old = acct_get(&ns->bacct); +	old = acct_get(ns);  	if (old) {  		acct_kill(old, acct);  	} else {  		spin_lock(&acct_lock);  		ns->bacct = acct;  		mnt_pin(mnt); -		list_add(&acct->list, &acct_list); +		hlist_add_head(&acct->s_list, &mnt->mnt_sb->s_pins); +		hlist_add_head(&acct->m_list, &real_mount(mnt)->mnt_pins);  		spin_unlock(&acct_lock);  	}  	mntput(mnt); /* it's pinned, now give up active reference */ @@ -261,79 +274,41 @@ SYSCALL_DEFINE1(acct, const char __user *, name)  		mutex_unlock(&acct_on_mutex);  		putname(tmp);  	} else { -		acct_kill(acct_get(&task_active_pid_ns(current)->bacct), NULL); +		acct_kill(acct_get(task_active_pid_ns(current)), NULL);  	}  	return error;  } -/** - * acct_auto_close - turn off a filesystem's accounting if it is on - * @m: vfsmount being shut down - * - * If the accounting is turned on for a file in the subtree pointed to - * to by m, turn accounting off.  Done when m is about to die. - */ -void acct_auto_close_mnt(struct vfsmount *m) +void acct_auto_close_mnt(struct hlist_head *list)  { -	struct bsd_acct_struct *acct; - -	spin_lock(&acct_lock); -restart: -	list_for_each_entry(acct, &acct_list, list) -		if (acct->file->f_path.mnt == m) { -			acct->count++; -			spin_unlock(&acct_lock); -			mutex_lock(&acct->lock); -			if (!acct->ns) { -				mutex_unlock(&acct->lock); -				spin_lock(&acct_lock); -				if (!--acct->count) -					kfree(acct); -				goto restart; -			} -			acct_kill(acct, NULL); -			spin_lock(&acct_lock); -			goto restart; -		} +	while (1) { +		spin_lock(&acct_lock); +		if (!list->first) +			break; +		acct_kill(__acct_get(hlist_entry(list->first, +						 struct bsd_acct_struct, +						 m_list)), NULL); +	}  	spin_unlock(&acct_lock);  } -/** - * acct_auto_close - turn off a filesystem's accounting if it is on - * @sb: super block for the filesystem - * - * If the accounting is turned on for a file in the filesystem pointed - * to by sb, turn accounting off. - */ -void acct_auto_close(struct super_block *sb) +void acct_auto_close(struct hlist_head *list)  { -	struct bsd_acct_struct *acct; - -	spin_lock(&acct_lock); -restart: -	list_for_each_entry(acct, &acct_list, list) -		if (acct->file->f_path.dentry->d_sb == sb) { -			acct->count++; -			spin_unlock(&acct_lock); -			mutex_lock(&acct->lock); -			if (!acct->ns) { -				mutex_unlock(&acct->lock); -				spin_lock(&acct_lock); -				if (!--acct->count) -					kfree(acct); -				goto restart; -			} -			acct_kill(acct, NULL); -			spin_lock(&acct_lock); -			goto restart; -		} +	while (1) { +		spin_lock(&acct_lock); +		if (!list->first) +			break; +		acct_kill(__acct_get(hlist_entry(list->first, +						 struct bsd_acct_struct, +						 s_list)), NULL); +	}  	spin_unlock(&acct_lock);  }  void acct_exit_ns(struct pid_namespace *ns)  { -	acct_kill(acct_get(&ns->bacct), NULL); +	acct_kill(acct_get(ns), NULL);  }  /* @@ -602,7 +577,7 @@ void acct_collect(long exitcode, int group_dead)  static void slow_acct_process(struct pid_namespace *ns)  {  	for ( ; ns; ns = ns->parent) { -		struct bsd_acct_struct *acct = acct_get(&ns->bacct); +		struct bsd_acct_struct *acct = acct_get(ns);  		if (acct) {  			do_acct_process(acct);  			mutex_unlock(&acct->lock);  | 
