Skip to content

Commit

Permalink
kernfs: make kernfs_get_active() block if the node is deactivated but…
Browse files Browse the repository at this point in the history
… not removed

Currently, kernfs_get_active() fails if the target node is
deactivated.  This is fine as a node always gets removed after
deactivation; however, we're gonna add reactivation so the assumption
won't hold.  It'd be incorrect for kernfs_get_active() to fail for a
node which was deactivated only temporarily.

This patch makes kernfs_get_active() block if the node is deactivated
but not removed.  If the node gets reactivated (not yet implemented),
it will be retried and succeed.  If the node gets removed, it will be
woken up and fail.

Signed-off-by: Tejun Heo <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
htejun authored and gregkh committed Jan 10, 2014
1 parent 99177a3 commit 895a068
Showing 1 changed file with 21 additions and 4 deletions.
25 changes: 21 additions & 4 deletions fs/kernfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,25 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn)
if (unlikely(!kn))
return NULL;

if (!atomic_inc_unless_negative(&kn->active))
return NULL;

if (kernfs_lockdep(kn))
rwsem_acquire_read(&kn->dep_map, 0, 1, _RET_IP_);
return kn;

/*
* Try to obtain an active ref. If @kn is deactivated, we block
* till either it's reactivated or killed.
*/
do {
if (atomic_inc_unless_negative(&kn->active))
return kn;

wait_event(kernfs_root(kn)->deactivate_waitq,
atomic_read(&kn->active) >= 0 ||
RB_EMPTY_NODE(&kn->rb));
} while (!RB_EMPTY_NODE(&kn->rb));

if (kernfs_lockdep(kn))
rwsem_release(&kn->dep_map, 1, _RET_IP_);
return NULL;
}

/**
Expand Down Expand Up @@ -786,6 +799,7 @@ static void __kernfs_deactivate(struct kernfs_node *kn)

static void __kernfs_remove(struct kernfs_node *kn)
{
struct kernfs_root *root = kernfs_root(kn);
struct kernfs_node *pos;

lockdep_assert_held(&kernfs_mutex);
Expand Down Expand Up @@ -837,6 +851,9 @@ static void __kernfs_remove(struct kernfs_node *kn)

kernfs_put(pos);
} while (pos != kn);

/* some nodes killed, kick get_active waiters */
wake_up_all(&root->deactivate_waitq);
}

/**
Expand Down

0 comments on commit 895a068

Please sign in to comment.