Skip to content

Commit

Permalink
inotify: Do not drop mark reference under idr_lock
Browse files Browse the repository at this point in the history
Dropping mark reference can result in mark being freed. Although it
should not happen in inotify_remove_from_idr() since caller should hold
another reference, just don't risk lock up just after WARN_ON
unnecessarily. Also fold do_inotify_remove_from_idr() into the single
callsite as that function really is just two lines of real code.

Reviewed-by: Miklos Szeredi <[email protected]>
Reviewed-by: Amir Goldstein <[email protected]>
Signed-off-by: Jan Kara <[email protected]>
  • Loading branch information
jankara committed Apr 10, 2017
1 parent 08991e8 commit e725376
Showing 1 changed file with 6 additions and 18 deletions.
24 changes: 6 additions & 18 deletions fs/notify/inotify/inotify_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,28 +395,14 @@ static struct inotify_inode_mark *inotify_idr_find(struct fsnotify_group *group,
return i_mark;
}

static void do_inotify_remove_from_idr(struct fsnotify_group *group,
struct inotify_inode_mark *i_mark)
{
struct idr *idr = &group->inotify_data.idr;
spinlock_t *idr_lock = &group->inotify_data.idr_lock;
int wd = i_mark->wd;

assert_spin_locked(idr_lock);

idr_remove(idr, wd);

/* removed from the idr, drop that ref */
fsnotify_put_mark(&i_mark->fsn_mark);
}

/*
* Remove the mark from the idr (if present) and drop the reference
* on the mark because it was in the idr.
*/
static void inotify_remove_from_idr(struct fsnotify_group *group,
struct inotify_inode_mark *i_mark)
{
struct idr *idr = &group->inotify_data.idr;
spinlock_t *idr_lock = &group->inotify_data.idr_lock;
struct inotify_inode_mark *found_i_mark = NULL;
int wd;
Expand Down Expand Up @@ -468,13 +454,15 @@ static void inotify_remove_from_idr(struct fsnotify_group *group,
BUG();
}

do_inotify_remove_from_idr(group, i_mark);
idr_remove(idr, wd);
/* Removed from the idr, drop that ref. */
fsnotify_put_mark(&i_mark->fsn_mark);
out:
i_mark->wd = -1;
spin_unlock(idr_lock);
/* match the ref taken by inotify_idr_find_locked() */
if (found_i_mark)
fsnotify_put_mark(&found_i_mark->fsn_mark);
i_mark->wd = -1;
spin_unlock(idr_lock);
}

/*
Expand Down

0 comments on commit e725376

Please sign in to comment.