@@ -1980,6 +1980,11 @@ static inline struct inet_timewait_sock *tw_next(struct inet_timewait_sock *tw)
1980
1980
hlist_nulls_entry (tw -> tw_node .next , typeof (* tw ), tw_node ) : NULL ;
1981
1981
}
1982
1982
1983
+ /*
1984
+ * Get next listener socket follow cur. If cur is NULL, get first socket
1985
+ * starting from bucket given in st->bucket; when st->bucket is zero the
1986
+ * very first socket in the hash table is returned.
1987
+ */
1983
1988
static void * listening_get_next (struct seq_file * seq , void * cur )
1984
1989
{
1985
1990
struct inet_connection_sock * icsk ;
@@ -1990,14 +1995,15 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
1990
1995
struct net * net = seq_file_net (seq );
1991
1996
1992
1997
if (!sk ) {
1993
- st -> bucket = 0 ;
1994
- ilb = & tcp_hashinfo .listening_hash [0 ];
1998
+ ilb = & tcp_hashinfo .listening_hash [st -> bucket ];
1995
1999
spin_lock_bh (& ilb -> lock );
1996
2000
sk = sk_nulls_head (& ilb -> head );
2001
+ st -> offset = 0 ;
1997
2002
goto get_sk ;
1998
2003
}
1999
2004
ilb = & tcp_hashinfo .listening_hash [st -> bucket ];
2000
2005
++ st -> num ;
2006
+ ++ st -> offset ;
2001
2007
2002
2008
if (st -> state == TCP_SEQ_STATE_OPENREQ ) {
2003
2009
struct request_sock * req = cur ;
@@ -2012,6 +2018,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
2012
2018
}
2013
2019
req = req -> dl_next ;
2014
2020
}
2021
+ st -> offset = 0 ;
2015
2022
if (++ st -> sbucket >= icsk -> icsk_accept_queue .listen_opt -> nr_table_entries )
2016
2023
break ;
2017
2024
get_req :
@@ -2047,6 +2054,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
2047
2054
read_unlock_bh (& icsk -> icsk_accept_queue .syn_wait_lock );
2048
2055
}
2049
2056
spin_unlock_bh (& ilb -> lock );
2057
+ st -> offset = 0 ;
2050
2058
if (++ st -> bucket < INET_LHTABLE_SIZE ) {
2051
2059
ilb = & tcp_hashinfo .listening_hash [st -> bucket ];
2052
2060
spin_lock_bh (& ilb -> lock );
@@ -2060,7 +2068,12 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
2060
2068
2061
2069
static void * listening_get_idx (struct seq_file * seq , loff_t * pos )
2062
2070
{
2063
- void * rc = listening_get_next (seq , NULL );
2071
+ struct tcp_iter_state * st = seq -> private ;
2072
+ void * rc ;
2073
+
2074
+ st -> bucket = 0 ;
2075
+ st -> offset = 0 ;
2076
+ rc = listening_get_next (seq , NULL );
2064
2077
2065
2078
while (rc && * pos ) {
2066
2079
rc = listening_get_next (seq , rc );
@@ -2075,13 +2088,18 @@ static inline int empty_bucket(struct tcp_iter_state *st)
2075
2088
hlist_nulls_empty (& tcp_hashinfo .ehash [st -> bucket ].twchain );
2076
2089
}
2077
2090
2091
+ /*
2092
+ * Get first established socket starting from bucket given in st->bucket.
2093
+ * If st->bucket is zero, the very first socket in the hash is returned.
2094
+ */
2078
2095
static void * established_get_first (struct seq_file * seq )
2079
2096
{
2080
2097
struct tcp_iter_state * st = seq -> private ;
2081
2098
struct net * net = seq_file_net (seq );
2082
2099
void * rc = NULL ;
2083
2100
2084
- for (st -> bucket = 0 ; st -> bucket <= tcp_hashinfo .ehash_mask ; ++ st -> bucket ) {
2101
+ st -> offset = 0 ;
2102
+ for (; st -> bucket <= tcp_hashinfo .ehash_mask ; ++ st -> bucket ) {
2085
2103
struct sock * sk ;
2086
2104
struct hlist_nulls_node * node ;
2087
2105
struct inet_timewait_sock * tw ;
@@ -2126,6 +2144,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
2126
2144
struct net * net = seq_file_net (seq );
2127
2145
2128
2146
++ st -> num ;
2147
+ ++ st -> offset ;
2129
2148
2130
2149
if (st -> state == TCP_SEQ_STATE_TIME_WAIT ) {
2131
2150
tw = cur ;
@@ -2142,6 +2161,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
2142
2161
st -> state = TCP_SEQ_STATE_ESTABLISHED ;
2143
2162
2144
2163
/* Look for next non empty bucket */
2164
+ st -> offset = 0 ;
2145
2165
while (++ st -> bucket <= tcp_hashinfo .ehash_mask &&
2146
2166
empty_bucket (st ))
2147
2167
;
@@ -2169,7 +2189,11 @@ static void *established_get_next(struct seq_file *seq, void *cur)
2169
2189
2170
2190
static void * established_get_idx (struct seq_file * seq , loff_t pos )
2171
2191
{
2172
- void * rc = established_get_first (seq );
2192
+ struct tcp_iter_state * st = seq -> private ;
2193
+ void * rc ;
2194
+
2195
+ st -> bucket = 0 ;
2196
+ rc = established_get_first (seq );
2173
2197
2174
2198
while (rc && pos ) {
2175
2199
rc = established_get_next (seq , rc );
@@ -2194,31 +2218,81 @@ static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
2194
2218
return rc ;
2195
2219
}
2196
2220
2221
+ static void * tcp_seek_last_pos (struct seq_file * seq )
2222
+ {
2223
+ struct tcp_iter_state * st = seq -> private ;
2224
+ int offset = st -> offset ;
2225
+ int orig_num = st -> num ;
2226
+ void * rc = NULL ;
2227
+
2228
+ switch (st -> state ) {
2229
+ case TCP_SEQ_STATE_OPENREQ :
2230
+ case TCP_SEQ_STATE_LISTENING :
2231
+ if (st -> bucket >= INET_LHTABLE_SIZE )
2232
+ break ;
2233
+ st -> state = TCP_SEQ_STATE_LISTENING ;
2234
+ rc = listening_get_next (seq , NULL );
2235
+ while (offset -- && rc )
2236
+ rc = listening_get_next (seq , rc );
2237
+ if (rc )
2238
+ break ;
2239
+ st -> bucket = 0 ;
2240
+ /* Fallthrough */
2241
+ case TCP_SEQ_STATE_ESTABLISHED :
2242
+ case TCP_SEQ_STATE_TIME_WAIT :
2243
+ st -> state = TCP_SEQ_STATE_ESTABLISHED ;
2244
+ if (st -> bucket > tcp_hashinfo .ehash_mask )
2245
+ break ;
2246
+ rc = established_get_first (seq );
2247
+ while (offset -- && rc )
2248
+ rc = established_get_next (seq , rc );
2249
+ }
2250
+
2251
+ st -> num = orig_num ;
2252
+
2253
+ return rc ;
2254
+ }
2255
+
2197
2256
static void * tcp_seq_start (struct seq_file * seq , loff_t * pos )
2198
2257
{
2199
2258
struct tcp_iter_state * st = seq -> private ;
2259
+ void * rc ;
2260
+
2261
+ if (* pos && * pos == st -> last_pos ) {
2262
+ rc = tcp_seek_last_pos (seq );
2263
+ if (rc )
2264
+ goto out ;
2265
+ }
2266
+
2200
2267
st -> state = TCP_SEQ_STATE_LISTENING ;
2201
2268
st -> num = 0 ;
2202
- return * pos ? tcp_get_idx (seq , * pos - 1 ) : SEQ_START_TOKEN ;
2269
+ st -> bucket = 0 ;
2270
+ st -> offset = 0 ;
2271
+ rc = * pos ? tcp_get_idx (seq , * pos - 1 ) : SEQ_START_TOKEN ;
2272
+
2273
+ out :
2274
+ st -> last_pos = * pos ;
2275
+ return rc ;
2203
2276
}
2204
2277
2205
2278
static void * tcp_seq_next (struct seq_file * seq , void * v , loff_t * pos )
2206
2279
{
2280
+ struct tcp_iter_state * st = seq -> private ;
2207
2281
void * rc = NULL ;
2208
- struct tcp_iter_state * st ;
2209
2282
2210
2283
if (v == SEQ_START_TOKEN ) {
2211
2284
rc = tcp_get_idx (seq , 0 );
2212
2285
goto out ;
2213
2286
}
2214
- st = seq -> private ;
2215
2287
2216
2288
switch (st -> state ) {
2217
2289
case TCP_SEQ_STATE_OPENREQ :
2218
2290
case TCP_SEQ_STATE_LISTENING :
2219
2291
rc = listening_get_next (seq , v );
2220
2292
if (!rc ) {
2221
2293
st -> state = TCP_SEQ_STATE_ESTABLISHED ;
2294
+ st -> bucket = 0 ;
2295
+ st -> offset = 0 ;
2222
2296
rc = established_get_first (seq );
2223
2297
}
2224
2298
break ;
@@ -2229,6 +2303,7 @@ static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2229
2303
}
2230
2304
out :
2231
2305
++ * pos ;
2306
+ st -> last_pos = * pos ;
2232
2307
return rc ;
2233
2308
}
2234
2309
@@ -2267,6 +2342,7 @@ static int tcp_seq_open(struct inode *inode, struct file *file)
2267
2342
2268
2343
s = ((struct seq_file * )file -> private_data )-> private ;
2269
2344
s -> family = afinfo -> family ;
2345
+ s -> last_pos = 0 ;
2270
2346
return 0 ;
2271
2347
}
2272
2348
0 commit comments