diff options
Diffstat (limited to 'kernel/watch_queue.c')
| -rw-r--r-- | kernel/watch_queue.c | 22 | 
1 files changed, 11 insertions, 11 deletions
diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c index 9c9eb20dd2c5..00703444a219 100644 --- a/kernel/watch_queue.c +++ b/kernel/watch_queue.c @@ -54,6 +54,7 @@ static void watch_queue_pipe_buf_release(struct pipe_inode_info *pipe,  	bit += page->index;  	set_bit(bit, wqueue->notes_bitmap); +	generic_pipe_buf_release(pipe, buf);  }  // No try_steal function => no stealing @@ -112,7 +113,7 @@ static bool post_one_notification(struct watch_queue *wqueue,  	buf->offset = offset;  	buf->len = len;  	buf->flags = PIPE_BUF_FLAG_WHOLE; -	pipe->head = head + 1; +	smp_store_release(&pipe->head, head + 1); /* vs pipe_read() */  	if (!test_and_clear_bit(note, wqueue->notes_bitmap)) {  		spin_unlock_irq(&pipe->rd_wait.lock); @@ -219,7 +220,6 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)  	struct page **pages;  	unsigned long *bitmap;  	unsigned long user_bufs; -	unsigned int bmsize;  	int ret, i, nr_pages;  	if (!wqueue) @@ -243,7 +243,8 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)  		goto error;  	} -	ret = pipe_resize_ring(pipe, nr_notes); +	nr_notes = nr_pages * WATCH_QUEUE_NOTES_PER_PAGE; +	ret = pipe_resize_ring(pipe, roundup_pow_of_two(nr_notes));  	if (ret < 0)  		goto error; @@ -258,17 +259,15 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)  		pages[i]->index = i * WATCH_QUEUE_NOTES_PER_PAGE;  	} -	bmsize = (nr_notes + BITS_PER_LONG - 1) / BITS_PER_LONG; -	bmsize *= sizeof(unsigned long); -	bitmap = kmalloc(bmsize, GFP_KERNEL); +	bitmap = bitmap_alloc(nr_notes, GFP_KERNEL);  	if (!bitmap)  		goto error_p; -	memset(bitmap, 0xff, bmsize); +	bitmap_fill(bitmap, nr_notes);  	wqueue->notes = pages;  	wqueue->notes_bitmap = bitmap;  	wqueue->nr_pages = nr_pages; -	wqueue->nr_notes = nr_pages * WATCH_QUEUE_NOTES_PER_PAGE; +	wqueue->nr_notes = nr_notes;  	return 0;  error_p: @@ -320,7 +319,7 @@ long watch_queue_set_filter(struct pipe_inode_info *pipe,  		    tf[i].info_mask & WATCH_INFO_LENGTH)  			goto err_filter;  		/* Ignore any unknown types */ -		if (tf[i].type >= sizeof(wfilter->type_filter) * 8) +		if (tf[i].type >= WATCH_TYPE__NR)  			continue;  		nr_filter++;  	} @@ -336,7 +335,7 @@ long watch_queue_set_filter(struct pipe_inode_info *pipe,  	q = wfilter->filters;  	for (i = 0; i < filter.nr_filters; i++) { -		if (tf[i].type >= sizeof(wfilter->type_filter) * BITS_PER_LONG) +		if (tf[i].type >= WATCH_TYPE__NR)  			continue;  		q->type			= tf[i].type; @@ -371,6 +370,7 @@ static void __put_watch_queue(struct kref *kref)  	for (i = 0; i < wqueue->nr_pages; i++)  		__free_page(wqueue->notes[i]); +	bitmap_free(wqueue->notes_bitmap);  	wfilter = rcu_access_pointer(wqueue->filter);  	if (wfilter) @@ -566,7 +566,7 @@ void watch_queue_clear(struct watch_queue *wqueue)  	rcu_read_lock();  	spin_lock_bh(&wqueue->lock); -	/* Prevent new additions and prevent notifications from happening */ +	/* Prevent new notifications from being stored. */  	wqueue->defunct = true;  	while (!hlist_empty(&wqueue->watches)) {  |