File tree Expand file tree Collapse file tree 4 files changed +40
-0
lines changed Expand file tree Collapse file tree 4 files changed +40
-0
lines changed Original file line number Diff line number Diff line change @@ -314,6 +314,30 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
314
314
unsigned int tail = pipe -> tail ;
315
315
unsigned int mask = pipe -> ring_size - 1 ;
316
316
317
+ #ifdef CONFIG_WATCH_QUEUE
318
+ if (pipe -> note_loss ) {
319
+ struct watch_notification n ;
320
+
321
+ if (total_len < 8 ) {
322
+ if (ret == 0 )
323
+ ret = - ENOBUFS ;
324
+ break ;
325
+ }
326
+
327
+ n .type = WATCH_TYPE_META ;
328
+ n .subtype = WATCH_META_LOSS_NOTIFICATION ;
329
+ n .info = watch_sizeof (n );
330
+ if (copy_to_iter (& n , sizeof (n ), to ) != sizeof (n )) {
331
+ if (ret == 0 )
332
+ ret = - EFAULT ;
333
+ break ;
334
+ }
335
+ ret += sizeof (n );
336
+ total_len -= sizeof (n );
337
+ pipe -> note_loss = false;
338
+ }
339
+ #endif
340
+
317
341
if (!pipe_empty (head , tail )) {
318
342
struct pipe_buffer * buf = & pipe -> bufs [tail & mask ];
319
343
size_t chars = buf -> len ;
@@ -355,6 +379,10 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
355
379
if (!buf -> len ) {
356
380
pipe_buf_release (pipe , buf );
357
381
spin_lock_irq (& pipe -> rd_wait .lock );
382
+ #ifdef CONFIG_WATCH_QUEUE
383
+ if (buf -> flags & PIPE_BUF_FLAG_LOSS )
384
+ pipe -> note_loss = true;
385
+ #endif
358
386
tail ++ ;
359
387
pipe -> tail = tail ;
360
388
spin_unlock_irq (& pipe -> rd_wait .lock );
Original file line number Diff line number Diff line change 9
9
#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
10
10
#define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */
11
11
#define PIPE_BUF_FLAG_WHOLE 0x10 /* read() must return entire buffer or error */
12
+ #ifdef CONFIG_WATCH_QUEUE
13
+ #define PIPE_BUF_FLAG_LOSS 0x20 /* Message loss happened after this buffer */
14
+ #endif
12
15
13
16
/**
14
17
* struct pipe_buffer - a linux kernel pipe buffer
@@ -34,6 +37,7 @@ struct pipe_buffer {
34
37
* @wr_wait: writer wait point in case of full pipe
35
38
* @head: The point of buffer production
36
39
* @tail: The point of buffer consumption
40
+ * @note_loss: The next read() should insert a data-lost message
37
41
* @max_usage: The maximum number of slots that may be used in the ring
38
42
* @ring_size: total number of buffers (should be a power of 2)
39
43
* @nr_accounted: The amount this pipe accounts for in user->pipe_bufs
@@ -56,6 +60,9 @@ struct pipe_inode_info {
56
60
unsigned int tail ;
57
61
unsigned int max_usage ;
58
62
unsigned int ring_size ;
63
+ #ifdef CONFIG_WATCH_QUEUE
64
+ bool note_loss ;
65
+ #endif
59
66
unsigned int nr_accounted ;
60
67
unsigned int readers ;
61
68
unsigned int writers ;
Original file line number Diff line number Diff line change @@ -132,6 +132,8 @@ static bool post_one_notification(struct watch_queue *wqueue,
132
132
return done ;
133
133
134
134
lost :
135
+ buf = & pipe -> bufs [(head - 1 ) & mask ];
136
+ buf -> flags |= PIPE_BUF_FLAG_LOSS ;
135
137
goto out ;
136
138
}
137
139
Original file line number Diff line number Diff line change @@ -120,6 +120,9 @@ static void consumer(int fd)
120
120
(n .n .info & WATCH_INFO_ID ) >>
121
121
WATCH_INFO_ID__SHIFT );
122
122
break ;
123
+ case WATCH_META_LOSS_NOTIFICATION :
124
+ printf ("-- LOSS --\n" );
125
+ break ;
123
126
default :
124
127
printf ("other meta record\n" );
125
128
break ;
You can’t perform that action at this time.
0 commit comments