forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a new field to fs_pin - kill(pin). That's what umount and r/o remount will be calling for all pins attached to vfsmount and superblock resp. Called after bumping the refcount, so it won't go away under us. Dropping the refcount is responsibility of the instance. All generic stuff moved to fs/fs_pin.c; the next step will rip all the knowledge of kernel/acct.c from fs/super.c and fs/namespace.c. After that - death to mnt_pin(); it was intended to be usable as generic mechanism for code that wants to attach objects to vfsmount, so that they would not make the sucker busy and would get killed on umount. Never got it right; it remained acct.c-specific all along. Now it's very close to being killable. Signed-off-by: Al Viro <[email protected]>
- Loading branch information
Al Viro
committed
Aug 7, 2014
1 parent
1629d0e
commit efb170c
Showing
5 changed files
with
129 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#include <linux/fs.h> | ||
#include <linux/slab.h> | ||
#include <linux/fs_pin.h> | ||
#include "mount.h" | ||
|
||
static void pin_free_rcu(struct rcu_head *head) | ||
{ | ||
kfree(container_of(head, struct fs_pin, rcu)); | ||
} | ||
|
||
static DEFINE_SPINLOCK(pin_lock); | ||
|
||
void pin_put(struct fs_pin *p) | ||
{ | ||
if (atomic_long_dec_and_test(&p->count)) | ||
call_rcu(&p->rcu, pin_free_rcu); | ||
} | ||
|
||
void pin_remove(struct fs_pin *pin) | ||
{ | ||
spin_lock(&pin_lock); | ||
hlist_del(&pin->m_list); | ||
hlist_del(&pin->s_list); | ||
spin_unlock(&pin_lock); | ||
} | ||
|
||
void pin_insert(struct fs_pin *pin, struct vfsmount *m) | ||
{ | ||
spin_lock(&pin_lock); | ||
hlist_add_head(&pin->s_list, &m->mnt_sb->s_pins); | ||
hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins); | ||
spin_unlock(&pin_lock); | ||
} | ||
|
||
void acct_auto_close_mnt(struct hlist_head *list) | ||
{ | ||
while (1) { | ||
struct hlist_node *p; | ||
struct fs_pin *pin; | ||
rcu_read_lock(); | ||
p = ACCESS_ONCE(list->first); | ||
if (!p) { | ||
rcu_read_unlock(); | ||
break; | ||
} | ||
pin = hlist_entry(p, struct fs_pin, m_list); | ||
if (!atomic_long_inc_not_zero(&pin->count)) { | ||
rcu_read_unlock(); | ||
cpu_relax(); | ||
continue; | ||
} | ||
rcu_read_unlock(); | ||
pin->kill(pin); | ||
} | ||
} | ||
|
||
void acct_auto_close(struct hlist_head *list) | ||
{ | ||
while (1) { | ||
struct hlist_node *p; | ||
struct fs_pin *pin; | ||
rcu_read_lock(); | ||
p = ACCESS_ONCE(list->first); | ||
if (!p) { | ||
rcu_read_unlock(); | ||
break; | ||
} | ||
pin = hlist_entry(p, struct fs_pin, s_list); | ||
if (!atomic_long_inc_not_zero(&pin->count)) { | ||
rcu_read_unlock(); | ||
cpu_relax(); | ||
continue; | ||
} | ||
rcu_read_unlock(); | ||
pin->kill(pin); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <linux/fs.h> | ||
|
||
struct fs_pin { | ||
atomic_long_t count; | ||
union { | ||
struct { | ||
struct hlist_node s_list; | ||
struct hlist_node m_list; | ||
}; | ||
struct rcu_head rcu; | ||
}; | ||
void (*kill)(struct fs_pin *); | ||
}; | ||
|
||
void pin_put(struct fs_pin *); | ||
void pin_remove(struct fs_pin *); | ||
void pin_insert(struct fs_pin *, struct vfsmount *); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters