diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2005-11-07 17:13:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 21:18:09 -0500 |
commit | 7b7b1ace2d9d06d76bce7481a045c22ed75e35dd (patch) | |
tree | 458f9f16b855ed0347013048c13d3a29031f00ee /include | |
parent | 254ce8dc882f8d69e5d49ed4807c94a61976fb15 (diff) |
[PATCH] saner handling of auto_acct_off() and DQUOT_OFF() in umount
The way we currently deal with quota and process accounting that might
keep vfsmount busy at umount time is inherently broken; we try to turn
them off just in case (not quite correctly, at that) and
a) pray umount doesn't fail (otherwise they'll stay turned off)
b) pray nobody doesn anything funny just as we turn quota off
Moreover, LSM provides hooks for doing the same sort of broken logics.
The proper way to deal with that is to introduce the second kind of
reference to vfsmount. Semantics:
- when the last normal reference is dropped, all special ones are
converted to normal ones and if there had been any, cleanup is done.
- normal reference can be cloned into a special one
- special reference can be converted to normal one; that's a no-op if
we'd already passed the point of no return (i.e. mntput() had
converted special references to normal and started cleanup).
The way it works: e.g. starting process accounting converts the vfsmount
reference pinned by the opened file into special one and turns it back
to normal when it gets shut down; acct_auto_close() is done when no
normal references are left. That way it does *not* obstruct umount(2)
and it silently gets turned off when the last normal reference to
vfsmount is gone. Which is exactly what we want...
The same should be done by LSM module that holds some internal
references to vfsmount and wants to shut them down on umount - it should
make them special and security_sb_umount_close() will be called exactly
when the last normal reference to vfsmount is gone.
quota handling is even simpler - we don't use normal file IO anymore, so
there's no need to hold vfsmounts at all. DQUOT_OFF() is done from
deactivate_super(), where it really belongs.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/acct.h | 3 | ||||
-rw-r--r-- | include/linux/mount.h | 13 | ||||
-rw-r--r-- | include/linux/quota.h | 1 |
3 files changed, 7 insertions, 10 deletions
diff --git a/include/linux/acct.h b/include/linux/acct.h index 19f70462b3be..93c5b3cdf951 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h | |||
@@ -117,12 +117,15 @@ struct acct_v3 | |||
117 | #include <linux/config.h> | 117 | #include <linux/config.h> |
118 | 118 | ||
119 | #ifdef CONFIG_BSD_PROCESS_ACCT | 119 | #ifdef CONFIG_BSD_PROCESS_ACCT |
120 | struct vfsmount; | ||
120 | struct super_block; | 121 | struct super_block; |
122 | extern void acct_auto_close_mnt(struct vfsmount *m); | ||
121 | extern void acct_auto_close(struct super_block *sb); | 123 | extern void acct_auto_close(struct super_block *sb); |
122 | extern void acct_process(long exitcode); | 124 | extern void acct_process(long exitcode); |
123 | extern void acct_update_integrals(struct task_struct *tsk); | 125 | extern void acct_update_integrals(struct task_struct *tsk); |
124 | extern void acct_clear_integrals(struct task_struct *tsk); | 126 | extern void acct_clear_integrals(struct task_struct *tsk); |
125 | #else | 127 | #else |
128 | #define acct_auto_close_mnt(x) do { } while (0) | ||
126 | #define acct_auto_close(x) do { } while (0) | 129 | #define acct_auto_close(x) do { } while (0) |
127 | #define acct_process(x) do { } while (0) | 130 | #define acct_process(x) do { } while (0) |
128 | #define acct_update_integrals(x) do { } while (0) | 131 | #define acct_update_integrals(x) do { } while (0) |
diff --git a/include/linux/mount.h b/include/linux/mount.h index f8f39937e301..ffb0b5089880 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
@@ -37,6 +37,7 @@ struct vfsmount | |||
37 | struct list_head mnt_list; | 37 | struct list_head mnt_list; |
38 | struct list_head mnt_expire; /* link in fs-specific expiry list */ | 38 | struct list_head mnt_expire; /* link in fs-specific expiry list */ |
39 | struct namespace *mnt_namespace; /* containing namespace */ | 39 | struct namespace *mnt_namespace; /* containing namespace */ |
40 | int mnt_pinned; | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | static inline struct vfsmount *mntget(struct vfsmount *mnt) | 43 | static inline struct vfsmount *mntget(struct vfsmount *mnt) |
@@ -46,15 +47,9 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt) | |||
46 | return mnt; | 47 | return mnt; |
47 | } | 48 | } |
48 | 49 | ||
49 | extern void __mntput(struct vfsmount *mnt); | 50 | extern void mntput_no_expire(struct vfsmount *mnt); |
50 | 51 | extern void mnt_pin(struct vfsmount *mnt); | |
51 | static inline void mntput_no_expire(struct vfsmount *mnt) | 52 | extern void mnt_unpin(struct vfsmount *mnt); |
52 | { | ||
53 | if (mnt) { | ||
54 | if (atomic_dec_and_test(&mnt->mnt_count)) | ||
55 | __mntput(mnt); | ||
56 | } | ||
57 | } | ||
58 | 53 | ||
59 | static inline void mntput(struct vfsmount *mnt) | 54 | static inline void mntput(struct vfsmount *mnt) |
60 | { | 55 | { |
diff --git a/include/linux/quota.h b/include/linux/quota.h index 700ead45084f..f33aeb22c26a 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -289,7 +289,6 @@ struct quota_info { | |||
289 | struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */ | 289 | struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */ |
290 | struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */ | 290 | struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */ |
291 | struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ | 291 | struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ |
292 | struct vfsmount *mnt[MAXQUOTAS]; /* mountpoint entries of filesystems with quota files */ | ||
293 | struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ | 292 | struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ |
294 | struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ | 293 | struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ |
295 | }; | 294 | }; |