Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 178751
b: refs/heads/master
c: 846f997
h: refs/heads/master
i:
  178749: 98a085c
  178747: 72f20aa
  178743: 6a403c0
  178735: 58620f7
  178719: 87b180c
  178687: 59a534c
v: v3
  • Loading branch information
Eric W. Biederman authored and Linus Torvalds committed Jan 4, 2010
1 parent 2dcce53 commit e335c7e
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3e27249c84beed1c79d767b350e52ad038db9053
refs/heads/master: 846f99749ab68bbc7f75c74fec305de675b1a1bf
14 changes: 12 additions & 2 deletions trunk/fs/sysfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,10 @@ static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
return NULL;

t = atomic_cmpxchg(&sd->s_active, v, v + 1);
if (likely(t == v))
if (likely(t == v)) {
rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
return sd;
}
if (t < 0)
return NULL;

Expand All @@ -130,6 +132,7 @@ static void sysfs_put_active(struct sysfs_dirent *sd)
if (unlikely(!sd))
return;

rwsem_release(&sd->dep_map, 1, _RET_IP_);
v = atomic_dec_return(&sd->s_active);
if (likely(v != SD_DEACTIVATED_BIAS))
return;
Expand Down Expand Up @@ -194,15 +197,21 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
sd->s_sibling = (void *)&wait;

rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_);
/* atomic_add_return() is a mb(), put_active() will always see
* the updated sd->s_sibling.
*/
v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);

if (v != SD_DEACTIVATED_BIAS)
if (v != SD_DEACTIVATED_BIAS) {
lock_contended(&sd->dep_map, _RET_IP_);
wait_for_completion(&wait);
}

sd->s_sibling = NULL;

lock_acquired(&sd->dep_map, _RET_IP_);
rwsem_release(&sd->dep_map, 1, _RET_IP_);
}

static int sysfs_alloc_ino(ino_t *pino)
Expand Down Expand Up @@ -345,6 +354,7 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)

atomic_set(&sd->s_count, 1);
atomic_set(&sd->s_active, 0);
sysfs_dirent_init_lockdep(sd);

sd->s_name = name;
sd->s_mode = mode;
Expand Down
15 changes: 15 additions & 0 deletions trunk/fs/sysfs/sysfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* This file is released under the GPLv2.
*/

#include <linux/lockdep.h>
#include <linux/fs.h>

struct sysfs_open_dirent;
Expand Down Expand Up @@ -50,6 +51,9 @@ struct sysfs_inode_attrs {
struct sysfs_dirent {
atomic_t s_count;
atomic_t s_active;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
struct sysfs_dirent *s_parent;
struct sysfs_dirent *s_sibling;
const char *s_name;
Expand Down Expand Up @@ -84,6 +88,17 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
return sd->s_flags & SYSFS_TYPE_MASK;
}

#ifdef CONFIG_DEBUG_LOCK_ALLOC
#define sysfs_dirent_init_lockdep(sd) \
do { \
static struct lock_class_key __key; \
\
lockdep_init_map(&sd->dep_map, "s_active", &__key, 0); \
} while(0)
#else
#define sysfs_dirent_init_lockdep(sd) do {} while(0)
#endif

/*
* Context structure to be used while adding/removing nodes.
*/
Expand Down

0 comments on commit e335c7e

Please sign in to comment.