Conflicts: include/linux/blkdev.h Trivial merge to incorporate tag prototypes.
Unified · Split
| @@ -2384,6 +2384,13 @@ N: Thomas Molina · 2383 unmodified lines | ||
| 2384 | 2384 | E: tmolina@cablespeed.com |
| 2385 | 2385 | D: bug fixes, documentation, minor hackery |
| 2386 | 2386 | |
| 2387 | +N: Paul Moore | |
| 2388 | +E: paul.moore@hp.com | |
| 2389 | +D: NetLabel author | |
| 2390 | +S: Hewlett-Packard | |
| 2391 | +S: 110 Spit Brook Road | |
| 2392 | +S: Nashua, NH 03062 | |
| 2393 | + | |
| 2387 | 2394 | N: James Morris |
| 2388 | 2395 | E: jmorris@namei.org |
| 2389 | 2396 | W: http://namei.org/ |
| @@ -184,6 +184,8 @@ mtrr.txt · 183 unmodified lines | ||
| 184 | 184 | - how to use PPro Memory Type Range Registers to increase performance. |
| 185 | 185 | nbd.txt |
| 186 | 186 | - info on a TCP implementation of a network block device. |
| 187 | +netlabel/ | |
| 188 | + - directory with information on the NetLabel subsystem. | |
| 187 | 189 | networking/ |
| 188 | 190 | - directory with info on various aspects of networking with Linux. |
| 189 | 191 | nfsroot.txt |
| @@ -0,0 +1,10 @@ | ||
| 1 | +00-INDEX | |
| 2 | + - this file. | |
| 3 | +cipso_ipv4.txt | |
| 4 | + - documentation on the IPv4 CIPSO protocol engine. | |
| 5 | +draft-ietf-cipso-ipsecurity-01.txt | |
| 6 | + - IETF draft of the CIPSO protocol, dated 16 July 1992. | |
| 7 | +introduction.txt | |
| 8 | + - NetLabel introduction, READ THIS FIRST. | |
| 9 | +lsm_interface.txt | |
| 10 | + - documentation on the NetLabel kernel security module API. | |
| @@ -0,0 +1,48 @@ | ||
| 1 | +NetLabel CIPSO/IPv4 Protocol Engine | |
| 2 | +============================================================================== | |
| 3 | +Paul Moore, paul.moore@hp.com | |
| 4 | + | |
| 5 | +May 17, 2006 | |
| 6 | + | |
| 7 | + * Overview | |
| 8 | + | |
| 9 | +The NetLabel CIPSO/IPv4 protocol engine is based on the IETF Commercial IP | |
| 10 | +Security Option (CIPSO) draft from July 16, 1992. A copy of this draft can be | |
| 11 | +found in this directory, consult '00-INDEX' for the filename. While the IETF | |
| 12 | +draft never made it to an RFC standard it has become a de-facto standard for | |
| 13 | +labeled networking and is used in many trusted operating systems. | |
| 14 | + | |
| 15 | + * Outbound Packet Processing | |
| 16 | + | |
| 17 | +The CIPSO/IPv4 protocol engine applies the CIPSO IP option to packets by | |
| 18 | +adding the CIPSO label to the socket. This causes all packets leaving the | |
| 19 | +system through the socket to have the CIPSO IP option applied. The socket's | |
| 20 | +CIPSO label can be changed at any point in time, however, it is recommended | |
| 21 | +that it is set upon the socket's creation. The LSM can set the socket's CIPSO | |
| 22 | +label by using the NetLabel security module API; if the NetLabel "domain" is | |
| 23 | +configured to use CIPSO for packet labeling then a CIPSO IP option will be | |
| 24 | +generated and attached to the socket. | |
| 25 | + | |
| 26 | + * Inbound Packet Processing | |
| 27 | + | |
| 28 | +The CIPSO/IPv4 protocol engine validates every CIPSO IP option it finds at the | |
| 29 | +IP layer without any special handling required by the LSM. However, in order | |
| 30 | +to decode and translate the CIPSO label on the packet the LSM must use the | |
| 31 | +NetLabel security module API to extract the security attributes of the packet. | |
| 32 | +This is typically done at the socket layer using the 'socket_sock_rcv_skb()' | |
| 33 | +LSM hook. | |
| 34 | + | |
| 35 | + * Label Translation | |
| 36 | + | |
| 37 | +The CIPSO/IPv4 protocol engine contains a mechanism to translate CIPSO security | |
| 38 | +attributes such as sensitivity level and category to values which are | |
| 39 | +appropriate for the host. These mappings are defined as part of a CIPSO | |
| 40 | +Domain Of Interpretation (DOI) definition and are configured through the | |
| 41 | +NetLabel user space communication layer. Each DOI definition can have a | |
| 42 | +different security attribute mapping table. | |
| 43 | + | |
| 44 | + * Label Translation Cache | |
| 45 | + | |
| 46 | +The NetLabel system provides a framework for caching security attribute | |
| 47 | +mappings from the network labels to the corresponding LSM identifiers. The | |
| 48 | +CIPSO/IPv4 protocol engine supports this caching mechanism. | |
| @@ -0,0 +1,791 @@ | ||
| 1 | +IETF CIPSO Working Group | |
| 2 | +16 July, 1992 | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | +1. Status | |
| 11 | + | |
| 12 | +This Internet Draft provides the high level specification for a Commercial | |
| 13 | +IP Security Option (CIPSO). This draft reflects the version as approved by | |
| 14 | +the CIPSO IETF Working Group. Distribution of this memo is unlimited. | |
| 15 | + | |
| 16 | +This document is an Internet Draft. Internet Drafts are working documents | |
| 17 | +of the Internet Engineering Task Force (IETF), its Areas, and its Working | |
| 18 | +Groups. Note that other groups may also distribute working documents as | |
| 19 | +Internet Drafts. | |
| 20 | + | |
| 21 | +Internet Drafts are draft documents valid for a maximum of six months. | |
| 22 | +Internet Drafts may be updated, replaced, or obsoleted by other documents | |
| 23 | +at any time. It is not appropriate to use Internet Drafts as reference | |
| 24 | +material or to cite them other than as a "working draft" or "work in | |
| 25 | +progress." | |
| 26 | + | |
| 27 | +Please check the I-D abstract listing contained in each Internet Draft | |
| 28 | +directory to learn the current status of this or any other Internet Draft. | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | +2. Background | |
| 34 | + | |
| 35 | +Currently the Internet Protocol includes two security options. One of | |
| 36 | +these options is the DoD Basic Security Option (BSO) (Type 130) which allows | |
| 37 | +IP datagrams to be labeled with security classifications. This option | |
| 38 | +provides sixteen security classifications and a variable number of handling | |
| 39 | +restrictions. To handle additional security information, such as security | |
| 40 | +categories or compartments, another security option (Type 133) exists and | |
| 41 | +is referred to as the DoD Extended Security Option (ESO). The values for | |
| 42 | +the fixed fields within these two options are administered by the Defense | |
| 43 | +Information Systems Agency (DISA). | |
| 44 | + | |
| 45 | +Computer vendors are now building commercial operating systems with | |
| 46 | +mandatory access controls and multi-level security. These systems are | |
| 47 | +no longer built specifically for a particular group in the defense or | |
| 48 | +intelligence communities. They are generally available commercial systems | |
| 49 | +for use in a variety of government and civil sector environments. | |
| 50 | + | |
| 51 | +The small number of ESO format codes can not support all the possible | |
| 52 | +applications of a commercial security option. The BSO and ESO were | |
| 53 | +designed to only support the United States DoD. CIPSO has been designed | |
| 54 | +to support multiple security policies. This Internet Draft provides the | |
| 55 | +format and procedures required to support a Mandatory Access Control | |
| 56 | +security policy. Support for additional security policies shall be | |
| 57 | +defined in future RFCs. | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | +Internet Draft, Expires 15 Jan 93 [PAGE 1] | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | +3. CIPSO Format | |
| 72 | + | |
| 73 | +Option type: 134 (Class 0, Number 6, Copy on Fragmentation) | |
| 74 | +Option length: Variable | |
| 75 | + | |
| 76 | +This option permits security related information to be passed between | |
| 77 | +systems within a single Domain of Interpretation (DOI). A DOI is a | |
| 78 | +collection of systems which agree on the meaning of particular values | |
| 79 | +in the security option. An authority that has been assigned a DOI | |
| 80 | +identifier will define a mapping between appropriate CIPSO field values | |
| 81 | +and their human readable equivalent. This authority will distribute that | |
| 82 | +mapping to hosts within the authority's domain. These mappings may be | |
| 83 | +sensitive, therefore a DOI authority is not required to make these | |
| 84 | +mappings available to anyone other than the systems that are included in | |
| 85 | +the DOI. | |
| 86 | + | |
| 87 | +This option MUST be copied on fragmentation. This option appears at most | |
| 88 | +once in a datagram. All multi-octet fields in the option are defined to be | |
| 89 | +transmitted in network byte order. The format of this option is as follows: | |
| 90 | + | |
| 91 | ++----------+----------+------//------+-----------//---------+ | |
| 92 | +| 10000110 | LLLLLLLL | DDDDDDDDDDDD | TTTTTTTTTTTTTTTTTTTT | | |
| 93 | ++----------+----------+------//------+-----------//---------+ | |
| 94 | + | |
| 95 | + TYPE=134 OPTION DOMAIN OF TAGS | |
| 96 | + LENGTH INTERPRETATION | |
| 97 | + | |
| 98 | + | |
| 99 | + Figure 1. CIPSO Format | |
| 100 | + | |
| 101 | + | |
| 102 | +3.1 Type | |
| 103 | + | |
| 104 | +This field is 1 octet in length. Its value is 134. | |
| 105 | + | |
| 106 | + | |
| 107 | +3.2 Length | |
| 108 | + | |
| 109 | +This field is 1 octet in length. It is the total length of the option | |
| 110 | +including the type and length fields. With the current IP header length | |
| 111 | +restriction of 40 octets the value of this field MUST not exceed 40. | |
| 112 | + | |
| 113 | + | |
| 114 | +3.3 Domain of Interpretation Identifier | |
| 115 | + | |
| 116 | +This field is an unsigned 32 bit integer. The value 0 is reserved and MUST | |
| 117 | +not appear as the DOI identifier in any CIPSO option. Implementations | |
| 118 | +should assume that the DOI identifier field is not aligned on any particular | |
| 119 | +byte boundary. | |
| 120 | + | |
| 121 | +To conserve space in the protocol, security levels and categories are | |
| 122 | +represented by numbers rather than their ASCII equivalent. This requires | |
| 123 | +a mapping table within CIPSO hosts to map these numbers to their | |
| 124 | +corresponding ASCII representations. Non-related groups of systems may | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | +Internet Draft, Expires 15 Jan 93 [PAGE 2] | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | +have their own unique mappings. For example, one group of systems may | |
| 137 | +use the number 5 to represent Unclassified while another group may use the | |
| 138 | +number 1 to represent that same security level. The DOI identifier is used | |
| 139 | +to identify which mapping was used for the values within the option. | |
| 140 | + | |
| 141 | + | |
| 142 | +3.4 Tag Types | |
| 143 | + | |
| 144 | +A common format for passing security related information is necessary | |
| 145 | +for interoperability. CIPSO uses sets of "tags" to contain the security | |
| 146 | +information relevant to the data in the IP packet. Each tag begins with | |
| 147 | +a tag type identifier followed by the length of the tag and ends with the | |
| 148 | +actual security information to be passed. All multi-octet fields in a tag | |
| 149 | +are defined to be transmitted in network byte order. Like the DOI | |
| 150 | +identifier field in the CIPSO header, implementations should assume that | |
| 151 | +all tags, as well as fields within a tag, are not aligned on any particular | |
| 152 | +octet boundary. The tag types defined in this document contain alignment | |
| 153 | +bytes to assist alignment of some information, however alignment can not | |
| 154 | +be guaranteed if CIPSO is not the first IP option. | |
| 155 | + | |
| 156 | +CIPSO tag types 0 through 127 are reserved for defining standard tag | |
| 157 | +formats. Their definitions will be published in RFCs. Tag types whose | |
| 158 | +identifiers are greater than 127 are defined by the DOI authority and may | |
| 159 | +only be meaningful in certain Domains of Interpretation. For these tag | |
| 160 | +types, implementations will require the DOI identifier as well as the tag | |
| 161 | +number to determine the security policy and the format associated with the | |
| 162 | +tag. Use of tag types above 127 are restricted to closed networks where | |
| 163 | +interoperability with other networks will not be an issue. Implementations | |
| 164 | +that support a tag type greater than 127 MUST support at least one DOI that | |
| 165 | +requires only tag types 1 to 127. | |
| 166 | + | |
| 167 | +Tag type 0 is reserved. Tag types 1, 2, and 5 are defined in this | |
| 168 | +Internet Draft. Types 3 and 4 are reserved for work in progress. | |
| 169 | +The standard format for all current and future CIPSO tags is shown below: | |
| 170 | + | |
| 171 | ++----------+----------+--------//--------+ | |
| 172 | +| TTTTTTTT | LLLLLLLL | IIIIIIIIIIIIIIII | | |
| 173 | ++----------+----------+--------//--------+ | |
| 174 | + TAG TAG TAG | |
| 175 | + TYPE LENGTH INFORMATION | |
| 176 | + | |
| 177 | + Figure 2: Standard Tag Format | |
| 178 | + | |
| 179 | +In the three tag types described in this document, the length and count | |
| 180 | +restrictions are based on the current IP limitation of 40 octets for all | |
| 181 | +IP options. If the IP header is later expanded, then the length and count | |
| 182 | +restrictions specified in this document may increase to use the full area | |
| 183 | +provided for IP options. | |
| 184 | + | |
| 185 | + | |
| 186 | +3.4.1 Tag Type Classes | |
| 187 | + | |
| 188 | +Tag classes consist of tag types that have common processing requirements | |
| 189 | +and support the same security policy. The three tags defined in this | |
| 190 | +Internet Draft belong to the Mandatory Access Control (MAC) Sensitivity | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | +Internet Draft, Expires 15 Jan 93 [PAGE 3] | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | +class and support the MAC Sensitivity security policy. | |
| 203 | + | |
| 204 | + | |
| 205 | +3.4.2 Tag Type 1 | |
| 206 | + | |
| 207 | +This is referred to as the "bit-mapped" tag type. Tag type 1 is included | |
| 208 | +in the MAC Sensitivity tag type class. The format of this tag type is as | |
| 209 | +follows: | |
| 210 | + | |
| 211 | ++----------+----------+----------+----------+--------//---------+ | |
| 212 | +| 00000001 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCC | | |
| 213 | ++----------+----------+----------+----------+--------//---------+ | |
| 214 | + | |
| 215 | + TAG TAG ALIGNMENT SENSITIVITY BIT MAP OF | |
| 216 | + TYPE LENGTH OCTET LEVEL CATEGORIES | |
| 217 | + | |
| 218 | + Figure 3. Tag Type 1 Format | |
| 219 | + | |
| 220 | + | |
| 221 | +3.4.2.1 Tag Type | |
| 222 | + | |
| 223 | +This field is 1 octet in length and has a value of 1. | |
| 224 | + | |
| 225 | + | |
| 226 | +3.4.2.2 Tag Length | |
| 227 | + | |
| 228 | +This field is 1 octet in length. It is the total length of the tag type | |
| 229 | +including the type and length fields. With the current IP header length | |
| 230 | +restriction of 40 bytes the value within this field is between 4 and 34. | |
| 231 | + | |
| 232 | + | |
| 233 | +3.4.2.3 Alignment Octet | |
| 234 | + | |
| 235 | +This field is 1 octet in length and always has the value of 0. Its purpose | |
| 236 | +is to align the category bitmap field on an even octet boundary. This will | |
| 237 | +speed many implementations including router implementations. | |
| 238 | + | |
| 239 | + | |
| 240 | +3.4.2.4 Sensitivity Level | |
| 241 | + | |
| 242 | +This field is 1 octet in length. Its value is from 0 to 255. The values | |
| 243 | +are ordered with 0 being the minimum value and 255 representing the maximum | |
| 244 | +value. | |
| 245 | + | |
| 246 | + | |
| 247 | +3.4.2.5 Bit Map of Categories | |
| 248 | + | |
| 249 | +The length of this field is variable and ranges from 0 to 30 octets. This | |
| 250 | +provides representation of categories 0 to 239. The ordering of the bits | |
| 251 | +is left to right or MSB to LSB. For example category 0 is represented by | |
| 252 | +the most significant bit of the first byte and category 15 is represented | |
| 253 | +by the least significant bit of the second byte. Figure 4 graphically | |
| 254 | +shows this ordering. Bit N is binary 1 if category N is part of the label | |
| 255 | +for the datagram, and bit N is binary 0 if category N is not part of the | |
| 256 | +label. Except for the optimized tag 1 format described in the next section, | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | +Internet Draft, Expires 15 Jan 93 [PAGE 4] | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | +minimal encoding SHOULD be used resulting in no trailing zero octets in the | |
| 269 | +category bitmap. | |
| 270 | + | |
| 271 | + octet 0 octet 1 octet 2 octet 3 octet 4 octet 5 | |
| 272 | + XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX . . . | |
| 273 | +bit 01234567 89111111 11112222 22222233 33333333 44444444 | |
| 274 | +number 012345 67890123 45678901 23456789 01234567 | |
| 275 | + | |
| 276 | + Figure 4. Ordering of Bits in Tag 1 Bit Map | |
| 277 | + | |
| 278 | + | |
| 279 | +3.4.2.6 Optimized Tag 1 Format | |
| 280 | + | |
| 281 | +Routers work most efficiently when processing fixed length fields. To | |
| 282 | +support these routers there is an optimized form of tag type 1. The format | |
| 283 | +does not change. The only change is to the category bitmap which is set to | |
| 284 | +a constant length of 10 octets. Trailing octets required to fill out the 10 | |
| 285 | +octets are zero filled. Ten octets, allowing for 80 categories, was chosen | |
| 286 | +because it makes the total length of the CIPSO option 20 octets. If CIPSO | |
| 287 | +is the only option then the option will be full word aligned and additional | |
| 288 | +filler octets will not be required. | |
| 289 | + | |
| 290 | + | |
| 291 | +3.4.3 Tag Type 2 | |
| 292 | + | |
| 293 | +This is referred to as the "enumerated" tag type. It is used to describe | |
| 294 | +large but sparsely populated sets of categories. Tag type 2 is in the MAC | |
| 295 | +Sensitivity tag type class. The format of this tag type is as follows: | |
| 296 | + | |
| 297 | ++----------+----------+----------+----------+-------------//-------------+ | |
| 298 | +| 00000010 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCCCCCCCCCCC | | |
| 299 | ++----------+----------+----------+----------+-------------//-------------+ | |
| 300 | + | |
| 301 | + TAG TAG ALIGNMENT SENSITIVITY ENUMERATED | |
| 302 | + TYPE LENGTH OCTET LEVEL CATEGORIES | |
| 303 | + | |
| 304 | + Figure 5. Tag Type 2 Format | |
| 305 | + | |
| 306 | + | |
| 307 | +3.4.3.1 Tag Type | |
| 308 | + | |
| 309 | +This field is one octet in length and has a value of 2. | |
| 310 | + | |
| 311 | + | |
| 312 | +3.4.3.2 Tag Length | |
| 313 | + | |
| 314 | +This field is 1 octet in length. It is the total length of the tag type | |
| 315 | +including the type and length fields. With the current IP header length | |
| 316 | +restriction of 40 bytes the value within this field is between 4 and 34. | |
| 317 | + | |
| 318 | + | |
| 319 | +3.4.3.3 Alignment Octet | |
| 320 | + | |
| 321 | +This field is 1 octet in length and always has the value of 0. Its purpose | |
| 322 | +is to align the category field on an even octet boundary. This will | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | +Internet Draft, Expires 15 Jan 93 [PAGE 5] | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | +speed many implementations including router implementations. | |
| 335 | + | |
| 336 | + | |
| 337 | +3.4.3.4 Sensitivity Level | |
| 338 | + | |
| 339 | +This field is 1 octet in length. Its value is from 0 to 255. The values | |
| 340 | +are ordered with 0 being the minimum value and 255 representing the | |
| 341 | +maximum value. | |
| 342 | + | |
| 343 | + | |
| 344 | +3.4.3.5 Enumerated Categories | |
| 345 | + | |
| 346 | +In this tag, categories are represented by their actual value rather than | |
| 347 | +by their position within a bit field. The length of each category is 2 | |
| 348 | +octets. Up to 15 categories may be represented by this tag. Valid values | |
| 349 | +for categories are 0 to 65534. Category 65535 is not a valid category | |
| 350 | +value. The categories MUST be listed in ascending order within the tag. | |
| 351 | + | |
| 352 | + | |
| 353 | +3.4.4 Tag Type 5 | |
| 354 | + | |
| 355 | +This is referred to as the "range" tag type. It is used to represent | |
| 356 | +labels where all categories in a range, or set of ranges, are included | |
| 357 | +in the sensitivity label. Tag type 5 is in the MAC Sensitivity tag type | |
| 358 | +class. The format of this tag type is as follows: | |
| 359 | + | |
| 360 | ++----------+----------+----------+----------+------------//-------------+ | |
| 361 | +| 00000101 | LLLLLLLL | 00000000 | LLLLLLLL | Top/Bottom | Top/Bottom | | |
| 362 | ++----------+----------+----------+----------+------------//-------------+ | |
| 363 | + | |
| 364 | + TAG TAG ALIGNMENT SENSITIVITY CATEGORY RANGES | |
| 365 | + TYPE LENGTH OCTET LEVEL | |
| 366 | + | |
| 367 | + Figure 6. Tag Type 5 Format | |
| 368 | + | |
| 369 | + | |
| 370 | +3.4.4.1 Tag Type | |
| 371 | + | |
| 372 | +This field is one octet in length and has a value of 5. | |
| 373 | + | |
| 374 | + | |
| 375 | +3.4.4.2 Tag Length | |
| 376 | + | |
| 377 | +This field is 1 octet in length. It is the total length of the tag type | |
| 378 | +including the type and length fields. With the current IP header length | |
| 379 | +restriction of 40 bytes the value within this field is between 4 and 34. | |
| 380 | + | |
| 381 | + | |
| 382 | +3.4.4.3 Alignment Octet | |
| 383 | + | |
| 384 | +This field is 1 octet in length and always has the value of 0. Its purpose | |
| 385 | +is to align the category range field on an even octet boundary. This will | |
| 386 | +speed many implementations including router implementations. | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | +Internet Draft, Expires 15 Jan 93 [PAGE 6] | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | +3.4.4.4 Sensitivity Level | |
| 401 | + | |
| 402 | +This field is 1 octet in length. Its value is from 0 to 255. The values | |
| 403 | +are ordered with 0 being the minimum value and 255 representing the maximum | |
| 404 | +value. | |
| 405 | + | |
| 406 | + | |
| 407 | +3.4.4.5 Category Ranges | |
| 408 | + | |
| 409 | +A category range is a 4 octet field comprised of the 2 octet index of the | |
| 410 | +highest numbered category followed by the 2 octet index of the lowest | |
| 411 | +numbered category. These range endpoints are inclusive within the range of | |
| 412 | +categories. All categories within a range are included in the sensitivity | |
| 413 | +label. This tag may contain a maximum of 7 category pairs. The bottom | |
| 414 | +category endpoint for the last pair in the tag MAY be omitted and SHOULD be | |
| 415 | +assumed to be 0. The ranges MUST be non-overlapping and be listed in | |
| 416 | +descending order. Valid values for categories are 0 to 65534. Category | |
| 417 | +65535 is not a valid category value. | |
| 418 | + | |
| 419 | + | |
| 420 | +3.4.5 Minimum Requirements | |
| 421 | + | |
| 422 | +A CIPSO implementation MUST be capable of generating at least tag type 1 in | |
| 423 | +the non-optimized form. In addition, a CIPSO implementation MUST be able | |
| 424 | +to receive any valid tag type 1 even those using the optimized tag type 1 | |
| 425 | +format. | |
| 426 | + | |
| 427 | + | |
| 428 | +4. Configuration Parameters | |
| 429 | + | |
| 430 | +The configuration parameters defined below are required for all CIPSO hosts, | |
| 431 | +gateways, and routers that support multiple sensitivity labels. A CIPSO | |
| 432 | +host is defined to be the origination or destination system for an IP | |
| 433 | +datagram. A CIPSO gateway provides IP routing services between two or more | |
| 434 | +IP networks and may be required to perform label translations between | |
| 435 | +networks. A CIPSO gateway may be an enhanced CIPSO host or it may just | |
| 436 | +provide gateway services with no end system CIPSO capabilities. A CIPSO | |
| 437 | +router is a dedicated IP router that routes IP datagrams between two or more | |
| 438 | +IP networks. | |
| 439 | + | |
| 440 | +An implementation of CIPSO on a host MUST have the capability to reject a | |
| 441 | +datagram for reasons that the information contained can not be adequately | |
| 442 | +protected by the receiving host or if acceptance may result in violation of | |
| 443 | +the host or network security policy. In addition, a CIPSO gateway or router | |
| 444 | +MUST be able to reject datagrams going to networks that can not provide | |
| 445 | +adequate protection or may violate the network's security policy. To | |
| 446 | +provide this capability the following minimal set of configuration | |
| 447 | +parameters are required for CIPSO implementations: | |
| 448 | + | |
| 449 | +HOST_LABEL_MAX - This parameter contains the maximum sensitivity label that | |
| 450 | +a CIPSO host is authorized to handle. All datagrams that have a label | |
| 451 | +greater than this maximum MUST be rejected by the CIPSO host. This | |
| 452 | +parameter does not apply to CIPSO gateways or routers. This parameter need | |
| 453 | +not be defined explicitly as it can be implicitly derived from the | |
| 454 | +PORT_LABEL_MAX parameters for the associated interfaces. | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | +Internet Draft, Expires 15 Jan 93 [PAGE 7] | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | +HOST_LABEL_MIN - This parameter contains the minimum sensitivity label that | |
| 468 | +a CIPSO host is authorized to handle. All datagrams that have a label less | |
| 469 | +than this minimum MUST be rejected by the CIPSO host. This parameter does | |
| 470 | +not apply to CIPSO gateways or routers. This parameter need not be defined | |
| 471 | +explicitly as it can be implicitly derived from the PORT_LABEL_MIN | |
| 472 | +parameters for the associated interfaces. | |
| 473 | + | |
| 474 | +PORT_LABEL_MAX - This parameter contains the maximum sensitivity label for | |
| 475 | +all datagrams that may exit a particular network interface port. All | |
| 476 | +outgoing datagrams that have a label greater than this maximum MUST be | |
| 477 | +rejected by the CIPSO system. The label within this parameter MUST be | |
| 478 | +less than or equal to the label within the HOST_LABEL_MAX parameter. This | |
| 479 | +parameter does not apply to CIPSO hosts that support only one network port. | |
| 480 | + | |
| 481 | +PORT_LABEL_MIN - This parameter contains the minimum sensitivity label for | |
| 482 | +all datagrams that may exit a particular network interface port. All | |
| 483 | +outgoing datagrams that have a label less than this minimum MUST be | |
| 484 | +rejected by the CIPSO system. The label within this parameter MUST be | |
| 485 | +greater than or equal to the label within the HOST_LABEL_MIN parameter. | |
| 486 | +This parameter does not apply to CIPSO hosts that support only one network | |
| 487 | +port. | |
| 488 | + | |
| 489 | +PORT_DOI - This parameter is used to assign a DOI identifier value to a | |
| 490 | +particular network interface port. All CIPSO labels within datagrams | |
| 491 | +going out this port MUST use the specified DOI identifier. All CIPSO | |
| 492 | +hosts and gateways MUST support either this parameter, the NET_DOI | |
| 493 | +parameter, or the HOST_DOI parameter. | |
| 494 | + | |
| 495 | +NET_DOI - This parameter is used to assign a DOI identifier value to a | |
| 496 | +particular IP network address. All CIPSO labels within datagrams destined | |
| 497 | +for the particular IP network MUST use the specified DOI identifier. All | |
| 498 | +CIPSO hosts and gateways MUST support either this parameter, the PORT_DOI | |
| 499 | +parameter, or the HOST_DOI parameter. | |
| 500 | + | |
| 501 | +HOST_DOI - This parameter is used to assign a DOI identifier value to a | |
| 502 | +particular IP host address. All CIPSO labels within datagrams destined for | |
| 503 | +the particular IP host will use the specified DOI identifier. All CIPSO | |
| 504 | +hosts and gateways MUST support either this parameter, the PORT_DOI | |
| 505 | +parameter, or the NET_DOI parameter. | |
| 506 | + | |
| 507 | +This list represents the minimal set of configuration parameters required | |
| 508 | +to be compliant. Implementors are encouraged to add to this list to | |
| 509 | +provide enhanced functionality and control. For example, many security | |
| 510 | +policies may require both incoming and outgoing datagrams be checked against | |
| 511 | +the port and host label ranges. | |
| 512 | + | |
| 513 | + | |
| 514 | +4.1 Port Range Parameters | |
| 515 | + | |
| 516 | +The labels represented by the PORT_LABEL_MAX and PORT_LABEL_MIN parameters | |
| 517 | +MAY be in CIPSO or local format. Some CIPSO systems, such as routers, may | |
| 518 | +want to have the range parameters expressed in CIPSO format so that incoming | |
| 519 | +labels do not have to be converted to a local format before being compared | |
| 520 | +against the range. If multiple DOIs are supported by one of these CIPSO | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | +Internet Draft, Expires 15 Jan 93 [PAGE 8] | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | +systems then multiple port range parameters would be needed, one set for | |
| 533 | +each DOI supported on a particular port. | |
| 534 | + | |
| 535 | +The port range will usually represent the total set of labels that may | |
| 536 | +exist on the logical network accessed through the corresponding network | |
| 537 | +interface. It may, however, represent a subset of these labels that are | |
| 538 | +allowed to enter the CIPSO system. | |
| 539 | + | |
| 540 | + | |
| 541 | +4.2 Single Label CIPSO Hosts | |
| 542 | + | |
| 543 | +CIPSO implementations that support only one label are not required to | |
| 544 | +support the parameters described above. These limited implementations are | |
| 545 | +only required to support a NET_LABEL parameter. This parameter contains | |
| 546 | +the CIPSO label that may be inserted in datagrams that exit the host. In | |
| 547 | +addition, the host MUST reject any incoming datagram that has a label which | |
| 548 | +is not equivalent to the NET_LABEL parameter. | |
| 549 | + | |
| 550 | + | |
| 551 | +5. Handling Procedures | |
| 552 | + | |
| 553 | +This section describes the processing requirements for incoming and | |
| 554 | +outgoing IP datagrams. Just providing the correct CIPSO label format | |
| 555 | +is not enough. Assumptions will be made by one system on how a | |
| 556 | +receiving system will handle the CIPSO label. Wrong assumptions may | |
| 557 | +lead to non-interoperability or even a security incident. The | |
| 558 | +requirements described below represent the minimal set needed for | |
| 559 | +interoperability and that provide users some level of confidence. | |
| 560 | +Many other requirements could be added to increase user confidence, | |
| 561 | +however at the risk of restricting creativity and limiting vendor | |
| 562 | +participation. | |
| 563 | + | |
| 564 | + | |
| 565 | +5.1 Input Procedures | |
| 566 | + | |
| 567 | +All datagrams received through a network port MUST have a security label | |
| 568 | +associated with them, either contained in the datagram or assigned to the | |
| 569 | +receiving port. Without this label the host, gateway, or router will not | |
| 570 | +have the information it needs to make security decisions. This security | |
| 571 | +label will be obtained from the CIPSO if the option is present in the | |
| 572 | +datagram. See section 4.1.2 for handling procedures for unlabeled | |
| 573 | +datagrams. This label will be compared against the PORT (if appropriate) | |
| 574 | +and HOST configuration parameters defined in section 3. | |
| 575 | + | |
| 576 | +If any field within the CIPSO option, such as the DOI identifier, is not | |
| 577 | +recognized the IP datagram is discarded and an ICMP "parameter problem" | |
| 578 | +(type 12) is generated and returned. The ICMP code field is set to "bad | |
| 579 | +parameter" (code 0) and the pointer is set to the start of the CIPSO field | |
| 580 | +that is unrecognized. | |
| 581 | + | |
| 582 | +If the contents of the CIPSO are valid but the security label is | |
| 583 | +outside of the configured host or port label range, the datagram is | |
| 584 | +discarded and an ICMP "destination unreachable" (type 3) is generated | |
| 585 | +and returned. The code field of the ICMP is set to "communication with | |
| 586 | +destination network administratively prohibited" (code 9) or to | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | +Internet Draft, Expires 15 Jan 93 [PAGE 9] | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | +"communication with destination host administratively prohibited" | |
| 599 | +(code 10). The value of the code field used is dependent upon whether | |
| 600 | +the originator of the ICMP message is acting as a CIPSO host or a CIPSO | |
| 601 | +gateway. The recipient of the ICMP message MUST be able to handle either | |
| 602 | +value. The same procedure is performed if a CIPSO can not be added to an | |
| 603 | +IP packet because it is too large to fit in the IP options area. | |
| 604 | + | |
| 605 | +If the error is triggered by receipt of an ICMP message, the message | |
| 606 | +is discarded and no response is permitted (consistent with general ICMP | |
| 607 | +processing rules). | |
| 608 | + | |
| 609 | + | |
| 610 | +5.1.1 Unrecognized tag types | |
| 611 | + | |
| 612 | +The default condition for any CIPSO implementation is that an | |
| 613 | +unrecognized tag type MUST be treated as a "parameter problem" and | |
| 614 | +handled as described in section 4.1. A CIPSO implementation MAY allow | |
| 615 | +the system administrator to identify tag types that may safely be | |
| 616 | +ignored. This capability is an allowable enhancement, not a | |
| 617 | +requirement. | |
| 618 | + | |
| 619 | + | |
| 620 | +5.1.2 Unlabeled Packets | |
| 621 | + | |
| 622 | +A network port may be configured to not require a CIPSO label for all | |
| 623 | +incoming datagrams. For this configuration a CIPSO label must be | |
| 624 | +assigned to that network port and associated with all unlabeled IP | |
| 625 | +datagrams. This capability might be used for single level networks or | |
| 626 | +networks that have CIPSO and non-CIPSO hosts and the non-CIPSO hosts | |
| 627 | +all operate at the same label. | |
| 628 | + | |
| 629 | +If a CIPSO option is required and none is found, the datagram is | |
| 630 | +discarded and an ICMP "parameter problem" (type 12) is generated and | |
| 631 | +returned to the originator of the datagram. The code field of the ICMP | |
| 632 | +is set to "option missing" (code 1) and the ICMP pointer is set to 134 | |
| 633 | +(the value of the option type for the missing CIPSO option). | |
| 634 | + | |
| 635 | + | |
| 636 | +5.2 Output Procedures | |
| 637 | + | |
| 638 | +A CIPSO option MUST appear only once in a datagram. Only one tag type | |
| 639 | +from the MAC Sensitivity class MAY be included in a CIPSO option. Given | |
| 640 | +the current set of defined tag types, this means that CIPSO labels at | |
| 641 | +first will contain only one tag. | |
| 642 | + | |
| 643 | +All datagrams leaving a CIPSO system MUST meet the following condition: | |
| 644 | + | |
| 645 | + PORT_LABEL_MIN <= CIPSO label <= PORT_LABEL_MAX | |
| 646 | + | |
| 647 | +If this condition is not satisfied the datagram MUST be discarded. | |
| 648 | +If the CIPSO system only supports one port, the HOST_LABEL_MIN and the | |
| 649 | +HOST_LABEL_MAX parameters MAY be substituted for the PORT parameters in | |
| 650 | +the above condition. | |
| 651 | + | |
| 652 | +The DOI identifier to be used for all outgoing datagrams is configured by | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | +Internet Draft, Expires 15 Jan 93 [PAGE 10] | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | +the administrator. If port level DOI identifier assignment is used, then | |
| 665 | +the PORT_DOI configuration parameter MUST contain the DOI identifier to | |
| 666 | +use. If network level DOI assignment is used, then the NET_DOI parameter | |
| 667 | +MUST contain the DOI identifier to use. And if host level DOI assignment | |
| 668 | +is employed, then the HOST_DOI parameter MUST contain the DOI identifier | |
| 669 | +to use. A CIPSO implementation need only support one level of DOI | |
| 670 | +assignment. | |
| 671 | + | |
| 672 | + | |
| 673 | +5.3 DOI Processing Requirements | |
| 674 | + | |
| 675 | +A CIPSO implementation MUST support at least one DOI and SHOULD support | |
| 676 | +multiple DOIs. System and network administrators are cautioned to | |
| 677 | +ensure that at least one DOI is common within an IP network to allow for | |
| 678 | +broadcasting of IP datagrams. | |
| 679 | + | |
| 680 | +CIPSO gateways MUST be capable of translating a CIPSO option from one | |
| 681 | +DOI to another when forwarding datagrams between networks. For | |
| 682 | +efficiency purposes this capability is only a desired feature for CIPSO | |
| 683 | +routers. | |
| 684 | + | |
| 685 | + | |
| 686 | +5.4 Label of ICMP Messages | |
| 687 | + | |
| 688 | +The CIPSO label to be used on all outgoing ICMP messages MUST be equivalent | |
| 689 | +to the label of the datagram that caused the ICMP message. If the ICMP was | |
| 690 | +generated due to a problem associated with the original CIPSO label then the | |
| 691 | +following responses are allowed: | |
| 692 | + | |
| 693 | + a. Use the CIPSO label of the original IP datagram | |
| 694 | + b. Drop the original datagram with no return message generated | |
| 695 | + | |
| 696 | +In most cases these options will have the same effect. If you can not | |
| 697 | +interpret the label or if it is outside the label range of your host or | |
| 698 | +interface then an ICMP message with the same label will probably not be | |
| 699 | +able to exit the system. | |
| 700 | + | |
| 701 | + | |
| 702 | +6. Assignment of DOI Identifier Numbers = | |
| 703 | + | |
| 704 | +Requests for assignment of a DOI identifier number should be addressed to | |
| 705 | +the Internet Assigned Numbers Authority (IANA). | |
| 706 | + | |
| 707 | + | |
| 708 | +7. Acknowledgements | |
| 709 | + | |
| 710 | +Much of the material in this RFC is based on (and copied from) work | |
| 711 | +done by Gary Winiger of Sun Microsystems and published as Commercial | |
| 712 | +IP Security Option at the INTEROP 89, Commercial IPSO Workshop. | |
| 713 | + | |
| 714 | + | |
| 715 | +8. Author's Address | |
| 716 | + | |
| 717 | +To submit mail for distribution to members of the IETF CIPSO Working | |
| 718 | +Group, send mail to: cipso@wdl1.wdl.loral.com. | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | +Internet Draft, Expires 15 Jan 93 [PAGE 11] | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | +CIPSO INTERNET DRAFT 16 July, 1992 | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | +To be added to or deleted from this distribution, send mail to: | |
| 732 | +cipso-request@wdl1.wdl.loral.com. | |
| 733 | + | |
| 734 | + | |
| 735 | +9. References | |
| 736 | + | |
| 737 | +RFC 1038, "Draft Revised IP Security Option", M. St. Johns, IETF, January | |
| 738 | +1988. | |
| 739 | + | |
| 740 | +RFC 1108, "U.S. Department of Defense Security Options | |
| 741 | +for the Internet Protocol", Stephen Kent, IAB, 1 March, 1991. | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | +Internet Draft, Expires 15 Jan 93 [PAGE 12] | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| @@ -0,0 +1,46 @@ | ||
| 1 | +NetLabel Introduction | |
| 2 | +============================================================================== | |
| 3 | +Paul Moore, paul.moore@hp.com | |
| 4 | + | |
| 5 | +August 2, 2006 | |
| 6 | + | |
| 7 | + * Overview | |
| 8 | + | |
| 9 | +NetLabel is a mechanism which can be used by kernel security modules to attach | |
| 10 | +security attributes to outgoing network packets generated from user space | |
| 11 | +applications and read security attributes from incoming network packets. It | |
| 12 | +is composed of three main components, the protocol engines, the communication | |
| 13 | +layer, and the kernel security module API. | |
| 14 | + | |
| 15 | + * Protocol Engines | |
| 16 | + | |
| 17 | +The protocol engines are responsible for both applying and retrieving the | |
| 18 | +network packet's security attributes. If any translation between the network | |
| 19 | +security attributes and those on the host are required then the protocol | |
| 20 | +engine will handle those tasks as well. Other kernel subsystems should | |
| 21 | +refrain from calling the protocol engines directly, instead they should use | |
| 22 | +the NetLabel kernel security module API described below. | |
| 23 | + | |
| 24 | +Detailed information about each NetLabel protocol engine can be found in this | |
| 25 | +directory, consult '00-INDEX' for filenames. | |
| 26 | + | |
| 27 | + * Communication Layer | |
| 28 | + | |
| 29 | +The communication layer exists to allow NetLabel configuration and monitoring | |
| 30 | +from user space. The NetLabel communication layer uses a message based | |
| 31 | +protocol built on top of the Generic NETLINK transport mechanism. The exact | |
| 32 | +formatting of these NetLabel messages as well as the Generic NETLINK family | |
| 33 | +names can be found in the the 'net/netlabel/' directory as comments in the | |
| 34 | +header files as well as in 'include/net/netlabel.h'. | |
| 35 | + | |
| 36 | + * Security Module API | |
| 37 | + | |
| 38 | +The purpose of the NetLabel security module API is to provide a protocol | |
| 39 | +independent interface to the underlying NetLabel protocol engines. In addition | |
| 40 | +to protocol independence, the security module API is designed to be completely | |
| 41 | +LSM independent which should allow multiple LSMs to leverage the same code | |
| 42 | +base. | |
| 43 | + | |
| 44 | +Detailed information about the NetLabel security module API can be found in the | |
| 45 | +'include/net/netlabel.h' header file as well as the 'lsm_interface.txt' file | |
| 46 | +found in this directory. | |
| @@ -0,0 +1,47 @@ | ||
| 1 | +NetLabel Linux Security Module Interface | |
| 2 | +============================================================================== | |
| 3 | +Paul Moore, paul.moore@hp.com | |
| 4 | + | |
| 5 | +May 17, 2006 | |
| 6 | + | |
| 7 | + * Overview | |
| 8 | + | |
| 9 | +NetLabel is a mechanism which can set and retrieve security attributes from | |
| 10 | +network packets. It is intended to be used by LSM developers who want to make | |
| 11 | +use of a common code base for several different packet labeling protocols. | |
| 12 | +The NetLabel security module API is defined in 'include/net/netlabel.h' but a | |
| 13 | +brief overview is given below. | |
| 14 | + | |
| 15 | + * NetLabel Security Attributes | |
| 16 | + | |
| 17 | +Since NetLabel supports multiple different packet labeling protocols and LSMs | |
| 18 | +it uses the concept of security attributes to refer to the packet's security | |
| 19 | +labels. The NetLabel security attributes are defined by the | |
| 20 | +'netlbl_lsm_secattr' structure in the NetLabel header file. Internally the | |
| 21 | +NetLabel subsystem converts the security attributes to and from the correct | |
| 22 | +low-level packet label depending on the NetLabel build time and run time | |
| 23 | +configuration. It is up to the LSM developer to translate the NetLabel | |
| 24 | +security attributes into whatever security identifiers are in use for their | |
| 25 | +particular LSM. | |
| 26 | + | |
| 27 | + * NetLabel LSM Protocol Operations | |
| 28 | + | |
| 29 | +These are the functions which allow the LSM developer to manipulate the labels | |
| 30 | +on outgoing packets as well as read the labels on incoming packets. Functions | |
| 31 | +exist to operate both on sockets as well as the sk_buffs directly. These high | |
| 32 | +level functions are translated into low level protocol operations based on how | |
| 33 | +the administrator has configured the NetLabel subsystem. | |
| 34 | + | |
| 35 | + * NetLabel Label Mapping Cache Operations | |
| 36 | + | |
| 37 | +Depending on the exact configuration, translation between the network packet | |
| 38 | +label and the internal LSM security identifier can be time consuming. The | |
| 39 | +NetLabel label mapping cache is a caching mechanism which can be used to | |
| 40 | +sidestep much of this overhead once a mapping has been established. Once the | |
| 41 | +LSM has received a packet, used NetLabel to decode it's security attributes, | |
| 42 | +and translated the security attributes into a LSM internal identifier the LSM | |
| 43 | +can use the NetLabel caching functions to associate the LSM internal | |
| 44 | +identifier with the network packet's label. This means that in the future | |
| 45 | +when a incoming packet matches a cached value not only are the internal | |
| 46 | +NetLabel translation mechanisms bypassed but the LSM translation mechanisms are | |
| 47 | +bypassed as well which should result in a significant reduction in overhead. | |
| @@ -375,6 +375,41 @@ tcp_slow_start_after_idle - BOOLEAN · 374 unmodified lines | ||
| 375 | 375 | be timed out after an idle period. |
| 376 | 376 | Default: 1 |
| 377 | 377 | |
| 378 | +CIPSOv4 Variables: | |
| 379 | + | |
| 380 | +cipso_cache_enable - BOOLEAN | |
| 381 | + If set, enable additions to and lookups from the CIPSO label mapping | |
| 382 | + cache. If unset, additions are ignored and lookups always result in a | |
| 383 | + miss. However, regardless of the setting the cache is still | |
| 384 | + invalidated when required when means you can safely toggle this on and | |
| 385 | + off and the cache will always be "safe". | |
| 386 | + Default: 1 | |
| 387 | + | |
| 388 | +cipso_cache_bucket_size - INTEGER | |
| 389 | + The CIPSO label cache consists of a fixed size hash table with each | |
| 390 | + hash bucket containing a number of cache entries. This variable limits | |
| 391 | + the number of entries in each hash bucket; the larger the value the | |
| 392 | + more CIPSO label mappings that can be cached. When the number of | |
| 393 | + entries in a given hash bucket reaches this limit adding new entries | |
| 394 | + causes the oldest entry in the bucket to be removed to make room. | |
| 395 | + Default: 10 | |
| 396 | + | |
| 397 | +cipso_rbm_optfmt - BOOLEAN | |
| 398 | + Enable the "Optimized Tag 1 Format" as defined in section 3.4.2.6 of | |
| 399 | + the CIPSO draft specification (see Documentation/netlabel for details). | |
| 400 | + This means that when set the CIPSO tag will be padded with empty | |
| 401 | + categories in order to make the packet data 32-bit aligned. | |
| 402 | + Default: 0 | |
| 403 | + | |
| 404 | +cipso_rbm_structvalid - BOOLEAN | |
| 405 | + If set, do a very strict check of the CIPSO option when | |
| 406 | + ip_options_compile() is called. If unset, relax the checks done during | |
| 407 | + ip_options_compile(). Either way is "safe" as errors are caught else | |
| 408 | + where in the CIPSO processing code but setting this to 0 (False) should | |
| 409 | + result in less work (i.e. it should be faster) but could cause problems | |
| 410 | + with other implementations that require strict checking. | |
| 411 | + Default: 0 | |
| 412 | + | |
| 378 | 413 | IP Variables: |
| 379 | 414 | |
| 380 | 415 | ip_local_port_range - 2 INTEGERS |
| @@ -730,6 +765,9 @@ conf/all/forwarding - BOOLEAN · 349 unmodified lines | ||
| 730 | 765 | |
| 731 | 766 | This referred to as global forwarding. |
| 732 | 767 | |
| 768 | +proxy_ndp - BOOLEAN | |
| 769 | + Do proxy ndp. | |
| 770 | + | |
| 733 | 771 | conf/interface/*: |
| 734 | 772 | Change special settings per interface. |
| 735 | 773 | |
| @@ -0,0 +1,14 @@ | ||
| 1 | +flowi structure: | |
| 2 | + | |
| 3 | +The secid member in the flow structure is used in LSMs (e.g. SELinux) to indicate | |
| 4 | +the label of the flow. This label of the flow is currently used in selecting | |
| 5 | +matching labeled xfrm(s). | |
| 6 | + | |
| 7 | +If this is an outbound flow, the label is derived from the socket, if any, or | |
| 8 | +the incoming packet this flow is being generated as a response to (e.g. tcp | |
| 9 | +resets, timewait ack, etc.). It is also conceivable that the label could be | |
| 10 | +derived from other sources such as process context, device, etc., in special | |
| 11 | +cases, as may be appropriate. | |
| 12 | + | |
| 13 | +If this is an inbound flow, the label is derived from the IPSec security | |
| 14 | +associations, if any, used by the packet. | |
| @@ -758,6 +758,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. · 757 unmodified lines | ||
| 758 | 758 | position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) |
| 759 | 759 | single_cmd - Use single immediate commands to communicate with |
| 760 | 760 | codecs (for debugging only) |
| 761 | + disable_msi - Disable Message Signaled Interrupt (MSI) | |
| 761 | 762 | |
| 762 | 763 | This module supports one card and autoprobe. |
| 763 | 764 | |
| @@ -778,11 +779,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. · 14 unmodified lines | ||
| 778 | 779 | 6stack-digout 6-jack with a SPDIF out |
| 779 | 780 | w810 3-jack |
| 780 | 781 | z71v 3-jack (HP shared SPDIF) |
| 781 | − asus 3-jack | |
| 782 | + asus 3-jack (ASUS Mobo) | |
| 783 | + asus-w1v ASUS W1V | |
| 784 | + asus-dig ASUS with SPDIF out | |
| 785 | + asus-dig2 ASUS with SPDIF out (using GPIO2) | |
| 782 | 786 | uniwill 3-jack |
| 783 | 787 | F1734 2-jack |
| 784 | 788 | lg LG laptop (m1 express dual) |
| 785 | − lg-lw LG LW20 laptop | |
| 789 | + lg-lw LG LW20/LW25 laptop | |
| 790 | + tcl TCL S700 | |
| 791 | + clevo Clevo laptops (m520G, m665n) | |
| 786 | 792 | test for testing/debugging purpose, almost all controls can be |
| 787 | 793 | adjusted. Appearing only when compiled with |
| 788 | 794 | $CONFIG_SND_DEBUG=y |
| @@ -790,6 +796,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. · 1 unmodified line | ||
| 790 | 796 | |
| 791 | 797 | ALC260 |
| 792 | 798 | hp HP machines |
| 799 | + hp-3013 HP machines (3013-variant) | |
| 793 | 800 | fujitsu Fujitsu S7020 |
| 794 | 801 | acer Acer TravelMate |
| 795 | 802 | basic fixed pin assignment (old default model) |
| @@ -797,24 +804,32 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. · 1 unmodified line | ||
| 797 | 804 | |
| 798 | 805 | ALC262 |
| 799 | 806 | fujitsu Fujitsu Laptop |
| 807 | + hp-bpc HP xw4400/6400/8400/9400 laptops | |
| 808 | + benq Benq ED8 | |
| 800 | 809 | basic fixed pin assignment w/o SPDIF |
| 801 | 810 | auto auto-config reading BIOS (default) |
| 802 | 811 | |
| 803 | 812 | ALC882/885 |
| 804 | 813 | 3stack-dig 3-jack with SPDIF I/O |
| 805 | 814 | 6stck-dig 6-jack digital with SPDIF I/O |
| 815 | + arima Arima W820Di1 | |
| 806 | 816 | auto auto-config reading BIOS (default) |
| 807 | 817 | |
| 808 | 818 | ALC883/888 |
| 809 | 819 | 3stack-dig 3-jack with SPDIF I/O |
| 810 | 820 | 6stack-dig 6-jack digital with SPDIF I/O |
| 811 | − 6stack-dig-demo 6-stack digital for Intel demo board | |
| 821 | + 3stack-6ch 3-jack 6-channel | |
| 822 | + 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O | |
| 823 | + 6stack-dig-demo 6-jack digital for Intel demo board | |
| 824 | + acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) | |
| 812 | 825 | auto auto-config reading BIOS (default) |
| 813 | 826 | |
| 814 | 827 | ALC861/660 |
| 815 | 828 | 3stack 3-jack |
| 816 | 829 | 3stack-dig 3-jack with SPDIF I/O |
| 817 | 830 | 6stack-dig 6-jack with SPDIF I/O |
| 831 | + 3stack-660 3-jack (for ALC660) | |
| 832 | + uniwill-m31 Uniwill M31 laptop | |
| 818 | 833 | auto auto-config reading BIOS (default) |
| 819 | 834 | |
| 820 | 835 | CMI9880 |
| @@ -843,10 +858,21 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. · 22 unmodified lines | ||
| 843 | 858 | 3stack-dig ditto with SPDIF |
| 844 | 859 | laptop 3-jack with hp-jack automute |
| 845 | 860 | laptop-dig ditto with SPDIF |
| 846 | − auto auto-confgi reading BIOS (default) | |
| 861 | + auto auto-config reading BIOS (default) | |
| 862 | + | |
| 863 | + STAC9200/9205/9220/9221/9254 | |
| 864 | + ref Reference board | |
| 865 | + 3stack D945 3stack | |
| 866 | + 5stack D945 5stack + SPDIF | |
| 847 | 867 | |
| 848 | − STAC7661(?) | |
| 868 | + STAC9227/9228/9229/927x | |
| 869 | + ref Reference board | |
| 870 | + 3stack D965 3stack | |
| 871 | + 5stack D965 5stack + SPDIF | |
| 872 | + | |
| 873 | + STAC9872 | |
| 849 | 874 | vaio Setup for VAIO FE550G/SZ110 |
| 875 | + vaio-ar Setup for VAIO AR | |
| 850 | 876 | |
| 851 | 877 | If the default configuration doesn't work and one of the above |
| 852 | 878 | matches with your device, report it together with the PCI |
| @@ -1213,6 +1239,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. · 360 unmodified lines | ||
| 1213 | 1239 | |
| 1214 | 1240 | Module supports only 1 card. This module has no enable option. |
| 1215 | 1241 | |
| 1242 | + Module snd-mts64 | |
| 1243 | + ---------------- | |
| 1244 | + | |
| 1245 | + Module for Ego Systems (ESI) Miditerminal 4140 | |
| 1246 | + | |
| 1247 | + This module supports multiple devices. | |
| 1248 | + Requires parport (CONFIG_PARPORT). | |
| 1249 | + | |
| 1216 | 1250 | Module snd-nm256 |
| 1217 | 1251 | ---------------- |
| 1218 | 1252 | |
| @@ -1054,9 +1054,8 @@ · 1053 unmodified lines | ||
| 1054 | 1054 | |
| 1055 | 1055 | <para> |
| 1056 | 1056 | For a device which allows hotplugging, you can use |
| 1057 | − <function>snd_card_free_in_thread</function>. This one will | |
| 1058 | − postpone the destruction and wait in a kernel-thread until all | |
| 1059 | − devices are closed. | |
| 1057 | + <function>snd_card_free_when_closed</function>. This one will | |
| 1058 | + postpone the destruction until all devices are closed. | |
| 1060 | 1059 | </para> |
| 1061 | 1060 | |
| 1062 | 1061 | </section> |
| @@ -1058,8 +1058,8 @@ core99_reset_cpu(struct device_node *node, long param, long value) · 1057 unmodified lines | ||
| 1058 | 1058 | if (np == NULL) |
| 1059 | 1059 | return -ENODEV; |
| 1060 | 1060 | for (np = np->child; np != NULL; np = np->sibling) { |
| 1061 | − u32 *num = get_property(np, "reg", NULL); | |
| 1062 | − u32 *rst = get_property(np, "soft-reset", NULL); | |
| 1061 | + const u32 *num = get_property(np, "reg", NULL); | |
| 1062 | + const u32 *rst = get_property(np, "soft-reset", NULL); | |
| 1063 | 1063 | if (num == NULL || rst == NULL) |
| 1064 | 1064 | continue; |
| 1065 | 1065 | if (param == *num) { |
| @@ -702,7 +702,7 @@ static void __init smp_core99_setup(int ncpus) · 701 unmodified lines | ||
| 702 | 702 | /* GPIO based HW sync on ppc32 Core99 */ |
| 703 | 703 | if (pmac_tb_freeze == NULL && !machine_is_compatible("MacRISC4")) { |
| 704 | 704 | struct device_node *cpu; |
| 705 | − u32 *tbprop = NULL; | |
| 705 | + const u32 *tbprop = NULL; | |
| 706 | 706 | |
| 707 | 707 | core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */ |
| 708 | 708 | cpu = of_find_node_by_type(NULL, "cpu"); |
| @@ -2801,6 +2801,18 @@ long blk_congestion_wait(int rw, long timeout) · 2800 unmodified lines | ||
| 2801 | 2801 | |
| 2802 | 2802 | EXPORT_SYMBOL(blk_congestion_wait); |
| 2803 | 2803 | |
| 2804 | +/** | |
| 2805 | + * blk_congestion_end - wake up sleepers on a congestion queue | |
| 2806 | + * @rw: READ or WRITE | |
| 2807 | + */ | |
| 2808 | +void blk_congestion_end(int rw) | |
| 2809 | +{ | |
| 2810 | + wait_queue_head_t *wqh = &congestion_wqh[rw]; | |
| 2811 | + | |
| 2812 | + if (waitqueue_active(wqh)) | |
| 2813 | + wake_up(wqh); | |
| 2814 | +} | |
| 2815 | + | |
| 2804 | 2816 | /* |
| 2805 | 2817 | * Has to be called with the request spinlock acquired |
| 2806 | 2818 | */ |
| @@ -92,13 +92,17 @@ static int hmac_init(struct hash_desc *pdesc) · 91 unmodified lines | ||
| 92 | 92 | struct hmac_ctx *ctx = align_ptr(ipad + bs * 2 + ds, sizeof(void *)); |
| 93 | 93 | struct hash_desc desc; |
| 94 | 94 | struct scatterlist tmp; |
| 95 | + int err; | |
| 95 | 96 | |
| 96 | 97 | desc.tfm = ctx->child; |
| 97 | 98 | desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; |
| 98 | 99 | sg_set_buf(&tmp, ipad, bs); |
| 99 | 100 | |
| 100 | − return unlikely(crypto_hash_init(&desc)) ?: | |
| 101 | − crypto_hash_update(&desc, &tmp, 1); | |
| 101 | + err = crypto_hash_init(&desc); | |
| 102 | + if (unlikely(err)) | |
| 103 | + return err; | |
| 104 | + | |
| 105 | + return crypto_hash_update(&desc, &tmp, bs); | |
| 102 | 106 | } |
| 103 | 107 | |
| 104 | 108 | static int hmac_update(struct hash_desc *pdesc, |
| @@ -123,13 +127,17 @@ static int hmac_final(struct hash_desc *pdesc, u8 *out) · 18 unmodified lines | ||
| 123 | 127 | struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *)); |
| 124 | 128 | struct hash_desc desc; |
| 125 | 129 | struct scatterlist tmp; |
| 130 | + int err; | |
| 126 | 131 | |
| 127 | 132 | desc.tfm = ctx->child; |
| 128 | 133 | desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; |
| 129 | 134 | sg_set_buf(&tmp, opad, bs + ds); |
| 130 | 135 | |
| 131 | − return unlikely(crypto_hash_final(&desc, digest)) ?: | |
| 132 | − crypto_hash_digest(&desc, &tmp, bs + ds, out); | |
| 136 | + err = crypto_hash_final(&desc, digest); | |
| 137 | + if (unlikely(err)) | |
| 138 | + return err; | |
| 139 | + | |
| 140 | + return crypto_hash_digest(&desc, &tmp, bs + ds, out); | |
| 133 | 141 | } |
| 134 | 142 | |
| 135 | 143 | static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg, |
| @@ -145,6 +153,7 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg, · 9 unmodified lines | ||
| 145 | 153 | struct hash_desc desc; |
| 146 | 154 | struct scatterlist sg1[2]; |
| 147 | 155 | struct scatterlist sg2[1]; |
| 156 | + int err; | |
| 148 | 157 | |
| 149 | 158 | desc.tfm = ctx->child; |
| 150 | 159 | desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; |
| @@ -154,8 +163,11 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg, · 3 unmodified lines | ||
| 154 | 163 | sg1[1].length = 0; |
| 155 | 164 | sg_set_buf(sg2, opad, bs + ds); |
| 156 | 165 | |
| 157 | − return unlikely(crypto_hash_digest(&desc, sg1, nbytes + bs, digest)) ?: | |
| 158 | − crypto_hash_digest(&desc, sg2, bs + ds, out); | |
| 166 | + err = crypto_hash_digest(&desc, sg1, nbytes + bs, digest); | |
| 167 | + if (unlikely(err)) | |
| 168 | + return err; | |
| 169 | + | |
| 170 | + return crypto_hash_digest(&desc, sg2, bs + ds, out); | |
| 159 | 171 | } |
| 160 | 172 | |
| 161 | 173 | static int hmac_init_tfm(struct crypto_tfm *tfm) |
| @@ -1912,7 +1912,7 @@ he_service_rbrq(struct he_dev *he_dev, int group) · 1911 unmodified lines | ||
| 1912 | 1912 | skb->tail = skb->data + skb->len; |
| 1913 | 1913 | #ifdef USE_CHECKSUM_HW |
| 1914 | 1914 | if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) { |
| 1915 | − skb->ip_summed = CHECKSUM_HW; | |
| 1915 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 1916 | 1916 | skb->csum = TCP_CKSUM(skb->data, |
| 1917 | 1917 | he_vcc->pdu_len); |
| 1918 | 1918 | } |
| @@ -87,7 +87,7 @@ static int briq_panel_release(struct inode *ino, struct file *filep) · 86 unmodified lines | ||
| 87 | 87 | return 0; |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | −static ssize_t briq_panel_read(struct file *file, char *buf, size_t count, | |
| 90 | +static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count, | |
| 91 | 91 | loff_t *ppos) |
| 92 | 92 | { |
| 93 | 93 | unsigned short c; |
| @@ -135,7 +135,7 @@ static void scroll_vfd( void ) · 41 unmodified lines | ||
| 135 | 135 | vfd_cursor = 20; |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | −static ssize_t briq_panel_write(struct file *file, const char *buf, size_t len, | |
| 138 | +static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_t len, | |
| 139 | 139 | loff_t *ppos) |
| 140 | 140 | { |
| 141 | 141 | size_t indx = len; |
| @@ -150,19 +150,22 @@ static ssize_t briq_panel_write(struct file *file, const char *buf, size_t len, · 8 unmodified lines | ||
| 150 | 150 | return -EBUSY; |
| 151 | 151 | |
| 152 | 152 | for (;;) { |
| 153 | + char c; | |
| 153 | 154 | if (!indx) |
| 154 | 155 | break; |
| 156 | + if (get_user(c, buf)) | |
| 157 | + return -EFAULT; | |
| 155 | 158 | if (esc) { |
| 156 | − set_led(*buf); | |
| 159 | + set_led(c); | |
| 157 | 160 | esc = 0; |
| 158 | − } else if (*buf == 27) { | |
| 161 | + } else if (c == 27) { | |
| 159 | 162 | esc = 1; |
| 160 | − } else if (*buf == 12) { | |
| 163 | + } else if (c == 12) { | |
| 161 | 164 | /* do a form feed */ |
| 162 | 165 | for (i=0; i<40; i++) |
| 163 | 166 | vfd[i] = ' '; |
| 164 | 167 | vfd_cursor = 0; |
| 165 | − } else if (*buf == 10) { | |
| 168 | + } else if (c == 10) { | |
| 166 | 169 | if (vfd_cursor < 20) |
| 167 | 170 | vfd_cursor = 20; |
| 168 | 171 | else if (vfd_cursor < 40) |
| @@ -175,7 +178,7 @@ static ssize_t briq_panel_write(struct file *file, const char *buf, size_t len, · 6 unmodified lines | ||
| 175 | 178 | /* just a character */ |
| 176 | 179 | if (vfd_cursor > 39) |
| 177 | 180 | scroll_vfd(); |
| 178 | − vfd[vfd_cursor++] = *buf; | |
| 181 | + vfd[vfd_cursor++] = c; | |
| 179 | 182 | } |
| 180 | 183 | indx--; |
| 181 | 184 | buf++; |
| @@ -202,7 +205,7 @@ static struct miscdevice briq_panel_miscdev = { · 20 unmodified lines | ||
| 202 | 205 | static int __init briq_panel_init(void) |
| 203 | 206 | { |
| 204 | 207 | struct device_node *root = find_path_device("/"); |
| 205 | − char *machine; | |
| 208 | + const char *machine; | |
| 206 | 209 | int i; |
| 207 | 210 | |
| 208 | 211 | machine = get_property(root, "model", NULL); |
| @@ -38,6 +38,7 @@ · 37 unmodified lines | ||
| 38 | 38 | #define __IB_MAD_PRIV_H__ |
| 39 | 39 | |
| 40 | 40 | #include <linux/completion.h> |
| 41 | +#include <linux/err.h> | |
| 41 | 42 | #include <linux/pci.h> |
| 42 | 43 | #include <linux/workqueue.h> |
| 43 | 44 | #include <rdma/ib_mad.h> |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | #include <linux/init.h> |
| 50 | 50 | #include <linux/dma-mapping.h> |
| 51 | 51 | #include <linux/if_arp.h> |
| 52 | +#include <linux/vmalloc.h> | |
| 52 | 53 | |
| 53 | 54 | #include <asm/io.h> |
| 54 | 55 | #include <asm/irq.h> |
| @@ -50,6 +50,7 @@ · 49 unmodified lines | ||
| 50 | 50 | #include <linux/dma-mapping.h> |
| 51 | 51 | #include <linux/mm.h> |
| 52 | 52 | #include <linux/inet.h> |
| 53 | +#include <linux/vmalloc.h> | |
| 53 | 54 | |
| 54 | 55 | #include <linux/route.h> |
| 55 | 56 | |
| @@ -43,6 +43,7 @@ · 42 unmodified lines | ||
| 43 | 43 | |
| 44 | 44 | #include <linux/io.h> |
| 45 | 45 | #include <linux/pci.h> |
| 46 | +#include <linux/vmalloc.h> | |
| 46 | 47 | #include <asm/uaccess.h> |
| 47 | 48 | |
| 48 | 49 | #include "ipath_kernel.h" |
| @@ -101,7 +101,7 @@ config MTD_REDBOOT_PARTS_READONLY · 100 unmodified lines | ||
| 101 | 101 | |
| 102 | 102 | config MTD_CMDLINE_PARTS |
| 103 | 103 | bool "Command line partition table parsing" |
| 104 | − depends on MTD_PARTITIONS = "y" | |
| 104 | + depends on MTD_PARTITIONS = "y" && MTD = "y" | |
| 105 | 105 | ---help--- |
| 106 | 106 | Allow generic configuration of the MTD partition tables via the kernel |
| 107 | 107 | command line. Multiple flash resources are supported for hardware where |
| @@ -264,7 +264,7 @@ config RFD_FTL · 156 unmodified lines | ||
| 264 | 264 | http://www.gensw.com/pages/prod/bios/rfd.htm |
| 265 | 265 | |
| 266 | 266 | config SSFDC |
| 267 | − bool "NAND SSFDC (SmartMedia) read only translation layer" | |
| 267 | + tristate "NAND SSFDC (SmartMedia) read only translation layer" | |
| 268 | 268 | depends on MTD |
| 269 | 269 | default n |
| 270 | 270 | help |
| @@ -10,7 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | * published by the Free Software Foundation. |
| 11 | 11 | */ |
| 12 | 12 | |
| 13 | −#include <linux/config.h> | |
| 14 | 13 | #include <linux/kernel.h> |
| 15 | 14 | #include <linux/module.h> |
| 16 | 15 | #include <linux/init.h> |
| @@ -29,7 +28,7 @@ struct ssfdcr_record { · 12 unmodified lines | ||
| 29 | 28 | int cis_block; /* block n. containing CIS/IDI */ |
| 30 | 29 | int erase_size; /* phys_block_size */ |
| 31 | 30 | unsigned short *logic_block_map; /* all zones (max 8192 phys blocks on |
| 32 | − the 128MB) */ | |
| 31 | + the 128MiB) */ | |
| 33 | 32 | int map_len; /* n. phys_blocks on the card */ |
| 34 | 33 | }; |
| 35 | 34 | |
| @@ -43,11 +42,11 @@ struct ssfdcr_record { · 7 unmodified lines | ||
| 43 | 42 | #define MAX_LOGIC_BLK_PER_ZONE 1000 |
| 44 | 43 | #define MAX_PHYS_BLK_PER_ZONE 1024 |
| 45 | 44 | |
| 46 | −#define KB(x) ( (x) * 1024L ) | |
| 47 | −#define MB(x) ( KB(x) * 1024L ) | |
| 45 | +#define KiB(x) ( (x) * 1024L ) | |
| 46 | +#define MiB(x) ( KiB(x) * 1024L ) | |
| 48 | 47 | |
| 49 | 48 | /** CHS Table |
| 50 | − 1MB 2MB 4MB 8MB 16MB 32MB 64MB 128MB | |
| 49 | + 1MiB 2MiB 4MiB 8MiB 16MiB 32MiB 64MiB 128MiB | |
| 51 | 50 | NCylinder 125 125 250 250 500 500 500 500 |
| 52 | 51 | NHead 4 4 4 4 4 8 8 16 |
| 53 | 52 | NSector 4 8 8 16 16 16 32 32 |
| @@ -64,14 +63,14 @@ typedef struct { · 10 unmodified lines | ||
| 64 | 63 | |
| 65 | 64 | /* Must be ordered by size */ |
| 66 | 65 | static const chs_entry_t chs_table[] = { |
| 67 | − { MB( 1), 125, 4, 4 }, | |
| 68 | − { MB( 2), 125, 4, 8 }, | |
| 69 | − { MB( 4), 250, 4, 8 }, | |
| 70 | − { MB( 8), 250, 4, 16 }, | |
| 71 | − { MB( 16), 500, 4, 16 }, | |
| 72 | − { MB( 32), 500, 8, 16 }, | |
| 73 | − { MB( 64), 500, 8, 32 }, | |
| 74 | − { MB(128), 500, 16, 32 }, | |
| 66 | + { MiB( 1), 125, 4, 4 }, | |
| 67 | + { MiB( 2), 125, 4, 8 }, | |
| 68 | + { MiB( 4), 250, 4, 8 }, | |
| 69 | + { MiB( 8), 250, 4, 16 }, | |
| 70 | + { MiB( 16), 500, 4, 16 }, | |
| 71 | + { MiB( 32), 500, 8, 16 }, | |
| 72 | + { MiB( 64), 500, 8, 32 }, | |
| 73 | + { MiB(128), 500, 16, 32 }, | |
| 75 | 74 | { 0 }, |
| 76 | 75 | }; |
| 77 | 76 | |
| @@ -109,25 +108,30 @@ static int get_valid_cis_sector(struct mtd_info *mtd) · 31 unmodified lines | ||
| 109 | 108 | int ret, k, cis_sector; |
| 110 | 109 | size_t retlen; |
| 111 | 110 | loff_t offset; |
| 112 | − uint8_t sect_buf[SECTOR_SIZE]; | |
| 111 | + uint8_t *sect_buf; | |
| 112 | + | |
| 113 | + cis_sector = -1; | |
| 114 | + | |
| 115 | + sect_buf = kmalloc(SECTOR_SIZE, GFP_KERNEL); | |
| 116 | + if (!sect_buf) | |
| 117 | + goto out; | |
| 113 | 118 | |
| 114 | 119 | /* |
| 115 | 120 | * Look for CIS/IDI sector on the first GOOD block (give up after 4 bad |
| 116 | 121 | * blocks). If the first good block doesn't contain CIS number the flash |
| 117 | 122 | * is not SSFDC formatted |
| 118 | 123 | */ |
| 119 | − cis_sector = -1; | |
| 120 | 124 | for (k = 0, offset = 0; k < 4; k++, offset += mtd->erasesize) { |
| 121 | 125 | if (!mtd->block_isbad(mtd, offset)) { |
| 122 | 126 | ret = mtd->read(mtd, offset, SECTOR_SIZE, &retlen, |
| 123 | 127 | sect_buf); |
| 124 | 128 | |
| 125 | 129 | /* CIS pattern match on the sector buffer */ |
| 126 | − if ( ret < 0 || retlen != SECTOR_SIZE ) { | |
| 130 | + if (ret < 0 || retlen != SECTOR_SIZE) { | |
| 127 | 131 | printk(KERN_WARNING |
| 128 | 132 | "SSFDC_RO:can't read CIS/IDI sector\n"); |
| 129 | − } else if ( !memcmp(sect_buf, cis_numbers, | |
| 130 | − sizeof(cis_numbers)) ) { | |
| 133 | + } else if (!memcmp(sect_buf, cis_numbers, | |
| 134 | + sizeof(cis_numbers))) { | |
| 131 | 135 | /* Found */ |
| 132 | 136 | cis_sector = (int)(offset >> SECTOR_SHIFT); |
| 133 | 137 | } else { |
| @@ -140,6 +144,8 @@ static int get_valid_cis_sector(struct mtd_info *mtd) · 6 unmodified lines | ||
| 140 | 144 | } |
| 141 | 145 | } |
| 142 | 146 | |
| 147 | + kfree(sect_buf); | |
| 148 | + out: | |
| 143 | 149 | return cis_sector; |
| 144 | 150 | } |
| 145 | 151 | |
| @@ -227,7 +233,7 @@ static int get_logical_address(uint8_t *oob_buf) · 81 unmodified lines | ||
| 227 | 233 | } |
| 228 | 234 | } |
| 229 | 235 | |
| 230 | − if ( !ok ) | |
| 236 | + if (!ok) | |
| 231 | 237 | block_address = -2; |
| 232 | 238 | |
| 233 | 239 | DEBUG(MTD_DEBUG_LEVEL3, "SSFDC_RO: get_logical_address() %d\n", |
| @@ -245,8 +251,8 @@ static int build_logical_block_map(struct ssfdcr_record *ssfdc) · 11 unmodified lines | ||
| 245 | 251 | struct mtd_info *mtd = ssfdc->mbd.mtd; |
| 246 | 252 | |
| 247 | 253 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: build_block_map() nblks=%d (%luK)\n", |
| 248 | − ssfdc->map_len, (unsigned long)ssfdc->map_len * | |
| 249 | − ssfdc->erase_size / 1024 ); | |
| 254 | + ssfdc->map_len, | |
| 255 | + (unsigned long)ssfdc->map_len * ssfdc->erase_size / 1024); | |
| 250 | 256 | |
| 251 | 257 | /* Scan every physical block, skip CIS block */ |
| 252 | 258 | for (phys_block = ssfdc->cis_block + 1; phys_block < ssfdc->map_len; |
| @@ -323,21 +329,21 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) · 70 unmodified lines | ||
| 323 | 329 | /* Set geometry */ |
| 324 | 330 | ssfdc->heads = 16; |
| 325 | 331 | ssfdc->sectors = 32; |
| 326 | − get_chs( mtd->size, NULL, &ssfdc->heads, &ssfdc->sectors); | |
| 332 | + get_chs(mtd->size, NULL, &ssfdc->heads, &ssfdc->sectors); | |
| 327 | 333 | ssfdc->cylinders = (unsigned short)((mtd->size >> SECTOR_SHIFT) / |
| 328 | 334 | ((long)ssfdc->sectors * (long)ssfdc->heads)); |
| 329 | 335 | |
| 330 | 336 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n", |
| 331 | 337 | ssfdc->cylinders, ssfdc->heads , ssfdc->sectors, |
| 332 | 338 | (long)ssfdc->cylinders * (long)ssfdc->heads * |
| 333 | − (long)ssfdc->sectors ); | |
| 339 | + (long)ssfdc->sectors); | |
| 334 | 340 | |
| 335 | 341 | ssfdc->mbd.size = (long)ssfdc->heads * (long)ssfdc->cylinders * |
| 336 | 342 | (long)ssfdc->sectors; |
| 337 | 343 | |
| 338 | 344 | /* Allocate logical block map */ |
| 339 | − ssfdc->logic_block_map = kmalloc( sizeof(ssfdc->logic_block_map[0]) * | |
| 340 | − ssfdc->map_len, GFP_KERNEL); | |
| 345 | + ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) * | |
| 346 | + ssfdc->map_len, GFP_KERNEL); | |
| 341 | 347 | if (!ssfdc->logic_block_map) { |
| 342 | 348 | printk(KERN_WARNING |
| 343 | 349 | "SSFDC_RO: out of memory for data structures\n"); |
| @@ -408,7 +414,7 @@ static int ssfdcr_readsect(struct mtd_blktrans_dev *dev, · 64 unmodified lines | ||
| 408 | 414 | "SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n", |
| 409 | 415 | sect_no); |
| 410 | 416 | |
| 411 | − if (read_physical_sector( ssfdc->mbd.mtd, buf, sect_no ) < 0) | |
| 417 | + if (read_physical_sector(ssfdc->mbd.mtd, buf, sect_no) < 0) | |
| 412 | 418 | return -EIO; |
| 413 | 419 | } else { |
| 414 | 420 | memset(buf, 0xff, SECTOR_SIZE); |
| @@ -2077,7 +2077,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) · 2076 unmodified lines | ||
| 2077 | 2077 | |
| 2078 | 2078 | vp->tx_ring[entry].next = 0; |
| 2079 | 2079 | #if DO_ZEROCOPY |
| 2080 | − if (skb->ip_summed != CHECKSUM_HW) | |
| 2080 | + if (skb->ip_summed != CHECKSUM_PARTIAL) | |
| 2081 | 2081 | vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); |
| 2082 | 2082 | else |
| 2083 | 2083 | vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum); |
| @@ -813,7 +813,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) · 812 unmodified lines | ||
| 813 | 813 | |
| 814 | 814 | if (mss) |
| 815 | 815 | flags |= LargeSend | ((mss & MSSMask) << MSSShift); |
| 816 | − else if (skb->ip_summed == CHECKSUM_HW) { | |
| 816 | + else if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 817 | 817 | const struct iphdr *ip = skb->nh.iph; |
| 818 | 818 | if (ip->protocol == IPPROTO_TCP) |
| 819 | 819 | flags |= IPCS | TCPCS; |
| @@ -867,7 +867,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) · 47 unmodified lines | ||
| 867 | 867 | if (mss) |
| 868 | 868 | ctrl |= LargeSend | |
| 869 | 869 | ((mss & MSSMask) << MSSShift); |
| 870 | − else if (skb->ip_summed == CHECKSUM_HW) { | |
| 870 | + else if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 871 | 871 | if (ip->protocol == IPPROTO_TCP) |
| 872 | 872 | ctrl |= IPCS | TCPCS; |
| 873 | 873 | else if (ip->protocol == IPPROTO_UDP) |
| @@ -898,7 +898,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) · 24 unmodified lines | ||
| 898 | 898 | txd->addr = cpu_to_le64(first_mapping); |
| 899 | 899 | wmb(); |
| 900 | 900 | |
| 901 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 901 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 902 | 902 | if (ip->protocol == IPPROTO_TCP) |
| 903 | 903 | txd->opts1 = cpu_to_le32(first_eor | first_len | |
| 904 | 904 | FirstFrag | DescOwn | |
| @@ -2040,7 +2040,7 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) · 2039 unmodified lines | ||
| 2040 | 2040 | */ |
| 2041 | 2041 | if (bd_flags & BD_FLG_TCP_UDP_SUM) { |
| 2042 | 2042 | skb->csum = htons(csum); |
| 2043 | − skb->ip_summed = CHECKSUM_HW; | |
| 2043 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 2044 | 2044 | } else { |
| 2045 | 2045 | skb->ip_summed = CHECKSUM_NONE; |
| 2046 | 2046 | } |
| @@ -2511,7 +2511,7 @@ restart: · 464 unmodified lines | ||
| 2511 | 2511 | |
| 2512 | 2512 | mapping = ace_map_tx_skb(ap, skb, skb, idx); |
| 2513 | 2513 | flagsize = (skb->len << 16) | (BD_FLG_END); |
| 2514 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 2514 | + if (skb->ip_summed == CHECKSUM_PARTIAL) | |
| 2515 | 2515 | flagsize |= BD_FLG_TCP_UDP_SUM; |
| 2516 | 2516 | #if ACENIC_DO_VLAN |
| 2517 | 2517 | if (vlan_tx_tag_present(skb)) { |
| @@ -2534,7 +2534,7 @@ restart: · 16 unmodified lines | ||
| 2534 | 2534 | |
| 2535 | 2535 | mapping = ace_map_tx_skb(ap, skb, NULL, idx); |
| 2536 | 2536 | flagsize = (skb_headlen(skb) << 16); |
| 2537 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 2537 | + if (skb->ip_summed == CHECKSUM_PARTIAL) | |
| 2538 | 2538 | flagsize |= BD_FLG_TCP_UDP_SUM; |
| 2539 | 2539 | #if ACENIC_DO_VLAN |
| 2540 | 2540 | if (vlan_tx_tag_present(skb)) { |
| @@ -2560,7 +2560,7 @@ restart: · 19 unmodified lines | ||
| 2560 | 2560 | PCI_DMA_TODEVICE); |
| 2561 | 2561 | |
| 2562 | 2562 | flagsize = (frag->size << 16); |
| 2563 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 2563 | + if (skb->ip_summed == CHECKSUM_PARTIAL) | |
| 2564 | 2564 | flagsize |= BD_FLG_TCP_UDP_SUM; |
| 2565 | 2565 | idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap); |
| 2566 | 2566 | |
| @@ -161,6 +161,7 @@ static struct pci_device_id com20020pci_id_table[] = { · 160 unmodified lines | ||
| 161 | 161 | { 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, |
| 162 | 162 | { 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, |
| 163 | 163 | { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, |
| 164 | + { 0x10B5, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, | |
| 164 | 165 | { 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, |
| 165 | 166 | {0,} |
| 166 | 167 | }; |
| @@ -4423,7 +4423,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) · 4422 unmodified lines | ||
| 4423 | 4423 | ring_prod = TX_RING_IDX(prod); |
| 4424 | 4424 | |
| 4425 | 4425 | vlan_tag_flags = 0; |
| 4426 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 4426 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 4427 | 4427 | vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; |
| 4428 | 4428 | } |
| 4429 | 4429 | |
| @@ -2167,7 +2167,7 @@ end_copy_pkt: · 2166 unmodified lines | ||
| 2167 | 2167 | cas_page_unmap(addr); |
| 2168 | 2168 | } |
| 2169 | 2169 | skb->csum = ntohs(i ^ 0xffff); |
| 2170 | − skb->ip_summed = CHECKSUM_HW; | |
| 2170 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 2171 | 2171 | skb->protocol = eth_type_trans(skb, cp->dev); |
| 2172 | 2172 | return len; |
| 2173 | 2173 | } |
| @@ -2821,7 +2821,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, · 647 unmodified lines | ||
| 2821 | 2821 | } |
| 2822 | 2822 | |
| 2823 | 2823 | ctrl = 0; |
| 2824 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 2824 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 2825 | 2825 | u64 csum_start_off, csum_stuff_off; |
| 2826 | 2826 | |
| 2827 | 2827 | csum_start_off = (u64) (skb->h.raw - skb->data); |
| @@ -1470,9 +1470,9 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) · 1469 unmodified lines | ||
| 1470 | 1470 | } |
| 1471 | 1471 | |
| 1472 | 1472 | if (!(adapter->flags & UDP_CSUM_CAPABLE) && |
| 1473 | − skb->ip_summed == CHECKSUM_HW && | |
| 1473 | + skb->ip_summed == CHECKSUM_PARTIAL && | |
| 1474 | 1474 | skb->nh.iph->protocol == IPPROTO_UDP) |
| 1475 | − if (unlikely(skb_checksum_help(skb, 0))) { | |
| 1475 | + if (unlikely(skb_checksum_help(skb))) { | |
| 1476 | 1476 | dev_kfree_skb_any(skb); |
| 1477 | 1477 | return NETDEV_TX_OK; |
| 1478 | 1478 | } |
| @@ -1495,11 +1495,11 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) · 16 unmodified lines | ||
| 1495 | 1495 | cpl = (struct cpl_tx_pkt *)__skb_push(skb, sizeof(*cpl)); |
| 1496 | 1496 | cpl->opcode = CPL_TX_PKT; |
| 1497 | 1497 | cpl->ip_csum_dis = 1; /* SW calculates IP csum */ |
| 1498 | − cpl->l4_csum_dis = skb->ip_summed == CHECKSUM_HW ? 0 : 1; | |
| 1498 | + cpl->l4_csum_dis = skb->ip_summed == CHECKSUM_PARTIAL ? 0 : 1; | |
| 1499 | 1499 | /* the length field isn't used so don't bother setting it */ |
| 1500 | 1500 | |
| 1501 | − st->tx_cso += (skb->ip_summed == CHECKSUM_HW); | |
| 1502 | − sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_HW); | |
| 1501 | + st->tx_cso += (skb->ip_summed == CHECKSUM_PARTIAL); | |
| 1502 | + sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_PARTIAL); | |
| 1503 | 1503 | sge->stats.tx_reg_pkts++; |
| 1504 | 1504 | } |
| 1505 | 1505 | cpl->iff = dev->if_port; |
| @@ -611,7 +611,7 @@ start_xmit (struct sk_buff *skb, struct net_device *dev) · 610 unmodified lines | ||
| 611 | 611 | txdesc = &np->tx_ring[entry]; |
| 612 | 612 | |
| 613 | 613 | #if 0 |
| 614 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 614 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 615 | 615 | txdesc->status |= |
| 616 | 616 | cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable | |
| 617 | 617 | IPChecksumEnable); |
| @@ -2600,7 +2600,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, · 2599 unmodified lines | ||
| 2600 | 2600 | unsigned int i; |
| 2601 | 2601 | uint8_t css; |
| 2602 | 2602 | |
| 2603 | − if (likely(skb->ip_summed == CHECKSUM_HW)) { | |
| 2603 | + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { | |
| 2604 | 2604 | css = skb->h.raw - skb->data; |
| 2605 | 2605 | |
| 2606 | 2606 | i = tx_ring->next_to_use; |
| @@ -2927,11 +2927,11 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) · 320 unmodified lines | ||
| 2927 | 2927 | } |
| 2928 | 2928 | |
| 2929 | 2929 | /* reserve a descriptor for the offload context */ |
| 2930 | − if ((mss) || (skb->ip_summed == CHECKSUM_HW)) | |
| 2930 | + if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) | |
| 2931 | 2931 | count++; |
| 2932 | 2932 | count++; |
| 2933 | 2933 | #else |
| 2934 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 2934 | + if (skb->ip_summed == CHECKSUM_PARTIAL) | |
| 2935 | 2935 | count++; |
| 2936 | 2936 | #endif |
| 2937 | 2937 | |
| @@ -3608,7 +3608,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter, · 670 unmodified lines | ||
| 3608 | 3608 | */ |
| 3609 | 3609 | csum = ntohl(csum ^ 0xFFFF); |
| 3610 | 3610 | skb->csum = csum; |
| 3611 | − skb->ip_summed = CHECKSUM_HW; | |
| 3611 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 3612 | 3612 | } |
| 3613 | 3613 | adapter->hw_csum_good++; |
| 3614 | 3614 | } |
| @@ -1503,7 +1503,8 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) · 1502 unmodified lines | ||
| 1503 | 1503 | tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT); |
| 1504 | 1504 | else |
| 1505 | 1505 | #endif |
| 1506 | − tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); | |
| 1506 | + tx_flags_extra = skb->ip_summed == CHECKSUM_PARTIAL ? | |
| 1507 | + NV_TX2_CHECKSUM_L3 | NV_TX2_CHECKSUM_L4 : 0; | |
| 1507 | 1508 | |
| 1508 | 1509 | /* vlan tag */ |
| 1509 | 1510 | if (np->vlangrp && vlan_tx_tag_present(skb)) { |
| @@ -947,7 +947,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) · 946 unmodified lines | ||
| 947 | 947 | |
| 948 | 948 | /* Set up checksumming */ |
| 949 | 949 | if (likely((dev->features & NETIF_F_IP_CSUM) |
| 950 | − && (CHECKSUM_HW == skb->ip_summed))) { | |
| 950 | + && (CHECKSUM_PARTIAL == skb->ip_summed))) { | |
| 951 | 951 | fcb = gfar_add_fcb(skb, txbdp); |
| 952 | 952 | status |= TXBD_TOE; |
| 953 | 953 | gfar_tx_checksum(skb, fcb); |
| @@ -1648,7 +1648,7 @@ static int hamachi_rx(struct net_device *dev) · 1647 unmodified lines | ||
| 1648 | 1648 | * could do the pseudo myself and return |
| 1649 | 1649 | * CHECKSUM_UNNECESSARY |
| 1650 | 1650 | */ |
| 1651 | − skb->ip_summed = CHECKSUM_HW; | |
| 1651 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 1652 | 1652 | } |
| 1653 | 1653 | } |
| 1654 | 1654 | } |
| @@ -1036,7 +1036,7 @@ static inline u16 emac_tx_csum(struct ocp_enet_private *dev, · 1035 unmodified lines | ||
| 1036 | 1036 | struct sk_buff *skb) |
| 1037 | 1037 | { |
| 1038 | 1038 | #if defined(CONFIG_IBM_EMAC_TAH) |
| 1039 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 1039 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 1040 | 1040 | ++dev->stats.tx_packets_csum; |
| 1041 | 1041 | return EMAC_TX_CTRL_TAH_CSUM; |
| 1042 | 1042 | } |
| @@ -1387,7 +1387,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) · 1386 unmodified lines | ||
| 1387 | 1387 | * MAC header which should not be summed and the TCP/UDP pseudo headers |
| 1388 | 1388 | * manually. |
| 1389 | 1389 | */ |
| 1390 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 1390 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 1391 | 1391 | int proto = ntohs(skb->nh.iph->protocol); |
| 1392 | 1392 | unsigned int csoff; |
| 1393 | 1393 | struct iphdr *ih = skb->nh.iph; |
| @@ -249,7 +249,7 @@ static void __exit ali_ircc_cleanup(void) · 248 unmodified lines | ||
| 249 | 249 | |
| 250 | 250 | IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); |
| 251 | 251 | |
| 252 | − for (i=0; i < 4; i++) { | |
| 252 | + for (i=0; i < ARRAY_SIZE(dev_self); i++) { | |
| 253 | 253 | if (dev_self[i]) |
| 254 | 254 | ali_ircc_close(dev_self[i]); |
| 255 | 255 | } |
| @@ -273,6 +273,12 @@ static int ali_ircc_open(int i, chipio_t *info) · 17 unmodified lines | ||
| 273 | 273 | int err; |
| 274 | 274 | |
| 275 | 275 | IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); |
| 276 | + | |
| 277 | + if (i >= ARRAY_SIZE(dev_self)) { | |
| 278 | + IRDA_ERROR("%s(), maximum number of supported chips reached!\n", | |
| 279 | + __FUNCTION__); | |
| 280 | + return -ENOMEM; | |
| 281 | + } | |
| 276 | 282 | |
| 277 | 283 | /* Set FIR FIFO and DMA Threshold */ |
| 278 | 284 | if ((ali_ircc_setup(info)) == -1) |
| @@ -1090,7 +1090,7 @@ static int __init irport_init(void) · 1089 unmodified lines | ||
| 1090 | 1090 | { |
| 1091 | 1091 | int i; |
| 1092 | 1092 | |
| 1093 | − for (i=0; (io[i] < 2000) && (i < 4); i++) { | |
| 1093 | + for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) { | |
| 1094 | 1094 | if (irport_open(i, io[i], irq[i]) != NULL) |
| 1095 | 1095 | return 0; |
| 1096 | 1096 | } |
| @@ -1112,7 +1112,7 @@ static void __exit irport_cleanup(void) · 15 unmodified lines | ||
| 1112 | 1112 | |
| 1113 | 1113 | IRDA_DEBUG( 4, "%s()\n", __FUNCTION__); |
| 1114 | 1114 | |
| 1115 | − for (i=0; i < 4; i++) { | |
| 1115 | + for (i=0; i < ARRAY_SIZE(dev_self); i++) { | |
| 1116 | 1116 | if (dev_self[i]) |
| 1117 | 1117 | irport_close(dev_self[i]); |
| 1118 | 1118 | } |
| @@ -279,7 +279,7 @@ static void via_ircc_clean(void) · 278 unmodified lines | ||
| 279 | 279 | |
| 280 | 280 | IRDA_DEBUG(3, "%s()\n", __FUNCTION__); |
| 281 | 281 | |
| 282 | − for (i=0; i < 4; i++) { | |
| 282 | + for (i=0; i < ARRAY_SIZE(dev_self); i++) { | |
| 283 | 283 | if (dev_self[i]) |
| 284 | 284 | via_ircc_close(dev_self[i]); |
| 285 | 285 | } |
| @@ -327,6 +327,9 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) · 41 unmodified lines | ||
| 327 | 327 | |
| 328 | 328 | IRDA_DEBUG(3, "%s()\n", __FUNCTION__); |
| 329 | 329 | |
| 330 | + if (i >= ARRAY_SIZE(dev_self)) | |
| 331 | + return -ENOMEM; | |
| 332 | + | |
| 330 | 333 | /* Allocate new instance of the driver */ |
| 331 | 334 | dev = alloc_irdadev(sizeof(struct via_ircc_cb)); |
| 332 | 335 | if (dev == NULL) |
| @@ -117,7 +117,7 @@ static int __init w83977af_init(void) · 116 unmodified lines | ||
| 117 | 117 | |
| 118 | 118 | IRDA_DEBUG(0, "%s()\n", __FUNCTION__ ); |
| 119 | 119 | |
| 120 | − for (i=0; (io[i] < 2000) && (i < 4); i++) { | |
| 120 | + for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) { | |
| 121 | 121 | if (w83977af_open(i, io[i], irq[i], dma[i]) == 0) |
| 122 | 122 | return 0; |
| 123 | 123 | } |
| @@ -136,7 +136,7 @@ static void __exit w83977af_cleanup(void) · 12 unmodified lines | ||
| 136 | 136 | |
| 137 | 137 | IRDA_DEBUG(4, "%s()\n", __FUNCTION__ ); |
| 138 | 138 | |
| 139 | − for (i=0; i < 4; i++) { | |
| 139 | + for (i=0; i < ARRAY_SIZE(dev_self); i++) { | |
| 140 | 140 | if (dev_self[i]) |
| 141 | 141 | w83977af_close(dev_self[i]); |
| 142 | 142 | } |
| @@ -1232,7 +1232,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb) · 1231 unmodified lines | ||
| 1232 | 1232 | unsigned int i; |
| 1233 | 1233 | uint8_t css, cso; |
| 1234 | 1234 | |
| 1235 | − if(likely(skb->ip_summed == CHECKSUM_HW)) { | |
| 1235 | + if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) { | |
| 1236 | 1236 | css = skb->h.raw - skb->data; |
| 1237 | 1237 | cso = (skb->h.raw + skb->csum) - skb->data; |
| 1238 | 1238 | |
| @@ -1147,7 +1147,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, · 1146 unmodified lines | ||
| 1147 | 1147 | desc->byte_cnt = length; |
| 1148 | 1148 | desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); |
| 1149 | 1149 | |
| 1150 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 1150 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 1151 | 1151 | BUG_ON(skb->protocol != ETH_P_IP); |
| 1152 | 1152 | |
| 1153 | 1153 | cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM | |
| @@ -930,7 +930,7 @@ static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum) · 929 unmodified lines | ||
| 930 | 930 | (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) || |
| 931 | 931 | vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) { |
| 932 | 932 | skb->csum = hw_csum; |
| 933 | − skb->ip_summed = CHECKSUM_HW; | |
| 933 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 934 | 934 | } |
| 935 | 935 | } |
| 936 | 936 | |
| @@ -973,7 +973,7 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, · 36 unmodified lines | ||
| 973 | 973 | if ((skb->protocol == ntohs(ETH_P_IP)) || |
| 974 | 974 | (skb->protocol == ntohs(ETH_P_IPV6))) { |
| 975 | 975 | skb->csum = ntohs((u16) csum); |
| 976 | − skb->ip_summed = CHECKSUM_HW; | |
| 976 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 977 | 977 | } else |
| 978 | 978 | myri10ge_vlan_ip_csum(skb, ntohs((u16) csum)); |
| 979 | 979 | } |
| @@ -1897,13 +1897,13 @@ again: · 917 unmodified lines | ||
| 1897 | 1897 | pseudo_hdr_offset = 0; |
| 1898 | 1898 | odd_flag = 0; |
| 1899 | 1899 | flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST); |
| 1900 | − if (likely(skb->ip_summed == CHECKSUM_HW)) { | |
| 1900 | + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { | |
| 1901 | 1901 | cksum_offset = (skb->h.raw - skb->data); |
| 1902 | 1902 | pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data; |
| 1903 | 1903 | /* If the headers are excessively large, then we must |
| 1904 | 1904 | * fall back to a software checksum */ |
| 1905 | 1905 | if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { |
| 1906 | − if (skb_checksum_help(skb, 0)) | |
| 1906 | + if (skb_checksum_help(skb)) | |
| 1907 | 1907 | goto drop; |
| 1908 | 1908 | cksum_offset = 0; |
| 1909 | 1909 | pseudo_hdr_offset = 0; |
| @@ -1153,7 +1153,7 @@ again: · 1152 unmodified lines | ||
| 1153 | 1153 | if (!nr_frags) |
| 1154 | 1154 | frag = NULL; |
| 1155 | 1155 | extsts = 0; |
| 1156 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 1156 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 1157 | 1157 | extsts |= EXTSTS_IPPKT; |
| 1158 | 1158 | if (IPPROTO_TCP == skb->nh.iph->protocol) |
| 1159 | 1159 | extsts |= EXTSTS_TCPPKT; |
| @@ -2169,7 +2169,7 @@ static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) · 2168 unmodified lines | ||
| 2169 | 2169 | if (mss) |
| 2170 | 2170 | return LargeSend | ((mss & MSSMask) << MSSShift); |
| 2171 | 2171 | } |
| 2172 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 2172 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 2173 | 2173 | const struct iphdr *ip = skb->nh.iph; |
| 2174 | 2174 | |
| 2175 | 2175 | if (ip->protocol == IPPROTO_TCP) |
| @@ -3893,7 +3893,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) · 3892 unmodified lines | ||
| 3893 | 3893 | txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb)); |
| 3894 | 3894 | } |
| 3895 | 3895 | #endif |
| 3896 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 3896 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 3897 | 3897 | txdp->Control_2 |= |
| 3898 | 3898 | (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN | |
| 3899 | 3899 | TXD_TX_CKO_UDP_EN); |
| @@ -1559,7 +1559,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ · 1558 unmodified lines | ||
| 1559 | 1559 | pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); |
| 1560 | 1560 | pTxd->pMBuf = pMessage; |
| 1561 | 1561 | |
| 1562 | − if (pMessage->ip_summed == CHECKSUM_HW) { | |
| 1562 | + if (pMessage->ip_summed == CHECKSUM_PARTIAL) { | |
| 1563 | 1563 | u16 hdrlen = pMessage->h.raw - pMessage->data; |
| 1564 | 1564 | u16 offset = hdrlen + pMessage->csum; |
| 1565 | 1565 | |
| @@ -1678,7 +1678,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ · 112 unmodified lines | ||
| 1678 | 1678 | /* |
| 1679 | 1679 | ** Does the HW need to evaluate checksum for TCP or UDP packets? |
| 1680 | 1680 | */ |
| 1681 | − if (pMessage->ip_summed == CHECKSUM_HW) { | |
| 1681 | + if (pMessage->ip_summed == CHECKSUM_PARTIAL) { | |
| 1682 | 1682 | u16 hdrlen = pMessage->h.raw - pMessage->data; |
| 1683 | 1683 | u16 offset = hdrlen + pMessage->csum; |
| 1684 | 1684 | |
| @@ -2158,7 +2158,7 @@ rx_start: · 473 unmodified lines | ||
| 2158 | 2158 | |
| 2159 | 2159 | #ifdef USE_SK_RX_CHECKSUM |
| 2160 | 2160 | pMsg->csum = pRxd->TcpSums & 0xffff; |
| 2161 | − pMsg->ip_summed = CHECKSUM_HW; | |
| 2161 | + pMsg->ip_summed = CHECKSUM_COMPLETE; | |
| 2162 | 2162 | #else |
| 2163 | 2163 | pMsg->ip_summed = CHECKSUM_NONE; |
| 2164 | 2164 | #endif |
| @@ -2338,7 +2338,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) · 2337 unmodified lines | ||
| 2338 | 2338 | td->dma_lo = map; |
| 2339 | 2339 | td->dma_hi = map >> 32; |
| 2340 | 2340 | |
| 2341 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 2341 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 2342 | 2342 | int offset = skb->h.raw - skb->data; |
| 2343 | 2343 | |
| 2344 | 2344 | /* This seems backwards, but it is what the sk98lin |
| @@ -2642,7 +2642,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, · 297 unmodified lines | ||
| 2642 | 2642 | skb->dev = skge->netdev; |
| 2643 | 2643 | if (skge->rx_csum) { |
| 2644 | 2644 | skb->csum = csum; |
| 2645 | − skb->ip_summed = CHECKSUM_HW; | |
| 2645 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 2646 | 2646 | } |
| 2647 | 2647 | |
| 2648 | 2648 | skb->protocol = eth_type_trans(skb, skge->netdev); |
| @@ -1163,7 +1163,7 @@ static unsigned tx_le_req(const struct sk_buff *skb) · 1162 unmodified lines | ||
| 1163 | 1163 | if (skb_is_gso(skb)) |
| 1164 | 1164 | ++count; |
| 1165 | 1165 | |
| 1166 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 1166 | + if (skb->ip_summed == CHECKSUM_PARTIAL) | |
| 1167 | 1167 | ++count; |
| 1168 | 1168 | |
| 1169 | 1169 | return count; |
| @@ -1272,7 +1272,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) · 102 unmodified lines | ||
| 1272 | 1272 | #endif |
| 1273 | 1273 | |
| 1274 | 1274 | /* Handle TCP checksum offload */ |
| 1275 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 1275 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 1276 | 1276 | u16 hdr = skb->h.raw - skb->data; |
| 1277 | 1277 | u16 offset = hdr + skb->csum; |
| 1278 | 1278 | |
| @@ -2000,7 +2000,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) · 721 unmodified lines | ||
| 2000 | 2000 | #endif |
| 2001 | 2001 | case OP_RXCHKS: |
| 2002 | 2002 | skb = sky2->rx_ring[sky2->rx_next].skb; |
| 2003 | − skb->ip_summed = CHECKSUM_HW; | |
| 2003 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 2004 | 2004 | skb->csum = le16_to_cpu(status); |
| 2005 | 2005 | break; |
| 2006 | 2006 | |
| @@ -1230,7 +1230,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) · 1229 unmodified lines | ||
| 1230 | 1230 | } |
| 1231 | 1231 | |
| 1232 | 1232 | #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE) |
| 1233 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 1233 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 1234 | 1234 | if (skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK)) |
| 1235 | 1235 | return NETDEV_TX_OK; |
| 1236 | 1236 | } |
| @@ -1252,7 +1252,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) · 15 unmodified lines | ||
| 1252 | 1252 | status |= TxDescIntr; |
| 1253 | 1253 | np->reap_tx = 0; |
| 1254 | 1254 | } |
| 1255 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 1255 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 1256 | 1256 | status |= TxCalTCP; |
| 1257 | 1257 | np->stats.tx_compressed++; |
| 1258 | 1258 | } |
| @@ -1499,7 +1499,7 @@ static int __netdev_rx(struct net_device *dev, int *quota) · 240 unmodified lines | ||
| 1499 | 1499 | * Until then, the printk stays. :-) -Ion |
| 1500 | 1500 | */ |
| 1501 | 1501 | else if (le16_to_cpu(desc->status2) & 0x0040) { |
| 1502 | − skb->ip_summed = CHECKSUM_HW; | |
| 1502 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 1503 | 1503 | skb->csum = le16_to_cpu(desc->csum); |
| 1504 | 1504 | printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2)); |
| 1505 | 1505 | } |
| @@ -855,7 +855,7 @@ static int gem_rx(struct gem *gp, int work_to_do) · 854 unmodified lines | ||
| 855 | 855 | } |
| 856 | 856 | |
| 857 | 857 | skb->csum = ntohs((status & RXDCTRL_TCPCSUM) ^ 0xffff); |
| 858 | − skb->ip_summed = CHECKSUM_HW; | |
| 858 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 859 | 859 | skb->protocol = eth_type_trans(skb, gp->dev); |
| 860 | 860 | |
| 861 | 861 | netif_receive_skb(skb); |
| @@ -1026,7 +1026,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) · 164 unmodified lines | ||
| 1026 | 1026 | unsigned long flags; |
| 1027 | 1027 | |
| 1028 | 1028 | ctrl = 0; |
| 1029 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 1029 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 1030 | 1030 | u64 csum_start_off, csum_stuff_off; |
| 1031 | 1031 | |
| 1032 | 1032 | csum_start_off = (u64) (skb->h.raw - skb->data); |
| @@ -1207,7 +1207,7 @@ static void happy_meal_transceiver_check(struct happy_meal *hp, void __iomem *tr · 1206 unmodified lines | ||
| 1207 | 1207 | * flags, thus: |
| 1208 | 1208 | * |
| 1209 | 1209 | * skb->csum = rxd->rx_flags & 0xffff; |
| 1210 | − * skb->ip_summed = CHECKSUM_HW; | |
| 1210 | + * skb->ip_summed = CHECKSUM_COMPLETE; | |
| 1211 | 1211 | * |
| 1212 | 1212 | * before sending off the skb to the protocols, and we are good as gold. |
| 1213 | 1213 | */ |
| @@ -2074,7 +2074,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) · 860 unmodified lines | ||
| 2074 | 2074 | |
| 2075 | 2075 | /* This card is _fucking_ hot... */ |
| 2076 | 2076 | skb->csum = ntohs(csum ^ 0xffff); |
| 2077 | − skb->ip_summed = CHECKSUM_HW; | |
| 2077 | + skb->ip_summed = CHECKSUM_COMPLETE; | |
| 2078 | 2078 | |
| 2079 | 2079 | RXD(("len=%d csum=%4x]", len, csum)); |
| 2080 | 2080 | skb->protocol = eth_type_trans(skb, dev); |
| @@ -2268,7 +2268,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) · 187 unmodified lines | ||
| 2268 | 2268 | u32 tx_flags; |
| 2269 | 2269 | |
| 2270 | 2270 | tx_flags = TXFLAG_OWN; |
| 2271 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 2271 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 2272 | 2272 | u32 csum_start_off, csum_stuff_off; |
| 2273 | 2273 | |
| 2274 | 2274 | csum_start_off = (u32) (skb->h.raw - skb->data); |
| @@ -149,122 +149,67 @@ module_param(tg3_debug, int, 0); · 148 unmodified lines | ||
| 149 | 149 | MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); |
| 150 | 150 | |
| 151 | 151 | static struct pci_device_id tg3_pci_tbl[] = { |
| 152 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700, | |
| 153 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 154 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701, | |
| 155 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 156 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702, | |
| 157 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 158 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703, | |
| 159 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 160 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704, | |
| 161 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 162 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE, | |
| 163 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 164 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705, | |
| 165 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 166 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2, | |
| 167 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 168 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M, | |
| 169 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 170 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2, | |
| 171 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 172 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X, | |
| 173 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 174 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X, | |
| 175 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 176 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S, | |
| 177 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 178 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3, | |
| 179 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 180 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3, | |
| 181 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 182 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782, | |
| 183 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 184 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788, | |
| 185 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 186 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789, | |
| 187 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 188 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901, | |
| 189 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 190 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2, | |
| 191 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 192 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2, | |
| 193 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 194 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F, | |
| 195 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 196 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720, | |
| 197 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 198 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721, | |
| 199 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 200 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750, | |
| 201 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 202 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751, | |
| 203 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 204 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M, | |
| 205 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 206 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M, | |
| 207 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 208 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, | |
| 209 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 210 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752, | |
| 211 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 212 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M, | |
| 213 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 214 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, | |
| 215 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 216 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M, | |
| 217 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 218 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, | |
| 219 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 220 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754, | |
| 221 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 222 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, | |
| 223 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 224 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755, | |
| 225 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 226 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M, | |
| 227 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 228 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786, | |
| 229 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 230 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, | |
| 231 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 232 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, | |
| 233 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 234 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, | |
| 235 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 236 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S, | |
| 237 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 238 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715, | |
| 239 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 240 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S, | |
| 241 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 242 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, | |
| 243 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 244 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S, | |
| 245 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 246 | − { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781, | |
| 247 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 248 | − { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, | |
| 249 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 250 | − { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, | |
| 251 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 252 | − { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000, | |
| 253 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 254 | − { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001, | |
| 255 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 256 | − { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003, | |
| 257 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 258 | − { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100, | |
| 259 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 260 | − { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3, | |
| 261 | − PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
| 262 | − { 0, } | |
| 152 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)}, | |
| 153 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)}, | |
| 154 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)}, | |
| 155 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703)}, | |
| 156 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704)}, | |
| 157 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE)}, | |
| 158 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705)}, | |
| 159 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2)}, | |
| 160 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M)}, | |
| 161 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2)}, | |
| 162 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X)}, | |
| 163 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X)}, | |
| 164 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S)}, | |
| 165 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3)}, | |
| 166 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3)}, | |
| 167 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)}, | |
| 168 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)}, | |
| 169 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)}, | |
| 170 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)}, | |
| 171 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)}, | |
| 172 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)}, | |
| 173 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)}, | |
| 174 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)}, | |
| 175 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)}, | |
| 176 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)}, | |
| 177 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)}, | |
| 178 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)}, | |
| 179 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)}, | |
| 180 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)}, | |
| 181 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)}, | |
| 182 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)}, | |
| 183 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)}, | |
| 184 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)}, | |
| 185 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)}, | |
| 186 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)}, | |
| 187 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)}, | |
| 188 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)}, | |
| 189 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)}, | |
| 190 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)}, | |
| 191 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)}, | |
| 192 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)}, | |
| 193 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)}, | |
| 194 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)}, | |
| 195 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)}, | |
| 196 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S)}, | |
| 197 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)}, | |
| 198 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)}, | |
| 199 | + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)}, | |
| 200 | + {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, | |
| 201 | + {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, | |
| 202 | + {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, | |
| 203 | + {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001)}, | |
| 204 | + {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003)}, | |
| 205 | + {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100)}, | |
| 206 | + {PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3)}, | |
| 207 | + {} | |
| 263 | 208 | }; |
| 264 | 209 | |
| 265 | 210 | MODULE_DEVICE_TABLE(pci, tg3_pci_tbl); |
| 266 | 211 | |
| 267 | −static struct { | |
| 212 | +static const struct { | |
| 268 | 213 | const char string[ETH_GSTRING_LEN]; |
| 269 | 214 | } ethtool_stats_keys[TG3_NUM_STATS] = { |
| 270 | 215 | { "rx_octets" }, |
| @@ -345,7 +290,7 @@ static struct { · 74 unmodified lines | ||
| 345 | 290 | { "nic_tx_threshold_hit" } |
| 346 | 291 | }; |
| 347 | 292 | |
| 348 | −static struct { | |
| 293 | +static const struct { | |
| 349 | 294 | const char string[ETH_GSTRING_LEN]; |
| 350 | 295 | } ethtool_test_keys[TG3_NUM_TEST] = { |
| 351 | 296 | { "nvram test (online) " }, |
| @@ -3851,11 +3796,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) · 3499 unmodified lines | ||
| 3851 | 3796 | skb->h.th->check = 0; |
| 3852 | 3797 | |
| 3853 | 3798 | } |
| 3854 | − else if (skb->ip_summed == CHECKSUM_HW) | |
| 3799 | + else if (skb->ip_summed == CHECKSUM_PARTIAL) | |
| 3855 | 3800 | base_flags |= TXD_FLAG_TCPUDP_CSUM; |
| 3856 | 3801 | #else |
| 3857 | 3802 | mss = 0; |
| 3858 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 3803 | + if (skb->ip_summed == CHECKSUM_PARTIAL) | |
| 3859 | 3804 | base_flags |= TXD_FLAG_TCPUDP_CSUM; |
| 3860 | 3805 | #endif |
| 3861 | 3806 | #if TG3_VLAN_TAG_USED |
| @@ -3981,7 +3926,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) · 119 unmodified lines | ||
| 3981 | 3926 | |
| 3982 | 3927 | entry = tp->tx_prod; |
| 3983 | 3928 | base_flags = 0; |
| 3984 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 3929 | + if (skb->ip_summed == CHECKSUM_PARTIAL) | |
| 3985 | 3930 | base_flags |= TXD_FLAG_TCPUDP_CSUM; |
| 3986 | 3931 | #if TG3_TSO_SUPPORT != 0 |
| 3987 | 3932 | mss = 0; |
| @@ -4969,7 +4914,7 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent) · 981 unmodified lines | ||
| 4969 | 4914 | #define TG3_FW_BSS_ADDR 0x08000a70 |
| 4970 | 4915 | #define TG3_FW_BSS_LEN 0x10 |
| 4971 | 4916 | |
| 4972 | −static u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { | |
| 4917 | +static const u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { | |
| 4973 | 4918 | 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800, |
| 4974 | 4919 | 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000, |
| 4975 | 4920 | 0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034, |
| @@ -5063,7 +5008,7 @@ static u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { · 87 unmodified lines | ||
| 5063 | 5008 | 0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000 |
| 5064 | 5009 | }; |
| 5065 | 5010 | |
| 5066 | −static u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = { | |
| 5011 | +static const u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = { | |
| 5067 | 5012 | 0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430, |
| 5068 | 5013 | 0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74, |
| 5069 | 5014 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, |
| @@ -5128,13 +5073,13 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) · 58 unmodified lines | ||
| 5128 | 5073 | struct fw_info { |
| 5129 | 5074 | unsigned int text_base; |
| 5130 | 5075 | unsigned int text_len; |
| 5131 | − u32 *text_data; | |
| 5076 | + const u32 *text_data; | |
| 5132 | 5077 | unsigned int rodata_base; |
| 5133 | 5078 | unsigned int rodata_len; |
| 5134 | − u32 *rodata_data; | |
| 5079 | + const u32 *rodata_data; | |
| 5135 | 5080 | unsigned int data_base; |
| 5136 | 5081 | unsigned int data_len; |
| 5137 | − u32 *data_data; | |
| 5082 | + const u32 *data_data; | |
| 5138 | 5083 | }; |
| 5139 | 5084 | |
| 5140 | 5085 | /* tp->lock is held. */ |
| @@ -5266,7 +5211,7 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) · 125 unmodified lines | ||
| 5266 | 5211 | #define TG3_TSO_FW_BSS_ADDR 0x08001b80 |
| 5267 | 5212 | #define TG3_TSO_FW_BSS_LEN 0x894 |
| 5268 | 5213 | |
| 5269 | −static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { | |
| 5214 | +static const u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { | |
| 5270 | 5215 | 0x0e000003, 0x00000000, 0x08001b24, 0x00000000, 0x10000003, 0x00000000, |
| 5271 | 5216 | 0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800, |
| 5272 | 5217 | 0x26100000, 0x0e000010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, |
| @@ -5553,7 +5498,7 @@ static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { · 280 unmodified lines | ||
| 5553 | 5498 | 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000, |
| 5554 | 5499 | }; |
| 5555 | 5500 | |
| 5556 | −static u32 tg3TsoFwRodata[] = { | |
| 5501 | +static const u32 tg3TsoFwRodata[] = { | |
| 5557 | 5502 | 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, |
| 5558 | 5503 | 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f, |
| 5559 | 5504 | 0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, |
| @@ -5561,7 +5506,7 @@ static u32 tg3TsoFwRodata[] = { · 1 unmodified line | ||
| 5561 | 5506 | 0x00000000, |
| 5562 | 5507 | }; |
| 5563 | 5508 | |
| 5564 | −static u32 tg3TsoFwData[] = { | |
| 5509 | +static const u32 tg3TsoFwData[] = { | |
| 5565 | 5510 | 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000, |
| 5566 | 5511 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
| 5567 | 5512 | 0x00000000, |
| @@ -5583,7 +5528,7 @@ static u32 tg3TsoFwData[] = { · 15 unmodified lines | ||
| 5583 | 5528 | #define TG3_TSO5_FW_BSS_ADDR 0x00010f50 |
| 5584 | 5529 | #define TG3_TSO5_FW_BSS_LEN 0x88 |
| 5585 | 5530 | |
| 5586 | −static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { | |
| 5531 | +static const u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { | |
| 5587 | 5532 | 0x0c004003, 0x00000000, 0x00010f04, 0x00000000, 0x10000003, 0x00000000, |
| 5588 | 5533 | 0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001, |
| 5589 | 5534 | 0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, |
| @@ -5742,14 +5687,14 @@ static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { · 152 unmodified lines | ||
| 5742 | 5687 | 0x00000000, 0x00000000, 0x00000000, |
| 5743 | 5688 | }; |
| 5744 | 5689 | |
| 5745 | −static u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { | |
| 5690 | +static const u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { | |
| 5746 | 5691 | 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, |
| 5747 | 5692 | 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, |
| 5748 | 5693 | 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, |
| 5749 | 5694 | 0x00000000, 0x00000000, 0x00000000, |
| 5750 | 5695 | }; |
| 5751 | 5696 | |
| 5752 | −static u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { | |
| 5697 | +static const u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { | |
| 5753 | 5698 | 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000, |
| 5754 | 5699 | 0x00000000, 0x00000000, 0x00000000, |
| 5755 | 5700 | }; |
| @@ -830,7 +830,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) · 829 unmodified lines | ||
| 830 | 830 | first_txd->addrHi = (u64)((unsigned long) skb) >> 32; |
| 831 | 831 | first_txd->processFlags = 0; |
| 832 | 832 | |
| 833 | − if(skb->ip_summed == CHECKSUM_HW) { | |
| 833 | + if(skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 834 | 834 | /* The 3XP will figure out if this is UDP/TCP */ |
| 835 | 835 | first_txd->processFlags |= TYPHOON_TX_PF_TCP_CHKSUM; |
| 836 | 836 | first_txd->processFlags |= TYPHOON_TX_PF_UDP_CHKSUM; |
| @@ -1230,7 +1230,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) · 1229 unmodified lines | ||
| 1230 | 1230 | rp->tx_skbuff[entry] = skb; |
| 1231 | 1231 | |
| 1232 | 1232 | if ((rp->quirks & rqRhineI) && |
| 1233 | − (((unsigned long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW)) { | |
| 1233 | + (((unsigned long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_PARTIAL)) { | |
| 1234 | 1234 | /* Must use alignment buffer. */ |
| 1235 | 1235 | if (skb->len > PKT_BUF_SZ) { |
| 1236 | 1236 | /* packet too long, drop it */ |
| @@ -2002,7 +2002,7 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) · 2001 unmodified lines | ||
| 2002 | 2002 | * Handle hardware checksum |
| 2003 | 2003 | */ |
| 2004 | 2004 | if ((vptr->flags & VELOCITY_FLAGS_TX_CSUM) |
| 2005 | − && (skb->ip_summed == CHECKSUM_HW)) { | |
| 2005 | + && (skb->ip_summed == CHECKSUM_PARTIAL)) { | |
| 2006 | 2006 | struct iphdr *ip = skb->nh.iph; |
| 2007 | 2007 | if (ip->protocol == IPPROTO_TCP) |
| 2008 | 2008 | td_ptr->tdesc1.TCR |= TCR0_TCPCK; |
| @@ -1826,8 +1826,8 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd) · 1825 unmodified lines | ||
| 1826 | 1826 | { |
| 1827 | 1827 | struct riva_par *par = info->par; |
| 1828 | 1828 | struct device_node *dp; |
| 1829 | − unsigned char *pedid = NULL; | |
| 1830 | − unsigned char *disptype = NULL; | |
| 1829 | + const unsigned char *pedid = NULL; | |
| 1830 | + const unsigned char *disptype = NULL; | |
| 1831 | 1831 | static char *propnames[] = { |
| 1832 | 1832 | "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL }; |
| 1833 | 1833 | int i; |
| @@ -1471,8 +1471,8 @@ config NFS_V4 · 1470 unmodified lines | ||
| 1471 | 1471 | If unsure, say N. |
| 1472 | 1472 | |
| 1473 | 1473 | config NFS_DIRECTIO |
| 1474 | − bool "Allow direct I/O on NFS files (EXPERIMENTAL)" | |
| 1475 | − depends on NFS_FS && EXPERIMENTAL | |
| 1474 | + bool "Allow direct I/O on NFS files" | |
| 1475 | + depends on NFS_FS | |
| 1476 | 1476 | help |
| 1477 | 1477 | This option enables applications to perform uncached I/O on files |
| 1478 | 1478 | in NFS file systems using the O_DIRECT open() flag. When O_DIRECT |
| @@ -828,17 +828,19 @@ void d_instantiate(struct dentry *entry, struct inode * inode) · 827 unmodified lines | ||
| 828 | 828 | * (or otherwise set) by the caller to indicate that it is now |
| 829 | 829 | * in use by the dcache. |
| 830 | 830 | */ |
| 831 | −struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) | |
| 831 | +static struct dentry *__d_instantiate_unique(struct dentry *entry, | |
| 832 | + struct inode *inode) | |
| 832 | 833 | { |
| 833 | 834 | struct dentry *alias; |
| 834 | 835 | int len = entry->d_name.len; |
| 835 | 836 | const char *name = entry->d_name.name; |
| 836 | 837 | unsigned int hash = entry->d_name.hash; |
| 837 | 838 | |
| 838 | − BUG_ON(!list_empty(&entry->d_alias)); | |
| 839 | − spin_lock(&dcache_lock); | |
| 840 | − if (!inode) | |
| 841 | − goto do_negative; | |
| 839 | + if (!inode) { | |
| 840 | + entry->d_inode = NULL; | |
| 841 | + return NULL; | |
| 842 | + } | |
| 843 | + | |
| 842 | 844 | list_for_each_entry(alias, &inode->i_dentry, d_alias) { |
| 843 | 845 | struct qstr *qstr = &alias->d_name; |
| 844 | 846 | |
| @@ -851,19 +853,35 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) · 6 unmodified lines | ||
| 851 | 853 | if (memcmp(qstr->name, name, len)) |
| 852 | 854 | continue; |
| 853 | 855 | dget_locked(alias); |
| 854 | − spin_unlock(&dcache_lock); | |
| 855 | − BUG_ON(!d_unhashed(alias)); | |
| 856 | − iput(inode); | |
| 857 | 856 | return alias; |
| 858 | 857 | } |
| 858 | + | |
| 859 | 859 | list_add(&entry->d_alias, &inode->i_dentry); |
| 860 | −do_negative: | |
| 861 | 860 | entry->d_inode = inode; |
| 862 | 861 | fsnotify_d_instantiate(entry, inode); |
| 863 | − spin_unlock(&dcache_lock); | |
| 864 | − security_d_instantiate(entry, inode); | |
| 865 | 862 | return NULL; |
| 866 | 863 | } |
| 864 | + | |
| 865 | +struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) | |
| 866 | +{ | |
| 867 | + struct dentry *result; | |
| 868 | + | |
| 869 | + BUG_ON(!list_empty(&entry->d_alias)); | |
| 870 | + | |
| 871 | + spin_lock(&dcache_lock); | |
| 872 | + result = __d_instantiate_unique(entry, inode); | |
| 873 | + spin_unlock(&dcache_lock); | |
| 874 | + | |
| 875 | + if (!result) { | |
| 876 | + security_d_instantiate(entry, inode); | |
| 877 | + return NULL; | |
| 878 | + } | |
| 879 | + | |
| 880 | + BUG_ON(!d_unhashed(result)); | |
| 881 | + iput(inode); | |
| 882 | + return result; | |
| 883 | +} | |
| 884 | + | |
| 867 | 885 | EXPORT_SYMBOL(d_instantiate_unique); |
| 868 | 886 | |
| 869 | 887 | /** |
| @@ -1235,6 +1253,11 @@ static void __d_rehash(struct dentry * entry, struct hlist_head *list) · 365 unmodified lines | ||
| 1235 | 1253 | hlist_add_head_rcu(&entry->d_hash, list); |
| 1236 | 1254 | } |
| 1237 | 1255 | |
| 1256 | +static void _d_rehash(struct dentry * entry) | |
| 1257 | +{ | |
| 1258 | + __d_rehash(entry, d_hash(entry->d_parent, entry->d_name.hash)); | |
| 1259 | +} | |
| 1260 | + | |
| 1238 | 1261 | /** |
| 1239 | 1262 | * d_rehash - add an entry back to the hash |
| 1240 | 1263 | * @entry: dentry to add to the hash |
| @@ -1244,11 +1267,9 @@ static void __d_rehash(struct dentry * entry, struct hlist_head *list) · 3 unmodified lines | ||
| 1244 | 1267 | |
| 1245 | 1268 | void d_rehash(struct dentry * entry) |
| 1246 | 1269 | { |
| 1247 | − struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash); | |
| 1248 | − | |
| 1249 | 1270 | spin_lock(&dcache_lock); |
| 1250 | 1271 | spin_lock(&entry->d_lock); |
| 1251 | − __d_rehash(entry, list); | |
| 1272 | + _d_rehash(entry); | |
| 1252 | 1273 | spin_unlock(&entry->d_lock); |
| 1253 | 1274 | spin_unlock(&dcache_lock); |
| 1254 | 1275 | } |
| @@ -1386,6 +1407,120 @@ already_unhashed: · 131 unmodified lines | ||
| 1386 | 1407 | spin_unlock(&dcache_lock); |
| 1387 | 1408 | } |
| 1388 | 1409 | |
| 1410 | +/* | |
| 1411 | + * Prepare an anonymous dentry for life in the superblock's dentry tree as a | |
| 1412 | + * named dentry in place of the dentry to be replaced. | |
| 1413 | + */ | |
| 1414 | +static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) | |
| 1415 | +{ | |
| 1416 | + struct dentry *dparent, *aparent; | |
| 1417 | + | |
| 1418 | + switch_names(dentry, anon); | |
| 1419 | + do_switch(dentry->d_name.len, anon->d_name.len); | |
| 1420 | + do_switch(dentry->d_name.hash, anon->d_name.hash); | |
| 1421 | + | |
| 1422 | + dparent = dentry->d_parent; | |
| 1423 | + aparent = anon->d_parent; | |
| 1424 | + | |
| 1425 | + dentry->d_parent = (aparent == anon) ? dentry : aparent; | |
| 1426 | + list_del(&dentry->d_u.d_child); | |
| 1427 | + if (!IS_ROOT(dentry)) | |
| 1428 | + list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); | |
| 1429 | + else | |
| 1430 | + INIT_LIST_HEAD(&dentry->d_u.d_child); | |
| 1431 | + | |
| 1432 | + anon->d_parent = (dparent == dentry) ? anon : dparent; | |
| 1433 | + list_del(&anon->d_u.d_child); | |
| 1434 | + if (!IS_ROOT(anon)) | |
| 1435 | + list_add(&anon->d_u.d_child, &anon->d_parent->d_subdirs); | |
| 1436 | + else | |
| 1437 | + INIT_LIST_HEAD(&anon->d_u.d_child); | |
| 1438 | + | |
| 1439 | + anon->d_flags &= ~DCACHE_DISCONNECTED; | |
| 1440 | +} | |
| 1441 | + | |
| 1442 | +/** | |
| 1443 | + * d_materialise_unique - introduce an inode into the tree | |
| 1444 | + * @dentry: candidate dentry | |
| 1445 | + * @inode: inode to bind to the dentry, to which aliases may be attached | |
| 1446 | + * | |
| 1447 | + * Introduces an dentry into the tree, substituting an extant disconnected | |
| 1448 | + * root directory alias in its place if there is one | |
| 1449 | + */ | |
| 1450 | +struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |
| 1451 | +{ | |
| 1452 | + struct dentry *alias, *actual; | |
| 1453 | + | |
| 1454 | + BUG_ON(!d_unhashed(dentry)); | |
| 1455 | + | |
| 1456 | + spin_lock(&dcache_lock); | |
| 1457 | + | |
| 1458 | + if (!inode) { | |
| 1459 | + actual = dentry; | |
| 1460 | + dentry->d_inode = NULL; | |
| 1461 | + goto found_lock; | |
| 1462 | + } | |
| 1463 | + | |
| 1464 | + /* See if a disconnected directory already exists as an anonymous root | |
| 1465 | + * that we should splice into the tree instead */ | |
| 1466 | + if (S_ISDIR(inode->i_mode) && (alias = __d_find_alias(inode, 1))) { | |
| 1467 | + spin_lock(&alias->d_lock); | |
| 1468 | + | |
| 1469 | + /* Is this a mountpoint that we could splice into our tree? */ | |
| 1470 | + if (IS_ROOT(alias)) | |
| 1471 | + goto connect_mountpoint; | |
| 1472 | + | |
| 1473 | + if (alias->d_name.len == dentry->d_name.len && | |
| 1474 | + alias->d_parent == dentry->d_parent && | |
| 1475 | + memcmp(alias->d_name.name, | |
| 1476 | + dentry->d_name.name, | |
| 1477 | + dentry->d_name.len) == 0) | |
| 1478 | + goto replace_with_alias; | |
| 1479 | + | |
| 1480 | + spin_unlock(&alias->d_lock); | |
| 1481 | + | |
| 1482 | + /* Doh! Seem to be aliasing directories for some reason... */ | |
| 1483 | + dput(alias); | |
| 1484 | + } | |
| 1485 | + | |
| 1486 | + /* Add a unique reference */ | |
| 1487 | + actual = __d_instantiate_unique(dentry, inode); | |
| 1488 | + if (!actual) | |
| 1489 | + actual = dentry; | |
| 1490 | + else if (unlikely(!d_unhashed(actual))) | |
| 1491 | + goto shouldnt_be_hashed; | |
| 1492 | + | |
| 1493 | +found_lock: | |
| 1494 | + spin_lock(&actual->d_lock); | |
| 1495 | +found: | |
| 1496 | + _d_rehash(actual); | |
| 1497 | + spin_unlock(&actual->d_lock); | |
| 1498 | + spin_unlock(&dcache_lock); | |
| 1499 | + | |
| 1500 | + if (actual == dentry) { | |
| 1501 | + security_d_instantiate(dentry, inode); | |
| 1502 | + return NULL; | |
| 1503 | + } | |
| 1504 | + | |
| 1505 | + iput(inode); | |
| 1506 | + return actual; | |
| 1507 | + | |
| 1508 | + /* Convert the anonymous/root alias into an ordinary dentry */ | |
| 1509 | +connect_mountpoint: | |
| 1510 | + __d_materialise_dentry(dentry, alias); | |
| 1511 | + | |
| 1512 | + /* Replace the candidate dentry with the alias in the tree */ | |
| 1513 | +replace_with_alias: | |
| 1514 | + __d_drop(alias); | |
| 1515 | + actual = alias; | |
| 1516 | + goto found; | |
| 1517 | + | |
| 1518 | +shouldnt_be_hashed: | |
| 1519 | + spin_unlock(&dcache_lock); | |
| 1520 | + BUG(); | |
| 1521 | + goto shouldnt_be_hashed; | |
| 1522 | +} | |
| 1523 | + | |
| 1389 | 1524 | /** |
| 1390 | 1525 | * d_path - return the path of a dentry |
| 1391 | 1526 | * @dentry: dentry to report |
| @@ -1784,6 +1919,7 @@ EXPORT_SYMBOL(d_instantiate); · 392 unmodified lines | ||
| 1784 | 1919 | EXPORT_SYMBOL(d_invalidate); |
| 1785 | 1920 | EXPORT_SYMBOL(d_lookup); |
| 1786 | 1921 | EXPORT_SYMBOL(d_move); |
| 1922 | +EXPORT_SYMBOL_GPL(d_materialise_unique); | |
| 1787 | 1923 | EXPORT_SYMBOL(d_path); |
| 1788 | 1924 | EXPORT_SYMBOL(d_prune_aliases); |
| 1789 | 1925 | EXPORT_SYMBOL(d_rehash); |
| @@ -151,11 +151,13 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req) · 150 unmodified lines | ||
| 151 | 151 | int |
| 152 | 152 | nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) |
| 153 | 153 | { |
| 154 | + struct rpc_clnt *client = NFS_CLIENT(inode); | |
| 155 | + struct sockaddr_in addr; | |
| 154 | 156 | struct nlm_host *host; |
| 155 | 157 | struct nlm_rqst *call; |
| 156 | 158 | sigset_t oldset; |
| 157 | 159 | unsigned long flags; |
| 158 | − int status, proto, vers; | |
| 160 | + int status, vers; | |
| 159 | 161 | |
| 160 | 162 | vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1; |
| 161 | 163 | if (NFS_PROTO(inode)->version > 3) { |
| @@ -163,10 +165,8 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) · 1 unmodified line | ||
| 163 | 165 | return -ENOLCK; |
| 164 | 166 | } |
| 165 | 167 | |
| 166 | − /* Retrieve transport protocol from NFS client */ | |
| 167 | − proto = NFS_CLIENT(inode)->cl_xprt->prot; | |
| 168 | − | |
| 169 | − host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers); | |
| 168 | + rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr)); | |
| 169 | + host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers); | |
| 170 | 170 | if (host == NULL) |
| 171 | 171 | return -ENOLCK; |
| 172 | 172 | |
| @@ -26,7 +26,6 @@ · 25 unmodified lines | ||
| 26 | 26 | #define NLM_HOST_REBIND (60 * HZ) |
| 27 | 27 | #define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ) |
| 28 | 28 | #define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ) |
| 29 | −#define NLM_HOST_ADDR(sv) (&(sv)->s_nlmclnt->cl_xprt->addr) | |
| 30 | 29 | |
| 31 | 30 | static struct nlm_host * nlm_hosts[NLM_HOST_NRHASH]; |
| 32 | 31 | static unsigned long next_gc; |
| @@ -167,7 +166,6 @@ struct rpc_clnt * · 134 unmodified lines | ||
| 167 | 166 | nlm_bind_host(struct nlm_host *host) |
| 168 | 167 | { |
| 169 | 168 | struct rpc_clnt *clnt; |
| 170 | − struct rpc_xprt *xprt; | |
| 171 | 169 | |
| 172 | 170 | dprintk("lockd: nlm_bind_host(%08x)\n", |
| 173 | 171 | (unsigned)ntohl(host->h_addr.sin_addr.s_addr)); |
| @@ -179,7 +177,6 @@ nlm_bind_host(struct nlm_host *host) · 5 unmodified lines | ||
| 179 | 177 | * RPC rebind is required |
| 180 | 178 | */ |
| 181 | 179 | if ((clnt = host->h_rpcclnt) != NULL) { |
| 182 | − xprt = clnt->cl_xprt; | |
| 183 | 180 | if (time_after_eq(jiffies, host->h_nextrebind)) { |
| 184 | 181 | rpc_force_rebind(clnt); |
| 185 | 182 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; |
| @@ -187,31 +184,37 @@ nlm_bind_host(struct nlm_host *host) · 1 unmodified line | ||
| 187 | 184 | host->h_nextrebind - jiffies); |
| 188 | 185 | } |
| 189 | 186 | } else { |
| 190 | − xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL); | |
| 191 | − if (IS_ERR(xprt)) | |
| 192 | − goto forgetit; | |
| 193 | − | |
| 194 | − xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); | |
| 195 | − xprt->resvport = 1; /* NLM requires a reserved port */ | |
| 196 | − | |
| 197 | − /* Existing NLM servers accept AUTH_UNIX only */ | |
| 198 | − clnt = rpc_new_client(xprt, host->h_name, &nlm_program, | |
| 199 | − host->h_version, RPC_AUTH_UNIX); | |
| 200 | − if (IS_ERR(clnt)) | |
| 201 | − goto forgetit; | |
| 202 | − clnt->cl_autobind = 1; /* turn on pmap queries */ | |
| 203 | − clnt->cl_softrtry = 1; /* All queries are soft */ | |
| 204 | − | |
| 205 | − host->h_rpcclnt = clnt; | |
| 187 | + unsigned long increment = nlmsvc_timeout * HZ; | |
| 188 | + struct rpc_timeout timeparms = { | |
| 189 | + .to_initval = increment, | |
| 190 | + .to_increment = increment, | |
| 191 | + .to_maxval = increment * 6UL, | |
| 192 | + .to_retries = 5U, | |
| 193 | + }; | |
| 194 | + struct rpc_create_args args = { | |
| 195 | + .protocol = host->h_proto, | |
| 196 | + .address = (struct sockaddr *)&host->h_addr, | |
| 197 | + .addrsize = sizeof(host->h_addr), | |
| 198 | + .timeout = &timeparms, | |
| 199 | + .servername = host->h_name, | |
| 200 | + .program = &nlm_program, | |
| 201 | + .version = host->h_version, | |
| 202 | + .authflavor = RPC_AUTH_UNIX, | |
| 203 | + .flags = (RPC_CLNT_CREATE_HARDRTRY | | |
| 204 | + RPC_CLNT_CREATE_AUTOBIND), | |
| 205 | + }; | |
| 206 | + | |
| 207 | + clnt = rpc_create(&args); | |
| 208 | + if (!IS_ERR(clnt)) | |
| 209 | + host->h_rpcclnt = clnt; | |
| 210 | + else { | |
| 211 | + printk("lockd: couldn't create RPC handle for %s\n", host->h_name); | |
| 212 | + clnt = NULL; | |
| 213 | + } | |
| 206 | 214 | } |
| 207 | 215 | |
| 208 | 216 | mutex_unlock(&host->h_mutex); |
| 209 | 217 | return clnt; |
| 210 | − | |
| 211 | −forgetit: | |
| 212 | − printk("lockd: couldn't create RPC handle for %s\n", host->h_name); | |
| 213 | − mutex_unlock(&host->h_mutex); | |
| 214 | − return NULL; | |
| 215 | 218 | } |
| 216 | 219 | |
| 217 | 220 | /* |
| @@ -109,30 +109,23 @@ nsm_unmonitor(struct nlm_host *host) · 108 unmodified lines | ||
| 109 | 109 | static struct rpc_clnt * |
| 110 | 110 | nsm_create(void) |
| 111 | 111 | { |
| 112 | − struct rpc_xprt *xprt; | |
| 113 | − struct rpc_clnt *clnt; | |
| 114 | − struct sockaddr_in sin; | |
| 115 | − | |
| 116 | − sin.sin_family = AF_INET; | |
| 117 | − sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | |
| 118 | − sin.sin_port = 0; | |
| 119 | − | |
| 120 | − xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL); | |
| 121 | − if (IS_ERR(xprt)) | |
| 122 | − return (struct rpc_clnt *)xprt; | |
| 123 | − xprt->resvport = 1; /* NSM requires a reserved port */ | |
| 124 | − | |
| 125 | − clnt = rpc_create_client(xprt, "localhost", | |
| 126 | − &nsm_program, SM_VERSION, | |
| 127 | − RPC_AUTH_NULL); | |
| 128 | − if (IS_ERR(clnt)) | |
| 129 | − goto out_err; | |
| 130 | − clnt->cl_softrtry = 1; | |
| 131 | − clnt->cl_oneshot = 1; | |
| 132 | − return clnt; | |
| 133 | − | |
| 134 | −out_err: | |
| 135 | − return clnt; | |
| 112 | + struct sockaddr_in sin = { | |
| 113 | + .sin_family = AF_INET, | |
| 114 | + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), | |
| 115 | + .sin_port = 0, | |
| 116 | + }; | |
| 117 | + struct rpc_create_args args = { | |
| 118 | + .protocol = IPPROTO_UDP, | |
| 119 | + .address = (struct sockaddr *)&sin, | |
| 120 | + .addrsize = sizeof(sin), | |
| 121 | + .servername = "localhost", | |
| 122 | + .program = &nsm_program, | |
| 123 | + .version = SM_VERSION, | |
| 124 | + .authflavor = RPC_AUTH_NULL, | |
| 125 | + .flags = (RPC_CLNT_CREATE_ONESHOT), | |
| 126 | + }; | |
| 127 | + | |
| 128 | + return rpc_create(&args); | |
| 136 | 129 | } |
| 137 | 130 | |
| 138 | 131 | /* |
| @@ -4,9 +4,9 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | obj-$(CONFIG_NFS_FS) += nfs.o |
| 6 | 6 | |
| 7 | −nfs-y := dir.o file.o inode.o super.o nfs2xdr.o pagelist.o \ | |
| 8 | − proc.o read.o symlink.o unlink.o write.o \ | |
| 9 | − namespace.o | |
| 7 | +nfs-y := client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \ | |
| 8 | + pagelist.o proc.o read.o symlink.o unlink.o \ | |
| 9 | + write.o namespace.o | |
| 10 | 10 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o |
| 11 | 11 | nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o |
| 12 | 12 | nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | #include "nfs4_fs.h" |
| 21 | 21 | #include "callback.h" |
| 22 | +#include "internal.h" | |
| 22 | 23 | |
| 23 | 24 | #define NFSDBG_FACILITY NFSDBG_CALLBACK |
| 24 | 25 | |
| @@ -36,6 +37,21 @@ static struct svc_program nfs4_callback_program; · 11 unmodified lines | ||
| 36 | 37 | |
| 37 | 38 | unsigned int nfs_callback_set_tcpport; |
| 38 | 39 | unsigned short nfs_callback_tcpport; |
| 40 | +static const int nfs_set_port_min = 0; | |
| 41 | +static const int nfs_set_port_max = 65535; | |
| 42 | + | |
| 43 | +static int param_set_port(const char *val, struct kernel_param *kp) | |
| 44 | +{ | |
| 45 | + char *endp; | |
| 46 | + int num = simple_strtol(val, &endp, 0); | |
| 47 | + if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max) | |
| 48 | + return -EINVAL; | |
| 49 | + *((int *)kp->arg) = num; | |
| 50 | + return 0; | |
| 51 | +} | |
| 52 | + | |
| 53 | +module_param_call(callback_tcpport, param_set_port, param_get_int, | |
| 54 | + &nfs_callback_set_tcpport, 0644); | |
| 39 | 55 | |
| 40 | 56 | /* |
| 41 | 57 | * This is the callback kernel thread. |
| @@ -134,10 +150,8 @@ out_err: · 92 unmodified lines | ||
| 134 | 150 | /* |
| 135 | 151 | * Kill the server process if it is not already up. |
| 136 | 152 | */ |
| 137 | −int nfs_callback_down(void) | |
| 153 | +void nfs_callback_down(void) | |
| 138 | 154 | { |
| 139 | − int ret = 0; | |
| 140 | − | |
| 141 | 155 | lock_kernel(); |
| 142 | 156 | mutex_lock(&nfs_callback_mutex); |
| 143 | 157 | nfs_callback_info.users--; |
| @@ -149,20 +163,19 @@ int nfs_callback_down(void) · 5 unmodified lines | ||
| 149 | 163 | } while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0); |
| 150 | 164 | mutex_unlock(&nfs_callback_mutex); |
| 151 | 165 | unlock_kernel(); |
| 152 | − return ret; | |
| 153 | 166 | } |
| 154 | 167 | |
| 155 | 168 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) |
| 156 | 169 | { |
| 157 | − struct in_addr *addr = &rqstp->rq_addr.sin_addr; | |
| 158 | − struct nfs4_client *clp; | |
| 170 | + struct sockaddr_in *addr = &rqstp->rq_addr; | |
| 171 | + struct nfs_client *clp; | |
| 159 | 172 | |
| 160 | 173 | /* Don't talk to strangers */ |
| 161 | − clp = nfs4_find_client(addr); | |
| 174 | + clp = nfs_find_client(addr, 4); | |
| 162 | 175 | if (clp == NULL) |
| 163 | 176 | return SVC_DROP; |
| 164 | − dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr)); | |
| 165 | − nfs4_put_client(clp); | |
| 177 | + dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr)); | |
| 178 | + nfs_put_client(clp); | |
| 166 | 179 | switch (rqstp->rq_authop->flavour) { |
| 167 | 180 | case RPC_AUTH_NULL: |
| 168 | 181 | if (rqstp->rq_proc != CB_NULL) |
| @@ -62,8 +62,13 @@ struct cb_recallargs { · 61 unmodified lines | ||
| 62 | 62 | extern unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res); |
| 63 | 63 | extern unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy); |
| 64 | 64 | |
| 65 | +#ifdef CONFIG_NFS_V4 | |
| 65 | 66 | extern int nfs_callback_up(void); |
| 66 | −extern int nfs_callback_down(void); | |
| 67 | +extern void nfs_callback_down(void); | |
| 68 | +#else | |
| 69 | +#define nfs_callback_up() (0) | |
| 70 | +#define nfs_callback_down() do {} while(0) | |
| 71 | +#endif | |
| 67 | 72 | |
| 68 | 73 | extern unsigned int nfs_callback_set_tcpport; |
| 69 | 74 | extern unsigned short nfs_callback_tcpport; |
| @@ -10,19 +10,20 @@ · 9 unmodified lines | ||
| 10 | 10 | #include "nfs4_fs.h" |
| 11 | 11 | #include "callback.h" |
| 12 | 12 | #include "delegation.h" |
| 13 | +#include "internal.h" | |
| 13 | 14 | |
| 14 | 15 | #define NFSDBG_FACILITY NFSDBG_CALLBACK |
| 15 | 16 | |
| 16 | 17 | unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res) |
| 17 | 18 | { |
| 18 | − struct nfs4_client *clp; | |
| 19 | + struct nfs_client *clp; | |
| 19 | 20 | struct nfs_delegation *delegation; |
| 20 | 21 | struct nfs_inode *nfsi; |
| 21 | 22 | struct inode *inode; |
| 22 | 23 | |
| 23 | 24 | res->bitmap[0] = res->bitmap[1] = 0; |
| 24 | 25 | res->status = htonl(NFS4ERR_BADHANDLE); |
| 25 | − clp = nfs4_find_client(&args->addr->sin_addr); | |
| 26 | + clp = nfs_find_client(args->addr, 4); | |
| 26 | 27 | if (clp == NULL) |
| 27 | 28 | goto out; |
| 28 | 29 | inode = nfs_delegation_find_inode(clp, &args->fh); |
| @@ -48,7 +49,7 @@ out_iput: · 19 unmodified lines | ||
| 48 | 49 | up_read(&nfsi->rwsem); |
| 49 | 50 | iput(inode); |
| 50 | 51 | out_putclient: |
| 51 | − nfs4_put_client(clp); | |
| 52 | + nfs_put_client(clp); | |
| 52 | 53 | out: |
| 53 | 54 | dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res->status)); |
| 54 | 55 | return res->status; |
| @@ -56,12 +57,12 @@ out: · 1 unmodified line | ||
| 56 | 57 | |
| 57 | 58 | unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy) |
| 58 | 59 | { |
| 59 | − struct nfs4_client *clp; | |
| 60 | + struct nfs_client *clp; | |
| 60 | 61 | struct inode *inode; |
| 61 | 62 | unsigned res; |
| 62 | 63 | |
| 63 | 64 | res = htonl(NFS4ERR_BADHANDLE); |
| 64 | − clp = nfs4_find_client(&args->addr->sin_addr); | |
| 65 | + clp = nfs_find_client(args->addr, 4); | |
| 65 | 66 | if (clp == NULL) |
| 66 | 67 | goto out; |
| 67 | 68 | inode = nfs_delegation_find_inode(clp, &args->fh); |
| @@ -80,7 +81,7 @@ unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy) · 12 unmodified lines | ||
| 80 | 81 | } |
| 81 | 82 | iput(inode); |
| 82 | 83 | out_putclient: |
| 83 | − nfs4_put_client(clp); | |
| 84 | + nfs_put_client(clp); | |
| 84 | 85 | out: |
| 85 | 86 | dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res)); |
| 86 | 87 | return res; |
| @@ -0,0 +1,1448 @@ | ||
| 1 | +/* client.c: NFS client sharing and management code | |
| 2 | + * | |
| 3 | + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | |
| 4 | + * Written by David Howells (dhowells@redhat.com) | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU General Public License | |
| 8 | + * as published by the Free Software Foundation; either version | |
| 9 | + * 2 of the License, or (at your option) any later version. | |
| 10 | + */ | |
| 11 | + | |
| 12 | + | |
| 13 | +#include <linux/config.h> | |
| 14 | +#include <linux/module.h> | |
| 15 | +#include <linux/init.h> | |
| 16 | + | |
| 17 | +#include <linux/time.h> | |
| 18 | +#include <linux/kernel.h> | |
| 19 | +#include <linux/mm.h> | |
| 20 | +#include <linux/string.h> | |
| 21 | +#include <linux/stat.h> | |
| 22 | +#include <linux/errno.h> | |
| 23 | +#include <linux/unistd.h> | |
| 24 | +#include <linux/sunrpc/clnt.h> | |
| 25 | +#include <linux/sunrpc/stats.h> | |
| 26 | +#include <linux/sunrpc/metrics.h> | |
| 27 | +#include <linux/nfs_fs.h> | |
| 28 | +#include <linux/nfs_mount.h> | |
| 29 | +#include <linux/nfs4_mount.h> | |
| 30 | +#include <linux/lockd/bind.h> | |
| 31 | +#include <linux/smp_lock.h> | |
| 32 | +#include <linux/seq_file.h> | |
| 33 | +#include <linux/mount.h> | |
| 34 | +#include <linux/nfs_idmap.h> | |
| 35 | +#include <linux/vfs.h> | |
| 36 | +#include <linux/inet.h> | |
| 37 | +#include <linux/nfs_xdr.h> | |
| 38 | + | |
| 39 | +#include <asm/system.h> | |
| 40 | + | |
| 41 | +#include "nfs4_fs.h" | |
| 42 | +#include "callback.h" | |
| 43 | +#include "delegation.h" | |
| 44 | +#include "iostat.h" | |
| 45 | +#include "internal.h" | |
| 46 | + | |
| 47 | +#define NFSDBG_FACILITY NFSDBG_CLIENT | |
| 48 | + | |
| 49 | +static DEFINE_SPINLOCK(nfs_client_lock); | |
| 50 | +static LIST_HEAD(nfs_client_list); | |
| 51 | +static LIST_HEAD(nfs_volume_list); | |
| 52 | +static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); | |
| 53 | + | |
| 54 | +/* | |
| 55 | + * RPC cruft for NFS | |
| 56 | + */ | |
| 57 | +static struct rpc_version *nfs_version[5] = { | |
| 58 | + [2] = &nfs_version2, | |
| 59 | +#ifdef CONFIG_NFS_V3 | |
| 60 | + [3] = &nfs_version3, | |
| 61 | +#endif | |
| 62 | +#ifdef CONFIG_NFS_V4 | |
| 63 | + [4] = &nfs_version4, | |
| 64 | +#endif | |
| 65 | +}; | |
| 66 | + | |
| 67 | +struct rpc_program nfs_program = { | |
| 68 | + .name = "nfs", | |
| 69 | + .number = NFS_PROGRAM, | |
| 70 | + .nrvers = ARRAY_SIZE(nfs_version), | |
| 71 | + .version = nfs_version, | |
| 72 | + .stats = &nfs_rpcstat, | |
| 73 | + .pipe_dir_name = "/nfs", | |
| 74 | +}; | |
| 75 | + | |
| 76 | +struct rpc_stat nfs_rpcstat = { | |
| 77 | + .program = &nfs_program | |
| 78 | +}; | |
| 79 | + | |
| 80 | + | |
| 81 | +#ifdef CONFIG_NFS_V3_ACL | |
| 82 | +static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; | |
| 83 | +static struct rpc_version * nfsacl_version[] = { | |
| 84 | + [3] = &nfsacl_version3, | |
| 85 | +}; | |
| 86 | + | |
| 87 | +struct rpc_program nfsacl_program = { | |
| 88 | + .name = "nfsacl", | |
| 89 | + .number = NFS_ACL_PROGRAM, | |
| 90 | + .nrvers = ARRAY_SIZE(nfsacl_version), | |
| 91 | + .version = nfsacl_version, | |
| 92 | + .stats = &nfsacl_rpcstat, | |
| 93 | +}; | |
| 94 | +#endif /* CONFIG_NFS_V3_ACL */ | |
| 95 | + | |
| 96 | +/* | |
| 97 | + * Allocate a shared client record | |
| 98 | + * | |
| 99 | + * Since these are allocated/deallocated very rarely, we don't | |
| 100 | + * bother putting them in a slab cache... | |
| 101 | + */ | |
| 102 | +static struct nfs_client *nfs_alloc_client(const char *hostname, | |
| 103 | + const struct sockaddr_in *addr, | |
| 104 | + int nfsversion) | |
| 105 | +{ | |
| 106 | + struct nfs_client *clp; | |
| 107 | + int error; | |
| 108 | + | |
| 109 | + if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) | |
| 110 | + goto error_0; | |
| 111 | + | |
| 112 | + error = rpciod_up(); | |
| 113 | + if (error < 0) { | |
| 114 | + dprintk("%s: couldn't start rpciod! Error = %d\n", | |
| 115 | + __FUNCTION__, error); | |
| 116 | + goto error_1; | |
| 117 | + } | |
| 118 | + __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state); | |
| 119 | + | |
| 120 | + if (nfsversion == 4) { | |
| 121 | + if (nfs_callback_up() < 0) | |
| 122 | + goto error_2; | |
| 123 | + __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); | |
| 124 | + } | |
| 125 | + | |
| 126 | + atomic_set(&clp->cl_count, 1); | |
| 127 | + clp->cl_cons_state = NFS_CS_INITING; | |
| 128 | + | |
| 129 | + clp->cl_nfsversion = nfsversion; | |
| 130 | + memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); | |
| 131 | + | |
| 132 | + if (hostname) { | |
| 133 | + clp->cl_hostname = kstrdup(hostname, GFP_KERNEL); | |
| 134 | + if (!clp->cl_hostname) | |
| 135 | + goto error_3; | |
| 136 | + } | |
| 137 | + | |
| 138 | + INIT_LIST_HEAD(&clp->cl_superblocks); | |
| 139 | + clp->cl_rpcclient = ERR_PTR(-EINVAL); | |
| 140 | + | |
| 141 | +#ifdef CONFIG_NFS_V4 | |
| 142 | + init_rwsem(&clp->cl_sem); | |
| 143 | + INIT_LIST_HEAD(&clp->cl_delegations); | |
| 144 | + INIT_LIST_HEAD(&clp->cl_state_owners); | |
| 145 | + INIT_LIST_HEAD(&clp->cl_unused); | |
| 146 | + spin_lock_init(&clp->cl_lock); | |
| 147 | + INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); | |
| 148 | + rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); | |
| 149 | + clp->cl_boot_time = CURRENT_TIME; | |
| 150 | + clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | |
| 151 | +#endif | |
| 152 | + | |
| 153 | + return clp; | |
| 154 | + | |
| 155 | +error_3: | |
| 156 | + if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) | |
| 157 | + nfs_callback_down(); | |
| 158 | +error_2: | |
| 159 | + rpciod_down(); | |
| 160 | + __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state); | |
| 161 | +error_1: | |
| 162 | + kfree(clp); | |
| 163 | +error_0: | |
| 164 | + return NULL; | |
| 165 | +} | |
| 166 | + | |
| 167 | +static void nfs4_shutdown_client(struct nfs_client *clp) | |
| 168 | +{ | |
| 169 | +#ifdef CONFIG_NFS_V4 | |
| 170 | + if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) | |
| 171 | + nfs4_kill_renewd(clp); | |
| 172 | + while (!list_empty(&clp->cl_unused)) { | |
| 173 | + struct nfs4_state_owner *sp; | |
| 174 | + | |
| 175 | + sp = list_entry(clp->cl_unused.next, | |
| 176 | + struct nfs4_state_owner, | |
| 177 | + so_list); | |
| 178 | + list_del(&sp->so_list); | |
| 179 | + kfree(sp); | |
| 180 | + } | |
| 181 | + BUG_ON(!list_empty(&clp->cl_state_owners)); | |
| 182 | + if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) | |
| 183 | + nfs_idmap_delete(clp); | |
| 184 | +#endif | |
| 185 | +} | |
| 186 | + | |
| 187 | +/* | |
| 188 | + * Destroy a shared client record | |
| 189 | + */ | |
| 190 | +static void nfs_free_client(struct nfs_client *clp) | |
| 191 | +{ | |
| 192 | + dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion); | |
| 193 | + | |
| 194 | + nfs4_shutdown_client(clp); | |
| 195 | + | |
| 196 | + /* -EIO all pending I/O */ | |
| 197 | + if (!IS_ERR(clp->cl_rpcclient)) | |
| 198 | + rpc_shutdown_client(clp->cl_rpcclient); | |
| 199 | + | |
| 200 | + if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) | |
| 201 | + nfs_callback_down(); | |
| 202 | + | |
| 203 | + if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state)) | |
| 204 | + rpciod_down(); | |
| 205 | + | |
| 206 | + kfree(clp->cl_hostname); | |
| 207 | + kfree(clp); | |
| 208 | + | |
| 209 | + dprintk("<-- nfs_free_client()\n"); | |
| 210 | +} | |
| 211 | + | |
| 212 | +/* | |
| 213 | + * Release a reference to a shared client record | |
| 214 | + */ | |
| 215 | +void nfs_put_client(struct nfs_client *clp) | |
| 216 | +{ | |
| 217 | + if (!clp) | |
| 218 | + return; | |
| 219 | + | |
| 220 | + dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count)); | |
| 221 | + | |
| 222 | + if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) { | |
| 223 | + list_del(&clp->cl_share_link); | |
| 224 | + spin_unlock(&nfs_client_lock); | |
| 225 | + | |
| 226 | + BUG_ON(!list_empty(&clp->cl_superblocks)); | |
| 227 | + | |
| 228 | + nfs_free_client(clp); | |
| 229 | + } | |
| 230 | +} | |
| 231 | + | |
| 232 | +/* | |
| 233 | + * Find a client by address | |
| 234 | + * - caller must hold nfs_client_lock | |
| 235 | + */ | |
| 236 | +static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion) | |
| 237 | +{ | |
| 238 | + struct nfs_client *clp; | |
| 239 | + | |
| 240 | + list_for_each_entry(clp, &nfs_client_list, cl_share_link) { | |
| 241 | + /* Different NFS versions cannot share the same nfs_client */ | |
| 242 | + if (clp->cl_nfsversion != nfsversion) | |
| 243 | + continue; | |
| 244 | + | |
| 245 | + if (memcmp(&clp->cl_addr.sin_addr, &addr->sin_addr, | |
| 246 | + sizeof(clp->cl_addr.sin_addr)) != 0) | |
| 247 | + continue; | |
| 248 | + | |
| 249 | + if (clp->cl_addr.sin_port == addr->sin_port) | |
| 250 | + goto found; | |
| 251 | + } | |
| 252 | + | |
| 253 | + return NULL; | |
| 254 | + | |
| 255 | +found: | |
| 256 | + atomic_inc(&clp->cl_count); | |
| 257 | + return clp; | |
| 258 | +} | |
| 259 | + | |
| 260 | +/* | |
| 261 | + * Find a client by IP address and protocol version | |
| 262 | + * - returns NULL if no such client | |
| 263 | + */ | |
| 264 | +struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion) | |
| 265 | +{ | |
| 266 | + struct nfs_client *clp; | |
| 267 | + | |
| 268 | + spin_lock(&nfs_client_lock); | |
| 269 | + clp = __nfs_find_client(addr, nfsversion); | |
| 270 | + spin_unlock(&nfs_client_lock); | |
| 271 | + | |
| 272 | + BUG_ON(clp && clp->cl_cons_state == 0); | |
| 273 | + | |
| 274 | + return clp; | |
| 275 | +} | |
| 276 | + | |
| 277 | +/* | |
| 278 | + * Look up a client by IP address and protocol version | |
| 279 | + * - creates a new record if one doesn't yet exist | |
| 280 | + */ | |
| 281 | +static struct nfs_client *nfs_get_client(const char *hostname, | |
| 282 | + const struct sockaddr_in *addr, | |
| 283 | + int nfsversion) | |
| 284 | +{ | |
| 285 | + struct nfs_client *clp, *new = NULL; | |
| 286 | + int error; | |
| 287 | + | |
| 288 | + dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n", | |
| 289 | + hostname ?: "", NIPQUAD(addr->sin_addr), | |
| 290 | + addr->sin_port, nfsversion); | |
| 291 | + | |
| 292 | + /* see if the client already exists */ | |
| 293 | + do { | |
| 294 | + spin_lock(&nfs_client_lock); | |
| 295 | + | |
| 296 | + clp = __nfs_find_client(addr, nfsversion); | |
| 297 | + if (clp) | |
| 298 | + goto found_client; | |
| 299 | + if (new) | |
| 300 | + goto install_client; | |
| 301 | + | |
| 302 | + spin_unlock(&nfs_client_lock); | |
| 303 | + | |
| 304 | + new = nfs_alloc_client(hostname, addr, nfsversion); | |
| 305 | + } while (new); | |
| 306 | + | |
| 307 | + return ERR_PTR(-ENOMEM); | |
| 308 | + | |
| 309 | + /* install a new client and return with it unready */ | |
| 310 | +install_client: | |
| 311 | + clp = new; | |
| 312 | + list_add(&clp->cl_share_link, &nfs_client_list); | |
| 313 | + spin_unlock(&nfs_client_lock); | |
| 314 | + dprintk("--> nfs_get_client() = %p [new]\n", clp); | |
| 315 | + return clp; | |
| 316 | + | |
| 317 | + /* found an existing client | |
| 318 | + * - make sure it's ready before returning | |
| 319 | + */ | |
| 320 | +found_client: | |
| 321 | + spin_unlock(&nfs_client_lock); | |
| 322 | + | |
| 323 | + if (new) | |
| 324 | + nfs_free_client(new); | |
| 325 | + | |
| 326 | + if (clp->cl_cons_state == NFS_CS_INITING) { | |
| 327 | + DECLARE_WAITQUEUE(myself, current); | |
| 328 | + | |
| 329 | + add_wait_queue(&nfs_client_active_wq, &myself); | |
| 330 | + | |
| 331 | + for (;;) { | |
| 332 | + set_current_state(TASK_INTERRUPTIBLE); | |
| 333 | + if (signal_pending(current) || | |
| 334 | + clp->cl_cons_state > NFS_CS_READY) | |
| 335 | + break; | |
| 336 | + schedule(); | |
| 337 | + } | |
| 338 | + | |
| 339 | + remove_wait_queue(&nfs_client_active_wq, &myself); | |
| 340 | + | |
| 341 | + if (signal_pending(current)) { | |
| 342 | + nfs_put_client(clp); | |
| 343 | + return ERR_PTR(-ERESTARTSYS); | |
| 344 | + } | |
| 345 | + } | |
| 346 | + | |
| 347 | + if (clp->cl_cons_state < NFS_CS_READY) { | |
| 348 | + error = clp->cl_cons_state; | |
| 349 | + nfs_put_client(clp); | |
| 350 | + return ERR_PTR(error); | |
| 351 | + } | |
| 352 | + | |
| 353 | + BUG_ON(clp->cl_cons_state != NFS_CS_READY); | |
| 354 | + | |
| 355 | + dprintk("--> nfs_get_client() = %p [share]\n", clp); | |
| 356 | + return clp; | |
| 357 | +} | |
| 358 | + | |
| 359 | +/* | |
| 360 | + * Mark a server as ready or failed | |
| 361 | + */ | |
| 362 | +static void nfs_mark_client_ready(struct nfs_client *clp, int state) | |
| 363 | +{ | |
| 364 | + clp->cl_cons_state = state; | |
| 365 | + wake_up_all(&nfs_client_active_wq); | |
| 366 | +} | |
| 367 | + | |
| 368 | +/* | |
| 369 | + * Initialise the timeout values for a connection | |
| 370 | + */ | |
| 371 | +static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | |
| 372 | + unsigned int timeo, unsigned int retrans) | |
| 373 | +{ | |
| 374 | + to->to_initval = timeo * HZ / 10; | |
| 375 | + to->to_retries = retrans; | |
| 376 | + if (!to->to_retries) | |
| 377 | + to->to_retries = 2; | |
| 378 | + | |
| 379 | + switch (proto) { | |
| 380 | + case IPPROTO_TCP: | |
| 381 | + if (!to->to_initval) | |
| 382 | + to->to_initval = 60 * HZ; | |
| 383 | + if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | |
| 384 | + to->to_initval = NFS_MAX_TCP_TIMEOUT; | |
| 385 | + to->to_increment = to->to_initval; | |
| 386 | + to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | |
| 387 | + to->to_exponential = 0; | |
| 388 | + break; | |
| 389 | + case IPPROTO_UDP: | |
| 390 | + default: | |
| 391 | + if (!to->to_initval) | |
| 392 | + to->to_initval = 11 * HZ / 10; | |
| 393 | + if (to->to_initval > NFS_MAX_UDP_TIMEOUT) | |
| 394 | + to->to_initval = NFS_MAX_UDP_TIMEOUT; | |
| 395 | + to->to_maxval = NFS_MAX_UDP_TIMEOUT; | |
| 396 | + to->to_exponential = 1; | |
| 397 | + break; | |
| 398 | + } | |
| 399 | +} | |
| 400 | + | |
| 401 | +/* | |
| 402 | + * Create an RPC client handle | |
| 403 | + */ | |
| 404 | +static int nfs_create_rpc_client(struct nfs_client *clp, int proto, | |
| 405 | + unsigned int timeo, | |
| 406 | + unsigned int retrans, | |
| 407 | + rpc_authflavor_t flavor) | |
| 408 | +{ | |
| 409 | + struct rpc_timeout timeparms; | |
| 410 | + struct rpc_clnt *clnt = NULL; | |
| 411 | + struct rpc_create_args args = { | |
| 412 | + .protocol = proto, | |
| 413 | + .address = (struct sockaddr *)&clp->cl_addr, | |
| 414 | + .addrsize = sizeof(clp->cl_addr), | |
| 415 | + .timeout = &timeparms, | |
| 416 | + .servername = clp->cl_hostname, | |
| 417 | + .program = &nfs_program, | |
| 418 | + .version = clp->rpc_ops->version, | |
| 419 | + .authflavor = flavor, | |
| 420 | + }; | |
| 421 | + | |
| 422 | + if (!IS_ERR(clp->cl_rpcclient)) | |
| 423 | + return 0; | |
| 424 | + | |
| 425 | + nfs_init_timeout_values(&timeparms, proto, timeo, retrans); | |
| 426 | + clp->retrans_timeo = timeparms.to_initval; | |
| 427 | + clp->retrans_count = timeparms.to_retries; | |
| 428 | + | |
| 429 | + clnt = rpc_create(&args); | |
| 430 | + if (IS_ERR(clnt)) { | |
| 431 | + dprintk("%s: cannot create RPC client. Error = %ld\n", | |
| 432 | + __FUNCTION__, PTR_ERR(clnt)); | |
| 433 | + return PTR_ERR(clnt); | |
| 434 | + } | |
| 435 | + | |
| 436 | + clp->cl_rpcclient = clnt; | |
| 437 | + return 0; | |
| 438 | +} | |
| 439 | + | |
| 440 | +/* | |
| 441 | + * Version 2 or 3 client destruction | |
| 442 | + */ | |
| 443 | +static void nfs_destroy_server(struct nfs_server *server) | |
| 444 | +{ | |
| 445 | + if (!IS_ERR(server->client_acl)) | |
| 446 | + rpc_shutdown_client(server->client_acl); | |
| 447 | + | |
| 448 | + if (!(server->flags & NFS_MOUNT_NONLM)) | |
| 449 | + lockd_down(); /* release rpc.lockd */ | |
| 450 | +} | |
| 451 | + | |
| 452 | +/* | |
| 453 | + * Version 2 or 3 lockd setup | |
| 454 | + */ | |
| 455 | +static int nfs_start_lockd(struct nfs_server *server) | |
| 456 | +{ | |
| 457 | + int error = 0; | |
| 458 | + | |
| 459 | + if (server->nfs_client->cl_nfsversion > 3) | |
| 460 | + goto out; | |
| 461 | + if (server->flags & NFS_MOUNT_NONLM) | |
| 462 | + goto out; | |
| 463 | + error = lockd_up(); | |
| 464 | + if (error < 0) | |
| 465 | + server->flags |= NFS_MOUNT_NONLM; | |
| 466 | + else | |
| 467 | + server->destroy = nfs_destroy_server; | |
| 468 | +out: | |
| 469 | + return error; | |
| 470 | +} | |
| 471 | + | |
| 472 | +/* | |
| 473 | + * Initialise an NFSv3 ACL client connection | |
| 474 | + */ | |
| 475 | +#ifdef CONFIG_NFS_V3_ACL | |
| 476 | +static void nfs_init_server_aclclient(struct nfs_server *server) | |
| 477 | +{ | |
| 478 | + if (server->nfs_client->cl_nfsversion != 3) | |
| 479 | + goto out_noacl; | |
| 480 | + if (server->flags & NFS_MOUNT_NOACL) | |
| 481 | + goto out_noacl; | |
| 482 | + | |
| 483 | + server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); | |
| 484 | + if (IS_ERR(server->client_acl)) | |
| 485 | + goto out_noacl; | |
| 486 | + | |
| 487 | + /* No errors! Assume that Sun nfsacls are supported */ | |
| 488 | + server->caps |= NFS_CAP_ACLS; | |
| 489 | + return; | |
| 490 | + | |
| 491 | +out_noacl: | |
| 492 | + server->caps &= ~NFS_CAP_ACLS; | |
| 493 | +} | |
| 494 | +#else | |
| 495 | +static inline void nfs_init_server_aclclient(struct nfs_server *server) | |
| 496 | +{ | |
| 497 | + server->flags &= ~NFS_MOUNT_NOACL; | |
| 498 | + server->caps &= ~NFS_CAP_ACLS; | |
| 499 | +} | |
| 500 | +#endif | |
| 501 | + | |
| 502 | +/* | |
| 503 | + * Create a general RPC client | |
| 504 | + */ | |
| 505 | +static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour) | |
| 506 | +{ | |
| 507 | + struct nfs_client *clp = server->nfs_client; | |
| 508 | + | |
| 509 | + server->client = rpc_clone_client(clp->cl_rpcclient); | |
| 510 | + if (IS_ERR(server->client)) { | |
| 511 | + dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__); | |
| 512 | + return PTR_ERR(server->client); | |
| 513 | + } | |
| 514 | + | |
| 515 | + if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { | |
| 516 | + struct rpc_auth *auth; | |
| 517 | + | |
| 518 | + auth = rpcauth_create(pseudoflavour, server->client); | |
| 519 | + if (IS_ERR(auth)) { | |
| 520 | + dprintk("%s: couldn't create credcache!\n", __FUNCTION__); | |
| 521 | + return PTR_ERR(auth); | |
| 522 | + } | |
| 523 | + } | |
| 524 | + server->client->cl_softrtry = 0; | |
| 525 | + if (server->flags & NFS_MOUNT_SOFT) | |
| 526 | + server->client->cl_softrtry = 1; | |
| 527 | + | |
| 528 | + server->client->cl_intr = 0; | |
| 529 | + if (server->flags & NFS4_MOUNT_INTR) | |
| 530 | + server->client->cl_intr = 1; | |
| 531 | + | |
| 532 | + return 0; | |
| 533 | +} | |
| 534 | + | |
| 535 | +/* | |
| 536 | + * Initialise an NFS2 or NFS3 client | |
| 537 | + */ | |
| 538 | +static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data) | |
| 539 | +{ | |
| 540 | + int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; | |
| 541 | + int error; | |
| 542 | + | |
| 543 | + if (clp->cl_cons_state == NFS_CS_READY) { | |
| 544 | + /* the client is already initialised */ | |
| 545 | + dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp); | |
| 546 | + return 0; | |
| 547 | + } | |
| 548 | + | |
| 549 | + /* Check NFS protocol revision and initialize RPC op vector */ | |
| 550 | + clp->rpc_ops = &nfs_v2_clientops; | |
| 551 | +#ifdef CONFIG_NFS_V3 | |
| 552 | + if (clp->cl_nfsversion == 3) | |
| 553 | + clp->rpc_ops = &nfs_v3_clientops; | |
| 554 | +#endif | |
| 555 | + /* | |
| 556 | + * Create a client RPC handle for doing FSSTAT with UNIX auth only | |
| 557 | + * - RFC 2623, sec 2.3.2 | |
| 558 | + */ | |
| 559 | + error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans, | |
| 560 | + RPC_AUTH_UNIX); | |
| 561 | + if (error < 0) | |
| 562 | + goto error; | |
| 563 | + nfs_mark_client_ready(clp, NFS_CS_READY); | |
| 564 | + return 0; | |
| 565 | + | |
| 566 | +error: | |
| 567 | + nfs_mark_client_ready(clp, error); | |
| 568 | + dprintk("<-- nfs_init_client() = xerror %d\n", error); | |
| 569 | + return error; | |
| 570 | +} | |
| 571 | + | |
| 572 | +/* | |
| 573 | + * Create a version 2 or 3 client | |
| 574 | + */ | |
| 575 | +static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data) | |
| 576 | +{ | |
| 577 | + struct nfs_client *clp; | |
| 578 | + int error, nfsvers = 2; | |
| 579 | + | |
| 580 | + dprintk("--> nfs_init_server()\n"); | |
| 581 | + | |
| 582 | +#ifdef CONFIG_NFS_V3 | |
| 583 | + if (data->flags & NFS_MOUNT_VER3) | |
| 584 | + nfsvers = 3; | |
| 585 | +#endif | |
| 586 | + | |
| 587 | + /* Allocate or find a client reference we can use */ | |
| 588 | + clp = nfs_get_client(data->hostname, &data->addr, nfsvers); | |
| 589 | + if (IS_ERR(clp)) { | |
| 590 | + dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); | |
| 591 | + return PTR_ERR(clp); | |
| 592 | + } | |
| 593 | + | |
| 594 | + error = nfs_init_client(clp, data); | |
| 595 | + if (error < 0) | |
| 596 | + goto error; | |
| 597 | + | |
| 598 | + server->nfs_client = clp; | |
| 599 | + | |
| 600 | + /* Initialise the client representation from the mount data */ | |
| 601 | + server->flags = data->flags & NFS_MOUNT_FLAGMASK; | |
| 602 | + | |
| 603 | + if (data->rsize) | |
| 604 | + server->rsize = nfs_block_size(data->rsize, NULL); | |
| 605 | + if (data->wsize) | |
| 606 | + server->wsize = nfs_block_size(data->wsize, NULL); | |
| 607 | + | |
| 608 | + server->acregmin = data->acregmin * HZ; | |
| 609 | + server->acregmax = data->acregmax * HZ; | |
| 610 | + server->acdirmin = data->acdirmin * HZ; | |
| 611 | + server->acdirmax = data->acdirmax * HZ; | |
| 612 | + | |
| 613 | + /* Start lockd here, before we might error out */ | |
| 614 | + error = nfs_start_lockd(server); | |
| 615 | + if (error < 0) | |
| 616 | + goto error; | |
| 617 | + | |
| 618 | + error = nfs_init_server_rpcclient(server, data->pseudoflavor); | |
| 619 | + if (error < 0) | |
| 620 | + goto error; | |
| 621 | + | |
| 622 | + server->namelen = data->namlen; | |
| 623 | + /* Create a client RPC handle for the NFSv3 ACL management interface */ | |
| 624 | + nfs_init_server_aclclient(server); | |
| 625 | + if (clp->cl_nfsversion == 3) { | |
| 626 | + if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) | |
| 627 | + server->namelen = NFS3_MAXNAMLEN; | |
| 628 | + server->caps |= NFS_CAP_READDIRPLUS; | |
| 629 | + } else { | |
| 630 | + if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) | |
| 631 | + server->namelen = NFS2_MAXNAMLEN; | |
| 632 | + } | |
| 633 | + | |
| 634 | + dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); | |
| 635 | + return 0; | |
| 636 | + | |
| 637 | +error: | |
| 638 | + server->nfs_client = NULL; | |
| 639 | + nfs_put_client(clp); | |
| 640 | + dprintk("<-- nfs_init_server() = xerror %d\n", error); | |
| 641 | + return error; | |
| 642 | +} | |
| 643 | + | |
| 644 | +/* | |
| 645 | + * Load up the server record from information gained in an fsinfo record | |
| 646 | + */ | |
| 647 | +static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo) | |
| 648 | +{ | |
| 649 | + unsigned long max_rpc_payload; | |
| 650 | + | |
| 651 | + /* Work out a lot of parameters */ | |
| 652 | + if (server->rsize == 0) | |
| 653 | + server->rsize = nfs_block_size(fsinfo->rtpref, NULL); | |
| 654 | + if (server->wsize == 0) | |
| 655 | + server->wsize = nfs_block_size(fsinfo->wtpref, NULL); | |
| 656 | + | |
| 657 | + if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax) | |
| 658 | + server->rsize = nfs_block_size(fsinfo->rtmax, NULL); | |
| 659 | + if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax) | |
| 660 | + server->wsize = nfs_block_size(fsinfo->wtmax, NULL); | |
| 661 | + | |
| 662 | + max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); | |
| 663 | + if (server->rsize > max_rpc_payload) | |
| 664 | + server->rsize = max_rpc_payload; | |
| 665 | + if (server->rsize > NFS_MAX_FILE_IO_SIZE) | |
| 666 | + server->rsize = NFS_MAX_FILE_IO_SIZE; | |
| 667 | + server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | |
| 668 | + server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; | |
| 669 | + | |
| 670 | + if (server->wsize > max_rpc_payload) | |
| 671 | + server->wsize = max_rpc_payload; | |
| 672 | + if (server->wsize > NFS_MAX_FILE_IO_SIZE) | |
| 673 | + server->wsize = NFS_MAX_FILE_IO_SIZE; | |
| 674 | + server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | |
| 675 | + server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); | |
| 676 | + | |
| 677 | + server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); | |
| 678 | + if (server->dtsize > PAGE_CACHE_SIZE) | |
| 679 | + server->dtsize = PAGE_CACHE_SIZE; | |
| 680 | + if (server->dtsize > server->rsize) | |
| 681 | + server->dtsize = server->rsize; | |
| 682 | + | |
| 683 | + if (server->flags & NFS_MOUNT_NOAC) { | |
| 684 | + server->acregmin = server->acregmax = 0; | |
| 685 | + server->acdirmin = server->acdirmax = 0; | |
| 686 | + } | |
| 687 | + | |
| 688 | + server->maxfilesize = fsinfo->maxfilesize; | |
| 689 | + | |
| 690 | + /* We're airborne Set socket buffersize */ | |
| 691 | + rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); | |
| 692 | +} | |
| 693 | + | |
| 694 | +/* | |
| 695 | + * Probe filesystem information, including the FSID on v2/v3 | |
| 696 | + */ | |
| 697 | +static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr) | |
| 698 | +{ | |
| 699 | + struct nfs_fsinfo fsinfo; | |
| 700 | + struct nfs_client *clp = server->nfs_client; | |
| 701 | + int error; | |
| 702 | + | |
| 703 | + dprintk("--> nfs_probe_fsinfo()\n"); | |
| 704 | + | |
| 705 | + if (clp->rpc_ops->set_capabilities != NULL) { | |
| 706 | + error = clp->rpc_ops->set_capabilities(server, mntfh); | |
| 707 | + if (error < 0) | |
| 708 | + goto out_error; | |
| 709 | + } | |
| 710 | + | |
| 711 | + fsinfo.fattr = fattr; | |
| 712 | + nfs_fattr_init(fattr); | |
| 713 | + error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); | |
| 714 | + if (error < 0) | |
| 715 | + goto out_error; | |
| 716 | + | |
| 717 | + nfs_server_set_fsinfo(server, &fsinfo); | |
| 718 | + | |
| 719 | + /* Get some general file system info */ | |
| 720 | + if (server->namelen == 0) { | |
| 721 | + struct nfs_pathconf pathinfo; | |
| 722 | + | |
| 723 | + pathinfo.fattr = fattr; | |
| 724 | + nfs_fattr_init(fattr); | |
| 725 | + | |
| 726 | + if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0) | |
| 727 | + server->namelen = pathinfo.max_namelen; | |
| 728 | + } | |
| 729 | + | |
| 730 | + dprintk("<-- nfs_probe_fsinfo() = 0\n"); | |
| 731 | + return 0; | |
| 732 | + | |
| 733 | +out_error: | |
| 734 | + dprintk("nfs_probe_fsinfo: error = %d\n", -error); | |
| 735 | + return error; | |
| 736 | +} | |
| 737 | + | |
| 738 | +/* | |
| 739 | + * Copy useful information when duplicating a server record | |
| 740 | + */ | |
| 741 | +static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) | |
| 742 | +{ | |
| 743 | + target->flags = source->flags; | |
| 744 | + target->acregmin = source->acregmin; | |
| 745 | + target->acregmax = source->acregmax; | |
| 746 | + target->acdirmin = source->acdirmin; | |
| 747 | + target->acdirmax = source->acdirmax; | |
| 748 | + target->caps = source->caps; | |
| 749 | +} | |
| 750 | + | |
| 751 | +/* | |
| 752 | + * Allocate and initialise a server record | |
| 753 | + */ | |
| 754 | +static struct nfs_server *nfs_alloc_server(void) | |
| 755 | +{ | |
| 756 | + struct nfs_server *server; | |
| 757 | + | |
| 758 | + server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); | |
| 759 | + if (!server) | |
| 760 | + return NULL; | |
| 761 | + | |
| 762 | + server->client = server->client_acl = ERR_PTR(-EINVAL); | |
| 763 | + | |
| 764 | + /* Zero out the NFS state stuff */ | |
| 765 | + INIT_LIST_HEAD(&server->client_link); | |
| 766 | + INIT_LIST_HEAD(&server->master_link); | |
| 767 | + | |
| 768 | + server->io_stats = nfs_alloc_iostats(); | |
| 769 | + if (!server->io_stats) { | |
| 770 | + kfree(server); | |
| 771 | + return NULL; | |
| 772 | + } | |
| 773 | + | |
| 774 | + return server; | |
| 775 | +} | |
| 776 | + | |
| 777 | +/* | |
| 778 | + * Free up a server record | |
| 779 | + */ | |
| 780 | +void nfs_free_server(struct nfs_server *server) | |
| 781 | +{ | |
| 782 | + dprintk("--> nfs_free_server()\n"); | |
| 783 | + | |
| 784 | + spin_lock(&nfs_client_lock); | |
| 785 | + list_del(&server->client_link); | |
| 786 | + list_del(&server->master_link); | |
| 787 | + spin_unlock(&nfs_client_lock); | |
| 788 | + | |
| 789 | + if (server->destroy != NULL) | |
| 790 | + server->destroy(server); | |
| 791 | + if (!IS_ERR(server->client)) | |
| 792 | + rpc_shutdown_client(server->client); | |
| 793 | + | |
| 794 | + nfs_put_client(server->nfs_client); | |
| 795 | + | |
| 796 | + nfs_free_iostats(server->io_stats); | |
| 797 | + kfree(server); | |
| 798 | + nfs_release_automount_timer(); | |
| 799 | + dprintk("<-- nfs_free_server()\n"); | |
| 800 | +} | |
| 801 | + | |
| 802 | +/* | |
| 803 | + * Create a version 2 or 3 volume record | |
| 804 | + * - keyed on server and FSID | |
| 805 | + */ | |
| 806 | +struct nfs_server *nfs_create_server(const struct nfs_mount_data *data, | |
| 807 | + struct nfs_fh *mntfh) | |
| 808 | +{ | |
| 809 | + struct nfs_server *server; | |
| 810 | + struct nfs_fattr fattr; | |
| 811 | + int error; | |
| 812 | + | |
| 813 | + server = nfs_alloc_server(); | |
| 814 | + if (!server) | |
| 815 | + return ERR_PTR(-ENOMEM); | |
| 816 | + | |
| 817 | + /* Get a client representation */ | |
| 818 | + error = nfs_init_server(server, data); | |
| 819 | + if (error < 0) | |
| 820 | + goto error; | |
| 821 | + | |
| 822 | + BUG_ON(!server->nfs_client); | |
| 823 | + BUG_ON(!server->nfs_client->rpc_ops); | |
| 824 | + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | |
| 825 | + | |
| 826 | + /* Probe the root fh to retrieve its FSID */ | |
| 827 | + error = nfs_probe_fsinfo(server, mntfh, &fattr); | |
| 828 | + if (error < 0) | |
| 829 | + goto error; | |
| 830 | + if (!(fattr.valid & NFS_ATTR_FATTR)) { | |
| 831 | + error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); | |
| 832 | + if (error < 0) { | |
| 833 | + dprintk("nfs_create_server: getattr error = %d\n", -error); | |
| 834 | + goto error; | |
| 835 | + } | |
| 836 | + } | |
| 837 | + memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); | |
| 838 | + | |
| 839 | + dprintk("Server FSID: %llx:%llx\n", | |
| 840 | + (unsigned long long) server->fsid.major, | |
| 841 | + (unsigned long long) server->fsid.minor); | |
| 842 | + | |
| 843 | + BUG_ON(!server->nfs_client); | |
| 844 | + BUG_ON(!server->nfs_client->rpc_ops); | |
| 845 | + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | |
| 846 | + | |
| 847 | + spin_lock(&nfs_client_lock); | |
| 848 | + list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | |
| 849 | + list_add_tail(&server->master_link, &nfs_volume_list); | |
| 850 | + spin_unlock(&nfs_client_lock); | |
| 851 | + | |
| 852 | + server->mount_time = jiffies; | |
| 853 | + return server; | |
| 854 | + | |
| 855 | +error: | |
| 856 | + nfs_free_server(server); | |
| 857 | + return ERR_PTR(error); | |
| 858 | +} | |
| 859 | + | |
| 860 | +#ifdef CONFIG_NFS_V4 | |
| 861 | +/* | |
| 862 | + * Initialise an NFS4 client record | |
| 863 | + */ | |
| 864 | +static int nfs4_init_client(struct nfs_client *clp, | |
| 865 | + int proto, int timeo, int retrans, | |
| 866 | + rpc_authflavor_t authflavour) | |
| 867 | +{ | |
| 868 | + int error; | |
| 869 | + | |
| 870 | + if (clp->cl_cons_state == NFS_CS_READY) { | |
| 871 | + /* the client is initialised already */ | |
| 872 | + dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp); | |
| 873 | + return 0; | |
| 874 | + } | |
| 875 | + | |
| 876 | + /* Check NFS protocol revision and initialize RPC op vector */ | |
| 877 | + clp->rpc_ops = &nfs_v4_clientops; | |
| 878 | + | |
| 879 | + error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour); | |
| 880 | + if (error < 0) | |
| 881 | + goto error; | |
| 882 | + | |
| 883 | + error = nfs_idmap_new(clp); | |
| 884 | + if (error < 0) { | |
| 885 | + dprintk("%s: failed to create idmapper. Error = %d\n", | |
| 886 | + __FUNCTION__, error); | |
| 887 | + goto error; | |
| 888 | + } | |
| 889 | + __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); | |
| 890 | + | |
| 891 | + nfs_mark_client_ready(clp, NFS_CS_READY); | |
| 892 | + return 0; | |
| 893 | + | |
| 894 | +error: | |
| 895 | + nfs_mark_client_ready(clp, error); | |
| 896 | + dprintk("<-- nfs4_init_client() = xerror %d\n", error); | |
| 897 | + return error; | |
| 898 | +} | |
| 899 | + | |
| 900 | +/* | |
| 901 | + * Set up an NFS4 client | |
| 902 | + */ | |
| 903 | +static int nfs4_set_client(struct nfs_server *server, | |
| 904 | + const char *hostname, const struct sockaddr_in *addr, | |
| 905 | + rpc_authflavor_t authflavour, | |
| 906 | + int proto, int timeo, int retrans) | |
| 907 | +{ | |
| 908 | + struct nfs_client *clp; | |
| 909 | + int error; | |
| 910 | + | |
| 911 | + dprintk("--> nfs4_set_client()\n"); | |
| 912 | + | |
| 913 | + /* Allocate or find a client reference we can use */ | |
| 914 | + clp = nfs_get_client(hostname, addr, 4); | |
| 915 | + if (IS_ERR(clp)) { | |
| 916 | + error = PTR_ERR(clp); | |
| 917 | + goto error; | |
| 918 | + } | |
| 919 | + error = nfs4_init_client(clp, proto, timeo, retrans, authflavour); | |
| 920 | + if (error < 0) | |
| 921 | + goto error_put; | |
| 922 | + | |
| 923 | + server->nfs_client = clp; | |
| 924 | + dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp); | |
| 925 | + return 0; | |
| 926 | + | |
| 927 | +error_put: | |
| 928 | + nfs_put_client(clp); | |
| 929 | +error: | |
| 930 | + dprintk("<-- nfs4_set_client() = xerror %d\n", error); | |
| 931 | + return error; | |
| 932 | +} | |
| 933 | + | |
| 934 | +/* | |
| 935 | + * Create a version 4 volume record | |
| 936 | + */ | |
| 937 | +static int nfs4_init_server(struct nfs_server *server, | |
| 938 | + const struct nfs4_mount_data *data, rpc_authflavor_t authflavour) | |
| 939 | +{ | |
| 940 | + int error; | |
| 941 | + | |
| 942 | + dprintk("--> nfs4_init_server()\n"); | |
| 943 | + | |
| 944 | + /* Initialise the client representation from the mount data */ | |
| 945 | + server->flags = data->flags & NFS_MOUNT_FLAGMASK; | |
| 946 | + server->caps |= NFS_CAP_ATOMIC_OPEN; | |
| 947 | + | |
| 948 | + if (data->rsize) | |
| 949 | + server->rsize = nfs_block_size(data->rsize, NULL); | |
| 950 | + if (data->wsize) | |
| 951 | + server->wsize = nfs_block_size(data->wsize, NULL); | |
| 952 | + | |
| 953 | + server->acregmin = data->acregmin * HZ; | |
| 954 | + server->acregmax = data->acregmax * HZ; | |
| 955 | + server->acdirmin = data->acdirmin * HZ; | |
| 956 | + server->acdirmax = data->acdirmax * HZ; | |
| 957 | + | |
| 958 | + error = nfs_init_server_rpcclient(server, authflavour); | |
| 959 | + | |
| 960 | + /* Done */ | |
| 961 | + dprintk("<-- nfs4_init_server() = %d\n", error); | |
| 962 | + return error; | |
| 963 | +} | |
| 964 | + | |
| 965 | +/* | |
| 966 | + * Create a version 4 volume record | |
| 967 | + * - keyed on server and FSID | |
| 968 | + */ | |
| 969 | +struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, | |
| 970 | + const char *hostname, | |
| 971 | + const struct sockaddr_in *addr, | |
| 972 | + const char *mntpath, | |
| 973 | + const char *ip_addr, | |
| 974 | + rpc_authflavor_t authflavour, | |
| 975 | + struct nfs_fh *mntfh) | |
| 976 | +{ | |
| 977 | + struct nfs_fattr fattr; | |
| 978 | + struct nfs_server *server; | |
| 979 | + int error; | |
| 980 | + | |
| 981 | + dprintk("--> nfs4_create_server()\n"); | |
| 982 | + | |
| 983 | + server = nfs_alloc_server(); | |
| 984 | + if (!server) | |
| 985 | + return ERR_PTR(-ENOMEM); | |
| 986 | + | |
| 987 | + /* Get a client record */ | |
| 988 | + error = nfs4_set_client(server, hostname, addr, authflavour, | |
| 989 | + data->proto, data->timeo, data->retrans); | |
| 990 | + if (error < 0) | |
| 991 | + goto error; | |
| 992 | + | |
| 993 | + /* set up the general RPC client */ | |
| 994 | + error = nfs4_init_server(server, data, authflavour); | |
| 995 | + if (error < 0) | |
| 996 | + goto error; | |
| 997 | + | |
| 998 | + BUG_ON(!server->nfs_client); | |
| 999 | + BUG_ON(!server->nfs_client->rpc_ops); | |
| 1000 | + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | |
| 1001 | + | |
| 1002 | + /* Probe the root fh to retrieve its FSID */ | |
| 1003 | + error = nfs4_path_walk(server, mntfh, mntpath); | |
| 1004 | + if (error < 0) | |
| 1005 | + goto error; | |
| 1006 | + | |
| 1007 | + dprintk("Server FSID: %llx:%llx\n", | |
| 1008 | + (unsigned long long) server->fsid.major, | |
| 1009 | + (unsigned long long) server->fsid.minor); | |
| 1010 | + dprintk("Mount FH: %d\n", mntfh->size); | |
| 1011 | + | |
| 1012 | + error = nfs_probe_fsinfo(server, mntfh, &fattr); | |
| 1013 | + if (error < 0) | |
| 1014 | + goto error; | |
| 1015 | + | |
| 1016 | + BUG_ON(!server->nfs_client); | |
| 1017 | + BUG_ON(!server->nfs_client->rpc_ops); | |
| 1018 | + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | |
| 1019 | + | |
| 1020 | + spin_lock(&nfs_client_lock); | |
| 1021 | + list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | |
| 1022 | + list_add_tail(&server->master_link, &nfs_volume_list); | |
| 1023 | + spin_unlock(&nfs_client_lock); | |
| 1024 | + | |
| 1025 | + server->mount_time = jiffies; | |
| 1026 | + dprintk("<-- nfs4_create_server() = %p\n", server); | |
| 1027 | + return server; | |
| 1028 | + | |
| 1029 | +error: | |
| 1030 | + nfs_free_server(server); | |
| 1031 | + dprintk("<-- nfs4_create_server() = error %d\n", error); | |
| 1032 | + return ERR_PTR(error); | |
| 1033 | +} | |
| 1034 | + | |
| 1035 | +/* | |
| 1036 | + * Create an NFS4 referral server record | |
| 1037 | + */ | |
| 1038 | +struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |
| 1039 | + struct nfs_fh *fh) | |
| 1040 | +{ | |
| 1041 | + struct nfs_client *parent_client; | |
| 1042 | + struct nfs_server *server, *parent_server; | |
| 1043 | + struct nfs_fattr fattr; | |
| 1044 | + int error; | |
| 1045 | + | |
| 1046 | + dprintk("--> nfs4_create_referral_server()\n"); | |
| 1047 | + | |
| 1048 | + server = nfs_alloc_server(); | |
| 1049 | + if (!server) | |
| 1050 | + return ERR_PTR(-ENOMEM); | |
| 1051 | + | |
| 1052 | + parent_server = NFS_SB(data->sb); | |
| 1053 | + parent_client = parent_server->nfs_client; | |
| 1054 | + | |
| 1055 | + /* Get a client representation. | |
| 1056 | + * Note: NFSv4 always uses TCP, */ | |
| 1057 | + error = nfs4_set_client(server, data->hostname, data->addr, | |
| 1058 | + data->authflavor, | |
| 1059 | + parent_server->client->cl_xprt->prot, | |
| 1060 | + parent_client->retrans_timeo, | |
| 1061 | + parent_client->retrans_count); | |
| 1062 | + if (error < 0) | |
| 1063 | + goto error; | |
| 1064 | + | |
| 1065 | + /* Initialise the client representation from the parent server */ | |
| 1066 | + nfs_server_copy_userdata(server, parent_server); | |
| 1067 | + server->caps |= NFS_CAP_ATOMIC_OPEN; | |
| 1068 | + | |
| 1069 | + error = nfs_init_server_rpcclient(server, data->authflavor); | |
| 1070 | + if (error < 0) | |
| 1071 | + goto error; | |
| 1072 | + | |
| 1073 | + BUG_ON(!server->nfs_client); | |
| 1074 | + BUG_ON(!server->nfs_client->rpc_ops); | |
| 1075 | + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | |
| 1076 | + | |
| 1077 | + /* probe the filesystem info for this server filesystem */ | |
| 1078 | + error = nfs_probe_fsinfo(server, fh, &fattr); | |
| 1079 | + if (error < 0) | |
| 1080 | + goto error; | |
| 1081 | + | |
| 1082 | + dprintk("Referral FSID: %llx:%llx\n", | |
| 1083 | + (unsigned long long) server->fsid.major, | |
| 1084 | + (unsigned long long) server->fsid.minor); | |
| 1085 | + | |
| 1086 | + spin_lock(&nfs_client_lock); | |
| 1087 | + list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | |
| 1088 | + list_add_tail(&server->master_link, &nfs_volume_list); | |
| 1089 | + spin_unlock(&nfs_client_lock); | |
| 1090 | + | |
| 1091 | + server->mount_time = jiffies; | |
| 1092 | + | |
| 1093 | + dprintk("<-- nfs_create_referral_server() = %p\n", server); | |
| 1094 | + return server; | |
| 1095 | + | |
| 1096 | +error: | |
| 1097 | + nfs_free_server(server); | |
| 1098 | + dprintk("<-- nfs4_create_referral_server() = error %d\n", error); | |
| 1099 | + return ERR_PTR(error); | |
| 1100 | +} | |
| 1101 | + | |
| 1102 | +#endif /* CONFIG_NFS_V4 */ | |
| 1103 | + | |
| 1104 | +/* | |
| 1105 | + * Clone an NFS2, NFS3 or NFS4 server record | |
| 1106 | + */ | |
| 1107 | +struct nfs_server *nfs_clone_server(struct nfs_server *source, | |
| 1108 | + struct nfs_fh *fh, | |
| 1109 | + struct nfs_fattr *fattr) | |
| 1110 | +{ | |
| 1111 | + struct nfs_server *server; | |
| 1112 | + struct nfs_fattr fattr_fsinfo; | |
| 1113 | + int error; | |
| 1114 | + | |
| 1115 | + dprintk("--> nfs_clone_server(,%llx:%llx,)\n", | |
| 1116 | + (unsigned long long) fattr->fsid.major, | |
| 1117 | + (unsigned long long) fattr->fsid.minor); | |
| 1118 | + | |
| 1119 | + server = nfs_alloc_server(); | |
| 1120 | + if (!server) | |
| 1121 | + return ERR_PTR(-ENOMEM); | |
| 1122 | + | |
| 1123 | + /* Copy data from the source */ | |
| 1124 | + server->nfs_client = source->nfs_client; | |
| 1125 | + atomic_inc(&server->nfs_client->cl_count); | |
| 1126 | + nfs_server_copy_userdata(server, source); | |
| 1127 | + | |
| 1128 | + server->fsid = fattr->fsid; | |
| 1129 | + | |
| 1130 | + error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor); | |
| 1131 | + if (error < 0) | |
| 1132 | + goto out_free_server; | |
| 1133 | + if (!IS_ERR(source->client_acl)) | |
| 1134 | + nfs_init_server_aclclient(server); | |
| 1135 | + | |
| 1136 | + /* probe the filesystem info for this server filesystem */ | |
| 1137 | + error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo); | |
| 1138 | + if (error < 0) | |
| 1139 | + goto out_free_server; | |
| 1140 | + | |
| 1141 | + dprintk("Cloned FSID: %llx:%llx\n", | |
| 1142 | + (unsigned long long) server->fsid.major, | |
| 1143 | + (unsigned long long) server->fsid.minor); | |
| 1144 | + | |
| 1145 | + error = nfs_start_lockd(server); | |
| 1146 | + if (error < 0) | |
| 1147 | + goto out_free_server; | |
| 1148 | + | |
| 1149 | + spin_lock(&nfs_client_lock); | |
| 1150 | + list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); | |
| 1151 | + list_add_tail(&server->master_link, &nfs_volume_list); | |
| 1152 | + spin_unlock(&nfs_client_lock); | |
| 1153 | + | |
| 1154 | + server->mount_time = jiffies; | |
| 1155 | + | |
| 1156 | + dprintk("<-- nfs_clone_server() = %p\n", server); | |
| 1157 | + return server; | |
| 1158 | + | |
| 1159 | +out_free_server: | |
| 1160 | + nfs_free_server(server); | |
| 1161 | + dprintk("<-- nfs_clone_server() = error %d\n", error); | |
| 1162 | + return ERR_PTR(error); | |
| 1163 | +} | |
| 1164 | + | |
| 1165 | +#ifdef CONFIG_PROC_FS | |
| 1166 | +static struct proc_dir_entry *proc_fs_nfs; | |
| 1167 | + | |
| 1168 | +static int nfs_server_list_open(struct inode *inode, struct file *file); | |
| 1169 | +static void *nfs_server_list_start(struct seq_file *p, loff_t *pos); | |
| 1170 | +static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos); | |
| 1171 | +static void nfs_server_list_stop(struct seq_file *p, void *v); | |
| 1172 | +static int nfs_server_list_show(struct seq_file *m, void *v); | |
| 1173 | + | |
| 1174 | +static struct seq_operations nfs_server_list_ops = { | |
| 1175 | + .start = nfs_server_list_start, | |
| 1176 | + .next = nfs_server_list_next, | |
| 1177 | + .stop = nfs_server_list_stop, | |
| 1178 | + .show = nfs_server_list_show, | |
| 1179 | +}; | |
| 1180 | + | |
| 1181 | +static struct file_operations nfs_server_list_fops = { | |
| 1182 | + .open = nfs_server_list_open, | |
| 1183 | + .read = seq_read, | |
| 1184 | + .llseek = seq_lseek, | |
| 1185 | + .release = seq_release, | |
| 1186 | +}; | |
| 1187 | + | |
| 1188 | +static int nfs_volume_list_open(struct inode *inode, struct file *file); | |
| 1189 | +static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos); | |
| 1190 | +static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos); | |
| 1191 | +static void nfs_volume_list_stop(struct seq_file *p, void *v); | |
| 1192 | +static int nfs_volume_list_show(struct seq_file *m, void *v); | |
| 1193 | + | |
| 1194 | +static struct seq_operations nfs_volume_list_ops = { | |
| 1195 | + .start = nfs_volume_list_start, | |
| 1196 | + .next = nfs_volume_list_next, | |
| 1197 | + .stop = nfs_volume_list_stop, | |
| 1198 | + .show = nfs_volume_list_show, | |
| 1199 | +}; | |
| 1200 | + | |
| 1201 | +static struct file_operations nfs_volume_list_fops = { | |
| 1202 | + .open = nfs_volume_list_open, | |
| 1203 | + .read = seq_read, | |
| 1204 | + .llseek = seq_lseek, | |
| 1205 | + .release = seq_release, | |
| 1206 | +}; | |
| 1207 | + | |
| 1208 | +/* | |
| 1209 | + * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which | |
| 1210 | + * we're dealing | |
| 1211 | + */ | |
| 1212 | +static int nfs_server_list_open(struct inode *inode, struct file *file) | |
| 1213 | +{ | |
| 1214 | + struct seq_file *m; | |
| 1215 | + int ret; | |
| 1216 | + | |
| 1217 | + ret = seq_open(file, &nfs_server_list_ops); | |
| 1218 | + if (ret < 0) | |
| 1219 | + return ret; | |
| 1220 | + | |
| 1221 | + m = file->private_data; | |
| 1222 | + m->private = PDE(inode)->data; | |
| 1223 | + | |
| 1224 | + return 0; | |
| 1225 | +} | |
| 1226 | + | |
| 1227 | +/* | |
| 1228 | + * set up the iterator to start reading from the server list and return the first item | |
| 1229 | + */ | |
| 1230 | +static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) | |
| 1231 | +{ | |
| 1232 | + struct list_head *_p; | |
| 1233 | + loff_t pos = *_pos; | |
| 1234 | + | |
| 1235 | + /* lock the list against modification */ | |
| 1236 | + spin_lock(&nfs_client_lock); | |
| 1237 | + | |
| 1238 | + /* allow for the header line */ | |
| 1239 | + if (!pos) | |
| 1240 | + return SEQ_START_TOKEN; | |
| 1241 | + pos--; | |
| 1242 | + | |
| 1243 | + /* find the n'th element in the list */ | |
| 1244 | + list_for_each(_p, &nfs_client_list) | |
| 1245 | + if (!pos--) | |
| 1246 | + break; | |
| 1247 | + | |
| 1248 | + return _p != &nfs_client_list ? _p : NULL; | |
| 1249 | +} | |
| 1250 | + | |
| 1251 | +/* | |
| 1252 | + * move to next server | |
| 1253 | + */ | |
| 1254 | +static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) | |
| 1255 | +{ | |
| 1256 | + struct list_head *_p; | |
| 1257 | + | |
| 1258 | + (*pos)++; | |
| 1259 | + | |
| 1260 | + _p = v; | |
| 1261 | + _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next; | |
| 1262 | + | |
| 1263 | + return _p != &nfs_client_list ? _p : NULL; | |
| 1264 | +} | |
| 1265 | + | |
| 1266 | +/* | |
| 1267 | + * clean up after reading from the transports list | |
| 1268 | + */ | |
| 1269 | +static void nfs_server_list_stop(struct seq_file *p, void *v) | |
| 1270 | +{ | |
| 1271 | + spin_unlock(&nfs_client_lock); | |
| 1272 | +} | |
| 1273 | + | |
| 1274 | +/* | |
| 1275 | + * display a header line followed by a load of call lines | |
| 1276 | + */ | |
| 1277 | +static int nfs_server_list_show(struct seq_file *m, void *v) | |
| 1278 | +{ | |
| 1279 | + struct nfs_client *clp; | |
| 1280 | + | |
| 1281 | + /* display header on line 1 */ | |
| 1282 | + if (v == SEQ_START_TOKEN) { | |
| 1283 | + seq_puts(m, "NV SERVER PORT USE HOSTNAME\n"); | |
| 1284 | + return 0; | |
| 1285 | + } | |
| 1286 | + | |
| 1287 | + /* display one transport per line on subsequent lines */ | |
| 1288 | + clp = list_entry(v, struct nfs_client, cl_share_link); | |
| 1289 | + | |
| 1290 | + seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n", | |
| 1291 | + clp->cl_nfsversion, | |
| 1292 | + NIPQUAD(clp->cl_addr.sin_addr), | |
| 1293 | + ntohs(clp->cl_addr.sin_port), | |
| 1294 | + atomic_read(&clp->cl_count), | |
| 1295 | + clp->cl_hostname); | |
| 1296 | + | |
| 1297 | + return 0; | |
| 1298 | +} | |
| 1299 | + | |
| 1300 | +/* | |
| 1301 | + * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes | |
| 1302 | + */ | |
| 1303 | +static int nfs_volume_list_open(struct inode *inode, struct file *file) | |
| 1304 | +{ | |
| 1305 | + struct seq_file *m; | |
| 1306 | + int ret; | |
| 1307 | + | |
| 1308 | + ret = seq_open(file, &nfs_volume_list_ops); | |
| 1309 | + if (ret < 0) | |
| 1310 | + return ret; | |
| 1311 | + | |
| 1312 | + m = file->private_data; | |
| 1313 | + m->private = PDE(inode)->data; | |
| 1314 | + | |
| 1315 | + return 0; | |
| 1316 | +} | |
| 1317 | + | |
| 1318 | +/* | |
| 1319 | + * set up the iterator to start reading from the volume list and return the first item | |
| 1320 | + */ | |
| 1321 | +static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) | |
| 1322 | +{ | |
| 1323 | + struct list_head *_p; | |
| 1324 | + loff_t pos = *_pos; | |
| 1325 | + | |
| 1326 | + /* lock the list against modification */ | |
| 1327 | + spin_lock(&nfs_client_lock); | |
| 1328 | + | |
| 1329 | + /* allow for the header line */ | |
| 1330 | + if (!pos) | |
| 1331 | + return SEQ_START_TOKEN; | |
| 1332 | + pos--; | |
| 1333 | + | |
| 1334 | + /* find the n'th element in the list */ | |
| 1335 | + list_for_each(_p, &nfs_volume_list) | |
| 1336 | + if (!pos--) | |
| 1337 | + break; | |
| 1338 | + | |
| 1339 | + return _p != &nfs_volume_list ? _p : NULL; | |
| 1340 | +} | |
| 1341 | + | |
| 1342 | +/* | |
| 1343 | + * move to next volume | |
| 1344 | + */ | |
| 1345 | +static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) | |
| 1346 | +{ | |
| 1347 | + struct list_head *_p; | |
| 1348 | + | |
| 1349 | + (*pos)++; | |
| 1350 | + | |
| 1351 | + _p = v; | |
| 1352 | + _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next; | |
| 1353 | + | |
| 1354 | + return _p != &nfs_volume_list ? _p : NULL; | |
| 1355 | +} | |
| 1356 | + | |
| 1357 | +/* | |
| 1358 | + * clean up after reading from the transports list | |
| 1359 | + */ | |
| 1360 | +static void nfs_volume_list_stop(struct seq_file *p, void *v) | |
| 1361 | +{ | |
| 1362 | + spin_unlock(&nfs_client_lock); | |
| 1363 | +} | |
| 1364 | + | |
| 1365 | +/* | |
| 1366 | + * display a header line followed by a load of call lines | |
| 1367 | + */ | |
| 1368 | +static int nfs_volume_list_show(struct seq_file *m, void *v) | |
| 1369 | +{ | |
| 1370 | + struct nfs_server *server; | |
| 1371 | + struct nfs_client *clp; | |
| 1372 | + char dev[8], fsid[17]; | |
| 1373 | + | |
| 1374 | + /* display header on line 1 */ | |
| 1375 | + if (v == SEQ_START_TOKEN) { | |
| 1376 | + seq_puts(m, "NV SERVER PORT DEV FSID\n"); | |
| 1377 | + return 0; | |
| 1378 | + } | |
| 1379 | + /* display one transport per line on subsequent lines */ | |
| 1380 | + server = list_entry(v, struct nfs_server, master_link); | |
| 1381 | + clp = server->nfs_client; | |
| 1382 | + | |
| 1383 | + snprintf(dev, 8, "%u:%u", | |
| 1384 | + MAJOR(server->s_dev), MINOR(server->s_dev)); | |
| 1385 | + | |
| 1386 | + snprintf(fsid, 17, "%llx:%llx", | |
| 1387 | + (unsigned long long) server->fsid.major, | |
| 1388 | + (unsigned long long) server->fsid.minor); | |
| 1389 | + | |
| 1390 | + seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s\n", | |
| 1391 | + clp->cl_nfsversion, | |
| 1392 | + NIPQUAD(clp->cl_addr.sin_addr), | |
| 1393 | + ntohs(clp->cl_addr.sin_port), | |
| 1394 | + dev, | |
| 1395 | + fsid); | |
| 1396 | + | |
| 1397 | + return 0; | |
| 1398 | +} | |
| 1399 | + | |
| 1400 | +/* | |
| 1401 | + * initialise the /proc/fs/nfsfs/ directory | |
| 1402 | + */ | |
| 1403 | +int __init nfs_fs_proc_init(void) | |
| 1404 | +{ | |
| 1405 | + struct proc_dir_entry *p; | |
| 1406 | + | |
| 1407 | + proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs); | |
| 1408 | + if (!proc_fs_nfs) | |
| 1409 | + goto error_0; | |
| 1410 | + | |
| 1411 | + proc_fs_nfs->owner = THIS_MODULE; | |
| 1412 | + | |
| 1413 | + /* a file of servers with which we're dealing */ | |
| 1414 | + p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs); | |
| 1415 | + if (!p) | |
| 1416 | + goto error_1; | |
| 1417 | + | |
| 1418 | + p->proc_fops = &nfs_server_list_fops; | |
| 1419 | + p->owner = THIS_MODULE; | |
| 1420 | + | |
| 1421 | + /* a file of volumes that we have mounted */ | |
| 1422 | + p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs); | |
| 1423 | + if (!p) | |
| 1424 | + goto error_2; | |
| 1425 | + | |
| 1426 | + p->proc_fops = &nfs_volume_list_fops; | |
| 1427 | + p->owner = THIS_MODULE; | |
| 1428 | + return 0; | |
| 1429 | + | |
| 1430 | +error_2: | |
| 1431 | + remove_proc_entry("servers", proc_fs_nfs); | |
| 1432 | +error_1: | |
| 1433 | + remove_proc_entry("nfsfs", proc_root_fs); | |
| 1434 | +error_0: | |
| 1435 | + return -ENOMEM; | |
| 1436 | +} | |
| 1437 | + | |
| 1438 | +/* | |
| 1439 | + * clean up the /proc/fs/nfsfs/ directory | |
| 1440 | + */ | |
| 1441 | +void nfs_fs_proc_exit(void) | |
| 1442 | +{ | |
| 1443 | + remove_proc_entry("volumes", proc_fs_nfs); | |
| 1444 | + remove_proc_entry("servers", proc_fs_nfs); | |
| 1445 | + remove_proc_entry("nfsfs", proc_root_fs); | |
| 1446 | +} | |
| 1447 | + | |
| 1448 | +#endif /* CONFIG_PROC_FS */ | |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #include "nfs4_fs.h" |
| 20 | 20 | #include "delegation.h" |
| 21 | +#include "internal.h" | |
| 21 | 22 | |
| 22 | 23 | static struct nfs_delegation *nfs_alloc_delegation(void) |
| 23 | 24 | { |
| @@ -52,7 +53,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_ · 28 unmodified lines | ||
| 52 | 53 | case -NFS4ERR_EXPIRED: |
| 53 | 54 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ |
| 54 | 55 | case -NFS4ERR_STALE_CLIENTID: |
| 55 | − nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs4_state); | |
| 56 | + nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs_client); | |
| 56 | 57 | goto out_err; |
| 57 | 58 | } |
| 58 | 59 | } |
| @@ -114,7 +115,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st · 55 unmodified lines | ||
| 114 | 115 | */ |
| 115 | 116 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) |
| 116 | 117 | { |
| 117 | − struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; | |
| 118 | + struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | |
| 118 | 119 | struct nfs_inode *nfsi = NFS_I(inode); |
| 119 | 120 | struct nfs_delegation *delegation; |
| 120 | 121 | int status = 0; |
| @@ -145,7 +146,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct · 24 unmodified lines | ||
| 145 | 146 | sizeof(delegation->stateid)) != 0 || |
| 146 | 147 | delegation->type != nfsi->delegation->type) { |
| 147 | 148 | printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n", |
| 148 | − __FUNCTION__, NIPQUAD(clp->cl_addr)); | |
| 149 | + __FUNCTION__, NIPQUAD(clp->cl_addr.sin_addr)); | |
| 149 | 150 | status = -EIO; |
| 150 | 151 | } |
| 151 | 152 | } |
| @@ -176,7 +177,7 @@ static void nfs_msync_inode(struct inode *inode) · 24 unmodified lines | ||
| 176 | 177 | */ |
| 177 | 178 | int __nfs_inode_return_delegation(struct inode *inode) |
| 178 | 179 | { |
| 179 | − struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; | |
| 180 | + struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | |
| 180 | 181 | struct nfs_inode *nfsi = NFS_I(inode); |
| 181 | 182 | struct nfs_delegation *delegation; |
| 182 | 183 | int res = 0; |
| @@ -208,7 +209,7 @@ int __nfs_inode_return_delegation(struct inode *inode) · 25 unmodified lines | ||
| 208 | 209 | */ |
| 209 | 210 | void nfs_return_all_delegations(struct super_block *sb) |
| 210 | 211 | { |
| 211 | − struct nfs4_client *clp = NFS_SB(sb)->nfs4_state; | |
| 212 | + struct nfs_client *clp = NFS_SB(sb)->nfs_client; | |
| 212 | 213 | struct nfs_delegation *delegation; |
| 213 | 214 | struct inode *inode; |
| 214 | 215 | |
| @@ -232,7 +233,7 @@ restart: · 17 unmodified lines | ||
| 232 | 233 | |
| 233 | 234 | int nfs_do_expire_all_delegations(void *ptr) |
| 234 | 235 | { |
| 235 | − struct nfs4_client *clp = ptr; | |
| 236 | + struct nfs_client *clp = ptr; | |
| 236 | 237 | struct nfs_delegation *delegation; |
| 237 | 238 | struct inode *inode; |
| 238 | 239 | |
| @@ -254,11 +255,11 @@ restart: · 15 unmodified lines | ||
| 254 | 255 | } |
| 255 | 256 | out: |
| 256 | 257 | spin_unlock(&clp->cl_lock); |
| 257 | − nfs4_put_client(clp); | |
| 258 | + nfs_put_client(clp); | |
| 258 | 259 | module_put_and_exit(0); |
| 259 | 260 | } |
| 260 | 261 | |
| 261 | −void nfs_expire_all_delegations(struct nfs4_client *clp) | |
| 262 | +void nfs_expire_all_delegations(struct nfs_client *clp) | |
| 262 | 263 | { |
| 263 | 264 | struct task_struct *task; |
| 264 | 265 | |
| @@ -266,17 +267,17 @@ void nfs_expire_all_delegations(struct nfs4_client *clp) · 1 unmodified line | ||
| 266 | 267 | atomic_inc(&clp->cl_count); |
| 267 | 268 | task = kthread_run(nfs_do_expire_all_delegations, clp, |
| 268 | 269 | "%u.%u.%u.%u-delegreturn", |
| 269 | − NIPQUAD(clp->cl_addr)); | |
| 270 | + NIPQUAD(clp->cl_addr.sin_addr)); | |
| 270 | 271 | if (!IS_ERR(task)) |
| 271 | 272 | return; |
| 272 | − nfs4_put_client(clp); | |
| 273 | + nfs_put_client(clp); | |
| 273 | 274 | module_put(THIS_MODULE); |
| 274 | 275 | } |
| 275 | 276 | |
| 276 | 277 | /* |
| 277 | 278 | * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. |
| 278 | 279 | */ |
| 279 | −void nfs_handle_cb_pathdown(struct nfs4_client *clp) | |
| 280 | +void nfs_handle_cb_pathdown(struct nfs_client *clp) | |
| 280 | 281 | { |
| 281 | 282 | struct nfs_delegation *delegation; |
| 282 | 283 | struct inode *inode; |
| @@ -299,7 +300,7 @@ restart: · 16 unmodified lines | ||
| 299 | 300 | |
| 300 | 301 | struct recall_threadargs { |
| 301 | 302 | struct inode *inode; |
| 302 | − struct nfs4_client *clp; | |
| 303 | + struct nfs_client *clp; | |
| 303 | 304 | const nfs4_stateid *stateid; |
| 304 | 305 | |
| 305 | 306 | struct completion started; |
| @@ -310,7 +311,7 @@ static int recall_thread(void *data) · 4 unmodified lines | ||
| 310 | 311 | { |
| 311 | 312 | struct recall_threadargs *args = (struct recall_threadargs *)data; |
| 312 | 313 | struct inode *inode = igrab(args->inode); |
| 313 | − struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; | |
| 314 | + struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | |
| 314 | 315 | struct nfs_inode *nfsi = NFS_I(inode); |
| 315 | 316 | struct nfs_delegation *delegation; |
| 316 | 317 | |
| @@ -371,7 +372,7 @@ out_module_put: · 54 unmodified lines | ||
| 371 | 372 | /* |
| 372 | 373 | * Retrieve the inode associated with a delegation |
| 373 | 374 | */ |
| 374 | −struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle) | |
| 375 | +struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle) | |
| 375 | 376 | { |
| 376 | 377 | struct nfs_delegation *delegation; |
| 377 | 378 | struct inode *res = NULL; |
| @@ -389,7 +390,7 @@ struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nf · 11 unmodified lines | ||
| 389 | 390 | /* |
| 390 | 391 | * Mark all delegations as needing to be reclaimed |
| 391 | 392 | */ |
| 392 | −void nfs_delegation_mark_reclaim(struct nfs4_client *clp) | |
| 393 | +void nfs_delegation_mark_reclaim(struct nfs_client *clp) | |
| 393 | 394 | { |
| 394 | 395 | struct nfs_delegation *delegation; |
| 395 | 396 | spin_lock(&clp->cl_lock); |
| @@ -401,7 +402,7 @@ void nfs_delegation_mark_reclaim(struct nfs4_client *clp) · 5 unmodified lines | ||
| 401 | 402 | /* |
| 402 | 403 | * Reap all unclaimed delegations after reboot recovery is done |
| 403 | 404 | */ |
| 404 | −void nfs_delegation_reap_unclaimed(struct nfs4_client *clp) | |
| 405 | +void nfs_delegation_reap_unclaimed(struct nfs_client *clp) | |
| 405 | 406 | { |
| 406 | 407 | struct nfs_delegation *delegation, *n; |
| 407 | 408 | LIST_HEAD(head); |
| @@ -423,7 +424,7 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp) · 15 unmodified lines | ||
| 423 | 424 | |
| 424 | 425 | int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode) |
| 425 | 426 | { |
| 426 | − struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; | |
| 427 | + struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | |
| 427 | 428 | struct nfs_inode *nfsi = NFS_I(inode); |
| 428 | 429 | struct nfs_delegation *delegation; |
| 429 | 430 | int res = 0; |
| @@ -29,13 +29,13 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st · 28 unmodified lines | ||
| 29 | 29 | int __nfs_inode_return_delegation(struct inode *inode); |
| 30 | 30 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); |
| 31 | 31 | |
| 32 | −struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle); | |
| 32 | +struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); | |
| 33 | 33 | void nfs_return_all_delegations(struct super_block *sb); |
| 34 | −void nfs_expire_all_delegations(struct nfs4_client *clp); | |
| 35 | −void nfs_handle_cb_pathdown(struct nfs4_client *clp); | |
| 34 | +void nfs_expire_all_delegations(struct nfs_client *clp); | |
| 35 | +void nfs_handle_cb_pathdown(struct nfs_client *clp); | |
| 36 | 36 | |
| 37 | −void nfs_delegation_mark_reclaim(struct nfs4_client *clp); | |
| 38 | −void nfs_delegation_reap_unclaimed(struct nfs4_client *clp); | |
| 37 | +void nfs_delegation_mark_reclaim(struct nfs_client *clp); | |
| 38 | +void nfs_delegation_reap_unclaimed(struct nfs_client *clp); | |
| 39 | 39 | |
| 40 | 40 | /* NFSv4 delegation-related procedures */ |
| 41 | 41 | int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid); |
| @@ -30,7 +30,9 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <linux/nfs_mount.h> |
| 31 | 31 | #include <linux/pagemap.h> |
| 32 | 32 | #include <linux/smp_lock.h> |
| 33 | +#include <linux/pagevec.h> | |
| 33 | 34 | #include <linux/namei.h> |
| 35 | +#include <linux/mount.h> | |
| 34 | 36 | |
| 35 | 37 | #include "nfs4_fs.h" |
| 36 | 38 | #include "delegation.h" |
| @@ -870,14 +872,14 @@ int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) · 833 unmodified lines | ||
| 870 | 872 | return (nd->intent.open.flags & O_EXCL) != 0; |
| 871 | 873 | } |
| 872 | 874 | |
| 873 | −static inline int nfs_reval_fsid(struct inode *dir, | |
| 874 | − struct nfs_fh *fh, struct nfs_fattr *fattr) | |
| 875 | +static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir, | |
| 876 | + struct nfs_fh *fh, struct nfs_fattr *fattr) | |
| 875 | 877 | { |
| 876 | 878 | struct nfs_server *server = NFS_SERVER(dir); |
| 877 | 879 | |
| 878 | 880 | if (!nfs_fsid_equal(&server->fsid, &fattr->fsid)) |
| 879 | 881 | /* Revalidate fsid on root dir */ |
| 880 | − return __nfs_revalidate_inode(server, dir->i_sb->s_root->d_inode); | |
| 882 | + return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode); | |
| 881 | 883 | return 0; |
| 882 | 884 | } |
| 883 | 885 | |
| @@ -902,9 +904,15 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru · 18 unmodified lines | ||
| 902 | 904 | |
| 903 | 905 | lock_kernel(); |
| 904 | 906 | |
| 905 | − /* If we're doing an exclusive create, optimize away the lookup */ | |
| 906 | − if (nfs_is_exclusive_create(dir, nd)) | |
| 907 | − goto no_entry; | |
| 907 | + /* | |
| 908 | + * If we're doing an exclusive create, optimize away the lookup | |
| 909 | + * but don't hash the dentry. | |
| 910 | + */ | |
| 911 | + if (nfs_is_exclusive_create(dir, nd)) { | |
| 912 | + d_instantiate(dentry, NULL); | |
| 913 | + res = NULL; | |
| 914 | + goto out_unlock; | |
| 915 | + } | |
| 908 | 916 | |
| 909 | 917 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); |
| 910 | 918 | if (error == -ENOENT) |
| @@ -913,7 +921,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru · 2 unmodified lines | ||
| 913 | 921 | res = ERR_PTR(error); |
| 914 | 922 | goto out_unlock; |
| 915 | 923 | } |
| 916 | − error = nfs_reval_fsid(dir, &fhandle, &fattr); | |
| 924 | + error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr); | |
| 917 | 925 | if (error < 0) { |
| 918 | 926 | res = ERR_PTR(error); |
| 919 | 927 | goto out_unlock; |
| @@ -922,8 +930,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru · 2 unmodified lines | ||
| 922 | 930 | res = (struct dentry *)inode; |
| 923 | 931 | if (IS_ERR(res)) |
| 924 | 932 | goto out_unlock; |
| 933 | + | |
| 925 | 934 | no_entry: |
| 926 | − res = d_add_unique(dentry, inode); | |
| 935 | + res = d_materialise_unique(dentry, inode); | |
| 927 | 936 | if (res != NULL) |
| 928 | 937 | dentry = res; |
| 929 | 938 | nfs_renew_times(dentry); |
| @@ -1117,11 +1126,13 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) · 187 unmodified lines | ||
| 1117 | 1126 | dput(dentry); |
| 1118 | 1127 | return NULL; |
| 1119 | 1128 | } |
| 1120 | − alias = d_add_unique(dentry, inode); | |
| 1129 | + | |
| 1130 | + alias = d_materialise_unique(dentry, inode); | |
| 1121 | 1131 | if (alias != NULL) { |
| 1122 | 1132 | dput(dentry); |
| 1123 | 1133 | dentry = alias; |
| 1124 | 1134 | } |
| 1135 | + | |
| 1125 | 1136 | nfs_renew_times(dentry); |
| 1126 | 1137 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 1127 | 1138 | return dentry; |
| @@ -1143,23 +1154,22 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, · 15 unmodified lines | ||
| 1143 | 1154 | struct inode *dir = dentry->d_parent->d_inode; |
| 1144 | 1155 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); |
| 1145 | 1156 | if (error) |
| 1146 | − goto out_err; | |
| 1157 | + return error; | |
| 1147 | 1158 | } |
| 1148 | 1159 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
| 1149 | 1160 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
| 1150 | − error = server->rpc_ops->getattr(server, fhandle, fattr); | |
| 1161 | + error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); | |
| 1151 | 1162 | if (error < 0) |
| 1152 | − goto out_err; | |
| 1163 | + return error; | |
| 1153 | 1164 | } |
| 1154 | 1165 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); |
| 1155 | 1166 | error = PTR_ERR(inode); |
| 1156 | 1167 | if (IS_ERR(inode)) |
| 1157 | − goto out_err; | |
| 1168 | + return error; | |
| 1158 | 1169 | d_instantiate(dentry, inode); |
| 1170 | + if (d_unhashed(dentry)) | |
| 1171 | + d_rehash(dentry); | |
| 1159 | 1172 | return 0; |
| 1160 | −out_err: | |
| 1161 | − d_drop(dentry); | |
| 1162 | − return error; | |
| 1163 | 1173 | } |
| 1164 | 1174 | |
| 1165 | 1175 | /* |
| @@ -1440,48 +1450,82 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) · 274 unmodified lines | ||
| 1440 | 1450 | return error; |
| 1441 | 1451 | } |
| 1442 | 1452 | |
| 1443 | −static int | |
| 1444 | −nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |
| 1453 | +/* | |
| 1454 | + * To create a symbolic link, most file systems instantiate a new inode, | |
| 1455 | + * add a page to it containing the path, then write it out to the disk | |
| 1456 | + * using prepare_write/commit_write. | |
| 1457 | + * | |
| 1458 | + * Unfortunately the NFS client can't create the in-core inode first | |
| 1459 | + * because it needs a file handle to create an in-core inode (see | |
| 1460 | + * fs/nfs/inode.c:nfs_fhget). We only have a file handle *after* the | |
| 1461 | + * symlink request has completed on the server. | |
| 1462 | + * | |
| 1463 | + * So instead we allocate a raw page, copy the symname into it, then do | |
| 1464 | + * the SYMLINK request with the page as the buffer. If it succeeds, we | |
| 1465 | + * now have a new file handle and can instantiate an in-core NFS inode | |
| 1466 | + * and move the raw page into its mapping. | |
| 1467 | + */ | |
| 1468 | +static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |
| 1445 | 1469 | { |
| 1470 | + struct pagevec lru_pvec; | |
| 1471 | + struct page *page; | |
| 1472 | + char *kaddr; | |
| 1446 | 1473 | struct iattr attr; |
| 1447 | − struct nfs_fattr sym_attr; | |
| 1448 | − struct nfs_fh sym_fh; | |
| 1449 | − struct qstr qsymname; | |
| 1474 | + unsigned int pathlen = strlen(symname); | |
| 1450 | 1475 | int error; |
| 1451 | 1476 | |
| 1452 | 1477 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id, |
| 1453 | 1478 | dir->i_ino, dentry->d_name.name, symname); |
| 1454 | 1479 | |
| 1455 | −#ifdef NFS_PARANOIA | |
| 1456 | −if (dentry->d_inode) | |
| 1457 | −printk("nfs_proc_symlink: %s/%s not negative!\n", | |
| 1458 | −dentry->d_parent->d_name.name, dentry->d_name.name); | |
| 1459 | −#endif | |
| 1460 | − /* | |
| 1461 | − * Fill in the sattr for the call. | |
| 1462 | − * Note: SunOS 4.1.2 crashes if the mode isn't initialized! | |
| 1463 | − */ | |
| 1464 | − attr.ia_valid = ATTR_MODE; | |
| 1465 | − attr.ia_mode = S_IFLNK | S_IRWXUGO; | |
| 1480 | + if (pathlen > PAGE_SIZE) | |
| 1481 | + return -ENAMETOOLONG; | |
| 1466 | 1482 | |
| 1467 | − qsymname.name = symname; | |
| 1468 | − qsymname.len = strlen(symname); | |
| 1483 | + attr.ia_mode = S_IFLNK | S_IRWXUGO; | |
| 1484 | + attr.ia_valid = ATTR_MODE; | |
| 1469 | 1485 | |
| 1470 | 1486 | lock_kernel(); |
| 1487 | + | |
| 1488 | + page = alloc_page(GFP_KERNEL); | |
| 1489 | + if (!page) { | |
| 1490 | + unlock_kernel(); | |
| 1491 | + return -ENOMEM; | |
| 1492 | + } | |
| 1493 | + | |
| 1494 | + kaddr = kmap_atomic(page, KM_USER0); | |
| 1495 | + memcpy(kaddr, symname, pathlen); | |
| 1496 | + if (pathlen < PAGE_SIZE) | |
| 1497 | + memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); | |
| 1498 | + kunmap_atomic(kaddr, KM_USER0); | |
| 1499 | + | |
| 1471 | 1500 | nfs_begin_data_update(dir); |
| 1472 | − error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname, | |
| 1473 | − &attr, &sym_fh, &sym_attr); | |
| 1501 | + error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); | |
| 1474 | 1502 | nfs_end_data_update(dir); |
| 1475 | − if (!error) { | |
| 1476 | − error = nfs_instantiate(dentry, &sym_fh, &sym_attr); | |
| 1477 | − } else { | |
| 1478 | − if (error == -EEXIST) | |
| 1479 | − printk("nfs_proc_symlink: %s/%s already exists??\n", | |
| 1480 | − dentry->d_parent->d_name.name, dentry->d_name.name); | |
| 1503 | + if (error != 0) { | |
| 1504 | + dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", | |
| 1505 | + dir->i_sb->s_id, dir->i_ino, | |
| 1506 | + dentry->d_name.name, symname, error); | |
| 1481 | 1507 | d_drop(dentry); |
| 1508 | + __free_page(page); | |
| 1509 | + unlock_kernel(); | |
| 1510 | + return error; | |
| 1482 | 1511 | } |
| 1512 | + | |
| 1513 | + /* | |
| 1514 | + * No big deal if we can't add this page to the page cache here. | |
| 1515 | + * READLINK will get the missing page from the server if needed. | |
| 1516 | + */ | |
| 1517 | + pagevec_init(&lru_pvec, 0); | |
| 1518 | + if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0, | |
| 1519 | + GFP_KERNEL)) { | |
| 1520 | + if (!pagevec_add(&lru_pvec, page)) | |
| 1521 | + __pagevec_lru_add(&lru_pvec); | |
| 1522 | + SetPageUptodate(page); | |
| 1523 | + unlock_page(page); | |
| 1524 | + } else | |
| 1525 | + __free_page(page); | |
| 1526 | + | |
| 1483 | 1527 | unlock_kernel(); |
| 1484 | − return error; | |
| 1528 | + return 0; | |
| 1485 | 1529 | } |
| 1486 | 1530 | |
| 1487 | 1531 | static int |
| @@ -1638,35 +1682,211 @@ out: · 150 unmodified lines | ||
| 1638 | 1682 | return error; |
| 1639 | 1683 | } |
| 1640 | 1684 | |
| 1685 | +static DEFINE_SPINLOCK(nfs_access_lru_lock); | |
| 1686 | +static LIST_HEAD(nfs_access_lru_list); | |
| 1687 | +static atomic_long_t nfs_access_nr_entries; | |
| 1688 | + | |
| 1689 | +static void nfs_access_free_entry(struct nfs_access_entry *entry) | |
| 1690 | +{ | |
| 1691 | + put_rpccred(entry->cred); | |
| 1692 | + kfree(entry); | |
| 1693 | + smp_mb__before_atomic_dec(); | |
| 1694 | + atomic_long_dec(&nfs_access_nr_entries); | |
| 1695 | + smp_mb__after_atomic_dec(); | |
| 1696 | +} | |
| 1697 | + | |
| 1698 | +int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) | |
| 1699 | +{ | |
| 1700 | + LIST_HEAD(head); | |
| 1701 | + struct nfs_inode *nfsi; | |
| 1702 | + struct nfs_access_entry *cache; | |
| 1703 | + | |
| 1704 | + spin_lock(&nfs_access_lru_lock); | |
| 1705 | +restart: | |
| 1706 | + list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) { | |
| 1707 | + struct inode *inode; | |
| 1708 | + | |
| 1709 | + if (nr_to_scan-- == 0) | |
| 1710 | + break; | |
| 1711 | + inode = igrab(&nfsi->vfs_inode); | |
| 1712 | + if (inode == NULL) | |
| 1713 | + continue; | |
| 1714 | + spin_lock(&inode->i_lock); | |
| 1715 | + if (list_empty(&nfsi->access_cache_entry_lru)) | |
| 1716 | + goto remove_lru_entry; | |
| 1717 | + cache = list_entry(nfsi->access_cache_entry_lru.next, | |
| 1718 | + struct nfs_access_entry, lru); | |
| 1719 | + list_move(&cache->lru, &head); | |
| 1720 | + rb_erase(&cache->rb_node, &nfsi->access_cache); | |
| 1721 | + if (!list_empty(&nfsi->access_cache_entry_lru)) | |
| 1722 | + list_move_tail(&nfsi->access_cache_inode_lru, | |
| 1723 | + &nfs_access_lru_list); | |
| 1724 | + else { | |
| 1725 | +remove_lru_entry: | |
| 1726 | + list_del_init(&nfsi->access_cache_inode_lru); | |
| 1727 | + clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags); | |
| 1728 | + } | |
| 1729 | + spin_unlock(&inode->i_lock); | |
| 1730 | + iput(inode); | |
| 1731 | + goto restart; | |
| 1732 | + } | |
| 1733 | + spin_unlock(&nfs_access_lru_lock); | |
| 1734 | + while (!list_empty(&head)) { | |
| 1735 | + cache = list_entry(head.next, struct nfs_access_entry, lru); | |
| 1736 | + list_del(&cache->lru); | |
| 1737 | + nfs_access_free_entry(cache); | |
| 1738 | + } | |
| 1739 | + return (atomic_long_read(&nfs_access_nr_entries) / 100) * sysctl_vfs_cache_pressure; | |
| 1740 | +} | |
| 1741 | + | |
| 1742 | +static void __nfs_access_zap_cache(struct inode *inode) | |
| 1743 | +{ | |
| 1744 | + struct nfs_inode *nfsi = NFS_I(inode); | |
| 1745 | + struct rb_root *root_node = &nfsi->access_cache; | |
| 1746 | + struct rb_node *n, *dispose = NULL; | |
| 1747 | + struct nfs_access_entry *entry; | |
| 1748 | + | |
| 1749 | + /* Unhook entries from the cache */ | |
| 1750 | + while ((n = rb_first(root_node)) != NULL) { | |
| 1751 | + entry = rb_entry(n, struct nfs_access_entry, rb_node); | |
| 1752 | + rb_erase(n, root_node); | |
| 1753 | + list_del(&entry->lru); | |
| 1754 | + n->rb_left = dispose; | |
| 1755 | + dispose = n; | |
| 1756 | + } | |
| 1757 | + nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS; | |
| 1758 | + spin_unlock(&inode->i_lock); | |
| 1759 | + | |
| 1760 | + /* Now kill them all! */ | |
| 1761 | + while (dispose != NULL) { | |
| 1762 | + n = dispose; | |
| 1763 | + dispose = n->rb_left; | |
| 1764 | + nfs_access_free_entry(rb_entry(n, struct nfs_access_entry, rb_node)); | |
| 1765 | + } | |
| 1766 | +} | |
| 1767 | + | |
| 1768 | +void nfs_access_zap_cache(struct inode *inode) | |
| 1769 | +{ | |
| 1770 | + /* Remove from global LRU init */ | |
| 1771 | + if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { | |
| 1772 | + spin_lock(&nfs_access_lru_lock); | |
| 1773 | + list_del_init(&NFS_I(inode)->access_cache_inode_lru); | |
| 1774 | + spin_unlock(&nfs_access_lru_lock); | |
| 1775 | + } | |
| 1776 | + | |
| 1777 | + spin_lock(&inode->i_lock); | |
| 1778 | + /* This will release the spinlock */ | |
| 1779 | + __nfs_access_zap_cache(inode); | |
| 1780 | +} | |
| 1781 | + | |
| 1782 | +static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, struct rpc_cred *cred) | |
| 1783 | +{ | |
| 1784 | + struct rb_node *n = NFS_I(inode)->access_cache.rb_node; | |
| 1785 | + struct nfs_access_entry *entry; | |
| 1786 | + | |
| 1787 | + while (n != NULL) { | |
| 1788 | + entry = rb_entry(n, struct nfs_access_entry, rb_node); | |
| 1789 | + | |
| 1790 | + if (cred < entry->cred) | |
| 1791 | + n = n->rb_left; | |
| 1792 | + else if (cred > entry->cred) | |
| 1793 | + n = n->rb_right; | |
| 1794 | + else | |
| 1795 | + return entry; | |
| 1796 | + } | |
| 1797 | + return NULL; | |
| 1798 | +} | |
| 1799 | + | |
| 1641 | 1800 | int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) |
| 1642 | 1801 | { |
| 1643 | 1802 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1644 | − struct nfs_access_entry *cache = &nfsi->cache_access; | |
| 1803 | + struct nfs_access_entry *cache; | |
| 1804 | + int err = -ENOENT; | |
| 1645 | 1805 | |
| 1646 | − if (cache->cred != cred | |
| 1647 | − || time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode)) | |
| 1648 | − || (nfsi->cache_validity & NFS_INO_INVALID_ACCESS)) | |
| 1649 | − return -ENOENT; | |
| 1650 | − memcpy(res, cache, sizeof(*res)); | |
| 1651 | − return 0; | |
| 1806 | + spin_lock(&inode->i_lock); | |
| 1807 | + if (nfsi->cache_validity & NFS_INO_INVALID_ACCESS) | |
| 1808 | + goto out_zap; | |
| 1809 | + cache = nfs_access_search_rbtree(inode, cred); | |
| 1810 | + if (cache == NULL) | |
| 1811 | + goto out; | |
| 1812 | + if (time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))) | |
| 1813 | + goto out_stale; | |
| 1814 | + res->jiffies = cache->jiffies; | |
| 1815 | + res->cred = cache->cred; | |
| 1816 | + res->mask = cache->mask; | |
| 1817 | + list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru); | |
| 1818 | + err = 0; | |
| 1819 | +out: | |
| 1820 | + spin_unlock(&inode->i_lock); | |
| 1821 | + return err; | |
| 1822 | +out_stale: | |
| 1823 | + rb_erase(&cache->rb_node, &nfsi->access_cache); | |
| 1824 | + list_del(&cache->lru); | |
| 1825 | + spin_unlock(&inode->i_lock); | |
| 1826 | + nfs_access_free_entry(cache); | |
| 1827 | + return -ENOENT; | |
| 1828 | +out_zap: | |
| 1829 | + /* This will release the spinlock */ | |
| 1830 | + __nfs_access_zap_cache(inode); | |
| 1831 | + return -ENOENT; | |
| 1652 | 1832 | } |
| 1653 | 1833 | |
| 1654 | −void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) | |
| 1834 | +static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set) | |
| 1655 | 1835 | { |
| 1656 | 1836 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1657 | − struct nfs_access_entry *cache = &nfsi->cache_access; | |
| 1837 | + struct rb_root *root_node = &nfsi->access_cache; | |
| 1838 | + struct rb_node **p = &root_node->rb_node; | |
| 1839 | + struct rb_node *parent = NULL; | |
| 1840 | + struct nfs_access_entry *entry; | |
| 1658 | 1841 | |
| 1659 | − if (cache->cred != set->cred) { | |
| 1660 | − if (cache->cred) | |
| 1661 | − put_rpccred(cache->cred); | |
| 1662 | − cache->cred = get_rpccred(set->cred); | |
| 1663 | − } | |
| 1664 | − /* FIXME: replace current access_cache BKL reliance with inode->i_lock */ | |
| 1665 | 1842 | spin_lock(&inode->i_lock); |
| 1666 | − nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS; | |
| 1843 | + while (*p != NULL) { | |
| 1844 | + parent = *p; | |
| 1845 | + entry = rb_entry(parent, struct nfs_access_entry, rb_node); | |
| 1846 | + | |
| 1847 | + if (set->cred < entry->cred) | |
| 1848 | + p = &parent->rb_left; | |
| 1849 | + else if (set->cred > entry->cred) | |
| 1850 | + p = &parent->rb_right; | |
| 1851 | + else | |
| 1852 | + goto found; | |
| 1853 | + } | |
| 1854 | + rb_link_node(&set->rb_node, parent, p); | |
| 1855 | + rb_insert_color(&set->rb_node, root_node); | |
| 1856 | + list_add_tail(&set->lru, &nfsi->access_cache_entry_lru); | |
| 1667 | 1857 | spin_unlock(&inode->i_lock); |
| 1858 | + return; | |
| 1859 | +found: | |
| 1860 | + rb_replace_node(parent, &set->rb_node, root_node); | |
| 1861 | + list_add_tail(&set->lru, &nfsi->access_cache_entry_lru); | |
| 1862 | + list_del(&entry->lru); | |
| 1863 | + spin_unlock(&inode->i_lock); | |
| 1864 | + nfs_access_free_entry(entry); | |
| 1865 | +} | |
| 1866 | + | |
| 1867 | +void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) | |
| 1868 | +{ | |
| 1869 | + struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); | |
| 1870 | + if (cache == NULL) | |
| 1871 | + return; | |
| 1872 | + RB_CLEAR_NODE(&cache->rb_node); | |
| 1668 | 1873 | cache->jiffies = set->jiffies; |
| 1874 | + cache->cred = get_rpccred(set->cred); | |
| 1669 | 1875 | cache->mask = set->mask; |
| 1876 | + | |
| 1877 | + nfs_access_add_rbtree(inode, cache); | |
| 1878 | + | |
| 1879 | + /* Update accounting */ | |
| 1880 | + smp_mb__before_atomic_inc(); | |
| 1881 | + atomic_long_inc(&nfs_access_nr_entries); | |
| 1882 | + smp_mb__after_atomic_inc(); | |
| 1883 | + | |
| 1884 | + /* Add inode to global LRU list */ | |
| 1885 | + if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { | |
| 1886 | + spin_lock(&nfs_access_lru_lock); | |
| 1887 | + list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list); | |
| 1888 | + spin_unlock(&nfs_access_lru_lock); | |
| 1889 | + } | |
| 1670 | 1890 | } |
| 1671 | 1891 | |
| 1672 | 1892 | static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) |
| @@ -111,7 +111,7 @@ nfs_file_open(struct inode *inode, struct file *filp) · 110 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | nfs_inc_stats(inode, NFSIOS_VFSOPEN); |
| 113 | 113 | lock_kernel(); |
| 114 | − res = NFS_SERVER(inode)->rpc_ops->file_open(inode, filp); | |
| 114 | + res = NFS_PROTO(inode)->file_open(inode, filp); | |
| 115 | 115 | unlock_kernel(); |
| 116 | 116 | return res; |
| 117 | 117 | } |
| @@ -157,7 +157,7 @@ force_reval: · 39 unmodified lines | ||
| 157 | 157 | static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) |
| 158 | 158 | { |
| 159 | 159 | /* origin == SEEK_END => we must revalidate the cached file length */ |
| 160 | − if (origin == 2) { | |
| 160 | + if (origin == SEEK_END) { | |
| 161 | 161 | struct inode *inode = filp->f_mapping->host; |
| 162 | 162 | int retval = nfs_revalidate_file_size(inode, filp); |
| 163 | 163 | if (retval < 0) |
| @@ -0,0 +1,311 @@ | ||
| 1 | +/* getroot.c: get the root dentry for an NFS mount | |
| 2 | + * | |
| 3 | + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | |
| 4 | + * Written by David Howells (dhowells@redhat.com) | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU General Public License | |
| 8 | + * as published by the Free Software Foundation; either version | |
| 9 | + * 2 of the License, or (at your option) any later version. | |
| 10 | + */ | |
| 11 | + | |
| 12 | +#include <linux/config.h> | |
| 13 | +#include <linux/module.h> | |
| 14 | +#include <linux/init.h> | |
| 15 | + | |
| 16 | +#include <linux/time.h> | |
| 17 | +#include <linux/kernel.h> | |
| 18 | +#include <linux/mm.h> | |
| 19 | +#include <linux/string.h> | |
| 20 | +#include <linux/stat.h> | |
| 21 | +#include <linux/errno.h> | |
| 22 | +#include <linux/unistd.h> | |
| 23 | +#include <linux/sunrpc/clnt.h> | |
| 24 | +#include <linux/sunrpc/stats.h> | |
| 25 | +#include <linux/nfs_fs.h> | |
| 26 | +#include <linux/nfs_mount.h> | |
| 27 | +#include <linux/nfs4_mount.h> | |
| 28 | +#include <linux/lockd/bind.h> | |
| 29 | +#include <linux/smp_lock.h> | |
| 30 | +#include <linux/seq_file.h> | |
| 31 | +#include <linux/mount.h> | |
| 32 | +#include <linux/nfs_idmap.h> | |
| 33 | +#include <linux/vfs.h> | |
| 34 | +#include <linux/namei.h> | |
| 35 | +#include <linux/namespace.h> | |
| 36 | +#include <linux/security.h> | |
| 37 | + | |
| 38 | +#include <asm/system.h> | |
| 39 | +#include <asm/uaccess.h> | |
| 40 | + | |
| 41 | +#include "nfs4_fs.h" | |
| 42 | +#include "delegation.h" | |
| 43 | +#include "internal.h" | |
| 44 | + | |
| 45 | +#define NFSDBG_FACILITY NFSDBG_CLIENT | |
| 46 | +#define NFS_PARANOIA 1 | |
| 47 | + | |
| 48 | +/* | |
| 49 | + * get an NFS2/NFS3 root dentry from the root filehandle | |
| 50 | + */ | |
| 51 | +struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |
| 52 | +{ | |
| 53 | + struct nfs_server *server = NFS_SB(sb); | |
| 54 | + struct nfs_fsinfo fsinfo; | |
| 55 | + struct nfs_fattr fattr; | |
| 56 | + struct dentry *mntroot; | |
| 57 | + struct inode *inode; | |
| 58 | + int error; | |
| 59 | + | |
| 60 | + /* create a dummy root dentry with dummy inode for this superblock */ | |
| 61 | + if (!sb->s_root) { | |
| 62 | + struct nfs_fh dummyfh; | |
| 63 | + struct dentry *root; | |
| 64 | + struct inode *iroot; | |
| 65 | + | |
| 66 | + memset(&dummyfh, 0, sizeof(dummyfh)); | |
| 67 | + memset(&fattr, 0, sizeof(fattr)); | |
| 68 | + nfs_fattr_init(&fattr); | |
| 69 | + fattr.valid = NFS_ATTR_FATTR; | |
| 70 | + fattr.type = NFDIR; | |
| 71 | + fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; | |
| 72 | + fattr.nlink = 2; | |
| 73 | + | |
| 74 | + iroot = nfs_fhget(sb, &dummyfh, &fattr); | |
| 75 | + if (IS_ERR(iroot)) | |
| 76 | + return ERR_PTR(PTR_ERR(iroot)); | |
| 77 | + | |
| 78 | + root = d_alloc_root(iroot); | |
| 79 | + if (!root) { | |
| 80 | + iput(iroot); | |
| 81 | + return ERR_PTR(-ENOMEM); | |
| 82 | + } | |
| 83 | + | |
| 84 | + sb->s_root = root; | |
| 85 | + } | |
| 86 | + | |
| 87 | + /* get the actual root for this mount */ | |
| 88 | + fsinfo.fattr = &fattr; | |
| 89 | + | |
| 90 | + error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); | |
| 91 | + if (error < 0) { | |
| 92 | + dprintk("nfs_get_root: getattr error = %d\n", -error); | |
| 93 | + return ERR_PTR(error); | |
| 94 | + } | |
| 95 | + | |
| 96 | + inode = nfs_fhget(sb, mntfh, fsinfo.fattr); | |
| 97 | + if (IS_ERR(inode)) { | |
| 98 | + dprintk("nfs_get_root: get root inode failed\n"); | |
| 99 | + return ERR_PTR(PTR_ERR(inode)); | |
| 100 | + } | |
| 101 | + | |
| 102 | + /* root dentries normally start off anonymous and get spliced in later | |
| 103 | + * if the dentry tree reaches them; however if the dentry already | |
| 104 | + * exists, we'll pick it up at this point and use it as the root | |
| 105 | + */ | |
| 106 | + mntroot = d_alloc_anon(inode); | |
| 107 | + if (!mntroot) { | |
| 108 | + iput(inode); | |
| 109 | + dprintk("nfs_get_root: get root dentry failed\n"); | |
| 110 | + return ERR_PTR(-ENOMEM); | |
| 111 | + } | |
| 112 | + | |
| 113 | + security_d_instantiate(mntroot, inode); | |
| 114 | + | |
| 115 | + if (!mntroot->d_op) | |
| 116 | + mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; | |
| 117 | + | |
| 118 | + return mntroot; | |
| 119 | +} | |
| 120 | + | |
| 121 | +#ifdef CONFIG_NFS_V4 | |
| 122 | + | |
| 123 | +/* | |
| 124 | + * Do a simple pathwalk from the root FH of the server to the nominated target | |
| 125 | + * of the mountpoint | |
| 126 | + * - give error on symlinks | |
| 127 | + * - give error on ".." occurring in the path | |
| 128 | + * - follow traversals | |
| 129 | + */ | |
| 130 | +int nfs4_path_walk(struct nfs_server *server, | |
| 131 | + struct nfs_fh *mntfh, | |
| 132 | + const char *path) | |
| 133 | +{ | |
| 134 | + struct nfs_fsinfo fsinfo; | |
| 135 | + struct nfs_fattr fattr; | |
| 136 | + struct nfs_fh lastfh; | |
| 137 | + struct qstr name; | |
| 138 | + int ret; | |
| 139 | + //int referral_count = 0; | |
| 140 | + | |
| 141 | + dprintk("--> nfs4_path_walk(,,%s)\n", path); | |
| 142 | + | |
| 143 | + fsinfo.fattr = &fattr; | |
| 144 | + nfs_fattr_init(&fattr); | |
| 145 | + | |
| 146 | + if (*path++ != '/') { | |
| 147 | + dprintk("nfs4_get_root: Path does not begin with a slash\n"); | |
| 148 | + return -EINVAL; | |
| 149 | + } | |
| 150 | + | |
| 151 | + /* Start by getting the root filehandle from the server */ | |
| 152 | + ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); | |
| 153 | + if (ret < 0) { | |
| 154 | + dprintk("nfs4_get_root: getroot error = %d\n", -ret); | |
| 155 | + return ret; | |
| 156 | + } | |
| 157 | + | |
| 158 | + if (fattr.type != NFDIR) { | |
| 159 | + printk(KERN_ERR "nfs4_get_root:" | |
| 160 | + " getroot encountered non-directory\n"); | |
| 161 | + return -ENOTDIR; | |
| 162 | + } | |
| 163 | + | |
| 164 | + if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { | |
| 165 | + printk(KERN_ERR "nfs4_get_root:" | |
| 166 | + " getroot obtained referral\n"); | |
| 167 | + return -EREMOTE; | |
| 168 | + } | |
| 169 | + | |
| 170 | +next_component: | |
| 171 | + dprintk("Next: %s\n", path); | |
| 172 | + | |
| 173 | + /* extract the next bit of the path */ | |
| 174 | + if (!*path) | |
| 175 | + goto path_walk_complete; | |
| 176 | + | |
| 177 | + name.name = path; | |
| 178 | + while (*path && *path != '/') | |
| 179 | + path++; | |
| 180 | + name.len = path - (const char *) name.name; | |
| 181 | + | |
| 182 | +eat_dot_dir: | |
| 183 | + while (*path == '/') | |
| 184 | + path++; | |
| 185 | + | |
| 186 | + if (path[0] == '.' && (path[1] == '/' || !path[1])) { | |
| 187 | + path += 2; | |
| 188 | + goto eat_dot_dir; | |
| 189 | + } | |
| 190 | + | |
| 191 | + if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2]) | |
| 192 | + ) { | |
| 193 | + printk(KERN_ERR "nfs4_get_root:" | |
| 194 | + " Mount path contains reference to \"..\"\n"); | |
| 195 | + return -EINVAL; | |
| 196 | + } | |
| 197 | + | |
| 198 | + /* lookup the next FH in the sequence */ | |
| 199 | + memcpy(&lastfh, mntfh, sizeof(lastfh)); | |
| 200 | + | |
| 201 | + dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path); | |
| 202 | + | |
| 203 | + ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name, | |
| 204 | + mntfh, &fattr); | |
| 205 | + if (ret < 0) { | |
| 206 | + dprintk("nfs4_get_root: getroot error = %d\n", -ret); | |
| 207 | + return ret; | |
| 208 | + } | |
| 209 | + | |
| 210 | + if (fattr.type != NFDIR) { | |
| 211 | + printk(KERN_ERR "nfs4_get_root:" | |
| 212 | + " lookupfh encountered non-directory\n"); | |
| 213 | + return -ENOTDIR; | |
| 214 | + } | |
| 215 | + | |
| 216 | + if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { | |
| 217 | + printk(KERN_ERR "nfs4_get_root:" | |
| 218 | + " lookupfh obtained referral\n"); | |
| 219 | + return -EREMOTE; | |
| 220 | + } | |
| 221 | + | |
| 222 | + goto next_component; | |
| 223 | + | |
| 224 | +path_walk_complete: | |
| 225 | + memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); | |
| 226 | + dprintk("<-- nfs4_path_walk() = 0\n"); | |
| 227 | + return 0; | |
| 228 | +} | |
| 229 | + | |
| 230 | +/* | |
| 231 | + * get an NFS4 root dentry from the root filehandle | |
| 232 | + */ | |
| 233 | +struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |
| 234 | +{ | |
| 235 | + struct nfs_server *server = NFS_SB(sb); | |
| 236 | + struct nfs_fattr fattr; | |
| 237 | + struct dentry *mntroot; | |
| 238 | + struct inode *inode; | |
| 239 | + int error; | |
| 240 | + | |
| 241 | + dprintk("--> nfs4_get_root()\n"); | |
| 242 | + | |
| 243 | + /* create a dummy root dentry with dummy inode for this superblock */ | |
| 244 | + if (!sb->s_root) { | |
| 245 | + struct nfs_fh dummyfh; | |
| 246 | + struct dentry *root; | |
| 247 | + struct inode *iroot; | |
| 248 | + | |
| 249 | + memset(&dummyfh, 0, sizeof(dummyfh)); | |
| 250 | + memset(&fattr, 0, sizeof(fattr)); | |
| 251 | + nfs_fattr_init(&fattr); | |
| 252 | + fattr.valid = NFS_ATTR_FATTR; | |
| 253 | + fattr.type = NFDIR; | |
| 254 | + fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; | |
| 255 | + fattr.nlink = 2; | |
| 256 | + | |
| 257 | + iroot = nfs_fhget(sb, &dummyfh, &fattr); | |
| 258 | + if (IS_ERR(iroot)) | |
| 259 | + return ERR_PTR(PTR_ERR(iroot)); | |
| 260 | + | |
| 261 | + root = d_alloc_root(iroot); | |
| 262 | + if (!root) { | |
| 263 | + iput(iroot); | |
| 264 | + return ERR_PTR(-ENOMEM); | |
| 265 | + } | |
| 266 | + | |
| 267 | + sb->s_root = root; | |
| 268 | + } | |
| 269 | + | |
| 270 | + /* get the info about the server and filesystem */ | |
| 271 | + error = nfs4_server_capabilities(server, mntfh); | |
| 272 | + if (error < 0) { | |
| 273 | + dprintk("nfs_get_root: getcaps error = %d\n", | |
| 274 | + -error); | |
| 275 | + return ERR_PTR(error); | |
| 276 | + } | |
| 277 | + | |
| 278 | + /* get the actual root for this mount */ | |
| 279 | + error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); | |
| 280 | + if (error < 0) { | |
| 281 | + dprintk("nfs_get_root: getattr error = %d\n", -error); | |
| 282 | + return ERR_PTR(error); | |
| 283 | + } | |
| 284 | + | |
| 285 | + inode = nfs_fhget(sb, mntfh, &fattr); | |
| 286 | + if (IS_ERR(inode)) { | |
| 287 | + dprintk("nfs_get_root: get root inode failed\n"); | |
| 288 | + return ERR_PTR(PTR_ERR(inode)); | |
| 289 | + } | |
| 290 | + | |
| 291 | + /* root dentries normally start off anonymous and get spliced in later | |
| 292 | + * if the dentry tree reaches them; however if the dentry already | |
| 293 | + * exists, we'll pick it up at this point and use it as the root | |
| 294 | + */ | |
| 295 | + mntroot = d_alloc_anon(inode); | |
| 296 | + if (!mntroot) { | |
| 297 | + iput(inode); | |
| 298 | + dprintk("nfs_get_root: get root dentry failed\n"); | |
| 299 | + return ERR_PTR(-ENOMEM); | |
| 300 | + } | |
| 301 | + | |
| 302 | + security_d_instantiate(mntroot, inode); | |
| 303 | + | |
| 304 | + if (!mntroot->d_op) | |
| 305 | + mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; | |
| 306 | + | |
| 307 | + dprintk("<-- nfs4_get_root()\n"); | |
| 308 | + return mntroot; | |
| 309 | +} | |
| 310 | + | |
| 311 | +#endif /* CONFIG_NFS_V4 */ | |
| @@ -57,6 +57,20 @@ · 56 unmodified lines | ||
| 57 | 57 | /* Default cache timeout is 10 minutes */ |
| 58 | 58 | unsigned int nfs_idmap_cache_timeout = 600 * HZ; |
| 59 | 59 | |
| 60 | +static int param_set_idmap_timeout(const char *val, struct kernel_param *kp) | |
| 61 | +{ | |
| 62 | + char *endp; | |
| 63 | + int num = simple_strtol(val, &endp, 0); | |
| 64 | + int jif = num * HZ; | |
| 65 | + if (endp == val || *endp || num < 0 || jif < num) | |
| 66 | + return -EINVAL; | |
| 67 | + *((int *)kp->arg) = jif; | |
| 68 | + return 0; | |
| 69 | +} | |
| 70 | + | |
| 71 | +module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, | |
| 72 | + &nfs_idmap_cache_timeout, 0644); | |
| 73 | + | |
| 60 | 74 | struct idmap_hashent { |
| 61 | 75 | unsigned long ih_expires; |
| 62 | 76 | __u32 ih_id; |
| @@ -70,7 +84,6 @@ struct idmap_hashtable { · 7 unmodified lines | ||
| 70 | 84 | }; |
| 71 | 85 | |
| 72 | 86 | struct idmap { |
| 73 | − char idmap_path[48]; | |
| 74 | 87 | struct dentry *idmap_dentry; |
| 75 | 88 | wait_queue_head_t idmap_wq; |
| 76 | 89 | struct idmap_msg idmap_im; |
| @@ -94,24 +107,23 @@ static struct rpc_pipe_ops idmap_upcall_ops = { · 17 unmodified lines | ||
| 94 | 107 | .destroy_msg = idmap_pipe_destroy_msg, |
| 95 | 108 | }; |
| 96 | 109 | |
| 97 | −void | |
| 98 | −nfs_idmap_new(struct nfs4_client *clp) | |
| 110 | +int | |
| 111 | +nfs_idmap_new(struct nfs_client *clp) | |
| 99 | 112 | { |
| 100 | 113 | struct idmap *idmap; |
| 114 | + int error; | |
| 101 | 115 | |
| 102 | − if (clp->cl_idmap != NULL) | |
| 103 | − return; | |
| 104 | − if ((idmap = kzalloc(sizeof(*idmap), GFP_KERNEL)) == NULL) | |
| 105 | − return; | |
| 116 | + BUG_ON(clp->cl_idmap != NULL); | |
| 106 | 117 | |
| 107 | − snprintf(idmap->idmap_path, sizeof(idmap->idmap_path), | |
| 108 | − "%s/idmap", clp->cl_rpcclient->cl_pathname); | |
| 118 | + if ((idmap = kzalloc(sizeof(*idmap), GFP_KERNEL)) == NULL) | |
| 119 | + return -ENOMEM; | |
| 109 | 120 | |
| 110 | − idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path, | |
| 121 | + idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_dentry, "idmap", | |
| 111 | 122 | idmap, &idmap_upcall_ops, 0); |
| 112 | 123 | if (IS_ERR(idmap->idmap_dentry)) { |
| 124 | + error = PTR_ERR(idmap->idmap_dentry); | |
| 113 | 125 | kfree(idmap); |
| 114 | − return; | |
| 126 | + return error; | |
| 115 | 127 | } |
| 116 | 128 | |
| 117 | 129 | mutex_init(&idmap->idmap_lock); |
| @@ -121,10 +133,11 @@ nfs_idmap_new(struct nfs4_client *clp) · 3 unmodified lines | ||
| 121 | 133 | idmap->idmap_group_hash.h_type = IDMAP_TYPE_GROUP; |
| 122 | 134 | |
| 123 | 135 | clp->cl_idmap = idmap; |
| 136 | + return 0; | |
| 124 | 137 | } |
| 125 | 138 | |
| 126 | 139 | void |
| 127 | −nfs_idmap_delete(struct nfs4_client *clp) | |
| 140 | +nfs_idmap_delete(struct nfs_client *clp) | |
| 128 | 141 | { |
| 129 | 142 | struct idmap *idmap = clp->cl_idmap; |
| 130 | 143 | |
| @@ -477,27 +490,27 @@ static unsigned int fnvhash32(const void *buf, size_t buflen) · 346 unmodified lines | ||
| 477 | 490 | return (hash); |
| 478 | 491 | } |
| 479 | 492 | |
| 480 | −int nfs_map_name_to_uid(struct nfs4_client *clp, const char *name, size_t namelen, __u32 *uid) | |
| 493 | +int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) | |
| 481 | 494 | { |
| 482 | 495 | struct idmap *idmap = clp->cl_idmap; |
| 483 | 496 | |
| 484 | 497 | return nfs_idmap_id(idmap, &idmap->idmap_user_hash, name, namelen, uid); |
| 485 | 498 | } |
| 486 | 499 | |
| 487 | −int nfs_map_group_to_gid(struct nfs4_client *clp, const char *name, size_t namelen, __u32 *uid) | |
| 500 | +int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) | |
| 488 | 501 | { |
| 489 | 502 | struct idmap *idmap = clp->cl_idmap; |
| 490 | 503 | |
| 491 | 504 | return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid); |
| 492 | 505 | } |
| 493 | 506 | |
| 494 | −int nfs_map_uid_to_name(struct nfs4_client *clp, __u32 uid, char *buf) | |
| 507 | +int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf) | |
| 495 | 508 | { |
| 496 | 509 | struct idmap *idmap = clp->cl_idmap; |
| 497 | 510 | |
| 498 | 511 | return nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); |
| 499 | 512 | } |
| 500 | −int nfs_map_gid_to_group(struct nfs4_client *clp, __u32 uid, char *buf) | |
| 513 | +int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf) | |
| 501 | 514 | { |
| 502 | 515 | struct idmap *idmap = clp->cl_idmap; |
| 503 | 516 | |
| @@ -76,19 +76,14 @@ int nfs_write_inode(struct inode *inode, int sync) · 75 unmodified lines | ||
| 76 | 76 | |
| 77 | 77 | void nfs_clear_inode(struct inode *inode) |
| 78 | 78 | { |
| 79 | − struct nfs_inode *nfsi = NFS_I(inode); | |
| 80 | − struct rpc_cred *cred; | |
| 81 | − | |
| 82 | 79 | /* |
| 83 | 80 | * The following should never happen... |
| 84 | 81 | */ |
| 85 | 82 | BUG_ON(nfs_have_writebacks(inode)); |
| 86 | − BUG_ON (!list_empty(&nfsi->open_files)); | |
| 83 | + BUG_ON(!list_empty(&NFS_I(inode)->open_files)); | |
| 84 | + BUG_ON(atomic_read(&NFS_I(inode)->data_updates) != 0); | |
| 87 | 85 | nfs_zap_acl_cache(inode); |
| 88 | − cred = nfsi->cache_access.cred; | |
| 89 | − if (cred) | |
| 90 | − put_rpccred(cred); | |
| 91 | − BUG_ON(atomic_read(&nfsi->data_updates) != 0); | |
| 86 | + nfs_access_zap_cache(inode); | |
| 92 | 87 | } |
| 93 | 88 | |
| 94 | 89 | /** |
| @@ -242,13 +237,13 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) · 147 unmodified lines | ||
| 242 | 237 | /* Why so? Because we want revalidate for devices/FIFOs, and |
| 243 | 238 | * that's precisely what we have in nfs_file_inode_operations. |
| 244 | 239 | */ |
| 245 | − inode->i_op = NFS_SB(sb)->rpc_ops->file_inode_ops; | |
| 240 | + inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->file_inode_ops; | |
| 246 | 241 | if (S_ISREG(inode->i_mode)) { |
| 247 | 242 | inode->i_fop = &nfs_file_operations; |
| 248 | 243 | inode->i_data.a_ops = &nfs_file_aops; |
| 249 | 244 | inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info; |
| 250 | 245 | } else if (S_ISDIR(inode->i_mode)) { |
| 251 | − inode->i_op = NFS_SB(sb)->rpc_ops->dir_inode_ops; | |
| 246 | + inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops; | |
| 252 | 247 | inode->i_fop = &nfs_dir_operations; |
| 253 | 248 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) |
| 254 | 249 | && fattr->size <= NFS_LIMIT_READDIRPLUS) |
| @@ -290,7 +285,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) · 35 unmodified lines | ||
| 290 | 285 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 291 | 286 | nfsi->attrtimeo_timestamp = jiffies; |
| 292 | 287 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
| 293 | − nfsi->cache_access.cred = NULL; | |
| 288 | + nfsi->access_cache = RB_ROOT; | |
| 294 | 289 | |
| 295 | 290 | unlock_new_inode(inode); |
| 296 | 291 | } else |
| @@ -722,13 +717,11 @@ void nfs_end_data_update(struct inode *inode) · 425 unmodified lines | ||
| 722 | 717 | { |
| 723 | 718 | struct nfs_inode *nfsi = NFS_I(inode); |
| 724 | 719 | |
| 725 | − if (!nfs_have_delegation(inode, FMODE_READ)) { | |
| 726 | − /* Directories and symlinks: invalidate page cache */ | |
| 727 | − if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { | |
| 728 | − spin_lock(&inode->i_lock); | |
| 729 | − nfsi->cache_validity |= NFS_INO_INVALID_DATA; | |
| 730 | − spin_unlock(&inode->i_lock); | |
| 731 | − } | |
| 720 | + /* Directories: invalidate page cache */ | |
| 721 | + if (S_ISDIR(inode->i_mode)) { | |
| 722 | + spin_lock(&inode->i_lock); | |
| 723 | + nfsi->cache_validity |= NFS_INO_INVALID_DATA; | |
| 724 | + spin_unlock(&inode->i_lock); | |
| 732 | 725 | } |
| 733 | 726 | nfsi->cache_change_attribute = jiffies; |
| 734 | 727 | atomic_dec(&nfsi->data_updates); |
| @@ -847,6 +840,12 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) · 112 unmodified lines | ||
| 847 | 840 | * |
| 848 | 841 | * After an operation that has changed the inode metadata, mark the |
| 849 | 842 | * attribute cache as being invalid, then try to update it. |
| 843 | + * | |
| 844 | + * NB: if the server didn't return any post op attributes, this | |
| 845 | + * function will force the retrieval of attributes before the next | |
| 846 | + * NFS request. Thus it should be used only for operations that | |
| 847 | + * are expected to change one or more attributes, to avoid | |
| 848 | + * unnecessary NFS requests and trips through nfs_update_inode(). | |
| 850 | 849 | */ |
| 851 | 850 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 852 | 851 | { |
| @@ -1025,7 +1024,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) · 172 unmodified lines | ||
| 1025 | 1024 | out_fileid: |
| 1026 | 1025 | printk(KERN_ERR "NFS: server %s error: fileid changed\n" |
| 1027 | 1026 | "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", |
| 1028 | − NFS_SERVER(inode)->hostname, inode->i_sb->s_id, | |
| 1027 | + NFS_SERVER(inode)->nfs_client->cl_hostname, inode->i_sb->s_id, | |
| 1029 | 1028 | (long long)nfsi->fileid, (long long)fattr->fileid); |
| 1030 | 1029 | goto out_err; |
| 1031 | 1030 | } |
| @@ -1109,6 +1108,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) · 77 unmodified lines | ||
| 1109 | 1108 | INIT_LIST_HEAD(&nfsi->dirty); |
| 1110 | 1109 | INIT_LIST_HEAD(&nfsi->commit); |
| 1111 | 1110 | INIT_LIST_HEAD(&nfsi->open_files); |
| 1111 | + INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); | |
| 1112 | + INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); | |
| 1112 | 1113 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); |
| 1113 | 1114 | atomic_set(&nfsi->data_updates, 0); |
| 1114 | 1115 | nfsi->ndirty = 0; |
| @@ -1144,6 +1145,10 @@ static int __init init_nfs_fs(void) · 29 unmodified lines | ||
| 1144 | 1145 | { |
| 1145 | 1146 | int err; |
| 1146 | 1147 | |
| 1148 | + err = nfs_fs_proc_init(); | |
| 1149 | + if (err) | |
| 1150 | + goto out5; | |
| 1151 | + | |
| 1147 | 1152 | err = nfs_init_nfspagecache(); |
| 1148 | 1153 | if (err) |
| 1149 | 1154 | goto out4; |
| @@ -1184,6 +1189,8 @@ out2: · 34 unmodified lines | ||
| 1184 | 1189 | out3: |
| 1185 | 1190 | nfs_destroy_nfspagecache(); |
| 1186 | 1191 | out4: |
| 1192 | + nfs_fs_proc_exit(); | |
| 1193 | +out5: | |
| 1187 | 1194 | return err; |
| 1188 | 1195 | } |
| 1189 | 1196 | |
| @@ -1198,6 +1205,7 @@ static void __exit exit_nfs_fs(void) · 8 unmodified lines | ||
| 1198 | 1205 | rpc_proc_unregister("nfs"); |
| 1199 | 1206 | #endif |
| 1200 | 1207 | unregister_nfs_fs(); |
| 1208 | + nfs_fs_proc_exit(); | |
| 1201 | 1209 | } |
| 1202 | 1210 | |
| 1203 | 1211 | /* Not quite true; I just maintain it */ |
| @@ -4,6 +4,18 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #include <linux/mount.h> |
| 6 | 6 | |
| 7 | +struct nfs_string; | |
| 8 | +struct nfs_mount_data; | |
| 9 | +struct nfs4_mount_data; | |
| 10 | + | |
| 11 | +/* Maximum number of readahead requests | |
| 12 | + * FIXME: this should really be a sysctl so that users may tune it to suit | |
| 13 | + * their needs. People that do NFS over a slow network, might for | |
| 14 | + * instance want to reduce it to something closer to 1 for improved | |
| 15 | + * interactive response. | |
| 16 | + */ | |
| 17 | +#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) | |
| 18 | + | |
| 7 | 19 | struct nfs_clone_mount { |
| 8 | 20 | const struct super_block *sb; |
| 9 | 21 | const struct dentry *dentry; |
| @@ -15,7 +27,40 @@ struct nfs_clone_mount { · 5 unmodified lines | ||
| 15 | 27 | rpc_authflavor_t authflavor; |
| 16 | 28 | }; |
| 17 | 29 | |
| 18 | −/* namespace-nfs4.c */ | |
| 30 | +/* client.c */ | |
| 31 | +extern struct rpc_program nfs_program; | |
| 32 | + | |
| 33 | +extern void nfs_put_client(struct nfs_client *); | |
| 34 | +extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int); | |
| 35 | +extern struct nfs_server *nfs_create_server(const struct nfs_mount_data *, | |
| 36 | + struct nfs_fh *); | |
| 37 | +extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *, | |
| 38 | + const char *, | |
| 39 | + const struct sockaddr_in *, | |
| 40 | + const char *, | |
| 41 | + const char *, | |
| 42 | + rpc_authflavor_t, | |
| 43 | + struct nfs_fh *); | |
| 44 | +extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, | |
| 45 | + struct nfs_fh *); | |
| 46 | +extern void nfs_free_server(struct nfs_server *server); | |
| 47 | +extern struct nfs_server *nfs_clone_server(struct nfs_server *, | |
| 48 | + struct nfs_fh *, | |
| 49 | + struct nfs_fattr *); | |
| 50 | +#ifdef CONFIG_PROC_FS | |
| 51 | +extern int __init nfs_fs_proc_init(void); | |
| 52 | +extern void nfs_fs_proc_exit(void); | |
| 53 | +#else | |
| 54 | +static inline int nfs_fs_proc_init(void) | |
| 55 | +{ | |
| 56 | + return 0; | |
| 57 | +} | |
| 58 | +static inline void nfs_fs_proc_exit(void) | |
| 59 | +{ | |
| 60 | +} | |
| 61 | +#endif | |
| 62 | + | |
| 63 | +/* nfs4namespace.c */ | |
| 19 | 64 | #ifdef CONFIG_NFS_V4 |
| 20 | 65 | extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry); |
| 21 | 66 | #else |
| @@ -46,6 +91,7 @@ extern void nfs_destroy_directcache(void); · 24 unmodified lines | ||
| 46 | 91 | #endif |
| 47 | 92 | |
| 48 | 93 | /* nfs2xdr.c */ |
| 94 | +extern int nfs_stat_to_errno(int); | |
| 49 | 95 | extern struct rpc_procinfo nfs_procedures[]; |
| 50 | 96 | extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); |
| 51 | 97 | |
| @@ -54,8 +100,9 @@ extern struct rpc_procinfo nfs3_procedures[]; · 2 unmodified lines | ||
| 54 | 100 | extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); |
| 55 | 101 | |
| 56 | 102 | /* nfs4xdr.c */ |
| 57 | −extern int nfs_stat_to_errno(int); | |
| 103 | +#ifdef CONFIG_NFS_V4 | |
| 58 | 104 | extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); |
| 105 | +#endif | |
| 59 | 106 | |
| 60 | 107 | /* nfs4proc.c */ |
| 61 | 108 | #ifdef CONFIG_NFS_V4 |
| @@ -66,6 +113,9 @@ extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, · 4 unmodified lines | ||
| 66 | 113 | struct page *page); |
| 67 | 114 | #endif |
| 68 | 115 | |
| 116 | +/* dir.c */ | |
| 117 | +extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); | |
| 118 | + | |
| 69 | 119 | /* inode.c */ |
| 70 | 120 | extern struct inode *nfs_alloc_inode(struct super_block *sb); |
| 71 | 121 | extern void nfs_destroy_inode(struct inode *); |
| @@ -76,10 +126,10 @@ extern void nfs4_clear_inode(struct inode *); · 4 unmodified lines | ||
| 76 | 126 | #endif |
| 77 | 127 | |
| 78 | 128 | /* super.c */ |
| 79 | −extern struct file_system_type nfs_referral_nfs4_fs_type; | |
| 80 | −extern struct file_system_type clone_nfs_fs_type; | |
| 129 | +extern struct file_system_type nfs_xdev_fs_type; | |
| 81 | 130 | #ifdef CONFIG_NFS_V4 |
| 82 | −extern struct file_system_type clone_nfs4_fs_type; | |
| 131 | +extern struct file_system_type nfs4_xdev_fs_type; | |
| 132 | +extern struct file_system_type nfs4_referral_fs_type; | |
| 83 | 133 | #endif |
| 84 | 134 | |
| 85 | 135 | extern struct rpc_stat nfs_rpcstat; |
| @@ -88,30 +138,30 @@ extern int __init register_nfs_fs(void); · 2 unmodified lines | ||
| 88 | 138 | extern void __exit unregister_nfs_fs(void); |
| 89 | 139 | |
| 90 | 140 | /* namespace.c */ |
| 91 | −extern char *nfs_path(const char *base, const struct dentry *dentry, | |
| 141 | +extern char *nfs_path(const char *base, | |
| 142 | + const struct dentry *droot, | |
| 143 | + const struct dentry *dentry, | |
| 92 | 144 | char *buffer, ssize_t buflen); |
| 93 | 145 | |
| 94 | −/* | |
| 95 | − * Determine the mount path as a string | |
| 96 | − */ | |
| 97 | −static inline char * | |
| 98 | −nfs4_path(const struct dentry *dentry, char *buffer, ssize_t buflen) | |
| 99 | −{ | |
| 146 | +/* getroot.c */ | |
| 147 | +extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *); | |
| 100 | 148 | #ifdef CONFIG_NFS_V4 |
| 101 | − return nfs_path(NFS_SB(dentry->d_sb)->mnt_path, dentry, buffer, buflen); | |
| 102 | −#else | |
| 103 | − return NULL; | |
| 149 | +extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); | |
| 150 | + | |
| 151 | +extern int nfs4_path_walk(struct nfs_server *server, | |
| 152 | + struct nfs_fh *mntfh, | |
| 153 | + const char *path); | |
| 104 | 154 | #endif |
| 105 | −} | |
| 106 | 155 | |
| 107 | 156 | /* |
| 108 | 157 | * Determine the device name as a string |
| 109 | 158 | */ |
| 110 | 159 | static inline char *nfs_devname(const struct vfsmount *mnt_parent, |
| 111 | − const struct dentry *dentry, | |
| 112 | − char *buffer, ssize_t buflen) | |
| 160 | + const struct dentry *dentry, | |
| 161 | + char *buffer, ssize_t buflen) | |
| 113 | 162 | { |
| 114 | − return nfs_path(mnt_parent->mnt_devname, dentry, buffer, buflen); | |
| 163 | + return nfs_path(mnt_parent->mnt_devname, mnt_parent->mnt_root, | |
| 164 | + dentry, buffer, buflen); | |
| 115 | 165 | } |
| 116 | 166 | |
| 117 | 167 | /* |
| @@ -167,20 +217,3 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) · 49 unmodified lines | ||
| 167 | 217 | if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0) |
| 168 | 218 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
| 169 | 219 | } |
| 170 | − | |
| 171 | −/* | |
| 172 | − * Check if the string represents a "valid" IPv4 address | |
| 173 | − */ | |
| 174 | −static inline int valid_ipaddr4(const char *buf) | |
| 175 | −{ | |
| 176 | − int rc, count, in[4]; | |
| 177 | − | |
| 178 | − rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); | |
| 179 | − if (rc != 4) | |
| 180 | − return -EINVAL; | |
| 181 | − for (count = 0; count < 4; count++) { | |
| 182 | − if (in[count] > 255) | |
| 183 | − return -EINVAL; | |
| 184 | − } | |
| 185 | − return 0; | |
| 186 | −} | |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/net.h> |
| 15 | 15 | #include <linux/in.h> |
| 16 | 16 | #include <linux/sunrpc/clnt.h> |
| 17 | −#include <linux/sunrpc/xprt.h> | |
| 18 | 17 | #include <linux/sunrpc/sched.h> |
| 19 | 18 | #include <linux/nfs_fs.h> |
| 20 | 19 | |
| @@ -77,22 +76,19 @@ static struct rpc_clnt * · 56 unmodified lines | ||
| 77 | 76 | mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version, |
| 78 | 77 | int protocol) |
| 79 | 78 | { |
| 80 | − struct rpc_xprt *xprt; | |
| 81 | − struct rpc_clnt *clnt; | |
| 82 | − | |
| 83 | − xprt = xprt_create_proto(protocol, srvaddr, NULL); | |
| 84 | − if (IS_ERR(xprt)) | |
| 85 | − return (struct rpc_clnt *)xprt; | |
| 86 | − | |
| 87 | − clnt = rpc_create_client(xprt, hostname, | |
| 88 | − &mnt_program, version, | |
| 89 | − RPC_AUTH_UNIX); | |
| 90 | − if (!IS_ERR(clnt)) { | |
| 91 | − clnt->cl_softrtry = 1; | |
| 92 | − clnt->cl_oneshot = 1; | |
| 93 | − clnt->cl_intr = 1; | |
| 94 | − } | |
| 95 | − return clnt; | |
| 79 | + struct rpc_create_args args = { | |
| 80 | + .protocol = protocol, | |
| 81 | + .address = (struct sockaddr *)srvaddr, | |
| 82 | + .addrsize = sizeof(*srvaddr), | |
| 83 | + .servername = hostname, | |
| 84 | + .program = &mnt_program, | |
| 85 | + .version = version, | |
| 86 | + .authflavor = RPC_AUTH_UNIX, | |
| 87 | + .flags = (RPC_CLNT_CREATE_ONESHOT | | |
| 88 | + RPC_CLNT_CREATE_INTR), | |
| 89 | + }; | |
| 90 | + | |
| 91 | + return rpc_create(&args); | |
| 96 | 92 | } |
| 97 | 93 | |
| 98 | 94 | /* |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | * linux/fs/nfs/namespace.c |
| 3 | 3 | * |
| 4 | 4 | * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com> |
| 5 | + * - Modified by David Howells <dhowells@redhat.com> | |
| 5 | 6 | * |
| 6 | 7 | * NFS namespace |
| 7 | 8 | */ |
| @@ -28,6 +29,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; · 20 unmodified lines | ||
| 28 | 29 | /* |
| 29 | 30 | * nfs_path - reconstruct the path given an arbitrary dentry |
| 30 | 31 | * @base - arbitrary string to prepend to the path |
| 32 | + * @droot - pointer to root dentry for mountpoint | |
| 31 | 33 | * @dentry - pointer to dentry |
| 32 | 34 | * @buffer - result buffer |
| 33 | 35 | * @buflen - length of buffer |
| @@ -38,7 +40,9 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; · 4 unmodified lines | ||
| 38 | 40 | * This is mainly for use in figuring out the path on the |
| 39 | 41 | * server side when automounting on top of an existing partition. |
| 40 | 42 | */ |
| 41 | −char *nfs_path(const char *base, const struct dentry *dentry, | |
| 43 | +char *nfs_path(const char *base, | |
| 44 | + const struct dentry *droot, | |
| 45 | + const struct dentry *dentry, | |
| 42 | 46 | char *buffer, ssize_t buflen) |
| 43 | 47 | { |
| 44 | 48 | char *end = buffer+buflen; |
| @@ -47,7 +51,7 @@ char *nfs_path(const char *base, const struct dentry *dentry, · 2 unmodified lines | ||
| 47 | 51 | *--end = '\0'; |
| 48 | 52 | buflen--; |
| 49 | 53 | spin_lock(&dcache_lock); |
| 50 | − while (!IS_ROOT(dentry)) { | |
| 54 | + while (!IS_ROOT(dentry) && dentry != droot) { | |
| 51 | 55 | namelen = dentry->d_name.len; |
| 52 | 56 | buflen -= namelen + 1; |
| 53 | 57 | if (buflen < 0) |
| @@ -96,15 +100,18 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) · 42 unmodified lines | ||
| 96 | 100 | struct nfs_fattr fattr; |
| 97 | 101 | int err; |
| 98 | 102 | |
| 103 | + dprintk("--> nfs_follow_mountpoint()\n"); | |
| 104 | + | |
| 99 | 105 | BUG_ON(IS_ROOT(dentry)); |
| 100 | 106 | dprintk("%s: enter\n", __FUNCTION__); |
| 101 | 107 | dput(nd->dentry); |
| 102 | 108 | nd->dentry = dget(dentry); |
| 103 | − if (d_mountpoint(nd->dentry)) | |
| 104 | − goto out_follow; | |
| 109 | + | |
| 105 | 110 | /* Look it up again */ |
| 106 | 111 | parent = dget_parent(nd->dentry); |
| 107 | − err = server->rpc_ops->lookup(parent->d_inode, &nd->dentry->d_name, &fh, &fattr); | |
| 112 | + err = server->nfs_client->rpc_ops->lookup(parent->d_inode, | |
| 113 | + &nd->dentry->d_name, | |
| 114 | + &fh, &fattr); | |
| 108 | 115 | dput(parent); |
| 109 | 116 | if (err != 0) |
| 110 | 117 | goto out_err; |
| @@ -132,6 +139,8 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) · 21 unmodified lines | ||
| 132 | 139 | schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout); |
| 133 | 140 | out: |
| 134 | 141 | dprintk("%s: done, returned %d\n", __FUNCTION__, err); |
| 142 | + | |
| 143 | + dprintk("<-- nfs_follow_mountpoint() = %d\n", err); | |
| 135 | 144 | return ERR_PTR(err); |
| 136 | 145 | out_err: |
| 137 | 146 | path_release(nd); |
| @@ -172,22 +181,23 @@ void nfs_release_automount_timer(void) · 34 unmodified lines | ||
| 172 | 181 | /* |
| 173 | 182 | * Clone a mountpoint of the appropriate type |
| 174 | 183 | */ |
| 175 | −static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, char *devname, | |
| 184 | +static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, | |
| 185 | + const char *devname, | |
| 176 | 186 | struct nfs_clone_mount *mountdata) |
| 177 | 187 | { |
| 178 | 188 | #ifdef CONFIG_NFS_V4 |
| 179 | 189 | struct vfsmount *mnt = NULL; |
| 180 | − switch (server->rpc_ops->version) { | |
| 190 | + switch (server->nfs_client->cl_nfsversion) { | |
| 181 | 191 | case 2: |
| 182 | 192 | case 3: |
| 183 | − mnt = vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata); | |
| 193 | + mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); | |
| 184 | 194 | break; |
| 185 | 195 | case 4: |
| 186 | − mnt = vfs_kern_mount(&clone_nfs4_fs_type, 0, devname, mountdata); | |
| 196 | + mnt = vfs_kern_mount(&nfs4_xdev_fs_type, 0, devname, mountdata); | |
| 187 | 197 | } |
| 188 | 198 | return mnt; |
| 189 | 199 | #else |
| 190 | − return vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata); | |
| 200 | + return vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); | |
| 191 | 201 | #endif |
| 192 | 202 | } |
| 193 | 203 | |
| @@ -213,6 +223,8 @@ struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, · 19 unmodified lines | ||
| 213 | 223 | char *page = (char *) __get_free_page(GFP_USER); |
| 214 | 224 | char *devname; |
| 215 | 225 | |
| 226 | + dprintk("--> nfs_do_submount()\n"); | |
| 227 | + | |
| 216 | 228 | dprintk("%s: submounting on %s/%s\n", __FUNCTION__, |
| 217 | 229 | dentry->d_parent->d_name.name, |
| 218 | 230 | dentry->d_name.name); |
| @@ -227,5 +239,7 @@ free_page: · 8 unmodified lines | ||
| 227 | 239 | free_page((unsigned long)page); |
| 228 | 240 | out: |
| 229 | 241 | dprintk("%s: done\n", __FUNCTION__); |
| 242 | + | |
| 243 | + dprintk("<-- nfs_do_submount() = %p\n", mnt); | |
| 230 | 244 | return mnt; |
| 231 | 245 | } |
| @@ -51,7 +51,7 @@ · 50 unmodified lines | ||
| 51 | 51 | #define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz) |
| 52 | 52 | #define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz) |
| 53 | 53 | #define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz) |
| 54 | −#define NFS_symlinkargs_sz (NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz) | |
| 54 | +#define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz) | |
| 55 | 55 | #define NFS_readdirargs_sz (NFS_fhandle_sz+2) |
| 56 | 56 | |
| 57 | 57 | #define NFS_attrstat_sz (1+NFS_fattr_sz) |
| @@ -351,11 +351,26 @@ nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args) · 293 unmodified lines | ||
| 351 | 351 | static int |
| 352 | 352 | nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args) |
| 353 | 353 | { |
| 354 | + struct xdr_buf *sndbuf = &req->rq_snd_buf; | |
| 355 | + size_t pad; | |
| 356 | + | |
| 354 | 357 | p = xdr_encode_fhandle(p, args->fromfh); |
| 355 | 358 | p = xdr_encode_array(p, args->fromname, args->fromlen); |
| 356 | − p = xdr_encode_array(p, args->topath, args->tolen); | |
| 359 | + *p++ = htonl(args->pathlen); | |
| 360 | + sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); | |
| 361 | + | |
| 362 | + xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen); | |
| 363 | + | |
| 364 | + /* | |
| 365 | + * xdr_encode_pages may have added a few bytes to ensure the | |
| 366 | + * pathname ends on a 4-byte boundary. Start encoding the | |
| 367 | + * attributes after the pad bytes. | |
| 368 | + */ | |
| 369 | + pad = sndbuf->tail->iov_len; | |
| 370 | + if (pad > 0) | |
| 371 | + p++; | |
| 357 | 372 | p = xdr_encode_sattr(p, args->sattr); |
| 358 | − req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); | |
| 373 | + sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad; | |
| 359 | 374 | return 0; |
| 360 | 375 | } |
| 361 | 376 | |
| @@ -81,7 +81,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle, · 80 unmodified lines | ||
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | /* |
| 84 | − * Bare-bones access to getattr: this is for nfs_read_super. | |
| 84 | + * Bare-bones access to getattr: this is for nfs_get_root/nfs_get_sb | |
| 85 | 85 | */ |
| 86 | 86 | static int |
| 87 | 87 | nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, |
| @@ -90,8 +90,8 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, · 2 unmodified lines | ||
| 90 | 90 | int status; |
| 91 | 91 | |
| 92 | 92 | status = do_proc_get_root(server->client, fhandle, info); |
| 93 | − if (status && server->client_sys != server->client) | |
| 94 | − status = do_proc_get_root(server->client_sys, fhandle, info); | |
| 93 | + if (status && server->nfs_client->cl_rpcclient != server->client) | |
| 94 | + status = do_proc_get_root(server->nfs_client->cl_rpcclient, fhandle, info); | |
| 95 | 95 | return status; |
| 96 | 96 | } |
| 97 | 97 | |
| @@ -544,23 +544,23 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) · 446 unmodified lines | ||
| 544 | 544 | } |
| 545 | 545 | |
| 546 | 546 | static int |
| 547 | −nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, | |
| 548 | − struct iattr *sattr, struct nfs_fh *fhandle, | |
| 549 | − struct nfs_fattr *fattr) | |
| 547 | +nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |
| 548 | + unsigned int len, struct iattr *sattr) | |
| 550 | 549 | { |
| 551 | − struct nfs_fattr dir_attr; | |
| 550 | + struct nfs_fh fhandle; | |
| 551 | + struct nfs_fattr fattr, dir_attr; | |
| 552 | 552 | struct nfs3_symlinkargs arg = { |
| 553 | 553 | .fromfh = NFS_FH(dir), |
| 554 | − .fromname = name->name, | |
| 555 | − .fromlen = name->len, | |
| 556 | − .topath = path->name, | |
| 557 | − .tolen = path->len, | |
| 554 | + .fromname = dentry->d_name.name, | |
| 555 | + .fromlen = dentry->d_name.len, | |
| 556 | + .pages = &page, | |
| 557 | + .pathlen = len, | |
| 558 | 558 | .sattr = sattr |
| 559 | 559 | }; |
| 560 | 560 | struct nfs3_diropres res = { |
| 561 | 561 | .dir_attr = &dir_attr, |
| 562 | − .fh = fhandle, | |
| 563 | − .fattr = fattr | |
| 562 | + .fh = &fhandle, | |
| 563 | + .fattr = &fattr | |
| 564 | 564 | }; |
| 565 | 565 | struct rpc_message msg = { |
| 566 | 566 | .rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK], |
| @@ -569,13 +569,19 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, · 2 unmodified lines | ||
| 569 | 569 | }; |
| 570 | 570 | int status; |
| 571 | 571 | |
| 572 | − if (path->len > NFS3_MAXPATHLEN) | |
| 572 | + if (len > NFS3_MAXPATHLEN) | |
| 573 | 573 | return -ENAMETOOLONG; |
| 574 | − dprintk("NFS call symlink %s -> %s\n", name->name, path->name); | |
| 574 | + | |
| 575 | + dprintk("NFS call symlink %s\n", dentry->d_name.name); | |
| 576 | + | |
| 575 | 577 | nfs_fattr_init(&dir_attr); |
| 576 | − nfs_fattr_init(fattr); | |
| 578 | + nfs_fattr_init(&fattr); | |
| 577 | 579 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 578 | 580 | nfs_post_op_update_inode(dir, &dir_attr); |
| 581 | + if (status != 0) | |
| 582 | + goto out; | |
| 583 | + status = nfs_instantiate(dentry, &fhandle, &fattr); | |
| 584 | +out: | |
| 579 | 585 | dprintk("NFS reply symlink: %d\n", status); |
| 580 | 586 | return status; |
| 581 | 587 | } |
| @@ -785,7 +791,7 @@ nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, · 203 unmodified lines | ||
| 785 | 791 | |
| 786 | 792 | dprintk("NFS call fsinfo\n"); |
| 787 | 793 | nfs_fattr_init(info->fattr); |
| 788 | − status = rpc_call_sync(server->client_sys, &msg, 0); | |
| 794 | + status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); | |
| 789 | 795 | dprintk("NFS reply fsinfo: %d\n", status); |
| 790 | 796 | return status; |
| 791 | 797 | } |
| @@ -886,7 +892,7 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) · 94 unmodified lines | ||
| 886 | 892 | return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl); |
| 887 | 893 | } |
| 888 | 894 | |
| 889 | −struct nfs_rpc_ops nfs_v3_clientops = { | |
| 895 | +const struct nfs_rpc_ops nfs_v3_clientops = { | |
| 890 | 896 | .version = 3, /* protocol version */ |
| 891 | 897 | .dentry_ops = &nfs_dentry_operations, |
| 892 | 898 | .dir_inode_ops = &nfs3_dir_inode_operations, |
| @@ -56,7 +56,7 @@ · 55 unmodified lines | ||
| 56 | 56 | #define NFS3_writeargs_sz (NFS3_fh_sz+5) |
| 57 | 57 | #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) |
| 58 | 58 | #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) |
| 59 | −#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz) | |
| 59 | +#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz) | |
| 60 | 60 | #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz) |
| 61 | 61 | #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz) |
| 62 | 62 | #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz) |
| @@ -398,8 +398,11 @@ nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args · 335 unmodified lines | ||
| 398 | 398 | p = xdr_encode_fhandle(p, args->fromfh); |
| 399 | 399 | p = xdr_encode_array(p, args->fromname, args->fromlen); |
| 400 | 400 | p = xdr_encode_sattr(p, args->sattr); |
| 401 | − p = xdr_encode_array(p, args->topath, args->tolen); | |
| 401 | + *p++ = htonl(args->pathlen); | |
| 402 | 402 | req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); |
| 403 | + | |
| 404 | + /* Copy the page */ | |
| 405 | + xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen); | |
| 403 | 406 | return 0; |
| 404 | 407 | } |
| 405 | 408 | |
| @@ -42,55 +42,6 @@ enum nfs4_client_state { · 41 unmodified lines | ||
| 42 | 42 | NFS4CLNT_LEASE_EXPIRED, |
| 43 | 43 | }; |
| 44 | 44 | |
| 45 | −/* | |
| 46 | − * The nfs4_client identifies our client state to the server. | |
| 47 | − */ | |
| 48 | −struct nfs4_client { | |
| 49 | − struct list_head cl_servers; /* Global list of servers */ | |
| 50 | − struct in_addr cl_addr; /* Server identifier */ | |
| 51 | − u64 cl_clientid; /* constant */ | |
| 52 | − nfs4_verifier cl_confirm; | |
| 53 | − unsigned long cl_state; | |
| 54 | − | |
| 55 | − u32 cl_lockowner_id; | |
| 56 | − | |
| 57 | − /* | |
| 58 | − * The following rwsem ensures exclusive access to the server | |
| 59 | − * while we recover the state following a lease expiration. | |
| 60 | − */ | |
| 61 | − struct rw_semaphore cl_sem; | |
| 62 | − | |
| 63 | − struct list_head cl_delegations; | |
| 64 | − struct list_head cl_state_owners; | |
| 65 | − struct list_head cl_unused; | |
| 66 | − int cl_nunused; | |
| 67 | − spinlock_t cl_lock; | |
| 68 | − atomic_t cl_count; | |
| 69 | − | |
| 70 | − struct rpc_clnt * cl_rpcclient; | |
| 71 | − | |
| 72 | − struct list_head cl_superblocks; /* List of nfs_server structs */ | |
| 73 | − | |
| 74 | − unsigned long cl_lease_time; | |
| 75 | − unsigned long cl_last_renewal; | |
| 76 | − struct work_struct cl_renewd; | |
| 77 | − struct work_struct cl_recoverd; | |
| 78 | − | |
| 79 | − struct rpc_wait_queue cl_rpcwaitq; | |
| 80 | − | |
| 81 | − /* used for the setclientid verifier */ | |
| 82 | − struct timespec cl_boot_time; | |
| 83 | − | |
| 84 | − /* idmapper */ | |
| 85 | − struct idmap * cl_idmap; | |
| 86 | − | |
| 87 | − /* Our own IP address, as a null-terminated string. | |
| 88 | − * This is used to generate the clientid, and the callback address. | |
| 89 | − */ | |
| 90 | − char cl_ipaddr[16]; | |
| 91 | − unsigned char cl_id_uniquifier; | |
| 92 | −}; | |
| 93 | − | |
| 94 | 45 | /* |
| 95 | 46 | * struct rpc_sequence ensures that RPC calls are sent in the exact |
| 96 | 47 | * order that they appear on the list. |
| @@ -127,7 +78,7 @@ static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status · 30 unmodified lines | ||
| 127 | 78 | struct nfs4_state_owner { |
| 128 | 79 | spinlock_t so_lock; |
| 129 | 80 | struct list_head so_list; /* per-clientid list of state_owners */ |
| 130 | − struct nfs4_client *so_client; | |
| 81 | + struct nfs_client *so_client; | |
| 131 | 82 | u32 so_id; /* 32-bit identifier, unique */ |
| 132 | 83 | atomic_t so_count; |
| 133 | 84 | |
| @@ -210,10 +161,10 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t); · 76 unmodified lines | ||
| 210 | 161 | |
| 211 | 162 | /* nfs4proc.c */ |
| 212 | 163 | extern int nfs4_map_errors(int err); |
| 213 | −extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short, struct rpc_cred *); | |
| 214 | −extern int nfs4_proc_setclientid_confirm(struct nfs4_client *, struct rpc_cred *); | |
| 215 | −extern int nfs4_proc_async_renew(struct nfs4_client *, struct rpc_cred *); | |
| 216 | −extern int nfs4_proc_renew(struct nfs4_client *, struct rpc_cred *); | |
| 164 | +extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *); | |
| 165 | +extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *); | |
| 166 | +extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); | |
| 167 | +extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); | |
| 217 | 168 | extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state); |
| 218 | 169 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); |
| 219 | 170 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); |
| @@ -231,19 +182,14 @@ extern const u32 nfs4_fsinfo_bitmap[2]; · 11 unmodified lines | ||
| 231 | 182 | extern const u32 nfs4_fs_locations_bitmap[2]; |
| 232 | 183 | |
| 233 | 184 | /* nfs4renewd.c */ |
| 234 | −extern void nfs4_schedule_state_renewal(struct nfs4_client *); | |
| 185 | +extern void nfs4_schedule_state_renewal(struct nfs_client *); | |
| 235 | 186 | extern void nfs4_renewd_prepare_shutdown(struct nfs_server *); |
| 236 | −extern void nfs4_kill_renewd(struct nfs4_client *); | |
| 187 | +extern void nfs4_kill_renewd(struct nfs_client *); | |
| 237 | 188 | extern void nfs4_renew_state(void *); |
| 238 | 189 | |
| 239 | 190 | /* nfs4state.c */ |
| 240 | −extern void init_nfsv4_state(struct nfs_server *); | |
| 241 | −extern void destroy_nfsv4_state(struct nfs_server *); | |
| 242 | −extern struct nfs4_client *nfs4_get_client(struct in_addr *); | |
| 243 | −extern void nfs4_put_client(struct nfs4_client *clp); | |
| 244 | −extern struct nfs4_client *nfs4_find_client(struct in_addr *); | |
| 245 | −struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp); | |
| 246 | −extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *); | |
| 191 | +struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp); | |
| 192 | +extern u32 nfs4_alloc_lockowner_id(struct nfs_client *); | |
| 247 | 193 | |
| 248 | 194 | extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); |
| 249 | 195 | extern void nfs4_put_state_owner(struct nfs4_state_owner *); |
| @@ -252,7 +198,7 @@ extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state · 2 unmodified lines | ||
| 252 | 198 | extern void nfs4_put_open_state(struct nfs4_state *); |
| 253 | 199 | extern void nfs4_close_state(struct nfs4_state *, mode_t); |
| 254 | 200 | extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t); |
| 255 | −extern void nfs4_schedule_state_recovery(struct nfs4_client *); | |
| 201 | +extern void nfs4_schedule_state_recovery(struct nfs_client *); | |
| 256 | 202 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); |
| 257 | 203 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
| 258 | 204 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); |
| @@ -276,10 +222,6 @@ extern struct svc_version nfs4_callback_version1; · 17 unmodified lines | ||
| 276 | 222 | |
| 277 | 223 | #else |
| 278 | 224 | |
| 279 | −#define init_nfsv4_state(server) do { } while (0) | |
| 280 | −#define destroy_nfsv4_state(server) do { } while (0) | |
| 281 | −#define nfs4_put_state_owner(inode, owner) do { } while (0) | |
| 282 | −#define nfs4_put_open_state(state) do { } while (0) | |
| 283 | 225 | #define nfs4_close_state(a, b) do { } while (0) |
| 284 | 226 | |
| 285 | 227 | #endif /* CONFIG_NFS_V4 */ |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | * linux/fs/nfs/nfs4namespace.c |
| 3 | 3 | * |
| 4 | 4 | * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com> |
| 5 | + * - Modified by David Howells <dhowells@redhat.com> | |
| 5 | 6 | * |
| 6 | 7 | * NFSv4 namespace |
| 7 | 8 | */ |
| @@ -23,7 +24,7 @@ · 15 unmodified lines | ||
| 23 | 24 | /* |
| 24 | 25 | * Check if fs_root is valid |
| 25 | 26 | */ |
| 26 | −static inline char *nfs4_pathname_string(struct nfs4_pathname *pathname, | |
| 27 | +static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname, | |
| 27 | 28 | char *buffer, ssize_t buflen) |
| 28 | 29 | { |
| 29 | 30 | char *end = buffer + buflen; |
| @@ -34,7 +35,7 @@ static inline char *nfs4_pathname_string(struct nfs4_pathname *pathname, · 4 unmodified lines | ||
| 34 | 35 | |
| 35 | 36 | n = pathname->ncomponents; |
| 36 | 37 | while (--n >= 0) { |
| 37 | − struct nfs4_string *component = &pathname->components[n]; | |
| 38 | + const struct nfs4_string *component = &pathname->components[n]; | |
| 38 | 39 | buflen -= component->len + 1; |
| 39 | 40 | if (buflen < 0) |
| 40 | 41 | goto Elong; |
| @@ -47,6 +48,68 @@ Elong: · 6 unmodified lines | ||
| 47 | 48 | return ERR_PTR(-ENAMETOOLONG); |
| 48 | 49 | } |
| 49 | 50 | |
| 51 | +/* | |
| 52 | + * Determine the mount path as a string | |
| 53 | + */ | |
| 54 | +static char *nfs4_path(const struct vfsmount *mnt_parent, | |
| 55 | + const struct dentry *dentry, | |
| 56 | + char *buffer, ssize_t buflen) | |
| 57 | +{ | |
| 58 | + const char *srvpath; | |
| 59 | + | |
| 60 | + srvpath = strchr(mnt_parent->mnt_devname, ':'); | |
| 61 | + if (srvpath) | |
| 62 | + srvpath++; | |
| 63 | + else | |
| 64 | + srvpath = mnt_parent->mnt_devname; | |
| 65 | + | |
| 66 | + return nfs_path(srvpath, mnt_parent->mnt_root, dentry, buffer, buflen); | |
| 67 | +} | |
| 68 | + | |
| 69 | +/* | |
| 70 | + * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we | |
| 71 | + * believe to be the server path to this dentry | |
| 72 | + */ | |
| 73 | +static int nfs4_validate_fspath(const struct vfsmount *mnt_parent, | |
| 74 | + const struct dentry *dentry, | |
| 75 | + const struct nfs4_fs_locations *locations, | |
| 76 | + char *page, char *page2) | |
| 77 | +{ | |
| 78 | + const char *path, *fs_path; | |
| 79 | + | |
| 80 | + path = nfs4_path(mnt_parent, dentry, page, PAGE_SIZE); | |
| 81 | + if (IS_ERR(path)) | |
| 82 | + return PTR_ERR(path); | |
| 83 | + | |
| 84 | + fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE); | |
| 85 | + if (IS_ERR(fs_path)) | |
| 86 | + return PTR_ERR(fs_path); | |
| 87 | + | |
| 88 | + if (strncmp(path, fs_path, strlen(fs_path)) != 0) { | |
| 89 | + dprintk("%s: path %s does not begin with fsroot %s\n", | |
| 90 | + __FUNCTION__, path, fs_path); | |
| 91 | + return -ENOENT; | |
| 92 | + } | |
| 93 | + | |
| 94 | + return 0; | |
| 95 | +} | |
| 96 | + | |
| 97 | +/* | |
| 98 | + * Check if the string represents a "valid" IPv4 address | |
| 99 | + */ | |
| 100 | +static inline int valid_ipaddr4(const char *buf) | |
| 101 | +{ | |
| 102 | + int rc, count, in[4]; | |
| 103 | + | |
| 104 | + rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); | |
| 105 | + if (rc != 4) | |
| 106 | + return -EINVAL; | |
| 107 | + for (count = 0; count < 4; count++) { | |
| 108 | + if (in[count] > 255) | |
| 109 | + return -EINVAL; | |
| 110 | + } | |
| 111 | + return 0; | |
| 112 | +} | |
| 50 | 113 | |
| 51 | 114 | /** |
| 52 | 115 | * nfs_follow_referral - set up mountpoint when hitting a referral on moved error |
| @@ -60,7 +123,7 @@ Elong: · 7 unmodified lines | ||
| 60 | 123 | */ |
| 61 | 124 | static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, |
| 62 | 125 | const struct dentry *dentry, |
| 63 | − struct nfs4_fs_locations *locations) | |
| 126 | + const struct nfs4_fs_locations *locations) | |
| 64 | 127 | { |
| 65 | 128 | struct vfsmount *mnt = ERR_PTR(-ENOENT); |
| 66 | 129 | struct nfs_clone_mount mountdata = { |
| @@ -68,10 +131,9 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, · 1 unmodified line | ||
| 68 | 131 | .dentry = dentry, |
| 69 | 132 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, |
| 70 | 133 | }; |
| 71 | − char *page, *page2; | |
| 72 | − char *path, *fs_path; | |
| 134 | + char *page = NULL, *page2 = NULL; | |
| 73 | 135 | char *devname; |
| 74 | − int loc, s; | |
| 136 | + int loc, s, error; | |
| 75 | 137 | |
| 76 | 138 | if (locations == NULL || locations->nlocations <= 0) |
| 77 | 139 | goto out; |
| @@ -79,36 +141,30 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, · 1 unmodified line | ||
| 79 | 141 | dprintk("%s: referral at %s/%s\n", __FUNCTION__, |
| 80 | 142 | dentry->d_parent->d_name.name, dentry->d_name.name); |
| 81 | 143 | |
| 82 | − /* Ensure fs path is a prefix of current dentry path */ | |
| 83 | 144 | page = (char *) __get_free_page(GFP_USER); |
| 84 | − if (page == NULL) | |
| 145 | + if (!page) | |
| 85 | 146 | goto out; |
| 147 | + | |
| 86 | 148 | page2 = (char *) __get_free_page(GFP_USER); |
| 87 | − if (page2 == NULL) | |
| 149 | + if (!page2) | |
| 88 | 150 | goto out; |
| 89 | 151 | |
| 90 | − path = nfs4_path(dentry, page, PAGE_SIZE); | |
| 91 | − if (IS_ERR(path)) | |
| 92 | − goto out_free; | |
| 93 | − | |
| 94 | − fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE); | |
| 95 | − if (IS_ERR(fs_path)) | |
| 96 | − goto out_free; | |
| 97 | − | |
| 98 | − if (strncmp(path, fs_path, strlen(fs_path)) != 0) { | |
| 99 | − dprintk("%s: path %s does not begin with fsroot %s\n", __FUNCTION__, path, fs_path); | |
| 100 | − goto out_free; | |
| 152 | + /* Ensure fs path is a prefix of current dentry path */ | |
| 153 | + error = nfs4_validate_fspath(mnt_parent, dentry, locations, page, page2); | |
| 154 | + if (error < 0) { | |
| 155 | + mnt = ERR_PTR(error); | |
| 156 | + goto out; | |
| 101 | 157 | } |
| 102 | 158 | |
| 103 | 159 | devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE); |
| 104 | 160 | if (IS_ERR(devname)) { |
| 105 | 161 | mnt = (struct vfsmount *)devname; |
| 106 | − goto out_free; | |
| 162 | + goto out; | |
| 107 | 163 | } |
| 108 | 164 | |
| 109 | 165 | loc = 0; |
| 110 | 166 | while (loc < locations->nlocations && IS_ERR(mnt)) { |
| 111 | − struct nfs4_fs_location *location = &locations->locations[loc]; | |
| 167 | + const struct nfs4_fs_location *location = &locations->locations[loc]; | |
| 112 | 168 | char *mnt_path; |
| 113 | 169 | |
| 114 | 170 | if (location == NULL || location->nservers <= 0 || |
| @@ -140,7 +196,7 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, · 25 unmodified lines | ||
| 140 | 196 | addr.sin_port = htons(NFS_PORT); |
| 141 | 197 | mountdata.addr = &addr; |
| 142 | 198 | |
| 143 | − mnt = vfs_kern_mount(&nfs_referral_nfs4_fs_type, 0, devname, &mountdata); | |
| 199 | + mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, devname, &mountdata); | |
| 144 | 200 | if (!IS_ERR(mnt)) { |
| 145 | 201 | break; |
| 146 | 202 | } |
| @@ -149,10 +205,9 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, · 2 unmodified lines | ||
| 149 | 205 | loc++; |
| 150 | 206 | } |
| 151 | 207 | |
| 152 | −out_free: | |
| 153 | − free_page((unsigned long)page); | |
| 154 | − free_page((unsigned long)page2); | |
| 155 | 208 | out: |
| 209 | + free_page((unsigned long) page); | |
| 210 | + free_page((unsigned long) page2); | |
| 156 | 211 | dprintk("%s: done\n", __FUNCTION__); |
| 157 | 212 | return mnt; |
| 158 | 213 | } |
| @@ -165,7 +220,7 @@ out: · 6 unmodified lines | ||
| 165 | 220 | */ |
| 166 | 221 | struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) |
| 167 | 222 | { |
| 168 | − struct vfsmount *mnt = ERR_PTR(-ENOENT); | |
| 223 | + struct vfsmount *mnt = ERR_PTR(-ENOMEM); | |
| 169 | 224 | struct dentry *parent; |
| 170 | 225 | struct nfs4_fs_locations *fs_locations = NULL; |
| 171 | 226 | struct page *page; |
| @@ -183,11 +238,16 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr · 11 unmodified lines | ||
| 183 | 238 | goto out_free; |
| 184 | 239 | |
| 185 | 240 | /* Get locations */ |
| 241 | + mnt = ERR_PTR(-ENOENT); | |
| 242 | + | |
| 186 | 243 | parent = dget_parent(dentry); |
| 187 | − dprintk("%s: getting locations for %s/%s\n", __FUNCTION__, parent->d_name.name, dentry->d_name.name); | |
| 244 | + dprintk("%s: getting locations for %s/%s\n", | |
| 245 | + __FUNCTION__, parent->d_name.name, dentry->d_name.name); | |
| 246 | + | |
| 188 | 247 | err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page); |
| 189 | 248 | dput(parent); |
| 190 | − if (err != 0 || fs_locations->nlocations <= 0 || | |
| 249 | + if (err != 0 || | |
| 250 | + fs_locations->nlocations <= 0 || | |
| 191 | 251 | fs_locations->fs_path.ncomponents <= 0) |
| 192 | 252 | goto out_free; |
| 193 | 253 | |
| @@ -55,7 +55,7 @@ · 54 unmodified lines | ||
| 55 | 55 | |
| 56 | 56 | #define NFSDBG_FACILITY NFSDBG_PROC |
| 57 | 57 | |
| 58 | −#define NFS4_POLL_RETRY_MIN (1*HZ) | |
| 58 | +#define NFS4_POLL_RETRY_MIN (HZ/10) | |
| 59 | 59 | #define NFS4_POLL_RETRY_MAX (15*HZ) |
| 60 | 60 | |
| 61 | 61 | struct nfs4_opendata; |
| @@ -64,7 +64,7 @@ static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinf · 2 unmodified lines | ||
| 64 | 64 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); |
| 65 | 65 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); |
| 66 | 66 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); |
| 67 | −static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp); | |
| 67 | +static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); | |
| 68 | 68 | |
| 69 | 69 | /* Prevent leaks of NFSv4 errors into userland */ |
| 70 | 70 | int nfs4_map_errors(int err) |
| @@ -195,7 +195,7 @@ static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry, · 124 unmodified lines | ||
| 195 | 195 | |
| 196 | 196 | static void renew_lease(const struct nfs_server *server, unsigned long timestamp) |
| 197 | 197 | { |
| 198 | − struct nfs4_client *clp = server->nfs4_state; | |
| 198 | + struct nfs_client *clp = server->nfs_client; | |
| 199 | 199 | spin_lock(&clp->cl_lock); |
| 200 | 200 | if (time_before(clp->cl_last_renewal,timestamp)) |
| 201 | 201 | clp->cl_last_renewal = timestamp; |
| @@ -252,7 +252,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, · 50 unmodified lines | ||
| 252 | 252 | atomic_inc(&sp->so_count); |
| 253 | 253 | p->o_arg.fh = NFS_FH(dir); |
| 254 | 254 | p->o_arg.open_flags = flags, |
| 255 | − p->o_arg.clientid = server->nfs4_state->cl_clientid; | |
| 255 | + p->o_arg.clientid = server->nfs_client->cl_clientid; | |
| 256 | 256 | p->o_arg.id = sp->so_id; |
| 257 | 257 | p->o_arg.name = &dentry->d_name; |
| 258 | 258 | p->o_arg.server = server; |
| @@ -550,7 +550,7 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state) · 291 unmodified lines | ||
| 550 | 550 | case -NFS4ERR_STALE_STATEID: |
| 551 | 551 | case -NFS4ERR_EXPIRED: |
| 552 | 552 | /* Don't recall a delegation if it was lost */ |
| 553 | − nfs4_schedule_state_recovery(server->nfs4_state); | |
| 553 | + nfs4_schedule_state_recovery(server->nfs_client); | |
| 554 | 554 | return err; |
| 555 | 555 | } |
| 556 | 556 | err = nfs4_handle_exception(server, err, &exception); |
| @@ -758,7 +758,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) · 201 unmodified lines | ||
| 758 | 758 | } |
| 759 | 759 | nfs_confirm_seqid(&data->owner->so_seqid, 0); |
| 760 | 760 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) |
| 761 | − return server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); | |
| 761 | + return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); | |
| 762 | 762 | return 0; |
| 763 | 763 | } |
| 764 | 764 | |
| @@ -792,11 +792,18 @@ out: · 27 unmodified lines | ||
| 792 | 792 | |
| 793 | 793 | int nfs4_recover_expired_lease(struct nfs_server *server) |
| 794 | 794 | { |
| 795 | − struct nfs4_client *clp = server->nfs4_state; | |
| 795 | + struct nfs_client *clp = server->nfs_client; | |
| 796 | + int ret; | |
| 796 | 797 | |
| 797 | − if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) | |
| 798 | + for (;;) { | |
| 799 | + ret = nfs4_wait_clnt_recover(server->client, clp); | |
| 800 | + if (ret != 0) | |
| 801 | + return ret; | |
| 802 | + if (!test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) | |
| 803 | + break; | |
| 798 | 804 | nfs4_schedule_state_recovery(clp); |
| 799 | − return nfs4_wait_clnt_recover(server->client, clp); | |
| 805 | + } | |
| 806 | + return 0; | |
| 800 | 807 | } |
| 801 | 808 | |
| 802 | 809 | /* |
| @@ -867,7 +874,7 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred · 64 unmodified lines | ||
| 867 | 874 | { |
| 868 | 875 | struct nfs_delegation *delegation; |
| 869 | 876 | struct nfs_server *server = NFS_SERVER(inode); |
| 870 | − struct nfs4_client *clp = server->nfs4_state; | |
| 877 | + struct nfs_client *clp = server->nfs_client; | |
| 871 | 878 | struct nfs_inode *nfsi = NFS_I(inode); |
| 872 | 879 | struct nfs4_state_owner *sp = NULL; |
| 873 | 880 | struct nfs4_state *state = NULL; |
| @@ -953,7 +960,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st · 79 unmodified lines | ||
| 953 | 960 | struct nfs4_state_owner *sp; |
| 954 | 961 | struct nfs4_state *state = NULL; |
| 955 | 962 | struct nfs_server *server = NFS_SERVER(dir); |
| 956 | − struct nfs4_client *clp = server->nfs4_state; | |
| 963 | + struct nfs_client *clp = server->nfs_client; | |
| 957 | 964 | struct nfs4_opendata *opendata; |
| 958 | 965 | int status; |
| 959 | 966 | |
| @@ -1133,7 +1140,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) · 173 unmodified lines | ||
| 1133 | 1140 | break; |
| 1134 | 1141 | case -NFS4ERR_STALE_STATEID: |
| 1135 | 1142 | case -NFS4ERR_EXPIRED: |
| 1136 | − nfs4_schedule_state_recovery(server->nfs4_state); | |
| 1143 | + nfs4_schedule_state_recovery(server->nfs_client); | |
| 1137 | 1144 | break; |
| 1138 | 1145 | default: |
| 1139 | 1146 | if (nfs4_async_handle_error(task, server) == -EAGAIN) { |
| @@ -1268,7 +1275,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) · 128 unmodified lines | ||
| 1268 | 1275 | BUG_ON(nd->intent.open.flags & O_CREAT); |
| 1269 | 1276 | } |
| 1270 | 1277 | |
| 1271 | − cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); | |
| 1278 | + cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); | |
| 1272 | 1279 | if (IS_ERR(cred)) |
| 1273 | 1280 | return (struct dentry *)cred; |
| 1274 | 1281 | state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred); |
| @@ -1291,7 +1298,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st · 16 unmodified lines | ||
| 1291 | 1298 | struct rpc_cred *cred; |
| 1292 | 1299 | struct nfs4_state *state; |
| 1293 | 1300 | |
| 1294 | − cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); | |
| 1301 | + cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); | |
| 1295 | 1302 | if (IS_ERR(cred)) |
| 1296 | 1303 | return PTR_ERR(cred); |
| 1297 | 1304 | state = nfs4_open_delegated(dentry->d_inode, openflags, cred); |
| @@ -1393,70 +1400,19 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, · 95 unmodified lines | ||
| 1393 | 1400 | return err; |
| 1394 | 1401 | } |
| 1395 | 1402 | |
| 1403 | +/* | |
| 1404 | + * get the file handle for the "/" directory on the server | |
| 1405 | + */ | |
| 1396 | 1406 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, |
| 1397 | − struct nfs_fsinfo *info) | |
| 1407 | + struct nfs_fsinfo *info) | |
| 1398 | 1408 | { |
| 1399 | − struct nfs_fattr * fattr = info->fattr; | |
| 1400 | − unsigned char * p; | |
| 1401 | − struct qstr q; | |
| 1402 | − struct nfs4_lookup_arg args = { | |
| 1403 | − .dir_fh = fhandle, | |
| 1404 | − .name = &q, | |
| 1405 | − .bitmask = nfs4_fattr_bitmap, | |
| 1406 | − }; | |
| 1407 | − struct nfs4_lookup_res res = { | |
| 1408 | − .server = server, | |
| 1409 | − .fattr = fattr, | |
| 1410 | − .fh = fhandle, | |
| 1411 | − }; | |
| 1412 | − struct rpc_message msg = { | |
| 1413 | − .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP], | |
| 1414 | − .rpc_argp = &args, | |
| 1415 | − .rpc_resp = &res, | |
| 1416 | − }; | |
| 1417 | 1409 | int status; |
| 1418 | 1410 | |
| 1419 | − /* | |
| 1420 | − * Now we do a separate LOOKUP for each component of the mount path. | |
| 1421 | − * The LOOKUPs are done separately so that we can conveniently | |
| 1422 | − * catch an ERR_WRONGSEC if it occurs along the way... | |
| 1423 | − */ | |
| 1424 | 1411 | status = nfs4_lookup_root(server, fhandle, info); |
| 1425 | − if (status) | |
| 1426 | − goto out; | |
| 1427 | − | |
| 1428 | − p = server->mnt_path; | |
| 1429 | − for (;;) { | |
| 1430 | − struct nfs4_exception exception = { }; | |
| 1431 | − | |
| 1432 | − while (*p == '/') | |
| 1433 | − p++; | |
| 1434 | − if (!*p) | |
| 1435 | − break; | |
| 1436 | − q.name = p; | |
| 1437 | − while (*p && (*p != '/')) | |
| 1438 | − p++; | |
| 1439 | − q.len = p - q.name; | |
| 1440 | − | |
| 1441 | − do { | |
| 1442 | − nfs_fattr_init(fattr); | |
| 1443 | − status = nfs4_handle_exception(server, | |
| 1444 | − rpc_call_sync(server->client, &msg, 0), | |
| 1445 | − &exception); | |
| 1446 | − } while (exception.retry); | |
| 1447 | − if (status == 0) | |
| 1448 | − continue; | |
| 1449 | − if (status == -ENOENT) { | |
| 1450 | − printk(KERN_NOTICE "NFS: mount path %s does not exist!\n", server->mnt_path); | |
| 1451 | − printk(KERN_NOTICE "NFS: suggestion: try mounting '/' instead.\n"); | |
| 1452 | − } | |
| 1453 | − break; | |
| 1454 | − } | |
| 1455 | 1412 | if (status == 0) |
| 1456 | 1413 | status = nfs4_server_capabilities(server, fhandle); |
| 1457 | 1414 | if (status == 0) |
| 1458 | 1415 | status = nfs4_do_fsinfo(server, fhandle, info); |
| 1459 | −out: | |
| 1460 | 1416 | return nfs4_map_errors(status); |
| 1461 | 1417 | } |
| 1462 | 1418 | |
| @@ -1565,7 +1521,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, · 102 unmodified lines | ||
| 1565 | 1521 | |
| 1566 | 1522 | nfs_fattr_init(fattr); |
| 1567 | 1523 | |
| 1568 | − cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); | |
| 1524 | + cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0); | |
| 1569 | 1525 | if (IS_ERR(cred)) |
| 1570 | 1526 | return PTR_ERR(cred); |
| 1571 | 1527 | |
| @@ -1583,6 +1539,52 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, · 11 unmodified lines | ||
| 1583 | 1539 | return status; |
| 1584 | 1540 | } |
| 1585 | 1541 | |
| 1542 | +static int _nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, | |
| 1543 | + struct qstr *name, struct nfs_fh *fhandle, | |
| 1544 | + struct nfs_fattr *fattr) | |
| 1545 | +{ | |
| 1546 | + int status; | |
| 1547 | + struct nfs4_lookup_arg args = { | |
| 1548 | + .bitmask = server->attr_bitmask, | |
| 1549 | + .dir_fh = dirfh, | |
| 1550 | + .name = name, | |
| 1551 | + }; | |
| 1552 | + struct nfs4_lookup_res res = { | |
| 1553 | + .server = server, | |
| 1554 | + .fattr = fattr, | |
| 1555 | + .fh = fhandle, | |
| 1556 | + }; | |
| 1557 | + struct rpc_message msg = { | |
| 1558 | + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP], | |
| 1559 | + .rpc_argp = &args, | |
| 1560 | + .rpc_resp = &res, | |
| 1561 | + }; | |
| 1562 | + | |
| 1563 | + nfs_fattr_init(fattr); | |
| 1564 | + | |
| 1565 | + dprintk("NFS call lookupfh %s\n", name->name); | |
| 1566 | + status = rpc_call_sync(server->client, &msg, 0); | |
| 1567 | + dprintk("NFS reply lookupfh: %d\n", status); | |
| 1568 | + if (status == -NFS4ERR_MOVED) | |
| 1569 | + status = -EREMOTE; | |
| 1570 | + return status; | |
| 1571 | +} | |
| 1572 | + | |
| 1573 | +static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, | |
| 1574 | + struct qstr *name, struct nfs_fh *fhandle, | |
| 1575 | + struct nfs_fattr *fattr) | |
| 1576 | +{ | |
| 1577 | + struct nfs4_exception exception = { }; | |
| 1578 | + int err; | |
| 1579 | + do { | |
| 1580 | + err = nfs4_handle_exception(server, | |
| 1581 | + _nfs4_proc_lookupfh(server, dirfh, name, | |
| 1582 | + fhandle, fattr), | |
| 1583 | + &exception); | |
| 1584 | + } while (exception.retry); | |
| 1585 | + return err; | |
| 1586 | +} | |
| 1587 | + | |
| 1586 | 1588 | static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name, |
| 1587 | 1589 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
| 1588 | 1590 | { |
| @@ -1881,7 +1883,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, · 292 unmodified lines | ||
| 1881 | 1883 | struct rpc_cred *cred; |
| 1882 | 1884 | int status = 0; |
| 1883 | 1885 | |
| 1884 | − cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); | |
| 1886 | + cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); | |
| 1885 | 1887 | if (IS_ERR(cred)) { |
| 1886 | 1888 | status = PTR_ERR(cred); |
| 1887 | 1889 | goto out; |
| @@ -2089,24 +2091,24 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n · 201 unmodified lines | ||
| 2089 | 2091 | return err; |
| 2090 | 2092 | } |
| 2091 | 2093 | |
| 2092 | −static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |
| 2093 | − struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, | |
| 2094 | − struct nfs_fattr *fattr) | |
| 2094 | +static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |
| 2095 | + struct page *page, unsigned int len, struct iattr *sattr) | |
| 2095 | 2096 | { |
| 2096 | 2097 | struct nfs_server *server = NFS_SERVER(dir); |
| 2097 | − struct nfs_fattr dir_fattr; | |
| 2098 | + struct nfs_fh fhandle; | |
| 2099 | + struct nfs_fattr fattr, dir_fattr; | |
| 2098 | 2100 | struct nfs4_create_arg arg = { |
| 2099 | 2101 | .dir_fh = NFS_FH(dir), |
| 2100 | 2102 | .server = server, |
| 2101 | − .name = name, | |
| 2103 | + .name = &dentry->d_name, | |
| 2102 | 2104 | .attrs = sattr, |
| 2103 | 2105 | .ftype = NF4LNK, |
| 2104 | 2106 | .bitmask = server->attr_bitmask, |
| 2105 | 2107 | }; |
| 2106 | 2108 | struct nfs4_create_res res = { |
| 2107 | 2109 | .server = server, |
| 2108 | − .fh = fhandle, | |
| 2109 | − .fattr = fattr, | |
| 2110 | + .fh = &fhandle, | |
| 2111 | + .fattr = &fattr, | |
| 2110 | 2112 | .dir_fattr = &dir_fattr, |
| 2111 | 2113 | }; |
| 2112 | 2114 | struct rpc_message msg = { |
| @@ -2116,29 +2118,32 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, · 3 unmodified lines | ||
| 2116 | 2118 | }; |
| 2117 | 2119 | int status; |
| 2118 | 2120 | |
| 2119 | − if (path->len > NFS4_MAXPATHLEN) | |
| 2121 | + if (len > NFS4_MAXPATHLEN) | |
| 2120 | 2122 | return -ENAMETOOLONG; |
| 2121 | − arg.u.symlink = path; | |
| 2122 | − nfs_fattr_init(fattr); | |
| 2123 | + | |
| 2124 | + arg.u.symlink.pages = &page; | |
| 2125 | + arg.u.symlink.len = len; | |
| 2126 | + nfs_fattr_init(&fattr); | |
| 2123 | 2127 | nfs_fattr_init(&dir_fattr); |
| 2124 | 2128 | |
| 2125 | 2129 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 2126 | − if (!status) | |
| 2130 | + if (!status) { | |
| 2127 | 2131 | update_changeattr(dir, &res.dir_cinfo); |
| 2128 | − nfs_post_op_update_inode(dir, res.dir_fattr); | |
| 2132 | + nfs_post_op_update_inode(dir, res.dir_fattr); | |
| 2133 | + status = nfs_instantiate(dentry, &fhandle, &fattr); | |
| 2134 | + } | |
| 2129 | 2135 | return status; |
| 2130 | 2136 | } |
| 2131 | 2137 | |
| 2132 | −static int nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |
| 2133 | − struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, | |
| 2134 | − struct nfs_fattr *fattr) | |
| 2138 | +static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |
| 2139 | + struct page *page, unsigned int len, struct iattr *sattr) | |
| 2135 | 2140 | { |
| 2136 | 2141 | struct nfs4_exception exception = { }; |
| 2137 | 2142 | int err; |
| 2138 | 2143 | do { |
| 2139 | 2144 | err = nfs4_handle_exception(NFS_SERVER(dir), |
| 2140 | − _nfs4_proc_symlink(dir, name, path, sattr, | |
| 2141 | − fhandle, fattr), | |
| 2145 | + _nfs4_proc_symlink(dir, dentry, page, | |
| 2146 | + len, sattr), | |
| 2142 | 2147 | &exception); |
| 2143 | 2148 | } while (exception.retry); |
| 2144 | 2149 | return err; |
| @@ -2521,7 +2526,7 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how) · 376 unmodified lines | ||
| 2521 | 2526 | */ |
| 2522 | 2527 | static void nfs4_renew_done(struct rpc_task *task, void *data) |
| 2523 | 2528 | { |
| 2524 | − struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; | |
| 2529 | + struct nfs_client *clp = (struct nfs_client *)task->tk_msg.rpc_argp; | |
| 2525 | 2530 | unsigned long timestamp = (unsigned long)data; |
| 2526 | 2531 | |
| 2527 | 2532 | if (task->tk_status < 0) { |
| @@ -2543,7 +2548,7 @@ static const struct rpc_call_ops nfs4_renew_ops = { · 15 unmodified lines | ||
| 2543 | 2548 | .rpc_call_done = nfs4_renew_done, |
| 2544 | 2549 | }; |
| 2545 | 2550 | |
| 2546 | −int nfs4_proc_async_renew(struct nfs4_client *clp, struct rpc_cred *cred) | |
| 2551 | +int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) | |
| 2547 | 2552 | { |
| 2548 | 2553 | struct rpc_message msg = { |
| 2549 | 2554 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], |
| @@ -2555,7 +2560,7 @@ int nfs4_proc_async_renew(struct nfs4_client *clp, struct rpc_cred *cred) · 5 unmodified lines | ||
| 2555 | 2560 | &nfs4_renew_ops, (void *)jiffies); |
| 2556 | 2561 | } |
| 2557 | 2562 | |
| 2558 | −int nfs4_proc_renew(struct nfs4_client *clp, struct rpc_cred *cred) | |
| 2563 | +int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) | |
| 2559 | 2564 | { |
| 2560 | 2565 | struct rpc_message msg = { |
| 2561 | 2566 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], |
| @@ -2770,7 +2775,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl · 208 unmodified lines | ||
| 2770 | 2775 | return -EOPNOTSUPP; |
| 2771 | 2776 | nfs_inode_return_delegation(inode); |
| 2772 | 2777 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); |
| 2773 | − ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0); | |
| 2778 | + ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | |
| 2774 | 2779 | if (ret == 0) |
| 2775 | 2780 | nfs4_write_cached_acl(inode, buf, buflen); |
| 2776 | 2781 | return ret; |
| @@ -2791,7 +2796,7 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen · 14 unmodified lines | ||
| 2791 | 2796 | static int |
| 2792 | 2797 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) |
| 2793 | 2798 | { |
| 2794 | − struct nfs4_client *clp = server->nfs4_state; | |
| 2799 | + struct nfs_client *clp = server->nfs_client; | |
| 2795 | 2800 | |
| 2796 | 2801 | if (!clp || task->tk_status >= 0) |
| 2797 | 2802 | return 0; |
| @@ -2828,7 +2833,7 @@ static int nfs4_wait_bit_interruptible(void *word) · 30 unmodified lines | ||
| 2828 | 2833 | return 0; |
| 2829 | 2834 | } |
| 2830 | 2835 | |
| 2831 | −static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp) | |
| 2836 | +static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp) | |
| 2832 | 2837 | { |
| 2833 | 2838 | sigset_t oldset; |
| 2834 | 2839 | int res; |
| @@ -2871,7 +2876,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) · 36 unmodified lines | ||
| 2871 | 2876 | */ |
| 2872 | 2877 | int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) |
| 2873 | 2878 | { |
| 2874 | − struct nfs4_client *clp = server->nfs4_state; | |
| 2879 | + struct nfs_client *clp = server->nfs_client; | |
| 2875 | 2880 | int ret = errorcode; |
| 2876 | 2881 | |
| 2877 | 2882 | exception->retry = 0; |
| @@ -2886,6 +2891,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct · 8 unmodified lines | ||
| 2886 | 2891 | if (ret == 0) |
| 2887 | 2892 | exception->retry = 1; |
| 2888 | 2893 | break; |
| 2894 | + case -NFS4ERR_FILE_OPEN: | |
| 2889 | 2895 | case -NFS4ERR_GRACE: |
| 2890 | 2896 | case -NFS4ERR_DELAY: |
| 2891 | 2897 | ret = nfs4_delay(server->client, &exception->timeout); |
| @@ -2898,7 +2904,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct · 6 unmodified lines | ||
| 2898 | 2904 | return nfs4_map_errors(ret); |
| 2899 | 2905 | } |
| 2900 | 2906 | |
| 2901 | −int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port, struct rpc_cred *cred) | |
| 2907 | +int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred) | |
| 2902 | 2908 | { |
| 2903 | 2909 | nfs4_verifier sc_verifier; |
| 2904 | 2910 | struct nfs4_setclientid setclientid = { |
| @@ -2922,7 +2928,7 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p · 17 unmodified lines | ||
| 2922 | 2928 | for(;;) { |
| 2923 | 2929 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, |
| 2924 | 2930 | sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u", |
| 2925 | − clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr), | |
| 2931 | + clp->cl_ipaddr, NIPQUAD(clp->cl_addr.sin_addr), | |
| 2926 | 2932 | cred->cr_ops->cr_name, |
| 2927 | 2933 | clp->cl_id_uniquifier); |
| 2928 | 2934 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, |
| @@ -2945,7 +2951,7 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p · 16 unmodified lines | ||
| 2945 | 2951 | return status; |
| 2946 | 2952 | } |
| 2947 | 2953 | |
| 2948 | −static int _nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred) | |
| 2954 | +static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred) | |
| 2949 | 2955 | { |
| 2950 | 2956 | struct nfs_fsinfo fsinfo; |
| 2951 | 2957 | struct rpc_message msg = { |
| @@ -2969,7 +2975,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cr · 17 unmodified lines | ||
| 2969 | 2975 | return status; |
| 2970 | 2976 | } |
| 2971 | 2977 | |
| 2972 | −int nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred) | |
| 2978 | +int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred) | |
| 2973 | 2979 | { |
| 2974 | 2980 | long timeout; |
| 2975 | 2981 | int err; |
| @@ -3077,7 +3083,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 · 101 unmodified lines | ||
| 3077 | 3083 | switch (err) { |
| 3078 | 3084 | case -NFS4ERR_STALE_STATEID: |
| 3079 | 3085 | case -NFS4ERR_EXPIRED: |
| 3080 | − nfs4_schedule_state_recovery(server->nfs4_state); | |
| 3086 | + nfs4_schedule_state_recovery(server->nfs_client); | |
| 3081 | 3087 | case 0: |
| 3082 | 3088 | return 0; |
| 3083 | 3089 | } |
| @@ -3106,7 +3112,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock · 22 unmodified lines | ||
| 3106 | 3112 | { |
| 3107 | 3113 | struct inode *inode = state->inode; |
| 3108 | 3114 | struct nfs_server *server = NFS_SERVER(inode); |
| 3109 | − struct nfs4_client *clp = server->nfs4_state; | |
| 3115 | + struct nfs_client *clp = server->nfs_client; | |
| 3110 | 3116 | struct nfs_lockt_args arg = { |
| 3111 | 3117 | .fh = NFS_FH(inode), |
| 3112 | 3118 | .fl = request, |
| @@ -3231,7 +3237,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) · 118 unmodified lines | ||
| 3231 | 3237 | break; |
| 3232 | 3238 | case -NFS4ERR_STALE_STATEID: |
| 3233 | 3239 | case -NFS4ERR_EXPIRED: |
| 3234 | − nfs4_schedule_state_recovery(calldata->server->nfs4_state); | |
| 3240 | + nfs4_schedule_state_recovery(calldata->server->nfs_client); | |
| 3235 | 3241 | break; |
| 3236 | 3242 | default: |
| 3237 | 3243 | if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN) { |
| @@ -3343,7 +3349,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, · 105 unmodified lines | ||
| 3343 | 3349 | if (p->arg.lock_seqid == NULL) |
| 3344 | 3350 | goto out_free; |
| 3345 | 3351 | p->arg.lock_stateid = &lsp->ls_stateid; |
| 3346 | − p->arg.lock_owner.clientid = server->nfs4_state->cl_clientid; | |
| 3352 | + p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; | |
| 3347 | 3353 | p->arg.lock_owner.id = lsp->ls_id; |
| 3348 | 3354 | p->lsp = lsp; |
| 3349 | 3355 | atomic_inc(&lsp->ls_count); |
| @@ -3513,7 +3519,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request · 163 unmodified lines | ||
| 3513 | 3519 | |
| 3514 | 3520 | static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) |
| 3515 | 3521 | { |
| 3516 | − struct nfs4_client *clp = state->owner->so_client; | |
| 3522 | + struct nfs_client *clp = state->owner->so_client; | |
| 3517 | 3523 | unsigned char fl_flags = request->fl_flags; |
| 3518 | 3524 | int status; |
| 3519 | 3525 | |
| @@ -3715,7 +3721,7 @@ static struct inode_operations nfs4_file_inode_operations = { · 195 unmodified lines | ||
| 3715 | 3721 | .listxattr = nfs4_listxattr, |
| 3716 | 3722 | }; |
| 3717 | 3723 | |
| 3718 | −struct nfs_rpc_ops nfs_v4_clientops = { | |
| 3724 | +const struct nfs_rpc_ops nfs_v4_clientops = { | |
| 3719 | 3725 | .version = 4, /* protocol version */ |
| 3720 | 3726 | .dentry_ops = &nfs4_dentry_operations, |
| 3721 | 3727 | .dir_inode_ops = &nfs4_dir_inode_operations, |
| @@ -3723,6 +3729,7 @@ struct nfs_rpc_ops nfs_v4_clientops = { · 1 unmodified line | ||
| 3723 | 3729 | .getroot = nfs4_proc_get_root, |
| 3724 | 3730 | .getattr = nfs4_proc_getattr, |
| 3725 | 3731 | .setattr = nfs4_proc_setattr, |
| 3732 | + .lookupfh = nfs4_proc_lookupfh, | |
| 3726 | 3733 | .lookup = nfs4_proc_lookup, |
| 3727 | 3734 | .access = nfs4_proc_access, |
| 3728 | 3735 | .readlink = nfs4_proc_readlink, |
| @@ -3743,6 +3750,7 @@ struct nfs_rpc_ops nfs_v4_clientops = { · 14 unmodified lines | ||
| 3743 | 3750 | .statfs = nfs4_proc_statfs, |
| 3744 | 3751 | .fsinfo = nfs4_proc_fsinfo, |
| 3745 | 3752 | .pathconf = nfs4_proc_pathconf, |
| 3753 | + .set_capabilities = nfs4_server_capabilities, | |
| 3746 | 3754 | .decode_dirent = nfs4_decode_dirent, |
| 3747 | 3755 | .read_setup = nfs4_proc_read_setup, |
| 3748 | 3756 | .read_done = nfs4_read_done, |
| @@ -61,7 +61,7 @@ · 60 unmodified lines | ||
| 61 | 61 | void |
| 62 | 62 | nfs4_renew_state(void *data) |
| 63 | 63 | { |
| 64 | − struct nfs4_client *clp = (struct nfs4_client *)data; | |
| 64 | + struct nfs_client *clp = (struct nfs_client *)data; | |
| 65 | 65 | struct rpc_cred *cred; |
| 66 | 66 | long lease, timeout; |
| 67 | 67 | unsigned long last, now; |
| @@ -108,7 +108,7 @@ out: · 40 unmodified lines | ||
| 108 | 108 | |
| 109 | 109 | /* Must be called with clp->cl_sem locked for writes */ |
| 110 | 110 | void |
| 111 | −nfs4_schedule_state_renewal(struct nfs4_client *clp) | |
| 111 | +nfs4_schedule_state_renewal(struct nfs_client *clp) | |
| 112 | 112 | { |
| 113 | 113 | long timeout; |
| 114 | 114 | |
| @@ -121,32 +121,20 @@ nfs4_schedule_state_renewal(struct nfs4_client *clp) · 6 unmodified lines | ||
| 121 | 121 | __FUNCTION__, (timeout + HZ - 1) / HZ); |
| 122 | 122 | cancel_delayed_work(&clp->cl_renewd); |
| 123 | 123 | schedule_delayed_work(&clp->cl_renewd, timeout); |
| 124 | + set_bit(NFS_CS_RENEWD, &clp->cl_res_state); | |
| 124 | 125 | spin_unlock(&clp->cl_lock); |
| 125 | 126 | } |
| 126 | 127 | |
| 127 | 128 | void |
| 128 | 129 | nfs4_renewd_prepare_shutdown(struct nfs_server *server) |
| 129 | 130 | { |
| 130 | − struct nfs4_client *clp = server->nfs4_state; | |
| 131 | − | |
| 132 | − if (!clp) | |
| 133 | − return; | |
| 134 | 131 | flush_scheduled_work(); |
| 135 | − down_write(&clp->cl_sem); | |
| 136 | − if (!list_empty(&server->nfs4_siblings)) | |
| 137 | − list_del_init(&server->nfs4_siblings); | |
| 138 | − up_write(&clp->cl_sem); | |
| 139 | 132 | } |
| 140 | 133 | |
| 141 | −/* Must be called with clp->cl_sem locked for writes */ | |
| 142 | 134 | void |
| 143 | −nfs4_kill_renewd(struct nfs4_client *clp) | |
| 135 | +nfs4_kill_renewd(struct nfs_client *clp) | |
| 144 | 136 | { |
| 145 | 137 | down_read(&clp->cl_sem); |
| 146 | − if (!list_empty(&clp->cl_superblocks)) { | |
| 147 | − up_read(&clp->cl_sem); | |
| 148 | − return; | |
| 149 | − } | |
| 150 | 138 | cancel_delayed_work(&clp->cl_renewd); |
| 151 | 139 | up_read(&clp->cl_sem); |
| 152 | 140 | flush_scheduled_work(); |
| @@ -50,149 +50,15 @@ · 49 unmodified lines | ||
| 50 | 50 | #include "nfs4_fs.h" |
| 51 | 51 | #include "callback.h" |
| 52 | 52 | #include "delegation.h" |
| 53 | +#include "internal.h" | |
| 53 | 54 | |
| 54 | 55 | #define OPENOWNER_POOL_SIZE 8 |
| 55 | 56 | |
| 56 | 57 | const nfs4_stateid zero_stateid; |
| 57 | 58 | |
| 58 | −static DEFINE_SPINLOCK(state_spinlock); | |
| 59 | 59 | static LIST_HEAD(nfs4_clientid_list); |
| 60 | 60 | |
| 61 | −void | |
| 62 | −init_nfsv4_state(struct nfs_server *server) | |
| 63 | −{ | |
| 64 | − server->nfs4_state = NULL; | |
| 65 | − INIT_LIST_HEAD(&server->nfs4_siblings); | |
| 66 | −} | |
| 67 | − | |
| 68 | −void | |
| 69 | −destroy_nfsv4_state(struct nfs_server *server) | |
| 70 | −{ | |
| 71 | − kfree(server->mnt_path); | |
| 72 | − server->mnt_path = NULL; | |
| 73 | − if (server->nfs4_state) { | |
| 74 | − nfs4_put_client(server->nfs4_state); | |
| 75 | − server->nfs4_state = NULL; | |
| 76 | − } | |
| 77 | −} | |
| 78 | − | |
| 79 | −/* | |
| 80 | − * nfs4_get_client(): returns an empty client structure | |
| 81 | − * nfs4_put_client(): drops reference to client structure | |
| 82 | − * | |
| 83 | − * Since these are allocated/deallocated very rarely, we don't | |
| 84 | − * bother putting them in a slab cache... | |
| 85 | − */ | |
| 86 | −static struct nfs4_client * | |
| 87 | −nfs4_alloc_client(struct in_addr *addr) | |
| 88 | −{ | |
| 89 | − struct nfs4_client *clp; | |
| 90 | − | |
| 91 | − if (nfs_callback_up() < 0) | |
| 92 | − return NULL; | |
| 93 | − if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) { | |
| 94 | − nfs_callback_down(); | |
| 95 | − return NULL; | |
| 96 | − } | |
| 97 | − memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); | |
| 98 | − init_rwsem(&clp->cl_sem); | |
| 99 | − INIT_LIST_HEAD(&clp->cl_delegations); | |
| 100 | − INIT_LIST_HEAD(&clp->cl_state_owners); | |
| 101 | − INIT_LIST_HEAD(&clp->cl_unused); | |
| 102 | − spin_lock_init(&clp->cl_lock); | |
| 103 | − atomic_set(&clp->cl_count, 1); | |
| 104 | − INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); | |
| 105 | − INIT_LIST_HEAD(&clp->cl_superblocks); | |
| 106 | − rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); | |
| 107 | − clp->cl_rpcclient = ERR_PTR(-EINVAL); | |
| 108 | − clp->cl_boot_time = CURRENT_TIME; | |
| 109 | − clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | |
| 110 | − return clp; | |
| 111 | −} | |
| 112 | − | |
| 113 | −static void | |
| 114 | −nfs4_free_client(struct nfs4_client *clp) | |
| 115 | −{ | |
| 116 | − struct nfs4_state_owner *sp; | |
| 117 | − | |
| 118 | − while (!list_empty(&clp->cl_unused)) { | |
| 119 | − sp = list_entry(clp->cl_unused.next, | |
| 120 | − struct nfs4_state_owner, | |
| 121 | − so_list); | |
| 122 | − list_del(&sp->so_list); | |
| 123 | − kfree(sp); | |
| 124 | − } | |
| 125 | − BUG_ON(!list_empty(&clp->cl_state_owners)); | |
| 126 | − nfs_idmap_delete(clp); | |
| 127 | − if (!IS_ERR(clp->cl_rpcclient)) | |
| 128 | − rpc_shutdown_client(clp->cl_rpcclient); | |
| 129 | − kfree(clp); | |
| 130 | − nfs_callback_down(); | |
| 131 | −} | |
| 132 | − | |
| 133 | −static struct nfs4_client *__nfs4_find_client(struct in_addr *addr) | |
| 134 | −{ | |
| 135 | − struct nfs4_client *clp; | |
| 136 | − list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) { | |
| 137 | − if (memcmp(&clp->cl_addr, addr, sizeof(clp->cl_addr)) == 0) { | |
| 138 | − atomic_inc(&clp->cl_count); | |
| 139 | − return clp; | |
| 140 | − } | |
| 141 | − } | |
| 142 | − return NULL; | |
| 143 | −} | |
| 144 | − | |
| 145 | −struct nfs4_client *nfs4_find_client(struct in_addr *addr) | |
| 146 | −{ | |
| 147 | − struct nfs4_client *clp; | |
| 148 | − spin_lock(&state_spinlock); | |
| 149 | − clp = __nfs4_find_client(addr); | |
| 150 | − spin_unlock(&state_spinlock); | |
| 151 | − return clp; | |
| 152 | −} | |
| 153 | − | |
| 154 | −struct nfs4_client * | |
| 155 | −nfs4_get_client(struct in_addr *addr) | |
| 156 | −{ | |
| 157 | − struct nfs4_client *clp, *new = NULL; | |
| 158 | − | |
| 159 | − spin_lock(&state_spinlock); | |
| 160 | − for (;;) { | |
| 161 | − clp = __nfs4_find_client(addr); | |
| 162 | − if (clp != NULL) | |
| 163 | − break; | |
| 164 | − clp = new; | |
| 165 | − if (clp != NULL) { | |
| 166 | − list_add(&clp->cl_servers, &nfs4_clientid_list); | |
| 167 | − new = NULL; | |
| 168 | − break; | |
| 169 | − } | |
| 170 | − spin_unlock(&state_spinlock); | |
| 171 | − new = nfs4_alloc_client(addr); | |
| 172 | − spin_lock(&state_spinlock); | |
| 173 | − if (new == NULL) | |
| 174 | − break; | |
| 175 | − } | |
| 176 | − spin_unlock(&state_spinlock); | |
| 177 | − if (new) | |
| 178 | − nfs4_free_client(new); | |
| 179 | − return clp; | |
| 180 | −} | |
| 181 | − | |
| 182 | −void | |
| 183 | −nfs4_put_client(struct nfs4_client *clp) | |
| 184 | −{ | |
| 185 | − if (!atomic_dec_and_lock(&clp->cl_count, &state_spinlock)) | |
| 186 | − return; | |
| 187 | − list_del(&clp->cl_servers); | |
| 188 | − spin_unlock(&state_spinlock); | |
| 189 | − BUG_ON(!list_empty(&clp->cl_superblocks)); | |
| 190 | − rpc_wake_up(&clp->cl_rpcwaitq); | |
| 191 | − nfs4_kill_renewd(clp); | |
| 192 | − nfs4_free_client(clp); | |
| 193 | −} | |
| 194 | − | |
| 195 | −static int nfs4_init_client(struct nfs4_client *clp, struct rpc_cred *cred) | |
| 61 | +static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred) | |
| 196 | 62 | { |
| 197 | 63 | int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, |
| 198 | 64 | nfs_callback_tcpport, cred); |
| @@ -204,13 +70,13 @@ static int nfs4_init_client(struct nfs4_client *clp, struct rpc_cred *cred) · 5 unmodified lines | ||
| 204 | 70 | } |
| 205 | 71 | |
| 206 | 72 | u32 |
| 207 | −nfs4_alloc_lockowner_id(struct nfs4_client *clp) | |
| 73 | +nfs4_alloc_lockowner_id(struct nfs_client *clp) | |
| 208 | 74 | { |
| 209 | 75 | return clp->cl_lockowner_id ++; |
| 210 | 76 | } |
| 211 | 77 | |
| 212 | 78 | static struct nfs4_state_owner * |
| 213 | −nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred) | |
| 79 | +nfs4_client_grab_unused(struct nfs_client *clp, struct rpc_cred *cred) | |
| 214 | 80 | { |
| 215 | 81 | struct nfs4_state_owner *sp = NULL; |
| 216 | 82 | |
| @@ -224,7 +90,7 @@ nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred) · 7 unmodified lines | ||
| 224 | 90 | return sp; |
| 225 | 91 | } |
| 226 | 92 | |
| 227 | −struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp) | |
| 93 | +struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp) | |
| 228 | 94 | { |
| 229 | 95 | struct nfs4_state_owner *sp; |
| 230 | 96 | struct rpc_cred *cred = NULL; |
| @@ -238,7 +104,7 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp) · 7 unmodified lines | ||
| 238 | 104 | return cred; |
| 239 | 105 | } |
| 240 | 106 | |
| 241 | −struct rpc_cred *nfs4_get_setclientid_cred(struct nfs4_client *clp) | |
| 107 | +struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) | |
| 242 | 108 | { |
| 243 | 109 | struct nfs4_state_owner *sp; |
| 244 | 110 | |
| @@ -251,7 +117,7 @@ struct rpc_cred *nfs4_get_setclientid_cred(struct nfs4_client *clp) · 6 unmodified lines | ||
| 251 | 117 | } |
| 252 | 118 | |
| 253 | 119 | static struct nfs4_state_owner * |
| 254 | −nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred) | |
| 120 | +nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred) | |
| 255 | 121 | { |
| 256 | 122 | struct nfs4_state_owner *sp, *res = NULL; |
| 257 | 123 | |
| @@ -294,7 +160,7 @@ nfs4_alloc_state_owner(void) · 36 unmodified lines | ||
| 294 | 160 | void |
| 295 | 161 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) |
| 296 | 162 | { |
| 297 | − struct nfs4_client *clp = sp->so_client; | |
| 163 | + struct nfs_client *clp = sp->so_client; | |
| 298 | 164 | spin_lock(&clp->cl_lock); |
| 299 | 165 | list_del_init(&sp->so_list); |
| 300 | 166 | spin_unlock(&clp->cl_lock); |
| @@ -306,7 +172,7 @@ nfs4_drop_state_owner(struct nfs4_state_owner *sp) · 5 unmodified lines | ||
| 306 | 172 | */ |
| 307 | 173 | struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred) |
| 308 | 174 | { |
| 309 | − struct nfs4_client *clp = server->nfs4_state; | |
| 175 | + struct nfs_client *clp = server->nfs_client; | |
| 310 | 176 | struct nfs4_state_owner *sp, *new; |
| 311 | 177 | |
| 312 | 178 | get_rpccred(cred); |
| @@ -337,7 +203,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct · 24 unmodified lines | ||
| 337 | 203 | */ |
| 338 | 204 | void nfs4_put_state_owner(struct nfs4_state_owner *sp) |
| 339 | 205 | { |
| 340 | − struct nfs4_client *clp = sp->so_client; | |
| 206 | + struct nfs_client *clp = sp->so_client; | |
| 341 | 207 | struct rpc_cred *cred = sp->so_cred; |
| 342 | 208 | |
| 343 | 209 | if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) |
| @@ -540,7 +406,7 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) · 196 unmodified lines | ||
| 540 | 406 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) |
| 541 | 407 | { |
| 542 | 408 | struct nfs4_lock_state *lsp; |
| 543 | − struct nfs4_client *clp = state->owner->so_client; | |
| 409 | + struct nfs_client *clp = state->owner->so_client; | |
| 544 | 410 | |
| 545 | 411 | lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); |
| 546 | 412 | if (lsp == NULL) |
| @@ -752,7 +618,7 @@ out: · 205 unmodified lines | ||
| 752 | 618 | |
| 753 | 619 | static int reclaimer(void *); |
| 754 | 620 | |
| 755 | −static inline void nfs4_clear_recover_bit(struct nfs4_client *clp) | |
| 621 | +static inline void nfs4_clear_recover_bit(struct nfs_client *clp) | |
| 756 | 622 | { |
| 757 | 623 | smp_mb__before_clear_bit(); |
| 758 | 624 | clear_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state); |
| @@ -764,25 +630,25 @@ static inline void nfs4_clear_recover_bit(struct nfs4_client *clp) · 5 unmodified lines | ||
| 764 | 630 | /* |
| 765 | 631 | * State recovery routine |
| 766 | 632 | */ |
| 767 | −static void nfs4_recover_state(struct nfs4_client *clp) | |
| 633 | +static void nfs4_recover_state(struct nfs_client *clp) | |
| 768 | 634 | { |
| 769 | 635 | struct task_struct *task; |
| 770 | 636 | |
| 771 | 637 | __module_get(THIS_MODULE); |
| 772 | 638 | atomic_inc(&clp->cl_count); |
| 773 | 639 | task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim", |
| 774 | − NIPQUAD(clp->cl_addr)); | |
| 640 | + NIPQUAD(clp->cl_addr.sin_addr)); | |
| 775 | 641 | if (!IS_ERR(task)) |
| 776 | 642 | return; |
| 777 | 643 | nfs4_clear_recover_bit(clp); |
| 778 | − nfs4_put_client(clp); | |
| 644 | + nfs_put_client(clp); | |
| 779 | 645 | module_put(THIS_MODULE); |
| 780 | 646 | } |
| 781 | 647 | |
| 782 | 648 | /* |
| 783 | 649 | * Schedule a state recovery attempt |
| 784 | 650 | */ |
| 785 | −void nfs4_schedule_state_recovery(struct nfs4_client *clp) | |
| 651 | +void nfs4_schedule_state_recovery(struct nfs_client *clp) | |
| 786 | 652 | { |
| 787 | 653 | if (!clp) |
| 788 | 654 | return; |
| @@ -879,7 +745,7 @@ out_err: · 90 unmodified lines | ||
| 879 | 745 | return status; |
| 880 | 746 | } |
| 881 | 747 | |
| 882 | −static void nfs4_state_mark_reclaim(struct nfs4_client *clp) | |
| 748 | +static void nfs4_state_mark_reclaim(struct nfs_client *clp) | |
| 883 | 749 | { |
| 884 | 750 | struct nfs4_state_owner *sp; |
| 885 | 751 | struct nfs4_state *state; |
| @@ -903,7 +769,7 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp) · 17 unmodified lines | ||
| 903 | 769 | |
| 904 | 770 | static int reclaimer(void *ptr) |
| 905 | 771 | { |
| 906 | − struct nfs4_client *clp = ptr; | |
| 772 | + struct nfs_client *clp = ptr; | |
| 907 | 773 | struct nfs4_state_owner *sp; |
| 908 | 774 | struct nfs4_state_recovery_ops *ops; |
| 909 | 775 | struct rpc_cred *cred; |
| @@ -970,12 +836,12 @@ out: · 60 unmodified lines | ||
| 970 | 836 | if (status == -NFS4ERR_CB_PATH_DOWN) |
| 971 | 837 | nfs_handle_cb_pathdown(clp); |
| 972 | 838 | nfs4_clear_recover_bit(clp); |
| 973 | − nfs4_put_client(clp); | |
| 839 | + nfs_put_client(clp); | |
| 974 | 840 | module_put_and_exit(0); |
| 975 | 841 | return 0; |
| 976 | 842 | out_error: |
| 977 | 843 | printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n", |
| 978 | − NIPQUAD(clp->cl_addr.s_addr), -status); | |
| 844 | + NIPQUAD(clp->cl_addr.sin_addr), -status); | |
| 979 | 845 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
| 980 | 846 | goto out; |
| 981 | 847 | } |
| @@ -58,7 +58,7 @@ · 57 unmodified lines | ||
| 58 | 58 | /* Mapping from NFS error code to "errno" error code. */ |
| 59 | 59 | #define errno_NFSERR_IO EIO |
| 60 | 60 | |
| 61 | −static int nfs_stat_to_errno(int); | |
| 61 | +static int nfs4_stat_to_errno(int); | |
| 62 | 62 | |
| 63 | 63 | /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ |
| 64 | 64 | #ifdef DEBUG |
| @@ -128,7 +128,7 @@ static int nfs_stat_to_errno(int); · 63 unmodified lines | ||
| 128 | 128 | #define decode_link_maxsz (op_decode_hdr_maxsz + 5) |
| 129 | 129 | #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ |
| 130 | 130 | 1 + nfs4_name_maxsz + \ |
| 131 | − nfs4_path_maxsz + \ | |
| 131 | + 1 + \ | |
| 132 | 132 | nfs4_fattr_maxsz) |
| 133 | 133 | #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) |
| 134 | 134 | #define encode_create_maxsz (op_encode_hdr_maxsz + \ |
| @@ -529,7 +529,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s · 394 unmodified lines | ||
| 529 | 529 | if (iap->ia_valid & ATTR_MODE) |
| 530 | 530 | len += 4; |
| 531 | 531 | if (iap->ia_valid & ATTR_UID) { |
| 532 | − owner_namelen = nfs_map_uid_to_name(server->nfs4_state, iap->ia_uid, owner_name); | |
| 532 | + owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name); | |
| 533 | 533 | if (owner_namelen < 0) { |
| 534 | 534 | printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n", |
| 535 | 535 | iap->ia_uid); |
| @@ -541,7 +541,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s · 5 unmodified lines | ||
| 541 | 541 | len += 4 + (XDR_QUADLEN(owner_namelen) << 2); |
| 542 | 542 | } |
| 543 | 543 | if (iap->ia_valid & ATTR_GID) { |
| 544 | − owner_grouplen = nfs_map_gid_to_group(server->nfs4_state, iap->ia_gid, owner_group); | |
| 544 | + owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group); | |
| 545 | 545 | if (owner_grouplen < 0) { |
| 546 | 546 | printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n", |
| 547 | 547 | iap->ia_gid); |
| @@ -673,9 +673,9 @@ static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *c · 125 unmodified lines | ||
| 673 | 673 | |
| 674 | 674 | switch (create->ftype) { |
| 675 | 675 | case NF4LNK: |
| 676 | − RESERVE_SPACE(4 + create->u.symlink->len); | |
| 677 | − WRITE32(create->u.symlink->len); | |
| 678 | − WRITEMEM(create->u.symlink->name, create->u.symlink->len); | |
| 676 | + RESERVE_SPACE(4); | |
| 677 | + WRITE32(create->u.symlink.len); | |
| 678 | + xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len); | |
| 679 | 679 | break; |
| 680 | 680 | |
| 681 | 681 | case NF4BLK: case NF4CHR: |
| @@ -1160,7 +1160,7 @@ static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, con · 478 unmodified lines | ||
| 1160 | 1160 | return 0; |
| 1161 | 1161 | } |
| 1162 | 1162 | |
| 1163 | −static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client_stateid) | |
| 1163 | +static int encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid) | |
| 1164 | 1164 | { |
| 1165 | 1165 | uint32_t *p; |
| 1166 | 1166 | |
| @@ -1246,7 +1246,7 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclien · 79 unmodified lines | ||
| 1246 | 1246 | return 0; |
| 1247 | 1247 | } |
| 1248 | 1248 | |
| 1249 | −static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_client *client_state) | |
| 1249 | +static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state) | |
| 1250 | 1250 | { |
| 1251 | 1251 | uint32_t *p; |
| 1252 | 1252 | |
| @@ -1945,7 +1945,7 @@ static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, uint32_t *p, const str · 692 unmodified lines | ||
| 1945 | 1945 | /* |
| 1946 | 1946 | * a RENEW request |
| 1947 | 1947 | */ |
| 1948 | −static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp) | |
| 1948 | +static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp) | |
| 1949 | 1949 | { |
| 1950 | 1950 | struct xdr_stream xdr; |
| 1951 | 1951 | struct compound_hdr hdr = { |
| @@ -1975,7 +1975,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, uint32_t *p, struct nf · 23 unmodified lines | ||
| 1975 | 1975 | /* |
| 1976 | 1976 | * a SETCLIENTID_CONFIRM request |
| 1977 | 1977 | */ |
| 1978 | −static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp) | |
| 1978 | +static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp) | |
| 1979 | 1979 | { |
| 1980 | 1980 | struct xdr_stream xdr; |
| 1981 | 1981 | struct compound_hdr hdr = { |
| @@ -2127,12 +2127,12 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) · 145 unmodified lines | ||
| 2127 | 2127 | } |
| 2128 | 2128 | READ32(nfserr); |
| 2129 | 2129 | if (nfserr != NFS_OK) |
| 2130 | − return -nfs_stat_to_errno(nfserr); | |
| 2130 | + return -nfs4_stat_to_errno(nfserr); | |
| 2131 | 2131 | return 0; |
| 2132 | 2132 | } |
| 2133 | 2133 | |
| 2134 | 2134 | /* Dummy routine */ |
| 2135 | −static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs4_client *clp) | |
| 2135 | +static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp) | |
| 2136 | 2136 | { |
| 2137 | 2137 | uint32_t *p; |
| 2138 | 2138 | unsigned int strlen; |
| @@ -2636,7 +2636,7 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t · 497 unmodified lines | ||
| 2636 | 2636 | return 0; |
| 2637 | 2637 | } |
| 2638 | 2638 | |
| 2639 | −static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *uid) | |
| 2639 | +static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *uid) | |
| 2640 | 2640 | { |
| 2641 | 2641 | uint32_t len, *p; |
| 2642 | 2642 | |
| @@ -2660,7 +2660,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nf · 17 unmodified lines | ||
| 2660 | 2660 | return 0; |
| 2661 | 2661 | } |
| 2662 | 2662 | |
| 2663 | −static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *gid) | |
| 2663 | +static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *gid) | |
| 2664 | 2664 | { |
| 2665 | 2665 | uint32_t len, *p; |
| 2666 | 2666 | |
| @@ -3051,9 +3051,9 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons · 384 unmodified lines | ||
| 3051 | 3051 | fattr->mode |= fmode; |
| 3052 | 3052 | if ((status = decode_attr_nlink(xdr, bitmap, &fattr->nlink)) != 0) |
| 3053 | 3053 | goto xdr_error; |
| 3054 | − if ((status = decode_attr_owner(xdr, bitmap, server->nfs4_state, &fattr->uid)) != 0) | |
| 3054 | + if ((status = decode_attr_owner(xdr, bitmap, server->nfs_client, &fattr->uid)) != 0) | |
| 3055 | 3055 | goto xdr_error; |
| 3056 | − if ((status = decode_attr_group(xdr, bitmap, server->nfs4_state, &fattr->gid)) != 0) | |
| 3056 | + if ((status = decode_attr_group(xdr, bitmap, server->nfs_client, &fattr->gid)) != 0) | |
| 3057 | 3057 | goto xdr_error; |
| 3058 | 3058 | if ((status = decode_attr_rdev(xdr, bitmap, &fattr->rdev)) != 0) |
| 3059 | 3059 | goto xdr_error; |
| @@ -3254,7 +3254,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) · 194 unmodified lines | ||
| 3254 | 3254 | if (decode_space_limit(xdr, &res->maxsize) < 0) |
| 3255 | 3255 | return -EIO; |
| 3256 | 3256 | } |
| 3257 | − return decode_ace(xdr, NULL, res->server->nfs4_state); | |
| 3257 | + return decode_ace(xdr, NULL, res->server->nfs_client); | |
| 3258 | 3258 | } |
| 3259 | 3259 | |
| 3260 | 3260 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) |
| @@ -3565,7 +3565,7 @@ static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res) · 304 unmodified lines | ||
| 3565 | 3565 | return 0; |
| 3566 | 3566 | } |
| 3567 | 3567 | |
| 3568 | −static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp) | |
| 3568 | +static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp) | |
| 3569 | 3569 | { |
| 3570 | 3570 | uint32_t *p; |
| 3571 | 3571 | uint32_t opnum; |
| @@ -3598,7 +3598,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp) · 26 unmodified lines | ||
| 3598 | 3598 | READ_BUF(len); |
| 3599 | 3599 | return -NFSERR_CLID_INUSE; |
| 3600 | 3600 | } else |
| 3601 | − return -nfs_stat_to_errno(nfserr); | |
| 3601 | + return -nfs4_stat_to_errno(nfserr); | |
| 3602 | 3602 | |
| 3603 | 3603 | return 0; |
| 3604 | 3604 | } |
| @@ -4256,7 +4256,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs_fsi · 651 unmodified lines | ||
| 4256 | 4256 | if (!status) |
| 4257 | 4257 | status = decode_fsinfo(&xdr, fsinfo); |
| 4258 | 4258 | if (!status) |
| 4259 | − status = -nfs_stat_to_errno(hdr.status); | |
| 4259 | + status = -nfs4_stat_to_errno(hdr.status); | |
| 4260 | 4260 | return status; |
| 4261 | 4261 | } |
| 4262 | 4262 | |
| @@ -4335,7 +4335,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy) · 72 unmodified lines | ||
| 4335 | 4335 | * a SETCLIENTID request |
| 4336 | 4336 | */ |
| 4337 | 4337 | static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, |
| 4338 | − struct nfs4_client *clp) | |
| 4338 | + struct nfs_client *clp) | |
| 4339 | 4339 | { |
| 4340 | 4340 | struct xdr_stream xdr; |
| 4341 | 4341 | struct compound_hdr hdr; |
| @@ -4346,7 +4346,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, · 4 unmodified lines | ||
| 4346 | 4346 | if (!status) |
| 4347 | 4347 | status = decode_setclientid(&xdr, clp); |
| 4348 | 4348 | if (!status) |
| 4349 | − status = -nfs_stat_to_errno(hdr.status); | |
| 4349 | + status = -nfs4_stat_to_errno(hdr.status); | |
| 4350 | 4350 | return status; |
| 4351 | 4351 | } |
| 4352 | 4352 | |
| @@ -4368,7 +4368,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s · 15 unmodified lines | ||
| 4368 | 4368 | if (!status) |
| 4369 | 4369 | status = decode_fsinfo(&xdr, fsinfo); |
| 4370 | 4370 | if (!status) |
| 4371 | − status = -nfs_stat_to_errno(hdr.status); | |
| 4371 | + status = -nfs4_stat_to_errno(hdr.status); | |
| 4372 | 4372 | return status; |
| 4373 | 4373 | } |
| 4374 | 4374 | |
| @@ -4521,7 +4521,7 @@ static struct { · 146 unmodified lines | ||
| 4521 | 4521 | * This one is used jointly by NFSv2 and NFSv3. |
| 4522 | 4522 | */ |
| 4523 | 4523 | static int |
| 4524 | −nfs_stat_to_errno(int stat) | |
| 4524 | +nfs4_stat_to_errno(int stat) | |
| 4525 | 4525 | { |
| 4526 | 4526 | int i; |
| 4527 | 4527 | for (i = 0; nfs_errtbl[i].stat != -1; i++) { |
| @@ -66,14 +66,14 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, · 65 unmodified lines | ||
| 66 | 66 | |
| 67 | 67 | dprintk("%s: call getattr\n", __FUNCTION__); |
| 68 | 68 | nfs_fattr_init(fattr); |
| 69 | − status = rpc_call_sync(server->client_sys, &msg, 0); | |
| 69 | + status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); | |
| 70 | 70 | dprintk("%s: reply getattr: %d\n", __FUNCTION__, status); |
| 71 | 71 | if (status) |
| 72 | 72 | return status; |
| 73 | 73 | dprintk("%s: call statfs\n", __FUNCTION__); |
| 74 | 74 | msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS]; |
| 75 | 75 | msg.rpc_resp = &fsinfo; |
| 76 | − status = rpc_call_sync(server->client_sys, &msg, 0); | |
| 76 | + status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); | |
| 77 | 77 | dprintk("%s: reply statfs: %d\n", __FUNCTION__, status); |
| 78 | 78 | if (status) |
| 79 | 79 | return status; |
| @@ -425,16 +425,17 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) · 345 unmodified lines | ||
| 425 | 425 | } |
| 426 | 426 | |
| 427 | 427 | static int |
| 428 | −nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, | |
| 429 | − struct iattr *sattr, struct nfs_fh *fhandle, | |
| 430 | − struct nfs_fattr *fattr) | |
| 428 | +nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |
| 429 | + unsigned int len, struct iattr *sattr) | |
| 431 | 430 | { |
| 431 | + struct nfs_fh fhandle; | |
| 432 | + struct nfs_fattr fattr; | |
| 432 | 433 | struct nfs_symlinkargs arg = { |
| 433 | 434 | .fromfh = NFS_FH(dir), |
| 434 | − .fromname = name->name, | |
| 435 | − .fromlen = name->len, | |
| 436 | − .topath = path->name, | |
| 437 | − .tolen = path->len, | |
| 435 | + .fromname = dentry->d_name.name, | |
| 436 | + .fromlen = dentry->d_name.len, | |
| 437 | + .pages = &page, | |
| 438 | + .pathlen = len, | |
| 438 | 439 | .sattr = sattr |
| 439 | 440 | }; |
| 440 | 441 | struct rpc_message msg = { |
| @@ -443,13 +444,25 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, · 2 unmodified lines | ||
| 443 | 444 | }; |
| 444 | 445 | int status; |
| 445 | 446 | |
| 446 | − if (path->len > NFS2_MAXPATHLEN) | |
| 447 | + if (len > NFS2_MAXPATHLEN) | |
| 447 | 448 | return -ENAMETOOLONG; |
| 448 | − dprintk("NFS call symlink %s -> %s\n", name->name, path->name); | |
| 449 | − nfs_fattr_init(fattr); | |
| 450 | − fhandle->size = 0; | |
| 449 | + | |
| 450 | + dprintk("NFS call symlink %s\n", dentry->d_name.name); | |
| 451 | + | |
| 451 | 452 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 452 | 453 | nfs_mark_for_revalidate(dir); |
| 454 | + | |
| 455 | + /* | |
| 456 | + * V2 SYMLINK requests don't return any attributes. Setting the | |
| 457 | + * filehandle size to zero indicates to nfs_instantiate that it | |
| 458 | + * should fill in the data with a LOOKUP call on the wire. | |
| 459 | + */ | |
| 460 | + if (status == 0) { | |
| 461 | + nfs_fattr_init(&fattr); | |
| 462 | + fhandle.size = 0; | |
| 463 | + status = nfs_instantiate(dentry, &fhandle, &fattr); | |
| 464 | + } | |
| 465 | + | |
| 453 | 466 | dprintk("NFS reply symlink: %d\n", status); |
| 454 | 467 | return status; |
| 455 | 468 | } |
| @@ -671,7 +684,7 @@ nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) · 215 unmodified lines | ||
| 671 | 684 | } |
| 672 | 685 | |
| 673 | 686 | |
| 674 | −struct nfs_rpc_ops nfs_v2_clientops = { | |
| 687 | +const struct nfs_rpc_ops nfs_v2_clientops = { | |
| 675 | 688 | .version = 2, /* protocol version */ |
| 676 | 689 | .dentry_ops = &nfs_dentry_operations, |
| 677 | 690 | .dir_inode_ops = &nfs_dir_inode_operations, |
| @@ -171,7 +171,7 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode, · 170 unmodified lines | ||
| 171 | 171 | rdata->args.offset = page_offset(page) + rdata->args.pgbase; |
| 172 | 172 | |
| 173 | 173 | dprintk("NFS: nfs_proc_read(%s, (%s/%Ld), %Lu, %u)\n", |
| 174 | − NFS_SERVER(inode)->hostname, | |
| 174 | + NFS_SERVER(inode)->nfs_client->cl_hostname, | |
| 175 | 175 | inode->i_sb->s_id, |
| 176 | 176 | (long long)NFS_FILEID(inode), |
| 177 | 177 | (unsigned long long)rdata->args.pgbase, |
| @@ -568,8 +568,13 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) · 390 unmodified lines | ||
| 568 | 568 | |
| 569 | 569 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count); |
| 570 | 570 | |
| 571 | − /* Is this a short read? */ | |
| 572 | − if (task->tk_status >= 0 && resp->count < argp->count && !resp->eof) { | |
| 571 | + if (task->tk_status < 0) { | |
| 572 | + if (task->tk_status == -ESTALE) { | |
| 573 | + set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode)); | |
| 574 | + nfs_mark_for_revalidate(data->inode); | |
| 575 | + } | |
| 576 | + } else if (resp->count < argp->count && !resp->eof) { | |
| 577 | + /* This is a short read! */ | |
| 573 | 578 | nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); |
| 574 | 579 | /* Has the server at least made some progress? */ |
| 575 | 580 | if (resp->count != 0) { |
| @@ -616,6 +621,10 @@ int nfs_readpage(struct file *file, struct page *page) · 40 unmodified lines | ||
| 616 | 621 | if (error) |
| 617 | 622 | goto out_error; |
| 618 | 623 | |
| 624 | + error = -ESTALE; | |
| 625 | + if (NFS_STALE(inode)) | |
| 626 | + goto out_error; | |
| 627 | + | |
| 619 | 628 | if (file == NULL) { |
| 620 | 629 | ctx = nfs_find_open_context(inode, NULL, FMODE_READ); |
| 621 | 630 | if (ctx == NULL) |
| @@ -678,7 +687,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, · 56 unmodified lines | ||
| 678 | 687 | }; |
| 679 | 688 | struct inode *inode = mapping->host; |
| 680 | 689 | struct nfs_server *server = NFS_SERVER(inode); |
| 681 | − int ret; | |
| 690 | + int ret = -ESTALE; | |
| 682 | 691 | |
| 683 | 692 | dprintk("NFS: nfs_readpages (%s/%Ld %d)\n", |
| 684 | 693 | inode->i_sb->s_id, |
| @@ -686,6 +695,9 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, · 1 unmodified line | ||
| 686 | 695 | nr_pages); |
| 687 | 696 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGES); |
| 688 | 697 | |
| 698 | + if (NFS_STALE(inode)) | |
| 699 | + goto out; | |
| 700 | + | |
| 689 | 701 | if (filp == NULL) { |
| 690 | 702 | desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ); |
| 691 | 703 | if (desc.ctx == NULL) |
| @@ -701,6 +713,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, · 9 unmodified lines | ||
| 701 | 713 | ret = err; |
| 702 | 714 | } |
| 703 | 715 | put_nfs_open_context(desc.ctx); |
| 716 | +out: | |
| 704 | 717 | return ret; |
| 705 | 718 | } |
| 706 | 719 | |
| @@ -13,6 +13,11 @@ · 12 unmodified lines | ||
| 13 | 13 | * |
| 14 | 14 | * Split from inode.c by David Howells <dhowells@redhat.com> |
| 15 | 15 | * |
| 16 | + * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a | |
| 17 | + * particular server are held in the same superblock | |
| 18 | + * - NFS superblocks can have several effective roots to the dentry tree | |
| 19 | + * - directory type roots are spliced into the tree when a path from one root reaches the root | |
| 20 | + * of another (see nfs_lookup()) | |
| 16 | 21 | */ |
| 17 | 22 | |
| 18 | 23 | #include <linux/config.h> |
| @@ -52,66 +57,12 @@ · 33 unmodified lines | ||
| 52 | 57 | |
| 53 | 58 | #define NFSDBG_FACILITY NFSDBG_VFS |
| 54 | 59 | |
| 55 | −/* Maximum number of readahead requests | |
| 56 | − * FIXME: this should really be a sysctl so that users may tune it to suit | |
| 57 | − * their needs. People that do NFS over a slow network, might for | |
| 58 | − * instance want to reduce it to something closer to 1 for improved | |
| 59 | − * interactive response. | |
| 60 | − */ | |
| 61 | −#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) | |
| 62 | − | |
| 63 | −/* | |
| 64 | − * RPC cruft for NFS | |
| 65 | − */ | |
| 66 | −static struct rpc_version * nfs_version[] = { | |
| 67 | − NULL, | |
| 68 | − NULL, | |
| 69 | − &nfs_version2, | |
| 70 | −#if defined(CONFIG_NFS_V3) | |
| 71 | − &nfs_version3, | |
| 72 | −#elif defined(CONFIG_NFS_V4) | |
| 73 | − NULL, | |
| 74 | −#endif | |
| 75 | −#if defined(CONFIG_NFS_V4) | |
| 76 | − &nfs_version4, | |
| 77 | −#endif | |
| 78 | −}; | |
| 79 | − | |
| 80 | −static struct rpc_program nfs_program = { | |
| 81 | − .name = "nfs", | |
| 82 | − .number = NFS_PROGRAM, | |
| 83 | − .nrvers = ARRAY_SIZE(nfs_version), | |
| 84 | − .version = nfs_version, | |
| 85 | − .stats = &nfs_rpcstat, | |
| 86 | − .pipe_dir_name = "/nfs", | |
| 87 | −}; | |
| 88 | − | |
| 89 | −struct rpc_stat nfs_rpcstat = { | |
| 90 | − .program = &nfs_program | |
| 91 | −}; | |
| 92 | − | |
| 93 | − | |
| 94 | −#ifdef CONFIG_NFS_V3_ACL | |
| 95 | −static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; | |
| 96 | −static struct rpc_version * nfsacl_version[] = { | |
| 97 | − [3] = &nfsacl_version3, | |
| 98 | −}; | |
| 99 | − | |
| 100 | −struct rpc_program nfsacl_program = { | |
| 101 | − .name = "nfsacl", | |
| 102 | − .number = NFS_ACL_PROGRAM, | |
| 103 | − .nrvers = ARRAY_SIZE(nfsacl_version), | |
| 104 | − .version = nfsacl_version, | |
| 105 | − .stats = &nfsacl_rpcstat, | |
| 106 | −}; | |
| 107 | −#endif /* CONFIG_NFS_V3_ACL */ | |
| 108 | − | |
| 109 | 60 | static void nfs_umount_begin(struct vfsmount *, int); |
| 110 | 61 | static int nfs_statfs(struct dentry *, struct kstatfs *); |
| 111 | 62 | static int nfs_show_options(struct seq_file *, struct vfsmount *); |
| 112 | 63 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); |
| 113 | 64 | static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); |
| 114 | −static int nfs_clone_nfs_sb(struct file_system_type *fs_type, | |
| 65 | +static int nfs_xdev_get_sb(struct file_system_type *fs_type, | |
| 115 | 66 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); |
| 116 | 67 | static void nfs_kill_super(struct super_block *); |
| 117 | 68 | |
| @@ -123,10 +74,10 @@ static struct file_system_type nfs_fs_type = { · 5 unmodified lines | ||
| 123 | 74 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
| 124 | 75 | }; |
| 125 | 76 | |
| 126 | −struct file_system_type clone_nfs_fs_type = { | |
| 77 | +struct file_system_type nfs_xdev_fs_type = { | |
| 127 | 78 | .owner = THIS_MODULE, |
| 128 | 79 | .name = "nfs", |
| 129 | − .get_sb = nfs_clone_nfs_sb, | |
| 80 | + .get_sb = nfs_xdev_get_sb, | |
| 130 | 81 | .kill_sb = nfs_kill_super, |
| 131 | 82 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
| 132 | 83 | }; |
| @@ -145,10 +96,10 @@ static struct super_operations nfs_sops = { · 12 unmodified lines | ||
| 145 | 96 | #ifdef CONFIG_NFS_V4 |
| 146 | 97 | static int nfs4_get_sb(struct file_system_type *fs_type, |
| 147 | 98 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); |
| 148 | −static int nfs_clone_nfs4_sb(struct file_system_type *fs_type, | |
| 149 | − int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | |
| 150 | −static int nfs_referral_nfs4_sb(struct file_system_type *fs_type, | |
| 151 | − int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | |
| 99 | +static int nfs4_xdev_get_sb(struct file_system_type *fs_type, | |
| 100 | + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | |
| 101 | +static int nfs4_referral_get_sb(struct file_system_type *fs_type, | |
| 102 | + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | |
| 152 | 103 | static void nfs4_kill_super(struct super_block *sb); |
| 153 | 104 | |
| 154 | 105 | static struct file_system_type nfs4_fs_type = { |
| @@ -159,18 +110,18 @@ static struct file_system_type nfs4_fs_type = { · 4 unmodified lines | ||
| 159 | 110 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
| 160 | 111 | }; |
| 161 | 112 | |
| 162 | −struct file_system_type clone_nfs4_fs_type = { | |
| 113 | +struct file_system_type nfs4_xdev_fs_type = { | |
| 163 | 114 | .owner = THIS_MODULE, |
| 164 | 115 | .name = "nfs4", |
| 165 | − .get_sb = nfs_clone_nfs4_sb, | |
| 116 | + .get_sb = nfs4_xdev_get_sb, | |
| 166 | 117 | .kill_sb = nfs4_kill_super, |
| 167 | 118 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
| 168 | 119 | }; |
| 169 | 120 | |
| 170 | −struct file_system_type nfs_referral_nfs4_fs_type = { | |
| 121 | +struct file_system_type nfs4_referral_fs_type = { | |
| 171 | 122 | .owner = THIS_MODULE, |
| 172 | 123 | .name = "nfs4", |
| 173 | − .get_sb = nfs_referral_nfs4_sb, | |
| 124 | + .get_sb = nfs4_referral_get_sb, | |
| 174 | 125 | .kill_sb = nfs4_kill_super, |
| 175 | 126 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
| 176 | 127 | }; |
| @@ -187,39 +138,7 @@ static struct super_operations nfs4_sops = { · 10 unmodified lines | ||
| 187 | 138 | }; |
| 188 | 139 | #endif |
| 189 | 140 | |
| 190 | −#ifdef CONFIG_NFS_V4 | |
| 191 | −static const int nfs_set_port_min = 0; | |
| 192 | −static const int nfs_set_port_max = 65535; | |
| 193 | − | |
| 194 | −static int param_set_port(const char *val, struct kernel_param *kp) | |
| 195 | −{ | |
| 196 | − char *endp; | |
| 197 | − int num = simple_strtol(val, &endp, 0); | |
| 198 | − if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max) | |
| 199 | − return -EINVAL; | |
| 200 | − *((int *)kp->arg) = num; | |
| 201 | − return 0; | |
| 202 | −} | |
| 203 | − | |
| 204 | −module_param_call(callback_tcpport, param_set_port, param_get_int, | |
| 205 | − &nfs_callback_set_tcpport, 0644); | |
| 206 | −#endif | |
| 207 | − | |
| 208 | −#ifdef CONFIG_NFS_V4 | |
| 209 | −static int param_set_idmap_timeout(const char *val, struct kernel_param *kp) | |
| 210 | −{ | |
| 211 | − char *endp; | |
| 212 | − int num = simple_strtol(val, &endp, 0); | |
| 213 | − int jif = num * HZ; | |
| 214 | − if (endp == val || *endp || num < 0 || jif < num) | |
| 215 | − return -EINVAL; | |
| 216 | − *((int *)kp->arg) = jif; | |
| 217 | − return 0; | |
| 218 | −} | |
| 219 | − | |
| 220 | −module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, | |
| 221 | − &nfs_idmap_cache_timeout, 0644); | |
| 222 | −#endif | |
| 141 | +static struct shrinker *acl_shrinker; | |
| 223 | 142 | |
| 224 | 143 | /* |
| 225 | 144 | * Register the NFS filesystems |
| @@ -240,6 +159,7 @@ int __init register_nfs_fs(void) · 14 unmodified lines | ||
| 240 | 159 | if (ret < 0) |
| 241 | 160 | goto error_2; |
| 242 | 161 | #endif |
| 162 | + acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker); | |
| 243 | 163 | return 0; |
| 244 | 164 | |
| 245 | 165 | #ifdef CONFIG_NFS_V4 |
| @@ -257,6 +177,8 @@ error_0: · 11 unmodified lines | ||
| 257 | 177 | */ |
| 258 | 178 | void __exit unregister_nfs_fs(void) |
| 259 | 179 | { |
| 180 | + if (acl_shrinker != NULL) | |
| 181 | + remove_shrinker(acl_shrinker); | |
| 260 | 182 | #ifdef CONFIG_NFS_V4 |
| 261 | 183 | unregister_filesystem(&nfs4_fs_type); |
| 262 | 184 | nfs_unregister_sysctl(); |
| @@ -269,11 +191,10 @@ void __exit unregister_nfs_fs(void) · 6 unmodified lines | ||
| 269 | 191 | */ |
| 270 | 192 | static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
| 271 | 193 | { |
| 272 | − struct super_block *sb = dentry->d_sb; | |
| 273 | − struct nfs_server *server = NFS_SB(sb); | |
| 194 | + struct nfs_server *server = NFS_SB(dentry->d_sb); | |
| 274 | 195 | unsigned char blockbits; |
| 275 | 196 | unsigned long blockres; |
| 276 | − struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode); | |
| 197 | + struct nfs_fh *fh = NFS_FH(dentry->d_inode); | |
| 277 | 198 | struct nfs_fattr fattr; |
| 278 | 199 | struct nfs_fsstat res = { |
| 279 | 200 | .fattr = &fattr, |
| @@ -282,7 +203,7 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) · 2 unmodified lines | ||
| 282 | 203 | |
| 283 | 204 | lock_kernel(); |
| 284 | 205 | |
| 285 | − error = server->rpc_ops->statfs(server, rootfh, &res); | |
| 206 | + error = server->nfs_client->rpc_ops->statfs(server, fh, &res); | |
| 286 | 207 | buf->f_type = NFS_SUPER_MAGIC; |
| 287 | 208 | if (error < 0) |
| 288 | 209 | goto out_err; |
| @@ -292,7 +213,7 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) · 3 unmodified lines | ||
| 292 | 213 | * case where f_frsize != f_bsize. Eventually we want to |
| 293 | 214 | * report the value of wtmult in this field. |
| 294 | 215 | */ |
| 295 | − buf->f_frsize = sb->s_blocksize; | |
| 216 | + buf->f_frsize = dentry->d_sb->s_blocksize; | |
| 296 | 217 | |
| 297 | 218 | /* |
| 298 | 219 | * On most *nix systems, f_blocks, f_bfree, and f_bavail |
| @@ -301,8 +222,8 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) · 2 unmodified lines | ||
| 301 | 222 | * thus historically Linux's sys_statfs reports these |
| 302 | 223 | * fields in units of f_bsize. |
| 303 | 224 | */ |
| 304 | − buf->f_bsize = sb->s_blocksize; | |
| 305 | − blockbits = sb->s_blocksize_bits; | |
| 225 | + buf->f_bsize = dentry->d_sb->s_blocksize; | |
| 226 | + blockbits = dentry->d_sb->s_blocksize_bits; | |
| 306 | 227 | blockres = (1 << blockbits) - 1; |
| 307 | 228 | buf->f_blocks = (res.tbytes + blockres) >> blockbits; |
| 308 | 229 | buf->f_bfree = (res.fbytes + blockres) >> blockbits; |
| @@ -323,9 +244,12 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) · 14 unmodified lines | ||
| 323 | 244 | |
| 324 | 245 | } |
| 325 | 246 | |
| 247 | +/* | |
| 248 | + * Map the security flavour number to a name | |
| 249 | + */ | |
| 326 | 250 | static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) |
| 327 | 251 | { |
| 328 | − static struct { | |
| 252 | + static const struct { | |
| 329 | 253 | rpc_authflavor_t flavour; |
| 330 | 254 | const char *str; |
| 331 | 255 | } sec_flavours[] = { |
| @@ -356,10 +280,10 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) · 24 unmodified lines | ||
| 356 | 280 | */ |
| 357 | 281 | static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults) |
| 358 | 282 | { |
| 359 | − static struct proc_nfs_info { | |
| 283 | + static const struct proc_nfs_info { | |
| 360 | 284 | int flag; |
| 361 | − char *str; | |
| 362 | − char *nostr; | |
| 285 | + const char *str; | |
| 286 | + const char *nostr; | |
| 363 | 287 | } nfs_info[] = { |
| 364 | 288 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, |
| 365 | 289 | { NFS_MOUNT_INTR, ",intr", "" }, |
| @@ -369,11 +293,12 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, · 3 unmodified lines | ||
| 369 | 293 | { NFS_MOUNT_NOACL, ",noacl", "" }, |
| 370 | 294 | { 0, NULL, NULL } |
| 371 | 295 | }; |
| 372 | − struct proc_nfs_info *nfs_infop; | |
| 296 | + const struct proc_nfs_info *nfs_infop; | |
| 297 | + struct nfs_client *clp = nfss->nfs_client; | |
| 373 | 298 | char buf[12]; |
| 374 | − char *proto; | |
| 299 | + const char *proto; | |
| 375 | 300 | |
| 376 | − seq_printf(m, ",vers=%d", nfss->rpc_ops->version); | |
| 301 | + seq_printf(m, ",vers=%d", clp->rpc_ops->version); | |
| 377 | 302 | seq_printf(m, ",rsize=%d", nfss->rsize); |
| 378 | 303 | seq_printf(m, ",wsize=%d", nfss->wsize); |
| 379 | 304 | if (nfss->acregmin != 3*HZ || showdefaults) |
| @@ -402,8 +327,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, · 22 unmodified lines | ||
| 402 | 327 | proto = buf; |
| 403 | 328 | } |
| 404 | 329 | seq_printf(m, ",proto=%s", proto); |
| 405 | − seq_printf(m, ",timeo=%lu", 10U * nfss->retrans_timeo / HZ); | |
| 406 | − seq_printf(m, ",retrans=%u", nfss->retrans_count); | |
| 330 | + seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); | |
| 331 | + seq_printf(m, ",retrans=%u", clp->retrans_count); | |
| 407 | 332 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); |
| 408 | 333 | } |
| 409 | 334 | |
| @@ -417,7 +342,7 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) · 7 unmodified lines | ||
| 417 | 342 | nfs_show_mount_options(m, nfss, 0); |
| 418 | 343 | |
| 419 | 344 | seq_puts(m, ",addr="); |
| 420 | − seq_escape(m, nfss->hostname, " \t\n\\"); | |
| 345 | + seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\"); | |
| 421 | 346 | |
| 422 | 347 | return 0; |
| 423 | 348 | } |
| @@ -454,7 +379,7 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) · 30 unmodified lines | ||
| 454 | 379 | seq_printf(m, ",namelen=%d", nfss->namelen); |
| 455 | 380 | |
| 456 | 381 | #ifdef CONFIG_NFS_V4 |
| 457 | − if (nfss->rpc_ops->version == 4) { | |
| 382 | + if (nfss->nfs_client->cl_nfsversion == 4) { | |
| 458 | 383 | seq_printf(m, "\n\tnfsv4:\t"); |
| 459 | 384 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); |
| 460 | 385 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); |
| @@ -501,782 +426,353 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) · 40 unmodified lines | ||
| 501 | 426 | |
| 502 | 427 | /* |
| 503 | 428 | * Begin unmount by attempting to remove all automounted mountpoints we added |
| 504 | − * in response to traversals | |
| 429 | + * in response to xdev traversals and referrals | |
| 505 | 430 | */ |
| 506 | 431 | static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) |
| 507 | 432 | { |
| 508 | − struct nfs_server *server; | |
| 509 | − struct rpc_clnt *rpc; | |
| 510 | − | |
| 511 | 433 | shrink_submounts(vfsmnt, &nfs_automount_list); |
| 512 | − if (!(flags & MNT_FORCE)) | |
| 513 | − return; | |
| 514 | − /* -EIO all pending I/O */ | |
| 515 | − server = NFS_SB(vfsmnt->mnt_sb); | |
| 516 | − rpc = server->client; | |
| 517 | − if (!IS_ERR(rpc)) | |
| 518 | − rpc_killall_tasks(rpc); | |
| 519 | − rpc = server->client_acl; | |
| 520 | − if (!IS_ERR(rpc)) | |
| 521 | − rpc_killall_tasks(rpc); | |
| 522 | 434 | } |
| 523 | 435 | |
| 524 | 436 | /* |
| 525 | − * Obtain the root inode of the file system. | |
| 437 | + * Validate the NFS2/NFS3 mount data | |
| 438 | + * - fills in the mount root filehandle | |
| 526 | 439 | */ |
| 527 | −static struct inode * | |
| 528 | −nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo) | |
| 440 | +static int nfs_validate_mount_data(struct nfs_mount_data *data, | |
| 441 | + struct nfs_fh *mntfh) | |
| 529 | 442 | { |
| 530 | − struct nfs_server *server = NFS_SB(sb); | |
| 531 | − int error; | |
| 532 | − | |
| 533 | − error = server->rpc_ops->getroot(server, rootfh, fsinfo); | |
| 534 | − if (error < 0) { | |
| 535 | − dprintk("nfs_get_root: getattr error = %d\n", -error); | |
| 536 | − return ERR_PTR(error); | |
| 443 | + if (data == NULL) { | |
| 444 | + dprintk("%s: missing data argument\n", __FUNCTION__); | |
| 445 | + return -EINVAL; | |
| 537 | 446 | } |
| 538 | 447 | |
| 539 | − server->fsid = fsinfo->fattr->fsid; | |
| 540 | − return nfs_fhget(sb, rootfh, fsinfo->fattr); | |
| 541 | −} | |
| 542 | − | |
| 543 | −/* | |
| 544 | − * Do NFS version-independent mount processing, and sanity checking | |
| 545 | − */ | |
| 546 | −static int | |
| 547 | −nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor) | |
| 548 | −{ | |
| 549 | − struct nfs_server *server; | |
| 550 | − struct inode *root_inode; | |
| 551 | − struct nfs_fattr fattr; | |
| 552 | − struct nfs_fsinfo fsinfo = { | |
| 553 | − .fattr = &fattr, | |
| 554 | − }; | |
| 555 | − struct nfs_pathconf pathinfo = { | |
| 556 | − .fattr = &fattr, | |
| 557 | − }; | |
| 558 | − int no_root_error = 0; | |
| 559 | − unsigned long max_rpc_payload; | |
| 560 | − | |
| 561 | − /* We probably want something more informative here */ | |
| 562 | − snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); | |
| 563 | − | |
| 564 | − server = NFS_SB(sb); | |
| 448 | + if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { | |
| 449 | + dprintk("%s: bad mount version\n", __FUNCTION__); | |
| 450 | + return -EINVAL; | |
| 451 | + } | |
| 565 | 452 | |
| 566 | − sb->s_magic = NFS_SUPER_MAGIC; | |
| 453 | + switch (data->version) { | |
| 454 | + case 1: | |
| 455 | + data->namlen = 0; | |
| 456 | + case 2: | |
| 457 | + data->bsize = 0; | |
| 458 | + case 3: | |
| 459 | + if (data->flags & NFS_MOUNT_VER3) { | |
| 460 | + dprintk("%s: mount structure version %d does not support NFSv3\n", | |
| 461 | + __FUNCTION__, | |
| 462 | + data->version); | |
| 463 | + return -EINVAL; | |
| 464 | + } | |
| 465 | + data->root.size = NFS2_FHSIZE; | |
| 466 | + memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); | |
| 467 | + case 4: | |
| 468 | + if (data->flags & NFS_MOUNT_SECFLAVOUR) { | |
| 469 | + dprintk("%s: mount structure version %d does not support strong security\n", | |
| 470 | + __FUNCTION__, | |
| 471 | + data->version); | |
| 472 | + return -EINVAL; | |
| 473 | + } | |
| 474 | + case 5: | |
| 475 | + memset(data->context, 0, sizeof(data->context)); | |
| 476 | + } | |
| 567 | 477 | |
| 568 | − server->io_stats = nfs_alloc_iostats(); | |
| 569 | − if (server->io_stats == NULL) | |
| 570 | − return -ENOMEM; | |
| 478 | + /* Set the pseudoflavor */ | |
| 479 | + if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) | |
| 480 | + data->pseudoflavor = RPC_AUTH_UNIX; | |
| 571 | 481 | |
| 572 | − root_inode = nfs_get_root(sb, &server->fh, &fsinfo); | |
| 573 | − /* Did getting the root inode fail? */ | |
| 574 | − if (IS_ERR(root_inode)) { | |
| 575 | − no_root_error = PTR_ERR(root_inode); | |
| 576 | − goto out_no_root; | |
| 577 | − } | |
| 578 | − sb->s_root = d_alloc_root(root_inode); | |
| 579 | − if (!sb->s_root) { | |
| 580 | − no_root_error = -ENOMEM; | |
| 581 | − goto out_no_root; | |
| 482 | +#ifndef CONFIG_NFS_V3 | |
| 483 | + /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ | |
| 484 | + if (data->flags & NFS_MOUNT_VER3) { | |
| 485 | + dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); | |
| 486 | + return -EPROTONOSUPPORT; | |
| 582 | 487 | } |
| 583 | − sb->s_root->d_op = server->rpc_ops->dentry_ops; | |
| 584 | − | |
| 585 | − /* mount time stamp, in seconds */ | |
| 586 | − server->mount_time = jiffies; | |
| 587 | − | |
| 588 | − /* Get some general file system info */ | |
| 589 | − if (server->namelen == 0 && | |
| 590 | − server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0) | |
| 591 | − server->namelen = pathinfo.max_namelen; | |
| 592 | − /* Work out a lot of parameters */ | |
| 593 | − if (server->rsize == 0) | |
| 594 | − server->rsize = nfs_block_size(fsinfo.rtpref, NULL); | |
| 595 | − if (server->wsize == 0) | |
| 596 | − server->wsize = nfs_block_size(fsinfo.wtpref, NULL); | |
| 597 | − | |
| 598 | − if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax) | |
| 599 | − server->rsize = nfs_block_size(fsinfo.rtmax, NULL); | |
| 600 | − if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax) | |
| 601 | − server->wsize = nfs_block_size(fsinfo.wtmax, NULL); | |
| 602 | − | |
| 603 | − max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); | |
| 604 | − if (server->rsize > max_rpc_payload) | |
| 605 | − server->rsize = max_rpc_payload; | |
| 606 | − if (server->rsize > NFS_MAX_FILE_IO_SIZE) | |
| 607 | − server->rsize = NFS_MAX_FILE_IO_SIZE; | |
| 608 | − server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | |
| 609 | − | |
| 610 | − if (server->wsize > max_rpc_payload) | |
| 611 | − server->wsize = max_rpc_payload; | |
| 612 | − if (server->wsize > NFS_MAX_FILE_IO_SIZE) | |
| 613 | − server->wsize = NFS_MAX_FILE_IO_SIZE; | |
| 614 | − server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | |
| 488 | +#endif /* CONFIG_NFS_V3 */ | |
| 615 | 489 | |
| 616 | − if (sb->s_blocksize == 0) | |
| 617 | − sb->s_blocksize = nfs_block_bits(server->wsize, | |
| 618 | − &sb->s_blocksize_bits); | |
| 619 | − server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL); | |
| 620 | − | |
| 621 | − server->dtsize = nfs_block_size(fsinfo.dtpref, NULL); | |
| 622 | − if (server->dtsize > PAGE_CACHE_SIZE) | |
| 623 | − server->dtsize = PAGE_CACHE_SIZE; | |
| 624 | − if (server->dtsize > server->rsize) | |
| 625 | − server->dtsize = server->rsize; | |
| 626 | − | |
| 627 | − if (server->flags & NFS_MOUNT_NOAC) { | |
| 628 | − server->acregmin = server->acregmax = 0; | |
| 629 | − server->acdirmin = server->acdirmax = 0; | |
| 630 | − sb->s_flags |= MS_SYNCHRONOUS; | |
| 490 | + /* We now require that the mount process passes the remote address */ | |
| 491 | + if (data->addr.sin_addr.s_addr == INADDR_ANY) { | |
| 492 | + dprintk("%s: mount program didn't pass remote address!\n", | |
| 493 | + __FUNCTION__); | |
| 494 | + return -EINVAL; | |
| 631 | 495 | } |
| 632 | − server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; | |
| 633 | 496 | |
| 634 | − nfs_super_set_maxbytes(sb, fsinfo.maxfilesize); | |
| 497 | + /* Prepare the root filehandle */ | |
| 498 | + if (data->flags & NFS_MOUNT_VER3) | |
| 499 | + mntfh->size = data->root.size; | |
| 500 | + else | |
| 501 | + mntfh->size = NFS2_FHSIZE; | |
| 502 | + | |
| 503 | + if (mntfh->size > sizeof(mntfh->data)) { | |
| 504 | + dprintk("%s: invalid root filehandle\n", __FUNCTION__); | |
| 505 | + return -EINVAL; | |
| 506 | + } | |
| 635 | 507 | |
| 636 | − server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0; | |
| 637 | − server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0; | |
| 508 | + memcpy(mntfh->data, data->root.data, mntfh->size); | |
| 509 | + if (mntfh->size < sizeof(mntfh->data)) | |
| 510 | + memset(mntfh->data + mntfh->size, 0, | |
| 511 | + sizeof(mntfh->data) - mntfh->size); | |
| 638 | 512 | |
| 639 | − /* We're airborne Set socket buffersize */ | |
| 640 | − rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); | |
| 641 | 513 | return 0; |
| 642 | − /* Yargs. It didn't work out. */ | |
| 643 | −out_no_root: | |
| 644 | − dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error); | |
| 645 | − if (!IS_ERR(root_inode)) | |
| 646 | − iput(root_inode); | |
| 647 | − return no_root_error; | |
| 648 | 514 | } |
| 649 | 515 | |
| 650 | 516 | /* |
| 651 | − * Initialise the timeout values for a connection | |
| 517 | + * Initialise the common bits of the superblock | |
| 652 | 518 | */ |
| 653 | −static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans) | |
| 519 | +static inline void nfs_initialise_sb(struct super_block *sb) | |
| 654 | 520 | { |
| 655 | − to->to_initval = timeo * HZ / 10; | |
| 656 | − to->to_retries = retrans; | |
| 657 | − if (!to->to_retries) | |
| 658 | − to->to_retries = 2; | |
| 659 | − | |
| 660 | − switch (proto) { | |
| 661 | − case IPPROTO_TCP: | |
| 662 | − if (!to->to_initval) | |
| 663 | − to->to_initval = 60 * HZ; | |
| 664 | − if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | |
| 665 | − to->to_initval = NFS_MAX_TCP_TIMEOUT; | |
| 666 | − to->to_increment = to->to_initval; | |
| 667 | − to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | |
| 668 | − to->to_exponential = 0; | |
| 669 | − break; | |
| 670 | − case IPPROTO_UDP: | |
| 671 | − default: | |
| 672 | − if (!to->to_initval) | |
| 673 | − to->to_initval = 11 * HZ / 10; | |
| 674 | − if (to->to_initval > NFS_MAX_UDP_TIMEOUT) | |
| 675 | − to->to_initval = NFS_MAX_UDP_TIMEOUT; | |
| 676 | − to->to_maxval = NFS_MAX_UDP_TIMEOUT; | |
| 677 | − to->to_exponential = 1; | |
| 678 | − break; | |
| 679 | − } | |
| 680 | −} | |
| 521 | + struct nfs_server *server = NFS_SB(sb); | |
| 681 | 522 | |
| 682 | −/* | |
| 683 | − * Create an RPC client handle. | |
| 684 | − */ | |
| 685 | −static struct rpc_clnt * | |
| 686 | −nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) | |
| 687 | −{ | |
| 688 | − struct rpc_timeout timeparms; | |
| 689 | − struct rpc_xprt *xprt = NULL; | |
| 690 | − struct rpc_clnt *clnt = NULL; | |
| 691 | − int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; | |
| 692 | − | |
| 693 | − nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans); | |
| 694 | − | |
| 695 | − server->retrans_timeo = timeparms.to_initval; | |
| 696 | − server->retrans_count = timeparms.to_retries; | |
| 697 | − | |
| 698 | − /* create transport and client */ | |
| 699 | − xprt = xprt_create_proto(proto, &server->addr, &timeparms); | |
| 700 | − if (IS_ERR(xprt)) { | |
| 701 | − dprintk("%s: cannot create RPC transport. Error = %ld\n", | |
| 702 | − __FUNCTION__, PTR_ERR(xprt)); | |
| 703 | − return (struct rpc_clnt *)xprt; | |
| 704 | − } | |
| 705 | − clnt = rpc_create_client(xprt, server->hostname, &nfs_program, | |
| 706 | − server->rpc_ops->version, data->pseudoflavor); | |
| 707 | − if (IS_ERR(clnt)) { | |
| 708 | − dprintk("%s: cannot create RPC client. Error = %ld\n", | |
| 709 | − __FUNCTION__, PTR_ERR(xprt)); | |
| 710 | − goto out_fail; | |
| 711 | − } | |
| 523 | + sb->s_magic = NFS_SUPER_MAGIC; | |
| 712 | 524 | |
| 713 | − clnt->cl_intr = 1; | |
| 714 | − clnt->cl_softrtry = 1; | |
| 525 | + /* We probably want something more informative here */ | |
| 526 | + snprintf(sb->s_id, sizeof(sb->s_id), | |
| 527 | + "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); | |
| 528 | + | |
| 529 | + if (sb->s_blocksize == 0) | |
| 530 | + sb->s_blocksize = nfs_block_bits(server->wsize, | |
| 531 | + &sb->s_blocksize_bits); | |
| 715 | 532 | |
| 716 | − return clnt; | |
| 533 | + if (server->flags & NFS_MOUNT_NOAC) | |
| 534 | + sb->s_flags |= MS_SYNCHRONOUS; | |
| 717 | 535 | |
| 718 | −out_fail: | |
| 719 | − return clnt; | |
| 536 | + nfs_super_set_maxbytes(sb, server->maxfilesize); | |
| 720 | 537 | } |
| 721 | 538 | |
| 722 | 539 | /* |
| 723 | − * Clone a server record | |
| 540 | + * Finish setting up an NFS2/3 superblock | |
| 724 | 541 | */ |
| 725 | −static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_clone_mount *data) | |
| 542 | +static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data) | |
| 726 | 543 | { |
| 727 | 544 | struct nfs_server *server = NFS_SB(sb); |
| 728 | − struct nfs_server *parent = NFS_SB(data->sb); | |
| 729 | − struct inode *root_inode; | |
| 730 | − struct nfs_fsinfo fsinfo; | |
| 731 | − void *err = ERR_PTR(-ENOMEM); | |
| 732 | − | |
| 733 | − sb->s_op = data->sb->s_op; | |
| 734 | − sb->s_blocksize = data->sb->s_blocksize; | |
| 735 | − sb->s_blocksize_bits = data->sb->s_blocksize_bits; | |
| 736 | − sb->s_maxbytes = data->sb->s_maxbytes; | |
| 737 | − | |
| 738 | − server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | |
| 739 | − server->io_stats = nfs_alloc_iostats(); | |
| 740 | − if (server->io_stats == NULL) | |
| 741 | − goto out; | |
| 742 | − | |
| 743 | − server->client = rpc_clone_client(parent->client); | |
| 744 | − if (IS_ERR((err = server->client))) | |
| 745 | − goto out; | |
| 746 | − | |
| 747 | − if (!IS_ERR(parent->client_sys)) { | |
| 748 | − server->client_sys = rpc_clone_client(parent->client_sys); | |
| 749 | − if (IS_ERR((err = server->client_sys))) | |
| 750 | − goto out; | |
| 751 | − } | |
| 752 | − if (!IS_ERR(parent->client_acl)) { | |
| 753 | − server->client_acl = rpc_clone_client(parent->client_acl); | |
| 754 | − if (IS_ERR((err = server->client_acl))) | |
| 755 | − goto out; | |
| 756 | − } | |
| 757 | − root_inode = nfs_fhget(sb, data->fh, data->fattr); | |
| 758 | − if (!root_inode) | |
| 759 | − goto out; | |
| 760 | − sb->s_root = d_alloc_root(root_inode); | |
| 761 | − if (!sb->s_root) | |
| 762 | − goto out_put_root; | |
| 763 | − fsinfo.fattr = data->fattr; | |
| 764 | − if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0) | |
| 765 | − nfs_super_set_maxbytes(sb, fsinfo.maxfilesize); | |
| 766 | − sb->s_root->d_op = server->rpc_ops->dentry_ops; | |
| 767 | − sb->s_flags |= MS_ACTIVE; | |
| 768 | − return server; | |
| 769 | −out_put_root: | |
| 770 | − iput(root_inode); | |
| 771 | −out: | |
| 772 | − return err; | |
| 773 | −} | |
| 774 | 545 | |
| 775 | −/* | |
| 776 | − * Copy an existing superblock and attach revised data | |
| 777 | − */ | |
| 778 | −static int nfs_clone_generic_sb(struct nfs_clone_mount *data, | |
| 779 | − struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *), | |
| 780 | − struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *), | |
| 781 | − struct vfsmount *mnt) | |
| 782 | −{ | |
| 783 | − struct nfs_server *server; | |
| 784 | − struct nfs_server *parent = NFS_SB(data->sb); | |
| 785 | − struct super_block *sb = ERR_PTR(-EINVAL); | |
| 786 | − char *hostname; | |
| 787 | − int error = -ENOMEM; | |
| 788 | − int len; | |
| 789 | − | |
| 790 | − server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); | |
| 791 | − if (server == NULL) | |
| 792 | − goto out_err; | |
| 793 | − memcpy(server, parent, sizeof(*server)); | |
| 794 | − hostname = (data->hostname != NULL) ? data->hostname : parent->hostname; | |
| 795 | − len = strlen(hostname) + 1; | |
| 796 | − server->hostname = kmalloc(len, GFP_KERNEL); | |
| 797 | − if (server->hostname == NULL) | |
| 798 | − goto free_server; | |
| 799 | − memcpy(server->hostname, hostname, len); | |
| 800 | − error = rpciod_up(); | |
| 801 | − if (error != 0) | |
| 802 | − goto free_hostname; | |
| 803 | − | |
| 804 | − sb = fill_sb(server, data); | |
| 805 | − if (IS_ERR(sb)) { | |
| 806 | − error = PTR_ERR(sb); | |
| 807 | − goto kill_rpciod; | |
| 808 | − } | |
| 809 | − | |
| 810 | − if (sb->s_root) | |
| 811 | − goto out_rpciod_down; | |
| 546 | + sb->s_blocksize_bits = 0; | |
| 547 | + sb->s_blocksize = 0; | |
| 548 | + if (data->bsize) | |
| 549 | + sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); | |
| 812 | 550 | |
| 813 | − server = fill_server(sb, data); | |
| 814 | − if (IS_ERR(server)) { | |
| 815 | − error = PTR_ERR(server); | |
| 816 | − goto out_deactivate; | |
| 551 | + if (server->flags & NFS_MOUNT_VER3) { | |
| 552 | + /* The VFS shouldn't apply the umask to mode bits. We will do | |
| 553 | + * so ourselves when necessary. | |
| 554 | + */ | |
| 555 | + sb->s_flags |= MS_POSIXACL; | |
| 556 | + sb->s_time_gran = 1; | |
| 817 | 557 | } |
| 818 | − return simple_set_mnt(mnt, sb); | |
| 819 | −out_deactivate: | |
| 820 | − up_write(&sb->s_umount); | |
| 821 | − deactivate_super(sb); | |
| 822 | − return error; | |
| 823 | −out_rpciod_down: | |
| 824 | − rpciod_down(); | |
| 825 | − kfree(server->hostname); | |
| 826 | − kfree(server); | |
| 827 | − return simple_set_mnt(mnt, sb); | |
| 828 | −kill_rpciod: | |
| 829 | − rpciod_down(); | |
| 830 | −free_hostname: | |
| 831 | − kfree(server->hostname); | |
| 832 | −free_server: | |
| 833 | − kfree(server); | |
| 834 | −out_err: | |
| 835 | − return error; | |
| 558 | + | |
| 559 | + sb->s_op = &nfs_sops; | |
| 560 | + nfs_initialise_sb(sb); | |
| 836 | 561 | } |
| 837 | 562 | |
| 838 | 563 | /* |
| 839 | − * Set up an NFS2/3 superblock | |
| 840 | − * | |
| 841 | − * The way this works is that the mount process passes a structure | |
| 842 | − * in the data argument which contains the server's IP address | |
| 843 | − * and the root file handle obtained from the server's mount | |
| 844 | − * daemon. We stash these away in the private superblock fields. | |
| 564 | + * Finish setting up a cloned NFS2/3 superblock | |
| 845 | 565 | */ |
| 846 | −static int | |
| 847 | −nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) | |
| 566 | +static void nfs_clone_super(struct super_block *sb, | |
| 567 | + const struct super_block *old_sb) | |
| 848 | 568 | { |
| 849 | − struct nfs_server *server; | |
| 850 | − rpc_authflavor_t authflavor; | |
| 569 | + struct nfs_server *server = NFS_SB(sb); | |
| 851 | 570 | |
| 852 | − server = NFS_SB(sb); | |
| 853 | − sb->s_blocksize_bits = 0; | |
| 854 | − sb->s_blocksize = 0; | |
| 855 | − if (data->bsize) | |
| 856 | − sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); | |
| 857 | − if (data->rsize) | |
| 858 | − server->rsize = nfs_block_size(data->rsize, NULL); | |
| 859 | − if (data->wsize) | |
| 860 | − server->wsize = nfs_block_size(data->wsize, NULL); | |
| 861 | − server->flags = data->flags & NFS_MOUNT_FLAGMASK; | |
| 862 | − | |
| 863 | − server->acregmin = data->acregmin*HZ; | |
| 864 | − server->acregmax = data->acregmax*HZ; | |
| 865 | − server->acdirmin = data->acdirmin*HZ; | |
| 866 | − server->acdirmax = data->acdirmax*HZ; | |
| 867 | − | |
| 868 | − /* Start lockd here, before we might error out */ | |
| 869 | − if (!(server->flags & NFS_MOUNT_NONLM)) | |
| 870 | − lockd_up(); | |
| 871 | − | |
| 872 | − server->namelen = data->namlen; | |
| 873 | − server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL); | |
| 874 | − if (!server->hostname) | |
| 875 | − return -ENOMEM; | |
| 876 | − strcpy(server->hostname, data->hostname); | |
| 877 | − | |
| 878 | − /* Check NFS protocol revision and initialize RPC op vector | |
| 879 | − * and file handle pool. */ | |
| 880 | −#ifdef CONFIG_NFS_V3 | |
| 881 | − if (server->flags & NFS_MOUNT_VER3) { | |
| 882 | − server->rpc_ops = &nfs_v3_clientops; | |
| 883 | − server->caps |= NFS_CAP_READDIRPLUS; | |
| 884 | − } else { | |
| 885 | − server->rpc_ops = &nfs_v2_clientops; | |
| 886 | − } | |
| 887 | −#else | |
| 888 | − server->rpc_ops = &nfs_v2_clientops; | |
| 889 | −#endif | |
| 571 | + sb->s_blocksize_bits = old_sb->s_blocksize_bits; | |
| 572 | + sb->s_blocksize = old_sb->s_blocksize; | |
| 573 | + sb->s_maxbytes = old_sb->s_maxbytes; | |
| 890 | 574 | |
| 891 | − /* Fill in pseudoflavor for mount version < 5 */ | |
| 892 | − if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) | |
| 893 | − data->pseudoflavor = RPC_AUTH_UNIX; | |
| 894 | − authflavor = data->pseudoflavor; /* save for sb_init() */ | |
| 895 | − /* XXX maybe we want to add a server->pseudoflavor field */ | |
| 896 | − | |
| 897 | − /* Create RPC client handles */ | |
| 898 | − server->client = nfs_create_client(server, data); | |
| 899 | − if (IS_ERR(server->client)) | |
| 900 | − return PTR_ERR(server->client); | |
| 901 | − /* RFC 2623, sec 2.3.2 */ | |
| 902 | − if (authflavor != RPC_AUTH_UNIX) { | |
| 903 | − struct rpc_auth *auth; | |
| 904 | − | |
| 905 | − server->client_sys = rpc_clone_client(server->client); | |
| 906 | − if (IS_ERR(server->client_sys)) | |
| 907 | − return PTR_ERR(server->client_sys); | |
| 908 | − auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys); | |
| 909 | − if (IS_ERR(auth)) | |
| 910 | − return PTR_ERR(auth); | |
| 911 | − } else { | |
| 912 | − atomic_inc(&server->client->cl_count); | |
| 913 | − server->client_sys = server->client; | |
| 914 | − } | |
| 915 | 575 | if (server->flags & NFS_MOUNT_VER3) { |
| 916 | −#ifdef CONFIG_NFS_V3_ACL | |
| 917 | − if (!(server->flags & NFS_MOUNT_NOACL)) { | |
| 918 | − server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); | |
| 919 | − /* No errors! Assume that Sun nfsacls are supported */ | |
| 920 | − if (!IS_ERR(server->client_acl)) | |
| 921 | − server->caps |= NFS_CAP_ACLS; | |
| 922 | − } | |
| 923 | −#else | |
| 924 | − server->flags &= ~NFS_MOUNT_NOACL; | |
| 925 | −#endif /* CONFIG_NFS_V3_ACL */ | |
| 926 | − /* | |
| 927 | − * The VFS shouldn't apply the umask to mode bits. We will | |
| 928 | − * do so ourselves when necessary. | |
| 576 | + /* The VFS shouldn't apply the umask to mode bits. We will do | |
| 577 | + * so ourselves when necessary. | |
| 929 | 578 | */ |
| 930 | 579 | sb->s_flags |= MS_POSIXACL; |
| 931 | − if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) | |
| 932 | − server->namelen = NFS3_MAXNAMLEN; | |
| 933 | 580 | sb->s_time_gran = 1; |
| 934 | − } else { | |
| 935 | − if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) | |
| 936 | − server->namelen = NFS2_MAXNAMLEN; | |
| 937 | 581 | } |
| 938 | 582 | |
| 939 | − sb->s_op = &nfs_sops; | |
| 940 | − return nfs_sb_init(sb, authflavor); | |
| 583 | + sb->s_op = old_sb->s_op; | |
| 584 | + nfs_initialise_sb(sb); | |
| 941 | 585 | } |
| 942 | 586 | |
| 943 | −static int nfs_set_super(struct super_block *s, void *data) | |
| 587 | +static int nfs_set_super(struct super_block *s, void *_server) | |
| 944 | 588 | { |
| 945 | − s->s_fs_info = data; | |
| 946 | − return set_anon_super(s, data); | |
| 589 | + struct nfs_server *server = _server; | |
| 590 | + int ret; | |
| 591 | + | |
| 592 | + s->s_fs_info = server; | |
| 593 | + ret = set_anon_super(s, server); | |
| 594 | + if (ret == 0) | |
| 595 | + server->s_dev = s->s_dev; | |
| 596 | + return ret; | |
| 947 | 597 | } |
| 948 | 598 | |
| 949 | 599 | static int nfs_compare_super(struct super_block *sb, void *data) |
| 950 | 600 | { |
| 951 | − struct nfs_server *server = data; | |
| 952 | − struct nfs_server *old = NFS_SB(sb); | |
| 601 | + struct nfs_server *server = data, *old = NFS_SB(sb); | |
| 953 | 602 | |
| 954 | − if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr) | |
| 603 | + if (old->nfs_client != server->nfs_client) | |
| 955 | 604 | return 0; |
| 956 | − if (old->addr.sin_port != server->addr.sin_port) | |
| 605 | + if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0) | |
| 957 | 606 | return 0; |
| 958 | − return !nfs_compare_fh(&old->fh, &server->fh); | |
| 607 | + return 1; | |
| 959 | 608 | } |
| 960 | 609 | |
| 961 | 610 | static int nfs_get_sb(struct file_system_type *fs_type, |
| 962 | 611 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
| 963 | 612 | { |
| 964 | − int error; | |
| 965 | 613 | struct nfs_server *server = NULL; |
| 966 | 614 | struct super_block *s; |
| 967 | − struct nfs_fh *root; | |
| 615 | + struct nfs_fh mntfh; | |
| 968 | 616 | struct nfs_mount_data *data = raw_data; |
| 617 | + struct dentry *mntroot; | |
| 618 | + int error; | |
| 969 | 619 | |
| 970 | − error = -EINVAL; | |
| 971 | − if (data == NULL) { | |
| 972 | − dprintk("%s: missing data argument\n", __FUNCTION__); | |
| 973 | − goto out_err_noserver; | |
| 974 | − } | |
| 975 | − if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { | |
| 976 | − dprintk("%s: bad mount version\n", __FUNCTION__); | |
| 977 | − goto out_err_noserver; | |
| 978 | − } | |
| 979 | − switch (data->version) { | |
| 980 | − case 1: | |
| 981 | − data->namlen = 0; | |
| 982 | − case 2: | |
| 983 | − data->bsize = 0; | |
| 984 | − case 3: | |
| 985 | − if (data->flags & NFS_MOUNT_VER3) { | |
| 986 | − dprintk("%s: mount structure version %d does not support NFSv3\n", | |
| 987 | − __FUNCTION__, | |
| 988 | − data->version); | |
| 989 | − goto out_err_noserver; | |
| 990 | − } | |
| 991 | − data->root.size = NFS2_FHSIZE; | |
| 992 | − memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); | |
| 993 | − case 4: | |
| 994 | − if (data->flags & NFS_MOUNT_SECFLAVOUR) { | |
| 995 | − dprintk("%s: mount structure version %d does not support strong security\n", | |
| 996 | − __FUNCTION__, | |
| 997 | − data->version); | |
| 998 | − goto out_err_noserver; | |
| 999 | − } | |
| 1000 | − case 5: | |
| 1001 | − memset(data->context, 0, sizeof(data->context)); | |
| 1002 | − } | |
| 1003 | −#ifndef CONFIG_NFS_V3 | |
| 1004 | − /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ | |
| 1005 | − error = -EPROTONOSUPPORT; | |
| 1006 | − if (data->flags & NFS_MOUNT_VER3) { | |
| 1007 | − dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); | |
| 1008 | − goto out_err_noserver; | |
| 1009 | − } | |
| 1010 | −#endif /* CONFIG_NFS_V3 */ | |
| 620 | + /* Validate the mount data */ | |
| 621 | + error = nfs_validate_mount_data(data, &mntfh); | |
| 622 | + if (error < 0) | |
| 623 | + return error; | |
| 1011 | 624 | |
| 1012 | − error = -ENOMEM; | |
| 1013 | − server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); | |
| 1014 | − if (!server) | |
| 625 | + /* Get a volume representation */ | |
| 626 | + server = nfs_create_server(data, &mntfh); | |
| 627 | + if (IS_ERR(server)) { | |
| 628 | + error = PTR_ERR(server); | |
| 1015 | 629 | goto out_err_noserver; |
| 1016 | − /* Zero out the NFS state stuff */ | |
| 1017 | − init_nfsv4_state(server); | |
| 1018 | − server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | |
| 1019 | − | |
| 1020 | − root = &server->fh; | |
| 1021 | − if (data->flags & NFS_MOUNT_VER3) | |
| 1022 | − root->size = data->root.size; | |
| 1023 | − else | |
| 1024 | − root->size = NFS2_FHSIZE; | |
| 1025 | − error = -EINVAL; | |
| 1026 | − if (root->size > sizeof(root->data)) { | |
| 1027 | − dprintk("%s: invalid root filehandle\n", __FUNCTION__); | |
| 1028 | − goto out_err; | |
| 1029 | − } | |
| 1030 | − memcpy(root->data, data->root.data, root->size); | |
| 1031 | − | |
| 1032 | − /* We now require that the mount process passes the remote address */ | |
| 1033 | − memcpy(&server->addr, &data->addr, sizeof(server->addr)); | |
| 1034 | − if (server->addr.sin_addr.s_addr == INADDR_ANY) { | |
| 1035 | − dprintk("%s: mount program didn't pass remote address!\n", | |
| 1036 | − __FUNCTION__); | |
| 1037 | − goto out_err; | |
| 1038 | − } | |
| 1039 | − | |
| 1040 | − /* Fire up rpciod if not yet running */ | |
| 1041 | − error = rpciod_up(); | |
| 1042 | − if (error < 0) { | |
| 1043 | − dprintk("%s: couldn't start rpciod! Error = %d\n", | |
| 1044 | − __FUNCTION__, error); | |
| 1045 | − goto out_err; | |
| 1046 | 630 | } |
| 1047 | 631 | |
| 632 | + /* Get a superblock - note that we may end up sharing one that already exists */ | |
| 1048 | 633 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); |
| 1049 | 634 | if (IS_ERR(s)) { |
| 1050 | 635 | error = PTR_ERR(s); |
| 1051 | − goto out_err_rpciod; | |
| 636 | + goto out_err_nosb; | |
| 1052 | 637 | } |
| 1053 | 638 | |
| 1054 | − if (s->s_root) | |
| 1055 | − goto out_rpciod_down; | |
| 639 | + if (s->s_fs_info != server) { | |
| 640 | + nfs_free_server(server); | |
| 641 | + server = NULL; | |
| 642 | + } | |
| 1056 | 643 | |
| 1057 | − s->s_flags = flags; | |
| 644 | + if (!s->s_root) { | |
| 645 | + /* initial superblock/root creation */ | |
| 646 | + s->s_flags = flags; | |
| 647 | + nfs_fill_super(s, data); | |
| 648 | + } | |
| 1058 | 649 | |
| 1059 | − error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0); | |
| 1060 | − if (error) { | |
| 1061 | − up_write(&s->s_umount); | |
| 1062 | − deactivate_super(s); | |
| 1063 | − return error; | |
| 650 | + mntroot = nfs_get_root(s, &mntfh); | |
| 651 | + if (IS_ERR(mntroot)) { | |
| 652 | + error = PTR_ERR(mntroot); | |
| 653 | + goto error_splat_super; | |
| 1064 | 654 | } |
| 1065 | − s->s_flags |= MS_ACTIVE; | |
| 1066 | − return simple_set_mnt(mnt, s); | |
| 1067 | 655 | |
| 1068 | −out_rpciod_down: | |
| 1069 | − rpciod_down(); | |
| 1070 | − kfree(server); | |
| 1071 | − return simple_set_mnt(mnt, s); | |
| 656 | + s->s_flags |= MS_ACTIVE; | |
| 657 | + mnt->mnt_sb = s; | |
| 658 | + mnt->mnt_root = mntroot; | |
| 659 | + return 0; | |
| 1072 | 660 | |
| 1073 | −out_err_rpciod: | |
| 1074 | − rpciod_down(); | |
| 1075 | −out_err: | |
| 1076 | − kfree(server); | |
| 661 | +out_err_nosb: | |
| 662 | + nfs_free_server(server); | |
| 1077 | 663 | out_err_noserver: |
| 1078 | 664 | return error; |
| 665 | + | |
| 666 | +error_splat_super: | |
| 667 | + up_write(&s->s_umount); | |
| 668 | + deactivate_super(s); | |
| 669 | + return error; | |
| 1079 | 670 | } |
| 1080 | 671 | |
| 672 | +/* | |
| 673 | + * Destroy an NFS2/3 superblock | |
| 674 | + */ | |
| 1081 | 675 | static void nfs_kill_super(struct super_block *s) |
| 1082 | 676 | { |
| 1083 | 677 | struct nfs_server *server = NFS_SB(s); |
| 1084 | 678 | |
| 1085 | 679 | kill_anon_super(s); |
| 1086 | − | |
| 1087 | − if (!IS_ERR(server->client)) | |
| 1088 | − rpc_shutdown_client(server->client); | |
| 1089 | − if (!IS_ERR(server->client_sys)) | |
| 1090 | − rpc_shutdown_client(server->client_sys); | |
| 1091 | − if (!IS_ERR(server->client_acl)) | |
| 1092 | − rpc_shutdown_client(server->client_acl); | |
| 1093 | − | |
| 1094 | − if (!(server->flags & NFS_MOUNT_NONLM)) | |
| 1095 | − lockd_down(); /* release rpc.lockd */ | |
| 1096 | − | |
| 1097 | − rpciod_down(); /* release rpciod */ | |
| 1098 | − | |
| 1099 | − nfs_free_iostats(server->io_stats); | |
| 1100 | − kfree(server->hostname); | |
| 1101 | − kfree(server); | |
| 1102 | − nfs_release_automount_timer(); | |
| 1103 | −} | |
| 1104 | − | |
| 1105 | −static struct super_block *nfs_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data) | |
| 1106 | −{ | |
| 1107 | − struct super_block *sb; | |
| 1108 | − | |
| 1109 | − server->fsid = data->fattr->fsid; | |
| 1110 | − nfs_copy_fh(&server->fh, data->fh); | |
| 1111 | − sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); | |
| 1112 | − if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM)) | |
| 1113 | − lockd_up(); | |
| 1114 | − return sb; | |
| 680 | + nfs_free_server(server); | |
| 1115 | 681 | } |
| 1116 | 682 | |
| 1117 | −static int nfs_clone_nfs_sb(struct file_system_type *fs_type, | |
| 1118 | − int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | |
| 683 | +/* | |
| 684 | + * Clone an NFS2/3 server record on xdev traversal (FSID-change) | |
| 685 | + */ | |
| 686 | +static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | |
| 687 | + const char *dev_name, void *raw_data, | |
| 688 | + struct vfsmount *mnt) | |
| 1119 | 689 | { |
| 1120 | 690 | struct nfs_clone_mount *data = raw_data; |
| 1121 | − return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server, mnt); | |
| 1122 | −} | |
| 691 | + struct super_block *s; | |
| 692 | + struct nfs_server *server; | |
| 693 | + struct dentry *mntroot; | |
| 694 | + int error; | |
| 1123 | 695 | |
| 1124 | −#ifdef CONFIG_NFS_V4 | |
| 1125 | −static struct rpc_clnt *nfs4_create_client(struct nfs_server *server, | |
| 1126 | − struct rpc_timeout *timeparms, int proto, rpc_authflavor_t flavor) | |
| 1127 | −{ | |
| 1128 | − struct nfs4_client *clp; | |
| 1129 | − struct rpc_xprt *xprt = NULL; | |
| 1130 | − struct rpc_clnt *clnt = NULL; | |
| 1131 | − int err = -EIO; | |
| 1132 | − | |
| 1133 | − clp = nfs4_get_client(&server->addr.sin_addr); | |
| 1134 | − if (!clp) { | |
| 1135 | − dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__); | |
| 1136 | − return ERR_PTR(err); | |
| 1137 | − } | |
| 696 | + dprintk("--> nfs_xdev_get_sb()\n"); | |
| 1138 | 697 | |
| 1139 | − /* Now create transport and client */ | |
| 1140 | − down_write(&clp->cl_sem); | |
| 1141 | − if (IS_ERR(clp->cl_rpcclient)) { | |
| 1142 | − xprt = xprt_create_proto(proto, &server->addr, timeparms); | |
| 1143 | − if (IS_ERR(xprt)) { | |
| 1144 | − up_write(&clp->cl_sem); | |
| 1145 | − err = PTR_ERR(xprt); | |
| 1146 | − dprintk("%s: cannot create RPC transport. Error = %d\n", | |
| 1147 | − __FUNCTION__, err); | |
| 1148 | − goto out_fail; | |
| 1149 | − } | |
| 1150 | − /* Bind to a reserved port! */ | |
| 1151 | − xprt->resvport = 1; | |
| 1152 | − clnt = rpc_create_client(xprt, server->hostname, &nfs_program, | |
| 1153 | − server->rpc_ops->version, flavor); | |
| 1154 | − if (IS_ERR(clnt)) { | |
| 1155 | − up_write(&clp->cl_sem); | |
| 1156 | − err = PTR_ERR(clnt); | |
| 1157 | − dprintk("%s: cannot create RPC client. Error = %d\n", | |
| 1158 | − __FUNCTION__, err); | |
| 1159 | − goto out_fail; | |
| 1160 | − } | |
| 1161 | − clnt->cl_intr = 1; | |
| 1162 | − clnt->cl_softrtry = 1; | |
| 1163 | − clp->cl_rpcclient = clnt; | |
| 1164 | − memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr)); | |
| 1165 | − nfs_idmap_new(clp); | |
| 1166 | − } | |
| 1167 | − list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); | |
| 1168 | − clnt = rpc_clone_client(clp->cl_rpcclient); | |
| 1169 | − if (!IS_ERR(clnt)) | |
| 1170 | − server->nfs4_state = clp; | |
| 1171 | − up_write(&clp->cl_sem); | |
| 1172 | − clp = NULL; | |
| 1173 | − | |
| 1174 | − if (IS_ERR(clnt)) { | |
| 1175 | − dprintk("%s: cannot create RPC client. Error = %d\n", | |
| 1176 | − __FUNCTION__, err); | |
| 1177 | − return clnt; | |
| 698 | + /* create a new volume representation */ | |
| 699 | + server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); | |
| 700 | + if (IS_ERR(server)) { | |
| 701 | + error = PTR_ERR(server); | |
| 702 | + goto out_err_noserver; | |
| 1178 | 703 | } |
| 1179 | 704 | |
| 1180 | − if (server->nfs4_state->cl_idmap == NULL) { | |
| 1181 | − dprintk("%s: failed to create idmapper.\n", __FUNCTION__); | |
| 1182 | − return ERR_PTR(-ENOMEM); | |
| 705 | + /* Get a superblock - note that we may end up sharing one that already exists */ | |
| 706 | + s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); | |
| 707 | + if (IS_ERR(s)) { | |
| 708 | + error = PTR_ERR(s); | |
| 709 | + goto out_err_nosb; | |
| 1183 | 710 | } |
| 1184 | 711 | |
| 1185 | − if (clnt->cl_auth->au_flavor != flavor) { | |
| 1186 | − struct rpc_auth *auth; | |
| 1187 | − | |
| 1188 | − auth = rpcauth_create(flavor, clnt); | |
| 1189 | − if (IS_ERR(auth)) { | |
| 1190 | − dprintk("%s: couldn't create credcache!\n", __FUNCTION__); | |
| 1191 | − return (struct rpc_clnt *)auth; | |
| 1192 | − } | |
| 712 | + if (s->s_fs_info != server) { | |
| 713 | + nfs_free_server(server); | |
| 714 | + server = NULL; | |
| 1193 | 715 | } |
| 1194 | − return clnt; | |
| 1195 | − | |
| 1196 | − out_fail: | |
| 1197 | − if (clp) | |
| 1198 | − nfs4_put_client(clp); | |
| 1199 | − return ERR_PTR(err); | |
| 1200 | −} | |
| 1201 | − | |
| 1202 | −/* | |
| 1203 | − * Set up an NFS4 superblock | |
| 1204 | − */ | |
| 1205 | −static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent) | |
| 1206 | −{ | |
| 1207 | − struct nfs_server *server; | |
| 1208 | − struct rpc_timeout timeparms; | |
| 1209 | − rpc_authflavor_t authflavour; | |
| 1210 | − int err = -EIO; | |
| 1211 | 716 | |
| 1212 | − sb->s_blocksize_bits = 0; | |
| 1213 | − sb->s_blocksize = 0; | |
| 1214 | − server = NFS_SB(sb); | |
| 1215 | − if (data->rsize != 0) | |
| 1216 | − server->rsize = nfs_block_size(data->rsize, NULL); | |
| 1217 | − if (data->wsize != 0) | |
| 1218 | − server->wsize = nfs_block_size(data->wsize, NULL); | |
| 1219 | − server->flags = data->flags & NFS_MOUNT_FLAGMASK; | |
| 1220 | − server->caps = NFS_CAP_ATOMIC_OPEN; | |
| 717 | + if (!s->s_root) { | |
| 718 | + /* initial superblock/root creation */ | |
| 719 | + s->s_flags = flags; | |
| 720 | + nfs_clone_super(s, data->sb); | |
| 721 | + } | |
| 1221 | 722 | |
| 1222 | − server->acregmin = data->acregmin*HZ; | |
| 1223 | − server->acregmax = data->acregmax*HZ; | |
| 1224 | − server->acdirmin = data->acdirmin*HZ; | |
| 1225 | − server->acdirmax = data->acdirmax*HZ; | |
| 723 | + mntroot = nfs_get_root(s, data->fh); | |
| 724 | + if (IS_ERR(mntroot)) { | |
| 725 | + error = PTR_ERR(mntroot); | |
| 726 | + goto error_splat_super; | |
| 727 | + } | |
| 1226 | 728 | |
| 1227 | − server->rpc_ops = &nfs_v4_clientops; | |
| 729 | + s->s_flags |= MS_ACTIVE; | |
| 730 | + mnt->mnt_sb = s; | |
| 731 | + mnt->mnt_root = mntroot; | |
| 1228 | 732 | |
| 1229 | − nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans); | |
| 733 | + dprintk("<-- nfs_xdev_get_sb() = 0\n"); | |
| 734 | + return 0; | |
| 1230 | 735 | |
| 1231 | − server->retrans_timeo = timeparms.to_initval; | |
| 1232 | − server->retrans_count = timeparms.to_retries; | |
| 736 | +out_err_nosb: | |
| 737 | + nfs_free_server(server); | |
| 738 | +out_err_noserver: | |
| 739 | + dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error); | |
| 740 | + return error; | |
| 1233 | 741 | |
| 1234 | − /* Now create transport and client */ | |
| 1235 | − authflavour = RPC_AUTH_UNIX; | |
| 1236 | − if (data->auth_flavourlen != 0) { | |
| 1237 | − if (data->auth_flavourlen != 1) { | |
| 1238 | − dprintk("%s: Invalid number of RPC auth flavours %d.\n", | |
| 1239 | − __FUNCTION__, data->auth_flavourlen); | |
| 1240 | − err = -EINVAL; | |
| 1241 | − goto out_fail; | |
| 1242 | − } | |
| 1243 | − if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { | |
| 1244 | − err = -EFAULT; | |
| 1245 | − goto out_fail; | |
| 1246 | − } | |
| 1247 | − } | |
| 742 | +error_splat_super: | |
| 743 | + up_write(&s->s_umount); | |
| 744 | + deactivate_super(s); | |
| 745 | + dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); | |
| 746 | + return error; | |
| 747 | +} | |
| 1248 | 748 | |
| 1249 | − server->client = nfs4_create_client(server, &timeparms, data->proto, authflavour); | |
| 1250 | − if (IS_ERR(server->client)) { | |
| 1251 | − err = PTR_ERR(server->client); | |
| 1252 | − dprintk("%s: cannot create RPC client. Error = %d\n", | |
| 1253 | − __FUNCTION__, err); | |
| 1254 | − goto out_fail; | |
| 1255 | − } | |
| 749 | +#ifdef CONFIG_NFS_V4 | |
| 1256 | 750 | |
| 751 | +/* | |
| 752 | + * Finish setting up a cloned NFS4 superblock | |
| 753 | + */ | |
| 754 | +static void nfs4_clone_super(struct super_block *sb, | |
| 755 | + const struct super_block *old_sb) | |
| 756 | +{ | |
| 757 | + sb->s_blocksize_bits = old_sb->s_blocksize_bits; | |
| 758 | + sb->s_blocksize = old_sb->s_blocksize; | |
| 759 | + sb->s_maxbytes = old_sb->s_maxbytes; | |
| 1257 | 760 | sb->s_time_gran = 1; |
| 1258 | − | |
| 1259 | − sb->s_op = &nfs4_sops; | |
| 1260 | − err = nfs_sb_init(sb, authflavour); | |
| 1261 | − | |
| 1262 | − out_fail: | |
| 1263 | − return err; | |
| 761 | + sb->s_op = old_sb->s_op; | |
| 762 | + nfs_initialise_sb(sb); | |
| 1264 | 763 | } |
| 1265 | 764 | |
| 1266 | −static int nfs4_compare_super(struct super_block *sb, void *data) | |
| 765 | +/* | |
| 766 | + * Set up an NFS4 superblock | |
| 767 | + */ | |
| 768 | +static void nfs4_fill_super(struct super_block *sb) | |
| 1267 | 769 | { |
| 1268 | − struct nfs_server *server = data; | |
| 1269 | − struct nfs_server *old = NFS_SB(sb); | |
| 1270 | − | |
| 1271 | − if (strcmp(server->hostname, old->hostname) != 0) | |
| 1272 | − return 0; | |
| 1273 | − if (strcmp(server->mnt_path, old->mnt_path) != 0) | |
| 1274 | − return 0; | |
| 1275 | − return 1; | |
| 770 | + sb->s_time_gran = 1; | |
| 771 | + sb->s_op = &nfs4_sops; | |
| 772 | + nfs_initialise_sb(sb); | |
| 1276 | 773 | } |
| 1277 | 774 | |
| 1278 | −static void * | |
| 1279 | −nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) | |
| 775 | +static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) | |
| 1280 | 776 | { |
| 1281 | 777 | void *p = NULL; |
| 1282 | 778 | |
| @@ -1297,14 +793,22 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) · 14 unmodified lines | ||
| 1297 | 793 | return dst; |
| 1298 | 794 | } |
| 1299 | 795 | |
| 796 | +/* | |
| 797 | + * Get the superblock for an NFS4 mountpoint | |
| 798 | + */ | |
| 1300 | 799 | static int nfs4_get_sb(struct file_system_type *fs_type, |
| 1301 | 800 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
| 1302 | 801 | { |
| 1303 | − int error; | |
| 1304 | − struct nfs_server *server; | |
| 1305 | − struct super_block *s; | |
| 1306 | 802 | struct nfs4_mount_data *data = raw_data; |
| 803 | + struct super_block *s; | |
| 804 | + struct nfs_server *server; | |
| 805 | + struct sockaddr_in addr; | |
| 806 | + rpc_authflavor_t authflavour; | |
| 807 | + struct nfs_fh mntfh; | |
| 808 | + struct dentry *mntroot; | |
| 809 | + char *mntpath = NULL, *hostname = NULL, ip_addr[16]; | |
| 1307 | 810 | void *p; |
| 811 | + int error; | |
| 1308 | 812 | |
| 1309 | 813 | if (data == NULL) { |
| 1310 | 814 | dprintk("%s: missing data argument\n", __FUNCTION__); |
| @@ -1315,84 +819,112 @@ static int nfs4_get_sb(struct file_system_type *fs_type, · 4 unmodified lines | ||
| 1315 | 819 | return -EINVAL; |
| 1316 | 820 | } |
| 1317 | 821 | |
| 1318 | − server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); | |
| 1319 | − if (!server) | |
| 1320 | − return -ENOMEM; | |
| 1321 | − /* Zero out the NFS state stuff */ | |
| 1322 | − init_nfsv4_state(server); | |
| 1323 | − server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | |
| 822 | + /* We now require that the mount process passes the remote address */ | |
| 823 | + if (data->host_addrlen != sizeof(addr)) | |
| 824 | + return -EINVAL; | |
| 825 | + | |
| 826 | + if (copy_from_user(&addr, data->host_addr, sizeof(addr))) | |
| 827 | + return -EFAULT; | |
| 828 | + | |
| 829 | + if (addr.sin_family != AF_INET || | |
| 830 | + addr.sin_addr.s_addr == INADDR_ANY | |
| 831 | + ) { | |
| 832 | + dprintk("%s: mount program didn't pass remote IP address!\n", | |
| 833 | + __FUNCTION__); | |
| 834 | + return -EINVAL; | |
| 835 | + } | |
| 836 | + /* RFC3530: The default port for NFS is 2049 */ | |
| 837 | + if (addr.sin_port == 0) | |
| 838 | + addr.sin_port = NFS_PORT; | |
| 839 | + | |
| 840 | + /* Grab the authentication type */ | |
| 841 | + authflavour = RPC_AUTH_UNIX; | |
| 842 | + if (data->auth_flavourlen != 0) { | |
| 843 | + if (data->auth_flavourlen != 1) { | |
| 844 | + dprintk("%s: Invalid number of RPC auth flavours %d.\n", | |
| 845 | + __FUNCTION__, data->auth_flavourlen); | |
| 846 | + error = -EINVAL; | |
| 847 | + goto out_err_noserver; | |
| 848 | + } | |
| 849 | + | |
| 850 | + if (copy_from_user(&authflavour, data->auth_flavours, | |
| 851 | + sizeof(authflavour))) { | |
| 852 | + error = -EFAULT; | |
| 853 | + goto out_err_noserver; | |
| 854 | + } | |
| 855 | + } | |
| 1324 | 856 | |
| 1325 | 857 | p = nfs_copy_user_string(NULL, &data->hostname, 256); |
| 1326 | 858 | if (IS_ERR(p)) |
| 1327 | 859 | goto out_err; |
| 1328 | − server->hostname = p; | |
| 860 | + hostname = p; | |
| 1329 | 861 | |
| 1330 | 862 | p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); |
| 1331 | 863 | if (IS_ERR(p)) |
| 1332 | 864 | goto out_err; |
| 1333 | − server->mnt_path = p; | |
| 865 | + mntpath = p; | |
| 866 | + | |
| 867 | + dprintk("MNTPATH: %s\n", mntpath); | |
| 1334 | 868 | |
| 1335 | − p = nfs_copy_user_string(server->ip_addr, &data->client_addr, | |
| 1336 | − sizeof(server->ip_addr) - 1); | |
| 869 | + p = nfs_copy_user_string(ip_addr, &data->client_addr, | |
| 870 | + sizeof(ip_addr) - 1); | |
| 1337 | 871 | if (IS_ERR(p)) |
| 1338 | 872 | goto out_err; |
| 1339 | 873 | |
| 1340 | − /* We now require that the mount process passes the remote address */ | |
| 1341 | − if (data->host_addrlen != sizeof(server->addr)) { | |
| 1342 | − error = -EINVAL; | |
| 1343 | − goto out_free; | |
| 1344 | − } | |
| 1345 | − if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { | |
| 1346 | − error = -EFAULT; | |
| 1347 | − goto out_free; | |
| 1348 | − } | |
| 1349 | − if (server->addr.sin_family != AF_INET || | |
| 1350 | − server->addr.sin_addr.s_addr == INADDR_ANY) { | |
| 1351 | − dprintk("%s: mount program didn't pass remote IP address!\n", | |
| 1352 | − __FUNCTION__); | |
| 1353 | − error = -EINVAL; | |
| 1354 | − goto out_free; | |
| 1355 | − } | |
| 1356 | − | |
| 1357 | − /* Fire up rpciod if not yet running */ | |
| 1358 | − error = rpciod_up(); | |
| 1359 | − if (error < 0) { | |
| 1360 | − dprintk("%s: couldn't start rpciod! Error = %d\n", | |
| 1361 | − __FUNCTION__, error); | |
| 1362 | − goto out_free; | |
| 874 | + /* Get a volume representation */ | |
| 875 | + server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, | |
| 876 | + authflavour, &mntfh); | |
| 877 | + if (IS_ERR(server)) { | |
| 878 | + error = PTR_ERR(server); | |
| 879 | + goto out_err_noserver; | |
| 1363 | 880 | } |
| 1364 | 881 | |
| 1365 | − s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); | |
| 1366 | − | |
| 882 | + /* Get a superblock - note that we may end up sharing one that already exists */ | |
| 883 | + s = sget(fs_type, nfs_compare_super, nfs_set_super, server); | |
| 1367 | 884 | if (IS_ERR(s)) { |
| 1368 | 885 | error = PTR_ERR(s); |
| 1369 | 886 | goto out_free; |
| 1370 | 887 | } |
| 1371 | 888 | |
| 1372 | − if (s->s_root) { | |
| 1373 | − kfree(server->mnt_path); | |
| 1374 | − kfree(server->hostname); | |
| 1375 | − kfree(server); | |
| 1376 | − return simple_set_mnt(mnt, s); | |
| 889 | + if (s->s_fs_info != server) { | |
| 890 | + nfs_free_server(server); | |
| 891 | + server = NULL; | |
| 1377 | 892 | } |
| 1378 | 893 | |
| 1379 | − s->s_flags = flags; | |
| 894 | + if (!s->s_root) { | |
| 895 | + /* initial superblock/root creation */ | |
| 896 | + s->s_flags = flags; | |
| 897 | + nfs4_fill_super(s); | |
| 898 | + } | |
| 1380 | 899 | |
| 1381 | − error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0); | |
| 1382 | − if (error) { | |
| 1383 | − up_write(&s->s_umount); | |
| 1384 | − deactivate_super(s); | |
| 1385 | − return error; | |
| 900 | + mntroot = nfs4_get_root(s, &mntfh); | |
| 901 | + if (IS_ERR(mntroot)) { | |
| 902 | + error = PTR_ERR(mntroot); | |
| 903 | + goto error_splat_super; | |
| 1386 | 904 | } |
| 905 | + | |
| 1387 | 906 | s->s_flags |= MS_ACTIVE; |
| 1388 | − return simple_set_mnt(mnt, s); | |
| 907 | + mnt->mnt_sb = s; | |
| 908 | + mnt->mnt_root = mntroot; | |
| 909 | + kfree(mntpath); | |
| 910 | + kfree(hostname); | |
| 911 | + return 0; | |
| 912 | + | |
| 1389 | 913 | out_err: |
| 1390 | 914 | error = PTR_ERR(p); |
| 915 | + goto out_err_noserver; | |
| 916 | + | |
| 1391 | 917 | out_free: |
| 1392 | − kfree(server->mnt_path); | |
| 1393 | − kfree(server->hostname); | |
| 1394 | − kfree(server); | |
| 918 | + nfs_free_server(server); | |
| 919 | +out_err_noserver: | |
| 920 | + kfree(mntpath); | |
| 921 | + kfree(hostname); | |
| 1395 | 922 | return error; |
| 923 | + | |
| 924 | +error_splat_super: | |
| 925 | + up_write(&s->s_umount); | |
| 926 | + deactivate_super(s); | |
| 927 | + goto out_err_noserver; | |
| 1396 | 928 | } |
| 1397 | 929 | |
| 1398 | 930 | static void nfs4_kill_super(struct super_block *sb) |
| @@ -1403,135 +935,140 @@ static void nfs4_kill_super(struct super_block *sb) · 4 unmodified lines | ||
| 1403 | 935 | kill_anon_super(sb); |
| 1404 | 936 | |
| 1405 | 937 | nfs4_renewd_prepare_shutdown(server); |
| 938 | + nfs_free_server(server); | |
| 939 | +} | |
| 940 | + | |
| 941 | +/* | |
| 942 | + * Clone an NFS4 server record on xdev traversal (FSID-change) | |
| 943 | + */ | |
| 944 | +static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, | |
| 945 | + const char *dev_name, void *raw_data, | |
| 946 | + struct vfsmount *mnt) | |
| 947 | +{ | |
| 948 | + struct nfs_clone_mount *data = raw_data; | |
| 949 | + struct super_block *s; | |
| 950 | + struct nfs_server *server; | |
| 951 | + struct dentry *mntroot; | |
| 952 | + int error; | |
| 953 | + | |
| 954 | + dprintk("--> nfs4_xdev_get_sb()\n"); | |
| 955 | + | |
| 956 | + /* create a new volume representation */ | |
| 957 | + server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); | |
| 958 | + if (IS_ERR(server)) { | |
| 959 | + error = PTR_ERR(server); | |
| 960 | + goto out_err_noserver; | |
| 961 | + } | |
| 962 | + | |
| 963 | + /* Get a superblock - note that we may end up sharing one that already exists */ | |
| 964 | + s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); | |
| 965 | + if (IS_ERR(s)) { | |
| 966 | + error = PTR_ERR(s); | |
| 967 | + goto out_err_nosb; | |
| 968 | + } | |
| 1406 | 969 | |
| 1407 | − if (server->client != NULL && !IS_ERR(server->client)) | |
| 1408 | − rpc_shutdown_client(server->client); | |
| 970 | + if (s->s_fs_info != server) { | |
| 971 | + nfs_free_server(server); | |
| 972 | + server = NULL; | |
| 973 | + } | |
| 1409 | 974 | |
| 1410 | − destroy_nfsv4_state(server); | |
| 975 | + if (!s->s_root) { | |
| 976 | + /* initial superblock/root creation */ | |
| 977 | + s->s_flags = flags; | |
| 978 | + nfs4_clone_super(s, data->sb); | |
| 979 | + } | |
| 980 | + | |
| 981 | + mntroot = nfs4_get_root(s, data->fh); | |
| 982 | + if (IS_ERR(mntroot)) { | |
| 983 | + error = PTR_ERR(mntroot); | |
| 984 | + goto error_splat_super; | |
| 985 | + } | |
| 1411 | 986 | |
| 1412 | − rpciod_down(); | |
| 987 | + s->s_flags |= MS_ACTIVE; | |
| 988 | + mnt->mnt_sb = s; | |
| 989 | + mnt->mnt_root = mntroot; | |
| 990 | + | |
| 991 | + dprintk("<-- nfs4_xdev_get_sb() = 0\n"); | |
| 992 | + return 0; | |
| 993 | + | |
| 994 | +out_err_nosb: | |
| 995 | + nfs_free_server(server); | |
| 996 | +out_err_noserver: | |
| 997 | + dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error); | |
| 998 | + return error; | |
| 1413 | 999 | |
| 1414 | − nfs_free_iostats(server->io_stats); | |
| 1415 | − kfree(server->hostname); | |
| 1416 | − kfree(server); | |
| 1417 | − nfs_release_automount_timer(); | |
| 1000 | +error_splat_super: | |
| 1001 | + up_write(&s->s_umount); | |
| 1002 | + deactivate_super(s); | |
| 1003 | + dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); | |
| 1004 | + return error; | |
| 1418 | 1005 | } |
| 1419 | 1006 | |
| 1420 | 1007 | /* |
| 1421 | − * Constructs the SERVER-side path | |
| 1008 | + * Create an NFS4 server record on referral traversal | |
| 1422 | 1009 | */ |
| 1423 | −static inline char *nfs4_dup_path(const struct dentry *dentry) | |
| 1010 | +static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags, | |
| 1011 | + const char *dev_name, void *raw_data, | |
| 1012 | + struct vfsmount *mnt) | |
| 1424 | 1013 | { |
| 1425 | − char *page = (char *) __get_free_page(GFP_USER); | |
| 1426 | − char *path; | |
| 1014 | + struct nfs_clone_mount *data = raw_data; | |
| 1015 | + struct super_block *s; | |
| 1016 | + struct nfs_server *server; | |
| 1017 | + struct dentry *mntroot; | |
| 1018 | + struct nfs_fh mntfh; | |
| 1019 | + int error; | |
| 1427 | 1020 | |
| 1428 | − path = nfs4_path(dentry, page, PAGE_SIZE); | |
| 1429 | − if (!IS_ERR(path)) { | |
| 1430 | − int len = PAGE_SIZE + page - path; | |
| 1431 | − char *tmp = path; | |
| 1021 | + dprintk("--> nfs4_referral_get_sb()\n"); | |
| 1432 | 1022 | |
| 1433 | − path = kmalloc(len, GFP_KERNEL); | |
| 1434 | − if (path) | |
| 1435 | − memcpy(path, tmp, len); | |
| 1436 | − else | |
| 1437 | − path = ERR_PTR(-ENOMEM); | |
| 1023 | + /* create a new volume representation */ | |
| 1024 | + server = nfs4_create_referral_server(data, &mntfh); | |
| 1025 | + if (IS_ERR(server)) { | |
| 1026 | + error = PTR_ERR(server); | |
| 1027 | + goto out_err_noserver; | |
| 1438 | 1028 | } |
| 1439 | − free_page((unsigned long)page); | |
| 1440 | − return path; | |
| 1441 | −} | |
| 1442 | 1029 | |
| 1443 | −static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data) | |
| 1444 | −{ | |
| 1445 | − const struct dentry *dentry = data->dentry; | |
| 1446 | − struct nfs4_client *clp = server->nfs4_state; | |
| 1447 | − struct super_block *sb; | |
| 1448 | − | |
| 1449 | − server->fsid = data->fattr->fsid; | |
| 1450 | − nfs_copy_fh(&server->fh, data->fh); | |
| 1451 | − server->mnt_path = nfs4_dup_path(dentry); | |
| 1452 | − if (IS_ERR(server->mnt_path)) { | |
| 1453 | − sb = (struct super_block *)server->mnt_path; | |
| 1454 | − goto err; | |
| 1030 | + /* Get a superblock - note that we may end up sharing one that already exists */ | |
| 1031 | + s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); | |
| 1032 | + if (IS_ERR(s)) { | |
| 1033 | + error = PTR_ERR(s); | |
| 1034 | + goto out_err_nosb; | |
| 1455 | 1035 | } |
| 1456 | − sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server); | |
| 1457 | − if (IS_ERR(sb) || sb->s_root) | |
| 1458 | − goto free_path; | |
| 1459 | − nfs4_server_capabilities(server, &server->fh); | |
| 1460 | − | |
| 1461 | − down_write(&clp->cl_sem); | |
| 1462 | − atomic_inc(&clp->cl_count); | |
| 1463 | − list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); | |
| 1464 | − up_write(&clp->cl_sem); | |
| 1465 | − return sb; | |
| 1466 | −free_path: | |
| 1467 | − kfree(server->mnt_path); | |
| 1468 | −err: | |
| 1469 | − server->mnt_path = NULL; | |
| 1470 | − return sb; | |
| 1471 | −} | |
| 1472 | 1036 | |
| 1473 | −static int nfs_clone_nfs4_sb(struct file_system_type *fs_type, | |
| 1474 | − int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | |
| 1475 | −{ | |
| 1476 | − struct nfs_clone_mount *data = raw_data; | |
| 1477 | − return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server, mnt); | |
| 1478 | −} | |
| 1037 | + if (s->s_fs_info != server) { | |
| 1038 | + nfs_free_server(server); | |
| 1039 | + server = NULL; | |
| 1040 | + } | |
| 1479 | 1041 | |
| 1480 | −static struct super_block *nfs4_referral_sb(struct nfs_server *server, struct nfs_clone_mount *data) | |
| 1481 | −{ | |
| 1482 | − struct super_block *sb = ERR_PTR(-ENOMEM); | |
| 1483 | − int len; | |
| 1484 | − | |
| 1485 | − len = strlen(data->mnt_path) + 1; | |
| 1486 | − server->mnt_path = kmalloc(len, GFP_KERNEL); | |
| 1487 | − if (server->mnt_path == NULL) | |
| 1488 | − goto err; | |
| 1489 | − memcpy(server->mnt_path, data->mnt_path, len); | |
| 1490 | − memcpy(&server->addr, data->addr, sizeof(struct sockaddr_in)); | |
| 1491 | − | |
| 1492 | − sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server); | |
| 1493 | − if (IS_ERR(sb) || sb->s_root) | |
| 1494 | − goto free_path; | |
| 1495 | − return sb; | |
| 1496 | −free_path: | |
| 1497 | − kfree(server->mnt_path); | |
| 1498 | −err: | |
| 1499 | − server->mnt_path = NULL; | |
| 1500 | − return sb; | |
| 1501 | −} | |
| 1042 | + if (!s->s_root) { | |
| 1043 | + /* initial superblock/root creation */ | |
| 1044 | + s->s_flags = flags; | |
| 1045 | + nfs4_fill_super(s); | |
| 1046 | + } | |
| 1502 | 1047 | |
| 1503 | −static struct nfs_server *nfs4_referral_server(struct super_block *sb, struct nfs_clone_mount *data) | |
| 1504 | −{ | |
| 1505 | − struct nfs_server *server = NFS_SB(sb); | |
| 1506 | − struct rpc_timeout timeparms; | |
| 1507 | − int proto, timeo, retrans; | |
| 1508 | − void *err; | |
| 1509 | − | |
| 1510 | − proto = IPPROTO_TCP; | |
| 1511 | − /* Since we are following a referral and there may be alternatives, | |
| 1512 | − set the timeouts and retries to low values */ | |
| 1513 | − timeo = 2; | |
| 1514 | − retrans = 1; | |
| 1515 | − nfs_init_timeout_values(&timeparms, proto, timeo, retrans); | |
| 1516 | − | |
| 1517 | − server->client = nfs4_create_client(server, &timeparms, proto, data->authflavor); | |
| 1518 | − if (IS_ERR((err = server->client))) | |
| 1519 | − goto out_err; | |
| 1048 | + mntroot = nfs4_get_root(s, data->fh); | |
| 1049 | + if (IS_ERR(mntroot)) { | |
| 1050 | + error = PTR_ERR(mntroot); | |
| 1051 | + goto error_splat_super; | |
| 1052 | + } | |
| 1520 | 1053 | |
| 1521 | − sb->s_time_gran = 1; | |
| 1522 | − sb->s_op = &nfs4_sops; | |
| 1523 | − err = ERR_PTR(nfs_sb_init(sb, data->authflavor)); | |
| 1524 | − if (!IS_ERR(err)) | |
| 1525 | − return server; | |
| 1526 | −out_err: | |
| 1527 | − return (struct nfs_server *)err; | |
| 1528 | −} | |
| 1054 | + s->s_flags |= MS_ACTIVE; | |
| 1055 | + mnt->mnt_sb = s; | |
| 1056 | + mnt->mnt_root = mntroot; | |
| 1529 | 1057 | |
| 1530 | −static int nfs_referral_nfs4_sb(struct file_system_type *fs_type, | |
| 1531 | − int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | |
| 1532 | −{ | |
| 1533 | − struct nfs_clone_mount *data = raw_data; | |
| 1534 | − return nfs_clone_generic_sb(data, nfs4_referral_sb, nfs4_referral_server, mnt); | |
| 1058 | + dprintk("<-- nfs4_referral_get_sb() = 0\n"); | |
| 1059 | + return 0; | |
| 1060 | + | |
| 1061 | +out_err_nosb: | |
| 1062 | + nfs_free_server(server); | |
| 1063 | +out_err_noserver: | |
| 1064 | + dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error); | |
| 1065 | + return error; | |
| 1066 | + | |
| 1067 | +error_splat_super: | |
| 1068 | + up_write(&s->s_umount); | |
| 1069 | + deactivate_super(s); | |
| 1070 | + dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); | |
| 1071 | + return error; | |
| 1535 | 1072 | } |
| 1536 | 1073 | |
| 1537 | −#endif | |
| 1074 | +#endif /* CONFIG_NFS_V4 */ | |
| @@ -396,6 +396,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) · 395 unmodified lines | ||
| 396 | 396 | out: |
| 397 | 397 | clear_bit(BDI_write_congested, &bdi->state); |
| 398 | 398 | wake_up_all(&nfs_write_congestion); |
| 399 | + writeback_congestion_end(); | |
| 399 | 400 | return err; |
| 400 | 401 | } |
| 401 | 402 | |
| @@ -1252,7 +1253,13 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) · 850 unmodified lines | ||
| 1252 | 1253 | dprintk("NFS: %4d nfs_writeback_done (status %d)\n", |
| 1253 | 1254 | task->tk_pid, task->tk_status); |
| 1254 | 1255 | |
| 1255 | − /* Call the NFS version-specific code */ | |
| 1256 | + /* | |
| 1257 | + * ->write_done will attempt to use post-op attributes to detect | |
| 1258 | + * conflicting writes by other clients. A strict interpretation | |
| 1259 | + * of close-to-open would allow us to continue caching even if | |
| 1260 | + * another writer had changed the file, but some applications | |
| 1261 | + * depend on tighter cache coherency when writing. | |
| 1262 | + */ | |
| 1256 | 1263 | status = NFS_PROTO(data->inode)->write_done(task, data); |
| 1257 | 1264 | if (status != 0) |
| 1258 | 1265 | return status; |
| @@ -1273,7 +1280,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) · 14 unmodified lines | ||
| 1273 | 1280 | if (time_before(complain, jiffies)) { |
| 1274 | 1281 | dprintk("NFS: faulty NFS server %s:" |
| 1275 | 1282 | " (committed = %d) != (stable = %d)\n", |
| 1276 | − NFS_SERVER(data->inode)->hostname, | |
| 1283 | + NFS_SERVER(data->inode)->nfs_client->cl_hostname, | |
| 1277 | 1284 | resp->verf->committed, argp->stable); |
| 1278 | 1285 | complain = jiffies + 300 * HZ; |
| 1279 | 1286 | } |
| @@ -375,16 +375,28 @@ nfsd4_probe_callback(struct nfs4_client *clp) · 374 unmodified lines | ||
| 375 | 375 | { |
| 376 | 376 | struct sockaddr_in addr; |
| 377 | 377 | struct nfs4_callback *cb = &clp->cl_callback; |
| 378 | − struct rpc_timeout timeparms; | |
| 379 | − struct rpc_xprt * xprt; | |
| 378 | + struct rpc_timeout timeparms = { | |
| 379 | + .to_initval = (NFSD_LEASE_TIME/4) * HZ, | |
| 380 | + .to_retries = 5, | |
| 381 | + .to_maxval = (NFSD_LEASE_TIME/2) * HZ, | |
| 382 | + .to_exponential = 1, | |
| 383 | + }; | |
| 380 | 384 | struct rpc_program * program = &cb->cb_program; |
| 381 | − struct rpc_stat * stat = &cb->cb_stat; | |
| 382 | − struct rpc_clnt * clnt; | |
| 385 | + struct rpc_create_args args = { | |
| 386 | + .protocol = IPPROTO_TCP, | |
| 387 | + .address = (struct sockaddr *)&addr, | |
| 388 | + .addrsize = sizeof(addr), | |
| 389 | + .timeout = &timeparms, | |
| 390 | + .servername = clp->cl_name.data, | |
| 391 | + .program = program, | |
| 392 | + .version = nfs_cb_version[1]->number, | |
| 393 | + .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ | |
| 394 | + .flags = (RPC_CLNT_CREATE_NOPING), | |
| 395 | + }; | |
| 383 | 396 | struct rpc_message msg = { |
| 384 | 397 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], |
| 385 | 398 | .rpc_argp = clp, |
| 386 | 399 | }; |
| 387 | − char hostname[32]; | |
| 388 | 400 | int status; |
| 389 | 401 | |
| 390 | 402 | if (atomic_read(&cb->cb_set)) |
| @@ -396,51 +408,27 @@ nfsd4_probe_callback(struct nfs4_client *clp) · 5 unmodified lines | ||
| 396 | 408 | addr.sin_port = htons(cb->cb_port); |
| 397 | 409 | addr.sin_addr.s_addr = htonl(cb->cb_addr); |
| 398 | 410 | |
| 399 | − /* Initialize timeout */ | |
| 400 | − timeparms.to_initval = (NFSD_LEASE_TIME/4) * HZ; | |
| 401 | − timeparms.to_retries = 0; | |
| 402 | − timeparms.to_maxval = (NFSD_LEASE_TIME/2) * HZ; | |
| 403 | − timeparms.to_exponential = 1; | |
| 404 | − | |
| 405 | − /* Create RPC transport */ | |
| 406 | − xprt = xprt_create_proto(IPPROTO_TCP, &addr, &timeparms); | |
| 407 | − if (IS_ERR(xprt)) { | |
| 408 | − dprintk("NFSD: couldn't create callback transport!\n"); | |
| 409 | − goto out_err; | |
| 410 | − } | |
| 411 | − | |
| 412 | 411 | /* Initialize rpc_program */ |
| 413 | 412 | program->name = "nfs4_cb"; |
| 414 | 413 | program->number = cb->cb_prog; |
| 415 | 414 | program->nrvers = ARRAY_SIZE(nfs_cb_version); |
| 416 | 415 | program->version = nfs_cb_version; |
| 417 | − program->stats = stat; | |
| 416 | + program->stats = &cb->cb_stat; | |
| 418 | 417 | |
| 419 | 418 | /* Initialize rpc_stat */ |
| 420 | − memset(stat, 0, sizeof(struct rpc_stat)); | |
| 421 | − stat->program = program; | |
| 422 | − | |
| 423 | − /* Create RPC client | |
| 424 | − * | |
| 425 | − * XXX AUTH_UNIX only - need AUTH_GSS.... | |
| 426 | − */ | |
| 427 | − sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr)); | |
| 428 | − clnt = rpc_new_client(xprt, hostname, program, 1, RPC_AUTH_UNIX); | |
| 429 | − if (IS_ERR(clnt)) { | |
| 419 | + memset(program->stats, 0, sizeof(cb->cb_stat)); | |
| 420 | + program->stats->program = program; | |
| 421 | + | |
| 422 | + /* Create RPC client */ | |
| 423 | + cb->cb_client = rpc_create(&args); | |
| 424 | + if (!cb->cb_client) { | |
| 430 | 425 | dprintk("NFSD: couldn't create callback client\n"); |
| 431 | 426 | goto out_err; |
| 432 | 427 | } |
| 433 | − clnt->cl_intr = 0; | |
| 434 | − clnt->cl_softrtry = 1; | |
| 435 | 428 | |
| 436 | 429 | /* Kick rpciod, put the call on the wire. */ |
| 437 | − | |
| 438 | − if (rpciod_up() != 0) { | |
| 439 | − dprintk("nfsd: couldn't start rpciod for callbacks!\n"); | |
| 430 | + if (rpciod_up() != 0) | |
| 440 | 431 | goto out_clnt; |
| 441 | − } | |
| 442 | − | |
| 443 | − cb->cb_client = clnt; | |
| 444 | 432 | |
| 445 | 433 | /* the task holds a reference to the nfs4_client struct */ |
| 446 | 434 | atomic_inc(&clp->cl_count); |
| @@ -448,7 +436,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) · 1 unmodified line | ||
| 448 | 436 | msg.rpc_cred = nfsd4_lookupcred(clp,0); |
| 449 | 437 | if (IS_ERR(msg.rpc_cred)) |
| 450 | 438 | goto out_rpciod; |
| 451 | − status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); | |
| 439 | + status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); | |
| 452 | 440 | put_rpccred(msg.rpc_cred); |
| 453 | 441 | |
| 454 | 442 | if (status != 0) { |
| @@ -462,7 +450,7 @@ out_rpciod: · 7 unmodified lines | ||
| 462 | 450 | rpciod_down(); |
| 463 | 451 | cb->cb_client = NULL; |
| 464 | 452 | out_clnt: |
| 465 | − rpc_shutdown_client(clnt); | |
| 453 | + rpc_shutdown_client(cb->cb_client); | |
| 466 | 454 | out_err: |
| 467 | 455 | dprintk("NFSD: warning: no callback path to client %.*s\n", |
| 468 | 456 | (int)clp->cl_name.len, clp->cl_name.data); |
| @@ -86,7 +86,7 @@ void ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5, · 85 unmodified lines | ||
| 86 | 86 | #define PCI_DRAM_OFFSET 0 |
| 87 | 87 | #endif |
| 88 | 88 | |
| 89 | −#elif CONFIG_44x | |
| 89 | +#elif defined(CONFIG_44x) | |
| 90 | 90 | |
| 91 | 91 | #if defined(CONFIG_BAMBOO) |
| 92 | 92 | #include <platforms/4xx/bamboo.h> |
| @@ -748,6 +748,7 @@ extern void blk_queue_invalidate_tags(request_queue_t *); · 747 unmodified lines | ||
| 748 | 748 | extern long blk_congestion_wait(int rw, long timeout); |
| 749 | 749 | extern struct blk_queue_tag *blk_init_tags(int); |
| 750 | 750 | extern void blk_free_tags(struct blk_queue_tag *); |
| 751 | +extern void blk_congestion_end(int rw); | |
| 751 | 752 | |
| 752 | 753 | extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *); |
| 753 | 754 | extern int blkdev_issue_flush(struct block_device *, sector_t *); |
| @@ -114,7 +114,7 @@ extern void *__init alloc_large_system_hash(const char *tablename, · 113 unmodified lines | ||
| 114 | 114 | #else |
| 115 | 115 | #define HASHDIST_DEFAULT 0 |
| 116 | 116 | #endif |
| 117 | −extern int __initdata hashdist; /* Distribute hashes across NUMA nodes? */ | |
| 117 | +extern int hashdist; /* Distribute hashes across NUMA nodes? */ | |
| 118 | 118 | |
| 119 | 119 | |
| 120 | 120 | #endif /* _LINUX_BOOTMEM_H */ |
| @@ -221,6 +221,7 @@ static inline int dname_external(struct dentry *dentry) · 220 unmodified lines | ||
| 221 | 221 | */ |
| 222 | 222 | extern void d_instantiate(struct dentry *, struct inode *); |
| 223 | 223 | extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *); |
| 224 | +extern struct dentry * d_materialise_unique(struct dentry *, struct inode *); | |
| 224 | 225 | extern void d_delete(struct dentry *); |
| 225 | 226 | |
| 226 | 227 | /* allocate/de-allocate */ |
| @@ -438,6 +438,7 @@ struct dccp_ackvec; · 437 unmodified lines | ||
| 438 | 438 | * @dccps_role - Role of this sock, one of %dccp_role |
| 439 | 439 | * @dccps_ndp_count - number of Non Data Packets since last data packet |
| 440 | 440 | * @dccps_hc_rx_ackvec - rx half connection ack vector |
| 441 | + * @dccps_xmit_timer - timer for when CCID is not ready to send | |
| 441 | 442 | */ |
| 442 | 443 | struct dccp_sock { |
| 443 | 444 | /* inet_connection_sock has to be the first member of dccp_sock */ |
| @@ -470,6 +471,7 @@ struct dccp_sock { · 26 unmodified lines | ||
| 470 | 471 | enum dccp_role dccps_role:2; |
| 471 | 472 | __u8 dccps_hc_rx_insert_options:1; |
| 472 | 473 | __u8 dccps_hc_tx_insert_options:1; |
| 474 | + struct timer_list dccps_xmit_timer; | |
| 473 | 475 | }; |
| 474 | 476 | |
| 475 | 477 | static inline struct dccp_sock *dccp_sk(const struct sock *sk) |
| @@ -0,0 +1,65 @@ | ||
| 1 | +#ifndef __LINUX_FIB_RULES_H | |
| 2 | +#define __LINUX_FIB_RULES_H | |
| 3 | + | |
| 4 | +#include <linux/types.h> | |
| 5 | +#include <linux/rtnetlink.h> | |
| 6 | + | |
| 7 | +/* rule is permanent, and cannot be deleted */ | |
| 8 | +#define FIB_RULE_PERMANENT 1 | |
| 9 | + | |
| 10 | +struct fib_rule_hdr | |
| 11 | +{ | |
| 12 | + __u8 family; | |
| 13 | + __u8 dst_len; | |
| 14 | + __u8 src_len; | |
| 15 | + __u8 tos; | |
| 16 | + | |
| 17 | + __u8 table; | |
| 18 | + __u8 res1; /* reserved */ | |
| 19 | + __u8 res2; /* reserved */ | |
| 20 | + __u8 action; | |
| 21 | + | |
| 22 | + __u32 flags; | |
| 23 | +}; | |
| 24 | + | |
| 25 | +enum | |
| 26 | +{ | |
| 27 | + FRA_UNSPEC, | |
| 28 | + FRA_DST, /* destination address */ | |
| 29 | + FRA_SRC, /* source address */ | |
| 30 | + FRA_IFNAME, /* interface name */ | |
| 31 | + FRA_UNUSED1, | |
| 32 | + FRA_UNUSED2, | |
| 33 | + FRA_PRIORITY, /* priority/preference */ | |
| 34 | + FRA_UNUSED3, | |
| 35 | + FRA_UNUSED4, | |
| 36 | + FRA_UNUSED5, | |
| 37 | + FRA_FWMARK, /* netfilter mark */ | |
| 38 | + FRA_FLOW, /* flow/class id */ | |
| 39 | + FRA_UNUSED6, | |
| 40 | + FRA_UNUSED7, | |
| 41 | + FRA_UNUSED8, | |
| 42 | + FRA_TABLE, /* Extended table id */ | |
| 43 | + FRA_FWMASK, /* mask for netfilter mark */ | |
| 44 | + __FRA_MAX | |
| 45 | +}; | |
| 46 | + | |
| 47 | +#define FRA_MAX (__FRA_MAX - 1) | |
| 48 | + | |
| 49 | +enum | |
| 50 | +{ | |
| 51 | + FR_ACT_UNSPEC, | |
| 52 | + FR_ACT_TO_TBL, /* Pass to fixed table */ | |
| 53 | + FR_ACT_RES1, | |
| 54 | + FR_ACT_RES2, | |
| 55 | + FR_ACT_RES3, | |
| 56 | + FR_ACT_RES4, | |
| 57 | + FR_ACT_BLACKHOLE, /* Drop without notification */ | |
| 58 | + FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ | |
| 59 | + FR_ACT_PROHIBIT, /* Drop with EACCES */ | |
| 60 | + __FR_ACT_MAX, | |
| 61 | +}; | |
| 62 | + | |
| 63 | +#define FR_ACT_MAX (__FR_ACT_MAX - 1) | |
| 64 | + | |
| 65 | +#endif | |
| @@ -25,10 +25,10 @@ · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | struct sock_filter /* Filter block */ |
| 27 | 27 | { |
| 28 | − __u16 code; /* Actual filter code */ | |
| 29 | − __u8 jt; /* Jump true */ | |
| 30 | − __u8 jf; /* Jump false */ | |
| 31 | − __u32 k; /* Generic multiuse field */ | |
| 28 | + __u16 code; /* Actual filter code */ | |
| 29 | + __u8 jt; /* Jump true */ | |
| 30 | + __u8 jf; /* Jump false */ | |
| 31 | + __u32 k; /* Generic multiuse field */ | |
| 32 | 32 | }; |
| 33 | 33 | |
| 34 | 34 | struct sock_fprog /* Required for SO_ATTACH_FILTER. */ |
| @@ -41,8 +41,9 @@ struct sock_fprog /* Required for SO_ATTACH_FILTER. */ · 6 unmodified lines | ||
| 41 | 41 | struct sk_filter |
| 42 | 42 | { |
| 43 | 43 | atomic_t refcnt; |
| 44 | − unsigned int len; /* Number of filter blocks */ | |
| 45 | − struct sock_filter insns[0]; | |
| 44 | + unsigned int len; /* Number of filter blocks */ | |
| 45 | + struct rcu_head rcu; | |
| 46 | + struct sock_filter insns[0]; | |
| 46 | 47 | }; |
| 47 | 48 | |
| 48 | 49 | static inline unsigned int sk_filter_len(struct sk_filter *fp) |
| @@ -16,6 +16,8 @@ struct genlmsghdr { · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | #define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) |
| 18 | 18 | |
| 19 | +#define GENL_ADMIN_PERM 0x01 | |
| 20 | + | |
| 19 | 21 | /* |
| 20 | 22 | * List of reserved static generic netlink identifiers: |
| 21 | 23 | */ |
| @@ -43,9 +45,25 @@ enum { · 21 unmodified lines | ||
| 43 | 45 | CTRL_ATTR_UNSPEC, |
| 44 | 46 | CTRL_ATTR_FAMILY_ID, |
| 45 | 47 | CTRL_ATTR_FAMILY_NAME, |
| 48 | + CTRL_ATTR_VERSION, | |
| 49 | + CTRL_ATTR_HDRSIZE, | |
| 50 | + CTRL_ATTR_MAXATTR, | |
| 51 | + CTRL_ATTR_OPS, | |
| 46 | 52 | __CTRL_ATTR_MAX, |
| 47 | 53 | }; |
| 48 | 54 | |
| 49 | 55 | #define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1) |
| 50 | 56 | |
| 57 | +enum { | |
| 58 | + CTRL_ATTR_OP_UNSPEC, | |
| 59 | + CTRL_ATTR_OP_ID, | |
| 60 | + CTRL_ATTR_OP_FLAGS, | |
| 61 | + CTRL_ATTR_OP_POLICY, | |
| 62 | + CTRL_ATTR_OP_DOIT, | |
| 63 | + CTRL_ATTR_OP_DUMPIT, | |
| 64 | + __CTRL_ATTR_OP_MAX, | |
| 65 | +}; | |
| 66 | + | |
| 67 | +#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) | |
| 68 | + | |
| 51 | 69 | #endif /* __LINUX_GENERIC_NETLINK_H */ |
| @@ -212,5 +212,134 @@ struct ifconf · 211 unmodified lines | ||
| 212 | 212 | #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ |
| 213 | 213 | #define ifc_req ifc_ifcu.ifcu_req /* array of structures */ |
| 214 | 214 | |
| 215 | +/* The struct should be in sync with struct net_device_stats */ | |
| 216 | +struct rtnl_link_stats | |
| 217 | +{ | |
| 218 | + __u32 rx_packets; /* total packets received */ | |
| 219 | + __u32 tx_packets; /* total packets transmitted */ | |
| 220 | + __u32 rx_bytes; /* total bytes received */ | |
| 221 | + __u32 tx_bytes; /* total bytes transmitted */ | |
| 222 | + __u32 rx_errors; /* bad packets received */ | |
| 223 | + __u32 tx_errors; /* packet transmit problems */ | |
| 224 | + __u32 rx_dropped; /* no space in linux buffers */ | |
| 225 | + __u32 tx_dropped; /* no space available in linux */ | |
| 226 | + __u32 multicast; /* multicast packets received */ | |
| 227 | + __u32 collisions; | |
| 228 | + | |
| 229 | + /* detailed rx_errors: */ | |
| 230 | + __u32 rx_length_errors; | |
| 231 | + __u32 rx_over_errors; /* receiver ring buff overflow */ | |
| 232 | + __u32 rx_crc_errors; /* recved pkt with crc error */ | |
| 233 | + __u32 rx_frame_errors; /* recv'd frame alignment error */ | |
| 234 | + __u32 rx_fifo_errors; /* recv'r fifo overrun */ | |
| 235 | + __u32 rx_missed_errors; /* receiver missed packet */ | |
| 236 | + | |
| 237 | + /* detailed tx_errors */ | |
| 238 | + __u32 tx_aborted_errors; | |
| 239 | + __u32 tx_carrier_errors; | |
| 240 | + __u32 tx_fifo_errors; | |
| 241 | + __u32 tx_heartbeat_errors; | |
| 242 | + __u32 tx_window_errors; | |
| 243 | + | |
| 244 | + /* for cslip etc */ | |
| 245 | + __u32 rx_compressed; | |
| 246 | + __u32 tx_compressed; | |
| 247 | +}; | |
| 248 | + | |
| 249 | +/* The struct should be in sync with struct ifmap */ | |
| 250 | +struct rtnl_link_ifmap | |
| 251 | +{ | |
| 252 | + __u64 mem_start; | |
| 253 | + __u64 mem_end; | |
| 254 | + __u64 base_addr; | |
| 255 | + __u16 irq; | |
| 256 | + __u8 dma; | |
| 257 | + __u8 port; | |
| 258 | +}; | |
| 259 | + | |
| 260 | +enum | |
| 261 | +{ | |
| 262 | + IFLA_UNSPEC, | |
| 263 | + IFLA_ADDRESS, | |
| 264 | + IFLA_BROADCAST, | |
| 265 | + IFLA_IFNAME, | |
| 266 | + IFLA_MTU, | |
| 267 | + IFLA_LINK, | |
| 268 | + IFLA_QDISC, | |
| 269 | + IFLA_STATS, | |
| 270 | + IFLA_COST, | |
| 271 | +#define IFLA_COST IFLA_COST | |
| 272 | + IFLA_PRIORITY, | |
| 273 | +#define IFLA_PRIORITY IFLA_PRIORITY | |
| 274 | + IFLA_MASTER, | |
| 275 | +#define IFLA_MASTER IFLA_MASTER | |
| 276 | + IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ | |
| 277 | +#define IFLA_WIRELESS IFLA_WIRELESS | |
| 278 | + IFLA_PROTINFO, /* Protocol specific information for a link */ | |
| 279 | +#define IFLA_PROTINFO IFLA_PROTINFO | |
| 280 | + IFLA_TXQLEN, | |
| 281 | +#define IFLA_TXQLEN IFLA_TXQLEN | |
| 282 | + IFLA_MAP, | |
| 283 | +#define IFLA_MAP IFLA_MAP | |
| 284 | + IFLA_WEIGHT, | |
| 285 | +#define IFLA_WEIGHT IFLA_WEIGHT | |
| 286 | + IFLA_OPERSTATE, | |
| 287 | + IFLA_LINKMODE, | |
| 288 | + __IFLA_MAX | |
| 289 | +}; | |
| 290 | + | |
| 291 | + | |
| 292 | +#define IFLA_MAX (__IFLA_MAX - 1) | |
| 293 | + | |
| 294 | +/* ifi_flags. | |
| 295 | + | |
| 296 | + IFF_* flags. | |
| 297 | + | |
| 298 | + The only change is: | |
| 299 | + IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are | |
| 300 | + more not changeable by user. They describe link media | |
| 301 | + characteristics and set by device driver. | |
| 302 | + | |
| 303 | + Comments: | |
| 304 | + - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid | |
| 305 | + - If neither of these three flags are set; | |
| 306 | + the interface is NBMA. | |
| 307 | + | |
| 308 | + - IFF_MULTICAST does not mean anything special: | |
| 309 | + multicasts can be used on all not-NBMA links. | |
| 310 | + IFF_MULTICAST means that this media uses special encapsulation | |
| 311 | + for multicast frames. Apparently, all IFF_POINTOPOINT and | |
| 312 | + IFF_BROADCAST devices are able to use multicasts too. | |
| 313 | + */ | |
| 314 | + | |
| 315 | +/* IFLA_LINK. | |
| 316 | + For usual devices it is equal ifi_index. | |
| 317 | + If it is a "virtual interface" (f.e. tunnel), ifi_link | |
| 318 | + can point to real physical interface (f.e. for bandwidth calculations), | |
| 319 | + or maybe 0, what means, that real media is unknown (usual | |
| 320 | + for IPIP tunnels, when route to endpoint is allowed to change) | |
| 321 | + */ | |
| 322 | + | |
| 323 | +/* Subtype attributes for IFLA_PROTINFO */ | |
| 324 | +enum | |
| 325 | +{ | |
| 326 | + IFLA_INET6_UNSPEC, | |
| 327 | + IFLA_INET6_FLAGS, /* link flags */ | |
| 328 | + IFLA_INET6_CONF, /* sysctl parameters */ | |
| 329 | + IFLA_INET6_STATS, /* statistics */ | |
| 330 | + IFLA_INET6_MCAST, /* MC things. What of them? */ | |
| 331 | + IFLA_INET6_CACHEINFO, /* time values and max reasm size */ | |
| 332 | + __IFLA_INET6_MAX | |
| 333 | +}; | |
| 334 | + | |
| 335 | +#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) | |
| 336 | + | |
| 337 | +struct ifla_cacheinfo | |
| 338 | +{ | |
| 339 | + __u32 max_reasm_len; | |
| 340 | + __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ | |
| 341 | + __u32 reachable_time; | |
| 342 | + __u32 retrans_time; | |
| 343 | +}; | |
| 215 | 344 | |
| 216 | 345 | #endif /* _LINUX_IF_H */ |
| @@ -0,0 +1,55 @@ | ||
| 1 | +#ifndef __LINUX_IF_ADDR_H | |
| 2 | +#define __LINUX_IF_ADDR_H | |
| 3 | + | |
| 4 | +#include <linux/netlink.h> | |
| 5 | + | |
| 6 | +struct ifaddrmsg | |
| 7 | +{ | |
| 8 | + __u8 ifa_family; | |
| 9 | + __u8 ifa_prefixlen; /* The prefix length */ | |
| 10 | + __u8 ifa_flags; /* Flags */ | |
| 11 | + __u8 ifa_scope; /* Address scope */ | |
| 12 | + __u32 ifa_index; /* Link index */ | |
| 13 | +}; | |
| 14 | + | |
| 15 | +/* | |
| 16 | + * Important comment: | |
| 17 | + * IFA_ADDRESS is prefix address, rather than local interface address. | |
| 18 | + * It makes no difference for normally configured broadcast interfaces, | |
| 19 | + * but for point-to-point IFA_ADDRESS is DESTINATION address, | |
| 20 | + * local address is supplied in IFA_LOCAL attribute. | |
| 21 | + */ | |
| 22 | +enum | |
| 23 | +{ | |
| 24 | + IFA_UNSPEC, | |
| 25 | + IFA_ADDRESS, | |
| 26 | + IFA_LOCAL, | |
| 27 | + IFA_LABEL, | |
| 28 | + IFA_BROADCAST, | |
| 29 | + IFA_ANYCAST, | |
| 30 | + IFA_CACHEINFO, | |
| 31 | + IFA_MULTICAST, | |
| 32 | + __IFA_MAX, | |
| 33 | +}; | |
| 34 | + | |
| 35 | +#define IFA_MAX (__IFA_MAX - 1) | |
| 36 | + | |
| 37 | +/* ifa_flags */ | |
| 38 | +#define IFA_F_SECONDARY 0x01 | |
| 39 | +#define IFA_F_TEMPORARY IFA_F_SECONDARY | |
| 40 | + | |
| 41 | +#define IFA_F_NODAD 0x02 | |
| 42 | +#define IFA_F_HOMEADDRESS 0x10 | |
| 43 | +#define IFA_F_DEPRECATED 0x20 | |
| 44 | +#define IFA_F_TENTATIVE 0x40 | |
| 45 | +#define IFA_F_PERMANENT 0x80 | |
| 46 | + | |
| 47 | +struct ifa_cacheinfo | |
| 48 | +{ | |
| 49 | + __u32 ifa_prefered; | |
| 50 | + __u32 ifa_valid; | |
| 51 | + __u32 cstamp; /* created timestamp, hundredths of seconds */ | |
| 52 | + __u32 tstamp; /* updated timestamp, hundredths of seconds */ | |
| 53 | +}; | |
| 54 | + | |
| 55 | +#endif | |
| @@ -52,7 +52,7 @@ enum { · 51 unmodified lines | ||
| 52 | 52 | |
| 53 | 53 | /* Internet address. */ |
| 54 | 54 | struct in_addr { |
| 55 | − __u32 s_addr; | |
| 55 | + __be32 s_addr; | |
| 56 | 56 | }; |
| 57 | 57 | |
| 58 | 58 | #define IP_TOS 1 |
| @@ -177,7 +177,7 @@ struct in_pktinfo · 118 unmodified lines | ||
| 177 | 177 | #define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ |
| 178 | 178 | struct sockaddr_in { |
| 179 | 179 | sa_family_t sin_family; /* Address family */ |
| 180 | − unsigned short int sin_port; /* Port number */ | |
| 180 | + __be16 sin_port; /* Port number */ | |
| 181 | 181 | struct in_addr sin_addr; /* Internet address */ |
| 182 | 182 | |
| 183 | 183 | /* Pad to size of `struct sockaddr'. */ |
| @@ -134,6 +134,7 @@ struct in6_flowlabel_req · 133 unmodified lines | ||
| 134 | 134 | #define IPPROTO_ICMPV6 58 /* ICMPv6 */ |
| 135 | 135 | #define IPPROTO_NONE 59 /* IPv6 no next header */ |
| 136 | 136 | #define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ |
| 137 | +#define IPPROTO_MH 135 /* IPv6 mobility header */ | |
| 137 | 138 | |
| 138 | 139 | /* |
| 139 | 140 | * IPv6 TLV options. |
| @@ -142,6 +143,7 @@ struct in6_flowlabel_req · 2 unmodified lines | ||
| 142 | 143 | #define IPV6_TLV_PADN 1 |
| 143 | 144 | #define IPV6_TLV_ROUTERALERT 5 |
| 144 | 145 | #define IPV6_TLV_JUMBO 194 |
| 146 | +#define IPV6_TLV_HAO 201 /* home address option */ | |
| 145 | 147 | |
| 146 | 148 | /* |
| 147 | 149 | * IPV6 socket options |
| @@ -46,5 +46,7 @@ · 45 unmodified lines | ||
| 46 | 46 | #include <linux/types.h> |
| 47 | 47 | |
| 48 | 48 | extern __be32 in_aton(const char *str); |
| 49 | +extern int in4_pton(const char *src, int srclen, u8 *dst, char delim, const char **end); | |
| 50 | +extern int in6_pton(const char *src, int srclen, u8 *dst, char delim, const char **end); | |
| 49 | 51 | #endif |
| 50 | 52 | #endif /* _LINUX_INET_H */ |
| @@ -57,6 +57,7 @@ · 56 unmodified lines | ||
| 57 | 57 | #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY) |
| 58 | 58 | #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY) |
| 59 | 59 | #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT) |
| 60 | +#define IPOPT_CIPSO (6 |IPOPT_CONTROL|IPOPT_COPY) | |
| 60 | 61 | #define IPOPT_RR (7 |IPOPT_CONTROL) |
| 61 | 62 | #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY) |
| 62 | 63 | #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY) |
| @@ -29,6 +29,7 @@ struct in6_ifreq { · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | #define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */ |
| 31 | 31 | #define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */ |
| 32 | +#define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */ | |
| 32 | 33 | |
| 33 | 34 | /* |
| 34 | 35 | * routing header |
| @@ -73,6 +74,28 @@ struct rt0_hdr { · 38 unmodified lines | ||
| 73 | 74 | #define rt0_type rt_hdr.type |
| 74 | 75 | }; |
| 75 | 76 | |
| 77 | +/* | |
| 78 | + * routing header type 2 | |
| 79 | + */ | |
| 80 | + | |
| 81 | +struct rt2_hdr { | |
| 82 | + struct ipv6_rt_hdr rt_hdr; | |
| 83 | + __u32 reserved; | |
| 84 | + struct in6_addr addr; | |
| 85 | + | |
| 86 | +#define rt2_type rt_hdr.type | |
| 87 | +}; | |
| 88 | + | |
| 89 | +/* | |
| 90 | + * home address option in destination options header | |
| 91 | + */ | |
| 92 | + | |
| 93 | +struct ipv6_destopt_hao { | |
| 94 | + __u8 type; | |
| 95 | + __u8 length; | |
| 96 | + struct in6_addr addr; | |
| 97 | +} __attribute__ ((__packed__)); | |
| 98 | + | |
| 76 | 99 | struct ipv6_auth_hdr { |
| 77 | 100 | __u8 nexthdr; |
| 78 | 101 | __u8 hdrlen; /* This one is measured in 32 bit units! */ |
| @@ -153,6 +176,7 @@ struct ipv6_devconf { · 74 unmodified lines | ||
| 153 | 176 | __s32 accept_ra_rt_info_max_plen; |
| 154 | 177 | #endif |
| 155 | 178 | #endif |
| 179 | + __s32 proxy_ndp; | |
| 156 | 180 | void *sysctl; |
| 157 | 181 | }; |
| 158 | 182 | |
| @@ -180,6 +204,7 @@ enum { · 21 unmodified lines | ||
| 180 | 204 | DEVCONF_ACCEPT_RA_RTR_PREF, |
| 181 | 205 | DEVCONF_RTR_PROBE_INTERVAL, |
| 182 | 206 | DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, |
| 207 | + DEVCONF_PROXY_NDP, | |
| 183 | 208 | DEVCONF_MAX |
| 184 | 209 | }; |
| 185 | 210 | |
| @@ -206,6 +231,9 @@ struct inet6_skb_parm { · 20 unmodified lines | ||
| 206 | 231 | __u16 lastopt; |
| 207 | 232 | __u32 nhoff; |
| 208 | 233 | __u16 flags; |
| 234 | +#ifdef CONFIG_IPV6_MIP6 | |
| 235 | + __u16 dsthao; | |
| 236 | +#endif | |
| 209 | 237 | |
| 210 | 238 | #define IP6SKB_XFRM_TRANSFORMED 1 |
| 211 | 239 | }; |
| @@ -242,6 +270,9 @@ struct ipv6_pinfo { · 30 unmodified lines | ||
| 242 | 270 | struct in6_addr rcv_saddr; |
| 243 | 271 | struct in6_addr daddr; |
| 244 | 272 | struct in6_addr *daddr_cache; |
| 273 | +#ifdef CONFIG_IPV6_SUBTREES | |
| 274 | + struct in6_addr *saddr_cache; | |
| 275 | +#endif | |
| 245 | 276 | |
| 246 | 277 | __u32 flow_label; |
| 247 | 278 | __u32 frag_size; |
| @@ -31,7 +31,7 @@ extern const char linux_banner[]; · 30 unmodified lines | ||
| 31 | 31 | #define STACK_MAGIC 0xdeadbeef |
| 32 | 32 | |
| 33 | 33 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
| 34 | −#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) | |
| 34 | +#define ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL)) | |
| 35 | 35 | #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) |
| 36 | 36 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) |
| 37 | 37 | |
| @@ -0,0 +1,159 @@ | ||
| 1 | +#ifndef __LINUX_NEIGHBOUR_H | |
| 2 | +#define __LINUX_NEIGHBOUR_H | |
| 3 | + | |
| 4 | +#include <linux/netlink.h> | |
| 5 | + | |
| 6 | +struct ndmsg | |
| 7 | +{ | |
| 8 | + __u8 ndm_family; | |
| 9 | + __u8 ndm_pad1; | |
| 10 | + __u16 ndm_pad2; | |
| 11 | + __s32 ndm_ifindex; | |
| 12 | + __u16 ndm_state; | |
| 13 | + __u8 ndm_flags; | |
| 14 | + __u8 ndm_type; | |
| 15 | +}; | |
| 16 | + | |
| 17 | +enum | |
| 18 | +{ | |
| 19 | + NDA_UNSPEC, | |
| 20 | + NDA_DST, | |
| 21 | + NDA_LLADDR, | |
| 22 | + NDA_CACHEINFO, | |
| 23 | + NDA_PROBES, | |
| 24 | + __NDA_MAX | |
| 25 | +}; | |
| 26 | + | |
| 27 | +#define NDA_MAX (__NDA_MAX - 1) | |
| 28 | + | |
| 29 | +/* | |
| 30 | + * Neighbor Cache Entry Flags | |
| 31 | + */ | |
| 32 | + | |
| 33 | +#define NTF_PROXY 0x08 /* == ATF_PUBL */ | |
| 34 | +#define NTF_ROUTER 0x80 | |
| 35 | + | |
| 36 | +/* | |
| 37 | + * Neighbor Cache Entry States. | |
| 38 | + */ | |
| 39 | + | |
| 40 | +#define NUD_INCOMPLETE 0x01 | |
| 41 | +#define NUD_REACHABLE 0x02 | |
| 42 | +#define NUD_STALE 0x04 | |
| 43 | +#define NUD_DELAY 0x08 | |
| 44 | +#define NUD_PROBE 0x10 | |
| 45 | +#define NUD_FAILED 0x20 | |
| 46 | + | |
| 47 | +/* Dummy states */ | |
| 48 | +#define NUD_NOARP 0x40 | |
| 49 | +#define NUD_PERMANENT 0x80 | |
| 50 | +#define NUD_NONE 0x00 | |
| 51 | + | |
| 52 | +/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change | |
| 53 | + and make no address resolution or NUD. | |
| 54 | + NUD_PERMANENT is also cannot be deleted by garbage collectors. | |
| 55 | + */ | |
| 56 | + | |
| 57 | +struct nda_cacheinfo | |
| 58 | +{ | |
| 59 | + __u32 ndm_confirmed; | |
| 60 | + __u32 ndm_used; | |
| 61 | + __u32 ndm_updated; | |
| 62 | + __u32 ndm_refcnt; | |
| 63 | +}; | |
| 64 | + | |
| 65 | +/***************************************************************** | |
| 66 | + * Neighbour tables specific messages. | |
| 67 | + * | |
| 68 | + * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the | |
| 69 | + * NLM_F_DUMP flag set. Every neighbour table configuration is | |
| 70 | + * spread over multiple messages to avoid running into message | |
| 71 | + * size limits on systems with many interfaces. The first message | |
| 72 | + * in the sequence transports all not device specific data such as | |
| 73 | + * statistics, configuration, and the default parameter set. | |
| 74 | + * This message is followed by 0..n messages carrying device | |
| 75 | + * specific parameter sets. | |
| 76 | + * Although the ordering should be sufficient, NDTA_NAME can be | |
| 77 | + * used to identify sequences. The initial message can be identified | |
| 78 | + * by checking for NDTA_CONFIG. The device specific messages do | |
| 79 | + * not contain this TLV but have NDTPA_IFINDEX set to the | |
| 80 | + * corresponding interface index. | |
| 81 | + * | |
| 82 | + * To change neighbour table attributes, send RTM_SETNEIGHTBL | |
| 83 | + * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3], | |
| 84 | + * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked | |
| 85 | + * otherwise. Device specific parameter sets can be changed by | |
| 86 | + * setting NDTPA_IFINDEX to the interface index of the corresponding | |
| 87 | + * device. | |
| 88 | + ****/ | |
| 89 | + | |
| 90 | +struct ndt_stats | |
| 91 | +{ | |
| 92 | + __u64 ndts_allocs; | |
| 93 | + __u64 ndts_destroys; | |
| 94 | + __u64 ndts_hash_grows; | |
| 95 | + __u64 ndts_res_failed; | |
| 96 | + __u64 ndts_lookups; | |
| 97 | + __u64 ndts_hits; | |
| 98 | + __u64 ndts_rcv_probes_mcast; | |
| 99 | + __u64 ndts_rcv_probes_ucast; | |
| 100 | + __u64 ndts_periodic_gc_runs; | |
| 101 | + __u64 ndts_forced_gc_runs; | |
| 102 | +}; | |
| 103 | + | |
| 104 | +enum { | |
| 105 | + NDTPA_UNSPEC, | |
| 106 | + NDTPA_IFINDEX, /* u32, unchangeable */ | |
| 107 | + NDTPA_REFCNT, /* u32, read-only */ | |
| 108 | + NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */ | |
| 109 | + NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */ | |
| 110 | + NDTPA_RETRANS_TIME, /* u64, msecs */ | |
| 111 | + NDTPA_GC_STALETIME, /* u64, msecs */ | |
| 112 | + NDTPA_DELAY_PROBE_TIME, /* u64, msecs */ | |
| 113 | + NDTPA_QUEUE_LEN, /* u32 */ | |
| 114 | + NDTPA_APP_PROBES, /* u32 */ | |
| 115 | + NDTPA_UCAST_PROBES, /* u32 */ | |
| 116 | + NDTPA_MCAST_PROBES, /* u32 */ | |
| 117 | + NDTPA_ANYCAST_DELAY, /* u64, msecs */ | |
| 118 | + NDTPA_PROXY_DELAY, /* u64, msecs */ | |
| 119 | + NDTPA_PROXY_QLEN, /* u32 */ | |
| 120 | + NDTPA_LOCKTIME, /* u64, msecs */ | |
| 121 | + __NDTPA_MAX | |
| 122 | +}; | |
| 123 | +#define NDTPA_MAX (__NDTPA_MAX - 1) | |
| 124 | + | |
| 125 | +struct ndtmsg | |
| 126 | +{ | |
| 127 | + __u8 ndtm_family; | |
| 128 | + __u8 ndtm_pad1; | |
| 129 | + __u16 ndtm_pad2; | |
| 130 | +}; | |
| 131 | + | |
| 132 | +struct ndt_config | |
| 133 | +{ | |
| 134 | + __u16 ndtc_key_len; | |
| 135 | + __u16 ndtc_entry_size; | |
| 136 | + __u32 ndtc_entries; | |
| 137 | + __u32 ndtc_last_flush; /* delta to now in msecs */ | |
| 138 | + __u32 ndtc_last_rand; /* delta to now in msecs */ | |
| 139 | + __u32 ndtc_hash_rnd; | |
| 140 | + __u32 ndtc_hash_mask; | |
| 141 | + __u32 ndtc_hash_chain_gc; | |
| 142 | + __u32 ndtc_proxy_qlen; | |
| 143 | +}; | |
| 144 | + | |
| 145 | +enum { | |
| 146 | + NDTA_UNSPEC, | |
| 147 | + NDTA_NAME, /* char *, unchangeable */ | |
| 148 | + NDTA_THRESH1, /* u32 */ | |
| 149 | + NDTA_THRESH2, /* u32 */ | |
| 150 | + NDTA_THRESH3, /* u32 */ | |
| 151 | + NDTA_CONFIG, /* struct ndt_config, read-only */ | |
| 152 | + NDTA_PARMS, /* nested TLV NDTPA_* */ | |
| 153 | + NDTA_STATS, /* struct ndt_stats, read-only */ | |
| 154 | + NDTA_GC_INTERVAL, /* u64, msecs */ | |
| 155 | + __NDTA_MAX | |
| 156 | +}; | |
| 157 | +#define NDTA_MAX (__NDTA_MAX - 1) | |
| 158 | + | |
| 159 | +#endif | |
| @@ -169,11 +169,6 @@ struct proto_ops { · 168 unmodified lines | ||
| 169 | 169 | struct net_proto_family { |
| 170 | 170 | int family; |
| 171 | 171 | int (*create)(struct socket *sock, int protocol); |
| 172 | − /* These are counters for the number of different methods of | |
| 173 | − each we support */ | |
| 174 | − short authentication; | |
| 175 | − short encryption; | |
| 176 | − short encrypt_net; | |
| 177 | 172 | struct module *owner; |
| 178 | 173 | }; |
| 179 | 174 | |
| @@ -181,8 +176,8 @@ struct iovec; · 1 unmodified line | ||
| 181 | 176 | struct kvec; |
| 182 | 177 | |
| 183 | 178 | extern int sock_wake_async(struct socket *sk, int how, int band); |
| 184 | −extern int sock_register(struct net_proto_family *fam); | |
| 185 | −extern int sock_unregister(int family); | |
| 179 | +extern int sock_register(const struct net_proto_family *fam); | |
| 180 | +extern void sock_unregister(int family); | |
| 186 | 181 | extern int sock_create(int family, int type, int proto, |
| 187 | 182 | struct socket **res); |
| 188 | 183 | extern int sock_create_kern(int family, int type, int proto, |
| @@ -208,6 +203,25 @@ extern int kernel_recvmsg(struct socket *sock, struct msghdr *msg, · 19 unmodified lines | ||
| 208 | 203 | struct kvec *vec, size_t num, |
| 209 | 204 | size_t len, int flags); |
| 210 | 205 | |
| 206 | +extern int kernel_bind(struct socket *sock, struct sockaddr *addr, | |
| 207 | + int addrlen); | |
| 208 | +extern int kernel_listen(struct socket *sock, int backlog); | |
| 209 | +extern int kernel_accept(struct socket *sock, struct socket **newsock, | |
| 210 | + int flags); | |
| 211 | +extern int kernel_connect(struct socket *sock, struct sockaddr *addr, | |
| 212 | + int addrlen, int flags); | |
| 213 | +extern int kernel_getsockname(struct socket *sock, struct sockaddr *addr, | |
| 214 | + int *addrlen); | |
| 215 | +extern int kernel_getpeername(struct socket *sock, struct sockaddr *addr, | |
| 216 | + int *addrlen); | |
| 217 | +extern int kernel_getsockopt(struct socket *sock, int level, int optname, | |
| 218 | + char *optval, int *optlen); | |
| 219 | +extern int kernel_setsockopt(struct socket *sock, int level, int optname, | |
| 220 | + char *optval, int optlen); | |
| 221 | +extern int kernel_sendpage(struct socket *sock, struct page *page, int offset, | |
| 222 | + size_t size, int flags); | |
| 223 | +extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg); | |
| 224 | + | |
| 211 | 225 | #ifndef CONFIG_SMP |
| 212 | 226 | #define SOCKOPS_WRAPPED(name) name |
| 213 | 227 | #define SOCKOPS_WRAP(name, fam) |
| @@ -976,7 +976,7 @@ extern void dev_mcast_init(void); · 975 unmodified lines | ||
| 976 | 976 | extern int netdev_max_backlog; |
| 977 | 977 | extern int weight_p; |
| 978 | 978 | extern int netdev_set_master(struct net_device *dev, struct net_device *master); |
| 979 | −extern int skb_checksum_help(struct sk_buff *skb, int inward); | |
| 979 | +extern int skb_checksum_help(struct sk_buff *skb); | |
| 980 | 980 | extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features); |
| 981 | 981 | #ifdef CONFIG_BUG |
| 982 | 982 | extern void netdev_rx_csum_fault(struct net_device *dev); |
| @@ -1012,7 +1012,7 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) · 29 unmodified lines | ||
| 1012 | 1012 | { |
| 1013 | 1013 | return skb_is_gso(skb) && |
| 1014 | 1014 | (!skb_gso_ok(skb, dev->features) || |
| 1015 | − unlikely(skb->ip_summed != CHECKSUM_HW)); | |
| 1015 | + unlikely(skb->ip_summed != CHECKSUM_PARTIAL)); | |
| 1016 | 1016 | } |
| 1017 | 1017 | |
| 1018 | 1018 | /* On bonding slaves other than the currently active slave, suppress |
| @@ -282,6 +282,12 @@ extern void nf_invalidate_cache(int pf); · 281 unmodified lines | ||
| 282 | 282 | Returns true or false. */ |
| 283 | 283 | extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); |
| 284 | 284 | |
| 285 | +extern u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, | |
| 286 | + u_int32_t csum); | |
| 287 | +extern u_int16_t nf_proto_csum_update(struct sk_buff *skb, | |
| 288 | + u_int32_t oldval, u_int32_t newval, | |
| 289 | + u_int16_t csum, int pseudohdr); | |
| 290 | + | |
| 285 | 291 | struct nf_afinfo { |
| 286 | 292 | unsigned short family; |
| 287 | 293 | unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook, |
| @@ -125,6 +125,10 @@ enum ip_conntrack_events · 124 unmodified lines | ||
| 125 | 125 | /* Counter highest bit has been set */ |
| 126 | 126 | IPCT_COUNTER_FILLING_BIT = 11, |
| 127 | 127 | IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT), |
| 128 | + | |
| 129 | + /* Mark is set */ | |
| 130 | + IPCT_MARK_BIT = 12, | |
| 131 | + IPCT_MARK = (1 << IPCT_MARK_BIT), | |
| 128 | 132 | }; |
| 129 | 133 | |
| 130 | 134 | enum ip_conntrack_expect_events { |
| @@ -49,6 +49,7 @@ struct ip_ct_tcp · 48 unmodified lines | ||
| 49 | 49 | u_int32_t last_seq; /* Last sequence number seen in dir */ |
| 50 | 50 | u_int32_t last_ack; /* Last sequence number seen in opposite dir */ |
| 51 | 51 | u_int32_t last_end; /* Last seq + len */ |
| 52 | + u_int16_t last_win; /* Last window advertisement seen in dir */ | |
| 52 | 53 | }; |
| 53 | 54 | |
| 54 | 55 | #endif /* __KERNEL__ */ |
| @@ -43,7 +43,7 @@ struct nfattr · 42 unmodified lines | ||
| 43 | 43 | u_int16_t nfa_len; |
| 44 | 44 | u_int16_t nfa_type; /* we use 15 bits for the type, and the highest |
| 45 | 45 | * bit to indicate whether the payload is nested */ |
| 46 | −} __attribute__ ((packed)); | |
| 46 | +}; | |
| 47 | 47 | |
| 48 | 48 | /* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from |
| 49 | 49 | * rtnetlink.h, it's time to put this in a generic file */ |
| @@ -79,7 +79,7 @@ struct nfgenmsg { · 29 unmodified lines | ||
| 79 | 79 | u_int8_t nfgen_family; /* AF_xxx */ |
| 80 | 80 | u_int8_t version; /* nfnetlink version */ |
| 81 | 81 | u_int16_t res_id; /* resource id */ |
| 82 | −} __attribute__ ((packed)); | |
| 82 | +}; | |
| 83 | 83 | |
| 84 | 84 | #define NFNETLINK_V0 0 |
| 85 | 85 | |
| @@ -19,18 +19,18 @@ struct nfulnl_msg_packet_hdr { · 18 unmodified lines | ||
| 19 | 19 | u_int16_t hw_protocol; /* hw protocol (network order) */ |
| 20 | 20 | u_int8_t hook; /* netfilter hook */ |
| 21 | 21 | u_int8_t _pad; |
| 22 | −} __attribute__ ((packed)); | |
| 22 | +}; | |
| 23 | 23 | |
| 24 | 24 | struct nfulnl_msg_packet_hw { |
| 25 | 25 | u_int16_t hw_addrlen; |
| 26 | 26 | u_int16_t _pad; |
| 27 | 27 | u_int8_t hw_addr[8]; |
| 28 | −} __attribute__ ((packed)); | |
| 28 | +}; | |
| 29 | 29 | |
| 30 | 30 | struct nfulnl_msg_packet_timestamp { |
| 31 | 31 | aligned_u64 sec; |
| 32 | 32 | aligned_u64 usec; |
| 33 | −} __attribute__ ((packed)); | |
| 33 | +}; | |
| 34 | 34 | |
| 35 | 35 | #define NFULNL_PREFIXLEN 30 /* just like old log target */ |
| 36 | 36 | |
| @@ -22,12 +22,12 @@ struct nfqnl_msg_packet_hw { · 21 unmodified lines | ||
| 22 | 22 | u_int16_t hw_addrlen; |
| 23 | 23 | u_int16_t _pad; |
| 24 | 24 | u_int8_t hw_addr[8]; |
| 25 | −} __attribute__ ((packed)); | |
| 25 | +}; | |
| 26 | 26 | |
| 27 | 27 | struct nfqnl_msg_packet_timestamp { |
| 28 | 28 | aligned_u64 sec; |
| 29 | 29 | aligned_u64 usec; |
| 30 | −} __attribute__ ((packed)); | |
| 30 | +}; | |
| 31 | 31 | |
| 32 | 32 | enum nfqnl_attr_type { |
| 33 | 33 | NFQA_UNSPEC, |
| @@ -49,7 +49,7 @@ enum nfqnl_attr_type { · 15 unmodified lines | ||
| 49 | 49 | struct nfqnl_msg_verdict_hdr { |
| 50 | 50 | u_int32_t verdict; |
| 51 | 51 | u_int32_t id; |
| 52 | −} __attribute__ ((packed)); | |
| 52 | +}; | |
| 53 | 53 | |
| 54 | 54 | |
| 55 | 55 | enum nfqnl_msg_config_cmds { |
| @@ -64,7 +64,7 @@ struct nfqnl_msg_config_cmd { · 8 unmodified lines | ||
| 64 | 64 | u_int8_t command; /* nfqnl_msg_config_cmds */ |
| 65 | 65 | u_int8_t _pad; |
| 66 | 66 | u_int16_t pf; /* AF_xxx for PF_[UN]BIND */ |
| 67 | −} __attribute__ ((packed)); | |
| 67 | +}; | |
| 68 | 68 | |
| 69 | 69 | enum nfqnl_config_mode { |
| 70 | 70 | NFQNL_COPY_NONE, |
| @@ -138,16 +138,6 @@ struct xt_counters_info · 137 unmodified lines | ||
| 138 | 138 | |
| 139 | 139 | #include <linux/netdevice.h> |
| 140 | 140 | |
| 141 | −#define ASSERT_READ_LOCK(x) | |
| 142 | −#define ASSERT_WRITE_LOCK(x) | |
| 143 | −#include <linux/netfilter_ipv4/listhelp.h> | |
| 144 | − | |
| 145 | −#ifdef CONFIG_COMPAT | |
| 146 | −#define COMPAT_TO_USER 1 | |
| 147 | −#define COMPAT_FROM_USER -1 | |
| 148 | −#define COMPAT_CALC_SIZE 0 | |
| 149 | −#endif | |
| 150 | − | |
| 151 | 141 | struct xt_match |
| 152 | 142 | { |
| 153 | 143 | struct list_head list; |
| @@ -174,21 +164,24 @@ struct xt_match · 20 unmodified lines | ||
| 174 | 164 | const void *ip, |
| 175 | 165 | const struct xt_match *match, |
| 176 | 166 | void *matchinfo, |
| 177 | − unsigned int matchinfosize, | |
| 178 | 167 | unsigned int hook_mask); |
| 179 | 168 | |
| 180 | 169 | /* Called when entry of this type deleted. */ |
| 181 | − void (*destroy)(const struct xt_match *match, void *matchinfo, | |
| 182 | − unsigned int matchinfosize); | |
| 170 | + void (*destroy)(const struct xt_match *match, void *matchinfo); | |
| 183 | 171 | |
| 184 | 172 | /* Called when userspace align differs from kernel space one */ |
| 185 | − int (*compat)(void *match, void **dstptr, int *size, int convert); | |
| 173 | + void (*compat_from_user)(void *dst, void *src); | |
| 174 | + int (*compat_to_user)(void __user *dst, void *src); | |
| 186 | 175 | |
| 187 | 176 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ |
| 188 | 177 | struct module *me; |
| 189 | 178 | |
| 179 | + /* Free to use by each match */ | |
| 180 | + unsigned long data; | |
| 181 | + | |
| 190 | 182 | char *table; |
| 191 | 183 | unsigned int matchsize; |
| 184 | + unsigned int compatsize; | |
| 192 | 185 | unsigned int hooks; |
| 193 | 186 | unsigned short proto; |
| 194 | 187 | |
| @@ -211,8 +204,7 @@ struct xt_target · 16 unmodified lines | ||
| 211 | 204 | const struct net_device *out, |
| 212 | 205 | unsigned int hooknum, |
| 213 | 206 | const struct xt_target *target, |
| 214 | − const void *targinfo, | |
| 215 | − void *userdata); | |
| 207 | + const void *targinfo); | |
| 216 | 208 | |
| 217 | 209 | /* Called when user tries to insert an entry of this type: |
| 218 | 210 | hook_mask is a bitmask of hooks from which it can be |
| @@ -222,21 +214,21 @@ struct xt_target · 3 unmodified lines | ||
| 222 | 214 | const void *entry, |
| 223 | 215 | const struct xt_target *target, |
| 224 | 216 | void *targinfo, |
| 225 | − unsigned int targinfosize, | |
| 226 | 217 | unsigned int hook_mask); |
| 227 | 218 | |
| 228 | 219 | /* Called when entry of this type deleted. */ |
| 229 | − void (*destroy)(const struct xt_target *target, void *targinfo, | |
| 230 | − unsigned int targinfosize); | |
| 220 | + void (*destroy)(const struct xt_target *target, void *targinfo); | |
| 231 | 221 | |
| 232 | 222 | /* Called when userspace align differs from kernel space one */ |
| 233 | − int (*compat)(void *target, void **dstptr, int *size, int convert); | |
| 223 | + void (*compat_from_user)(void *dst, void *src); | |
| 224 | + int (*compat_to_user)(void __user *dst, void *src); | |
| 234 | 225 | |
| 235 | 226 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ |
| 236 | 227 | struct module *me; |
| 237 | 228 | |
| 238 | 229 | char *table; |
| 239 | 230 | unsigned int targetsize; |
| 231 | + unsigned int compatsize; | |
| 240 | 232 | unsigned int hooks; |
| 241 | 233 | unsigned short proto; |
| 242 | 234 | |
| @@ -290,8 +282,13 @@ struct xt_table_info · 47 unmodified lines | ||
| 290 | 282 | |
| 291 | 283 | extern int xt_register_target(struct xt_target *target); |
| 292 | 284 | extern void xt_unregister_target(struct xt_target *target); |
| 285 | +extern int xt_register_targets(struct xt_target *target, unsigned int n); | |
| 286 | +extern void xt_unregister_targets(struct xt_target *target, unsigned int n); | |
| 287 | + | |
| 293 | 288 | extern int xt_register_match(struct xt_match *target); |
| 294 | 289 | extern void xt_unregister_match(struct xt_match *target); |
| 290 | +extern int xt_register_matches(struct xt_match *match, unsigned int n); | |
| 291 | +extern void xt_unregister_matches(struct xt_match *match, unsigned int n); | |
| 295 | 292 | |
| 296 | 293 | extern int xt_check_match(const struct xt_match *match, unsigned short family, |
| 297 | 294 | unsigned int size, const char *table, unsigned int hook, |
| @@ -388,9 +385,18 @@ struct compat_xt_counters_info · 90 unmodified lines | ||
| 388 | 385 | |
| 389 | 386 | extern void xt_compat_lock(int af); |
| 390 | 387 | extern void xt_compat_unlock(int af); |
| 391 | −extern int xt_compat_match(void *match, void **dstptr, int *size, int convert); | |
| 392 | −extern int xt_compat_target(void *target, void **dstptr, int *size, | |
| 393 | − int convert); | |
| 388 | + | |
| 389 | +extern int xt_compat_match_offset(struct xt_match *match); | |
| 390 | +extern void xt_compat_match_from_user(struct xt_entry_match *m, | |
| 391 | + void **dstptr, int *size); | |
| 392 | +extern int xt_compat_match_to_user(struct xt_entry_match *m, | |
| 393 | + void * __user *dstptr, int *size); | |
| 394 | + | |
| 395 | +extern int xt_compat_target_offset(struct xt_target *target); | |
| 396 | +extern void xt_compat_target_from_user(struct xt_entry_target *t, | |
| 397 | + void **dstptr, int *size); | |
| 398 | +extern int xt_compat_target_to_user(struct xt_entry_target *t, | |
| 399 | + void * __user *dstptr, int *size); | |
| 394 | 400 | |
| 395 | 401 | #endif /* CONFIG_COMPAT */ |
| 396 | 402 | #endif /* __KERNEL__ */ |
| @@ -0,0 +1,20 @@ | ||
| 1 | +/* x_tables module for setting the IPv4/IPv6 DSCP field | |
| 2 | + * | |
| 3 | + * (C) 2002 Harald Welte <laforge@gnumonks.org> | |
| 4 | + * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com> | |
| 5 | + * This software is distributed under GNU GPL v2, 1991 | |
| 6 | + * | |
| 7 | + * See RFC2474 for a description of the DSCP field within the IP Header. | |
| 8 | + * | |
| 9 | + * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp | |
| 10 | +*/ | |
| 11 | +#ifndef _XT_DSCP_TARGET_H | |
| 12 | +#define _XT_DSCP_TARGET_H | |
| 13 | +#include <linux/netfilter/xt_dscp.h> | |
| 14 | + | |
| 15 | +/* target info */ | |
| 16 | +struct xt_DSCP_info { | |
| 17 | + u_int8_t dscp; | |
| 18 | +}; | |
| 19 | + | |
| 20 | +#endif /* _XT_DSCP_TARGET_H */ | |
| @@ -0,0 +1,23 @@ | ||
| 1 | +/* x_tables module for matching the IPv4/IPv6 DSCP field | |
| 2 | + * | |
| 3 | + * (C) 2002 Harald Welte <laforge@gnumonks.org> | |
| 4 | + * This software is distributed under GNU GPL v2, 1991 | |
| 5 | + * | |
| 6 | + * See RFC2474 for a description of the DSCP field within the IP Header. | |
| 7 | + * | |
| 8 | + * xt_dscp.h,v 1.3 2002/08/05 19:00:21 laforge Exp | |
| 9 | +*/ | |
| 10 | +#ifndef _XT_DSCP_H | |
| 11 | +#define _XT_DSCP_H | |
| 12 | + | |
| 13 | +#define XT_DSCP_MASK 0xfc /* 11111100 */ | |
| 14 | +#define XT_DSCP_SHIFT 2 | |
| 15 | +#define XT_DSCP_MAX 0x3f /* 00111111 */ | |
| 16 | + | |
| 17 | +/* match info */ | |
| 18 | +struct xt_dscp_info { | |
| 19 | + u_int8_t dscp; | |
| 20 | + u_int8_t invert; | |
| 21 | +}; | |
| 22 | + | |
| 23 | +#endif /* _XT_DSCP_H */ | |
| @@ -248,8 +248,7 @@ extern unsigned int arpt_do_table(struct sk_buff **pskb, · 247 unmodified lines | ||
| 248 | 248 | unsigned int hook, |
| 249 | 249 | const struct net_device *in, |
| 250 | 250 | const struct net_device *out, |
| 251 | − struct arpt_table *table, | |
| 252 | − void *userdata); | |
| 251 | + struct arpt_table *table); | |
| 253 | 252 | |
| 254 | 253 | #define ARPT_ALIGN(s) (((s) + (__alignof__(struct arpt_entry)-1)) & ~(__alignof__(struct arpt_entry)-1)) |
| 255 | 254 | #endif /*__KERNEL__*/ |
| @@ -5,9 +5,8 @@ · 4 unmodified lines | ||
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | #include <linux/netfilter.h> |
| 8 | −#if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER) | |
| 9 | 8 | #include <linux/if_ether.h> |
| 10 | −#endif | |
| 9 | +#include <linux/if_vlan.h> | |
| 11 | 10 | |
| 12 | 11 | /* Bridge Hooks */ |
| 13 | 12 | /* After promisc drops, checksum checks. */ |
| @@ -47,40 +46,20 @@ enum nf_br_hook_priorities { · 33 unmodified lines | ||
| 47 | 46 | |
| 48 | 47 | |
| 49 | 48 | /* Only used in br_forward.c */ |
| 50 | −static inline | |
| 51 | −int nf_bridge_maybe_copy_header(struct sk_buff *skb) | |
| 49 | +extern int nf_bridge_copy_header(struct sk_buff *skb); | |
| 50 | +static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb) | |
| 52 | 51 | { |
| 53 | − int err; | |
| 54 | − | |
| 55 | − if (skb->nf_bridge) { | |
| 56 | − if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | |
| 57 | − err = skb_cow(skb, 18); | |
| 58 | − if (err) | |
| 59 | − return err; | |
| 60 | − memcpy(skb->data - 18, skb->nf_bridge->data, 18); | |
| 61 | − skb_push(skb, 4); | |
| 62 | − } else { | |
| 63 | − err = skb_cow(skb, 16); | |
| 64 | − if (err) | |
| 65 | − return err; | |
| 66 | − memcpy(skb->data - 16, skb->nf_bridge->data, 16); | |
| 67 | − } | |
| 68 | − } | |
| 69 | − return 0; | |
| 52 | + if (skb->nf_bridge) | |
| 53 | + return nf_bridge_copy_header(skb); | |
| 54 | + return 0; | |
| 70 | 55 | } |
| 71 | 56 | |
| 72 | 57 | /* This is called by the IP fragmenting code and it ensures there is |
| 73 | 58 | * enough room for the encapsulating header (if there is one). */ |
| 74 | −static inline | |
| 75 | −int nf_bridge_pad(struct sk_buff *skb) | |
| 59 | +static inline int nf_bridge_pad(const struct sk_buff *skb) | |
| 76 | 60 | { |
| 77 | − if (skb->protocol == __constant_htons(ETH_P_IP)) | |
| 78 | − return 0; | |
| 79 | − if (skb->nf_bridge) { | |
| 80 | − if (skb->protocol == __constant_htons(ETH_P_8021Q)) | |
| 81 | − return 4; | |
| 82 | − } | |
| 83 | − return 0; | |
| 61 | + return (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q)) | |
| 62 | + ? VLAN_HLEN : 0; | |
| 84 | 63 | } |
| 85 | 64 | |
| 86 | 65 | struct bridge_skb_cb { |
| @@ -90,6 +69,9 @@ struct bridge_skb_cb { · 3 unmodified lines | ||
| 90 | 69 | }; |
| 91 | 70 | |
| 92 | 71 | extern int brnf_deferred_hooks; |
| 72 | +#else | |
| 73 | +#define nf_bridge_maybe_copy_header(skb) (0) | |
| 74 | +#define nf_bridge_pad(skb) (0) | |
| 93 | 75 | #endif /* CONFIG_BRIDGE_NETFILTER */ |
| 94 | 76 | |
| 95 | 77 | #endif /* __KERNEL__ */ |
| @@ -25,6 +25,8 @@ struct ip_conntrack_helper · 24 unmodified lines | ||
| 25 | 25 | struct ip_conntrack *ct, |
| 26 | 26 | enum ip_conntrack_info conntrackinfo); |
| 27 | 27 | |
| 28 | + void (*destroy)(struct ip_conntrack *ct); | |
| 29 | + | |
| 28 | 30 | int (*to_nfattr)(struct sk_buff *skb, const struct ip_conntrack *ct); |
| 29 | 31 | }; |
| 30 | 32 | |
| @@ -31,8 +31,8 @@ struct ip_ct_pptp_master { · 30 unmodified lines | ||
| 31 | 31 | /* everything below is going to be per-expectation in newnat, |
| 32 | 32 | * since there could be more than one call within one session */ |
| 33 | 33 | enum pptp_ctrlcall_state cstate; /* call state */ |
| 34 | − u_int16_t pac_call_id; /* call id of PAC, host byte order */ | |
| 35 | − u_int16_t pns_call_id; /* call id of PNS, host byte order */ | |
| 34 | + __be16 pac_call_id; /* call id of PAC, host byte order */ | |
| 35 | + __be16 pns_call_id; /* call id of PNS, host byte order */ | |
| 36 | 36 | |
| 37 | 37 | /* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack |
| 38 | 38 | * and therefore imposes a fixed limit on the number of maps */ |
| @@ -42,8 +42,8 @@ struct ip_ct_pptp_master { · 3 unmodified lines | ||
| 42 | 42 | /* conntrack_expect private member */ |
| 43 | 43 | struct ip_ct_pptp_expect { |
| 44 | 44 | enum pptp_ctrlcall_state cstate; /* call state */ |
| 45 | − u_int16_t pac_call_id; /* call id of PAC */ | |
| 46 | − u_int16_t pns_call_id; /* call id of PNS */ | |
| 45 | + __be16 pac_call_id; /* call id of PAC */ | |
| 46 | + __be16 pns_call_id; /* call id of PNS */ | |
| 47 | 47 | }; |
| 48 | 48 | |
| 49 | 49 | |
| @@ -107,8 +107,7 @@ struct PptpControlHeader { · 57 unmodified lines | ||
| 107 | 107 | |
| 108 | 108 | struct PptpStartSessionRequest { |
| 109 | 109 | __be16 protocolVersion; |
| 110 | − __u8 reserved1; | |
| 111 | − __u8 reserved2; | |
| 110 | + __u16 reserved1; | |
| 112 | 111 | __be32 framingCapability; |
| 113 | 112 | __be32 bearerCapability; |
| 114 | 113 | __be16 maxChannels; |
| @@ -143,6 +142,8 @@ struct PptpStartSessionReply { · 28 unmodified lines | ||
| 143 | 142 | |
| 144 | 143 | struct PptpStopSessionRequest { |
| 145 | 144 | __u8 reason; |
| 145 | + __u8 reserved1; | |
| 146 | + __u16 reserved2; | |
| 146 | 147 | }; |
| 147 | 148 | |
| 148 | 149 | /* PptpStopSessionResultCode */ |
| @@ -152,6 +153,7 @@ struct PptpStopSessionRequest { · 3 unmodified lines | ||
| 152 | 153 | struct PptpStopSessionReply { |
| 153 | 154 | __u8 resultCode; |
| 154 | 155 | __u8 generalErrorCode; |
| 156 | + __u16 reserved1; | |
| 155 | 157 | }; |
| 156 | 158 | |
| 157 | 159 | struct PptpEchoRequest { |
| @@ -188,9 +190,8 @@ struct PptpOutCallRequest { · 30 unmodified lines | ||
| 188 | 190 | __be32 framingType; |
| 189 | 191 | __be16 packetWindow; |
| 190 | 192 | __be16 packetProcDelay; |
| 191 | − __u16 reserved1; | |
| 192 | 193 | __be16 phoneNumberLength; |
| 193 | − __u16 reserved2; | |
| 194 | + __u16 reserved1; | |
| 194 | 195 | __u8 phoneNumber[64]; |
| 195 | 196 | __u8 subAddress[64]; |
| 196 | 197 | }; |
| @@ -285,19 +286,19 @@ struct PptpSetLinkInfo { · 88 unmodified lines | ||
| 285 | 286 | }; |
| 286 | 287 | |
| 287 | 288 | union pptp_ctrl_union { |
| 288 | − struct PptpStartSessionRequest sreq; | |
| 289 | − struct PptpStartSessionReply srep; | |
| 290 | − struct PptpStopSessionRequest streq; | |
| 291 | − struct PptpStopSessionReply strep; | |
| 292 | − struct PptpOutCallRequest ocreq; | |
| 293 | − struct PptpOutCallReply ocack; | |
| 294 | − struct PptpInCallRequest icreq; | |
| 295 | − struct PptpInCallReply icack; | |
| 296 | − struct PptpInCallConnected iccon; | |
| 297 | − struct PptpClearCallRequest clrreq; | |
| 298 | − struct PptpCallDisconnectNotify disc; | |
| 299 | − struct PptpWanErrorNotify wanerr; | |
| 300 | − struct PptpSetLinkInfo setlink; | |
| 289 | + struct PptpStartSessionRequest sreq; | |
| 290 | + struct PptpStartSessionReply srep; | |
| 291 | + struct PptpStopSessionRequest streq; | |
| 292 | + struct PptpStopSessionReply strep; | |
| 293 | + struct PptpOutCallRequest ocreq; | |
| 294 | + struct PptpOutCallReply ocack; | |
| 295 | + struct PptpInCallRequest icreq; | |
| 296 | + struct PptpInCallReply icack; | |
| 297 | + struct PptpInCallConnected iccon; | |
| 298 | + struct PptpClearCallRequest clrreq; | |
| 299 | + struct PptpCallDisconnectNotify disc; | |
| 300 | + struct PptpWanErrorNotify wanerr; | |
| 301 | + struct PptpSetLinkInfo setlink; | |
| 301 | 302 | }; |
| 302 | 303 | |
| 303 | 304 | extern int |
| @@ -314,7 +315,7 @@ extern int · 10 unmodified lines | ||
| 314 | 315 | struct PptpControlHeader *ctlh, |
| 315 | 316 | union pptp_ctrl_union *pptpReq); |
| 316 | 317 | |
| 317 | −extern int | |
| 318 | +extern void | |
| 318 | 319 | (*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig, |
| 319 | 320 | struct ip_conntrack_expect *exp_reply); |
| 320 | 321 | |
| @@ -49,18 +49,18 @@ struct gre_hdr { · 48 unmodified lines | ||
| 49 | 49 | #else |
| 50 | 50 | #error "Adjust your <asm/byteorder.h> defines" |
| 51 | 51 | #endif |
| 52 | − __u16 protocol; | |
| 52 | + __be16 protocol; | |
| 53 | 53 | }; |
| 54 | 54 | |
| 55 | 55 | /* modified GRE header for PPTP */ |
| 56 | 56 | struct gre_hdr_pptp { |
| 57 | − __u8 flags; /* bitfield */ | |
| 58 | − __u8 version; /* should be GRE_VERSION_PPTP */ | |
| 59 | − __u16 protocol; /* should be GRE_PROTOCOL_PPTP */ | |
| 60 | − __u16 payload_len; /* size of ppp payload, not inc. gre header */ | |
| 61 | − __u16 call_id; /* peer's call_id for this session */ | |
| 62 | − __u32 seq; /* sequence number. Present if S==1 */ | |
| 63 | − __u32 ack; /* seq number of highest packet recieved by */ | |
| 57 | + __u8 flags; /* bitfield */ | |
| 58 | + __u8 version; /* should be GRE_VERSION_PPTP */ | |
| 59 | + __be16 protocol; /* should be GRE_PROTOCOL_PPTP */ | |
| 60 | + __be16 payload_len; /* size of ppp payload, not inc. gre header */ | |
| 61 | + __be16 call_id; /* peer's call_id for this session */ | |
| 62 | + __be32 seq; /* sequence number. Present if S==1 */ | |
| 63 | + __be32 ack; /* seq number of highest packet recieved by */ | |
| 64 | 64 | /* sender in this session */ |
| 65 | 65 | }; |
| 66 | 66 | |
| @@ -92,13 +92,13 @@ void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct); · 25 unmodified lines | ||
| 92 | 92 | |
| 93 | 93 | |
| 94 | 94 | /* get pointer to gre key, if present */ |
| 95 | −static inline u_int32_t *gre_key(struct gre_hdr *greh) | |
| 95 | +static inline __be32 *gre_key(struct gre_hdr *greh) | |
| 96 | 96 | { |
| 97 | 97 | if (!greh->key) |
| 98 | 98 | return NULL; |
| 99 | 99 | if (greh->csum || greh->routing) |
| 100 | − return (u_int32_t *) (greh+sizeof(*greh)+4); | |
| 101 | − return (u_int32_t *) (greh+sizeof(*greh)); | |
| 100 | + return (__be32 *) (greh+sizeof(*greh)+4); | |
| 101 | + return (__be32 *) (greh+sizeof(*greh)); | |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | 104 | /* get pointer ot gre csum, if present */ |
| @@ -72,10 +72,6 @@ extern unsigned int ip_nat_setup_info(struct ip_conntrack *conntrack, · 71 unmodified lines | ||
| 72 | 72 | extern int ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple, |
| 73 | 73 | const struct ip_conntrack *ignored_conntrack); |
| 74 | 74 | |
| 75 | −/* Calculate relative checksum. */ | |
| 76 | −extern u_int16_t ip_nat_cheat_check(u_int32_t oldvalinv, | |
| 77 | − u_int32_t newval, | |
| 78 | − u_int16_t oldcheck); | |
| 79 | 75 | #else /* !__KERNEL__: iptables wants this to compile. */ |
| 80 | 76 | #define ip_nat_multi_range ip_nat_multi_range_compat |
| 81 | 77 | #endif /*__KERNEL__*/ |
| @@ -11,8 +11,8 @@ extern unsigned int ip_nat_packet(struct ip_conntrack *ct, · 10 unmodified lines | ||
| 11 | 11 | unsigned int hooknum, |
| 12 | 12 | struct sk_buff **pskb); |
| 13 | 13 | |
| 14 | −extern int ip_nat_icmp_reply_translation(struct sk_buff **pskb, | |
| 15 | − struct ip_conntrack *ct, | |
| 16 | − enum ip_nat_manip_type manip, | |
| 17 | − enum ip_conntrack_dir dir); | |
| 14 | +extern int ip_nat_icmp_reply_translation(struct ip_conntrack *ct, | |
| 15 | + enum ip_conntrack_info ctinfo, | |
| 16 | + unsigned int hooknum, | |
| 17 | + struct sk_buff **pskb); | |
| 18 | 18 | #endif /* _IP_NAT_CORE_H */ |
| @@ -4,8 +4,8 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | /* conntrack private data */ |
| 6 | 6 | struct ip_nat_pptp { |
| 7 | − u_int16_t pns_call_id; /* NAT'ed PNS call id */ | |
| 8 | − u_int16_t pac_call_id; /* NAT'ed PAC call id */ | |
| 7 | + __be16 pns_call_id; /* NAT'ed PNS call id */ | |
| 8 | + __be16 pac_call_id; /* NAT'ed PAC call id */ | |
| 9 | 9 | }; |
| 10 | 10 | |
| 11 | 11 | #endif /* _NAT_PPTP_H */ |
| @@ -312,8 +312,7 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb, · 311 unmodified lines | ||
| 312 | 312 | unsigned int hook, |
| 313 | 313 | const struct net_device *in, |
| 314 | 314 | const struct net_device *out, |
| 315 | − struct ipt_table *table, | |
| 316 | − void *userdata); | |
| 315 | + struct ipt_table *table); | |
| 317 | 316 | |
| 318 | 317 | #define IPT_ALIGN(s) XT_ALIGN(s) |
| 319 | 318 | |
| @@ -11,10 +11,8 @@ · 10 unmodified lines | ||
| 11 | 11 | #ifndef _IPT_DSCP_TARGET_H |
| 12 | 12 | #define _IPT_DSCP_TARGET_H |
| 13 | 13 | #include <linux/netfilter_ipv4/ipt_dscp.h> |
| 14 | +#include <linux/netfilter/xt_DSCP.h> | |
| 14 | 15 | |
| 15 | −/* target info */ | |
| 16 | −struct ipt_DSCP_info { | |
| 17 | − u_int8_t dscp; | |
| 18 | −}; | |
| 16 | +#define ipt_DSCP_info xt_DSCP_info | |
| 19 | 17 | |
| 20 | 18 | #endif /* _IPT_DSCP_TARGET_H */ |
| @@ -10,14 +10,12 @@ · 9 unmodified lines | ||
| 10 | 10 | #ifndef _IPT_DSCP_H |
| 11 | 11 | #define _IPT_DSCP_H |
| 12 | 12 | |
| 13 | −#define IPT_DSCP_MASK 0xfc /* 11111100 */ | |
| 14 | −#define IPT_DSCP_SHIFT 2 | |
| 15 | −#define IPT_DSCP_MAX 0x3f /* 00111111 */ | |
| 13 | +#include <linux/netfilter/xt_dscp.h> | |
| 16 | 14 | |
| 17 | −/* match info */ | |
| 18 | −struct ipt_dscp_info { | |
| 19 | − u_int8_t dscp; | |
| 20 | − u_int8_t invert; | |
| 21 | −}; | |
| 15 | +#define IPT_DSCP_MASK XT_DSCP_MASK | |
| 16 | +#define IPT_DSCP_SHIFT XT_DSCP_SHIFT | |
| 17 | +#define IPT_DSCP_MAX XT_DSCP_MAX | |
| 18 | + | |
| 19 | +#define ipt_dscp_info xt_dscp_info | |
| 22 | 20 | |
| 23 | 21 | #endif /* _IPT_DSCP_H */ |
| @@ -1,123 +0,0 @@ | ||
| 1 | −#ifndef _LISTHELP_H | |
| 2 | −#define _LISTHELP_H | |
| 3 | −#include <linux/list.h> | |
| 4 | − | |
| 5 | −/* Header to do more comprehensive job than linux/list.h; assume list | |
| 6 | − is first entry in structure. */ | |
| 7 | − | |
| 8 | −/* Return pointer to first true entry, if any, or NULL. A macro | |
| 9 | − required to allow inlining of cmpfn. */ | |
| 10 | −#define LIST_FIND(head, cmpfn, type, args...) \ | |
| 11 | −({ \ | |
| 12 | − const struct list_head *__i, *__j = NULL; \ | |
| 13 | − \ | |
| 14 | − ASSERT_READ_LOCK(head); \ | |
| 15 | − list_for_each(__i, (head)) \ | |
| 16 | − if (cmpfn((const type)__i , ## args)) { \ | |
| 17 | − __j = __i; \ | |
| 18 | − break; \ | |
| 19 | − } \ | |
| 20 | − (type)__j; \ | |
| 21 | −}) | |
| 22 | − | |
| 23 | −#define LIST_FIND_W(head, cmpfn, type, args...) \ | |
| 24 | −({ \ | |
| 25 | − const struct list_head *__i, *__j = NULL; \ | |
| 26 | − \ | |
| 27 | − ASSERT_WRITE_LOCK(head); \ | |
| 28 | − list_for_each(__i, (head)) \ | |
| 29 | − if (cmpfn((type)__i , ## args)) { \ | |
| 30 | − __j = __i; \ | |
| 31 | − break; \ | |
| 32 | − } \ | |
| 33 | − (type)__j; \ | |
| 34 | −}) | |
| 35 | − | |
| 36 | −/* Just like LIST_FIND but we search backwards */ | |
| 37 | −#define LIST_FIND_B(head, cmpfn, type, args...) \ | |
| 38 | −({ \ | |
| 39 | − const struct list_head *__i, *__j = NULL; \ | |
| 40 | − \ | |
| 41 | − ASSERT_READ_LOCK(head); \ | |
| 42 | − list_for_each_prev(__i, (head)) \ | |
| 43 | − if (cmpfn((const type)__i , ## args)) { \ | |
| 44 | − __j = __i; \ | |
| 45 | − break; \ | |
| 46 | − } \ | |
| 47 | − (type)__j; \ | |
| 48 | −}) | |
| 49 | − | |
| 50 | −static inline int | |
| 51 | −__list_cmp_same(const void *p1, const void *p2) { return p1 == p2; } | |
| 52 | − | |
| 53 | −/* Is this entry in the list? */ | |
| 54 | −static inline int | |
| 55 | −list_inlist(struct list_head *head, const void *entry) | |
| 56 | −{ | |
| 57 | − return LIST_FIND(head, __list_cmp_same, void *, entry) != NULL; | |
| 58 | −} | |
| 59 | − | |
| 60 | −/* Delete from list. */ | |
| 61 | −#ifdef CONFIG_NETFILTER_DEBUG | |
| 62 | −#define LIST_DELETE(head, oldentry) \ | |
| 63 | −do { \ | |
| 64 | − ASSERT_WRITE_LOCK(head); \ | |
| 65 | − if (!list_inlist(head, oldentry)) \ | |
| 66 | − printk("LIST_DELETE: %s:%u `%s'(%p) not in %s.\n", \ | |
| 67 | − __FILE__, __LINE__, #oldentry, oldentry, #head); \ | |
| 68 | − else list_del((struct list_head *)oldentry); \ | |
| 69 | −} while(0) | |
| 70 | −#else | |
| 71 | −#define LIST_DELETE(head, oldentry) list_del((struct list_head *)oldentry) | |
| 72 | −#endif | |
| 73 | − | |
| 74 | −/* Append. */ | |
| 75 | −static inline void | |
| 76 | −list_append(struct list_head *head, void *new) | |
| 77 | −{ | |
| 78 | − ASSERT_WRITE_LOCK(head); | |
| 79 | − list_add((new), (head)->prev); | |
| 80 | −} | |
| 81 | − | |
| 82 | −/* Prepend. */ | |
| 83 | −static inline void | |
| 84 | −list_prepend(struct list_head *head, void *new) | |
| 85 | −{ | |
| 86 | − ASSERT_WRITE_LOCK(head); | |
| 87 | − list_add(new, head); | |
| 88 | −} | |
| 89 | − | |
| 90 | −/* Insert according to ordering function; insert before first true. */ | |
| 91 | −#define LIST_INSERT(head, new, cmpfn) \ | |
| 92 | −do { \ | |
| 93 | − struct list_head *__i; \ | |
| 94 | − ASSERT_WRITE_LOCK(head); \ | |
| 95 | − list_for_each(__i, (head)) \ | |
| 96 | − if ((new), (typeof (new))__i) \ | |
| 97 | − break; \ | |
| 98 | − list_add((struct list_head *)(new), __i->prev); \ | |
| 99 | −} while(0) | |
| 100 | − | |
| 101 | −/* If the field after the list_head is a nul-terminated string, you | |
| 102 | − can use these functions. */ | |
| 103 | −static inline int __list_cmp_name(const void *i, const char *name) | |
| 104 | −{ | |
| 105 | − return strcmp(name, i+sizeof(struct list_head)) == 0; | |
| 106 | −} | |
| 107 | − | |
| 108 | −/* Returns false if same name already in list, otherwise does insert. */ | |
| 109 | −static inline int | |
| 110 | −list_named_insert(struct list_head *head, void *new) | |
| 111 | −{ | |
| 112 | − if (LIST_FIND(head, __list_cmp_name, void *, | |
| 113 | − new + sizeof(struct list_head))) | |
| 114 | − return 0; | |
| 115 | − list_prepend(head, new); | |
| 116 | − return 1; | |
| 117 | −} | |
| 118 | − | |
| 119 | −/* Find this named element in the list. */ | |
| 120 | −#define list_named_find(head, name) \ | |
| 121 | −LIST_FIND(head, __list_cmp_name, void *, name) | |
| 122 | − | |
| 123 | −#endif /*_LISTHELP_H*/ | |
| @@ -73,6 +73,7 @@ enum nf_ip6_hook_priorities { · 72 unmodified lines | ||
| 73 | 73 | }; |
| 74 | 74 | |
| 75 | 75 | #ifdef CONFIG_NETFILTER |
| 76 | +extern int ip6_route_me_harder(struct sk_buff *skb); | |
| 76 | 77 | extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, |
| 77 | 78 | unsigned int dataoff, u_int8_t protocol); |
| 78 | 79 | |
| @@ -300,8 +300,7 @@ extern unsigned int ip6t_do_table(struct sk_buff **pskb, · 299 unmodified lines | ||
| 300 | 300 | unsigned int hook, |
| 301 | 301 | const struct net_device *in, |
| 302 | 302 | const struct net_device *out, |
| 303 | − struct ip6t_table *table, | |
| 304 | − void *userdata); | |
| 303 | + struct ip6t_table *table); | |
| 305 | 304 | |
| 306 | 305 | /* Check for an extension */ |
| 307 | 306 | extern int ip6t_ext_hdr(u8 nexthdr); |
| @@ -1,33 +0,0 @@ | ||
| 1 | −/* Internal logging interface, which relies on the real | |
| 2 | − LOG target modules */ | |
| 3 | −#ifndef __LINUX_NETFILTER_LOGGING_H | |
| 4 | −#define __LINUX_NETFILTER_LOGGING_H | |
| 5 | − | |
| 6 | −#ifdef __KERNEL__ | |
| 7 | −#include <asm/atomic.h> | |
| 8 | − | |
| 9 | −struct nf_logging_t { | |
| 10 | − void (*nf_log_packet)(struct sk_buff **pskb, | |
| 11 | − unsigned int hooknum, | |
| 12 | − const struct net_device *in, | |
| 13 | − const struct net_device *out, | |
| 14 | − const char *prefix); | |
| 15 | − void (*nf_log)(char *pfh, size_t len, | |
| 16 | − const char *prefix); | |
| 17 | −}; | |
| 18 | − | |
| 19 | −extern void nf_log_register(int pf, const struct nf_logging_t *logging); | |
| 20 | −extern void nf_log_unregister(int pf, const struct nf_logging_t *logging); | |
| 21 | − | |
| 22 | −extern void nf_log_packet(int pf, | |
| 23 | − struct sk_buff **pskb, | |
| 24 | − unsigned int hooknum, | |
| 25 | − const struct net_device *in, | |
| 26 | − const struct net_device *out, | |
| 27 | − const char *fmt, ...); | |
| 28 | −extern void nf_log(int pf, | |
| 29 | − char *pfh, size_t len, | |
| 30 | − const char *fmt, ...); | |
| 31 | −#endif /*__KERNEL__*/ | |
| 32 | − | |
| 33 | −#endif /*__LINUX_NETFILTER_LOGGING_H*/ | |
| @@ -42,6 +42,7 @@ · 41 unmodified lines | ||
| 42 | 42 | #include <linux/in.h> |
| 43 | 43 | #include <linux/mm.h> |
| 44 | 44 | #include <linux/pagemap.h> |
| 45 | +#include <linux/rbtree.h> | |
| 45 | 46 | #include <linux/rwsem.h> |
| 46 | 47 | #include <linux/wait.h> |
| 47 | 48 | |
| @@ -69,6 +70,8 @@ · 21 unmodified lines | ||
| 69 | 70 | * NFSv3/v4 Access mode cache entry |
| 70 | 71 | */ |
| 71 | 72 | struct nfs_access_entry { |
| 73 | + struct rb_node rb_node; | |
| 74 | + struct list_head lru; | |
| 72 | 75 | unsigned long jiffies; |
| 73 | 76 | struct rpc_cred * cred; |
| 74 | 77 | int mask; |
| @@ -145,7 +148,9 @@ struct nfs_inode { · 70 unmodified lines | ||
| 145 | 148 | */ |
| 146 | 149 | atomic_t data_updates; |
| 147 | 150 | |
| 148 | − struct nfs_access_entry cache_access; | |
| 151 | + struct rb_root access_cache; | |
| 152 | + struct list_head access_cache_entry_lru; | |
| 153 | + struct list_head access_cache_inode_lru; | |
| 149 | 154 | #ifdef CONFIG_NFS_V3_ACL |
| 150 | 155 | struct posix_acl *acl_access; |
| 151 | 156 | struct posix_acl *acl_default; |
| @@ -199,6 +204,7 @@ struct nfs_inode { · 47 unmodified lines | ||
| 199 | 204 | #define NFS_INO_REVALIDATING (0) /* revalidating attrs */ |
| 200 | 205 | #define NFS_INO_ADVISE_RDPLUS (1) /* advise readdirplus */ |
| 201 | 206 | #define NFS_INO_STALE (2) /* possible stale inode */ |
| 207 | +#define NFS_INO_ACL_LRU_SET (3) /* Inode is on the LRU list */ | |
| 202 | 208 | |
| 203 | 209 | static inline struct nfs_inode *NFS_I(struct inode *inode) |
| 204 | 210 | { |
| @@ -209,8 +215,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode) · 4 unmodified lines | ||
| 209 | 215 | #define NFS_FH(inode) (&NFS_I(inode)->fh) |
| 210 | 216 | #define NFS_SERVER(inode) (NFS_SB(inode->i_sb)) |
| 211 | 217 | #define NFS_CLIENT(inode) (NFS_SERVER(inode)->client) |
| 212 | −#define NFS_PROTO(inode) (NFS_SERVER(inode)->rpc_ops) | |
| 213 | −#define NFS_ADDR(inode) (RPC_PEERADDR(NFS_CLIENT(inode))) | |
| 218 | +#define NFS_PROTO(inode) (NFS_SERVER(inode)->nfs_client->rpc_ops) | |
| 214 | 219 | #define NFS_COOKIEVERF(inode) (NFS_I(inode)->cookieverf) |
| 215 | 220 | #define NFS_READTIME(inode) (NFS_I(inode)->read_cache_jiffies) |
| 216 | 221 | #define NFS_CHANGE_ATTR(inode) (NFS_I(inode)->change_attr) |
| @@ -297,6 +302,7 @@ extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); · 80 unmodified lines | ||
| 297 | 302 | extern int nfs_permission(struct inode *, int, struct nameidata *); |
| 298 | 303 | extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *); |
| 299 | 304 | extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); |
| 305 | +extern void nfs_access_zap_cache(struct inode *inode); | |
| 300 | 306 | extern int nfs_open(struct inode *, struct file *); |
| 301 | 307 | extern int nfs_release(struct inode *, struct file *); |
| 302 | 308 | extern int nfs_attribute_timeout(struct inode *inode); |
| @@ -579,6 +585,7 @@ extern void * nfs_root_data(void); · 276 unmodified lines | ||
| 579 | 585 | #define NFSDBG_FILE 0x0040 |
| 580 | 586 | #define NFSDBG_ROOT 0x0080 |
| 581 | 587 | #define NFSDBG_CALLBACK 0x0100 |
| 588 | +#define NFSDBG_CLIENT 0x0200 | |
| 582 | 589 | #define NFSDBG_ALL 0xFFFF |
| 583 | 590 | |
| 584 | 591 | #ifdef __KERNEL__ |
| @@ -6,14 +6,80 @@ · 5 unmodified lines | ||
| 6 | 6 | |
| 7 | 7 | struct nfs_iostats; |
| 8 | 8 | |
| 9 | +/* | |
| 10 | + * The nfs_client identifies our client state to the server. | |
| 11 | + */ | |
| 12 | +struct nfs_client { | |
| 13 | + atomic_t cl_count; | |
| 14 | + int cl_cons_state; /* current construction state (-ve: init error) */ | |
| 15 | +#define NFS_CS_READY 0 /* ready to be used */ | |
| 16 | +#define NFS_CS_INITING 1 /* busy initialising */ | |
| 17 | + int cl_nfsversion; /* NFS protocol version */ | |
| 18 | + unsigned long cl_res_state; /* NFS resources state */ | |
| 19 | +#define NFS_CS_RPCIOD 0 /* - rpciod started */ | |
| 20 | +#define NFS_CS_CALLBACK 1 /* - callback started */ | |
| 21 | +#define NFS_CS_IDMAP 2 /* - idmap started */ | |
| 22 | +#define NFS_CS_RENEWD 3 /* - renewd started */ | |
| 23 | + struct sockaddr_in cl_addr; /* server identifier */ | |
| 24 | + char * cl_hostname; /* hostname of server */ | |
| 25 | + struct list_head cl_share_link; /* link in global client list */ | |
| 26 | + struct list_head cl_superblocks; /* List of nfs_server structs */ | |
| 27 | + | |
| 28 | + struct rpc_clnt * cl_rpcclient; | |
| 29 | + const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ | |
| 30 | + unsigned long retrans_timeo; /* retransmit timeout */ | |
| 31 | + unsigned int retrans_count; /* number of retransmit tries */ | |
| 32 | + | |
| 33 | +#ifdef CONFIG_NFS_V4 | |
| 34 | + u64 cl_clientid; /* constant */ | |
| 35 | + nfs4_verifier cl_confirm; | |
| 36 | + unsigned long cl_state; | |
| 37 | + | |
| 38 | + u32 cl_lockowner_id; | |
| 39 | + | |
| 40 | + /* | |
| 41 | + * The following rwsem ensures exclusive access to the server | |
| 42 | + * while we recover the state following a lease expiration. | |
| 43 | + */ | |
| 44 | + struct rw_semaphore cl_sem; | |
| 45 | + | |
| 46 | + struct list_head cl_delegations; | |
| 47 | + struct list_head cl_state_owners; | |
| 48 | + struct list_head cl_unused; | |
| 49 | + int cl_nunused; | |
| 50 | + spinlock_t cl_lock; | |
| 51 | + | |
| 52 | + unsigned long cl_lease_time; | |
| 53 | + unsigned long cl_last_renewal; | |
| 54 | + struct work_struct cl_renewd; | |
| 55 | + | |
| 56 | + struct rpc_wait_queue cl_rpcwaitq; | |
| 57 | + | |
| 58 | + /* used for the setclientid verifier */ | |
| 59 | + struct timespec cl_boot_time; | |
| 60 | + | |
| 61 | + /* idmapper */ | |
| 62 | + struct idmap * cl_idmap; | |
| 63 | + | |
| 64 | + /* Our own IP address, as a null-terminated string. | |
| 65 | + * This is used to generate the clientid, and the callback address. | |
| 66 | + */ | |
| 67 | + char cl_ipaddr[16]; | |
| 68 | + unsigned char cl_id_uniquifier; | |
| 69 | +#endif | |
| 70 | +}; | |
| 71 | + | |
| 9 | 72 | /* |
| 10 | 73 | * NFS client parameters stored in the superblock. |
| 11 | 74 | */ |
| 12 | 75 | struct nfs_server { |
| 76 | + struct nfs_client * nfs_client; /* shared client and NFS4 state */ | |
| 77 | + struct list_head client_link; /* List of other nfs_server structs | |
| 78 | + * that share the same client | |
| 79 | + */ | |
| 80 | + struct list_head master_link; /* link in master servers list */ | |
| 13 | 81 | struct rpc_clnt * client; /* RPC client handle */ |
| 14 | − struct rpc_clnt * client_sys; /* 2nd handle for FSINFO */ | |
| 15 | 82 | struct rpc_clnt * client_acl; /* ACL RPC client handle */ |
| 16 | − struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */ | |
| 17 | 83 | struct nfs_iostats * io_stats; /* I/O statistics */ |
| 18 | 84 | struct backing_dev_info backing_dev_info; |
| 19 | 85 | int flags; /* various flags */ |
| @@ -29,24 +95,14 @@ struct nfs_server { · 9 unmodified lines | ||
| 29 | 95 | unsigned int acregmax; |
| 30 | 96 | unsigned int acdirmin; |
| 31 | 97 | unsigned int acdirmax; |
| 32 | − unsigned long retrans_timeo; /* retransmit timeout */ | |
| 33 | − unsigned int retrans_count; /* number of retransmit tries */ | |
| 34 | 98 | unsigned int namelen; |
| 35 | − char * hostname; /* remote hostname */ | |
| 36 | − struct nfs_fh fh; | |
| 37 | − struct sockaddr_in addr; | |
| 99 | + | |
| 38 | 100 | struct nfs_fsid fsid; |
| 101 | + __u64 maxfilesize; /* maximum file size */ | |
| 39 | 102 | unsigned long mount_time; /* when this fs was mounted */ |
| 103 | + dev_t s_dev; /* superblock dev numbers */ | |
| 104 | + | |
| 40 | 105 | #ifdef CONFIG_NFS_V4 |
| 41 | − /* Our own IP address, as a null-terminated string. | |
| 42 | − * This is used to generate the clientid, and the callback address. | |
| 43 | − */ | |
| 44 | − char ip_addr[16]; | |
| 45 | − char * mnt_path; | |
| 46 | − struct nfs4_client * nfs4_state; /* all NFSv4 state starts here */ | |
| 47 | − struct list_head nfs4_siblings; /* List of other nfs_server structs | |
| 48 | − * that share the same clientid | |
| 49 | − */ | |
| 50 | 106 | u32 attr_bitmask[2];/* V4 bitmask representing the set |
| 51 | 107 | of attributes supported on this |
| 52 | 108 | filesystem */ |
| @@ -54,6 +110,7 @@ struct nfs_server { · 1 unmodified line | ||
| 54 | 110 | that are supported on this |
| 55 | 111 | filesystem */ |
| 56 | 112 | #endif |
| 113 | + void (*destroy)(struct nfs_server *); | |
| 57 | 114 | }; |
| 58 | 115 | |
| 59 | 116 | /* Server capabilities */ |
| @@ -62,15 +62,15 @@ struct idmap_msg { · 61 unmodified lines | ||
| 62 | 62 | #ifdef __KERNEL__ |
| 63 | 63 | |
| 64 | 64 | /* Forward declaration to make this header independent of others */ |
| 65 | −struct nfs4_client; | |
| 65 | +struct nfs_client; | |
| 66 | 66 | |
| 67 | −void nfs_idmap_new(struct nfs4_client *); | |
| 68 | −void nfs_idmap_delete(struct nfs4_client *); | |
| 67 | +int nfs_idmap_new(struct nfs_client *); | |
| 68 | +void nfs_idmap_delete(struct nfs_client *); | |
| 69 | 69 | |
| 70 | −int nfs_map_name_to_uid(struct nfs4_client *, const char *, size_t, __u32 *); | |
| 71 | −int nfs_map_group_to_gid(struct nfs4_client *, const char *, size_t, __u32 *); | |
| 72 | −int nfs_map_uid_to_name(struct nfs4_client *, __u32, char *); | |
| 73 | −int nfs_map_gid_to_group(struct nfs4_client *, __u32, char *); | |
| 70 | +int nfs_map_name_to_uid(struct nfs_client *, const char *, size_t, __u32 *); | |
| 71 | +int nfs_map_group_to_gid(struct nfs_client *, const char *, size_t, __u32 *); | |
| 72 | +int nfs_map_uid_to_name(struct nfs_client *, __u32, char *); | |
| 73 | +int nfs_map_gid_to_group(struct nfs_client *, __u32, char *); | |
| 74 | 74 | |
| 75 | 75 | extern unsigned int nfs_idmap_cache_timeout; |
| 76 | 76 | #endif /* __KERNEL__ */ |
| @@ -1,7 +1,6 @@ | ||
| 1 | 1 | #ifndef _LINUX_NFS_XDR_H |
| 2 | 2 | #define _LINUX_NFS_XDR_H |
| 3 | 3 | |
| 4 | −#include <linux/sunrpc/xprt.h> | |
| 5 | 4 | #include <linux/nfsacl.h> |
| 6 | 5 | |
| 7 | 6 | /* |
| @@ -359,8 +358,8 @@ struct nfs_symlinkargs { · 351 unmodified lines | ||
| 359 | 358 | struct nfs_fh * fromfh; |
| 360 | 359 | const char * fromname; |
| 361 | 360 | unsigned int fromlen; |
| 362 | − const char * topath; | |
| 363 | − unsigned int tolen; | |
| 361 | + struct page ** pages; | |
| 362 | + unsigned int pathlen; | |
| 364 | 363 | struct iattr * sattr; |
| 365 | 364 | }; |
| 366 | 365 | |
| @@ -435,8 +434,8 @@ struct nfs3_symlinkargs { · 68 unmodified lines | ||
| 435 | 434 | struct nfs_fh * fromfh; |
| 436 | 435 | const char * fromname; |
| 437 | 436 | unsigned int fromlen; |
| 438 | − const char * topath; | |
| 439 | − unsigned int tolen; | |
| 437 | + struct page ** pages; | |
| 438 | + unsigned int pathlen; | |
| 440 | 439 | struct iattr * sattr; |
| 441 | 440 | }; |
| 442 | 441 | |
| @@ -534,7 +533,10 @@ struct nfs4_accessres { · 91 unmodified lines | ||
| 534 | 533 | struct nfs4_create_arg { |
| 535 | 534 | u32 ftype; |
| 536 | 535 | union { |
| 537 | − struct qstr * symlink; /* NF4LNK */ | |
| 536 | + struct { | |
| 537 | + struct page ** pages; | |
| 538 | + unsigned int len; | |
| 539 | + } symlink; /* NF4LNK */ | |
| 538 | 540 | struct { |
| 539 | 541 | u32 specdata1; |
| 540 | 542 | u32 specdata2; |
| @@ -770,6 +772,9 @@ struct nfs_rpc_ops { · 229 unmodified lines | ||
| 770 | 772 | |
| 771 | 773 | int (*getroot) (struct nfs_server *, struct nfs_fh *, |
| 772 | 774 | struct nfs_fsinfo *); |
| 775 | + int (*lookupfh)(struct nfs_server *, struct nfs_fh *, | |
| 776 | + struct qstr *, struct nfs_fh *, | |
| 777 | + struct nfs_fattr *); | |
| 773 | 778 | int (*getattr) (struct nfs_server *, struct nfs_fh *, |
| 774 | 779 | struct nfs_fattr *); |
| 775 | 780 | int (*setattr) (struct dentry *, struct nfs_fattr *, |
| @@ -791,9 +796,8 @@ struct nfs_rpc_ops { · 15 unmodified lines | ||
| 791 | 796 | int (*rename) (struct inode *, struct qstr *, |
| 792 | 797 | struct inode *, struct qstr *); |
| 793 | 798 | int (*link) (struct inode *, struct inode *, struct qstr *); |
| 794 | − int (*symlink) (struct inode *, struct qstr *, struct qstr *, | |
| 795 | − struct iattr *, struct nfs_fh *, | |
| 796 | − struct nfs_fattr *); | |
| 799 | + int (*symlink) (struct inode *, struct dentry *, struct page *, | |
| 800 | + unsigned int, struct iattr *); | |
| 797 | 801 | int (*mkdir) (struct inode *, struct dentry *, struct iattr *); |
| 798 | 802 | int (*rmdir) (struct inode *, struct qstr *); |
| 799 | 803 | int (*readdir) (struct dentry *, struct rpc_cred *, |
| @@ -806,6 +810,7 @@ struct nfs_rpc_ops { · 6 unmodified lines | ||
| 806 | 810 | struct nfs_fsinfo *); |
| 807 | 811 | int (*pathconf) (struct nfs_server *, struct nfs_fh *, |
| 808 | 812 | struct nfs_pathconf *); |
| 813 | + int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); | |
| 809 | 814 | u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); |
| 810 | 815 | void (*read_setup) (struct nfs_read_data *); |
| 811 | 816 | int (*read_done) (struct rpc_task *, struct nfs_read_data *); |
| @@ -829,9 +834,9 @@ struct nfs_rpc_ops { · 17 unmodified lines | ||
| 829 | 834 | /* |
| 830 | 835 | * Function vectors etc. for the NFS client |
| 831 | 836 | */ |
| 832 | −extern struct nfs_rpc_ops nfs_v2_clientops; | |
| 833 | −extern struct nfs_rpc_ops nfs_v3_clientops; | |
| 834 | −extern struct nfs_rpc_ops nfs_v4_clientops; | |
| 837 | +extern const struct nfs_rpc_ops nfs_v2_clientops; | |
| 838 | +extern const struct nfs_rpc_ops nfs_v3_clientops; | |
| 839 | +extern const struct nfs_rpc_ops nfs_v4_clientops; | |
| 835 | 840 | extern struct rpc_version nfs_version2; |
| 836 | 841 | extern struct rpc_version nfs_version3; |
| 837 | 842 | extern struct rpc_version nfs_version4; |
| @@ -305,6 +305,7 @@ enum · 304 unmodified lines | ||
| 305 | 305 | TCA_FW_POLICE, |
| 306 | 306 | TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */ |
| 307 | 307 | TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */ |
| 308 | + TCA_FW_MASK, | |
| 308 | 309 | __TCA_FW_MAX |
| 309 | 310 | }; |
| 310 | 311 | |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | #define __LINUX_RTNETLINK_H |
| 3 | 3 | |
| 4 | 4 | #include <linux/netlink.h> |
| 5 | +#include <linux/if.h> | |
| 5 | 6 | |
| 6 | 7 | /**** |
| 7 | 8 | * Routing/neighbour discovery messages. |
| @@ -238,10 +239,8 @@ enum rt_class_t · 230 unmodified lines | ||
| 238 | 239 | RT_TABLE_DEFAULT=253, |
| 239 | 240 | RT_TABLE_MAIN=254, |
| 240 | 241 | RT_TABLE_LOCAL=255, |
| 241 | − __RT_TABLE_MAX | |
| 242 | + RT_TABLE_MAX=0xFFFFFFFF | |
| 242 | 243 | }; |
| 243 | −#define RT_TABLE_MAX (__RT_TABLE_MAX - 1) | |
| 244 | − | |
| 245 | 244 | |
| 246 | 245 | |
| 247 | 246 | /* Routing message attributes */ |
| @@ -263,6 +262,7 @@ enum rtattr_type_t · 15 unmodified lines | ||
| 263 | 262 | RTA_CACHEINFO, |
| 264 | 263 | RTA_SESSION, |
| 265 | 264 | RTA_MP_ALGO, |
| 265 | + RTA_TABLE, | |
| 266 | 266 | __RTA_MAX |
| 267 | 267 | }; |
| 268 | 268 | |
| @@ -383,226 +383,6 @@ struct rta_session · 114 unmodified lines | ||
| 383 | 383 | } u; |
| 384 | 384 | }; |
| 385 | 385 | |
| 386 | − | |
| 387 | −/********************************************************* | |
| 388 | − * Interface address. | |
| 389 | − ****/ | |
| 390 | − | |
| 391 | −struct ifaddrmsg | |
| 392 | −{ | |
| 393 | − unsigned char ifa_family; | |
| 394 | − unsigned char ifa_prefixlen; /* The prefix length */ | |
| 395 | − unsigned char ifa_flags; /* Flags */ | |
| 396 | − unsigned char ifa_scope; /* See above */ | |
| 397 | − int ifa_index; /* Link index */ | |
| 398 | −}; | |
| 399 | − | |
| 400 | −enum | |
| 401 | −{ | |
| 402 | − IFA_UNSPEC, | |
| 403 | − IFA_ADDRESS, | |
| 404 | − IFA_LOCAL, | |
| 405 | − IFA_LABEL, | |
| 406 | − IFA_BROADCAST, | |
| 407 | − IFA_ANYCAST, | |
| 408 | − IFA_CACHEINFO, | |
| 409 | − IFA_MULTICAST, | |
| 410 | − __IFA_MAX | |
| 411 | −}; | |
| 412 | − | |
| 413 | −#define IFA_MAX (__IFA_MAX - 1) | |
| 414 | − | |
| 415 | −/* ifa_flags */ | |
| 416 | − | |
| 417 | −#define IFA_F_SECONDARY 0x01 | |
| 418 | −#define IFA_F_TEMPORARY IFA_F_SECONDARY | |
| 419 | − | |
| 420 | −#define IFA_F_DEPRECATED 0x20 | |
| 421 | −#define IFA_F_TENTATIVE 0x40 | |
| 422 | −#define IFA_F_PERMANENT 0x80 | |
| 423 | − | |
| 424 | −struct ifa_cacheinfo | |
| 425 | −{ | |
| 426 | − __u32 ifa_prefered; | |
| 427 | − __u32 ifa_valid; | |
| 428 | − __u32 cstamp; /* created timestamp, hundredths of seconds */ | |
| 429 | − __u32 tstamp; /* updated timestamp, hundredths of seconds */ | |
| 430 | −}; | |
| 431 | − | |
| 432 | − | |
| 433 | −#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) | |
| 434 | −#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) | |
| 435 | − | |
| 436 | −/* | |
| 437 | − Important comment: | |
| 438 | − IFA_ADDRESS is prefix address, rather than local interface address. | |
| 439 | − It makes no difference for normally configured broadcast interfaces, | |
| 440 | − but for point-to-point IFA_ADDRESS is DESTINATION address, | |
| 441 | − local address is supplied in IFA_LOCAL attribute. | |
| 442 | − */ | |
| 443 | − | |
| 444 | −/************************************************************** | |
| 445 | − * Neighbour discovery. | |
| 446 | − ****/ | |
| 447 | − | |
| 448 | −struct ndmsg | |
| 449 | −{ | |
| 450 | − unsigned char ndm_family; | |
| 451 | − unsigned char ndm_pad1; | |
| 452 | − unsigned short ndm_pad2; | |
| 453 | − int ndm_ifindex; /* Link index */ | |
| 454 | − __u16 ndm_state; | |
| 455 | − __u8 ndm_flags; | |
| 456 | − __u8 ndm_type; | |
| 457 | −}; | |
| 458 | − | |
| 459 | −enum | |
| 460 | −{ | |
| 461 | − NDA_UNSPEC, | |
| 462 | − NDA_DST, | |
| 463 | − NDA_LLADDR, | |
| 464 | − NDA_CACHEINFO, | |
| 465 | − NDA_PROBES, | |
| 466 | − __NDA_MAX | |
| 467 | −}; | |
| 468 | − | |
| 469 | −#define NDA_MAX (__NDA_MAX - 1) | |
| 470 | − | |
| 471 | −#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) | |
| 472 | −#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg)) | |
| 473 | − | |
| 474 | −/* | |
| 475 | − * Neighbor Cache Entry Flags | |
| 476 | − */ | |
| 477 | − | |
| 478 | −#define NTF_PROXY 0x08 /* == ATF_PUBL */ | |
| 479 | −#define NTF_ROUTER 0x80 | |
| 480 | − | |
| 481 | −/* | |
| 482 | − * Neighbor Cache Entry States. | |
| 483 | − */ | |
| 484 | − | |
| 485 | −#define NUD_INCOMPLETE 0x01 | |
| 486 | −#define NUD_REACHABLE 0x02 | |
| 487 | −#define NUD_STALE 0x04 | |
| 488 | −#define NUD_DELAY 0x08 | |
| 489 | −#define NUD_PROBE 0x10 | |
| 490 | −#define NUD_FAILED 0x20 | |
| 491 | − | |
| 492 | −/* Dummy states */ | |
| 493 | −#define NUD_NOARP 0x40 | |
| 494 | −#define NUD_PERMANENT 0x80 | |
| 495 | −#define NUD_NONE 0x00 | |
| 496 | − | |
| 497 | − | |
| 498 | −struct nda_cacheinfo | |
| 499 | −{ | |
| 500 | − __u32 ndm_confirmed; | |
| 501 | − __u32 ndm_used; | |
| 502 | − __u32 ndm_updated; | |
| 503 | − __u32 ndm_refcnt; | |
| 504 | −}; | |
| 505 | − | |
| 506 | − | |
| 507 | −/***************************************************************** | |
| 508 | − * Neighbour tables specific messages. | |
| 509 | − * | |
| 510 | − * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the | |
| 511 | − * NLM_F_DUMP flag set. Every neighbour table configuration is | |
| 512 | − * spread over multiple messages to avoid running into message | |
| 513 | − * size limits on systems with many interfaces. The first message | |
| 514 | − * in the sequence transports all not device specific data such as | |
| 515 | − * statistics, configuration, and the default parameter set. | |
| 516 | − * This message is followed by 0..n messages carrying device | |
| 517 | − * specific parameter sets. | |
| 518 | − * Although the ordering should be sufficient, NDTA_NAME can be | |
| 519 | − * used to identify sequences. The initial message can be identified | |
| 520 | − * by checking for NDTA_CONFIG. The device specific messages do | |
| 521 | − * not contain this TLV but have NDTPA_IFINDEX set to the | |
| 522 | − * corresponding interface index. | |
| 523 | − * | |
| 524 | − * To change neighbour table attributes, send RTM_SETNEIGHTBL | |
| 525 | − * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3], | |
| 526 | − * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked | |
| 527 | − * otherwise. Device specific parameter sets can be changed by | |
| 528 | − * setting NDTPA_IFINDEX to the interface index of the corresponding | |
| 529 | − * device. | |
| 530 | − ****/ | |
| 531 | − | |
| 532 | −struct ndt_stats | |
| 533 | −{ | |
| 534 | − __u64 ndts_allocs; | |
| 535 | − __u64 ndts_destroys; | |
| 536 | − __u64 ndts_hash_grows; | |
| 537 | − __u64 ndts_res_failed; | |
| 538 | − __u64 ndts_lookups; | |
| 539 | − __u64 ndts_hits; | |
| 540 | − __u64 ndts_rcv_probes_mcast; | |
| 541 | − __u64 ndts_rcv_probes_ucast; | |
| 542 | − __u64 ndts_periodic_gc_runs; | |
| 543 | − __u64 ndts_forced_gc_runs; | |
| 544 | −}; | |
| 545 | − | |
| 546 | −enum { | |
| 547 | − NDTPA_UNSPEC, | |
| 548 | − NDTPA_IFINDEX, /* u32, unchangeable */ | |
| 549 | − NDTPA_REFCNT, /* u32, read-only */ | |
| 550 | − NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */ | |
| 551 | − NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */ | |
| 552 | − NDTPA_RETRANS_TIME, /* u64, msecs */ | |
| 553 | − NDTPA_GC_STALETIME, /* u64, msecs */ | |
| 554 | − NDTPA_DELAY_PROBE_TIME, /* u64, msecs */ | |
| 555 | − NDTPA_QUEUE_LEN, /* u32 */ | |
| 556 | − NDTPA_APP_PROBES, /* u32 */ | |
| 557 | − NDTPA_UCAST_PROBES, /* u32 */ | |
| 558 | − NDTPA_MCAST_PROBES, /* u32 */ | |
| 559 | − NDTPA_ANYCAST_DELAY, /* u64, msecs */ | |
| 560 | − NDTPA_PROXY_DELAY, /* u64, msecs */ | |
| 561 | − NDTPA_PROXY_QLEN, /* u32 */ | |
| 562 | − NDTPA_LOCKTIME, /* u64, msecs */ | |
| 563 | − __NDTPA_MAX | |
| 564 | −}; | |
| 565 | −#define NDTPA_MAX (__NDTPA_MAX - 1) | |
| 566 | − | |
| 567 | −struct ndtmsg | |
| 568 | −{ | |
| 569 | − __u8 ndtm_family; | |
| 570 | − __u8 ndtm_pad1; | |
| 571 | − __u16 ndtm_pad2; | |
| 572 | −}; | |
| 573 | − | |
| 574 | −struct ndt_config | |
| 575 | −{ | |
| 576 | − __u16 ndtc_key_len; | |
| 577 | − __u16 ndtc_entry_size; | |
| 578 | − __u32 ndtc_entries; | |
| 579 | − __u32 ndtc_last_flush; /* delta to now in msecs */ | |
| 580 | − __u32 ndtc_last_rand; /* delta to now in msecs */ | |
| 581 | − __u32 ndtc_hash_rnd; | |
| 582 | − __u32 ndtc_hash_mask; | |
| 583 | − __u32 ndtc_hash_chain_gc; | |
| 584 | − __u32 ndtc_proxy_qlen; | |
| 585 | −}; | |
| 586 | − | |
| 587 | −enum { | |
| 588 | − NDTA_UNSPEC, | |
| 589 | − NDTA_NAME, /* char *, unchangeable */ | |
| 590 | − NDTA_THRESH1, /* u32 */ | |
| 591 | − NDTA_THRESH2, /* u32 */ | |
| 592 | − NDTA_THRESH3, /* u32 */ | |
| 593 | − NDTA_CONFIG, /* struct ndt_config, read-only */ | |
| 594 | − NDTA_PARMS, /* nested TLV NDTPA_* */ | |
| 595 | − NDTA_STATS, /* struct ndt_stats, read-only */ | |
| 596 | − NDTA_GC_INTERVAL, /* u64, msecs */ | |
| 597 | − __NDTA_MAX | |
| 598 | −}; | |
| 599 | −#define NDTA_MAX (__NDTA_MAX - 1) | |
| 600 | − | |
| 601 | −#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \ | |
| 602 | − NLMSG_ALIGN(sizeof(struct ndtmsg)))) | |
| 603 | −#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg)) | |
| 604 | − | |
| 605 | − | |
| 606 | 386 | /**** |
| 607 | 387 | * General form of address family dependent message. |
| 608 | 388 | ****/ |
| @@ -663,138 +443,6 @@ struct prefix_cacheinfo · 54 unmodified lines | ||
| 663 | 443 | __u32 valid_time; |
| 664 | 444 | }; |
| 665 | 445 | |
| 666 | −/* The struct should be in sync with struct net_device_stats */ | |
| 667 | −struct rtnl_link_stats | |
| 668 | −{ | |
| 669 | − __u32 rx_packets; /* total packets received */ | |
| 670 | − __u32 tx_packets; /* total packets transmitted */ | |
| 671 | − __u32 rx_bytes; /* total bytes received */ | |
| 672 | − __u32 tx_bytes; /* total bytes transmitted */ | |
| 673 | − __u32 rx_errors; /* bad packets received */ | |
| 674 | − __u32 tx_errors; /* packet transmit problems */ | |
| 675 | − __u32 rx_dropped; /* no space in linux buffers */ | |
| 676 | − __u32 tx_dropped; /* no space available in linux */ | |
| 677 | − __u32 multicast; /* multicast packets received */ | |
| 678 | − __u32 collisions; | |
| 679 | − | |
| 680 | − /* detailed rx_errors: */ | |
| 681 | − __u32 rx_length_errors; | |
| 682 | − __u32 rx_over_errors; /* receiver ring buff overflow */ | |
| 683 | − __u32 rx_crc_errors; /* recved pkt with crc error */ | |
| 684 | − __u32 rx_frame_errors; /* recv'd frame alignment error */ | |
| 685 | − __u32 rx_fifo_errors; /* recv'r fifo overrun */ | |
| 686 | − __u32 rx_missed_errors; /* receiver missed packet */ | |
| 687 | − | |
| 688 | − /* detailed tx_errors */ | |
| 689 | − __u32 tx_aborted_errors; | |
| 690 | − __u32 tx_carrier_errors; | |
| 691 | − __u32 tx_fifo_errors; | |
| 692 | − __u32 tx_heartbeat_errors; | |
| 693 | − __u32 tx_window_errors; | |
| 694 | − | |
| 695 | − /* for cslip etc */ | |
| 696 | − __u32 rx_compressed; | |
| 697 | − __u32 tx_compressed; | |
| 698 | −}; | |
| 699 | − | |
| 700 | −/* The struct should be in sync with struct ifmap */ | |
| 701 | −struct rtnl_link_ifmap | |
| 702 | −{ | |
| 703 | − __u64 mem_start; | |
| 704 | − __u64 mem_end; | |
| 705 | − __u64 base_addr; | |
| 706 | − __u16 irq; | |
| 707 | − __u8 dma; | |
| 708 | − __u8 port; | |
| 709 | −}; | |
| 710 | − | |
| 711 | −enum | |
| 712 | −{ | |
| 713 | − IFLA_UNSPEC, | |
| 714 | − IFLA_ADDRESS, | |
| 715 | − IFLA_BROADCAST, | |
| 716 | − IFLA_IFNAME, | |
| 717 | − IFLA_MTU, | |
| 718 | − IFLA_LINK, | |
| 719 | − IFLA_QDISC, | |
| 720 | − IFLA_STATS, | |
| 721 | − IFLA_COST, | |
| 722 | −#define IFLA_COST IFLA_COST | |
| 723 | − IFLA_PRIORITY, | |
| 724 | −#define IFLA_PRIORITY IFLA_PRIORITY | |
| 725 | − IFLA_MASTER, | |
| 726 | −#define IFLA_MASTER IFLA_MASTER | |
| 727 | − IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ | |
| 728 | −#define IFLA_WIRELESS IFLA_WIRELESS | |
| 729 | − IFLA_PROTINFO, /* Protocol specific information for a link */ | |
| 730 | −#define IFLA_PROTINFO IFLA_PROTINFO | |
| 731 | − IFLA_TXQLEN, | |
| 732 | −#define IFLA_TXQLEN IFLA_TXQLEN | |
| 733 | − IFLA_MAP, | |
| 734 | −#define IFLA_MAP IFLA_MAP | |
| 735 | − IFLA_WEIGHT, | |
| 736 | −#define IFLA_WEIGHT IFLA_WEIGHT | |
| 737 | − IFLA_OPERSTATE, | |
| 738 | − IFLA_LINKMODE, | |
| 739 | − __IFLA_MAX | |
| 740 | −}; | |
| 741 | − | |
| 742 | − | |
| 743 | −#define IFLA_MAX (__IFLA_MAX - 1) | |
| 744 | − | |
| 745 | −#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) | |
| 746 | −#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) | |
| 747 | − | |
| 748 | −/* ifi_flags. | |
| 749 | − | |
| 750 | − IFF_* flags. | |
| 751 | − | |
| 752 | − The only change is: | |
| 753 | − IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are | |
| 754 | − more not changeable by user. They describe link media | |
| 755 | − characteristics and set by device driver. | |
| 756 | − | |
| 757 | − Comments: | |
| 758 | − - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid | |
| 759 | − - If neither of these three flags are set; | |
| 760 | − the interface is NBMA. | |
| 761 | − | |
| 762 | − - IFF_MULTICAST does not mean anything special: | |
| 763 | − multicasts can be used on all not-NBMA links. | |
| 764 | − IFF_MULTICAST means that this media uses special encapsulation | |
| 765 | − for multicast frames. Apparently, all IFF_POINTOPOINT and | |
| 766 | − IFF_BROADCAST devices are able to use multicasts too. | |
| 767 | − */ | |
| 768 | − | |
| 769 | −/* IFLA_LINK. | |
| 770 | − For usual devices it is equal ifi_index. | |
| 771 | − If it is a "virtual interface" (f.e. tunnel), ifi_link | |
| 772 | − can point to real physical interface (f.e. for bandwidth calculations), | |
| 773 | − or maybe 0, what means, that real media is unknown (usual | |
| 774 | − for IPIP tunnels, when route to endpoint is allowed to change) | |
| 775 | − */ | |
| 776 | − | |
| 777 | −/* Subtype attributes for IFLA_PROTINFO */ | |
| 778 | −enum | |
| 779 | −{ | |
| 780 | − IFLA_INET6_UNSPEC, | |
| 781 | − IFLA_INET6_FLAGS, /* link flags */ | |
| 782 | − IFLA_INET6_CONF, /* sysctl parameters */ | |
| 783 | − IFLA_INET6_STATS, /* statistics */ | |
| 784 | − IFLA_INET6_MCAST, /* MC things. What of them? */ | |
| 785 | − IFLA_INET6_CACHEINFO, /* time values and max reasm size */ | |
| 786 | − __IFLA_INET6_MAX | |
| 787 | −}; | |
| 788 | − | |
| 789 | −#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) | |
| 790 | − | |
| 791 | −struct ifla_cacheinfo | |
| 792 | −{ | |
| 793 | − __u32 max_reasm_len; | |
| 794 | − __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ | |
| 795 | − __u32 reachable_time; | |
| 796 | − __u32 retrans_time; | |
| 797 | −}; | |
| 798 | 446 | |
| 799 | 447 | /***************************************************************** |
| 800 | 448 | * Traffic control messages. |
| @@ -885,10 +533,13 @@ enum rtnetlink_groups { · 84 unmodified lines | ||
| 885 | 533 | RTNLGRP_NOP2, |
| 886 | 534 | RTNLGRP_DECnet_ROUTE, |
| 887 | 535 | #define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE |
| 888 | − RTNLGRP_NOP3, | |
| 536 | + RTNLGRP_DECnet_RULE, | |
| 537 | +#define RTNLGRP_DECnet_RULE RTNLGRP_DECnet_RULE | |
| 889 | 538 | RTNLGRP_NOP4, |
| 890 | 539 | RTNLGRP_IPV6_PREFIX, |
| 891 | 540 | #define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX |
| 541 | + RTNLGRP_IPV6_RULE, | |
| 542 | +#define RTNLGRP_IPV6_RULE RTNLGRP_IPV6_RULE | |
| 892 | 543 | __RTNLGRP_MAX |
| 893 | 544 | }; |
| 894 | 545 | #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) |
| @@ -923,8 +574,6 @@ extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, in · 28 unmodified lines | ||
| 923 | 574 | #define rtattr_parse_nested(tb, max, rta) \ |
| 924 | 575 | rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta))) |
| 925 | 576 | |
| 926 | −extern struct sock *rtnl; | |
| 927 | − | |
| 928 | 577 | struct rtnetlink_link |
| 929 | 578 | { |
| 930 | 579 | int (*doit)(struct sk_buff *, struct nlmsghdr*, void *attr); |
| @@ -933,6 +582,10 @@ struct rtnetlink_link · 2 unmodified lines | ||
| 933 | 582 | |
| 934 | 583 | extern struct rtnetlink_link * rtnetlink_links[NPROTO]; |
| 935 | 584 | extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo); |
| 585 | +extern int rtnl_unicast(struct sk_buff *skb, u32 pid); | |
| 586 | +extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group, | |
| 587 | + struct nlmsghdr *nlh, gfp_t flags); | |
| 588 | +extern void rtnl_set_sk_err(u32 group, int error); | |
| 936 | 589 | extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics); |
| 937 | 590 | |
| 938 | 591 | extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data); |
| @@ -1065,6 +718,13 @@ extern void __rtnl_unlock(void); · 126 unmodified lines | ||
| 1065 | 718 | } \ |
| 1066 | 719 | } while(0) |
| 1067 | 720 | |
| 721 | +static inline u32 rtm_get_table(struct rtattr **rta, u8 table) | |
| 722 | +{ | |
| 723 | + return RTA_GET_U32(rta[RTA_TABLE-1]); | |
| 724 | +rtattr_failure: | |
| 725 | + return table; | |
| 726 | +} | |
| 727 | + | |
| 1068 | 728 | #endif /* __KERNEL__ */ |
| 1069 | 729 | |
| 1070 | 730 | |
| @@ -31,6 +31,8 @@ · 30 unmodified lines | ||
| 31 | 31 | #include <linux/msg.h> |
| 32 | 32 | #include <linux/sched.h> |
| 33 | 33 | #include <linux/key.h> |
| 34 | +#include <linux/xfrm.h> | |
| 35 | +#include <net/flow.h> | |
| 34 | 36 | |
| 35 | 37 | struct ctl_table; |
| 36 | 38 | |
| @@ -88,6 +90,7 @@ extern int cap_netlink_recv(struct sk_buff *skb, int cap); · 51 unmodified lines | ||
| 88 | 90 | struct nfsctl_arg; |
| 89 | 91 | struct sched_param; |
| 90 | 92 | struct swap_info_struct; |
| 93 | +struct request_sock; | |
| 91 | 94 | |
| 92 | 95 | /* bprm_apply_creds unsafe reasons */ |
| 93 | 96 | #define LSM_UNSAFE_SHARE 1 |
| @@ -812,9 +815,19 @@ struct swap_info_struct; · 718 unmodified lines | ||
| 812 | 815 | * which is used to copy security attributes between local stream sockets. |
| 813 | 816 | * @sk_free_security: |
| 814 | 817 | * Deallocate security structure. |
| 815 | − * @sk_getsid: | |
| 816 | − * Retrieve the LSM-specific sid for the sock to enable caching of network | |
| 818 | + * @sk_clone_security: | |
| 819 | + * Clone/copy security structure. | |
| 820 | + * @sk_getsecid: | |
| 821 | + * Retrieve the LSM-specific secid for the sock to enable caching of network | |
| 817 | 822 | * authorizations. |
| 823 | + * @sock_graft: | |
| 824 | + * Sets the socket's isec sid to the sock's sid. | |
| 825 | + * @inet_conn_request: | |
| 826 | + * Sets the openreq's sid to socket's sid with MLS portion taken from peer sid. | |
| 827 | + * @inet_csk_clone: | |
| 828 | + * Sets the new child socket's sid to the openreq sid. | |
| 829 | + * @req_classify_flow: | |
| 830 | + * Sets the flow's sid to the openreq sid. | |
| 818 | 831 | * |
| 819 | 832 | * Security hooks for XFRM operations. |
| 820 | 833 | * |
| @@ -823,9 +836,10 @@ struct swap_info_struct; · 2 unmodified lines | ||
| 823 | 836 | * used by the XFRM system. |
| 824 | 837 | * @sec_ctx contains the security context information being provided by |
| 825 | 838 | * the user-level policy update program (e.g., setkey). |
| 826 | − * Allocate a security structure to the xp->security field. | |
| 827 | − * The security field is initialized to NULL when the xfrm_policy is | |
| 828 | − * allocated. | |
| 839 | + * @sk refers to the sock from which to derive the security context. | |
| 840 | + * Allocate a security structure to the xp->security field; the security | |
| 841 | + * field is initialized to NULL when the xfrm_policy is allocated. Only | |
| 842 | + * one of sec_ctx or sock can be specified. | |
| 829 | 843 | * Return 0 if operation was successful (memory to allocate, legal context) |
| 830 | 844 | * @xfrm_policy_clone_security: |
| 831 | 845 | * @old contains an existing xfrm_policy in the SPD. |
| @@ -844,9 +858,14 @@ struct swap_info_struct; · 12 unmodified lines | ||
| 844 | 858 | * Database by the XFRM system. |
| 845 | 859 | * @sec_ctx contains the security context information being provided by |
| 846 | 860 | * the user-level SA generation program (e.g., setkey or racoon). |
| 847 | − * Allocate a security structure to the x->security field. The | |
| 848 | − * security field is initialized to NULL when the xfrm_state is | |
| 849 | − * allocated. | |
| 861 | + * @polsec contains the security context information associated with a xfrm | |
| 862 | + * policy rule from which to take the base context. polsec must be NULL | |
| 863 | + * when sec_ctx is specified. | |
| 864 | + * @secid contains the secid from which to take the mls portion of the context. | |
| 865 | + * Allocate a security structure to the x->security field; the security | |
| 866 | + * field is initialized to NULL when the xfrm_state is allocated. Set the | |
| 867 | + * context to correspond to either sec_ctx or polsec, with the mls portion | |
| 868 | + * taken from secid in the latter case. | |
| 850 | 869 | * Return 0 if operation was successful (memory to allocate, legal context). |
| 851 | 870 | * @xfrm_state_free_security: |
| 852 | 871 | * @x contains the xfrm_state. |
| @@ -857,13 +876,27 @@ struct swap_info_struct; · 4 unmodified lines | ||
| 857 | 876 | * @xfrm_policy_lookup: |
| 858 | 877 | * @xp contains the xfrm_policy for which the access control is being |
| 859 | 878 | * checked. |
| 860 | − * @sk_sid contains the sock security label that is used to authorize | |
| 879 | + * @fl_secid contains the flow security label that is used to authorize | |
| 861 | 880 | * access to the policy xp. |
| 862 | 881 | * @dir contains the direction of the flow (input or output). |
| 863 | − * Check permission when a sock selects a xfrm_policy for processing | |
| 882 | + * Check permission when a flow selects a xfrm_policy for processing | |
| 864 | 883 | * XFRMs on a packet. The hook is called when selecting either a |
| 865 | 884 | * per-socket policy or a generic xfrm policy. |
| 866 | 885 | * Return 0 if permission is granted. |
| 886 | + * @xfrm_state_pol_flow_match: | |
| 887 | + * @x contains the state to match. | |
| 888 | + * @xp contains the policy to check for a match. | |
| 889 | + * @fl contains the flow to check for a match. | |
| 890 | + * Return 1 if there is a match. | |
| 891 | + * @xfrm_flow_state_match: | |
| 892 | + * @fl contains the flow key to match. | |
| 893 | + * @xfrm points to the xfrm_state to match. | |
| 894 | + * Return 1 if there is a match. | |
| 895 | + * @xfrm_decode_session: | |
| 896 | + * @skb points to skb to decode. | |
| 897 | + * @secid points to the flow key secid to set. | |
| 898 | + * @ckall says if all xfrms used should be checked for same secid. | |
| 899 | + * Return 0 if ckall is zero or all xfrms used have the same secid. | |
| 867 | 900 | * |
| 868 | 901 | * Security hooks affecting all Key Management operations |
| 869 | 902 | * |
| @@ -1308,8 +1341,8 @@ struct security_operations { · 438 unmodified lines | ||
| 1308 | 1341 | int (*unix_may_send) (struct socket * sock, struct socket * other); |
| 1309 | 1342 | |
| 1310 | 1343 | int (*socket_create) (int family, int type, int protocol, int kern); |
| 1311 | − void (*socket_post_create) (struct socket * sock, int family, | |
| 1312 | − int type, int protocol, int kern); | |
| 1344 | + int (*socket_post_create) (struct socket * sock, int family, | |
| 1345 | + int type, int protocol, int kern); | |
| 1313 | 1346 | int (*socket_bind) (struct socket * sock, |
| 1314 | 1347 | struct sockaddr * address, int addrlen); |
| 1315 | 1348 | int (*socket_connect) (struct socket * sock, |
| @@ -1332,18 +1365,31 @@ struct security_operations { · 16 unmodified lines | ||
| 1332 | 1365 | int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid); |
| 1333 | 1366 | int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); |
| 1334 | 1367 | void (*sk_free_security) (struct sock *sk); |
| 1335 | − unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir); | |
| 1368 | + void (*sk_clone_security) (const struct sock *sk, struct sock *newsk); | |
| 1369 | + void (*sk_getsecid) (struct sock *sk, u32 *secid); | |
| 1370 | + void (*sock_graft)(struct sock* sk, struct socket *parent); | |
| 1371 | + int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb, | |
| 1372 | + struct request_sock *req); | |
| 1373 | + void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req); | |
| 1374 | + void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl); | |
| 1336 | 1375 | #endif /* CONFIG_SECURITY_NETWORK */ |
| 1337 | 1376 | |
| 1338 | 1377 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
| 1339 | − int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); | |
| 1378 | + int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, | |
| 1379 | + struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk); | |
| 1340 | 1380 | int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new); |
| 1341 | 1381 | void (*xfrm_policy_free_security) (struct xfrm_policy *xp); |
| 1342 | 1382 | int (*xfrm_policy_delete_security) (struct xfrm_policy *xp); |
| 1343 | − int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); | |
| 1383 | + int (*xfrm_state_alloc_security) (struct xfrm_state *x, | |
| 1384 | + struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *polsec, | |
| 1385 | + u32 secid); | |
| 1344 | 1386 | void (*xfrm_state_free_security) (struct xfrm_state *x); |
| 1345 | 1387 | int (*xfrm_state_delete_security) (struct xfrm_state *x); |
| 1346 | − int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 sk_sid, u8 dir); | |
| 1388 | + int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir); | |
| 1389 | + int (*xfrm_state_pol_flow_match)(struct xfrm_state *x, | |
| 1390 | + struct xfrm_policy *xp, struct flowi *fl); | |
| 1391 | + int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm); | |
| 1392 | + int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall); | |
| 1347 | 1393 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
| 1348 | 1394 | |
| 1349 | 1395 | /* key management security hooks */ |
| @@ -2778,13 +2824,13 @@ static inline int security_socket_create (int family, int type, · 1428 unmodified lines | ||
| 2778 | 2824 | return security_ops->socket_create(family, type, protocol, kern); |
| 2779 | 2825 | } |
| 2780 | 2826 | |
| 2781 | −static inline void security_socket_post_create(struct socket * sock, | |
| 2782 | − int family, | |
| 2783 | − int type, | |
| 2784 | − int protocol, int kern) | |
| 2827 | +static inline int security_socket_post_create(struct socket * sock, | |
| 2828 | + int family, | |
| 2829 | + int type, | |
| 2830 | + int protocol, int kern) | |
| 2785 | 2831 | { |
| 2786 | − security_ops->socket_post_create(sock, family, type, | |
| 2787 | − protocol, kern); | |
| 2832 | + return security_ops->socket_post_create(sock, family, type, | |
| 2833 | + protocol, kern); | |
| 2788 | 2834 | } |
| 2789 | 2835 | |
| 2790 | 2836 | static inline int security_socket_bind(struct socket * sock, |
| @@ -2885,9 +2931,36 @@ static inline void security_sk_free(struct sock *sk) · 94 unmodified lines | ||
| 2885 | 2931 | return security_ops->sk_free_security(sk); |
| 2886 | 2932 | } |
| 2887 | 2933 | |
| 2888 | −static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) | |
| 2934 | +static inline void security_sk_clone(const struct sock *sk, struct sock *newsk) | |
| 2935 | +{ | |
| 2936 | + return security_ops->sk_clone_security(sk, newsk); | |
| 2937 | +} | |
| 2938 | + | |
| 2939 | +static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl) | |
| 2889 | 2940 | { |
| 2890 | − return security_ops->sk_getsid(sk, fl, dir); | |
| 2941 | + security_ops->sk_getsecid(sk, &fl->secid); | |
| 2942 | +} | |
| 2943 | + | |
| 2944 | +static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) | |
| 2945 | +{ | |
| 2946 | + security_ops->req_classify_flow(req, fl); | |
| 2947 | +} | |
| 2948 | + | |
| 2949 | +static inline void security_sock_graft(struct sock* sk, struct socket *parent) | |
| 2950 | +{ | |
| 2951 | + security_ops->sock_graft(sk, parent); | |
| 2952 | +} | |
| 2953 | + | |
| 2954 | +static inline int security_inet_conn_request(struct sock *sk, | |
| 2955 | + struct sk_buff *skb, struct request_sock *req) | |
| 2956 | +{ | |
| 2957 | + return security_ops->inet_conn_request(sk, skb, req); | |
| 2958 | +} | |
| 2959 | + | |
| 2960 | +static inline void security_inet_csk_clone(struct sock *newsk, | |
| 2961 | + const struct request_sock *req) | |
| 2962 | +{ | |
| 2963 | + security_ops->inet_csk_clone(newsk, req); | |
| 2891 | 2964 | } |
| 2892 | 2965 | #else /* CONFIG_SECURITY_NETWORK */ |
| 2893 | 2966 | static inline int security_unix_stream_connect(struct socket * sock, |
| @@ -2909,11 +2982,12 @@ static inline int security_socket_create (int family, int type, · 15 unmodified lines | ||
| 2909 | 2982 | return 0; |
| 2910 | 2983 | } |
| 2911 | 2984 | |
| 2912 | −static inline void security_socket_post_create(struct socket * sock, | |
| 2913 | − int family, | |
| 2914 | − int type, | |
| 2915 | − int protocol, int kern) | |
| 2985 | +static inline int security_socket_post_create(struct socket * sock, | |
| 2986 | + int family, | |
| 2987 | + int type, | |
| 2988 | + int protocol, int kern) | |
| 2916 | 2989 | { |
| 2990 | + return 0; | |
| 2917 | 2991 | } |
| 2918 | 2992 | |
| 2919 | 2993 | static inline int security_socket_bind(struct socket * sock, |
| @@ -3011,16 +3085,43 @@ static inline void security_sk_free(struct sock *sk) · 91 unmodified lines | ||
| 3011 | 3085 | { |
| 3012 | 3086 | } |
| 3013 | 3087 | |
| 3014 | −static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) | |
| 3088 | +static inline void security_sk_clone(const struct sock *sk, struct sock *newsk) | |
| 3089 | +{ | |
| 3090 | +} | |
| 3091 | + | |
| 3092 | +static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl) | |
| 3093 | +{ | |
| 3094 | +} | |
| 3095 | + | |
| 3096 | +static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) | |
| 3097 | +{ | |
| 3098 | +} | |
| 3099 | + | |
| 3100 | +static inline void security_sock_graft(struct sock* sk, struct socket *parent) | |
| 3101 | +{ | |
| 3102 | +} | |
| 3103 | + | |
| 3104 | +static inline int security_inet_conn_request(struct sock *sk, | |
| 3105 | + struct sk_buff *skb, struct request_sock *req) | |
| 3015 | 3106 | { |
| 3016 | 3107 | return 0; |
| 3017 | 3108 | } |
| 3109 | + | |
| 3110 | +static inline void security_inet_csk_clone(struct sock *newsk, | |
| 3111 | + const struct request_sock *req) | |
| 3112 | +{ | |
| 3113 | +} | |
| 3018 | 3114 | #endif /* CONFIG_SECURITY_NETWORK */ |
| 3019 | 3115 | |
| 3020 | 3116 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
| 3021 | 3117 | static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) |
| 3022 | 3118 | { |
| 3023 | − return security_ops->xfrm_policy_alloc_security(xp, sec_ctx); | |
| 3119 | + return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL); | |
| 3120 | +} | |
| 3121 | + | |
| 3122 | +static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk) | |
| 3123 | +{ | |
| 3124 | + return security_ops->xfrm_policy_alloc_security(xp, NULL, sk); | |
| 3024 | 3125 | } |
| 3025 | 3126 | |
| 3026 | 3127 | static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) |
| @@ -3038,9 +3139,18 @@ static inline int security_xfrm_policy_delete(struct xfrm_policy *xp) · 11 unmodified lines | ||
| 3038 | 3139 | return security_ops->xfrm_policy_delete_security(xp); |
| 3039 | 3140 | } |
| 3040 | 3141 | |
| 3041 | −static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) | |
| 3142 | +static inline int security_xfrm_state_alloc(struct xfrm_state *x, | |
| 3143 | + struct xfrm_user_sec_ctx *sec_ctx) | |
| 3042 | 3144 | { |
| 3043 | − return security_ops->xfrm_state_alloc_security(x, sec_ctx); | |
| 3145 | + return security_ops->xfrm_state_alloc_security(x, sec_ctx, NULL, 0); | |
| 3146 | +} | |
| 3147 | + | |
| 3148 | +static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x, | |
| 3149 | + struct xfrm_sec_ctx *polsec, u32 secid) | |
| 3150 | +{ | |
| 3151 | + if (!polsec) | |
| 3152 | + return 0; | |
| 3153 | + return security_ops->xfrm_state_alloc_security(x, NULL, polsec, secid); | |
| 3044 | 3154 | } |
| 3045 | 3155 | |
| 3046 | 3156 | static inline int security_xfrm_state_delete(struct xfrm_state *x) |
| @@ -3053,9 +3163,32 @@ static inline void security_xfrm_state_free(struct xfrm_state *x) · 6 unmodified lines | ||
| 3053 | 3163 | security_ops->xfrm_state_free_security(x); |
| 3054 | 3164 | } |
| 3055 | 3165 | |
| 3056 | −static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) | |
| 3166 | +static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) | |
| 3167 | +{ | |
| 3168 | + return security_ops->xfrm_policy_lookup(xp, fl_secid, dir); | |
| 3169 | +} | |
| 3170 | + | |
| 3171 | +static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, | |
| 3172 | + struct xfrm_policy *xp, struct flowi *fl) | |
| 3057 | 3173 | { |
| 3058 | − return security_ops->xfrm_policy_lookup(xp, sk_sid, dir); | |
| 3174 | + return security_ops->xfrm_state_pol_flow_match(x, xp, fl); | |
| 3175 | +} | |
| 3176 | + | |
| 3177 | +static inline int security_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) | |
| 3178 | +{ | |
| 3179 | + return security_ops->xfrm_flow_state_match(fl, xfrm); | |
| 3180 | +} | |
| 3181 | + | |
| 3182 | +static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) | |
| 3183 | +{ | |
| 3184 | + return security_ops->xfrm_decode_session(skb, secid, 1); | |
| 3185 | +} | |
| 3186 | + | |
| 3187 | +static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) | |
| 3188 | +{ | |
| 3189 | + int rc = security_ops->xfrm_decode_session(skb, &fl->secid, 0); | |
| 3190 | + | |
| 3191 | + BUG_ON(rc); | |
| 3059 | 3192 | } |
| 3060 | 3193 | #else /* CONFIG_SECURITY_NETWORK_XFRM */ |
| 3061 | 3194 | static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) |
| @@ -3063,6 +3196,11 @@ static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm · 1 unmodified line | ||
| 3063 | 3196 | return 0; |
| 3064 | 3197 | } |
| 3065 | 3198 | |
| 3199 | +static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk) | |
| 3200 | +{ | |
| 3201 | + return 0; | |
| 3202 | +} | |
| 3203 | + | |
| 3066 | 3204 | static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) |
| 3067 | 3205 | { |
| 3068 | 3206 | return 0; |
| @@ -3077,7 +3215,14 @@ static inline int security_xfrm_policy_delete(struct xfrm_policy *xp) · 8 unmodified lines | ||
| 3077 | 3215 | return 0; |
| 3078 | 3216 | } |
| 3079 | 3217 | |
| 3080 | −static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) | |
| 3218 | +static inline int security_xfrm_state_alloc(struct xfrm_state *x, | |
| 3219 | + struct xfrm_user_sec_ctx *sec_ctx) | |
| 3220 | +{ | |
| 3221 | + return 0; | |
| 3222 | +} | |
| 3223 | + | |
| 3224 | +static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x, | |
| 3225 | + struct xfrm_sec_ctx *polsec, u32 secid) | |
| 3081 | 3226 | { |
| 3082 | 3227 | return 0; |
| 3083 | 3228 | } |
| @@ -3091,10 +3236,32 @@ static inline int security_xfrm_state_delete(struct xfrm_state *x) · 7 unmodified lines | ||
| 3091 | 3236 | return 0; |
| 3092 | 3237 | } |
| 3093 | 3238 | |
| 3094 | −static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) | |
| 3239 | +static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) | |
| 3240 | +{ | |
| 3241 | + return 0; | |
| 3242 | +} | |
| 3243 | + | |
| 3244 | +static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, | |
| 3245 | + struct xfrm_policy *xp, struct flowi *fl) | |
| 3246 | +{ | |
| 3247 | + return 1; | |
| 3248 | +} | |
| 3249 | + | |
| 3250 | +static inline int security_xfrm_flow_state_match(struct flowi *fl, | |
| 3251 | + struct xfrm_state *xfrm) | |
| 3252 | +{ | |
| 3253 | + return 1; | |
| 3254 | +} | |
| 3255 | + | |
| 3256 | +static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) | |
| 3095 | 3257 | { |
| 3096 | 3258 | return 0; |
| 3097 | 3259 | } |
| 3260 | + | |
| 3261 | +static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) | |
| 3262 | +{ | |
| 3263 | +} | |
| 3264 | + | |
| 3098 | 3265 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
| 3099 | 3266 | |
| 3100 | 3267 | #ifdef CONFIG_KEYS |
| @@ -34,8 +34,9 @@ · 33 unmodified lines | ||
| 34 | 34 | #define HAVE_ALIGNABLE_SKB /* Ditto 8) */ |
| 35 | 35 | |
| 36 | 36 | #define CHECKSUM_NONE 0 |
| 37 | −#define CHECKSUM_HW 1 | |
| 37 | +#define CHECKSUM_PARTIAL 1 | |
| 38 | 38 | #define CHECKSUM_UNNECESSARY 2 |
| 39 | +#define CHECKSUM_COMPLETE 3 | |
| 39 | 40 | |
| 40 | 41 | #define SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES - 1)) & \ |
| 41 | 42 | ~(SMP_CACHE_BYTES - 1)) |
| @@ -56,17 +57,17 @@ · 14 unmodified lines | ||
| 56 | 57 | * Apparently with secret goal to sell you new device, when you |
| 57 | 58 | * will add new protocol to your host. F.e. IPv6. 8) |
| 58 | 59 | * |
| 59 | − * HW: the most generic way. Device supplied checksum of _all_ | |
| 60 | + * COMPLETE: the most generic way. Device supplied checksum of _all_ | |
| 60 | 61 | * the packet as seen by netif_rx in skb->csum. |
| 61 | 62 | * NOTE: Even if device supports only some protocols, but |
| 62 | − * is able to produce some skb->csum, it MUST use HW, | |
| 63 | + * is able to produce some skb->csum, it MUST use COMPLETE, | |
| 63 | 64 | * not UNNECESSARY. |
| 64 | 65 | * |
| 65 | 66 | * B. Checksumming on output. |
| 66 | 67 | * |
| 67 | 68 | * NONE: skb is checksummed by protocol or csum is not required. |
| 68 | 69 | * |
| 69 | − * HW: device is required to csum packet as seen by hard_start_xmit | |
| 70 | + * PARTIAL: device is required to csum packet as seen by hard_start_xmit | |
| 70 | 71 | * from skb->h.raw to the end and to record the checksum |
| 71 | 72 | * at skb->h.raw+skb->csum. |
| 72 | 73 | * |
| @@ -1261,14 +1262,14 @@ static inline int skb_linearize_cow(struct sk_buff *skb) · 1188 unmodified lines | ||
| 1261 | 1262 | * @len: length of data pulled |
| 1262 | 1263 | * |
| 1263 | 1264 | * After doing a pull on a received packet, you need to call this to |
| 1264 | − * update the CHECKSUM_HW checksum, or set ip_summed to CHECKSUM_NONE | |
| 1265 | − * so that it can be recomputed from scratch. | |
| 1265 | + * update the CHECKSUM_COMPLETE checksum, or set ip_summed to | |
| 1266 | + * CHECKSUM_NONE so that it can be recomputed from scratch. | |
| 1266 | 1267 | */ |
| 1267 | 1268 | |
| 1268 | 1269 | static inline void skb_postpull_rcsum(struct sk_buff *skb, |
| 1269 | 1270 | const void *start, unsigned int len) |
| 1270 | 1271 | { |
| 1271 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 1272 | + if (skb->ip_summed == CHECKSUM_COMPLETE) | |
| 1272 | 1273 | skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); |
| 1273 | 1274 | } |
| 1274 | 1275 | |
| @@ -1287,7 +1288,7 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) · 12 unmodified lines | ||
| 1287 | 1288 | { |
| 1288 | 1289 | if (likely(len >= skb->len)) |
| 1289 | 1290 | return 0; |
| 1290 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 1291 | + if (skb->ip_summed == CHECKSUM_COMPLETE) | |
| 1291 | 1292 | skb->ip_summed = CHECKSUM_NONE; |
| 1292 | 1293 | return __pskb_trim(skb, len); |
| 1293 | 1294 | } |
| @@ -155,42 +155,11 @@ enum · 154 unmodified lines | ||
| 155 | 155 | UDP_MIB_NOPORTS, /* NoPorts */ |
| 156 | 156 | UDP_MIB_INERRORS, /* InErrors */ |
| 157 | 157 | UDP_MIB_OUTDATAGRAMS, /* OutDatagrams */ |
| 158 | + UDP_MIB_RCVBUFERRORS, /* RcvbufErrors */ | |
| 159 | + UDP_MIB_SNDBUFERRORS, /* SndbufErrors */ | |
| 158 | 160 | __UDP_MIB_MAX |
| 159 | 161 | }; |
| 160 | 162 | |
| 161 | −/* sctp mib definitions */ | |
| 162 | −/* | |
| 163 | − * draft-ietf-sigtran-sctp-mib-07.txt | |
| 164 | − */ | |
| 165 | −enum | |
| 166 | −{ | |
| 167 | − SCTP_MIB_NUM = 0, | |
| 168 | − SCTP_MIB_CURRESTAB, /* CurrEstab */ | |
| 169 | − SCTP_MIB_ACTIVEESTABS, /* ActiveEstabs */ | |
| 170 | − SCTP_MIB_PASSIVEESTABS, /* PassiveEstabs */ | |
| 171 | − SCTP_MIB_ABORTEDS, /* Aborteds */ | |
| 172 | − SCTP_MIB_SHUTDOWNS, /* Shutdowns */ | |
| 173 | − SCTP_MIB_OUTOFBLUES, /* OutOfBlues */ | |
| 174 | − SCTP_MIB_CHECKSUMERRORS, /* ChecksumErrors */ | |
| 175 | − SCTP_MIB_OUTCTRLCHUNKS, /* OutCtrlChunks */ | |
| 176 | − SCTP_MIB_OUTORDERCHUNKS, /* OutOrderChunks */ | |
| 177 | − SCTP_MIB_OUTUNORDERCHUNKS, /* OutUnorderChunks */ | |
| 178 | − SCTP_MIB_INCTRLCHUNKS, /* InCtrlChunks */ | |
| 179 | − SCTP_MIB_INORDERCHUNKS, /* InOrderChunks */ | |
| 180 | − SCTP_MIB_INUNORDERCHUNKS, /* InUnorderChunks */ | |
| 181 | − SCTP_MIB_FRAGUSRMSGS, /* FragUsrMsgs */ | |
| 182 | − SCTP_MIB_REASMUSRMSGS, /* ReasmUsrMsgs */ | |
| 183 | − SCTP_MIB_OUTSCTPPACKS, /* OutSCTPPacks */ | |
| 184 | − SCTP_MIB_INSCTPPACKS, /* InSCTPPacks */ | |
| 185 | − SCTP_MIB_RTOALGORITHM, /* RtoAlgorithm */ | |
| 186 | − SCTP_MIB_RTOMIN, /* RtoMin */ | |
| 187 | − SCTP_MIB_RTOMAX, /* RtoMax */ | |
| 188 | − SCTP_MIB_RTOINITIAL, /* RtoInitial */ | |
| 189 | − SCTP_MIB_VALCOOKIELIFE, /* ValCookieLife */ | |
| 190 | − SCTP_MIB_MAXINITRETR, /* MaxInitRetr */ | |
| 191 | − __SCTP_MIB_MAX | |
| 192 | −}; | |
| 193 | − | |
| 194 | 163 | /* linux mib definitions */ |
| 195 | 164 | enum |
| 196 | 165 | { |
| @@ -18,18 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/sunrpc/timer.h> |
| 19 | 19 | #include <asm/signal.h> |
| 20 | 20 | |
| 21 | −/* | |
| 22 | − * This defines an RPC port mapping | |
| 23 | − */ | |
| 24 | −struct rpc_portmap { | |
| 25 | − __u32 pm_prog; | |
| 26 | − __u32 pm_vers; | |
| 27 | − __u32 pm_prot; | |
| 28 | − __u16 pm_port; | |
| 29 | − unsigned char pm_binding : 1; /* doing a getport() */ | |
| 30 | − struct rpc_wait_queue pm_bindwait; /* waiting on getport() */ | |
| 31 | −}; | |
| 32 | − | |
| 33 | 21 | struct rpc_inode; |
| 34 | 22 | |
| 35 | 23 | /* |
| @@ -40,7 +28,9 @@ struct rpc_clnt { · 4 unmodified lines | ||
| 40 | 28 | atomic_t cl_users; /* number of references */ |
| 41 | 29 | struct rpc_xprt * cl_xprt; /* transport */ |
| 42 | 30 | struct rpc_procinfo * cl_procinfo; /* procedure info */ |
| 43 | − u32 cl_maxproc; /* max procedure number */ | |
| 31 | + u32 cl_prog, /* RPC program number */ | |
| 32 | + cl_vers, /* RPC version number */ | |
| 33 | + cl_maxproc; /* max procedure number */ | |
| 44 | 34 | |
| 45 | 35 | char * cl_server; /* server machine name */ |
| 46 | 36 | char * cl_protname; /* protocol name */ |
| @@ -55,7 +45,6 @@ struct rpc_clnt { · 8 unmodified lines | ||
| 55 | 45 | cl_dead : 1;/* abandoned */ |
| 56 | 46 | |
| 57 | 47 | struct rpc_rtt * cl_rtt; /* RTO estimator data */ |
| 58 | − struct rpc_portmap * cl_pmap; /* port mapping */ | |
| 59 | 48 | |
| 60 | 49 | int cl_nodelen; /* nodename length */ |
| 61 | 50 | char cl_nodename[UNX_MAXNODENAME]; |
| @@ -64,14 +53,8 @@ struct rpc_clnt { · 2 unmodified lines | ||
| 64 | 53 | struct dentry * cl_dentry; /* inode */ |
| 65 | 54 | struct rpc_clnt * cl_parent; /* Points to parent of clones */ |
| 66 | 55 | struct rpc_rtt cl_rtt_default; |
| 67 | − struct rpc_portmap cl_pmap_default; | |
| 68 | 56 | char cl_inline_name[32]; |
| 69 | 57 | }; |
| 70 | −#define cl_timeout cl_xprt->timeout | |
| 71 | −#define cl_prog cl_pmap->pm_prog | |
| 72 | −#define cl_vers cl_pmap->pm_vers | |
| 73 | −#define cl_port cl_pmap->pm_port | |
| 74 | −#define cl_prot cl_pmap->pm_prot | |
| 75 | 58 | |
| 76 | 59 | /* |
| 77 | 60 | * General RPC program info |
| @@ -106,24 +89,36 @@ struct rpc_procinfo { · 28 unmodified lines | ||
| 106 | 89 | char * p_name; /* name of procedure */ |
| 107 | 90 | }; |
| 108 | 91 | |
| 109 | −#define RPC_CONGESTED(clnt) (RPCXPRT_CONGESTED((clnt)->cl_xprt)) | |
| 110 | −#define RPC_PEERADDR(clnt) (&(clnt)->cl_xprt->addr) | |
| 111 | − | |
| 112 | 92 | #ifdef __KERNEL__ |
| 113 | 93 | |
| 114 | −struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname, | |
| 115 | − struct rpc_program *info, | |
| 116 | − u32 version, rpc_authflavor_t authflavor); | |
| 117 | −struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname, | |
| 118 | − struct rpc_program *info, | |
| 119 | − u32 version, rpc_authflavor_t authflavor); | |
| 94 | +struct rpc_create_args { | |
| 95 | + int protocol; | |
| 96 | + struct sockaddr *address; | |
| 97 | + size_t addrsize; | |
| 98 | + struct rpc_timeout *timeout; | |
| 99 | + char *servername; | |
| 100 | + struct rpc_program *program; | |
| 101 | + u32 version; | |
| 102 | + rpc_authflavor_t authflavor; | |
| 103 | + unsigned long flags; | |
| 104 | +}; | |
| 105 | + | |
| 106 | +/* Values for "flags" field */ | |
| 107 | +#define RPC_CLNT_CREATE_HARDRTRY (1UL << 0) | |
| 108 | +#define RPC_CLNT_CREATE_INTR (1UL << 1) | |
| 109 | +#define RPC_CLNT_CREATE_AUTOBIND (1UL << 2) | |
| 110 | +#define RPC_CLNT_CREATE_ONESHOT (1UL << 3) | |
| 111 | +#define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 4) | |
| 112 | +#define RPC_CLNT_CREATE_NOPING (1UL << 5) | |
| 113 | + | |
| 114 | +struct rpc_clnt *rpc_create(struct rpc_create_args *args); | |
| 120 | 115 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, |
| 121 | 116 | struct rpc_program *, int); |
| 122 | 117 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); |
| 123 | 118 | int rpc_shutdown_client(struct rpc_clnt *); |
| 124 | 119 | int rpc_destroy_client(struct rpc_clnt *); |
| 125 | 120 | void rpc_release_client(struct rpc_clnt *); |
| 126 | −void rpc_getport(struct rpc_task *, struct rpc_clnt *); | |
| 121 | +void rpc_getport(struct rpc_task *); | |
| 127 | 122 | int rpc_register(u32, u32, int, unsigned short, int *); |
| 128 | 123 | |
| 129 | 124 | void rpc_call_setup(struct rpc_task *, struct rpc_message *, int); |
| @@ -140,6 +135,8 @@ void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); · 10 unmodified lines | ||
| 140 | 135 | size_t rpc_max_payload(struct rpc_clnt *); |
| 141 | 136 | void rpc_force_rebind(struct rpc_clnt *); |
| 142 | 137 | int rpc_ping(struct rpc_clnt *clnt, int flags); |
| 138 | +size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t); | |
| 139 | +char * rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); | |
| 143 | 140 | |
| 144 | 141 | /* |
| 145 | 142 | * Helper function for NFSroot support |
| @@ -43,7 +43,7 @@ extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); · 42 unmodified lines | ||
| 43 | 43 | |
| 44 | 44 | extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *); |
| 45 | 45 | extern int rpc_rmdir(struct dentry *); |
| 46 | −extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags); | |
| 46 | +extern struct dentry *rpc_mkpipe(struct dentry *, const char *, void *, struct rpc_pipe_ops *, int flags); | |
| 47 | 47 | extern int rpc_unlink(struct dentry *); |
| 48 | 48 | extern struct vfsmount *rpc_get_mount(void); |
| 49 | 49 | extern void rpc_put_mount(void); |
| @@ -127,7 +127,6 @@ struct rpc_call_ops { · 126 unmodified lines | ||
| 127 | 127 | */ |
| 128 | 128 | #define RPC_TASK_ASYNC 0x0001 /* is an async task */ |
| 129 | 129 | #define RPC_TASK_SWAPPER 0x0002 /* is swapping in/out */ |
| 130 | −#define RPC_TASK_CHILD 0x0008 /* is child of other task */ | |
| 131 | 130 | #define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */ |
| 132 | 131 | #define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */ |
| 133 | 132 | #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ |
| @@ -136,7 +135,6 @@ struct rpc_call_ops { · 2 unmodified lines | ||
| 136 | 135 | #define RPC_TASK_NOINTR 0x0400 /* uninterruptible task */ |
| 137 | 136 | |
| 138 | 137 | #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) |
| 139 | −#define RPC_IS_CHILD(t) ((t)->tk_flags & RPC_TASK_CHILD) | |
| 140 | 138 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) |
| 141 | 139 | #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) |
| 142 | 140 | #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) |
| @@ -253,7 +251,6 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags, · 110 unmodified lines | ||
| 253 | 251 | const struct rpc_call_ops *ops, void *data); |
| 254 | 252 | struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, |
| 255 | 253 | const struct rpc_call_ops *ops, void *data); |
| 256 | −struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent); | |
| 257 | 254 | void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, |
| 258 | 255 | int flags, const struct rpc_call_ops *ops, |
| 259 | 256 | void *data); |
| @@ -261,8 +258,6 @@ void rpc_release_task(struct rpc_task *); · 1 unmodified line | ||
| 261 | 258 | void rpc_exit_task(struct rpc_task *); |
| 262 | 259 | void rpc_killall_tasks(struct rpc_clnt *); |
| 263 | 260 | int rpc_execute(struct rpc_task *); |
| 264 | −void rpc_run_child(struct rpc_task *parent, struct rpc_task *child, | |
| 265 | − rpc_action action); | |
| 266 | 261 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *); |
| 267 | 262 | void rpc_init_wait_queue(struct rpc_wait_queue *, const char *); |
| 268 | 263 | void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *, |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/uio.h> |
| 13 | 13 | #include <linux/socket.h> |
| 14 | 14 | #include <linux/in.h> |
| 15 | +#include <linux/kref.h> | |
| 15 | 16 | #include <linux/sunrpc/sched.h> |
| 16 | 17 | #include <linux/sunrpc/xdr.h> |
| 17 | 18 | |
| @@ -51,6 +52,14 @@ struct rpc_timeout { · 33 unmodified lines | ||
| 51 | 52 | unsigned char to_exponential; |
| 52 | 53 | }; |
| 53 | 54 | |
| 55 | +enum rpc_display_format_t { | |
| 56 | + RPC_DISPLAY_ADDR = 0, | |
| 57 | + RPC_DISPLAY_PORT, | |
| 58 | + RPC_DISPLAY_PROTO, | |
| 59 | + RPC_DISPLAY_ALL, | |
| 60 | + RPC_DISPLAY_MAX, | |
| 61 | +}; | |
| 62 | + | |
| 54 | 63 | struct rpc_task; |
| 55 | 64 | struct rpc_xprt; |
| 56 | 65 | struct seq_file; |
| @@ -103,8 +112,10 @@ struct rpc_rqst { · 46 unmodified lines | ||
| 103 | 112 | |
| 104 | 113 | struct rpc_xprt_ops { |
| 105 | 114 | void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize); |
| 115 | + char * (*print_addr)(struct rpc_xprt *xprt, enum rpc_display_format_t format); | |
| 106 | 116 | int (*reserve_xprt)(struct rpc_task *task); |
| 107 | 117 | void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); |
| 118 | + void (*rpcbind)(struct rpc_task *task); | |
| 108 | 119 | void (*set_port)(struct rpc_xprt *xprt, unsigned short port); |
| 109 | 120 | void (*connect)(struct rpc_task *task); |
| 110 | 121 | void * (*buf_alloc)(struct rpc_task *task, size_t size); |
| @@ -119,12 +130,14 @@ struct rpc_xprt_ops { · 8 unmodified lines | ||
| 119 | 130 | }; |
| 120 | 131 | |
| 121 | 132 | struct rpc_xprt { |
| 133 | + struct kref kref; /* Reference count */ | |
| 122 | 134 | struct rpc_xprt_ops * ops; /* transport methods */ |
| 123 | 135 | struct socket * sock; /* BSD socket layer */ |
| 124 | 136 | struct sock * inet; /* INET layer */ |
| 125 | 137 | |
| 126 | 138 | struct rpc_timeout timeout; /* timeout parms */ |
| 127 | − struct sockaddr_in addr; /* server address */ | |
| 139 | + struct sockaddr_storage addr; /* server address */ | |
| 140 | + size_t addrlen; /* size of server address */ | |
| 128 | 141 | int prot; /* IP protocol */ |
| 129 | 142 | |
| 130 | 143 | unsigned long cong; /* current congestion */ |
| @@ -138,6 +151,7 @@ struct rpc_xprt { · 7 unmodified lines | ||
| 138 | 151 | unsigned int tsh_size; /* size of transport specific |
| 139 | 152 | header */ |
| 140 | 153 | |
| 154 | + struct rpc_wait_queue binding; /* requests waiting on rpcbind */ | |
| 141 | 155 | struct rpc_wait_queue sending; /* requests waiting to send */ |
| 142 | 156 | struct rpc_wait_queue resend; /* requests waiting to resend */ |
| 143 | 157 | struct rpc_wait_queue pending; /* requests in flight */ |
| @@ -205,6 +219,8 @@ struct rpc_xprt { · 61 unmodified lines | ||
| 205 | 219 | void (*old_data_ready)(struct sock *, int); |
| 206 | 220 | void (*old_state_change)(struct sock *); |
| 207 | 221 | void (*old_write_space)(struct sock *); |
| 222 | + | |
| 223 | + char * address_strings[RPC_DISPLAY_MAX]; | |
| 208 | 224 | }; |
| 209 | 225 | |
| 210 | 226 | #define XPRT_LAST_FRAG (1 << 0) |
| @@ -217,12 +233,12 @@ struct rpc_xprt { · 6 unmodified lines | ||
| 217 | 233 | /* |
| 218 | 234 | * Transport operations used by ULPs |
| 219 | 235 | */ |
| 220 | −struct rpc_xprt * xprt_create_proto(int proto, struct sockaddr_in *addr, struct rpc_timeout *to); | |
| 221 | 236 | void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr); |
| 222 | 237 | |
| 223 | 238 | /* |
| 224 | 239 | * Generic internal transport functions |
| 225 | 240 | */ |
| 241 | +struct rpc_xprt * xprt_create_transport(int proto, struct sockaddr *addr, size_t size, struct rpc_timeout *toparms); | |
| 226 | 242 | void xprt_connect(struct rpc_task *task); |
| 227 | 243 | void xprt_reserve(struct rpc_task *task); |
| 228 | 244 | int xprt_reserve_xprt(struct rpc_task *task); |
| @@ -234,7 +250,8 @@ int xprt_adjust_timeout(struct rpc_rqst *req); · 5 unmodified lines | ||
| 234 | 250 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); |
| 235 | 251 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); |
| 236 | 252 | void xprt_release(struct rpc_task *task); |
| 237 | −int xprt_destroy(struct rpc_xprt *xprt); | |
| 253 | +struct rpc_xprt * xprt_get(struct rpc_xprt *xprt); | |
| 254 | +void xprt_put(struct rpc_xprt *xprt); | |
| 238 | 255 | |
| 239 | 256 | static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p) |
| 240 | 257 | { |
| @@ -269,6 +286,8 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to); · 28 unmodified lines | ||
| 269 | 286 | #define XPRT_CONNECTED (1) |
| 270 | 287 | #define XPRT_CONNECTING (2) |
| 271 | 288 | #define XPRT_CLOSE_WAIT (3) |
| 289 | +#define XPRT_BOUND (4) | |
| 290 | +#define XPRT_BINDING (5) | |
| 272 | 291 | |
| 273 | 292 | static inline void xprt_set_connected(struct rpc_xprt *xprt) |
| 274 | 293 | { |
| @@ -312,6 +331,33 @@ static inline int xprt_test_and_set_connecting(struct rpc_xprt *xprt) · 37 unmodified lines | ||
| 312 | 331 | return test_and_set_bit(XPRT_CONNECTING, &xprt->state); |
| 313 | 332 | } |
| 314 | 333 | |
| 334 | +static inline void xprt_set_bound(struct rpc_xprt *xprt) | |
| 335 | +{ | |
| 336 | + test_and_set_bit(XPRT_BOUND, &xprt->state); | |
| 337 | +} | |
| 338 | + | |
| 339 | +static inline int xprt_bound(struct rpc_xprt *xprt) | |
| 340 | +{ | |
| 341 | + return test_bit(XPRT_BOUND, &xprt->state); | |
| 342 | +} | |
| 343 | + | |
| 344 | +static inline void xprt_clear_bound(struct rpc_xprt *xprt) | |
| 345 | +{ | |
| 346 | + clear_bit(XPRT_BOUND, &xprt->state); | |
| 347 | +} | |
| 348 | + | |
| 349 | +static inline void xprt_clear_binding(struct rpc_xprt *xprt) | |
| 350 | +{ | |
| 351 | + smp_mb__before_clear_bit(); | |
| 352 | + clear_bit(XPRT_BINDING, &xprt->state); | |
| 353 | + smp_mb__after_clear_bit(); | |
| 354 | +} | |
| 355 | + | |
| 356 | +static inline int xprt_test_and_set_binding(struct rpc_xprt *xprt) | |
| 357 | +{ | |
| 358 | + return test_and_set_bit(XPRT_BINDING, &xprt->state); | |
| 359 | +} | |
| 360 | + | |
| 315 | 361 | #endif /* __KERNEL__*/ |
| 316 | 362 | |
| 317 | 363 | #endif /* _LINUX_SUNRPC_XPRT_H */ |
| @@ -411,6 +411,10 @@ enum · 410 unmodified lines | ||
| 411 | 411 | NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115, |
| 412 | 412 | NET_TCP_DMA_COPYBREAK=116, |
| 413 | 413 | NET_TCP_SLOW_START_AFTER_IDLE=117, |
| 414 | + NET_CIPSOV4_CACHE_ENABLE=118, | |
| 415 | + NET_CIPSOV4_CACHE_BUCKET_SIZE=119, | |
| 416 | + NET_CIPSOV4_RBM_OPTFMT=120, | |
| 417 | + NET_CIPSOV4_RBM_STRICTVALID=121, | |
| 414 | 418 | }; |
| 415 | 419 | |
| 416 | 420 | enum { |
| @@ -552,6 +556,7 @@ enum { · 135 unmodified lines | ||
| 552 | 556 | NET_IPV6_ACCEPT_RA_RTR_PREF=20, |
| 553 | 557 | NET_IPV6_RTR_PROBE_INTERVAL=21, |
| 554 | 558 | NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22, |
| 559 | + NET_IPV6_PROXY_NDP=23, | |
| 555 | 560 | __NET_IPV6_MAX |
| 556 | 561 | }; |
| 557 | 562 | |
| @@ -85,6 +85,7 @@ int wakeup_pdflush(long nr_pages); · 84 unmodified lines | ||
| 85 | 85 | void laptop_io_completion(void); |
| 86 | 86 | void laptop_sync_completion(void); |
| 87 | 87 | void throttle_vm_writeout(void); |
| 88 | +void writeback_congestion_end(void); | |
| 88 | 89 | |
| 89 | 90 | /* These are exported to sysctl. */ |
| 90 | 91 | extern int dirty_background_ratio; |
| @@ -102,6 +102,13 @@ struct xfrm_stats { · 101 unmodified lines | ||
| 102 | 102 | __u32 integrity_failed; |
| 103 | 103 | }; |
| 104 | 104 | |
| 105 | +enum | |
| 106 | +{ | |
| 107 | + XFRM_POLICY_TYPE_MAIN = 0, | |
| 108 | + XFRM_POLICY_TYPE_SUB = 1, | |
| 109 | + XFRM_POLICY_TYPE_MAX = 2 | |
| 110 | +}; | |
| 111 | + | |
| 105 | 112 | enum |
| 106 | 113 | { |
| 107 | 114 | XFRM_POLICY_IN = 0, |
| @@ -120,7 +127,9 @@ enum · 12 unmodified lines | ||
| 120 | 127 | |
| 121 | 128 | #define XFRM_MODE_TRANSPORT 0 |
| 122 | 129 | #define XFRM_MODE_TUNNEL 1 |
| 123 | −#define XFRM_MODE_MAX 2 | |
| 130 | +#define XFRM_MODE_ROUTEOPTIMIZATION 2 | |
| 131 | +#define XFRM_MODE_IN_TRIGGER 3 | |
| 132 | +#define XFRM_MODE_MAX 4 | |
| 124 | 133 | |
| 125 | 134 | /* Netlink configuration messages. */ |
| 126 | 135 | enum { |
| @@ -164,6 +173,10 @@ enum { · 37 unmodified lines | ||
| 164 | 173 | #define XFRM_MSG_NEWAE XFRM_MSG_NEWAE |
| 165 | 174 | XFRM_MSG_GETAE, |
| 166 | 175 | #define XFRM_MSG_GETAE XFRM_MSG_GETAE |
| 176 | + | |
| 177 | + XFRM_MSG_REPORT, | |
| 178 | +#define XFRM_MSG_REPORT XFRM_MSG_REPORT | |
| 179 | + | |
| 167 | 180 | __XFRM_MSG_MAX |
| 168 | 181 | }; |
| 169 | 182 | #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) |
| @@ -217,6 +230,12 @@ enum xfrm_ae_ftype_t { · 47 unmodified lines | ||
| 217 | 230 | #define XFRM_AE_MAX (__XFRM_AE_MAX - 1) |
| 218 | 231 | }; |
| 219 | 232 | |
| 233 | +struct xfrm_userpolicy_type { | |
| 234 | + __u8 type; | |
| 235 | + __u16 reserved1; | |
| 236 | + __u8 reserved2; | |
| 237 | +}; | |
| 238 | + | |
| 220 | 239 | /* Netlink message attributes. */ |
| 221 | 240 | enum xfrm_attr_type_t { |
| 222 | 241 | XFRMA_UNSPEC, |
| @@ -232,6 +251,10 @@ enum xfrm_attr_type_t { · 9 unmodified lines | ||
| 232 | 251 | XFRMA_REPLAY_VAL, |
| 233 | 252 | XFRMA_REPLAY_THRESH, |
| 234 | 253 | XFRMA_ETIMER_THRESH, |
| 254 | + XFRMA_SRCADDR, /* xfrm_address_t */ | |
| 255 | + XFRMA_COADDR, /* xfrm_address_t */ | |
| 256 | + XFRMA_LASTUSED, | |
| 257 | + XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ | |
| 235 | 258 | __XFRMA_MAX |
| 236 | 259 | |
| 237 | 260 | #define XFRMA_MAX (__XFRMA_MAX - 1) |
| @@ -247,12 +270,13 @@ struct xfrm_usersa_info { · 9 unmodified lines | ||
| 247 | 270 | __u32 seq; |
| 248 | 271 | __u32 reqid; |
| 249 | 272 | __u16 family; |
| 250 | − __u8 mode; /* 0=transport,1=tunnel */ | |
| 273 | + __u8 mode; /* XFRM_MODE_xxx */ | |
| 251 | 274 | __u8 replay_window; |
| 252 | 275 | __u8 flags; |
| 253 | 276 | #define XFRM_STATE_NOECN 1 |
| 254 | 277 | #define XFRM_STATE_DECAP_DSCP 2 |
| 255 | 278 | #define XFRM_STATE_NOPMTUDISC 4 |
| 279 | +#define XFRM_STATE_WILDRECV 8 | |
| 256 | 280 | }; |
| 257 | 281 | |
| 258 | 282 | struct xfrm_usersa_id { |
| @@ -319,12 +343,18 @@ struct xfrm_usersa_flush { · 60 unmodified lines | ||
| 319 | 343 | __u8 proto; |
| 320 | 344 | }; |
| 321 | 345 | |
| 346 | +struct xfrm_user_report { | |
| 347 | + __u8 proto; | |
| 348 | + struct xfrm_selector sel; | |
| 349 | +}; | |
| 350 | + | |
| 322 | 351 | #ifndef __KERNEL__ |
| 323 | 352 | /* backwards compatibility for userspace */ |
| 324 | 353 | #define XFRMGRP_ACQUIRE 1 |
| 325 | 354 | #define XFRMGRP_EXPIRE 2 |
| 326 | 355 | #define XFRMGRP_SA 4 |
| 327 | 356 | #define XFRMGRP_POLICY 8 |
| 357 | +#define XFRMGRP_REPORT 0x10 | |
| 328 | 358 | #endif |
| 329 | 359 | |
| 330 | 360 | enum xfrm_nlgroups { |
| @@ -340,6 +370,8 @@ enum xfrm_nlgroups { · 9 unmodified lines | ||
| 340 | 370 | #define XFRMNLGRP_POLICY XFRMNLGRP_POLICY |
| 341 | 371 | XFRMNLGRP_AEVENTS, |
| 342 | 372 | #define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS |
| 373 | + XFRMNLGRP_REPORT, | |
| 374 | +#define XFRMNLGRP_REPORT XFRMNLGRP_REPORT | |
| 343 | 375 | __XFRMNLGRP_MAX |
| 344 | 376 | }; |
| 345 | 377 | #define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) |
| @@ -8,70 +8,110 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <net/sch_generic.h> |
| 9 | 9 | #include <net/pkt_sched.h> |
| 10 | 10 | |
| 11 | −#define tca_gen(name) \ | |
| 12 | −struct tcf_##name *next; \ | |
| 13 | − u32 index; \ | |
| 14 | − int refcnt; \ | |
| 15 | − int bindcnt; \ | |
| 16 | − u32 capab; \ | |
| 17 | − int action; \ | |
| 18 | − struct tcf_t tm; \ | |
| 19 | − struct gnet_stats_basic bstats; \ | |
| 20 | − struct gnet_stats_queue qstats; \ | |
| 21 | − struct gnet_stats_rate_est rate_est; \ | |
| 22 | − spinlock_t *stats_lock; \ | |
| 23 | − spinlock_t lock | |
| 24 | − | |
| 25 | −struct tcf_police | |
| 26 | −{ | |
| 27 | − tca_gen(police); | |
| 28 | − int result; | |
| 29 | − u32 ewma_rate; | |
| 30 | − u32 burst; | |
| 31 | − u32 mtu; | |
| 32 | − u32 toks; | |
| 33 | − u32 ptoks; | |
| 34 | − psched_time_t t_c; | |
| 35 | − struct qdisc_rate_table *R_tab; | |
| 36 | − struct qdisc_rate_table *P_tab; | |
| 11 | +struct tcf_common { | |
| 12 | + struct tcf_common *tcfc_next; | |
| 13 | + u32 tcfc_index; | |
| 14 | + int tcfc_refcnt; | |
| 15 | + int tcfc_bindcnt; | |
| 16 | + u32 tcfc_capab; | |
| 17 | + int tcfc_action; | |
| 18 | + struct tcf_t tcfc_tm; | |
| 19 | + struct gnet_stats_basic tcfc_bstats; | |
| 20 | + struct gnet_stats_queue tcfc_qstats; | |
| 21 | + struct gnet_stats_rate_est tcfc_rate_est; | |
| 22 | + spinlock_t *tcfc_stats_lock; | |
| 23 | + spinlock_t tcfc_lock; | |
| 24 | +}; | |
| 25 | +#define tcf_next common.tcfc_next | |
| 26 | +#define tcf_index common.tcfc_index | |
| 27 | +#define tcf_refcnt common.tcfc_refcnt | |
| 28 | +#define tcf_bindcnt common.tcfc_bindcnt | |
| 29 | +#define tcf_capab common.tcfc_capab | |
| 30 | +#define tcf_action common.tcfc_action | |
| 31 | +#define tcf_tm common.tcfc_tm | |
| 32 | +#define tcf_bstats common.tcfc_bstats | |
| 33 | +#define tcf_qstats common.tcfc_qstats | |
| 34 | +#define tcf_rate_est common.tcfc_rate_est | |
| 35 | +#define tcf_stats_lock common.tcfc_stats_lock | |
| 36 | +#define tcf_lock common.tcfc_lock | |
| 37 | + | |
| 38 | +struct tcf_police { | |
| 39 | + struct tcf_common common; | |
| 40 | + int tcfp_result; | |
| 41 | + u32 tcfp_ewma_rate; | |
| 42 | + u32 tcfp_burst; | |
| 43 | + u32 tcfp_mtu; | |
| 44 | + u32 tcfp_toks; | |
| 45 | + u32 tcfp_ptoks; | |
| 46 | + psched_time_t tcfp_t_c; | |
| 47 | + struct qdisc_rate_table *tcfp_R_tab; | |
| 48 | + struct qdisc_rate_table *tcfp_P_tab; | |
| 37 | 49 | }; |
| 50 | +#define to_police(pc) \ | |
| 51 | + container_of(pc, struct tcf_police, common) | |
| 52 | + | |
| 53 | +struct tcf_hashinfo { | |
| 54 | + struct tcf_common **htab; | |
| 55 | + unsigned int hmask; | |
| 56 | + rwlock_t *lock; | |
| 57 | +}; | |
| 58 | + | |
| 59 | +static inline unsigned int tcf_hash(u32 index, unsigned int hmask) | |
| 60 | +{ | |
| 61 | + return index & hmask; | |
| 62 | +} | |
| 38 | 63 | |
| 39 | 64 | #ifdef CONFIG_NET_CLS_ACT |
| 40 | 65 | |
| 41 | 66 | #define ACT_P_CREATED 1 |
| 42 | 67 | #define ACT_P_DELETED 1 |
| 43 | 68 | |
| 44 | −struct tcf_act_hdr | |
| 45 | −{ | |
| 46 | − tca_gen(act_hdr); | |
| 69 | +struct tcf_act_hdr { | |
| 70 | + struct tcf_common common; | |
| 47 | 71 | }; |
| 48 | 72 | |
| 49 | −struct tc_action | |
| 50 | −{ | |
| 51 | − void *priv; | |
| 52 | − struct tc_action_ops *ops; | |
| 53 | − __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ | |
| 54 | − __u32 order; | |
| 55 | − struct tc_action *next; | |
| 73 | +struct tc_action { | |
| 74 | + void *priv; | |
| 75 | + struct tc_action_ops *ops; | |
| 76 | + __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ | |
| 77 | + __u32 order; | |
| 78 | + struct tc_action *next; | |
| 56 | 79 | }; |
| 57 | 80 | |
| 58 | 81 | #define TCA_CAP_NONE 0 |
| 59 | −struct tc_action_ops | |
| 60 | −{ | |
| 82 | +struct tc_action_ops { | |
| 61 | 83 | struct tc_action_ops *next; |
| 84 | + struct tcf_hashinfo *hinfo; | |
| 62 | 85 | char kind[IFNAMSIZ]; |
| 63 | 86 | __u32 type; /* TBD to match kind */ |
| 64 | 87 | __u32 capab; /* capabilities includes 4 bit version */ |
| 65 | 88 | struct module *owner; |
| 66 | 89 | int (*act)(struct sk_buff *, struct tc_action *, struct tcf_result *); |
| 67 | 90 | int (*get_stats)(struct sk_buff *, struct tc_action *); |
| 68 | − int (*dump)(struct sk_buff *, struct tc_action *,int , int); | |
| 91 | + int (*dump)(struct sk_buff *, struct tc_action *, int, int); | |
| 69 | 92 | int (*cleanup)(struct tc_action *, int bind); |
| 70 | − int (*lookup)(struct tc_action *, u32 ); | |
| 71 | − int (*init)(struct rtattr *,struct rtattr *,struct tc_action *, int , int ); | |
| 72 | − int (*walk)(struct sk_buff *, struct netlink_callback *, int , struct tc_action *); | |
| 93 | + int (*lookup)(struct tc_action *, u32); | |
| 94 | + int (*init)(struct rtattr *, struct rtattr *, struct tc_action *, int , int); | |
| 95 | + int (*walk)(struct sk_buff *, struct netlink_callback *, int, struct tc_action *); | |
| 73 | 96 | }; |
| 74 | 97 | |
| 98 | +extern struct tcf_common *tcf_hash_lookup(u32 index, | |
| 99 | + struct tcf_hashinfo *hinfo); | |
| 100 | +extern void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo); | |
| 101 | +extern int tcf_hash_release(struct tcf_common *p, int bind, | |
| 102 | + struct tcf_hashinfo *hinfo); | |
| 103 | +extern int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, | |
| 104 | + int type, struct tc_action *a); | |
| 105 | +extern u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo); | |
| 106 | +extern int tcf_hash_search(struct tc_action *a, u32 index); | |
| 107 | +extern struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, | |
| 108 | + int bind, struct tcf_hashinfo *hinfo); | |
| 109 | +extern struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, | |
| 110 | + struct tc_action *a, int size, | |
| 111 | + int bind, u32 *idx_gen, | |
| 112 | + struct tcf_hashinfo *hinfo); | |
| 113 | +extern void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo); | |
| 114 | + | |
| 75 | 115 | extern int tcf_register_action(struct tc_action_ops *a); |
| 76 | 116 | extern int tcf_unregister_action(struct tc_action_ops *a); |
| 77 | 117 | extern void tcf_action_destroy(struct tc_action *a, int bind); |
| @@ -96,17 +136,17 @@ tcf_police_release(struct tcf_police *p, int bind) · 18 unmodified lines | ||
| 96 | 136 | int ret = 0; |
| 97 | 137 | #ifdef CONFIG_NET_CLS_ACT |
| 98 | 138 | if (p) { |
| 99 | − if (bind) { | |
| 100 | − p->bindcnt--; | |
| 101 | − } | |
| 102 | − p->refcnt--; | |
| 103 | − if (p->refcnt <= 0 && !p->bindcnt) { | |
| 139 | + if (bind) | |
| 140 | + p->tcf_bindcnt--; | |
| 141 | + | |
| 142 | + p->tcf_refcnt--; | |
| 143 | + if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) { | |
| 104 | 144 | tcf_police_destroy(p); |
| 105 | 145 | ret = 1; |
| 106 | 146 | } |
| 107 | 147 | } |
| 108 | 148 | #else |
| 109 | − if (p && --p->refcnt == 0) | |
| 149 | + if (p && --p->tcf_refcnt == 0) | |
| 110 | 150 | tcf_police_destroy(p); |
| 111 | 151 | |
| 112 | 152 | #endif /* CONFIG_NET_CLS_ACT */ |
| @@ -1,142 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * include/net/act_generic.h | |
| 3 | − * | |
| 4 | −*/ | |
| 5 | −#ifndef _NET_ACT_GENERIC_H | |
| 6 | −#define _NET_ACT_GENERIC_H | |
| 7 | −static inline int tcf_defact_release(struct tcf_defact *p, int bind) | |
| 8 | −{ | |
| 9 | − int ret = 0; | |
| 10 | − if (p) { | |
| 11 | − if (bind) { | |
| 12 | − p->bindcnt--; | |
| 13 | − } | |
| 14 | − p->refcnt--; | |
| 15 | − if (p->bindcnt <= 0 && p->refcnt <= 0) { | |
| 16 | − kfree(p->defdata); | |
| 17 | − tcf_hash_destroy(p); | |
| 18 | − ret = 1; | |
| 19 | − } | |
| 20 | − } | |
| 21 | − return ret; | |
| 22 | −} | |
| 23 | − | |
| 24 | −static inline int | |
| 25 | −alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata) | |
| 26 | −{ | |
| 27 | − p->defdata = kmalloc(datalen, GFP_KERNEL); | |
| 28 | − if (p->defdata == NULL) | |
| 29 | − return -ENOMEM; | |
| 30 | − p->datalen = datalen; | |
| 31 | − memcpy(p->defdata, defdata, datalen); | |
| 32 | − return 0; | |
| 33 | −} | |
| 34 | − | |
| 35 | −static inline int | |
| 36 | −realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata) | |
| 37 | −{ | |
| 38 | − /* safer to be just brute force for now */ | |
| 39 | − kfree(p->defdata); | |
| 40 | − return alloc_defdata(p, datalen, defdata); | |
| 41 | −} | |
| 42 | − | |
| 43 | −static inline int | |
| 44 | −tcf_defact_init(struct rtattr *rta, struct rtattr *est, | |
| 45 | − struct tc_action *a, int ovr, int bind) | |
| 46 | −{ | |
| 47 | − struct rtattr *tb[TCA_DEF_MAX]; | |
| 48 | − struct tc_defact *parm; | |
| 49 | − struct tcf_defact *p; | |
| 50 | − void *defdata; | |
| 51 | − u32 datalen = 0; | |
| 52 | − int ret = 0; | |
| 53 | − | |
| 54 | − if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0) | |
| 55 | − return -EINVAL; | |
| 56 | − | |
| 57 | − if (tb[TCA_DEF_PARMS - 1] == NULL || | |
| 58 | − RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm)) | |
| 59 | − return -EINVAL; | |
| 60 | − | |
| 61 | − parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]); | |
| 62 | − defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]); | |
| 63 | − if (defdata == NULL) | |
| 64 | − return -EINVAL; | |
| 65 | − | |
| 66 | − datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]); | |
| 67 | − if (datalen <= 0) | |
| 68 | − return -EINVAL; | |
| 69 | − | |
| 70 | − p = tcf_hash_check(parm->index, a, ovr, bind); | |
| 71 | − if (p == NULL) { | |
| 72 | − p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); | |
| 73 | − if (p == NULL) | |
| 74 | − return -ENOMEM; | |
| 75 | − | |
| 76 | − ret = alloc_defdata(p, datalen, defdata); | |
| 77 | − if (ret < 0) { | |
| 78 | − kfree(p); | |
| 79 | − return ret; | |
| 80 | − } | |
| 81 | − ret = ACT_P_CREATED; | |
| 82 | − } else { | |
| 83 | − if (!ovr) { | |
| 84 | − tcf_defact_release(p, bind); | |
| 85 | − return -EEXIST; | |
| 86 | − } | |
| 87 | − realloc_defdata(p, datalen, defdata); | |
| 88 | − } | |
| 89 | − | |
| 90 | − spin_lock_bh(&p->lock); | |
| 91 | − p->action = parm->action; | |
| 92 | − spin_unlock_bh(&p->lock); | |
| 93 | − if (ret == ACT_P_CREATED) | |
| 94 | − tcf_hash_insert(p); | |
| 95 | − return ret; | |
| 96 | −} | |
| 97 | − | |
| 98 | −static inline int tcf_defact_cleanup(struct tc_action *a, int bind) | |
| 99 | −{ | |
| 100 | − struct tcf_defact *p = PRIV(a, defact); | |
| 101 | − | |
| 102 | − if (p != NULL) | |
| 103 | − return tcf_defact_release(p, bind); | |
| 104 | − return 0; | |
| 105 | −} | |
| 106 | − | |
| 107 | −static inline int | |
| 108 | −tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | |
| 109 | −{ | |
| 110 | − unsigned char *b = skb->tail; | |
| 111 | − struct tc_defact opt; | |
| 112 | − struct tcf_defact *p = PRIV(a, defact); | |
| 113 | − struct tcf_t t; | |
| 114 | − | |
| 115 | − opt.index = p->index; | |
| 116 | − opt.refcnt = p->refcnt - ref; | |
| 117 | − opt.bindcnt = p->bindcnt - bind; | |
| 118 | − opt.action = p->action; | |
| 119 | − RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt); | |
| 120 | − RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata); | |
| 121 | − t.install = jiffies_to_clock_t(jiffies - p->tm.install); | |
| 122 | − t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); | |
| 123 | − t.expires = jiffies_to_clock_t(p->tm.expires); | |
| 124 | − RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t); | |
| 125 | − return skb->len; | |
| 126 | − | |
| 127 | −rtattr_failure: | |
| 128 | − skb_trim(skb, b - skb->data); | |
| 129 | − return -1; | |
| 130 | −} | |
| 131 | − | |
| 132 | −#define tca_use_default_ops \ | |
| 133 | − .dump = tcf_defact_dump, \ | |
| 134 | − .cleanup = tcf_defact_cleanup, \ | |
| 135 | − .init = tcf_defact_init, \ | |
| 136 | − .walk = tcf_generic_walker, \ | |
| 137 | − | |
| 138 | −#define tca_use_default_defines(name) \ | |
| 139 | − static u32 idx_gen; \ | |
| 140 | − static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \ | |
| 141 | − static DEFINE_RWLOCK(##name_lock); | |
| 142 | −#endif /* _NET_ACT_GENERIC_H */ | |
| @@ -61,6 +61,9 @@ extern int addrconf_set_dstaddr(void __user *arg); · 60 unmodified lines | ||
| 61 | 61 | extern int ipv6_chk_addr(struct in6_addr *addr, |
| 62 | 62 | struct net_device *dev, |
| 63 | 63 | int strict); |
| 64 | +#ifdef CONFIG_IPV6_MIP6 | |
| 65 | +extern int ipv6_chk_home_addr(struct in6_addr *addr); | |
| 66 | +#endif | |
| 64 | 67 | extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, |
| 65 | 68 | struct net_device *dev, |
| 66 | 69 | int strict); |
| @@ -126,20 +129,18 @@ extern int unregister_inet6addr_notifier(struct notifier_block *nb); · 59 unmodified lines | ||
| 126 | 129 | static inline struct inet6_dev * |
| 127 | 130 | __in6_dev_get(struct net_device *dev) |
| 128 | 131 | { |
| 129 | − return (struct inet6_dev *)dev->ip6_ptr; | |
| 132 | + return rcu_dereference(dev->ip6_ptr); | |
| 130 | 133 | } |
| 131 | 134 | |
| 132 | −extern rwlock_t addrconf_lock; | |
| 133 | − | |
| 134 | 135 | static inline struct inet6_dev * |
| 135 | 136 | in6_dev_get(struct net_device *dev) |
| 136 | 137 | { |
| 137 | 138 | struct inet6_dev *idev = NULL; |
| 138 | − read_lock(&addrconf_lock); | |
| 139 | − idev = dev->ip6_ptr; | |
| 139 | + rcu_read_lock(); | |
| 140 | + idev = __in6_dev_get(dev); | |
| 140 | 141 | if (idev) |
| 141 | 142 | atomic_inc(&idev->refcnt); |
| 142 | − read_unlock(&addrconf_lock); | |
| 143 | + rcu_read_unlock(); | |
| 143 | 144 | return idev; |
| 144 | 145 | } |
| 145 | 146 | |
| @@ -0,0 +1,246 @@ | ||
| 1 | +/* | |
| 2 | + * CIPSO - Commercial IP Security Option | |
| 3 | + * | |
| 4 | + * This is an implementation of the CIPSO 2.2 protocol as specified in | |
| 5 | + * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in | |
| 6 | + * FIPS-188, copies of both documents can be found in the Documentation | |
| 7 | + * directory. While CIPSO never became a full IETF RFC standard many vendors | |
| 8 | + * have chosen to adopt the protocol and over the years it has become a | |
| 9 | + * de-facto standard for labeled networking. | |
| 10 | + * | |
| 11 | + * Author: Paul Moore <paul.moore@hp.com> | |
| 12 | + * | |
| 13 | + */ | |
| 14 | + | |
| 15 | +/* | |
| 16 | + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | |
| 17 | + * | |
| 18 | + * This program is free software; you can redistribute it and/or modify | |
| 19 | + * it under the terms of the GNU General Public License as published by | |
| 20 | + * the Free Software Foundation; either version 2 of the License, or | |
| 21 | + * (at your option) any later version. | |
| 22 | + * | |
| 23 | + * This program is distributed in the hope that it will be useful, | |
| 24 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 25 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | |
| 26 | + * the GNU General Public License for more details. | |
| 27 | + * | |
| 28 | + * You should have received a copy of the GNU General Public License | |
| 29 | + * along with this program; if not, write to the Free Software | |
| 30 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 31 | + * | |
| 32 | + */ | |
| 33 | + | |
| 34 | +#ifndef _CIPSO_IPV4_H | |
| 35 | +#define _CIPSO_IPV4_H | |
| 36 | + | |
| 37 | +#include <linux/types.h> | |
| 38 | +#include <linux/rcupdate.h> | |
| 39 | +#include <linux/list.h> | |
| 40 | +#include <linux/net.h> | |
| 41 | +#include <linux/skbuff.h> | |
| 42 | +#include <net/netlabel.h> | |
| 43 | + | |
| 44 | +/* known doi values */ | |
| 45 | +#define CIPSO_V4_DOI_UNKNOWN 0x00000000 | |
| 46 | + | |
| 47 | +/* tag types */ | |
| 48 | +#define CIPSO_V4_TAG_INVALID 0 | |
| 49 | +#define CIPSO_V4_TAG_RBITMAP 1 | |
| 50 | +#define CIPSO_V4_TAG_ENUM 2 | |
| 51 | +#define CIPSO_V4_TAG_RANGE 5 | |
| 52 | +#define CIPSO_V4_TAG_PBITMAP 6 | |
| 53 | +#define CIPSO_V4_TAG_FREEFORM 7 | |
| 54 | + | |
| 55 | +/* doi mapping types */ | |
| 56 | +#define CIPSO_V4_MAP_UNKNOWN 0 | |
| 57 | +#define CIPSO_V4_MAP_STD 1 | |
| 58 | +#define CIPSO_V4_MAP_PASS 2 | |
| 59 | + | |
| 60 | +/* limits */ | |
| 61 | +#define CIPSO_V4_MAX_REM_LVLS 256 | |
| 62 | +#define CIPSO_V4_INV_LVL 0x80000000 | |
| 63 | +#define CIPSO_V4_MAX_LOC_LVLS (CIPSO_V4_INV_LVL - 1) | |
| 64 | +#define CIPSO_V4_MAX_REM_CATS 65536 | |
| 65 | +#define CIPSO_V4_INV_CAT 0x80000000 | |
| 66 | +#define CIPSO_V4_MAX_LOC_CATS (CIPSO_V4_INV_CAT - 1) | |
| 67 | + | |
| 68 | +/* | |
| 69 | + * CIPSO DOI definitions | |
| 70 | + */ | |
| 71 | + | |
| 72 | +/* DOI definition struct */ | |
| 73 | +#define CIPSO_V4_TAG_MAXCNT 5 | |
| 74 | +struct cipso_v4_doi { | |
| 75 | + u32 doi; | |
| 76 | + u32 type; | |
| 77 | + union { | |
| 78 | + struct cipso_v4_std_map_tbl *std; | |
| 79 | + } map; | |
| 80 | + u8 tags[CIPSO_V4_TAG_MAXCNT]; | |
| 81 | + | |
| 82 | + u32 valid; | |
| 83 | + struct list_head list; | |
| 84 | + struct rcu_head rcu; | |
| 85 | + struct list_head dom_list; | |
| 86 | +}; | |
| 87 | + | |
| 88 | +/* Standard CIPSO mapping table */ | |
| 89 | +/* NOTE: the highest order bit (i.e. 0x80000000) is an 'invalid' flag, if the | |
| 90 | + * bit is set then consider that value as unspecified, meaning the | |
| 91 | + * mapping for that particular level/category is invalid */ | |
| 92 | +struct cipso_v4_std_map_tbl { | |
| 93 | + struct { | |
| 94 | + u32 *cipso; | |
| 95 | + u32 *local; | |
| 96 | + u32 cipso_size; | |
| 97 | + u32 local_size; | |
| 98 | + } lvl; | |
| 99 | + struct { | |
| 100 | + u32 *cipso; | |
| 101 | + u32 *local; | |
| 102 | + u32 cipso_size; | |
| 103 | + u32 local_size; | |
| 104 | + } cat; | |
| 105 | +}; | |
| 106 | + | |
| 107 | +/* | |
| 108 | + * Sysctl Variables | |
| 109 | + */ | |
| 110 | + | |
| 111 | +#ifdef CONFIG_NETLABEL | |
| 112 | +extern int cipso_v4_cache_enabled; | |
| 113 | +extern int cipso_v4_cache_bucketsize; | |
| 114 | +extern int cipso_v4_rbm_optfmt; | |
| 115 | +extern int cipso_v4_rbm_strictvalid; | |
| 116 | +#endif | |
| 117 | + | |
| 118 | +/* | |
| 119 | + * Helper Functions | |
| 120 | + */ | |
| 121 | + | |
| 122 | +#define CIPSO_V4_OPTEXIST(x) (IPCB(x)->opt.cipso != 0) | |
| 123 | +#define CIPSO_V4_OPTPTR(x) ((x)->nh.raw + IPCB(x)->opt.cipso) | |
| 124 | + | |
| 125 | +/* | |
| 126 | + * DOI List Functions | |
| 127 | + */ | |
| 128 | + | |
| 129 | +#ifdef CONFIG_NETLABEL | |
| 130 | +int cipso_v4_doi_add(struct cipso_v4_doi *doi_def); | |
| 131 | +int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head)); | |
| 132 | +struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi); | |
| 133 | +struct sk_buff *cipso_v4_doi_dump_all(size_t headroom); | |
| 134 | +struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom); | |
| 135 | +int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain); | |
| 136 | +int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, | |
| 137 | + const char *domain); | |
| 138 | +#else | |
| 139 | +static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) | |
| 140 | +{ | |
| 141 | + return -ENOSYS; | |
| 142 | +} | |
| 143 | + | |
| 144 | +static inline int cipso_v4_doi_remove(u32 doi, | |
| 145 | + void (*callback) (struct rcu_head * head)) | |
| 146 | +{ | |
| 147 | + return 0; | |
| 148 | +} | |
| 149 | + | |
| 150 | +static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) | |
| 151 | +{ | |
| 152 | + return NULL; | |
| 153 | +} | |
| 154 | + | |
| 155 | +static inline struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) | |
| 156 | +{ | |
| 157 | + return NULL; | |
| 158 | +} | |
| 159 | + | |
| 160 | +static inline struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom) | |
| 161 | +{ | |
| 162 | + return NULL; | |
| 163 | +} | |
| 164 | + | |
| 165 | +static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, | |
| 166 | + const char *domain) | |
| 167 | +{ | |
| 168 | + return -ENOSYS; | |
| 169 | +} | |
| 170 | + | |
| 171 | +static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, | |
| 172 | + const char *domain) | |
| 173 | +{ | |
| 174 | + return 0; | |
| 175 | +} | |
| 176 | +#endif /* CONFIG_NETLABEL */ | |
| 177 | + | |
| 178 | +/* | |
| 179 | + * Label Mapping Cache Functions | |
| 180 | + */ | |
| 181 | + | |
| 182 | +#ifdef CONFIG_NETLABEL | |
| 183 | +void cipso_v4_cache_invalidate(void); | |
| 184 | +int cipso_v4_cache_add(const struct sk_buff *skb, | |
| 185 | + const struct netlbl_lsm_secattr *secattr); | |
| 186 | +#else | |
| 187 | +static inline void cipso_v4_cache_invalidate(void) | |
| 188 | +{ | |
| 189 | + return; | |
| 190 | +} | |
| 191 | + | |
| 192 | +static inline int cipso_v4_cache_add(const struct sk_buff *skb, | |
| 193 | + const struct netlbl_lsm_secattr *secattr) | |
| 194 | +{ | |
| 195 | + return 0; | |
| 196 | +} | |
| 197 | +#endif /* CONFIG_NETLABEL */ | |
| 198 | + | |
| 199 | +/* | |
| 200 | + * Protocol Handling Functions | |
| 201 | + */ | |
| 202 | + | |
| 203 | +#ifdef CONFIG_NETLABEL | |
| 204 | +void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway); | |
| 205 | +int cipso_v4_socket_setattr(const struct socket *sock, | |
| 206 | + const struct cipso_v4_doi *doi_def, | |
| 207 | + const struct netlbl_lsm_secattr *secattr); | |
| 208 | +int cipso_v4_socket_getattr(const struct socket *sock, | |
| 209 | + struct netlbl_lsm_secattr *secattr); | |
| 210 | +int cipso_v4_skbuff_getattr(const struct sk_buff *skb, | |
| 211 | + struct netlbl_lsm_secattr *secattr); | |
| 212 | +int cipso_v4_validate(unsigned char **option); | |
| 213 | +#else | |
| 214 | +static inline void cipso_v4_error(struct sk_buff *skb, | |
| 215 | + int error, | |
| 216 | + u32 gateway) | |
| 217 | +{ | |
| 218 | + return; | |
| 219 | +} | |
| 220 | + | |
| 221 | +static inline int cipso_v4_socket_setattr(const struct socket *sock, | |
| 222 | + const struct cipso_v4_doi *doi_def, | |
| 223 | + const struct netlbl_lsm_secattr *secattr) | |
| 224 | +{ | |
| 225 | + return -ENOSYS; | |
| 226 | +} | |
| 227 | + | |
| 228 | +static inline int cipso_v4_socket_getattr(const struct socket *sock, | |
| 229 | + struct netlbl_lsm_secattr *secattr) | |
| 230 | +{ | |
| 231 | + return -ENOSYS; | |
| 232 | +} | |
| 233 | + | |
| 234 | +static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb, | |
| 235 | + struct netlbl_lsm_secattr *secattr) | |
| 236 | +{ | |
| 237 | + return -ENOSYS; | |
| 238 | +} | |
| 239 | + | |
| 240 | +static inline int cipso_v4_validate(unsigned char **option) | |
| 241 | +{ | |
| 242 | + return -ENOSYS; | |
| 243 | +} | |
| 244 | +#endif /* CONFIG_NETLABEL */ | |
| 245 | + | |
| 246 | +#endif /* _CIPSO_IPV4_H */ | |
| @@ -22,7 +22,7 @@ struct dn_kern_rta · 21 unmodified lines | ||
| 22 | 22 | }; |
| 23 | 23 | |
| 24 | 24 | struct dn_fib_res { |
| 25 | − struct dn_fib_rule *r; | |
| 25 | + struct fib_rule *r; | |
| 26 | 26 | struct dn_fib_info *fi; |
| 27 | 27 | unsigned char prefixlen; |
| 28 | 28 | unsigned char nh_sel; |
| @@ -94,7 +94,8 @@ struct dn_fib_node { · 65 unmodified lines | ||
| 94 | 94 | |
| 95 | 95 | |
| 96 | 96 | struct dn_fib_table { |
| 97 | − int n; | |
| 97 | + struct hlist_node hlist; | |
| 98 | + u32 n; | |
| 98 | 99 | |
| 99 | 100 | int (*insert)(struct dn_fib_table *t, struct rtmsg *r, |
| 100 | 101 | struct dn_kern_rta *rta, struct nlmsghdr *n, |
| @@ -130,14 +131,11 @@ extern __le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type); · 29 unmodified lines | ||
| 130 | 131 | extern void dn_fib_flush(void); |
| 131 | 132 | extern void dn_fib_select_multipath(const struct flowi *fl, |
| 132 | 133 | struct dn_fib_res *res); |
| 133 | −extern int dn_fib_sync_down(__le16 local, struct net_device *dev, | |
| 134 | − int force); | |
| 135 | −extern int dn_fib_sync_up(struct net_device *dev); | |
| 136 | 134 | |
| 137 | 135 | /* |
| 138 | 136 | * dn_tables.c |
| 139 | 137 | */ |
| 140 | −extern struct dn_fib_table *dn_fib_get_table(int n, int creat); | |
| 138 | +extern struct dn_fib_table *dn_fib_get_table(u32 n, int creat); | |
| 141 | 139 | extern struct dn_fib_table *dn_fib_empty_table(void); |
| 142 | 140 | extern void dn_fib_table_init(void); |
| 143 | 141 | extern void dn_fib_table_cleanup(void); |
| @@ -147,10 +145,8 @@ extern void dn_fib_table_cleanup(void); · 3 unmodified lines | ||
| 147 | 145 | */ |
| 148 | 146 | extern void dn_fib_rules_init(void); |
| 149 | 147 | extern void dn_fib_rules_cleanup(void); |
| 150 | −extern void dn_fib_rule_put(struct dn_fib_rule *); | |
| 151 | −extern __le16 dn_fib_rules_policy(__le16 saddr, struct dn_fib_res *res, unsigned *flags); | |
| 152 | 148 | extern unsigned dnet_addr_type(__le16 addr); |
| 153 | −extern int dn_fib_lookup(const struct flowi *fl, struct dn_fib_res *res); | |
| 149 | +extern int dn_fib_lookup(struct flowi *fl, struct dn_fib_res *res); | |
| 154 | 150 | |
| 155 | 151 | /* |
| 156 | 152 | * rtnetlink interface |
| @@ -176,11 +172,9 @@ static inline void dn_fib_res_put(struct dn_fib_res *res) · 19 unmodified lines | ||
| 176 | 172 | if (res->fi) |
| 177 | 173 | dn_fib_info_put(res->fi); |
| 178 | 174 | if (res->r) |
| 179 | − dn_fib_rule_put(res->r); | |
| 175 | + fib_rule_put(res->r); | |
| 180 | 176 | } |
| 181 | 177 | |
| 182 | −extern struct dn_fib_table *dn_fib_tables[]; | |
| 183 | − | |
| 184 | 178 | #else /* Endnode */ |
| 185 | 179 | |
| 186 | 180 | #define dn_fib_init() do { } while(0) |
| @@ -54,6 +54,7 @@ struct dst_entry · 53 unmodified lines | ||
| 54 | 54 | unsigned long expires; |
| 55 | 55 | |
| 56 | 56 | unsigned short header_len; /* more space at head required */ |
| 57 | + unsigned short nfheader_len; /* more non-fragment space at head required */ | |
| 57 | 58 | unsigned short trailer_len; /* space to reserve at tail */ |
| 58 | 59 | |
| 59 | 60 | u32 metrics[RTAX_MAX]; |
| @@ -15,13 +15,14 @@ struct esp_data · 14 unmodified lines | ||
| 15 | 15 | struct { |
| 16 | 16 | u8 *key; /* Key */ |
| 17 | 17 | int key_len; /* Key length */ |
| 18 | − u8 *ivec; /* ivec buffer */ | |
| 18 | + int padlen; /* 0..255 */ | |
| 19 | 19 | /* ivlen is offset from enc_data, where encrypted data start. |
| 20 | 20 | * It is logically different of crypto_tfm_alg_ivsize(tfm). |
| 21 | 21 | * We assume that it is either zero (no ivec), or |
| 22 | 22 | * >= crypto_tfm_alg_ivsize(tfm). */ |
| 23 | 23 | int ivlen; |
| 24 | − int padlen; /* 0..255 */ | |
| 24 | + int ivinitted; | |
| 25 | + u8 *ivec; /* ivec buffer */ | |
| 25 | 26 | struct crypto_blkcipher *tfm; /* crypto handle */ |
| 26 | 27 | } conf; |
| 27 | 28 | |
| @@ -0,0 +1,97 @@ | ||
| 1 | +#ifndef __NET_FIB_RULES_H | |
| 2 | +#define __NET_FIB_RULES_H | |
| 3 | + | |
| 4 | +#include <linux/types.h> | |
| 5 | +#include <linux/netdevice.h> | |
| 6 | +#include <linux/fib_rules.h> | |
| 7 | +#include <net/flow.h> | |
| 8 | +#include <net/netlink.h> | |
| 9 | + | |
| 10 | +struct fib_rule | |
| 11 | +{ | |
| 12 | + struct list_head list; | |
| 13 | + atomic_t refcnt; | |
| 14 | + int ifindex; | |
| 15 | + char ifname[IFNAMSIZ]; | |
| 16 | + u32 pref; | |
| 17 | + u32 flags; | |
| 18 | + u32 table; | |
| 19 | + u8 action; | |
| 20 | + struct rcu_head rcu; | |
| 21 | +}; | |
| 22 | + | |
| 23 | +struct fib_lookup_arg | |
| 24 | +{ | |
| 25 | + void *lookup_ptr; | |
| 26 | + void *result; | |
| 27 | + struct fib_rule *rule; | |
| 28 | +}; | |
| 29 | + | |
| 30 | +struct fib_rules_ops | |
| 31 | +{ | |
| 32 | + int family; | |
| 33 | + struct list_head list; | |
| 34 | + int rule_size; | |
| 35 | + | |
| 36 | + int (*action)(struct fib_rule *, | |
| 37 | + struct flowi *, int, | |
| 38 | + struct fib_lookup_arg *); | |
| 39 | + int (*match)(struct fib_rule *, | |
| 40 | + struct flowi *, int); | |
| 41 | + int (*configure)(struct fib_rule *, | |
| 42 | + struct sk_buff *, | |
| 43 | + struct nlmsghdr *, | |
| 44 | + struct fib_rule_hdr *, | |
| 45 | + struct nlattr **); | |
| 46 | + int (*compare)(struct fib_rule *, | |
| 47 | + struct fib_rule_hdr *, | |
| 48 | + struct nlattr **); | |
| 49 | + int (*fill)(struct fib_rule *, struct sk_buff *, | |
| 50 | + struct nlmsghdr *, | |
| 51 | + struct fib_rule_hdr *); | |
| 52 | + u32 (*default_pref)(void); | |
| 53 | + | |
| 54 | + int nlgroup; | |
| 55 | + struct nla_policy *policy; | |
| 56 | + struct list_head *rules_list; | |
| 57 | + struct module *owner; | |
| 58 | +}; | |
| 59 | + | |
| 60 | +static inline void fib_rule_get(struct fib_rule *rule) | |
| 61 | +{ | |
| 62 | + atomic_inc(&rule->refcnt); | |
| 63 | +} | |
| 64 | + | |
| 65 | +static inline void fib_rule_put_rcu(struct rcu_head *head) | |
| 66 | +{ | |
| 67 | + struct fib_rule *rule = container_of(head, struct fib_rule, rcu); | |
| 68 | + kfree(rule); | |
| 69 | +} | |
| 70 | + | |
| 71 | +static inline void fib_rule_put(struct fib_rule *rule) | |
| 72 | +{ | |
| 73 | + if (atomic_dec_and_test(&rule->refcnt)) | |
| 74 | + call_rcu(&rule->rcu, fib_rule_put_rcu); | |
| 75 | +} | |
| 76 | + | |
| 77 | +static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla) | |
| 78 | +{ | |
| 79 | + if (nla[FRA_TABLE]) | |
| 80 | + return nla_get_u32(nla[FRA_TABLE]); | |
| 81 | + return frh->table; | |
| 82 | +} | |
| 83 | + | |
| 84 | +extern int fib_rules_register(struct fib_rules_ops *); | |
| 85 | +extern int fib_rules_unregister(struct fib_rules_ops *); | |
| 86 | + | |
| 87 | +extern int fib_rules_lookup(struct fib_rules_ops *, | |
| 88 | + struct flowi *, int flags, | |
| 89 | + struct fib_lookup_arg *); | |
| 90 | + | |
| 91 | +extern int fib_nl_newrule(struct sk_buff *, | |
| 92 | + struct nlmsghdr *, void *); | |
| 93 | +extern int fib_nl_delrule(struct sk_buff *, | |
| 94 | + struct nlmsghdr *, void *); | |
| 95 | +extern int fib_rules_dump(struct sk_buff *, | |
| 96 | + struct netlink_callback *, int); | |
| 97 | +#endif | |
| @@ -26,6 +26,7 @@ struct flowi { · 25 unmodified lines | ||
| 26 | 26 | struct { |
| 27 | 27 | struct in6_addr daddr; |
| 28 | 28 | struct in6_addr saddr; |
| 29 | + __u32 fwmark; | |
| 29 | 30 | __u32 flowlabel; |
| 30 | 31 | } ip6_u; |
| 31 | 32 | |
| @@ -42,6 +43,7 @@ struct flowi { · 10 unmodified lines | ||
| 42 | 43 | #define fld_scope nl_u.dn_u.scope |
| 43 | 44 | #define fl6_dst nl_u.ip6_u.daddr |
| 44 | 45 | #define fl6_src nl_u.ip6_u.saddr |
| 46 | +#define fl6_fwmark nl_u.ip6_u.fwmark | |
| 45 | 47 | #define fl6_flowlabel nl_u.ip6_u.flowlabel |
| 46 | 48 | #define fl4_dst nl_u.ip4_u.daddr |
| 47 | 49 | #define fl4_src nl_u.ip4_u.saddr |
| @@ -72,12 +74,22 @@ struct flowi { · 24 unmodified lines | ||
| 72 | 74 | } dnports; |
| 73 | 75 | |
| 74 | 76 | __u32 spi; |
| 77 | + | |
| 78 | +#ifdef CONFIG_IPV6_MIP6 | |
| 79 | + struct { | |
| 80 | + __u8 type; | |
| 81 | + } mht; | |
| 82 | +#endif | |
| 75 | 83 | } uli_u; |
| 76 | 84 | #define fl_ip_sport uli_u.ports.sport |
| 77 | 85 | #define fl_ip_dport uli_u.ports.dport |
| 78 | 86 | #define fl_icmp_type uli_u.icmpt.type |
| 79 | 87 | #define fl_icmp_code uli_u.icmpt.code |
| 80 | 88 | #define fl_ipsec_spi uli_u.spi |
| 89 | +#ifdef CONFIG_IPV6_MIP6 | |
| 90 | +#define fl_mh_type uli_u.mht.type | |
| 91 | +#endif | |
| 92 | + __u32 secid; /* used by xfrm; see secid.txt */ | |
| 81 | 93 | } __attribute__((__aligned__(BITS_PER_LONG/8))); |
| 82 | 94 | |
| 83 | 95 | #define FLOW_DIR_IN 0 |
| @@ -85,10 +97,10 @@ struct flowi { · 1 unmodified line | ||
| 85 | 97 | #define FLOW_DIR_FWD 2 |
| 86 | 98 | |
| 87 | 99 | struct sock; |
| 88 | −typedef void (*flow_resolve_t)(struct flowi *key, u32 sk_sid, u16 family, u8 dir, | |
| 100 | +typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir, | |
| 89 | 101 | void **objp, atomic_t **obj_refp); |
| 90 | 102 | |
| 91 | −extern void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir, | |
| 103 | +extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, | |
| 92 | 104 | flow_resolve_t resolver); |
| 93 | 105 | extern void flow_cache_flush(void); |
| 94 | 106 | extern atomic_t flow_cache_genid; |
| @@ -27,8 +27,6 @@ struct genl_family · 26 unmodified lines | ||
| 27 | 27 | struct list_head family_list; /* private */ |
| 28 | 28 | }; |
| 29 | 29 | |
| 30 | −#define GENL_ADMIN_PERM 0x01 | |
| 31 | − | |
| 32 | 30 | /** |
| 33 | 31 | * struct genl_info - receiving information |
| 34 | 32 | * @snd_seq: sending sequence number |
| @@ -133,11 +131,12 @@ static inline int genlmsg_cancel(struct sk_buff *skb, void *hdr) · 98 unmodified lines | ||
| 133 | 131 | * @skb: netlink message as socket buffer |
| 134 | 132 | * @pid: own netlink pid to avoid sending to yourself |
| 135 | 133 | * @group: multicast group id |
| 134 | + * @flags: allocation flags | |
| 136 | 135 | */ |
| 137 | 136 | static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid, |
| 138 | − unsigned int group) | |
| 137 | + unsigned int group, gfp_t flags) | |
| 139 | 138 | { |
| 140 | − return nlmsg_multicast(genl_sock, skb, pid, group); | |
| 139 | + return nlmsg_multicast(genl_sock, skb, pid, group, flags); | |
| 141 | 140 | } |
| 142 | 141 | |
| 143 | 142 | /** |
| @@ -189,6 +189,7 @@ struct inet6_dev · 188 unmodified lines | ||
| 189 | 189 | struct ipv6_devconf cnf; |
| 190 | 190 | struct ipv6_devstat stats; |
| 191 | 191 | unsigned long tstamp; /* ipv6InterfaceTable update timestamp */ |
| 192 | + struct rcu_head rcu; | |
| 192 | 193 | }; |
| 193 | 194 | |
| 194 | 195 | extern struct ipv6_devconf ipv6_devconf; |
| @@ -147,7 +147,8 @@ extern struct sock *inet_csk_clone(struct sock *sk, · 146 unmodified lines | ||
| 147 | 147 | enum inet_csk_ack_state_t { |
| 148 | 148 | ICSK_ACK_SCHED = 1, |
| 149 | 149 | ICSK_ACK_TIMER = 2, |
| 150 | − ICSK_ACK_PUSHED = 4 | |
| 150 | + ICSK_ACK_PUSHED = 4, | |
| 151 | + ICSK_ACK_PUSHED2 = 8 | |
| 151 | 152 | }; |
| 152 | 153 | |
| 153 | 154 | extern void inet_csk_init_xmit_timers(struct sock *sk, |
| @@ -271,38 +271,15 @@ static inline int inet_iif(const struct sk_buff *skb) · 270 unmodified lines | ||
| 271 | 271 | return ((struct rtable *)skb->dst)->rt_iif; |
| 272 | 272 | } |
| 273 | 273 | |
| 274 | −extern struct sock *__inet_lookup_listener(const struct hlist_head *head, | |
| 274 | +extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo, | |
| 275 | 275 | const u32 daddr, |
| 276 | 276 | const unsigned short hnum, |
| 277 | 277 | const int dif); |
| 278 | 278 | |
| 279 | −/* Optimize the common listener case. */ | |
| 280 | −static inline struct sock * | |
| 281 | − inet_lookup_listener(struct inet_hashinfo *hashinfo, | |
| 282 | − const u32 daddr, | |
| 283 | − const unsigned short hnum, const int dif) | |
| 279 | +static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo, | |
| 280 | + u32 daddr, u16 dport, int dif) | |
| 284 | 281 | { |
| 285 | − struct sock *sk = NULL; | |
| 286 | − const struct hlist_head *head; | |
| 287 | − | |
| 288 | − read_lock(&hashinfo->lhash_lock); | |
| 289 | − head = &hashinfo->listening_hash[inet_lhashfn(hnum)]; | |
| 290 | − if (!hlist_empty(head)) { | |
| 291 | − const struct inet_sock *inet = inet_sk((sk = __sk_head(head))); | |
| 292 | − | |
| 293 | − if (inet->num == hnum && !sk->sk_node.next && | |
| 294 | − (!inet->rcv_saddr || inet->rcv_saddr == daddr) && | |
| 295 | − (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) && | |
| 296 | − !sk->sk_bound_dev_if) | |
| 297 | − goto sherry_cache; | |
| 298 | − sk = __inet_lookup_listener(head, daddr, hnum, dif); | |
| 299 | − } | |
| 300 | − if (sk) { | |
| 301 | −sherry_cache: | |
| 302 | − sock_hold(sk); | |
| 303 | − } | |
| 304 | − read_unlock(&hashinfo->lhash_lock); | |
| 305 | − return sk; | |
| 282 | + return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif); | |
| 306 | 283 | } |
| 307 | 284 | |
| 308 | 285 | /* Socket demux engine toys. */ |
| @@ -391,14 +368,25 @@ hit: · 82 unmodified lines | ||
| 391 | 368 | goto out; |
| 392 | 369 | } |
| 393 | 370 | |
| 371 | +static inline struct sock * | |
| 372 | + inet_lookup_established(struct inet_hashinfo *hashinfo, | |
| 373 | + const u32 saddr, const u16 sport, | |
| 374 | + const u32 daddr, const u16 dport, | |
| 375 | + const int dif) | |
| 376 | +{ | |
| 377 | + return __inet_lookup_established(hashinfo, saddr, sport, daddr, | |
| 378 | + ntohs(dport), dif); | |
| 379 | +} | |
| 380 | + | |
| 394 | 381 | static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo, |
| 395 | 382 | const u32 saddr, const u16 sport, |
| 396 | − const u32 daddr, const u16 hnum, | |
| 383 | + const u32 daddr, const u16 dport, | |
| 397 | 384 | const int dif) |
| 398 | 385 | { |
| 386 | + u16 hnum = ntohs(dport); | |
| 399 | 387 | struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr, |
| 400 | 388 | hnum, dif); |
| 401 | − return sk ? : inet_lookup_listener(hashinfo, daddr, hnum, dif); | |
| 389 | + return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif); | |
| 402 | 390 | } |
| 403 | 391 | |
| 404 | 392 | static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, |
| @@ -409,7 +397,7 @@ static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, · 4 unmodified lines | ||
| 409 | 397 | struct sock *sk; |
| 410 | 398 | |
| 411 | 399 | local_bh_disable(); |
| 412 | − sk = __inet_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif); | |
| 400 | + sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif); | |
| 413 | 401 | local_bh_enable(); |
| 414 | 402 | |
| 415 | 403 | return sk; |
| @@ -27,7 +27,6 @@ · 26 unmodified lines | ||
| 27 | 27 | /** struct ip_options - IP Options |
| 28 | 28 | * |
| 29 | 29 | * @faddr - Saved first hop address |
| 30 | − * @is_setbyuser - Set by setsockopt? | |
| 31 | 30 | * @is_data - Options in __data, rather than skb |
| 32 | 31 | * @is_strictroute - Strict source route |
| 33 | 32 | * @srr_is_hit - Packet destination addr was our one |
| @@ -42,8 +41,7 @@ struct ip_options { · 8 unmodified lines | ||
| 42 | 41 | unsigned char srr; |
| 43 | 42 | unsigned char rr; |
| 44 | 43 | unsigned char ts; |
| 45 | − unsigned char is_setbyuser:1, | |
| 46 | − is_data:1, | |
| 44 | + unsigned char is_data:1, | |
| 47 | 45 | is_strictroute:1, |
| 48 | 46 | srr_is_hit:1, |
| 49 | 47 | is_changed:1, |
| @@ -51,7 +49,7 @@ struct ip_options { · 1 unmodified line | ||
| 51 | 49 | ts_needtime:1, |
| 52 | 50 | ts_needaddr:1; |
| 53 | 51 | unsigned char router_alert; |
| 54 | − unsigned char __pad1; | |
| 52 | + unsigned char cipso; | |
| 55 | 53 | unsigned char __pad2; |
| 56 | 54 | unsigned char __data[0]; |
| 57 | 55 | }; |
| @@ -16,14 +16,35 @@ · 15 unmodified lines | ||
| 16 | 16 | #ifdef __KERNEL__ |
| 17 | 17 | |
| 18 | 18 | #include <linux/ipv6_route.h> |
| 19 | − | |
| 20 | −#include <net/dst.h> | |
| 21 | −#include <net/flow.h> | |
| 22 | 19 | #include <linux/rtnetlink.h> |
| 23 | 20 | #include <linux/spinlock.h> |
| 21 | +#include <net/dst.h> | |
| 22 | +#include <net/flow.h> | |
| 23 | +#include <net/netlink.h> | |
| 24 | 24 | |
| 25 | 25 | struct rt6_info; |
| 26 | 26 | |
| 27 | +struct fib6_config | |
| 28 | +{ | |
| 29 | + u32 fc_table; | |
| 30 | + u32 fc_metric; | |
| 31 | + int fc_dst_len; | |
| 32 | + int fc_src_len; | |
| 33 | + int fc_ifindex; | |
| 34 | + u32 fc_flags; | |
| 35 | + u32 fc_protocol; | |
| 36 | + | |
| 37 | + struct in6_addr fc_dst; | |
| 38 | + struct in6_addr fc_src; | |
| 39 | + struct in6_addr fc_gateway; | |
| 40 | + | |
| 41 | + unsigned long fc_expires; | |
| 42 | + struct nlattr *fc_mx; | |
| 43 | + int fc_mx_len; | |
| 44 | + | |
| 45 | + struct nl_info fc_nlinfo; | |
| 46 | +}; | |
| 47 | + | |
| 27 | 48 | struct fib6_node |
| 28 | 49 | { |
| 29 | 50 | struct fib6_node *parent; |
| @@ -39,6 +60,11 @@ struct fib6_node · 9 unmodified lines | ||
| 39 | 60 | __u32 fn_sernum; |
| 40 | 61 | }; |
| 41 | 62 | |
| 63 | +#ifndef CONFIG_IPV6_SUBTREES | |
| 64 | +#define FIB6_SUBTREE(fn) NULL | |
| 65 | +#else | |
| 66 | +#define FIB6_SUBTREE(fn) ((fn)->subtree) | |
| 67 | +#endif | |
| 42 | 68 | |
| 43 | 69 | /* |
| 44 | 70 | * routing information |
| @@ -51,6 +77,8 @@ struct rt6key · 6 unmodified lines | ||
| 51 | 77 | int plen; |
| 52 | 78 | }; |
| 53 | 79 | |
| 80 | +struct fib6_table; | |
| 81 | + | |
| 54 | 82 | struct rt6_info |
| 55 | 83 | { |
| 56 | 84 | union { |
| @@ -71,6 +99,7 @@ struct rt6_info · 14 unmodified lines | ||
| 71 | 99 | u32 rt6i_flags; |
| 72 | 100 | u32 rt6i_metric; |
| 73 | 101 | atomic_t rt6i_ref; |
| 102 | + struct fib6_table *rt6i_table; | |
| 74 | 103 | |
| 75 | 104 | struct rt6key rt6i_dst; |
| 76 | 105 | struct rt6key rt6i_src; |
| @@ -89,28 +118,6 @@ struct fib6_walker_t · 12 unmodified lines | ||
| 89 | 118 | void *args; |
| 90 | 119 | }; |
| 91 | 120 | |
| 92 | −extern struct fib6_walker_t fib6_walker_list; | |
| 93 | −extern rwlock_t fib6_walker_lock; | |
| 94 | − | |
| 95 | −static inline void fib6_walker_link(struct fib6_walker_t *w) | |
| 96 | −{ | |
| 97 | − write_lock_bh(&fib6_walker_lock); | |
| 98 | − w->next = fib6_walker_list.next; | |
| 99 | − w->prev = &fib6_walker_list; | |
| 100 | − w->next->prev = w; | |
| 101 | − w->prev->next = w; | |
| 102 | − write_unlock_bh(&fib6_walker_lock); | |
| 103 | −} | |
| 104 | − | |
| 105 | −static inline void fib6_walker_unlink(struct fib6_walker_t *w) | |
| 106 | −{ | |
| 107 | − write_lock_bh(&fib6_walker_lock); | |
| 108 | − w->next->prev = w->prev; | |
| 109 | − w->prev->next = w->next; | |
| 110 | − w->prev = w->next = w; | |
| 111 | − write_unlock_bh(&fib6_walker_lock); | |
| 112 | −} | |
| 113 | − | |
| 114 | 121 | struct rt6_statistics { |
| 115 | 122 | __u32 fib_nodes; |
| 116 | 123 | __u32 fib_route_nodes; |
| @@ -143,12 +150,41 @@ struct rt6_statistics { · 26 unmodified lines | ||
| 143 | 150 | |
| 144 | 151 | typedef void (*f_pnode)(struct fib6_node *fn, void *); |
| 145 | 152 | |
| 146 | −extern struct fib6_node ip6_routing_table; | |
| 153 | +struct fib6_table { | |
| 154 | + struct hlist_node tb6_hlist; | |
| 155 | + u32 tb6_id; | |
| 156 | + rwlock_t tb6_lock; | |
| 157 | + struct fib6_node tb6_root; | |
| 158 | +}; | |
| 159 | + | |
| 160 | +#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC | |
| 161 | +#define RT6_TABLE_MAIN RT_TABLE_MAIN | |
| 162 | +#define RT6_TABLE_DFLT RT6_TABLE_MAIN | |
| 163 | +#define RT6_TABLE_INFO RT6_TABLE_MAIN | |
| 164 | +#define RT6_TABLE_PREFIX RT6_TABLE_MAIN | |
| 165 | + | |
| 166 | +#ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
| 167 | +#define FIB6_TABLE_MIN 1 | |
| 168 | +#define FIB6_TABLE_MAX RT_TABLE_MAX | |
| 169 | +#define RT6_TABLE_LOCAL RT_TABLE_LOCAL | |
| 170 | +#else | |
| 171 | +#define FIB6_TABLE_MIN RT_TABLE_MAIN | |
| 172 | +#define FIB6_TABLE_MAX FIB6_TABLE_MIN | |
| 173 | +#define RT6_TABLE_LOCAL RT6_TABLE_MAIN | |
| 174 | +#endif | |
| 175 | + | |
| 176 | +typedef struct rt6_info *(*pol_lookup_t)(struct fib6_table *, | |
| 177 | + struct flowi *, int); | |
| 147 | 178 | |
| 148 | 179 | /* |
| 149 | 180 | * exported functions |
| 150 | 181 | */ |
| 151 | 182 | |
| 183 | +extern struct fib6_table * fib6_get_table(u32 id); | |
| 184 | +extern struct fib6_table * fib6_new_table(u32 id); | |
| 185 | +extern struct dst_entry * fib6_rule_lookup(struct flowi *fl, int flags, | |
| 186 | + pol_lookup_t lookup); | |
| 187 | + | |
| 152 | 188 | extern struct fib6_node *fib6_lookup(struct fib6_node *root, |
| 153 | 189 | struct in6_addr *daddr, |
| 154 | 190 | struct in6_addr *saddr); |
| @@ -157,32 +193,29 @@ struct fib6_node *fib6_locate(struct fib6_node *root, · 2 unmodified lines | ||
| 157 | 193 | struct in6_addr *daddr, int dst_len, |
| 158 | 194 | struct in6_addr *saddr, int src_len); |
| 159 | 195 | |
| 160 | −extern void fib6_clean_tree(struct fib6_node *root, | |
| 161 | − int (*func)(struct rt6_info *, void *arg), | |
| 162 | − int prune, void *arg); | |
| 163 | − | |
| 164 | −extern int fib6_walk(struct fib6_walker_t *w); | |
| 165 | −extern int fib6_walk_continue(struct fib6_walker_t *w); | |
| 196 | +extern void fib6_clean_all(int (*func)(struct rt6_info *, void *arg), | |
| 197 | + int prune, void *arg); | |
| 166 | 198 | |
| 167 | 199 | extern int fib6_add(struct fib6_node *root, |
| 168 | 200 | struct rt6_info *rt, |
| 169 | − struct nlmsghdr *nlh, | |
| 170 | − void *rtattr, | |
| 171 | − struct netlink_skb_parms *req); | |
| 201 | + struct nl_info *info); | |
| 172 | 202 | |
| 173 | 203 | extern int fib6_del(struct rt6_info *rt, |
| 174 | − struct nlmsghdr *nlh, | |
| 175 | − void *rtattr, | |
| 176 | − struct netlink_skb_parms *req); | |
| 204 | + struct nl_info *info); | |
| 177 | 205 | |
| 178 | 206 | extern void inet6_rt_notify(int event, struct rt6_info *rt, |
| 179 | − struct nlmsghdr *nlh, | |
| 180 | − struct netlink_skb_parms *req); | |
| 207 | + struct nl_info *info); | |
| 181 | 208 | |
| 182 | 209 | extern void fib6_run_gc(unsigned long dummy); |
| 183 | 210 | |
| 184 | 211 | extern void fib6_gc_cleanup(void); |
| 185 | 212 | |
| 186 | 213 | extern void fib6_init(void); |
| 214 | + | |
| 215 | +extern void fib6_rules_init(void); | |
| 216 | +extern void fib6_rules_cleanup(void); | |
| 217 | +extern int fib6_rules_dump(struct sk_buff *, | |
| 218 | + struct netlink_callback *); | |
| 219 | + | |
| 187 | 220 | #endif |
| 188 | 221 | #endif |
| @@ -32,6 +32,10 @@ struct route_info { · 31 unmodified lines | ||
| 32 | 32 | #include <linux/ip.h> |
| 33 | 33 | #include <linux/ipv6.h> |
| 34 | 34 | |
| 35 | +#define RT6_LOOKUP_F_IFACE 0x1 | |
| 36 | +#define RT6_LOOKUP_F_REACHABLE 0x2 | |
| 37 | +#define RT6_LOOKUP_F_HAS_SADDR 0x4 | |
| 38 | + | |
| 35 | 39 | struct pol_chain { |
| 36 | 40 | int type; |
| 37 | 41 | int priority; |
| @@ -41,6 +45,11 @@ struct pol_chain { · 3 unmodified lines | ||
| 41 | 45 | |
| 42 | 46 | extern struct rt6_info ip6_null_entry; |
| 43 | 47 | |
| 48 | +#ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
| 49 | +extern struct rt6_info ip6_prohibit_entry; | |
| 50 | +extern struct rt6_info ip6_blk_hole_entry; | |
| 51 | +#endif | |
| 52 | + | |
| 44 | 53 | extern int ip6_rt_gc_interval; |
| 45 | 54 | |
| 46 | 55 | extern void ip6_route_input(struct sk_buff *skb); |
| @@ -48,25 +57,14 @@ extern void ip6_route_input(struct sk_buff *skb); · 1 unmodified line | ||
| 48 | 57 | extern struct dst_entry * ip6_route_output(struct sock *sk, |
| 49 | 58 | struct flowi *fl); |
| 50 | 59 | |
| 51 | −extern int ip6_route_me_harder(struct sk_buff *skb); | |
| 52 | − | |
| 53 | 60 | extern void ip6_route_init(void); |
| 54 | 61 | extern void ip6_route_cleanup(void); |
| 55 | 62 | |
| 56 | 63 | extern int ipv6_route_ioctl(unsigned int cmd, void __user *arg); |
| 57 | 64 | |
| 58 | −extern int ip6_route_add(struct in6_rtmsg *rtmsg, | |
| 59 | − struct nlmsghdr *, | |
| 60 | − void *rtattr, | |
| 61 | − struct netlink_skb_parms *req); | |
| 62 | −extern int ip6_ins_rt(struct rt6_info *, | |
| 63 | − struct nlmsghdr *, | |
| 64 | − void *rtattr, | |
| 65 | − struct netlink_skb_parms *req); | |
| 66 | −extern int ip6_del_rt(struct rt6_info *, | |
| 67 | − struct nlmsghdr *, | |
| 68 | − void *rtattr, | |
| 69 | − struct netlink_skb_parms *req); | |
| 65 | +extern int ip6_route_add(struct fib6_config *cfg); | |
| 66 | +extern int ip6_ins_rt(struct rt6_info *); | |
| 67 | +extern int ip6_del_rt(struct rt6_info *); | |
| 70 | 68 | |
| 71 | 69 | extern int ip6_rt_addr_add(struct in6_addr *addr, |
| 72 | 70 | struct net_device *dev, |
| @@ -114,6 +112,7 @@ extern int rt6_route_rcv(struct net_device *dev, · 41 unmodified lines | ||
| 114 | 112 | struct in6_addr *gwaddr); |
| 115 | 113 | |
| 116 | 114 | extern void rt6_redirect(struct in6_addr *dest, |
| 115 | + struct in6_addr *src, | |
| 117 | 116 | struct in6_addr *saddr, |
| 118 | 117 | struct neighbour *neigh, |
| 119 | 118 | u8 *lladdr, |
| @@ -131,6 +130,13 @@ extern int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a · 11 unmodified lines | ||
| 131 | 130 | extern int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); |
| 132 | 131 | extern int inet6_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); |
| 133 | 132 | |
| 133 | +struct rt6_rtnl_dump_arg | |
| 134 | +{ | |
| 135 | + struct sk_buff *skb; | |
| 136 | + struct netlink_callback *cb; | |
| 137 | +}; | |
| 138 | + | |
| 139 | +extern int rt6_dump_route(struct rt6_info *rt, void *p_arg); | |
| 134 | 140 | extern void rt6_ifdown(struct net_device *dev); |
| 135 | 141 | extern void rt6_mtu_change(struct net_device *dev, unsigned mtu); |
| 136 | 142 | |
| @@ -140,21 +146,24 @@ extern rwlock_t rt6_lock; · 3 unmodified lines | ||
| 140 | 146 | * Store a destination cache entry in a socket |
| 141 | 147 | */ |
| 142 | 148 | static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst, |
| 143 | − struct in6_addr *daddr) | |
| 149 | + struct in6_addr *daddr, struct in6_addr *saddr) | |
| 144 | 150 | { |
| 145 | 151 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 146 | 152 | struct rt6_info *rt = (struct rt6_info *) dst; |
| 147 | 153 | |
| 148 | 154 | sk_setup_caps(sk, dst); |
| 149 | 155 | np->daddr_cache = daddr; |
| 156 | +#ifdef CONFIG_IPV6_SUBTREES | |
| 157 | + np->saddr_cache = saddr; | |
| 158 | +#endif | |
| 150 | 159 | np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; |
| 151 | 160 | } |
| 152 | 161 | |
| 153 | 162 | static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, |
| 154 | − struct in6_addr *daddr) | |
| 163 | + struct in6_addr *daddr, struct in6_addr *saddr) | |
| 155 | 164 | { |
| 156 | 165 | write_lock(&sk->sk_dst_lock); |
| 157 | − __ip6_dst_store(sk, dst, daddr); | |
| 166 | + __ip6_dst_store(sk, dst, daddr, saddr); | |
| 158 | 167 | write_unlock(&sk->sk_dst_lock); |
| 159 | 168 | } |
| 160 | 169 | |
| @@ -18,26 +18,34 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #include <net/flow.h> |
| 20 | 20 | #include <linux/seq_file.h> |
| 21 | − | |
| 22 | −/* WARNING: The ordering of these elements must match ordering | |
| 23 | − * of RTA_* rtnetlink attribute numbers. | |
| 24 | − */ | |
| 25 | −struct kern_rta { | |
| 26 | − void *rta_dst; | |
| 27 | − void *rta_src; | |
| 28 | − int *rta_iif; | |
| 29 | − int *rta_oif; | |
| 30 | − void *rta_gw; | |
| 31 | − u32 *rta_priority; | |
| 32 | − void *rta_prefsrc; | |
| 33 | − struct rtattr *rta_mx; | |
| 34 | − struct rtattr *rta_mp; | |
| 35 | − unsigned char *rta_protoinfo; | |
| 36 | − u32 *rta_flow; | |
| 37 | − struct rta_cacheinfo *rta_ci; | |
| 38 | − struct rta_session *rta_sess; | |
| 39 | − u32 *rta_mp_alg; | |
| 40 | −}; | |
| 21 | +#include <net/fib_rules.h> | |
| 22 | + | |
| 23 | +struct fib_config { | |
| 24 | + u8 fc_family; | |
| 25 | + u8 fc_dst_len; | |
| 26 | + u8 fc_src_len; | |
| 27 | + u8 fc_tos; | |
| 28 | + u8 fc_protocol; | |
| 29 | + u8 fc_scope; | |
| 30 | + u8 fc_type; | |
| 31 | + /* 1 byte unused */ | |
| 32 | + u32 fc_table; | |
| 33 | + u32 fc_dst; | |
| 34 | + u32 fc_src; | |
| 35 | + u32 fc_gw; | |
| 36 | + int fc_oif; | |
| 37 | + u32 fc_flags; | |
| 38 | + u32 fc_priority; | |
| 39 | + u32 fc_prefsrc; | |
| 40 | + struct nlattr *fc_mx; | |
| 41 | + struct rtnexthop *fc_mp; | |
| 42 | + int fc_mx_len; | |
| 43 | + int fc_mp_len; | |
| 44 | + u32 fc_flow; | |
| 45 | + u32 fc_mp_alg; | |
| 46 | + u32 fc_nlflags; | |
| 47 | + struct nl_info fc_nlinfo; | |
| 48 | + }; | |
| 41 | 49 | |
| 42 | 50 | struct fib_info; |
| 43 | 51 | |
| @@ -149,15 +157,12 @@ struct fib_result_nl { · 105 unmodified lines | ||
| 149 | 157 | #endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */ |
| 150 | 158 | |
| 151 | 159 | struct fib_table { |
| 152 | − unsigned char tb_id; | |
| 160 | + struct hlist_node tb_hlist; | |
| 161 | + u32 tb_id; | |
| 153 | 162 | unsigned tb_stamp; |
| 154 | 163 | int (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res); |
| 155 | − int (*tb_insert)(struct fib_table *table, struct rtmsg *r, | |
| 156 | − struct kern_rta *rta, struct nlmsghdr *n, | |
| 157 | − struct netlink_skb_parms *req); | |
| 158 | − int (*tb_delete)(struct fib_table *table, struct rtmsg *r, | |
| 159 | − struct kern_rta *rta, struct nlmsghdr *n, | |
| 160 | − struct netlink_skb_parms *req); | |
| 164 | + int (*tb_insert)(struct fib_table *, struct fib_config *); | |
| 165 | + int (*tb_delete)(struct fib_table *, struct fib_config *); | |
| 161 | 166 | int (*tb_dump)(struct fib_table *table, struct sk_buff *skb, |
| 162 | 167 | struct netlink_callback *cb); |
| 163 | 168 | int (*tb_flush)(struct fib_table *table); |
| @@ -172,14 +177,14 @@ struct fib_table { · 8 unmodified lines | ||
| 172 | 177 | extern struct fib_table *ip_fib_local_table; |
| 173 | 178 | extern struct fib_table *ip_fib_main_table; |
| 174 | 179 | |
| 175 | −static inline struct fib_table *fib_get_table(int id) | |
| 180 | +static inline struct fib_table *fib_get_table(u32 id) | |
| 176 | 181 | { |
| 177 | 182 | if (id != RT_TABLE_LOCAL) |
| 178 | 183 | return ip_fib_main_table; |
| 179 | 184 | return ip_fib_local_table; |
| 180 | 185 | } |
| 181 | 186 | |
| 182 | −static inline struct fib_table *fib_new_table(int id) | |
| 187 | +static inline struct fib_table *fib_new_table(u32 id) | |
| 183 | 188 | { |
| 184 | 189 | return fib_get_table(id); |
| 185 | 190 | } |
| @@ -199,35 +204,19 @@ static inline void fib_select_default(const struct flowi *flp, struct fib_result · 13 unmodified lines | ||
| 199 | 204 | } |
| 200 | 205 | |
| 201 | 206 | #else /* CONFIG_IP_MULTIPLE_TABLES */ |
| 202 | −#define ip_fib_local_table (fib_tables[RT_TABLE_LOCAL]) | |
| 203 | −#define ip_fib_main_table (fib_tables[RT_TABLE_MAIN]) | |
| 204 | − | |
| 205 | −extern struct fib_table * fib_tables[RT_TABLE_MAX+1]; | |
| 206 | −extern int fib_lookup(const struct flowi *flp, struct fib_result *res); | |
| 207 | −extern struct fib_table *__fib_new_table(int id); | |
| 208 | −extern void fib_rule_put(struct fib_rule *r); | |
| 207 | +#define ip_fib_local_table fib_get_table(RT_TABLE_LOCAL) | |
| 208 | +#define ip_fib_main_table fib_get_table(RT_TABLE_MAIN) | |
| 209 | 209 | |
| 210 | −static inline struct fib_table *fib_get_table(int id) | |
| 211 | −{ | |
| 212 | − if (id == 0) | |
| 213 | − id = RT_TABLE_MAIN; | |
| 214 | − | |
| 215 | − return fib_tables[id]; | |
| 216 | −} | |
| 217 | − | |
| 218 | −static inline struct fib_table *fib_new_table(int id) | |
| 219 | −{ | |
| 220 | − if (id == 0) | |
| 221 | − id = RT_TABLE_MAIN; | |
| 222 | − | |
| 223 | − return fib_tables[id] ? : __fib_new_table(id); | |
| 224 | −} | |
| 210 | +extern int fib_lookup(struct flowi *flp, struct fib_result *res); | |
| 225 | 211 | |
| 212 | +extern struct fib_table *fib_new_table(u32 id); | |
| 213 | +extern struct fib_table *fib_get_table(u32 id); | |
| 226 | 214 | extern void fib_select_default(const struct flowi *flp, struct fib_result *res); |
| 227 | 215 | |
| 228 | 216 | #endif /* CONFIG_IP_MULTIPLE_TABLES */ |
| 229 | 217 | |
| 230 | 218 | /* Exported by fib_frontend.c */ |
| 219 | +extern struct nla_policy rtm_ipv4_policy[]; | |
| 231 | 220 | extern void ip_fib_init(void); |
| 232 | 221 | extern int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); |
| 233 | 222 | extern int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); |
| @@ -243,23 +232,20 @@ struct rtentry; · 9 unmodified lines | ||
| 243 | 232 | extern int ip_fib_check_default(u32 gw, struct net_device *dev); |
| 244 | 233 | extern int fib_sync_down(u32 local, struct net_device *dev, int force); |
| 245 | 234 | extern int fib_sync_up(struct net_device *dev); |
| 246 | −extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, | |
| 247 | − struct kern_rta *rta, struct rtentry *r); | |
| 248 | 235 | extern u32 __fib_res_prefsrc(struct fib_result *res); |
| 249 | 236 | |
| 250 | 237 | /* Exported by fib_hash.c */ |
| 251 | −extern struct fib_table *fib_hash_init(int id); | |
| 238 | +extern struct fib_table *fib_hash_init(u32 id); | |
| 252 | 239 | |
| 253 | 240 | #ifdef CONFIG_IP_MULTIPLE_TABLES |
| 254 | −/* Exported by fib_rules.c */ | |
| 241 | +extern int fib4_rules_dump(struct sk_buff *skb, struct netlink_callback *cb); | |
| 242 | + | |
| 243 | +extern void __init fib4_rules_init(void); | |
| 255 | 244 | |
| 256 | −extern int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); | |
| 257 | −extern int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); | |
| 258 | −extern int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb); | |
| 259 | 245 | #ifdef CONFIG_NET_CLS_ROUTE |
| 260 | 246 | extern u32 fib_rules_tclass(struct fib_result *res); |
| 261 | 247 | #endif |
| 262 | −extern void fib_rules_init(void); | |
| 248 | + | |
| 263 | 249 | #endif |
| 264 | 250 | |
| 265 | 251 | static inline void fib_combine_itag(u32 *itag, struct fib_result *res) |
| @@ -40,6 +40,7 @@ · 39 unmodified lines | ||
| 40 | 40 | #define NEXTHDR_ICMP 58 /* ICMP for IPv6. */ |
| 41 | 41 | #define NEXTHDR_NONE 59 /* No next header */ |
| 42 | 42 | #define NEXTHDR_DEST 60 /* Destination options header. */ |
| 43 | +#define NEXTHDR_MOBILITY 135 /* Mobility header. */ | |
| 43 | 44 | |
| 44 | 45 | #define NEXTHDR_MAX 255 |
| 45 | 46 | |
| @@ -229,7 +230,7 @@ extern int ip6_ra_control(struct sock *sk, int sel, · 183 unmodified lines | ||
| 229 | 230 | void (*destructor)(struct sock *)); |
| 230 | 231 | |
| 231 | 232 | |
| 232 | −extern int ipv6_parse_hopopts(struct sk_buff *skb); | |
| 233 | +extern int ipv6_parse_hopopts(struct sk_buff **skbp); | |
| 233 | 234 | |
| 234 | 235 | extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); |
| 235 | 236 | extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, |
| @@ -506,6 +507,8 @@ extern int ipv6_skip_exthdr(const struct sk_buff *, int start, · 270 unmodified lines | ||
| 506 | 507 | |
| 507 | 508 | extern int ipv6_ext_hdr(u8 nexthdr); |
| 508 | 509 | |
| 510 | +extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); | |
| 511 | + | |
| 509 | 512 | extern struct ipv6_txoptions * ipv6_invert_rthdr(struct sock *sk, |
| 510 | 513 | struct ipv6_rt_hdr *hdr); |
| 511 | 514 | |
| @@ -0,0 +1,61 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C)2003-2006 Helsinki University of Technology | |
| 3 | + * Copyright (C)2003-2006 USAGI/WIDE Project | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify | |
| 6 | + * it under the terms of the GNU General Public License as published by | |
| 7 | + * the Free Software Foundation; either version 2 of the License, or | |
| 8 | + * (at your option) any later version. | |
| 9 | + * | |
| 10 | + * This program is distributed in the hope that it will be useful, | |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 13 | + * GNU General Public License for more details. | |
| 14 | + * | |
| 15 | + * You should have received a copy of the GNU General Public License | |
| 16 | + * along with this program; if not, write to the Free Software | |
| 17 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 18 | + */ | |
| 19 | +/* | |
| 20 | + * Authors: | |
| 21 | + * Noriaki TAKAMIYA @USAGI | |
| 22 | + * Masahide NAKAMURA @USAGI | |
| 23 | + * YOSHIFUJI Hideaki @USAGI | |
| 24 | + */ | |
| 25 | +#ifndef _NET_MIP6_H | |
| 26 | +#define _NET_MIP6_H | |
| 27 | + | |
| 28 | +#include <linux/skbuff.h> | |
| 29 | +#include <net/sock.h> | |
| 30 | + | |
| 31 | +#define MIP6_OPT_PAD_1 0 | |
| 32 | +#define MIP6_OPT_PAD_N 1 | |
| 33 | + | |
| 34 | +/* | |
| 35 | + * Mobility Header | |
| 36 | + */ | |
| 37 | +struct ip6_mh { | |
| 38 | + __u8 ip6mh_proto; | |
| 39 | + __u8 ip6mh_hdrlen; | |
| 40 | + __u8 ip6mh_type; | |
| 41 | + __u8 ip6mh_reserved; | |
| 42 | + __u16 ip6mh_cksum; | |
| 43 | + /* Followed by type specific messages */ | |
| 44 | + __u8 data[0]; | |
| 45 | +} __attribute__ ((__packed__)); | |
| 46 | + | |
| 47 | +#define IP6_MH_TYPE_BRR 0 /* Binding Refresh Request */ | |
| 48 | +#define IP6_MH_TYPE_HOTI 1 /* HOTI Message */ | |
| 49 | +#define IP6_MH_TYPE_COTI 2 /* COTI Message */ | |
| 50 | +#define IP6_MH_TYPE_HOT 3 /* HOT Message */ | |
| 51 | +#define IP6_MH_TYPE_COT 4 /* COT Message */ | |
| 52 | +#define IP6_MH_TYPE_BU 5 /* Binding Update */ | |
| 53 | +#define IP6_MH_TYPE_BACK 6 /* Binding ACK */ | |
| 54 | +#define IP6_MH_TYPE_BERROR 7 /* Binding Error */ | |
| 55 | +#define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR | |
| 56 | + | |
| 57 | +extern int mip6_init(void); | |
| 58 | +extern void mip6_fini(void); | |
| 59 | +extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb); | |
| 60 | + | |
| 61 | +#endif | |
| @@ -1,6 +1,8 @@ | ||
| 1 | 1 | #ifndef _NET_NEIGHBOUR_H |
| 2 | 2 | #define _NET_NEIGHBOUR_H |
| 3 | 3 | |
| 4 | +#include <linux/neighbour.h> | |
| 5 | + | |
| 4 | 6 | /* |
| 5 | 7 | * Generic neighbour manipulation |
| 6 | 8 | * |
| @@ -14,40 +16,6 @@ · 7 unmodified lines | ||
| 14 | 16 | * - Add neighbour cache statistics like rtstat |
| 15 | 17 | */ |
| 16 | 18 | |
| 17 | −/* The following flags & states are exported to user space, | |
| 18 | − so that they should be moved to include/linux/ directory. | |
| 19 | − */ | |
| 20 | − | |
| 21 | −/* | |
| 22 | − * Neighbor Cache Entry Flags | |
| 23 | − */ | |
| 24 | − | |
| 25 | −#define NTF_PROXY 0x08 /* == ATF_PUBL */ | |
| 26 | −#define NTF_ROUTER 0x80 | |
| 27 | − | |
| 28 | −/* | |
| 29 | − * Neighbor Cache Entry States. | |
| 30 | − */ | |
| 31 | − | |
| 32 | −#define NUD_INCOMPLETE 0x01 | |
| 33 | −#define NUD_REACHABLE 0x02 | |
| 34 | −#define NUD_STALE 0x04 | |
| 35 | −#define NUD_DELAY 0x08 | |
| 36 | −#define NUD_PROBE 0x10 | |
| 37 | −#define NUD_FAILED 0x20 | |
| 38 | − | |
| 39 | −/* Dummy states */ | |
| 40 | −#define NUD_NOARP 0x40 | |
| 41 | −#define NUD_PERMANENT 0x80 | |
| 42 | −#define NUD_NONE 0x00 | |
| 43 | − | |
| 44 | −/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change | |
| 45 | − and make no address resolution or NUD. | |
| 46 | − NUD_PERMANENT is also cannot be deleted by garbage collectors. | |
| 47 | − */ | |
| 48 | − | |
| 49 | −#ifdef __KERNEL__ | |
| 50 | − | |
| 51 | 19 | #include <asm/atomic.h> |
| 52 | 20 | #include <linux/netdevice.h> |
| 53 | 21 | #include <linux/skbuff.h> |
| @@ -133,7 +101,7 @@ struct neighbour · 79 unmodified lines | ||
| 133 | 101 | __u8 dead; |
| 134 | 102 | atomic_t probes; |
| 135 | 103 | rwlock_t lock; |
| 136 | − unsigned char ha[(MAX_ADDR_LEN+sizeof(unsigned long)-1)&~(sizeof(unsigned long)-1)]; | |
| 104 | + unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; | |
| 137 | 105 | struct hh_cache *hh; |
| 138 | 106 | atomic_t refcnt; |
| 139 | 107 | int (*output)(struct sk_buff *skb); |
| @@ -158,6 +126,7 @@ struct pneigh_entry · 18 unmodified lines | ||
| 158 | 126 | { |
| 159 | 127 | struct pneigh_entry *next; |
| 160 | 128 | struct net_device *dev; |
| 129 | + u8 flags; | |
| 161 | 130 | u8 key[0]; |
| 162 | 131 | }; |
| 163 | 132 | |
| @@ -374,6 +343,3 @@ struct neighbour_cb { · 210 unmodified lines | ||
| 374 | 343 | #define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb) |
| 375 | 344 | |
| 376 | 345 | #endif |
| 377 | −#endif | |
| 378 | − | |
| 379 | − | |
| @@ -0,0 +1,292 @@ | ||
| 1 | +/* | |
| 2 | + * NetLabel System | |
| 3 | + * | |
| 4 | + * The NetLabel system manages static and dynamic label mappings for network | |
| 5 | + * protocols such as CIPSO and RIPSO. | |
| 6 | + * | |
| 7 | + * Author: Paul Moore <paul.moore@hp.com> | |
| 8 | + * | |
| 9 | + */ | |
| 10 | + | |
| 11 | +/* | |
| 12 | + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | |
| 13 | + * | |
| 14 | + * This program is free software; you can redistribute it and/or modify | |
| 15 | + * it under the terms of the GNU General Public License as published by | |
| 16 | + * the Free Software Foundation; either version 2 of the License, or | |
| 17 | + * (at your option) any later version. | |
| 18 | + * | |
| 19 | + * This program is distributed in the hope that it will be useful, | |
| 20 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 21 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | |
| 22 | + * the GNU General Public License for more details. | |
| 23 | + * | |
| 24 | + * You should have received a copy of the GNU General Public License | |
| 25 | + * along with this program; if not, write to the Free Software | |
| 26 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 27 | + * | |
| 28 | + */ | |
| 29 | + | |
| 30 | +#ifndef _NETLABEL_H | |
| 31 | +#define _NETLABEL_H | |
| 32 | + | |
| 33 | +#include <linux/types.h> | |
| 34 | +#include <linux/net.h> | |
| 35 | +#include <linux/skbuff.h> | |
| 36 | +#include <net/netlink.h> | |
| 37 | + | |
| 38 | +/* | |
| 39 | + * NetLabel - A management interface for maintaining network packet label | |
| 40 | + * mapping tables for explicit packet labling protocols. | |
| 41 | + * | |
| 42 | + * Network protocols such as CIPSO and RIPSO require a label translation layer | |
| 43 | + * to convert the label on the packet into something meaningful on the host | |
| 44 | + * machine. In the current Linux implementation these mapping tables live | |
| 45 | + * inside the kernel; NetLabel provides a mechanism for user space applications | |
| 46 | + * to manage these mapping tables. | |
| 47 | + * | |
| 48 | + * NetLabel makes use of the Generic NETLINK mechanism as a transport layer to | |
| 49 | + * send messages between kernel and user space. The general format of a | |
| 50 | + * NetLabel message is shown below: | |
| 51 | + * | |
| 52 | + * +-----------------+-------------------+--------- --- -- - | |
| 53 | + * | struct nlmsghdr | struct genlmsghdr | payload | |
| 54 | + * +-----------------+-------------------+--------- --- -- - | |
| 55 | + * | |
| 56 | + * The 'nlmsghdr' and 'genlmsghdr' structs should be dealt with like normal. | |
| 57 | + * The payload is dependent on the subsystem specified in the | |
| 58 | + * 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions | |
| 59 | + * should be defined in the corresponding net/netlabel/netlabel_<subsys>.h|c | |
| 60 | + * file. All of the fields in the NetLabel payload are NETLINK attributes, the | |
| 61 | + * length of each field is the length of the NETLINK attribute payload, see | |
| 62 | + * include/net/netlink.h for more information on NETLINK attributes. | |
| 63 | + * | |
| 64 | + */ | |
| 65 | + | |
| 66 | +/* | |
| 67 | + * NetLabel NETLINK protocol | |
| 68 | + */ | |
| 69 | + | |
| 70 | +#define NETLBL_PROTO_VERSION 1 | |
| 71 | + | |
| 72 | +/* NetLabel NETLINK types/families */ | |
| 73 | +#define NETLBL_NLTYPE_NONE 0 | |
| 74 | +#define NETLBL_NLTYPE_MGMT 1 | |
| 75 | +#define NETLBL_NLTYPE_MGMT_NAME "NLBL_MGMT" | |
| 76 | +#define NETLBL_NLTYPE_RIPSO 2 | |
| 77 | +#define NETLBL_NLTYPE_RIPSO_NAME "NLBL_RIPSO" | |
| 78 | +#define NETLBL_NLTYPE_CIPSOV4 3 | |
| 79 | +#define NETLBL_NLTYPE_CIPSOV4_NAME "NLBL_CIPSOv4" | |
| 80 | +#define NETLBL_NLTYPE_CIPSOV6 4 | |
| 81 | +#define NETLBL_NLTYPE_CIPSOV6_NAME "NLBL_CIPSOv6" | |
| 82 | +#define NETLBL_NLTYPE_UNLABELED 5 | |
| 83 | +#define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL" | |
| 84 | + | |
| 85 | +/* NetLabel return codes */ | |
| 86 | +#define NETLBL_E_OK 0 | |
| 87 | + | |
| 88 | +/* | |
| 89 | + * Helper functions | |
| 90 | + */ | |
| 91 | + | |
| 92 | +#define NETLBL_LEN_U8 nla_total_size(sizeof(u8)) | |
| 93 | +#define NETLBL_LEN_U16 nla_total_size(sizeof(u16)) | |
| 94 | +#define NETLBL_LEN_U32 nla_total_size(sizeof(u32)) | |
| 95 | + | |
| 96 | +/** | |
| 97 | + * netlbl_netlink_alloc_skb - Allocate a NETLINK message buffer | |
| 98 | + * @head: the amount of headroom in bytes | |
| 99 | + * @body: the desired size (minus headroom) in bytes | |
| 100 | + * @gfp_flags: the alloc flags to pass to alloc_skb() | |
| 101 | + * | |
| 102 | + * Description: | |
| 103 | + * Allocate a NETLINK message buffer based on the sizes given in @head and | |
| 104 | + * @body. If @head is greater than zero skb_reserve() is called to reserve | |
| 105 | + * @head bytes at the start of the buffer. Returns a valid sk_buff pointer on | |
| 106 | + * success, NULL on failure. | |
| 107 | + * | |
| 108 | + */ | |
| 109 | +static inline struct sk_buff *netlbl_netlink_alloc_skb(size_t head, | |
| 110 | + size_t body, | |
| 111 | + int gfp_flags) | |
| 112 | +{ | |
| 113 | + struct sk_buff *skb; | |
| 114 | + | |
| 115 | + skb = alloc_skb(NLMSG_ALIGN(head + body), gfp_flags); | |
| 116 | + if (skb == NULL) | |
| 117 | + return NULL; | |
| 118 | + if (head > 0) { | |
| 119 | + skb_reserve(skb, head); | |
| 120 | + if (skb_tailroom(skb) < body) { | |
| 121 | + kfree_skb(skb); | |
| 122 | + return NULL; | |
| 123 | + } | |
| 124 | + } | |
| 125 | + | |
| 126 | + return skb; | |
| 127 | +} | |
| 128 | + | |
| 129 | +/* | |
| 130 | + * NetLabel - Kernel API for accessing the network packet label mappings. | |
| 131 | + * | |
| 132 | + * The following functions are provided for use by other kernel modules, | |
| 133 | + * specifically kernel LSM modules, to provide a consistent, transparent API | |
| 134 | + * for dealing with explicit packet labeling protocols such as CIPSO and | |
| 135 | + * RIPSO. The functions defined here are implemented in the | |
| 136 | + * net/netlabel/netlabel_kapi.c file. | |
| 137 | + * | |
| 138 | + */ | |
| 139 | + | |
| 140 | +/* Domain mapping definition struct */ | |
| 141 | +struct netlbl_dom_map; | |
| 142 | + | |
| 143 | +/* Domain mapping operations */ | |
| 144 | +int netlbl_domhsh_remove(const char *domain); | |
| 145 | + | |
| 146 | +/* LSM security attributes */ | |
| 147 | +struct netlbl_lsm_cache { | |
| 148 | + void (*free) (const void *data); | |
| 149 | + void *data; | |
| 150 | +}; | |
| 151 | +struct netlbl_lsm_secattr { | |
| 152 | + char *domain; | |
| 153 | + | |
| 154 | + u32 mls_lvl; | |
| 155 | + u32 mls_lvl_vld; | |
| 156 | + unsigned char *mls_cat; | |
| 157 | + size_t mls_cat_len; | |
| 158 | + | |
| 159 | + struct netlbl_lsm_cache cache; | |
| 160 | +}; | |
| 161 | + | |
| 162 | +/* | |
| 163 | + * LSM security attribute operations | |
| 164 | + */ | |
| 165 | + | |
| 166 | + | |
| 167 | +/** | |
| 168 | + * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct | |
| 169 | + * @secattr: the struct to initialize | |
| 170 | + * | |
| 171 | + * Description: | |
| 172 | + * Initialize an already allocated netlbl_lsm_secattr struct. Returns zero on | |
| 173 | + * success, negative values on error. | |
| 174 | + * | |
| 175 | + */ | |
| 176 | +static inline int netlbl_secattr_init(struct netlbl_lsm_secattr *secattr) | |
| 177 | +{ | |
| 178 | + memset(secattr, 0, sizeof(*secattr)); | |
| 179 | + return 0; | |
| 180 | +} | |
| 181 | + | |
| 182 | +/** | |
| 183 | + * netlbl_secattr_destroy - Clears a netlbl_lsm_secattr struct | |
| 184 | + * @secattr: the struct to clear | |
| 185 | + * @clear_cache: cache clear flag | |
| 186 | + * | |
| 187 | + * Description: | |
| 188 | + * Destroys the @secattr struct, including freeing all of the internal buffers. | |
| 189 | + * If @clear_cache is true then free the cache fields, otherwise leave them | |
| 190 | + * intact. The struct must be reset with a call to netlbl_secattr_init() | |
| 191 | + * before reuse. | |
| 192 | + * | |
| 193 | + */ | |
| 194 | +static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr, | |
| 195 | + u32 clear_cache) | |
| 196 | +{ | |
| 197 | + if (clear_cache && secattr->cache.data != NULL && secattr->cache.free) | |
| 198 | + secattr->cache.free(secattr->cache.data); | |
| 199 | + kfree(secattr->domain); | |
| 200 | + kfree(secattr->mls_cat); | |
| 201 | +} | |
| 202 | + | |
| 203 | +/** | |
| 204 | + * netlbl_secattr_alloc - Allocate and initialize a netlbl_lsm_secattr struct | |
| 205 | + * @flags: the memory allocation flags | |
| 206 | + * | |
| 207 | + * Description: | |
| 208 | + * Allocate and initialize a netlbl_lsm_secattr struct. Returns a valid | |
| 209 | + * pointer on success, or NULL on failure. | |
| 210 | + * | |
| 211 | + */ | |
| 212 | +static inline struct netlbl_lsm_secattr *netlbl_secattr_alloc(int flags) | |
| 213 | +{ | |
| 214 | + return kzalloc(sizeof(struct netlbl_lsm_secattr), flags); | |
| 215 | +} | |
| 216 | + | |
| 217 | +/** | |
| 218 | + * netlbl_secattr_free - Frees a netlbl_lsm_secattr struct | |
| 219 | + * @secattr: the struct to free | |
| 220 | + * @clear_cache: cache clear flag | |
| 221 | + * | |
| 222 | + * Description: | |
| 223 | + * Frees @secattr including all of the internal buffers. If @clear_cache is | |
| 224 | + * true then free the cache fields, otherwise leave them intact. | |
| 225 | + * | |
| 226 | + */ | |
| 227 | +static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr, | |
| 228 | + u32 clear_cache) | |
| 229 | +{ | |
| 230 | + netlbl_secattr_destroy(secattr, clear_cache); | |
| 231 | + kfree(secattr); | |
| 232 | +} | |
| 233 | + | |
| 234 | +/* | |
| 235 | + * LSM protocol operations | |
| 236 | + */ | |
| 237 | + | |
| 238 | +#ifdef CONFIG_NETLABEL | |
| 239 | +int netlbl_socket_setattr(const struct socket *sock, | |
| 240 | + const struct netlbl_lsm_secattr *secattr); | |
| 241 | +int netlbl_socket_getattr(const struct socket *sock, | |
| 242 | + struct netlbl_lsm_secattr *secattr); | |
| 243 | +int netlbl_skbuff_getattr(const struct sk_buff *skb, | |
| 244 | + struct netlbl_lsm_secattr *secattr); | |
| 245 | +void netlbl_skbuff_err(struct sk_buff *skb, int error); | |
| 246 | +#else | |
| 247 | +static inline int netlbl_socket_setattr(const struct socket *sock, | |
| 248 | + const struct netlbl_lsm_secattr *secattr) | |
| 249 | +{ | |
| 250 | + return -ENOSYS; | |
| 251 | +} | |
| 252 | + | |
| 253 | +static inline int netlbl_socket_getattr(const struct socket *sock, | |
| 254 | + struct netlbl_lsm_secattr *secattr) | |
| 255 | +{ | |
| 256 | + return -ENOSYS; | |
| 257 | +} | |
| 258 | + | |
| 259 | +static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, | |
| 260 | + struct netlbl_lsm_secattr *secattr) | |
| 261 | +{ | |
| 262 | + return -ENOSYS; | |
| 263 | +} | |
| 264 | + | |
| 265 | +static inline void netlbl_skbuff_err(struct sk_buff *skb, int error) | |
| 266 | +{ | |
| 267 | + return; | |
| 268 | +} | |
| 269 | +#endif /* CONFIG_NETLABEL */ | |
| 270 | + | |
| 271 | +/* | |
| 272 | + * LSM label mapping cache operations | |
| 273 | + */ | |
| 274 | + | |
| 275 | +#ifdef CONFIG_NETLABEL | |
| 276 | +void netlbl_cache_invalidate(void); | |
| 277 | +int netlbl_cache_add(const struct sk_buff *skb, | |
| 278 | + const struct netlbl_lsm_secattr *secattr); | |
| 279 | +#else | |
| 280 | +static inline void netlbl_cache_invalidate(void) | |
| 281 | +{ | |
| 282 | + return; | |
| 283 | +} | |
| 284 | + | |
| 285 | +static inline int netlbl_cache_add(const struct sk_buff *skb, | |
| 286 | + const struct netlbl_lsm_secattr *secattr) | |
| 287 | +{ | |
| 288 | + return 0; | |
| 289 | +} | |
| 290 | +#endif /* CONFIG_NETLABEL */ | |
| 291 | + | |
| 292 | +#endif /* _NETLABEL_H */ | |
| @@ -35,12 +35,15 @@ · 34 unmodified lines | ||
| 35 | 35 | * nlmsg_put() add a netlink message to an skb |
| 36 | 36 | * nlmsg_put_answer() callback based nlmsg_put() |
| 37 | 37 | * nlmsg_end() finanlize netlink message |
| 38 | + * nlmsg_get_pos() return current position in message | |
| 39 | + * nlmsg_trim() trim part of message | |
| 38 | 40 | * nlmsg_cancel() cancel message construction |
| 39 | 41 | * nlmsg_free() free a netlink message |
| 40 | 42 | * |
| 41 | 43 | * Message Sending: |
| 42 | 44 | * nlmsg_multicast() multicast message to several groups |
| 43 | 45 | * nlmsg_unicast() unicast a message to a single socket |
| 46 | + * nlmsg_notify() send notification message | |
| 44 | 47 | * |
| 45 | 48 | * Message Length Calculations: |
| 46 | 49 | * nlmsg_msg_size(payload) length of message w/o padding |
| @@ -62,6 +65,9 @@ · 15 unmodified lines | ||
| 62 | 65 | * nlmsg_validate() validate netlink message incl. attrs |
| 63 | 66 | * nlmsg_for_each_attr() loop over all attributes |
| 64 | 67 | * |
| 68 | + * Misc: | |
| 69 | + * nlmsg_report() report back to application? | |
| 70 | + * | |
| 65 | 71 | * ------------------------------------------------------------------------ |
| 66 | 72 | * Attributes Interface |
| 67 | 73 | * ------------------------------------------------------------------------ |
| @@ -80,8 +86,10 @@ · 12 unmodified lines | ||
| 80 | 86 | * struct nlattr netlink attribtue header |
| 81 | 87 | * |
| 82 | 88 | * Attribute Construction: |
| 83 | − * nla_reserve(skb, type, len) reserve skb tailroom for an attribute | |
| 89 | + * nla_reserve(skb, type, len) reserve room for an attribute | |
| 90 | + * nla_reserve_nohdr(skb, len) reserve room for an attribute w/o hdr | |
| 84 | 91 | * nla_put(skb, type, len, data) add attribute to skb |
| 92 | + * nla_put_nohdr(skb, len, data) add attribute w/o hdr | |
| 85 | 93 | * |
| 86 | 94 | * Attribute Construction for Basic Types: |
| 87 | 95 | * nla_put_u8(skb, type, value) add u8 attribute to skb |
| @@ -139,6 +147,7 @@ · 51 unmodified lines | ||
| 139 | 147 | * nla_next(nla, remaining) get next netlink attribute |
| 140 | 148 | * nla_validate() validate a stream of attributes |
| 141 | 149 | * nla_find() find attribute in stream of attributes |
| 150 | + * nla_find_nested() find attribute in nested attributes | |
| 142 | 151 | * nla_parse() parse and validate stream of attrs |
| 143 | 152 | * nla_parse_nested() parse nested attribuets |
| 144 | 153 | * nla_for_each_attr() loop over all attributes |
| @@ -158,6 +167,7 @@ enum { · 13 unmodified lines | ||
| 158 | 167 | NLA_FLAG, |
| 159 | 168 | NLA_MSECS, |
| 160 | 169 | NLA_NESTED, |
| 170 | + NLA_NUL_STRING, | |
| 161 | 171 | __NLA_TYPE_MAX, |
| 162 | 172 | }; |
| 163 | 173 | |
| @@ -166,21 +176,37 @@ enum { · 2 unmodified lines | ||
| 166 | 176 | /** |
| 167 | 177 | * struct nla_policy - attribute validation policy |
| 168 | 178 | * @type: Type of attribute or NLA_UNSPEC |
| 169 | − * @minlen: Minimal length of payload required to be available | |
| 179 | + * @len: Type specific length of payload | |
| 170 | 180 | * |
| 171 | 181 | * Policies are defined as arrays of this struct, the array must be |
| 172 | 182 | * accessible by attribute type up to the highest identifier to be expected. |
| 173 | 183 | * |
| 184 | + * Meaning of `len' field: | |
| 185 | + * NLA_STRING Maximum length of string | |
| 186 | + * NLA_NUL_STRING Maximum length of string (excluding NUL) | |
| 187 | + * NLA_FLAG Unused | |
| 188 | + * All other Exact length of attribute payload | |
| 189 | + * | |
| 174 | 190 | * Example: |
| 175 | 191 | * static struct nla_policy my_policy[ATTR_MAX+1] __read_mostly = { |
| 176 | 192 | * [ATTR_FOO] = { .type = NLA_U16 }, |
| 177 | − * [ATTR_BAR] = { .type = NLA_STRING }, | |
| 178 | − * [ATTR_BAZ] = { .minlen = sizeof(struct mystruct) }, | |
| 193 | + * [ATTR_BAR] = { .type = NLA_STRING, len = BARSIZ }, | |
| 194 | + * [ATTR_BAZ] = { .len = sizeof(struct mystruct) }, | |
| 179 | 195 | * }; |
| 180 | 196 | */ |
| 181 | 197 | struct nla_policy { |
| 182 | 198 | u16 type; |
| 183 | − u16 minlen; | |
| 199 | + u16 len; | |
| 200 | +}; | |
| 201 | + | |
| 202 | +/** | |
| 203 | + * struct nl_info - netlink source information | |
| 204 | + * @nlh: Netlink message header of original request | |
| 205 | + * @pid: Netlink PID of requesting application | |
| 206 | + */ | |
| 207 | +struct nl_info { | |
| 208 | + struct nlmsghdr *nlh; | |
| 209 | + u32 pid; | |
| 184 | 210 | }; |
| 185 | 211 | |
| 186 | 212 | extern void netlink_run_queue(struct sock *sk, unsigned int *qlen, |
| @@ -188,6 +214,9 @@ extern void netlink_run_queue(struct sock *sk, unsigned int *qlen, · 1 unmodified line | ||
| 188 | 214 | struct nlmsghdr *, int *)); |
| 189 | 215 | extern void netlink_queue_skip(struct nlmsghdr *nlh, |
| 190 | 216 | struct sk_buff *skb); |
| 217 | +extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb, | |
| 218 | + u32 pid, unsigned int group, int report, | |
| 219 | + gfp_t flags); | |
| 191 | 220 | |
| 192 | 221 | extern int nla_validate(struct nlattr *head, int len, int maxtype, |
| 193 | 222 | struct nla_policy *policy); |
| @@ -203,12 +232,18 @@ extern int nla_memcmp(const struct nlattr *nla, const void *data, · 9 unmodified lines | ||
| 203 | 232 | extern int nla_strcmp(const struct nlattr *nla, const char *str); |
| 204 | 233 | extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype, |
| 205 | 234 | int attrlen); |
| 235 | +extern void * __nla_reserve_nohdr(struct sk_buff *skb, int attrlen); | |
| 206 | 236 | extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype, |
| 207 | 237 | int attrlen); |
| 238 | +extern void * nla_reserve_nohdr(struct sk_buff *skb, int attrlen); | |
| 208 | 239 | extern void __nla_put(struct sk_buff *skb, int attrtype, |
| 209 | 240 | int attrlen, const void *data); |
| 241 | +extern void __nla_put_nohdr(struct sk_buff *skb, int attrlen, | |
| 242 | + const void *data); | |
| 210 | 243 | extern int nla_put(struct sk_buff *skb, int attrtype, |
| 211 | 244 | int attrlen, const void *data); |
| 245 | +extern int nla_put_nohdr(struct sk_buff *skb, int attrlen, | |
| 246 | + const void *data); | |
| 212 | 247 | |
| 213 | 248 | /************************************************************************** |
| 214 | 249 | * Netlink Messages |
| @@ -363,6 +398,17 @@ static inline int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, · 148 unmodified lines | ||
| 363 | 398 | nlmsg_attrlen(nlh, hdrlen), maxtype, policy); |
| 364 | 399 | } |
| 365 | 400 | |
| 401 | +/** | |
| 402 | + * nlmsg_report - need to report back to application? | |
| 403 | + * @nlh: netlink message header | |
| 404 | + * | |
| 405 | + * Returns 1 if a report back to the application is requested. | |
| 406 | + */ | |
| 407 | +static inline int nlmsg_report(struct nlmsghdr *nlh) | |
| 408 | +{ | |
| 409 | + return !!(nlh->nlmsg_flags & NLM_F_ECHO); | |
| 410 | +} | |
| 411 | + | |
| 366 | 412 | /** |
| 367 | 413 | * nlmsg_for_each_attr - iterate over a stream of attributes |
| 368 | 414 | * @pos: loop counter, set to current attribute |
| @@ -453,12 +499,13 @@ static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb, · 84 unmodified lines | ||
| 453 | 499 | /** |
| 454 | 500 | * nlmsg_new - Allocate a new netlink message |
| 455 | 501 | * @size: maximum size of message |
| 502 | + * @flags: the type of memory to allocate. | |
| 456 | 503 | * |
| 457 | 504 | * Use NLMSG_GOODSIZE if size isn't know and you need a good default size. |
| 458 | 505 | */ |
| 459 | −static inline struct sk_buff *nlmsg_new(int size) | |
| 506 | +static inline struct sk_buff *nlmsg_new(int size, gfp_t flags) | |
| 460 | 507 | { |
| 461 | − return alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | |
| 508 | + return alloc_skb(size, flags); | |
| 462 | 509 | } |
| 463 | 510 | |
| 464 | 511 | /** |
| @@ -479,6 +526,32 @@ static inline int nlmsg_end(struct sk_buff *skb, struct nlmsghdr *nlh) · 14 unmodified lines | ||
| 479 | 526 | return skb->len; |
| 480 | 527 | } |
| 481 | 528 | |
| 529 | +/** | |
| 530 | + * nlmsg_get_pos - return current position in netlink message | |
| 531 | + * @skb: socket buffer the message is stored in | |
| 532 | + * | |
| 533 | + * Returns a pointer to the current tail of the message. | |
| 534 | + */ | |
| 535 | +static inline void *nlmsg_get_pos(struct sk_buff *skb) | |
| 536 | +{ | |
| 537 | + return skb->tail; | |
| 538 | +} | |
| 539 | + | |
| 540 | +/** | |
| 541 | + * nlmsg_trim - Trim message to a mark | |
| 542 | + * @skb: socket buffer the message is stored in | |
| 543 | + * @mark: mark to trim to | |
| 544 | + * | |
| 545 | + * Trims the message to the provided mark. Returns -1. | |
| 546 | + */ | |
| 547 | +static inline int nlmsg_trim(struct sk_buff *skb, void *mark) | |
| 548 | +{ | |
| 549 | + if (mark) | |
| 550 | + skb_trim(skb, (unsigned char *) mark - skb->data); | |
| 551 | + | |
| 552 | + return -1; | |
| 553 | +} | |
| 554 | + | |
| 482 | 555 | /** |
| 483 | 556 | * nlmsg_cancel - Cancel construction of a netlink message |
| 484 | 557 | * @skb: socket buffer the message is stored in |
| @@ -489,9 +562,7 @@ static inline int nlmsg_end(struct sk_buff *skb, struct nlmsghdr *nlh) · 4 unmodified lines | ||
| 489 | 562 | */ |
| 490 | 563 | static inline int nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh) |
| 491 | 564 | { |
| 492 | − skb_trim(skb, (unsigned char *) nlh - skb->data); | |
| 493 | − | |
| 494 | − return -1; | |
| 565 | + return nlmsg_trim(skb, nlh); | |
| 495 | 566 | } |
| 496 | 567 | |
| 497 | 568 | /** |
| @@ -509,15 +580,16 @@ static inline void nlmsg_free(struct sk_buff *skb) · 11 unmodified lines | ||
| 509 | 580 | * @skb: netlink message as socket buffer |
| 510 | 581 | * @pid: own netlink pid to avoid sending to yourself |
| 511 | 582 | * @group: multicast group id |
| 583 | + * @flags: allocation flags | |
| 512 | 584 | */ |
| 513 | 585 | static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb, |
| 514 | − u32 pid, unsigned int group) | |
| 586 | + u32 pid, unsigned int group, gfp_t flags) | |
| 515 | 587 | { |
| 516 | 588 | int err; |
| 517 | 589 | |
| 518 | 590 | NETLINK_CB(skb).dst_group = group; |
| 519 | 591 | |
| 520 | − err = netlink_broadcast(sk, skb, pid, group, GFP_KERNEL); | |
| 592 | + err = netlink_broadcast(sk, skb, pid, group, flags); | |
| 521 | 593 | if (err > 0) |
| 522 | 594 | err = 0; |
| 523 | 595 | |
| @@ -630,6 +702,18 @@ static inline struct nlattr *nla_next(const struct nlattr *nla, int *remaining) · 106 unmodified lines | ||
| 630 | 702 | return (struct nlattr *) ((char *) nla + totlen); |
| 631 | 703 | } |
| 632 | 704 | |
| 705 | +/** | |
| 706 | + * nla_find_nested - find attribute in a set of nested attributes | |
| 707 | + * @nla: attribute containing the nested attributes | |
| 708 | + * @attrtype: type of attribute to look for | |
| 709 | + * | |
| 710 | + * Returns the first attribute which matches the specified type. | |
| 711 | + */ | |
| 712 | +static inline struct nlattr *nla_find_nested(struct nlattr *nla, int attrtype) | |
| 713 | +{ | |
| 714 | + return nla_find(nla_data(nla), nla_len(nla), attrtype); | |
| 715 | +} | |
| 716 | + | |
| 633 | 717 | /** |
| 634 | 718 | * nla_parse_nested - parse nested attributes |
| 635 | 719 | * @tb: destination array with maxtype+1 elements |
| @@ -751,7 +835,7 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype, · 115 unmodified lines | ||
| 751 | 835 | #define NLA_PUT_STRING(skb, attrtype, value) \ |
| 752 | 836 | NLA_PUT(skb, attrtype, strlen(value) + 1, value) |
| 753 | 837 | |
| 754 | −#define NLA_PUT_FLAG(skb, attrtype, value) \ | |
| 838 | +#define NLA_PUT_FLAG(skb, attrtype) \ | |
| 755 | 839 | NLA_PUT(skb, attrtype, 0, NULL) |
| 756 | 840 | |
| 757 | 841 | #define NLA_PUT_MSECS(skb, attrtype, jiffies) \ |
| @@ -862,10 +946,7 @@ static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start) · 104 unmodified lines | ||
| 862 | 946 | */ |
| 863 | 947 | static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start) |
| 864 | 948 | { |
| 865 | − if (start) | |
| 866 | − skb_trim(skb, (unsigned char *) start - skb->data); | |
| 867 | − | |
| 868 | − return -1; | |
| 949 | + return nlmsg_trim(skb, start); | |
| 869 | 950 | } |
| 870 | 951 | |
| 871 | 952 | /** |
| @@ -880,4 +961,13 @@ static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start) · 8 unmodified lines | ||
| 880 | 961 | nla_ok(pos, rem); \ |
| 881 | 962 | pos = nla_next(pos, &(rem))) |
| 882 | 963 | |
| 964 | +/** | |
| 965 | + * nla_for_each_nested - iterate over nested attributes | |
| 966 | + * @pos: loop counter, set to current attribute | |
| 967 | + * @nla: attribute containing the nested attributes | |
| 968 | + * @rem: initialized to len, holds bytes currently remaining in stream | |
| 969 | + */ | |
| 970 | +#define nla_for_each_nested(pos, nla, rem) \ | |
| 971 | + nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem) | |
| 972 | + | |
| 883 | 973 | #endif |
| @@ -0,0 +1,33 @@ | ||
| 1 | +#ifndef __NET_NEXTHOP_H | |
| 2 | +#define __NET_NEXTHOP_H | |
| 3 | + | |
| 4 | +#include <linux/rtnetlink.h> | |
| 5 | +#include <net/netlink.h> | |
| 6 | + | |
| 7 | +static inline int rtnh_ok(const struct rtnexthop *rtnh, int remaining) | |
| 8 | +{ | |
| 9 | + return remaining >= sizeof(*rtnh) && | |
| 10 | + rtnh->rtnh_len >= sizeof(*rtnh) && | |
| 11 | + rtnh->rtnh_len <= remaining; | |
| 12 | +} | |
| 13 | + | |
| 14 | +static inline struct rtnexthop *rtnh_next(const struct rtnexthop *rtnh, | |
| 15 | + int *remaining) | |
| 16 | +{ | |
| 17 | + int totlen = NLA_ALIGN(rtnh->rtnh_len); | |
| 18 | + | |
| 19 | + *remaining -= totlen; | |
| 20 | + return (struct rtnexthop *) ((char *) rtnh + totlen); | |
| 21 | +} | |
| 22 | + | |
| 23 | +static inline struct nlattr *rtnh_attrs(const struct rtnexthop *rtnh) | |
| 24 | +{ | |
| 25 | + return (struct nlattr *) ((char *) rtnh + NLA_ALIGN(sizeof(*rtnh))); | |
| 26 | +} | |
| 27 | + | |
| 28 | +static inline int rtnh_attrlen(const struct rtnexthop *rtnh) | |
| 29 | +{ | |
| 30 | + return rtnh->rtnh_len - NLA_ALIGN(sizeof(*rtnh)); | |
| 31 | +} | |
| 32 | + | |
| 33 | +#endif | |
| @@ -1,273 +0,0 @@ | ||
| 1 | −#ifndef __NET_PKT_ACT_H | |
| 2 | −#define __NET_PKT_ACT_H | |
| 3 | − | |
| 4 | −#include <asm/uaccess.h> | |
| 5 | −#include <asm/system.h> | |
| 6 | −#include <linux/bitops.h> | |
| 7 | −#include <linux/types.h> | |
| 8 | −#include <linux/kernel.h> | |
| 9 | −#include <linux/sched.h> | |
| 10 | −#include <linux/string.h> | |
| 11 | −#include <linux/mm.h> | |
| 12 | −#include <linux/socket.h> | |
| 13 | −#include <linux/sockios.h> | |
| 14 | −#include <linux/in.h> | |
| 15 | −#include <linux/errno.h> | |
| 16 | −#include <linux/interrupt.h> | |
| 17 | −#include <linux/skbuff.h> | |
| 18 | −#include <linux/rtnetlink.h> | |
| 19 | −#include <linux/module.h> | |
| 20 | −#include <linux/init.h> | |
| 21 | −#include <linux/proc_fs.h> | |
| 22 | −#include <net/sock.h> | |
| 23 | −#include <net/pkt_sched.h> | |
| 24 | − | |
| 25 | −#define tca_st(val) (struct tcf_##val *) | |
| 26 | −#define PRIV(a,name) ( tca_st(name) (a)->priv) | |
| 27 | − | |
| 28 | −#if 0 /* control */ | |
| 29 | −#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | |
| 30 | −#else | |
| 31 | −#define DPRINTK(format,args...) | |
| 32 | −#endif | |
| 33 | − | |
| 34 | −#if 0 /* data */ | |
| 35 | −#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args) | |
| 36 | −#else | |
| 37 | −#define D2PRINTK(format,args...) | |
| 38 | −#endif | |
| 39 | − | |
| 40 | −static __inline__ unsigned | |
| 41 | −tcf_hash(u32 index) | |
| 42 | −{ | |
| 43 | − return index & MY_TAB_MASK; | |
| 44 | −} | |
| 45 | − | |
| 46 | −/* probably move this from being inline | |
| 47 | − * and put into act_generic | |
| 48 | −*/ | |
| 49 | −static inline void | |
| 50 | −tcf_hash_destroy(struct tcf_st *p) | |
| 51 | −{ | |
| 52 | − unsigned h = tcf_hash(p->index); | |
| 53 | − struct tcf_st **p1p; | |
| 54 | − | |
| 55 | − for (p1p = &tcf_ht[h]; *p1p; p1p = &(*p1p)->next) { | |
| 56 | − if (*p1p == p) { | |
| 57 | − write_lock_bh(&tcf_t_lock); | |
| 58 | − *p1p = p->next; | |
| 59 | − write_unlock_bh(&tcf_t_lock); | |
| 60 | −#ifdef CONFIG_NET_ESTIMATOR | |
| 61 | − gen_kill_estimator(&p->bstats, &p->rate_est); | |
| 62 | −#endif | |
| 63 | − kfree(p); | |
| 64 | − return; | |
| 65 | − } | |
| 66 | − } | |
| 67 | − BUG_TRAP(0); | |
| 68 | −} | |
| 69 | − | |
| 70 | −static inline int | |
| 71 | −tcf_hash_release(struct tcf_st *p, int bind ) | |
| 72 | −{ | |
| 73 | − int ret = 0; | |
| 74 | − if (p) { | |
| 75 | − if (bind) { | |
| 76 | − p->bindcnt--; | |
| 77 | − } | |
| 78 | − p->refcnt--; | |
| 79 | − if(p->bindcnt <=0 && p->refcnt <= 0) { | |
| 80 | − tcf_hash_destroy(p); | |
| 81 | − ret = 1; | |
| 82 | − } | |
| 83 | − } | |
| 84 | − return ret; | |
| 85 | −} | |
| 86 | − | |
| 87 | −static __inline__ int | |
| 88 | −tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, | |
| 89 | − struct tc_action *a) | |
| 90 | −{ | |
| 91 | − struct tcf_st *p; | |
| 92 | − int err =0, index = -1,i= 0, s_i = 0, n_i = 0; | |
| 93 | − struct rtattr *r ; | |
| 94 | − | |
| 95 | − read_lock(&tcf_t_lock); | |
| 96 | − | |
| 97 | − s_i = cb->args[0]; | |
| 98 | − | |
| 99 | − for (i = 0; i < MY_TAB_SIZE; i++) { | |
| 100 | − p = tcf_ht[tcf_hash(i)]; | |
| 101 | − | |
| 102 | − for (; p; p = p->next) { | |
| 103 | − index++; | |
| 104 | − if (index < s_i) | |
| 105 | − continue; | |
| 106 | − a->priv = p; | |
| 107 | − a->order = n_i; | |
| 108 | − r = (struct rtattr*) skb->tail; | |
| 109 | − RTA_PUT(skb, a->order, 0, NULL); | |
| 110 | − err = tcf_action_dump_1(skb, a, 0, 0); | |
| 111 | − if (0 > err) { | |
| 112 | − index--; | |
| 113 | − skb_trim(skb, (u8*)r - skb->data); | |
| 114 | − goto done; | |
| 115 | − } | |
| 116 | − r->rta_len = skb->tail - (u8*)r; | |
| 117 | − n_i++; | |
| 118 | − if (n_i >= TCA_ACT_MAX_PRIO) { | |
| 119 | − goto done; | |
| 120 | − } | |
| 121 | − } | |
| 122 | − } | |
| 123 | −done: | |
| 124 | − read_unlock(&tcf_t_lock); | |
| 125 | − if (n_i) | |
| 126 | − cb->args[0] += n_i; | |
| 127 | − return n_i; | |
| 128 | − | |
| 129 | −rtattr_failure: | |
| 130 | − skb_trim(skb, (u8*)r - skb->data); | |
| 131 | − goto done; | |
| 132 | −} | |
| 133 | − | |
| 134 | −static __inline__ int | |
| 135 | −tcf_del_walker(struct sk_buff *skb, struct tc_action *a) | |
| 136 | −{ | |
| 137 | − struct tcf_st *p, *s_p; | |
| 138 | − struct rtattr *r ; | |
| 139 | − int i= 0, n_i = 0; | |
| 140 | − | |
| 141 | − r = (struct rtattr*) skb->tail; | |
| 142 | − RTA_PUT(skb, a->order, 0, NULL); | |
| 143 | − RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); | |
| 144 | − for (i = 0; i < MY_TAB_SIZE; i++) { | |
| 145 | − p = tcf_ht[tcf_hash(i)]; | |
| 146 | − | |
| 147 | − while (p != NULL) { | |
| 148 | − s_p = p->next; | |
| 149 | − if (ACT_P_DELETED == tcf_hash_release(p, 0)) { | |
| 150 | − module_put(a->ops->owner); | |
| 151 | − } | |
| 152 | − n_i++; | |
| 153 | − p = s_p; | |
| 154 | − } | |
| 155 | − } | |
| 156 | − RTA_PUT(skb, TCA_FCNT, 4, &n_i); | |
| 157 | − r->rta_len = skb->tail - (u8*)r; | |
| 158 | − | |
| 159 | − return n_i; | |
| 160 | −rtattr_failure: | |
| 161 | − skb_trim(skb, (u8*)r - skb->data); | |
| 162 | − return -EINVAL; | |
| 163 | −} | |
| 164 | − | |
| 165 | −static __inline__ int | |
| 166 | −tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, int type, | |
| 167 | − struct tc_action *a) | |
| 168 | −{ | |
| 169 | − if (type == RTM_DELACTION) { | |
| 170 | − return tcf_del_walker(skb,a); | |
| 171 | − } else if (type == RTM_GETACTION) { | |
| 172 | − return tcf_dump_walker(skb,cb,a); | |
| 173 | − } else { | |
| 174 | − printk("tcf_generic_walker: unknown action %d\n",type); | |
| 175 | − return -EINVAL; | |
| 176 | − } | |
| 177 | −} | |
| 178 | − | |
| 179 | −static __inline__ struct tcf_st * | |
| 180 | −tcf_hash_lookup(u32 index) | |
| 181 | −{ | |
| 182 | − struct tcf_st *p; | |
| 183 | − | |
| 184 | − read_lock(&tcf_t_lock); | |
| 185 | − for (p = tcf_ht[tcf_hash(index)]; p; p = p->next) { | |
| 186 | − if (p->index == index) | |
| 187 | − break; | |
| 188 | − } | |
| 189 | − read_unlock(&tcf_t_lock); | |
| 190 | − return p; | |
| 191 | −} | |
| 192 | − | |
| 193 | −static __inline__ u32 | |
| 194 | −tcf_hash_new_index(void) | |
| 195 | −{ | |
| 196 | − do { | |
| 197 | − if (++idx_gen == 0) | |
| 198 | − idx_gen = 1; | |
| 199 | − } while (tcf_hash_lookup(idx_gen)); | |
| 200 | − | |
| 201 | − return idx_gen; | |
| 202 | −} | |
| 203 | − | |
| 204 | − | |
| 205 | −static inline int | |
| 206 | −tcf_hash_search(struct tc_action *a, u32 index) | |
| 207 | −{ | |
| 208 | − struct tcf_st *p = tcf_hash_lookup(index); | |
| 209 | − | |
| 210 | − if (p != NULL) { | |
| 211 | − a->priv = p; | |
| 212 | − return 1; | |
| 213 | − } | |
| 214 | − return 0; | |
| 215 | −} | |
| 216 | − | |
| 217 | −#ifdef CONFIG_NET_ACT_INIT | |
| 218 | −static inline struct tcf_st * | |
| 219 | −tcf_hash_check(u32 index, struct tc_action *a, int ovr, int bind) | |
| 220 | −{ | |
| 221 | − struct tcf_st *p = NULL; | |
| 222 | − if (index && (p = tcf_hash_lookup(index)) != NULL) { | |
| 223 | − if (bind) { | |
| 224 | − p->bindcnt++; | |
| 225 | − p->refcnt++; | |
| 226 | − } | |
| 227 | − a->priv = p; | |
| 228 | − } | |
| 229 | − return p; | |
| 230 | −} | |
| 231 | − | |
| 232 | −static inline struct tcf_st * | |
| 233 | −tcf_hash_create(u32 index, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind) | |
| 234 | −{ | |
| 235 | − struct tcf_st *p = NULL; | |
| 236 | − | |
| 237 | − p = kmalloc(size, GFP_KERNEL); | |
| 238 | − if (p == NULL) | |
| 239 | − return p; | |
| 240 | − | |
| 241 | − memset(p, 0, size); | |
| 242 | − p->refcnt = 1; | |
| 243 | − | |
| 244 | − if (bind) { | |
| 245 | − p->bindcnt = 1; | |
| 246 | − } | |
| 247 | − | |
| 248 | − spin_lock_init(&p->lock); | |
| 249 | − p->stats_lock = &p->lock; | |
| 250 | − p->index = index ? : tcf_hash_new_index(); | |
| 251 | − p->tm.install = jiffies; | |
| 252 | − p->tm.lastuse = jiffies; | |
| 253 | −#ifdef CONFIG_NET_ESTIMATOR | |
| 254 | − if (est) | |
| 255 | − gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); | |
| 256 | −#endif | |
| 257 | − a->priv = (void *) p; | |
| 258 | − return p; | |
| 259 | −} | |
| 260 | − | |
| 261 | −static inline void tcf_hash_insert(struct tcf_st *p) | |
| 262 | −{ | |
| 263 | − unsigned h = tcf_hash(p->index); | |
| 264 | − | |
| 265 | − write_lock_bh(&tcf_t_lock); | |
| 266 | − p->next = tcf_ht[h]; | |
| 267 | − tcf_ht[h] = p; | |
| 268 | − write_unlock_bh(&tcf_t_lock); | |
| 269 | −} | |
| 270 | − | |
| 271 | −#endif | |
| 272 | − | |
| 273 | −#endif | |
| @@ -53,6 +53,7 @@ struct request_sock { · 52 unmodified lines | ||
| 53 | 53 | unsigned long expires; |
| 54 | 54 | struct request_sock_ops *rsk_ops; |
| 55 | 55 | struct sock *sk; |
| 56 | + u32 secid; | |
| 56 | 57 | }; |
| 57 | 58 | |
| 58 | 59 | static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops) |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | ||
| 32 | 32 | #include <linux/route.h> |
| 33 | 33 | #include <linux/ip.h> |
| 34 | 34 | #include <linux/cache.h> |
| 35 | +#include <linux/security.h> | |
| 35 | 36 | |
| 36 | 37 | #ifndef __KERNEL__ |
| 37 | 38 | #warning This file is not supposed to be used outside of kernel. |
| @@ -166,6 +167,7 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst, · 128 unmodified lines | ||
| 166 | 167 | ip_rt_put(*rp); |
| 167 | 168 | *rp = NULL; |
| 168 | 169 | } |
| 170 | + security_sk_classify_flow(sk, &fl); | |
| 169 | 171 | return ip_route_output_flow(rp, &fl, sk, 0); |
| 170 | 172 | } |
| 171 | 173 | |
| @@ -182,6 +184,7 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol, · 10 unmodified lines | ||
| 182 | 184 | fl.proto = protocol; |
| 183 | 185 | ip_rt_put(*rp); |
| 184 | 186 | *rp = NULL; |
| 187 | + security_sk_classify_flow(sk, &fl); | |
| 185 | 188 | return ip_route_output_flow(rp, &fl, sk, 0); |
| 186 | 189 | } |
| 187 | 190 | return 0; |
| @@ -264,10 +264,10 @@ enum { SCTP_MAX_DUP_TSNS = 16 }; · 263 unmodified lines | ||
| 264 | 264 | enum { SCTP_MAX_GABS = 16 }; |
| 265 | 265 | |
| 266 | 266 | /* Heartbeat interval - 30 secs */ |
| 267 | −#define SCTP_DEFAULT_TIMEOUT_HEARTBEAT (30 * HZ) | |
| 267 | +#define SCTP_DEFAULT_TIMEOUT_HEARTBEAT (30*1000) | |
| 268 | 268 | |
| 269 | 269 | /* Delayed sack timer - 200ms */ |
| 270 | −#define SCTP_DEFAULT_TIMEOUT_SACK ((200 * HZ) / 1000) | |
| 270 | +#define SCTP_DEFAULT_TIMEOUT_SACK (200) | |
| 271 | 271 | |
| 272 | 272 | /* RTO.Initial - 3 seconds |
| 273 | 273 | * RTO.Min - 1 second |
| @@ -275,9 +275,9 @@ enum { SCTP_MAX_GABS = 16 }; · 1 unmodified line | ||
| 275 | 275 | * RTO.Alpha - 1/8 |
| 276 | 276 | * RTO.Beta - 1/4 |
| 277 | 277 | */ |
| 278 | −#define SCTP_RTO_INITIAL (3 * HZ) | |
| 279 | −#define SCTP_RTO_MIN (1 * HZ) | |
| 280 | −#define SCTP_RTO_MAX (60 * HZ) | |
| 278 | +#define SCTP_RTO_INITIAL (3 * 1000) | |
| 279 | +#define SCTP_RTO_MIN (1 * 1000) | |
| 280 | +#define SCTP_RTO_MAX (60 * 1000) | |
| 281 | 281 | |
| 282 | 282 | #define SCTP_RTO_ALPHA 3 /* 1/8 when converted to right shifts. */ |
| 283 | 283 | #define SCTP_RTO_BETA 2 /* 1/4 when converted to right shifts. */ |
| @@ -290,8 +290,7 @@ enum { SCTP_MAX_GABS = 16 }; · 6 unmodified lines | ||
| 290 | 290 | #define SCTP_DEF_MAX_INIT 6 |
| 291 | 291 | #define SCTP_DEF_MAX_SEND 10 |
| 292 | 292 | |
| 293 | −#define SCTP_DEFAULT_COOKIE_LIFE_SEC 60 /* seconds */ | |
| 294 | −#define SCTP_DEFAULT_COOKIE_LIFE_USEC 0 /* microseconds */ | |
| 293 | +#define SCTP_DEFAULT_COOKIE_LIFE (60 * 1000) /* 60 seconds */ | |
| 295 | 294 | |
| 296 | 295 | #define SCTP_DEFAULT_MINWINDOW 1500 /* default minimum rwnd size */ |
| 297 | 296 | #define SCTP_DEFAULT_MAXWINDOW 65535 /* default rwnd size */ |
| @@ -128,6 +128,8 @@ extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, · 127 unmodified lines | ||
| 128 | 128 | int flags); |
| 129 | 129 | extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); |
| 130 | 130 | extern int sctp_register_pf(struct sctp_pf *, sa_family_t); |
| 131 | +int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |
| 132 | + void *ptr); | |
| 131 | 133 | |
| 132 | 134 | /* |
| 133 | 135 | * sctp/socket.c |
| @@ -177,6 +179,17 @@ void sctp_icmp_proto_unreachable(struct sock *sk, · 43 unmodified lines | ||
| 177 | 179 | void sctp_backlog_migrate(struct sctp_association *assoc, |
| 178 | 180 | struct sock *oldsk, struct sock *newsk); |
| 179 | 181 | |
| 182 | +/* | |
| 183 | + * sctp/proc.c | |
| 184 | + */ | |
| 185 | +int sctp_snmp_proc_init(void); | |
| 186 | +void sctp_snmp_proc_exit(void); | |
| 187 | +int sctp_eps_proc_init(void); | |
| 188 | +void sctp_eps_proc_exit(void); | |
| 189 | +int sctp_assocs_proc_init(void); | |
| 190 | +void sctp_assocs_proc_exit(void); | |
| 191 | + | |
| 192 | + | |
| 180 | 193 | /* |
| 181 | 194 | * Section: Macros, externs, and inlines |
| 182 | 195 | */ |
| @@ -216,6 +229,50 @@ DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics); · 33 unmodified lines | ||
| 216 | 229 | |
| 217 | 230 | #endif /* !TEST_FRAME */ |
| 218 | 231 | |
| 232 | +/* sctp mib definitions */ | |
| 233 | +enum | |
| 234 | +{ | |
| 235 | + SCTP_MIB_NUM = 0, | |
| 236 | + SCTP_MIB_CURRESTAB, /* CurrEstab */ | |
| 237 | + SCTP_MIB_ACTIVEESTABS, /* ActiveEstabs */ | |
| 238 | + SCTP_MIB_PASSIVEESTABS, /* PassiveEstabs */ | |
| 239 | + SCTP_MIB_ABORTEDS, /* Aborteds */ | |
| 240 | + SCTP_MIB_SHUTDOWNS, /* Shutdowns */ | |
| 241 | + SCTP_MIB_OUTOFBLUES, /* OutOfBlues */ | |
| 242 | + SCTP_MIB_CHECKSUMERRORS, /* ChecksumErrors */ | |
| 243 | + SCTP_MIB_OUTCTRLCHUNKS, /* OutCtrlChunks */ | |
| 244 | + SCTP_MIB_OUTORDERCHUNKS, /* OutOrderChunks */ | |
| 245 | + SCTP_MIB_OUTUNORDERCHUNKS, /* OutUnorderChunks */ | |
| 246 | + SCTP_MIB_INCTRLCHUNKS, /* InCtrlChunks */ | |
| 247 | + SCTP_MIB_INORDERCHUNKS, /* InOrderChunks */ | |
| 248 | + SCTP_MIB_INUNORDERCHUNKS, /* InUnorderChunks */ | |
| 249 | + SCTP_MIB_FRAGUSRMSGS, /* FragUsrMsgs */ | |
| 250 | + SCTP_MIB_REASMUSRMSGS, /* ReasmUsrMsgs */ | |
| 251 | + SCTP_MIB_OUTSCTPPACKS, /* OutSCTPPacks */ | |
| 252 | + SCTP_MIB_INSCTPPACKS, /* InSCTPPacks */ | |
| 253 | + SCTP_MIB_T1_INIT_EXPIREDS, | |
| 254 | + SCTP_MIB_T1_COOKIE_EXPIREDS, | |
| 255 | + SCTP_MIB_T2_SHUTDOWN_EXPIREDS, | |
| 256 | + SCTP_MIB_T3_RTX_EXPIREDS, | |
| 257 | + SCTP_MIB_T4_RTO_EXPIREDS, | |
| 258 | + SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS, | |
| 259 | + SCTP_MIB_DELAY_SACK_EXPIREDS, | |
| 260 | + SCTP_MIB_AUTOCLOSE_EXPIREDS, | |
| 261 | + SCTP_MIB_T3_RETRANSMITS, | |
| 262 | + SCTP_MIB_PMTUD_RETRANSMITS, | |
| 263 | + SCTP_MIB_FAST_RETRANSMITS, | |
| 264 | + SCTP_MIB_IN_PKT_SOFTIRQ, | |
| 265 | + SCTP_MIB_IN_PKT_BACKLOG, | |
| 266 | + SCTP_MIB_IN_PKT_DISCARDS, | |
| 267 | + SCTP_MIB_IN_DATA_CHUNK_DISCARDS, | |
| 268 | + __SCTP_MIB_MAX | |
| 269 | +}; | |
| 270 | + | |
| 271 | +#define SCTP_MIB_MAX __SCTP_MIB_MAX | |
| 272 | +struct sctp_mib { | |
| 273 | + unsigned long mibs[SCTP_MIB_MAX]; | |
| 274 | +} __SNMP_MIB_ALIGN__; | |
| 275 | + | |
| 219 | 276 | |
| 220 | 277 | /* Print debugging messages. */ |
| 221 | 278 | #if SCTP_DEBUG |
| @@ -128,9 +128,9 @@ extern struct sctp_globals { · 127 unmodified lines | ||
| 128 | 128 | * RTO.Alpha - 1/8 (3 when converted to right shifts.) |
| 129 | 129 | * RTO.Beta - 1/4 (2 when converted to right shifts.) |
| 130 | 130 | */ |
| 131 | − unsigned long rto_initial; | |
| 132 | − unsigned long rto_min; | |
| 133 | − unsigned long rto_max; | |
| 131 | + unsigned int rto_initial; | |
| 132 | + unsigned int rto_min; | |
| 133 | + unsigned int rto_max; | |
| 134 | 134 | |
| 135 | 135 | /* Note: rto_alpha and rto_beta are really defined as inverse |
| 136 | 136 | * powers of two to facilitate integer operations. |
| @@ -145,13 +145,13 @@ extern struct sctp_globals { · 8 unmodified lines | ||
| 145 | 145 | int cookie_preserve_enable; |
| 146 | 146 | |
| 147 | 147 | /* Valid.Cookie.Life - 60 seconds */ |
| 148 | − unsigned long valid_cookie_life; | |
| 148 | + unsigned int valid_cookie_life; | |
| 149 | 149 | |
| 150 | 150 | /* Delayed SACK timeout 200ms default*/ |
| 151 | − unsigned long sack_timeout; | |
| 151 | + unsigned int sack_timeout; | |
| 152 | 152 | |
| 153 | 153 | /* HB.interval - 30 seconds */ |
| 154 | − unsigned long hb_interval; | |
| 154 | + unsigned int hb_interval; | |
| 155 | 155 | |
| 156 | 156 | /* Association.Max.Retrans - 10 attempts |
| 157 | 157 | * Path.Max.Retrans - 5 attempts (per destination address) |
| @@ -100,12 +100,6 @@ struct udp_mib { · 99 unmodified lines | ||
| 100 | 100 | unsigned long mibs[UDP_MIB_MAX]; |
| 101 | 101 | } __SNMP_MIB_ALIGN__; |
| 102 | 102 | |
| 103 | −/* SCTP */ | |
| 104 | −#define SCTP_MIB_MAX __SCTP_MIB_MAX | |
| 105 | −struct sctp_mib { | |
| 106 | − unsigned long mibs[SCTP_MIB_MAX]; | |
| 107 | −} __SNMP_MIB_ALIGN__; | |
| 108 | − | |
| 109 | 103 | /* Linux */ |
| 110 | 104 | #define LINUX_MIB_MAX __LINUX_MIB_MAX |
| 111 | 105 | struct linux_mib { |
| @@ -862,30 +862,24 @@ extern void sock_init_data(struct socket *sock, struct sock *sk); · 861 unmodified lines | ||
| 862 | 862 | * |
| 863 | 863 | */ |
| 864 | 864 | |
| 865 | −static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock) | |
| 865 | +static inline int sk_filter(struct sock *sk, struct sk_buff *skb) | |
| 866 | 866 | { |
| 867 | 867 | int err; |
| 868 | + struct sk_filter *filter; | |
| 868 | 869 | |
| 869 | 870 | err = security_sock_rcv_skb(sk, skb); |
| 870 | 871 | if (err) |
| 871 | 872 | return err; |
| 872 | 873 | |
| 873 | − if (sk->sk_filter) { | |
| 874 | − struct sk_filter *filter; | |
| 875 | − | |
| 876 | − if (needlock) | |
| 877 | − bh_lock_sock(sk); | |
| 878 | − | |
| 879 | − filter = sk->sk_filter; | |
| 880 | − if (filter) { | |
| 881 | − unsigned int pkt_len = sk_run_filter(skb, filter->insns, | |
| 882 | − filter->len); | |
| 883 | − err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; | |
| 884 | − } | |
| 885 | − | |
| 886 | − if (needlock) | |
| 887 | − bh_unlock_sock(sk); | |
| 874 | + rcu_read_lock_bh(); | |
| 875 | + filter = sk->sk_filter; | |
| 876 | + if (filter) { | |
| 877 | + unsigned int pkt_len = sk_run_filter(skb, filter->insns, | |
| 878 | + filter->len); | |
| 879 | + err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; | |
| 888 | 880 | } |
| 881 | + rcu_read_unlock_bh(); | |
| 882 | + | |
| 889 | 883 | return err; |
| 890 | 884 | } |
| 891 | 885 | |
| @@ -897,6 +891,12 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock) · 5 unmodified lines | ||
| 897 | 891 | * Remove a filter from a socket and release its resources. |
| 898 | 892 | */ |
| 899 | 893 | |
| 894 | +static inline void sk_filter_rcu_free(struct rcu_head *rcu) | |
| 895 | +{ | |
| 896 | + struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); | |
| 897 | + kfree(fp); | |
| 898 | +} | |
| 899 | + | |
| 900 | 900 | static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp) |
| 901 | 901 | { |
| 902 | 902 | unsigned int size = sk_filter_len(fp); |
| @@ -904,7 +904,7 @@ static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp) · 1 unmodified line | ||
| 904 | 904 | atomic_sub(size, &sk->sk_omem_alloc); |
| 905 | 905 | |
| 906 | 906 | if (atomic_dec_and_test(&fp->refcnt)) |
| 907 | − kfree(fp); | |
| 907 | + call_rcu_bh(&fp->rcu, sk_filter_rcu_free); | |
| 908 | 908 | } |
| 909 | 909 | |
| 910 | 910 | static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp) |
| @@ -969,9 +969,23 @@ static inline void sock_graft(struct sock *sk, struct socket *parent) · 58 unmodified lines | ||
| 969 | 969 | sk->sk_sleep = &parent->wait; |
| 970 | 970 | parent->sk = sk; |
| 971 | 971 | sk->sk_socket = parent; |
| 972 | + security_sock_graft(sk, parent); | |
| 972 | 973 | write_unlock_bh(&sk->sk_callback_lock); |
| 973 | 974 | } |
| 974 | 975 | |
| 976 | +static inline void sock_copy(struct sock *nsk, const struct sock *osk) | |
| 977 | +{ | |
| 978 | +#ifdef CONFIG_SECURITY_NETWORK | |
| 979 | + void *sptr = nsk->sk_security; | |
| 980 | +#endif | |
| 981 | + | |
| 982 | + memcpy(nsk, osk, osk->sk_prot->obj_size); | |
| 983 | +#ifdef CONFIG_SECURITY_NETWORK | |
| 984 | + nsk->sk_security = sptr; | |
| 985 | + security_sk_clone(osk, nsk); | |
| 986 | +#endif | |
| 987 | +} | |
| 988 | + | |
| 975 | 989 | extern int sock_i_uid(struct sock *sk); |
| 976 | 990 | extern unsigned long sock_i_ino(struct sock *sk); |
| 977 | 991 | |
| @@ -3,11 +3,12 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | #include <net/act_api.h> |
| 5 | 5 | |
| 6 | −struct tcf_defact | |
| 7 | −{ | |
| 8 | − tca_gen(defact); | |
| 9 | − u32 datalen; | |
| 10 | − void *defdata; | |
| 6 | +struct tcf_defact { | |
| 7 | + struct tcf_common common; | |
| 8 | + u32 tcfd_datalen; | |
| 9 | + void *tcfd_defdata; | |
| 11 | 10 | }; |
| 11 | +#define to_defact(pc) \ | |
| 12 | + container_of(pc, struct tcf_defact, common) | |
| 12 | 13 | |
| 13 | −#endif | |
| 14 | +#endif /* __NET_TC_DEF_H */ | |
| @@ -3,15 +3,15 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | #include <net/act_api.h> |
| 5 | 5 | |
| 6 | −struct tcf_gact | |
| 7 | −{ | |
| 8 | − tca_gen(gact); | |
| 6 | +struct tcf_gact { | |
| 7 | + struct tcf_common common; | |
| 9 | 8 | #ifdef CONFIG_GACT_PROB |
| 10 | − u16 ptype; | |
| 11 | − u16 pval; | |
| 12 | − int paction; | |
| 9 | + u16 tcfg_ptype; | |
| 10 | + u16 tcfg_pval; | |
| 11 | + int tcfg_paction; | |
| 13 | 12 | #endif |
| 14 | − | |
| 15 | 13 | }; |
| 16 | − | |
| 17 | −#endif | |
| 14 | +#define to_gact(pc) \ | |
| 15 | + container_of(pc, struct tcf_gact, common) | |
| 16 | + | |
| 17 | +#endif /* __NET_TC_GACT_H */ | |
| @@ -5,12 +5,13 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | struct xt_entry_target; |
| 7 | 7 | |
| 8 | −struct tcf_ipt | |
| 9 | −{ | |
| 10 | − tca_gen(ipt); | |
| 11 | − u32 hook; | |
| 12 | − char *tname; | |
| 13 | − struct xt_entry_target *t; | |
| 8 | +struct tcf_ipt { | |
| 9 | + struct tcf_common common; | |
| 10 | + u32 tcfi_hook; | |
| 11 | + char *tcfi_tname; | |
| 12 | + struct xt_entry_target *tcfi_t; | |
| 14 | 13 | }; |
| 14 | +#define to_ipt(pc) \ | |
| 15 | + container_of(pc, struct tcf_ipt, common) | |
| 15 | 16 | |
| 16 | −#endif | |
| 17 | +#endif /* __NET_TC_IPT_H */ | |
| @@ -3,13 +3,14 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | #include <net/act_api.h> |
| 5 | 5 | |
| 6 | −struct tcf_mirred | |
| 7 | −{ | |
| 8 | − tca_gen(mirred); | |
| 9 | − int eaction; | |
| 10 | − int ifindex; | |
| 11 | − int ok_push; | |
| 12 | − struct net_device *dev; | |
| 6 | +struct tcf_mirred { | |
| 7 | + struct tcf_common common; | |
| 8 | + int tcfm_eaction; | |
| 9 | + int tcfm_ifindex; | |
| 10 | + int tcfm_ok_push; | |
| 11 | + struct net_device *tcfm_dev; | |
| 13 | 12 | }; |
| 13 | +#define to_mirred(pc) \ | |
| 14 | + container_of(pc, struct tcf_mirred, common) | |
| 14 | 15 | |
| 15 | −#endif | |
| 16 | +#endif /* __NET_TC_MIR_H */ | |
| @@ -3,12 +3,13 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | #include <net/act_api.h> |
| 5 | 5 | |
| 6 | −struct tcf_pedit | |
| 7 | −{ | |
| 8 | − tca_gen(pedit); | |
| 9 | − unsigned char nkeys; | |
| 10 | − unsigned char flags; | |
| 11 | − struct tc_pedit_key *keys; | |
| 6 | +struct tcf_pedit { | |
| 7 | + struct tcf_common common; | |
| 8 | + unsigned char tcfp_nkeys; | |
| 9 | + unsigned char tcfp_flags; | |
| 10 | + struct tc_pedit_key *tcfp_keys; | |
| 12 | 11 | }; |
| 12 | +#define to_pedit(pc) \ | |
| 13 | + container_of(pc, struct tcf_pedit, common) | |
| 13 | 14 | |
| 14 | −#endif | |
| 15 | +#endif /* __NET_TC_PED_H */ | |
| @@ -30,25 +30,9 @@ · 29 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | #define UDP_HTABLE_SIZE 128 |
| 32 | 32 | |
| 33 | −/* udp.c: This needs to be shared by v4 and v6 because the lookup | |
| 34 | − * and hashing code needs to work with different AF's yet | |
| 35 | − * the port space is shared. | |
| 36 | − */ | |
| 37 | 33 | extern struct hlist_head udp_hash[UDP_HTABLE_SIZE]; |
| 38 | 34 | extern rwlock_t udp_hash_lock; |
| 39 | 35 | |
| 40 | −extern int udp_port_rover; | |
| 41 | − | |
| 42 | −static inline int udp_lport_inuse(u16 num) | |
| 43 | −{ | |
| 44 | − struct sock *sk; | |
| 45 | − struct hlist_node *node; | |
| 46 | − | |
| 47 | − sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)]) | |
| 48 | − if (inet_sk(sk)->num == num) | |
| 49 | − return 1; | |
| 50 | − return 0; | |
| 51 | −} | |
| 52 | 36 | |
| 53 | 37 | /* Note: this must match 'valbool' in sock_setsockopt */ |
| 54 | 38 | #define UDP_CSUM_NOXMIT 1 |
| @@ -63,6 +47,8 @@ extern struct proto udp_prot; · 8 unmodified lines | ||
| 63 | 47 | |
| 64 | 48 | struct sk_buff; |
| 65 | 49 | |
| 50 | +extern int udp_get_port(struct sock *sk, unsigned short snum, | |
| 51 | + int (*saddr_cmp)(const struct sock *, const struct sock *)); | |
| 66 | 52 | extern void udp_err(struct sk_buff *, u32); |
| 67 | 53 | |
| 68 | 54 | extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/skbuff.h> |
| 10 | 10 | #include <linux/socket.h> |
| 11 | 11 | #include <linux/pfkeyv2.h> |
| 12 | +#include <linux/ipsec.h> | |
| 12 | 13 | #include <linux/in6.h> |
| 13 | 14 | #include <linux/mutex.h> |
| 14 | 15 | |
| @@ -93,8 +94,9 @@ extern struct mutex xfrm_cfg_mutex; · 78 unmodified lines | ||
| 93 | 94 | struct xfrm_state |
| 94 | 95 | { |
| 95 | 96 | /* Note: bydst is re-used during gc */ |
| 96 | − struct list_head bydst; | |
| 97 | − struct list_head byspi; | |
| 97 | + struct hlist_node bydst; | |
| 98 | + struct hlist_node bysrc; | |
| 99 | + struct hlist_node byspi; | |
| 98 | 100 | |
| 99 | 101 | atomic_t refcnt; |
| 100 | 102 | spinlock_t lock; |
| @@ -102,6 +104,8 @@ struct xfrm_state · 1 unmodified line | ||
| 102 | 104 | struct xfrm_id id; |
| 103 | 105 | struct xfrm_selector sel; |
| 104 | 106 | |
| 107 | + u32 genid; | |
| 108 | + | |
| 105 | 109 | /* Key manger bits */ |
| 106 | 110 | struct { |
| 107 | 111 | u8 state; |
| @@ -132,6 +136,9 @@ struct xfrm_state · 24 unmodified lines | ||
| 132 | 136 | /* Data for encapsulator */ |
| 133 | 137 | struct xfrm_encap_tmpl *encap; |
| 134 | 138 | |
| 139 | + /* Data for care-of address */ | |
| 140 | + xfrm_address_t *coaddr; | |
| 141 | + | |
| 135 | 142 | /* IPComp needs an IPIP tunnel for handling uncompressed packets */ |
| 136 | 143 | struct xfrm_state *tunnel; |
| 137 | 144 | |
| @@ -162,6 +169,9 @@ struct xfrm_state · 24 unmodified lines | ||
| 162 | 169 | struct xfrm_lifetime_cur curlft; |
| 163 | 170 | struct timer_list timer; |
| 164 | 171 | |
| 172 | + /* Last used time */ | |
| 173 | + u64 lastused; | |
| 174 | + | |
| 165 | 175 | /* Reference to data common to all the instances of this |
| 166 | 176 | * transformer. */ |
| 167 | 177 | struct xfrm_type *type; |
| @@ -195,6 +205,7 @@ struct km_event · 27 unmodified lines | ||
| 195 | 205 | u32 proto; |
| 196 | 206 | u32 byid; |
| 197 | 207 | u32 aevent; |
| 208 | + u32 type; | |
| 198 | 209 | } data; |
| 199 | 210 | |
| 200 | 211 | u32 seq; |
| @@ -211,6 +222,7 @@ struct xfrm_policy_afinfo { · 10 unmodified lines | ||
| 211 | 222 | struct dst_ops *dst_ops; |
| 212 | 223 | void (*garbage_collect)(void); |
| 213 | 224 | int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl); |
| 225 | + int (*get_saddr)(xfrm_address_t *saddr, xfrm_address_t *daddr); | |
| 214 | 226 | struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy); |
| 215 | 227 | int (*bundle_create)(struct xfrm_policy *policy, |
| 216 | 228 | struct xfrm_state **xfrm, |
| @@ -234,16 +246,12 @@ extern int __xfrm_state_delete(struct xfrm_state *x); · 17 unmodified lines | ||
| 234 | 246 | |
| 235 | 247 | struct xfrm_state_afinfo { |
| 236 | 248 | unsigned short family; |
| 237 | − struct list_head *state_bydst; | |
| 238 | − struct list_head *state_byspi; | |
| 239 | 249 | int (*init_flags)(struct xfrm_state *x); |
| 240 | 250 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, |
| 241 | 251 | struct xfrm_tmpl *tmpl, |
| 242 | 252 | xfrm_address_t *daddr, xfrm_address_t *saddr); |
| 243 | − struct xfrm_state *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto); | |
| 244 | − struct xfrm_state *(*find_acq)(u8 mode, u32 reqid, u8 proto, | |
| 245 | − xfrm_address_t *daddr, xfrm_address_t *saddr, | |
| 246 | − int create); | |
| 253 | + int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); | |
| 254 | + int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); | |
| 247 | 255 | }; |
| 248 | 256 | |
| 249 | 257 | extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); |
| @@ -256,11 +264,17 @@ struct xfrm_type · 6 unmodified lines | ||
| 256 | 264 | char *description; |
| 257 | 265 | struct module *owner; |
| 258 | 266 | __u8 proto; |
| 267 | + __u8 flags; | |
| 268 | +#define XFRM_TYPE_NON_FRAGMENT 1 | |
| 259 | 269 | |
| 260 | 270 | int (*init_state)(struct xfrm_state *x); |
| 261 | 271 | void (*destructor)(struct xfrm_state *); |
| 262 | 272 | int (*input)(struct xfrm_state *, struct sk_buff *skb); |
| 263 | 273 | int (*output)(struct xfrm_state *, struct sk_buff *pskb); |
| 274 | + int (*reject)(struct xfrm_state *, struct sk_buff *, struct flowi *); | |
| 275 | + int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **); | |
| 276 | + xfrm_address_t *(*local_addr)(struct xfrm_state *, xfrm_address_t *); | |
| 277 | + xfrm_address_t *(*remote_addr)(struct xfrm_state *, xfrm_address_t *); | |
| 264 | 278 | /* Estimate maximal size of result of transformation of a dgram */ |
| 265 | 279 | u32 (*get_max_size)(struct xfrm_state *, int size); |
| 266 | 280 | }; |
| @@ -272,7 +286,7 @@ extern void xfrm_put_type(struct xfrm_type *type); · 5 unmodified lines | ||
| 272 | 286 | |
| 273 | 287 | struct xfrm_mode { |
| 274 | 288 | int (*input)(struct xfrm_state *x, struct sk_buff *skb); |
| 275 | − int (*output)(struct sk_buff *skb); | |
| 289 | + int (*output)(struct xfrm_state *x,struct sk_buff *skb); | |
| 276 | 290 | |
| 277 | 291 | struct module *owner; |
| 278 | 292 | unsigned int encap; |
| @@ -298,7 +312,7 @@ struct xfrm_tmpl · 19 unmodified lines | ||
| 298 | 312 | |
| 299 | 313 | __u32 reqid; |
| 300 | 314 | |
| 301 | −/* Mode: transport/tunnel */ | |
| 315 | +/* Mode: transport, tunnel etc. */ | |
| 302 | 316 | __u8 mode; |
| 303 | 317 | |
| 304 | 318 | /* Sharing mode: unique, this session only, this user only etc. */ |
| @@ -313,18 +327,20 @@ struct xfrm_tmpl · 8 unmodified lines | ||
| 313 | 327 | __u32 calgos; |
| 314 | 328 | }; |
| 315 | 329 | |
| 316 | −#define XFRM_MAX_DEPTH 4 | |
| 330 | +#define XFRM_MAX_DEPTH 6 | |
| 317 | 331 | |
| 318 | 332 | struct xfrm_policy |
| 319 | 333 | { |
| 320 | 334 | struct xfrm_policy *next; |
| 321 | − struct list_head list; | |
| 335 | + struct hlist_node bydst; | |
| 336 | + struct hlist_node byidx; | |
| 322 | 337 | |
| 323 | 338 | /* This lock only affects elements except for entry. */ |
| 324 | 339 | rwlock_t lock; |
| 325 | 340 | atomic_t refcnt; |
| 326 | 341 | struct timer_list timer; |
| 327 | 342 | |
| 343 | + u8 type; | |
| 328 | 344 | u32 priority; |
| 329 | 345 | u32 index; |
| 330 | 346 | struct xfrm_selector selector; |
| @@ -362,16 +378,16 @@ struct xfrm_mgr · 31 unmodified lines | ||
| 362 | 378 | char *id; |
| 363 | 379 | int (*notify)(struct xfrm_state *x, struct km_event *c); |
| 364 | 380 | int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir); |
| 365 | − struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir); | |
| 381 | + struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir); | |
| 366 | 382 | int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); |
| 367 | 383 | int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); |
| 384 | + int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); | |
| 368 | 385 | }; |
| 369 | 386 | |
| 370 | 387 | extern int xfrm_register_km(struct xfrm_mgr *km); |
| 371 | 388 | extern int xfrm_unregister_km(struct xfrm_mgr *km); |
| 372 | 389 | |
| 373 | − | |
| 374 | −extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2]; | |
| 390 | +extern unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2]; | |
| 375 | 391 | |
| 376 | 392 | static inline void xfrm_pol_hold(struct xfrm_policy *policy) |
| 377 | 393 | { |
| @@ -387,67 +403,19 @@ static inline void xfrm_pol_put(struct xfrm_policy *policy) · 9 unmodified lines | ||
| 387 | 403 | __xfrm_policy_destroy(policy); |
| 388 | 404 | } |
| 389 | 405 | |
| 390 | −#define XFRM_DST_HSIZE 1024 | |
| 391 | − | |
| 392 | −static __inline__ | |
| 393 | −unsigned __xfrm4_dst_hash(xfrm_address_t *addr) | |
| 394 | −{ | |
| 395 | − unsigned h; | |
| 396 | − h = ntohl(addr->a4); | |
| 397 | − h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | |
| 398 | − return h; | |
| 399 | −} | |
| 400 | − | |
| 401 | −static __inline__ | |
| 402 | −unsigned __xfrm6_dst_hash(xfrm_address_t *addr) | |
| 403 | −{ | |
| 404 | − unsigned h; | |
| 405 | − h = ntohl(addr->a6[2]^addr->a6[3]); | |
| 406 | − h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | |
| 407 | − return h; | |
| 408 | −} | |
| 409 | − | |
| 410 | −static __inline__ | |
| 411 | −unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) | |
| 412 | −{ | |
| 413 | − switch (family) { | |
| 414 | − case AF_INET: | |
| 415 | − return __xfrm4_dst_hash(addr); | |
| 416 | − case AF_INET6: | |
| 417 | − return __xfrm6_dst_hash(addr); | |
| 418 | − } | |
| 419 | − return 0; | |
| 420 | −} | |
| 421 | − | |
| 422 | −static __inline__ | |
| 423 | −unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | |
| 406 | +#ifdef CONFIG_XFRM_SUB_POLICY | |
| 407 | +static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) | |
| 424 | 408 | { |
| 425 | − unsigned h; | |
| 426 | − h = ntohl(addr->a4^spi^proto); | |
| 427 | − h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | |
| 428 | − return h; | |
| 409 | + int i; | |
| 410 | + for (i = npols - 1; i >= 0; --i) | |
| 411 | + xfrm_pol_put(pols[i]); | |
| 429 | 412 | } |
| 430 | − | |
| 431 | −static __inline__ | |
| 432 | −unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | |
| 433 | −{ | |
| 434 | − unsigned h; | |
| 435 | − h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto); | |
| 436 | − h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | |
| 437 | − return h; | |
| 438 | −} | |
| 439 | − | |
| 440 | −static __inline__ | |
| 441 | −unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family) | |
| 413 | +#else | |
| 414 | +static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) | |
| 442 | 415 | { |
| 443 | − switch (family) { | |
| 444 | − case AF_INET: | |
| 445 | − return __xfrm4_spi_hash(addr, spi, proto); | |
| 446 | − case AF_INET6: | |
| 447 | − return __xfrm6_spi_hash(addr, spi, proto); | |
| 448 | − } | |
| 449 | − return 0; /*XXX*/ | |
| 416 | + xfrm_pol_put(pols[0]); | |
| 450 | 417 | } |
| 418 | +#endif | |
| 451 | 419 | |
| 452 | 420 | extern void __xfrm_state_destroy(struct xfrm_state *); |
| 453 | 421 | |
| @@ -507,6 +475,11 @@ u16 xfrm_flowi_sport(struct flowi *fl) · 53 unmodified lines | ||
| 507 | 475 | case IPPROTO_ICMPV6: |
| 508 | 476 | port = htons(fl->fl_icmp_type); |
| 509 | 477 | break; |
| 478 | +#ifdef CONFIG_IPV6_MIP6 | |
| 479 | + case IPPROTO_MH: | |
| 480 | + port = htons(fl->fl_mh_type); | |
| 481 | + break; | |
| 482 | +#endif | |
| 510 | 483 | default: |
| 511 | 484 | port = 0; /*XXX*/ |
| 512 | 485 | } |
| @@ -607,6 +580,7 @@ struct xfrm_dst · 94 unmodified lines | ||
| 607 | 580 | struct rt6_info rt6; |
| 608 | 581 | } u; |
| 609 | 582 | struct dst_entry *route; |
| 583 | + u32 genid; | |
| 610 | 584 | u32 route_mtu_cached; |
| 611 | 585 | u32 child_mtu_cached; |
| 612 | 586 | u32 route_cookie; |
| @@ -657,6 +631,18 @@ secpath_reset(struct sk_buff *skb) · 44 unmodified lines | ||
| 657 | 631 | #endif |
| 658 | 632 | } |
| 659 | 633 | |
| 634 | +static inline int | |
| 635 | +xfrm_addr_any(xfrm_address_t *addr, unsigned short family) | |
| 636 | +{ | |
| 637 | + switch (family) { | |
| 638 | + case AF_INET: | |
| 639 | + return addr->a4 == 0; | |
| 640 | + case AF_INET6: | |
| 641 | + return ipv6_addr_any((struct in6_addr *)&addr->a6); | |
| 642 | + } | |
| 643 | + return 0; | |
| 644 | +} | |
| 645 | + | |
| 660 | 646 | static inline int |
| 661 | 647 | __xfrm4_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x) |
| 662 | 648 | { |
| @@ -691,8 +677,8 @@ static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *sk · 28 unmodified lines | ||
| 691 | 677 | { |
| 692 | 678 | if (sk && sk->sk_policy[XFRM_POLICY_IN]) |
| 693 | 679 | return __xfrm_policy_check(sk, dir, skb, family); |
| 694 | − | |
| 695 | − return (!xfrm_policy_list[dir] && !skb->sp) || | |
| 680 | + | |
| 681 | + return (!xfrm_policy_count[dir] && !skb->sp) || | |
| 696 | 682 | (skb->dst->flags & DST_NOPOLICY) || |
| 697 | 683 | __xfrm_policy_check(sk, dir, skb, family); |
| 698 | 684 | } |
| @@ -712,7 +698,7 @@ extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family); · 13 unmodified lines | ||
| 712 | 698 | |
| 713 | 699 | static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family) |
| 714 | 700 | { |
| 715 | − return !xfrm_policy_list[XFRM_POLICY_OUT] || | |
| 701 | + return !xfrm_policy_count[XFRM_POLICY_OUT] || | |
| 716 | 702 | (skb->dst->flags & DST_NOXFRM) || |
| 717 | 703 | __xfrm_route_forward(skb, family); |
| 718 | 704 | } |
| @@ -830,11 +816,36 @@ xfrm_state_addr_check(struct xfrm_state *x, · 111 unmodified lines | ||
| 830 | 816 | return 0; |
| 831 | 817 | } |
| 832 | 818 | |
| 819 | +static __inline__ int | |
| 820 | +xfrm_state_addr_flow_check(struct xfrm_state *x, struct flowi *fl, | |
| 821 | + unsigned short family) | |
| 822 | +{ | |
| 823 | + switch (family) { | |
| 824 | + case AF_INET: | |
| 825 | + return __xfrm4_state_addr_check(x, | |
| 826 | + (xfrm_address_t *)&fl->fl4_dst, | |
| 827 | + (xfrm_address_t *)&fl->fl4_src); | |
| 828 | + case AF_INET6: | |
| 829 | + return __xfrm6_state_addr_check(x, | |
| 830 | + (xfrm_address_t *)&fl->fl6_dst, | |
| 831 | + (xfrm_address_t *)&fl->fl6_src); | |
| 832 | + } | |
| 833 | + return 0; | |
| 834 | +} | |
| 835 | + | |
| 833 | 836 | static inline int xfrm_state_kern(struct xfrm_state *x) |
| 834 | 837 | { |
| 835 | 838 | return atomic_read(&x->tunnel_users); |
| 836 | 839 | } |
| 837 | 840 | |
| 841 | +static inline int xfrm_id_proto_match(u8 proto, u8 userproto) | |
| 842 | +{ | |
| 843 | + return (!userproto || proto == userproto || | |
| 844 | + (userproto == IPSEC_PROTO_ANY && (proto == IPPROTO_AH || | |
| 845 | + proto == IPPROTO_ESP || | |
| 846 | + proto == IPPROTO_COMP))); | |
| 847 | +} | |
| 848 | + | |
| 838 | 849 | /* |
| 839 | 850 | * xfrm algorithm information |
| 840 | 851 | */ |
| @@ -902,6 +913,25 @@ extern void xfrm_state_insert(struct xfrm_state *x); · 61 unmodified lines | ||
| 902 | 913 | extern int xfrm_state_add(struct xfrm_state *x); |
| 903 | 914 | extern int xfrm_state_update(struct xfrm_state *x); |
| 904 | 915 | extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family); |
| 916 | +extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family); | |
| 917 | +#ifdef CONFIG_XFRM_SUB_POLICY | |
| 918 | +extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, | |
| 919 | + int n, unsigned short family); | |
| 920 | +extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, | |
| 921 | + int n, unsigned short family); | |
| 922 | +#else | |
| 923 | +static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, | |
| 924 | + int n, unsigned short family) | |
| 925 | +{ | |
| 926 | + return -ENOSYS; | |
| 927 | +} | |
| 928 | + | |
| 929 | +static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, | |
| 930 | + int n, unsigned short family) | |
| 931 | +{ | |
| 932 | + return -ENOSYS; | |
| 933 | +} | |
| 934 | +#endif | |
| 905 | 935 | extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); |
| 906 | 936 | extern int xfrm_state_delete(struct xfrm_state *x); |
| 907 | 937 | extern void xfrm_state_flush(u8 proto); |
| @@ -917,12 +947,16 @@ extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); · 9 unmodified lines | ||
| 917 | 947 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); |
| 918 | 948 | extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi); |
| 919 | 949 | extern int xfrm6_rcv(struct sk_buff **pskb); |
| 950 | +extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |
| 951 | + xfrm_address_t *saddr, u8 proto); | |
| 920 | 952 | extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler); |
| 921 | 953 | extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler); |
| 922 | 954 | extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); |
| 923 | 955 | extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); |
| 924 | 956 | extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); |
| 925 | 957 | extern int xfrm6_output(struct sk_buff *skb); |
| 958 | +extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, | |
| 959 | + u8 **prevhdr); | |
| 926 | 960 | |
| 927 | 961 | #ifdef CONFIG_XFRM |
| 928 | 962 | extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); |
| @@ -947,27 +981,27 @@ static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsig · 18 unmodified lines | ||
| 947 | 981 | #endif |
| 948 | 982 | |
| 949 | 983 | struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp); |
| 950 | −extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *); | |
| 984 | +extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), void *); | |
| 951 | 985 | int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); |
| 952 | −struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel, | |
| 986 | +struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | |
| 987 | + struct xfrm_selector *sel, | |
| 953 | 988 | struct xfrm_sec_ctx *ctx, int delete); |
| 954 | −struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete); | |
| 955 | −void xfrm_policy_flush(void); | |
| 989 | +struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete); | |
| 990 | +void xfrm_policy_flush(u8 type); | |
| 956 | 991 | u32 xfrm_get_acqseq(void); |
| 957 | 992 | void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); |
| 958 | 993 | struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, |
| 959 | 994 | xfrm_address_t *daddr, xfrm_address_t *saddr, |
| 960 | 995 | int create, unsigned short family); |
| 961 | −extern void xfrm_policy_flush(void); | |
| 996 | +extern void xfrm_policy_flush(u8 type); | |
| 962 | 997 | extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); |
| 963 | −extern int xfrm_flush_bundles(void); | |
| 964 | −extern void xfrm_flush_all_bundles(void); | |
| 965 | −extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family); | |
| 998 | +extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family, int strict); | |
| 966 | 999 | extern void xfrm_init_pmtu(struct dst_entry *dst); |
| 967 | 1000 | |
| 968 | 1001 | extern wait_queue_head_t km_waitq; |
| 969 | 1002 | extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); |
| 970 | 1003 | extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid); |
| 1004 | +extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); | |
| 971 | 1005 | |
| 972 | 1006 | extern void xfrm_input_init(void); |
| 973 | 1007 | extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq); |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #include <linux/bitops.h> |
| 29 | 29 | #include <linux/device.h> |
| 30 | +#include <linux/workqueue.h> | |
| 30 | 31 | #include "pcm.h" |
| 31 | 32 | #include "control.h" |
| 32 | 33 | #include "info.h" |
| @@ -140,6 +141,20 @@ · 107 unmodified lines | ||
| 140 | 141 | #define AC97_GP_DRSS_1011 0x0000 /* LR(C) 10+11(+12) */ |
| 141 | 142 | #define AC97_GP_DRSS_78 0x0400 /* LR 7+8 */ |
| 142 | 143 | |
| 144 | +/* powerdown bits */ | |
| 145 | +#define AC97_PD_ADC_STATUS 0x0001 /* ADC status (RO) */ | |
| 146 | +#define AC97_PD_DAC_STATUS 0x0002 /* DAC status (RO) */ | |
| 147 | +#define AC97_PD_MIXER_STATUS 0x0004 /* Analog mixer status (RO) */ | |
| 148 | +#define AC97_PD_VREF_STATUS 0x0008 /* Vref status (RO) */ | |
| 149 | +#define AC97_PD_PR0 0x0100 /* Power down PCM ADCs and input MUX */ | |
| 150 | +#define AC97_PD_PR1 0x0200 /* Power down PCM front DAC */ | |
| 151 | +#define AC97_PD_PR2 0x0400 /* Power down Mixer (Vref still on) */ | |
| 152 | +#define AC97_PD_PR3 0x0800 /* Power down Mixer (Vref off) */ | |
| 153 | +#define AC97_PD_PR4 0x1000 /* Power down AC-Link */ | |
| 154 | +#define AC97_PD_PR5 0x2000 /* Disable internal clock usage */ | |
| 155 | +#define AC97_PD_PR6 0x4000 /* Headphone amplifier */ | |
| 156 | +#define AC97_PD_EAPD 0x8000 /* External Amplifer Power Down (EAPD) */ | |
| 157 | + | |
| 143 | 158 | /* extended audio ID bit defines */ |
| 144 | 159 | #define AC97_EI_VRA 0x0001 /* Variable bit rate supported */ |
| 145 | 160 | #define AC97_EI_DRA 0x0002 /* Double rate supported */ |
| @@ -359,6 +374,7 @@ · 213 unmodified lines | ||
| 359 | 374 | #define AC97_SCAP_INV_EAPD (1<<7) /* inverted EAPD */ |
| 360 | 375 | #define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */ |
| 361 | 376 | #define AC97_SCAP_NO_SPDIF (1<<9) /* don't build SPDIF controls */ |
| 377 | +#define AC97_SCAP_EAPD_LED (1<<10) /* EAPD as mute LED */ | |
| 362 | 378 | |
| 363 | 379 | /* ac97->flags */ |
| 364 | 380 | #define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */ |
| @@ -491,6 +507,12 @@ struct snd_ac97 { · 126 unmodified lines | ||
| 491 | 507 | /* jack-sharing info */ |
| 492 | 508 | unsigned char indep_surround; |
| 493 | 509 | unsigned char channel_mode; |
| 510 | + | |
| 511 | +#ifdef CONFIG_SND_AC97_POWER_SAVE | |
| 512 | + unsigned int power_up; /* power states */ | |
| 513 | + struct workqueue_struct *power_workq; | |
| 514 | + struct work_struct power_work; | |
| 515 | +#endif | |
| 494 | 516 | struct device dev; |
| 495 | 517 | }; |
| 496 | 518 | |
| @@ -532,6 +554,15 @@ unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg); · 35 unmodified lines | ||
| 532 | 554 | void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned short value); |
| 533 | 555 | int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value); |
| 534 | 556 | int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value); |
| 557 | +#ifdef CONFIG_SND_AC97_POWER_SAVE | |
| 558 | +int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup); | |
| 559 | +#else | |
| 560 | +static inline int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, | |
| 561 | + int powerup) | |
| 562 | +{ | |
| 563 | + return 0; | |
| 564 | +} | |
| 565 | +#endif | |
| 535 | 566 | #ifdef CONFIG_PM |
| 536 | 567 | void snd_ac97_suspend(struct snd_ac97 *ac97); |
| 537 | 568 | void snd_ac97_resume(struct snd_ac97 *ac97); |
| @@ -583,6 +614,7 @@ struct ac97_pcm { · 45 unmodified lines | ||
| 583 | 614 | copy_flag: 1, /* lowlevel driver must fill all entries */ |
| 584 | 615 | spdif: 1; /* spdif pcm */ |
| 585 | 616 | unsigned short aslots; /* active slots */ |
| 617 | + unsigned short cur_dbl; /* current double-rate state */ | |
| 586 | 618 | unsigned int rates; /* available rates */ |
| 587 | 619 | struct { |
| 588 | 620 | unsigned short slots; /* driver input: requested AC97 slot numbers */ |
| @@ -179,14 +179,13 @@ enum { AD1848_MIX_SINGLE, AD1848_MIX_DOUBLE, AD1848_MIX_CAPTURE }; · 178 unmodified lines | ||
| 179 | 179 | #define AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) \ |
| 180 | 180 | ((left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22)) |
| 181 | 181 | |
| 182 | −int snd_ad1848_add_ctl(struct snd_ad1848 *chip, const char *name, int index, int type, unsigned long value); | |
| 183 | − | |
| 184 | 182 | /* for ease of use */ |
| 185 | 183 | struct ad1848_mix_elem { |
| 186 | 184 | const char *name; |
| 187 | 185 | int index; |
| 188 | 186 | int type; |
| 189 | 187 | unsigned long private_value; |
| 188 | + unsigned int *tlv; | |
| 190 | 189 | }; |
| 191 | 190 | |
| 192 | 191 | #define AD1848_SINGLE(xname, xindex, reg, shift, mask, invert) \ |
| @@ -195,15 +194,26 @@ struct ad1848_mix_elem { · 2 unmodified lines | ||
| 195 | 194 | .type = AD1848_MIX_SINGLE, \ |
| 196 | 195 | .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert) } |
| 197 | 196 | |
| 197 | +#define AD1848_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ | |
| 198 | +{ .name = xname, \ | |
| 199 | + .index = xindex, \ | |
| 200 | + .type = AD1848_MIX_SINGLE, \ | |
| 201 | + .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert), \ | |
| 202 | + .tlv = xtlv } | |
| 203 | + | |
| 198 | 204 | #define AD1848_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ |
| 199 | 205 | { .name = xname, \ |
| 200 | 206 | .index = xindex, \ |
| 201 | 207 | .type = AD1848_MIX_DOUBLE, \ |
| 202 | 208 | .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) } |
| 203 | 209 | |
| 204 | −static inline int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, const struct ad1848_mix_elem *c) | |
| 205 | −{ | |
| 206 | − return snd_ad1848_add_ctl(chip, c->name, c->index, c->type, c->private_value); | |
| 207 | −} | |
| 210 | +#define AD1848_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ | |
| 211 | +{ .name = xname, \ | |
| 212 | + .index = xindex, \ | |
| 213 | + .type = AD1848_MIX_DOUBLE, \ | |
| 214 | + .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert), \ | |
| 215 | + .tlv = xtlv } | |
| 216 | + | |
| 217 | +int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, const struct ad1848_mix_elem *c); | |
| 208 | 218 | |
| 209 | 219 | #endif /* __SOUND_AD1848_H */ |
| @@ -39,26 +39,39 @@ struct snd_ak4xxx_ops { · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | #define AK4XXX_IMAGE_SIZE (AK4XXX_MAX_CHIPS * 16) /* 64 bytes */ |
| 41 | 41 | |
| 42 | +/* DAC label and channels */ | |
| 43 | +struct snd_akm4xxx_dac_channel { | |
| 44 | + char *name; /* mixer volume name */ | |
| 45 | + unsigned int num_channels; | |
| 46 | +}; | |
| 47 | + | |
| 48 | +/* ADC labels and channels */ | |
| 49 | +struct snd_akm4xxx_adc_channel { | |
| 50 | + char *name; /* capture gain volume label */ | |
| 51 | + char *switch_name; /* capture switch */ | |
| 52 | + unsigned int num_channels; | |
| 53 | +}; | |
| 54 | + | |
| 42 | 55 | struct snd_akm4xxx { |
| 43 | 56 | struct snd_card *card; |
| 44 | 57 | unsigned int num_adcs; /* AK4524 or AK4528 ADCs */ |
| 45 | 58 | unsigned int num_dacs; /* AK4524 or AK4528 DACs */ |
| 46 | 59 | unsigned char images[AK4XXX_IMAGE_SIZE]; /* saved register image */ |
| 47 | − unsigned char ipga_gain[AK4XXX_MAX_CHIPS][2]; /* saved register image | |
| 48 | − * for IPGA (AK4528) | |
| 49 | − */ | |
| 60 | + unsigned char volumes[AK4XXX_IMAGE_SIZE]; /* saved volume values */ | |
| 50 | 61 | unsigned long private_value[AK4XXX_MAX_CHIPS]; /* helper for driver */ |
| 51 | 62 | void *private_data[AK4XXX_MAX_CHIPS]; /* helper for driver */ |
| 52 | 63 | /* template should fill the following fields */ |
| 53 | 64 | unsigned int idx_offset; /* control index offset */ |
| 54 | 65 | enum { |
| 55 | 66 | SND_AK4524, SND_AK4528, SND_AK4529, |
| 56 | − SND_AK4355, SND_AK4358, SND_AK4381 | |
| 67 | + SND_AK4355, SND_AK4358, SND_AK4381, | |
| 68 | + SND_AK5365 | |
| 57 | 69 | } type; |
| 58 | − unsigned int *num_stereo; /* array of combined counts | |
| 59 | − * for the mixer | |
| 60 | − */ | |
| 61 | − char **channel_names; /* array of mixer channel names */ | |
| 70 | + | |
| 71 | + /* (array) information of combined codecs */ | |
| 72 | + struct snd_akm4xxx_dac_channel *dac_info; | |
| 73 | + struct snd_akm4xxx_adc_channel *adc_info; | |
| 74 | + | |
| 62 | 75 | struct snd_ak4xxx_ops ops; |
| 63 | 76 | }; |
| 64 | 77 | |
| @@ -72,9 +85,9 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak); · 7 unmodified lines | ||
| 72 | 85 | (ak)->images[(chip) * 16 + (reg)] |
| 73 | 86 | #define snd_akm4xxx_set(ak,chip,reg,val) \ |
| 74 | 87 | ((ak)->images[(chip) * 16 + (reg)] = (val)) |
| 75 | −#define snd_akm4xxx_get_ipga(ak,chip,reg) \ | |
| 76 | − (ak)->ipga_gain[chip][(reg)-4] | |
| 77 | −#define snd_akm4xxx_set_ipga(ak,chip,reg,val) \ | |
| 78 | − ((ak)->ipga_gain[chip][(reg)-4] = (val)) | |
| 88 | +#define snd_akm4xxx_get_vol(ak,chip,reg) \ | |
| 89 | + (ak)->volumes[(chip) * 16 + (reg)] | |
| 90 | +#define snd_akm4xxx_set_vol(ak,chip,reg,val) \ | |
| 91 | + ((ak)->volumes[(chip) * 16 + (reg)] = (val)) | |
| 79 | 92 | |
| 80 | 93 | #endif /* __SOUND_AK4XXX_ADDA_H */ |
| @@ -688,7 +688,7 @@ struct snd_timer_tread { · 687 unmodified lines | ||
| 688 | 688 | * * |
| 689 | 689 | ****************************************************************************/ |
| 690 | 690 | |
| 691 | −#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 3) | |
| 691 | +#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 4) | |
| 692 | 692 | |
| 693 | 693 | struct snd_ctl_card_info { |
| 694 | 694 | int card; /* card number */ |
| @@ -727,10 +727,15 @@ typedef int __bitwise snd_ctl_elem_iface_t; · 32 unmodified lines | ||
| 727 | 727 | #define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1) |
| 728 | 728 | #define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE) |
| 729 | 729 | #define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */ |
| 730 | −#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<2) /* when was control changed */ | |
| 730 | +#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */ | |
| 731 | +#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */ | |
| 732 | +#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */ | |
| 733 | +#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) | |
| 734 | +#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */ | |
| 731 | 735 | #define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */ |
| 732 | 736 | #define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */ |
| 733 | 737 | #define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */ |
| 738 | +#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */ | |
| 734 | 739 | #define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */ |
| 735 | 740 | #define SNDRV_CTL_ELEM_ACCESS_DINDIRECT (1<<30) /* indirect access for matrix dimensions in the info structure */ |
| 736 | 741 | #define SNDRV_CTL_ELEM_ACCESS_INDIRECT (1<<31) /* indirect access for element value in the value structure */ |
| @@ -818,6 +823,12 @@ struct snd_ctl_elem_value { · 81 unmodified lines | ||
| 818 | 823 | unsigned char reserved[128-sizeof(struct timespec)]; |
| 819 | 824 | }; |
| 820 | 825 | |
| 826 | +struct snd_ctl_tlv { | |
| 827 | + unsigned int numid; /* control element numeric identification */ | |
| 828 | + unsigned int length; /* in bytes aligned to 4 */ | |
| 829 | + unsigned int tlv[0]; /* first TLV */ | |
| 830 | +}; | |
| 831 | + | |
| 821 | 832 | enum { |
| 822 | 833 | SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int), |
| 823 | 834 | SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info), |
| @@ -831,6 +842,9 @@ enum { · 7 unmodified lines | ||
| 831 | 842 | SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info), |
| 832 | 843 | SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info), |
| 833 | 844 | SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id), |
| 845 | + SNDRV_CTL_IOCTL_TLV_READ = _IOWR('U', 0x1a, struct snd_ctl_tlv), | |
| 846 | + SNDRV_CTL_IOCTL_TLV_WRITE = _IOWR('U', 0x1b, struct snd_ctl_tlv), | |
| 847 | + SNDRV_CTL_IOCTL_TLV_COMMAND = _IOWR('U', 0x1c, struct snd_ctl_tlv), | |
| 834 | 848 | SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int), |
| 835 | 849 | SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info), |
| 836 | 850 | SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int), |
| @@ -855,6 +869,7 @@ enum sndrv_ctl_event_type { · 18 unmodified lines | ||
| 855 | 869 | #define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */ |
| 856 | 870 | #define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */ |
| 857 | 871 | #define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */ |
| 872 | +#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */ | |
| 858 | 873 | #define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */ |
| 859 | 874 | |
| 860 | 875 | struct snd_ctl_event { |
| @@ -30,6 +30,11 @@ struct snd_kcontrol; · 29 unmodified lines | ||
| 30 | 30 | typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_info * uinfo); |
| 31 | 31 | typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); |
| 32 | 32 | typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); |
| 33 | +typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol, | |
| 34 | + int op_flag, /* 0=read,1=write,-1=command */ | |
| 35 | + unsigned int size, | |
| 36 | + unsigned int __user *tlv); | |
| 37 | + | |
| 33 | 38 | |
| 34 | 39 | struct snd_kcontrol_new { |
| 35 | 40 | snd_ctl_elem_iface_t iface; /* interface identifier */ |
| @@ -42,6 +47,10 @@ struct snd_kcontrol_new { · 6 unmodified lines | ||
| 42 | 47 | snd_kcontrol_info_t *info; |
| 43 | 48 | snd_kcontrol_get_t *get; |
| 44 | 49 | snd_kcontrol_put_t *put; |
| 50 | + union { | |
| 51 | + snd_kcontrol_tlv_rw_t *c; | |
| 52 | + unsigned int *p; | |
| 53 | + } tlv; | |
| 45 | 54 | unsigned long private_value; |
| 46 | 55 | }; |
| 47 | 56 | |
| @@ -58,6 +67,10 @@ struct snd_kcontrol { · 10 unmodified lines | ||
| 58 | 67 | snd_kcontrol_info_t *info; |
| 59 | 68 | snd_kcontrol_get_t *get; |
| 60 | 69 | snd_kcontrol_put_t *put; |
| 70 | + union { | |
| 71 | + snd_kcontrol_tlv_rw_t *c; | |
| 72 | + unsigned int *p; | |
| 73 | + } tlv; | |
| 61 | 74 | unsigned long private_value; |
| 62 | 75 | void *private_data; |
| 63 | 76 | void (*private_free)(struct snd_kcontrol *kcontrol); |
| @@ -25,8 +25,8 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/sched.h> /* wake_up() */ |
| 26 | 26 | #include <linux/mutex.h> /* struct mutex */ |
| 27 | 27 | #include <linux/rwsem.h> /* struct rw_semaphore */ |
| 28 | −#include <linux/workqueue.h> /* struct workqueue_struct */ | |
| 29 | 28 | #include <linux/pm.h> /* pm_message_t */ |
| 29 | +#include <linux/device.h> | |
| 30 | 30 | |
| 31 | 31 | /* forward declarations */ |
| 32 | 32 | #ifdef CONFIG_PCI |
| @@ -71,7 +71,6 @@ struct snd_device_ops { · 38 unmodified lines | ||
| 71 | 71 | int (*dev_free)(struct snd_device *dev); |
| 72 | 72 | int (*dev_register)(struct snd_device *dev); |
| 73 | 73 | int (*dev_disconnect)(struct snd_device *dev); |
| 74 | − int (*dev_unregister)(struct snd_device *dev); | |
| 75 | 74 | }; |
| 76 | 75 | |
| 77 | 76 | struct snd_device { |
| @@ -131,8 +130,8 @@ struct snd_card { · 53 unmodified lines | ||
| 131 | 130 | state */ |
| 132 | 131 | spinlock_t files_lock; /* lock the files for this card */ |
| 133 | 132 | int shutdown; /* this card is going down */ |
| 133 | + int free_on_last_close; /* free in context of file_release */ | |
| 134 | 134 | wait_queue_head_t shutdown_sleep; |
| 135 | − struct work_struct free_workq; /* for free in workqueue */ | |
| 136 | 135 | struct device *dev; |
| 137 | 136 | |
| 138 | 137 | #ifdef CONFIG_PM |
| @@ -188,6 +187,7 @@ struct snd_minor { · 49 unmodified lines | ||
| 188 | 187 | int device; /* device number */ |
| 189 | 188 | const struct file_operations *f_ops; /* file operations */ |
| 190 | 189 | void *private_data; /* private data for f_ops->open */ |
| 190 | + struct class_device *class_dev; /* class device for sysfs */ | |
| 191 | 191 | }; |
| 192 | 192 | |
| 193 | 193 | /* sound.c */ |
| @@ -202,6 +202,8 @@ int snd_register_device(int type, struct snd_card *card, int dev, · 8 unmodified lines | ||
| 202 | 202 | const char *name); |
| 203 | 203 | int snd_unregister_device(int type, struct snd_card *card, int dev); |
| 204 | 204 | void *snd_lookup_minor_data(unsigned int minor, int type); |
| 205 | +int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, | |
| 206 | + const struct class_device_attribute *attr); | |
| 205 | 207 | |
| 206 | 208 | #ifdef CONFIG_SND_OSSEMUL |
| 207 | 209 | int snd_register_oss_device(int type, struct snd_card *card, int dev, |
| @@ -244,7 +246,7 @@ struct snd_card *snd_card_new(int idx, const char *id, · 36 unmodified lines | ||
| 244 | 246 | struct module *module, int extra_size); |
| 245 | 247 | int snd_card_disconnect(struct snd_card *card); |
| 246 | 248 | int snd_card_free(struct snd_card *card); |
| 247 | −int snd_card_free_in_thread(struct snd_card *card); | |
| 249 | +int snd_card_free_when_closed(struct snd_card *card); | |
| 248 | 250 | int snd_card_register(struct snd_card *card); |
| 249 | 251 | int snd_card_info_init(void); |
| 250 | 252 | int snd_card_info_done(void); |
| @@ -1524,6 +1524,10 @@ struct snd_emu10k1_fx8010_control_gpr { · 1523 unmodified lines | ||
| 1524 | 1524 | unsigned int value[32]; /* initial values */ |
| 1525 | 1525 | unsigned int min; /* minimum range */ |
| 1526 | 1526 | unsigned int max; /* maximum range */ |
| 1527 | + union { | |
| 1528 | + snd_kcontrol_tlv_rw_t *c; | |
| 1529 | + unsigned int *p; | |
| 1530 | + } tlv; | |
| 1527 | 1531 | unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ |
| 1528 | 1532 | }; |
| 1529 | 1533 | |
| @@ -71,7 +71,6 @@ struct snd_info_entry { · 70 unmodified lines | ||
| 71 | 71 | mode_t mode; |
| 72 | 72 | long size; |
| 73 | 73 | unsigned short content; |
| 74 | − unsigned short disconnected: 1; | |
| 75 | 74 | union { |
| 76 | 75 | struct snd_info_entry_text text; |
| 77 | 76 | struct snd_info_entry_ops *ops; |
| @@ -83,6 +82,8 @@ struct snd_info_entry { · 5 unmodified lines | ||
| 83 | 82 | void (*private_free)(struct snd_info_entry *entry); |
| 84 | 83 | struct proc_dir_entry *p; |
| 85 | 84 | struct mutex access; |
| 85 | + struct list_head children; | |
| 86 | + struct list_head list; | |
| 86 | 87 | }; |
| 87 | 88 | |
| 88 | 89 | #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) |
| @@ -122,8 +123,8 @@ int snd_info_restore_text(struct snd_info_entry * entry); · 33 unmodified lines | ||
| 122 | 123 | int snd_info_card_create(struct snd_card * card); |
| 123 | 124 | int snd_info_card_register(struct snd_card * card); |
| 124 | 125 | int snd_info_card_free(struct snd_card * card); |
| 126 | +void snd_info_card_disconnect(struct snd_card * card); | |
| 125 | 127 | int snd_info_register(struct snd_info_entry * entry); |
| 126 | −int snd_info_unregister(struct snd_info_entry * entry); | |
| 127 | 128 | |
| 128 | 129 | /* for card drivers */ |
| 129 | 130 | int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_entry **entryp); |
| @@ -156,8 +157,8 @@ static inline void snd_info_free_entry(struct snd_info_entry * entry) { ; } · 26 unmodified lines | ||
| 156 | 157 | static inline int snd_info_card_create(struct snd_card * card) { return 0; } |
| 157 | 158 | static inline int snd_info_card_register(struct snd_card * card) { return 0; } |
| 158 | 159 | static inline int snd_info_card_free(struct snd_card * card) { return 0; } |
| 160 | +static inline void snd_info_card_disconnect(struct snd_card * card) { } | |
| 159 | 161 | static inline int snd_info_register(struct snd_info_entry * entry) { return 0; } |
| 160 | −static inline int snd_info_unregister(struct snd_info_entry * entry) { return 0; } | |
| 161 | 162 | |
| 162 | 163 | static inline int snd_card_proc_new(struct snd_card *card, const char *name, |
| 163 | 164 | struct snd_info_entry **entryp) { return -EINVAL; } |
| @@ -190,7 +190,7 @@ struct snd_pcm_ops { · 189 unmodified lines | ||
| 190 | 190 | |
| 191 | 191 | struct snd_pcm_file { |
| 192 | 192 | struct snd_pcm_substream *substream; |
| 193 | − struct snd_pcm_file *next; | |
| 193 | + int no_compat_mmap; | |
| 194 | 194 | }; |
| 195 | 195 | |
| 196 | 196 | struct snd_pcm_hw_rule; |
| @@ -384,7 +384,6 @@ struct snd_pcm_substream { · 187 unmodified lines | ||
| 384 | 384 | struct snd_info_entry *proc_prealloc_entry; |
| 385 | 385 | #endif |
| 386 | 386 | /* misc flags */ |
| 387 | − unsigned int no_mmap_ctrl: 1; | |
| 388 | 387 | unsigned int hw_opened: 1; |
| 389 | 388 | }; |
| 390 | 389 | |
| @@ -402,7 +401,6 @@ struct snd_pcm_str { · 11 unmodified lines | ||
| 402 | 401 | /* -- OSS things -- */ |
| 403 | 402 | struct snd_pcm_oss_stream oss; |
| 404 | 403 | #endif |
| 405 | − struct snd_pcm_file *files; | |
| 406 | 404 | #ifdef CONFIG_SND_VERBOSE_PROCFS |
| 407 | 405 | struct snd_info_entry *proc_root; |
| 408 | 406 | struct snd_info_entry *proc_info_entry; |
| @@ -129,7 +129,6 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam · 128 unmodified lines | ||
| 129 | 129 | int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer); |
| 130 | 130 | int snd_timer_global_free(struct snd_timer *timer); |
| 131 | 131 | int snd_timer_global_register(struct snd_timer *timer); |
| 132 | −int snd_timer_global_unregister(struct snd_timer *timer); | |
| 133 | 132 | |
| 134 | 133 | int snd_timer_open(struct snd_timer_instance **ti, char *owner, struct snd_timer_id *tid, unsigned int slave_id); |
| 135 | 134 | int snd_timer_close(struct snd_timer_instance *timeri); |
| @@ -0,0 +1,60 @@ | ||
| 1 | +#ifndef __SOUND_TLV_H | |
| 2 | +#define __SOUND_TLV_H | |
| 3 | + | |
| 4 | +/* | |
| 5 | + * Advanced Linux Sound Architecture - ALSA - Driver | |
| 6 | + * Copyright (c) 2006 by Jaroslav Kysela <perex@suse.cz> | |
| 7 | + * | |
| 8 | + * | |
| 9 | + * This program is free software; you can redistribute it and/or modify | |
| 10 | + * it under the terms of the GNU General Public License as published by | |
| 11 | + * the Free Software Foundation; either version 2 of the License, or | |
| 12 | + * (at your option) any later version. | |
| 13 | + * | |
| 14 | + * This program is distributed in the hope that it will be useful, | |
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + * GNU General Public License for more details. | |
| 18 | + * | |
| 19 | + * You should have received a copy of the GNU General Public License | |
| 20 | + * along with this program; if not, write to the Free Software | |
| 21 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 22 | + * | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * TLV structure is right behind the struct snd_ctl_tlv: | |
| 27 | + * unsigned int type - see SNDRV_CTL_TLVT_* | |
| 28 | + * unsigned int length | |
| 29 | + * .... data aligned to sizeof(unsigned int), use | |
| 30 | + * block_length = (length + (sizeof(unsigned int) - 1)) & | |
| 31 | + * ~(sizeof(unsigned int) - 1)) .... | |
| 32 | + */ | |
| 33 | + | |
| 34 | +#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */ | |
| 35 | +#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */ | |
| 36 | +#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */ | |
| 37 | +#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */ | |
| 38 | + | |
| 39 | +#define TLV_DB_SCALE_ITEM(min, step, mute) \ | |
| 40 | + SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \ | |
| 41 | + (min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0) | |
| 42 | +#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \ | |
| 43 | + unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) } | |
| 44 | + | |
| 45 | +/* linear volume between min_dB and max_dB (.01dB unit) */ | |
| 46 | +#define TLV_DB_LINEAR_ITEM(min_dB, max_dB) \ | |
| 47 | + SNDRV_CTL_TLVT_DB_LINEAR, 2 * sizeof(unsigned int), \ | |
| 48 | + (min_dB), (max_dB) | |
| 49 | +#define DECLARE_TLV_DB_LINEAR(name, min_dB, max_dB) \ | |
| 50 | + unsigned int name[] = { TLV_DB_LINEAR_ITEM(min_dB, max_dB) } | |
| 51 | + | |
| 52 | +/* dB range container */ | |
| 53 | +/* Each item is: <min> <max> <TLV> */ | |
| 54 | +/* The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR */ | |
| 55 | +#define TLV_DB_RANGE_HEAD(num) \ | |
| 56 | + SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int) | |
| 57 | + | |
| 58 | +#define TLV_DB_GAIN_MUTE -9999999 | |
| 59 | + | |
| 60 | +#endif /* __SOUND_TLV_H */ | |
| @@ -128,6 +128,7 @@ struct snd_vx_hardware { · 127 unmodified lines | ||
| 128 | 128 | unsigned int num_ins; |
| 129 | 129 | unsigned int num_outs; |
| 130 | 130 | unsigned int output_level_max; |
| 131 | + unsigned int *output_level_db_scale; | |
| 131 | 132 | }; |
| 132 | 133 | |
| 133 | 134 | /* hwdep id string */ |
| @@ -75,7 +75,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, · 74 unmodified lines | ||
| 75 | 75 | /* |
| 76 | 76 | * If new attributes are added, please revisit this allocation |
| 77 | 77 | */ |
| 78 | − skb = nlmsg_new(size); | |
| 78 | + skb = nlmsg_new(size, GFP_KERNEL); | |
| 79 | 79 | if (!skb) |
| 80 | 80 | return -ENOMEM; |
| 81 | 81 | |
| @@ -802,6 +802,15 @@ int test_set_page_writeback(struct page *page) · 801 unmodified lines | ||
| 802 | 802 | } |
| 803 | 803 | EXPORT_SYMBOL(test_set_page_writeback); |
| 804 | 804 | |
| 805 | +/* | |
| 806 | + * Wakes up tasks that are being throttled due to writeback congestion | |
| 807 | + */ | |
| 808 | +void writeback_congestion_end(void) | |
| 809 | +{ | |
| 810 | + blk_congestion_end(WRITE); | |
| 811 | +} | |
| 812 | +EXPORT_SYMBOL(writeback_congestion_end); | |
| 813 | + | |
| 805 | 814 | /* |
| 806 | 815 | * Return true if any of the pages in the mapping are marged with the |
| 807 | 816 | * passed tag. |
| @@ -2363,7 +2363,7 @@ int percpu_pagelist_fraction_sysctl_handler(ctl_table *table, int write, · 2362 unmodified lines | ||
| 2363 | 2363 | return 0; |
| 2364 | 2364 | } |
| 2365 | 2365 | |
| 2366 | −__initdata int hashdist = HASHDIST_DEFAULT; | |
| 2366 | +int hashdist = HASHDIST_DEFAULT; | |
| 2367 | 2367 | |
| 2368 | 2368 | #ifdef CONFIG_NUMA |
| 2369 | 2369 | static int __init set_hashdist(char *str) |
| @@ -249,6 +249,11 @@ source "net/ieee80211/Kconfig" · 248 unmodified lines | ||
| 249 | 249 | config WIRELESS_EXT |
| 250 | 250 | bool |
| 251 | 251 | |
| 252 | +source "net/netlabel/Kconfig" | |
| 253 | + | |
| 254 | +config FIB_RULES | |
| 255 | + bool | |
| 256 | + | |
| 252 | 257 | endif # if NET |
| 253 | 258 | endmenu # Networking |
| 254 | 259 | |
| @@ -46,6 +46,7 @@ obj-$(CONFIG_IP_DCCP) += dccp/ · 45 unmodified lines | ||
| 46 | 46 | obj-$(CONFIG_IP_SCTP) += sctp/ |
| 47 | 47 | obj-$(CONFIG_IEEE80211) += ieee80211/ |
| 48 | 48 | obj-$(CONFIG_TIPC) += tipc/ |
| 49 | +obj-$(CONFIG_NETLABEL) += netlabel/ | |
| 49 | 50 | |
| 50 | 51 | ifeq ($(CONFIG_NET),y) |
| 51 | 52 | obj-$(CONFIG_SYSCTL) += sysctl_net.o |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* ATM driver model support. */ |
| 2 | 2 | |
| 3 | −#include <linux/config.h> | |
| 4 | 3 | #include <linux/kernel.h> |
| 5 | 4 | #include <linux/init.h> |
| 6 | 5 | #include <linux/kobject.h> |
| @@ -98,11 +98,6 @@ static struct notifier_block mpoa_notifier = { · 97 unmodified lines | ||
| 98 | 98 | 0 |
| 99 | 99 | }; |
| 100 | 100 | |
| 101 | −#ifdef CONFIG_PROC_FS | |
| 102 | −extern int mpc_proc_init(void); | |
| 103 | −extern void mpc_proc_clean(void); | |
| 104 | −#endif | |
| 105 | − | |
| 106 | 101 | struct mpoa_client *mpcs = NULL; /* FIXME */ |
| 107 | 102 | static struct atm_mpoa_qos *qos_head = NULL; |
| 108 | 103 | static DEFINE_TIMER(mpc_timer, NULL, 0, 0); |
| @@ -1439,12 +1434,8 @@ static __init int atm_mpoa_init(void) · 1330 unmodified lines | ||
| 1439 | 1434 | { |
| 1440 | 1435 | register_atm_ioctl(&atm_ioctl_ops); |
| 1441 | 1436 | |
| 1442 | −#ifdef CONFIG_PROC_FS | |
| 1443 | 1437 | if (mpc_proc_init() != 0) |
| 1444 | 1438 | printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n"); |
| 1445 | − else | |
| 1446 | − printk(KERN_INFO "mpoa: /proc/mpoa initialized\n"); | |
| 1447 | −#endif | |
| 1448 | 1439 | |
| 1449 | 1440 | printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n"); |
| 1450 | 1441 | |
| @@ -1457,9 +1448,7 @@ static void __exit atm_mpoa_cleanup(void) · 6 unmodified lines | ||
| 1457 | 1448 | struct atm_mpoa_qos *qos, *nextqos; |
| 1458 | 1449 | struct lec_priv *priv; |
| 1459 | 1450 | |
| 1460 | −#ifdef CONFIG_PROC_FS | |
| 1461 | 1451 | mpc_proc_clean(); |
| 1462 | −#endif | |
| 1463 | 1452 | |
| 1464 | 1453 | del_timer(&mpc_timer); |
| 1465 | 1454 | unregister_netdevice_notifier(&mpoa_notifier); |
| @@ -50,4 +50,12 @@ int atm_mpoa_delete_qos(struct atm_mpoa_qos *qos); · 49 unmodified lines | ||
| 50 | 50 | struct seq_file; |
| 51 | 51 | void atm_mpoa_disp_qos(struct seq_file *m); |
| 52 | 52 | |
| 53 | +#ifdef CONFIG_PROC_FS | |
| 54 | +int mpc_proc_init(void); | |
| 55 | +void mpc_proc_clean(void); | |
| 56 | +#else | |
| 57 | +#define mpc_proc_init() (0) | |
| 58 | +#define mpc_proc_clean() do { } while(0) | |
| 59 | +#endif | |
| 60 | + | |
| 53 | 61 | #endif /* _MPC_H_ */ |
| @@ -38,13 +38,10 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) · 37 unmodified lines | ||
| 38 | 38 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) |
| 39 | 39 | kfree_skb(skb); |
| 40 | 40 | else { |
| 41 | −#ifdef CONFIG_BRIDGE_NETFILTER | |
| 42 | 41 | /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ |
| 43 | 42 | if (nf_bridge_maybe_copy_header(skb)) |
| 44 | 43 | kfree_skb(skb); |
| 45 | − else | |
| 46 | −#endif | |
| 47 | − { | |
| 44 | + else { | |
| 48 | 45 | skb_push(skb, ETH_HLEN); |
| 49 | 46 | |
| 50 | 47 | dev_queue_xmit(skb); |
| @@ -53,10 +53,10 @@ · 52 unmodified lines | ||
| 53 | 53 | |
| 54 | 54 | #ifdef CONFIG_SYSCTL |
| 55 | 55 | static struct ctl_table_header *brnf_sysctl_header; |
| 56 | −static int brnf_call_iptables = 1; | |
| 57 | −static int brnf_call_ip6tables = 1; | |
| 58 | −static int brnf_call_arptables = 1; | |
| 59 | −static int brnf_filter_vlan_tagged = 1; | |
| 56 | +static int brnf_call_iptables __read_mostly = 1; | |
| 57 | +static int brnf_call_ip6tables __read_mostly = 1; | |
| 58 | +static int brnf_call_arptables __read_mostly = 1; | |
| 59 | +static int brnf_filter_vlan_tagged __read_mostly = 1; | |
| 60 | 60 | #else |
| 61 | 61 | #define brnf_filter_vlan_tagged 1 |
| 62 | 62 | #endif |
| @@ -127,14 +127,37 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) · 64 unmodified lines | ||
| 127 | 127 | |
| 128 | 128 | static inline void nf_bridge_save_header(struct sk_buff *skb) |
| 129 | 129 | { |
| 130 | − int header_size = 16; | |
| 130 | + int header_size = ETH_HLEN; | |
| 131 | 131 | |
| 132 | 132 | if (skb->protocol == htons(ETH_P_8021Q)) |
| 133 | − header_size = 18; | |
| 133 | + header_size += VLAN_HLEN; | |
| 134 | 134 | |
| 135 | 135 | memcpy(skb->nf_bridge->data, skb->data - header_size, header_size); |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | +/* | |
| 139 | + * When forwarding bridge frames, we save a copy of the original | |
| 140 | + * header before processing. | |
| 141 | + */ | |
| 142 | +int nf_bridge_copy_header(struct sk_buff *skb) | |
| 143 | +{ | |
| 144 | + int err; | |
| 145 | + int header_size = ETH_HLEN; | |
| 146 | + | |
| 147 | + if (skb->protocol == htons(ETH_P_8021Q)) | |
| 148 | + header_size += VLAN_HLEN; | |
| 149 | + | |
| 150 | + err = skb_cow(skb, header_size); | |
| 151 | + if (err) | |
| 152 | + return err; | |
| 153 | + | |
| 154 | + memcpy(skb->data - header_size, skb->nf_bridge->data, header_size); | |
| 155 | + | |
| 156 | + if (skb->protocol == htons(ETH_P_8021Q)) | |
| 157 | + __skb_push(skb, VLAN_HLEN); | |
| 158 | + return 0; | |
| 159 | +} | |
| 160 | + | |
| 138 | 161 | /* PF_BRIDGE/PRE_ROUTING *********************************************/ |
| 139 | 162 | /* Undo the changes made for ip6tables PREROUTING and continue the |
| 140 | 163 | * bridge PRE_ROUTING hook. */ |
| @@ -695,16 +718,6 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, · 554 unmodified lines | ||
| 695 | 718 | else |
| 696 | 719 | pf = PF_INET6; |
| 697 | 720 | |
| 698 | −#ifdef CONFIG_NETFILTER_DEBUG | |
| 699 | − /* Sometimes we get packets with NULL ->dst here (for example, | |
| 700 | − * running a dhcp client daemon triggers this). This should now | |
| 701 | − * be fixed, but let's keep the check around. */ | |
| 702 | − if (skb->dst == NULL) { | |
| 703 | − printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); | |
| 704 | − return NF_ACCEPT; | |
| 705 | − } | |
| 706 | −#endif | |
| 707 | − | |
| 708 | 721 | nf_bridge = skb->nf_bridge; |
| 709 | 722 | nf_bridge->physoutdev = skb->dev; |
| 710 | 723 | realindev = nf_bridge->physindev; |
| @@ -786,7 +799,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, · 75 unmodified lines | ||
| 786 | 799 | * keep the check just to be sure... */ |
| 787 | 800 | if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) { |
| 788 | 801 | printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: " |
| 789 | − "bad mac.raw pointer."); | |
| 802 | + "bad mac.raw pointer.\n"); | |
| 790 | 803 | goto print_error; |
| 791 | 804 | } |
| 792 | 805 | #endif |
| @@ -804,7 +817,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, · 11 unmodified lines | ||
| 804 | 817 | |
| 805 | 818 | #ifdef CONFIG_NETFILTER_DEBUG |
| 806 | 819 | if (skb->dst == NULL) { |
| 807 | − printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); | |
| 820 | + printk(KERN_INFO "br_netfilter post_routing: skb->dst == NULL\n"); | |
| 808 | 821 | goto print_error; |
| 809 | 822 | } |
| 810 | 823 | #endif |
| @@ -841,6 +854,7 @@ print_error: · 30 unmodified lines | ||
| 841 | 854 | } |
| 842 | 855 | printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw, |
| 843 | 856 | skb->data); |
| 857 | + dump_stack(); | |
| 844 | 858 | return NF_ACCEPT; |
| 845 | 859 | #endif |
| 846 | 860 | } |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include <linux/kernel.h> |
| 14 | 14 | #include <linux/rtnetlink.h> |
| 15 | +#include <net/netlink.h> | |
| 15 | 16 | #include "br_private.h" |
| 16 | 17 | |
| 17 | 18 | /* |
| @@ -76,26 +77,24 @@ rtattr_failure: · 58 unmodified lines | ||
| 76 | 77 | void br_ifinfo_notify(int event, struct net_bridge_port *port) |
| 77 | 78 | { |
| 78 | 79 | struct sk_buff *skb; |
| 79 | − int err = -ENOMEM; | |
| 80 | + int payload = sizeof(struct ifinfomsg) + 128; | |
| 81 | + int err = -ENOBUFS; | |
| 80 | 82 | |
| 81 | 83 | pr_debug("bridge notify event=%d\n", event); |
| 82 | − skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128), | |
| 83 | − GFP_ATOMIC); | |
| 84 | − if (!skb) | |
| 85 | − goto err_out; | |
| 84 | + skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); | |
| 85 | + if (skb == NULL) | |
| 86 | + goto errout; | |
| 87 | + | |
| 88 | + err = br_fill_ifinfo(skb, port, 0, 0, event, 0); | |
| 89 | + if (err < 0) { | |
| 90 | + kfree_skb(skb); | |
| 91 | + goto errout; | |
| 92 | + } | |
| 86 | 93 | |
| 87 | − err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0); | |
| 94 | + err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); | |
| 95 | +errout: | |
| 88 | 96 | if (err < 0) |
| 89 | − goto err_kfree; | |
| 90 | − | |
| 91 | − NETLINK_CB(skb).dst_group = RTNLGRP_LINK; | |
| 92 | − netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); | |
| 93 | − return; | |
| 94 | − | |
| 95 | −err_kfree: | |
| 96 | − kfree_skb(skb); | |
| 97 | −err_out: | |
| 98 | − netlink_set_err(rtnl, 0, RTNLGRP_LINK, err); | |
| 97 | + rtnl_set_sk_err(RTNLGRP_LINK, err); | |
| 99 | 98 | } |
| 100 | 99 | |
| 101 | 100 | /* |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/vmalloc.h> |
| 25 | 25 | #include <linux/netfilter_bridge/ebtables.h> |
| 26 | 26 | #include <linux/spinlock.h> |
| 27 | +#include <linux/mutex.h> | |
| 27 | 28 | #include <asm/uaccess.h> |
| 28 | 29 | #include <linux/smp.h> |
| 29 | 30 | #include <linux/cpumask.h> |
| @@ -31,36 +32,9 @@ · 1 unmodified line | ||
| 31 | 32 | /* needed for logical [in,out]-dev filtering */ |
| 32 | 33 | #include "../br_private.h" |
| 33 | 34 | |
| 34 | −/* list_named_find */ | |
| 35 | −#define ASSERT_READ_LOCK(x) | |
| 36 | −#define ASSERT_WRITE_LOCK(x) | |
| 37 | −#include <linux/netfilter_ipv4/listhelp.h> | |
| 38 | −#include <linux/mutex.h> | |
| 39 | − | |
| 40 | −#if 0 | |
| 41 | −/* use this for remote debugging | |
| 42 | − * Copyright (C) 1998 by Ori Pomerantz | |
| 43 | − * Print the string to the appropriate tty, the one | |
| 44 | − * the current task uses | |
| 45 | − */ | |
| 46 | −static void print_string(char *str) | |
| 47 | −{ | |
| 48 | − struct tty_struct *my_tty; | |
| 49 | − | |
| 50 | − /* The tty for the current task */ | |
| 51 | − my_tty = current->signal->tty; | |
| 52 | − if (my_tty != NULL) { | |
| 53 | − my_tty->driver->write(my_tty, 0, str, strlen(str)); | |
| 54 | − my_tty->driver->write(my_tty, 0, "\015\012", 2); | |
| 55 | − } | |
| 56 | −} | |
| 57 | − | |
| 58 | −#define BUGPRINT(args) print_string(args); | |
| 59 | −#else | |
| 60 | 35 | #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ |
| 61 | 36 | "report to author: "format, ## args) |
| 62 | 37 | /* #define BUGPRINT(format, args...) */ |
| 63 | −#endif | |
| 64 | 38 | #define MEMPRINT(format, args...) printk("kernel msg: ebtables "\ |
| 65 | 39 | ": out of memory: "format, ## args) |
| 66 | 40 | /* #define MEMPRINT(format, args...) */ |
| @@ -299,18 +273,22 @@ static inline void * · 232 unmodified lines | ||
| 299 | 273 | find_inlist_lock_noload(struct list_head *head, const char *name, int *error, |
| 300 | 274 | struct mutex *mutex) |
| 301 | 275 | { |
| 302 | − void *ret; | |
| 276 | + struct { | |
| 277 | + struct list_head list; | |
| 278 | + char name[EBT_FUNCTION_MAXNAMELEN]; | |
| 279 | + } *e; | |
| 303 | 280 | |
| 304 | 281 | *error = mutex_lock_interruptible(mutex); |
| 305 | 282 | if (*error != 0) |
| 306 | 283 | return NULL; |
| 307 | 284 | |
| 308 | − ret = list_named_find(head, name); | |
| 309 | − if (!ret) { | |
| 310 | − *error = -ENOENT; | |
| 311 | − mutex_unlock(mutex); | |
| 285 | + list_for_each_entry(e, head, list) { | |
| 286 | + if (strcmp(e->name, name) == 0) | |
| 287 | + return e; | |
| 312 | 288 | } |
| 313 | − return ret; | |
| 289 | + *error = -ENOENT; | |
| 290 | + mutex_unlock(mutex); | |
| 291 | + return NULL; | |
| 314 | 292 | } |
| 315 | 293 | |
| 316 | 294 | #ifndef CONFIG_KMOD |
| @@ -1064,15 +1042,19 @@ free_newinfo: · 747 unmodified lines | ||
| 1064 | 1042 | |
| 1065 | 1043 | int ebt_register_target(struct ebt_target *target) |
| 1066 | 1044 | { |
| 1045 | + struct ebt_target *t; | |
| 1067 | 1046 | int ret; |
| 1068 | 1047 | |
| 1069 | 1048 | ret = mutex_lock_interruptible(&ebt_mutex); |
| 1070 | 1049 | if (ret != 0) |
| 1071 | 1050 | return ret; |
| 1072 | − if (!list_named_insert(&ebt_targets, target)) { | |
| 1073 | − mutex_unlock(&ebt_mutex); | |
| 1074 | − return -EEXIST; | |
| 1051 | + list_for_each_entry(t, &ebt_targets, list) { | |
| 1052 | + if (strcmp(t->name, target->name) == 0) { | |
| 1053 | + mutex_unlock(&ebt_mutex); | |
| 1054 | + return -EEXIST; | |
| 1055 | + } | |
| 1075 | 1056 | } |
| 1057 | + list_add(&target->list, &ebt_targets); | |
| 1076 | 1058 | mutex_unlock(&ebt_mutex); |
| 1077 | 1059 | |
| 1078 | 1060 | return 0; |
| @@ -1081,21 +1063,25 @@ int ebt_register_target(struct ebt_target *target) · 2 unmodified lines | ||
| 1081 | 1063 | void ebt_unregister_target(struct ebt_target *target) |
| 1082 | 1064 | { |
| 1083 | 1065 | mutex_lock(&ebt_mutex); |
| 1084 | − LIST_DELETE(&ebt_targets, target); | |
| 1066 | + list_del(&target->list); | |
| 1085 | 1067 | mutex_unlock(&ebt_mutex); |
| 1086 | 1068 | } |
| 1087 | 1069 | |
| 1088 | 1070 | int ebt_register_match(struct ebt_match *match) |
| 1089 | 1071 | { |
| 1072 | + struct ebt_match *m; | |
| 1090 | 1073 | int ret; |
| 1091 | 1074 | |
| 1092 | 1075 | ret = mutex_lock_interruptible(&ebt_mutex); |
| 1093 | 1076 | if (ret != 0) |
| 1094 | 1077 | return ret; |
| 1095 | − if (!list_named_insert(&ebt_matches, match)) { | |
| 1096 | − mutex_unlock(&ebt_mutex); | |
| 1097 | − return -EEXIST; | |
| 1078 | + list_for_each_entry(m, &ebt_matches, list) { | |
| 1079 | + if (strcmp(m->name, match->name) == 0) { | |
| 1080 | + mutex_unlock(&ebt_mutex); | |
| 1081 | + return -EEXIST; | |
| 1082 | + } | |
| 1098 | 1083 | } |
| 1084 | + list_add(&match->list, &ebt_matches); | |
| 1099 | 1085 | mutex_unlock(&ebt_mutex); |
| 1100 | 1086 | |
| 1101 | 1087 | return 0; |
| @@ -1104,21 +1090,25 @@ int ebt_register_match(struct ebt_match *match) · 2 unmodified lines | ||
| 1104 | 1090 | void ebt_unregister_match(struct ebt_match *match) |
| 1105 | 1091 | { |
| 1106 | 1092 | mutex_lock(&ebt_mutex); |
| 1107 | − LIST_DELETE(&ebt_matches, match); | |
| 1093 | + list_del(&match->list); | |
| 1108 | 1094 | mutex_unlock(&ebt_mutex); |
| 1109 | 1095 | } |
| 1110 | 1096 | |
| 1111 | 1097 | int ebt_register_watcher(struct ebt_watcher *watcher) |
| 1112 | 1098 | { |
| 1099 | + struct ebt_watcher *w; | |
| 1113 | 1100 | int ret; |
| 1114 | 1101 | |
| 1115 | 1102 | ret = mutex_lock_interruptible(&ebt_mutex); |
| 1116 | 1103 | if (ret != 0) |
| 1117 | 1104 | return ret; |
| 1118 | − if (!list_named_insert(&ebt_watchers, watcher)) { | |
| 1119 | − mutex_unlock(&ebt_mutex); | |
| 1120 | − return -EEXIST; | |
| 1105 | + list_for_each_entry(w, &ebt_watchers, list) { | |
| 1106 | + if (strcmp(w->name, watcher->name) == 0) { | |
| 1107 | + mutex_unlock(&ebt_mutex); | |
| 1108 | + return -EEXIST; | |
| 1109 | + } | |
| 1121 | 1110 | } |
| 1111 | + list_add(&watcher->list, &ebt_watchers); | |
| 1122 | 1112 | mutex_unlock(&ebt_mutex); |
| 1123 | 1113 | |
| 1124 | 1114 | return 0; |
| @@ -1127,13 +1117,14 @@ int ebt_register_watcher(struct ebt_watcher *watcher) · 2 unmodified lines | ||
| 1127 | 1117 | void ebt_unregister_watcher(struct ebt_watcher *watcher) |
| 1128 | 1118 | { |
| 1129 | 1119 | mutex_lock(&ebt_mutex); |
| 1130 | − LIST_DELETE(&ebt_watchers, watcher); | |
| 1120 | + list_del(&watcher->list); | |
| 1131 | 1121 | mutex_unlock(&ebt_mutex); |
| 1132 | 1122 | } |
| 1133 | 1123 | |
| 1134 | 1124 | int ebt_register_table(struct ebt_table *table) |
| 1135 | 1125 | { |
| 1136 | 1126 | struct ebt_table_info *newinfo; |
| 1127 | + struct ebt_table *t; | |
| 1137 | 1128 | int ret, i, countersize; |
| 1138 | 1129 | |
| 1139 | 1130 | if (!table || !table->table ||!table->table->entries || |
| @@ -1179,10 +1170,12 @@ int ebt_register_table(struct ebt_table *table) · 39 unmodified lines | ||
| 1179 | 1170 | if (ret != 0) |
| 1180 | 1171 | goto free_chainstack; |
| 1181 | 1172 | |
| 1182 | − if (list_named_find(&ebt_tables, table->name)) { | |
| 1183 | − ret = -EEXIST; | |
| 1184 | − BUGPRINT("Table name already exists\n"); | |
| 1185 | − goto free_unlock; | |
| 1173 | + list_for_each_entry(t, &ebt_tables, list) { | |
| 1174 | + if (strcmp(t->name, table->name) == 0) { | |
| 1175 | + ret = -EEXIST; | |
| 1176 | + BUGPRINT("Table name already exists\n"); | |
| 1177 | + goto free_unlock; | |
| 1178 | + } | |
| 1186 | 1179 | } |
| 1187 | 1180 | |
| 1188 | 1181 | /* Hold a reference count if the chains aren't empty */ |
| @@ -1190,7 +1183,7 @@ int ebt_register_table(struct ebt_table *table) · 1 unmodified line | ||
| 1190 | 1183 | ret = -ENOENT; |
| 1191 | 1184 | goto free_unlock; |
| 1192 | 1185 | } |
| 1193 | − list_prepend(&ebt_tables, table); | |
| 1186 | + list_add(&table->list, &ebt_tables); | |
| 1194 | 1187 | mutex_unlock(&ebt_mutex); |
| 1195 | 1188 | return 0; |
| 1196 | 1189 | free_unlock: |
| @@ -1216,7 +1209,7 @@ void ebt_unregister_table(struct ebt_table *table) · 19 unmodified lines | ||
| 1216 | 1209 | return; |
| 1217 | 1210 | } |
| 1218 | 1211 | mutex_lock(&ebt_mutex); |
| 1219 | − LIST_DELETE(&ebt_tables, table); | |
| 1212 | + list_del(&table->list); | |
| 1220 | 1213 | mutex_unlock(&ebt_mutex); |
| 1221 | 1214 | vfree(table->private->entries); |
| 1222 | 1215 | if (table->private->chainstack) { |
| @@ -1486,7 +1479,7 @@ static int __init ebtables_init(void) · 263 unmodified lines | ||
| 1486 | 1479 | int ret; |
| 1487 | 1480 | |
| 1488 | 1481 | mutex_lock(&ebt_mutex); |
| 1489 | − list_named_insert(&ebt_targets, &ebt_standard_target); | |
| 1482 | + list_add(&ebt_standard_target.list, &ebt_targets); | |
| 1490 | 1483 | mutex_unlock(&ebt_mutex); |
| 1491 | 1484 | if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) |
| 1492 | 1485 | return ret; |
| @@ -17,3 +17,4 @@ obj-$(CONFIG_NET_PKTGEN) += pktgen.o · 16 unmodified lines | ||
| 17 | 17 | obj-$(CONFIG_WIRELESS_EXT) += wireless.o |
| 18 | 18 | obj-$(CONFIG_NETPOLL) += netpoll.o |
| 19 | 19 | obj-$(CONFIG_NET_DMA) += user_dma.o |
| 20 | +obj-$(CONFIG_FIB_RULES) += fib_rules.o | |
| @@ -417,7 +417,7 @@ unsigned int __skb_checksum_complete(struct sk_buff *skb) · 416 unmodified lines | ||
| 417 | 417 | |
| 418 | 418 | sum = (u16)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); |
| 419 | 419 | if (likely(!sum)) { |
| 420 | − if (unlikely(skb->ip_summed == CHECKSUM_HW)) | |
| 420 | + if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) | |
| 421 | 421 | netdev_rx_csum_fault(skb->dev); |
| 422 | 422 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 423 | 423 | } |
| @@ -462,7 +462,7 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, · 38 unmodified lines | ||
| 462 | 462 | goto fault; |
| 463 | 463 | if ((unsigned short)csum_fold(csum)) |
| 464 | 464 | goto csum_error; |
| 465 | − if (unlikely(skb->ip_summed == CHECKSUM_HW)) | |
| 465 | + if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) | |
| 466 | 466 | netdev_rx_csum_fault(skb->dev); |
| 467 | 467 | iov->iov_len -= chunk; |
| 468 | 468 | iov->iov_base += chunk; |
| @@ -640,6 +640,8 @@ int dev_valid_name(const char *name) · 639 unmodified lines | ||
| 640 | 640 | { |
| 641 | 641 | if (*name == '\0') |
| 642 | 642 | return 0; |
| 643 | + if (strlen(name) >= IFNAMSIZ) | |
| 644 | + return 0; | |
| 643 | 645 | if (!strcmp(name, ".") || !strcmp(name, "..")) |
| 644 | 646 | return 0; |
| 645 | 647 | |
| @@ -1166,12 +1168,12 @@ EXPORT_SYMBOL(netif_device_attach); · 520 unmodified lines | ||
| 1166 | 1168 | * Invalidate hardware checksum when packet is to be mangled, and |
| 1167 | 1169 | * complete checksum manually on outgoing path. |
| 1168 | 1170 | */ |
| 1169 | −int skb_checksum_help(struct sk_buff *skb, int inward) | |
| 1171 | +int skb_checksum_help(struct sk_buff *skb) | |
| 1170 | 1172 | { |
| 1171 | 1173 | unsigned int csum; |
| 1172 | 1174 | int ret = 0, offset = skb->h.raw - skb->data; |
| 1173 | 1175 | |
| 1174 | − if (inward) | |
| 1176 | + if (skb->ip_summed == CHECKSUM_COMPLETE) | |
| 1175 | 1177 | goto out_set_summed; |
| 1176 | 1178 | |
| 1177 | 1179 | if (unlikely(skb_shinfo(skb)->gso_size)) { |
| @@ -1223,7 +1225,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) · 45 unmodified lines | ||
| 1223 | 1225 | skb->mac_len = skb->nh.raw - skb->data; |
| 1224 | 1226 | __skb_pull(skb, skb->mac_len); |
| 1225 | 1227 | |
| 1226 | − if (unlikely(skb->ip_summed != CHECKSUM_HW)) { | |
| 1228 | + if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) { | |
| 1227 | 1229 | if (skb_header_cloned(skb) && |
| 1228 | 1230 | (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) |
| 1229 | 1231 | return ERR_PTR(err); |
| @@ -1232,7 +1234,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) · 2 unmodified lines | ||
| 1232 | 1234 | rcu_read_lock(); |
| 1233 | 1235 | list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { |
| 1234 | 1236 | if (ptype->type == type && !ptype->dev && ptype->gso_segment) { |
| 1235 | − if (unlikely(skb->ip_summed != CHECKSUM_HW)) { | |
| 1237 | + if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) { | |
| 1236 | 1238 | err = ptype->gso_send_check(skb); |
| 1237 | 1239 | segs = ERR_PTR(err); |
| 1238 | 1240 | if (err || skb_gso_ok(skb, features)) |
| @@ -1444,11 +1446,11 @@ int dev_queue_xmit(struct sk_buff *skb) · 205 unmodified lines | ||
| 1444 | 1446 | /* If packet is not checksummed and device does not support |
| 1445 | 1447 | * checksumming for this protocol, complete checksumming here. |
| 1446 | 1448 | */ |
| 1447 | − if (skb->ip_summed == CHECKSUM_HW && | |
| 1449 | + if (skb->ip_summed == CHECKSUM_PARTIAL && | |
| 1448 | 1450 | (!(dev->features & NETIF_F_GEN_CSUM) && |
| 1449 | 1451 | (!(dev->features & NETIF_F_IP_CSUM) || |
| 1450 | 1452 | skb->protocol != htons(ETH_P_IP)))) |
| 1451 | − if (skb_checksum_help(skb, 0)) | |
| 1453 | + if (skb_checksum_help(skb)) | |
| 1452 | 1454 | goto out_kfree_skb; |
| 1453 | 1455 | |
| 1454 | 1456 | gso: |
| @@ -3191,13 +3193,15 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, · 1736 unmodified lines | ||
| 3191 | 3193 | struct net_device *dev; |
| 3192 | 3194 | int alloc_size; |
| 3193 | 3195 | |
| 3196 | + BUG_ON(strlen(name) >= sizeof(dev->name)); | |
| 3197 | + | |
| 3194 | 3198 | /* ensure 32-byte alignment of both the device and private area */ |
| 3195 | 3199 | alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; |
| 3196 | 3200 | alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; |
| 3197 | 3201 | |
| 3198 | 3202 | p = kzalloc(alloc_size, GFP_KERNEL); |
| 3199 | 3203 | if (!p) { |
| 3200 | − printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); | |
| 3204 | + printk(KERN_ERR "alloc_netdev: Unable to allocate device.\n"); | |
| 3201 | 3205 | return NULL; |
| 3202 | 3206 | } |
| 3203 | 3207 | |
| @@ -21,8 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | * 2 of the License, or (at your option) any later version. |
| 22 | 22 | */ |
| 23 | 23 | |
| 24 | −#include <linux/config.h> | |
| 25 | −#include <linux/module.h> | |
| 24 | +#include <linux/module.h> | |
| 26 | 25 | #include <asm/uaccess.h> |
| 27 | 26 | #include <asm/system.h> |
| 28 | 27 | #include <linux/bitops.h> |
| @@ -0,0 +1,421 @@ | ||
| 1 | +/* | |
| 2 | + * net/core/fib_rules.c Generic Routing Rules | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or | |
| 5 | + * modify it under the terms of the GNU General Public License as | |
| 6 | + * published by the Free Software Foundation, version 2. | |
| 7 | + * | |
| 8 | + * Authors: Thomas Graf <tgraf@suug.ch> | |
| 9 | + */ | |
| 10 | + | |
| 11 | +#include <linux/config.h> | |
| 12 | +#include <linux/types.h> | |
| 13 | +#include <linux/kernel.h> | |
| 14 | +#include <linux/list.h> | |
| 15 | +#include <net/fib_rules.h> | |
| 16 | + | |
| 17 | +static LIST_HEAD(rules_ops); | |
| 18 | +static DEFINE_SPINLOCK(rules_mod_lock); | |
| 19 | + | |
| 20 | +static void notify_rule_change(int event, struct fib_rule *rule, | |
| 21 | + struct fib_rules_ops *ops, struct nlmsghdr *nlh, | |
| 22 | + u32 pid); | |
| 23 | + | |
| 24 | +static struct fib_rules_ops *lookup_rules_ops(int family) | |
| 25 | +{ | |
| 26 | + struct fib_rules_ops *ops; | |
| 27 | + | |
| 28 | + rcu_read_lock(); | |
| 29 | + list_for_each_entry_rcu(ops, &rules_ops, list) { | |
| 30 | + if (ops->family == family) { | |
| 31 | + if (!try_module_get(ops->owner)) | |
| 32 | + ops = NULL; | |
| 33 | + rcu_read_unlock(); | |
| 34 | + return ops; | |
| 35 | + } | |
| 36 | + } | |
| 37 | + rcu_read_unlock(); | |
| 38 | + | |
| 39 | + return NULL; | |
| 40 | +} | |
| 41 | + | |
| 42 | +static void rules_ops_put(struct fib_rules_ops *ops) | |
| 43 | +{ | |
| 44 | + if (ops) | |
| 45 | + module_put(ops->owner); | |
| 46 | +} | |
| 47 | + | |
| 48 | +int fib_rules_register(struct fib_rules_ops *ops) | |
| 49 | +{ | |
| 50 | + int err = -EEXIST; | |
| 51 | + struct fib_rules_ops *o; | |
| 52 | + | |
| 53 | + if (ops->rule_size < sizeof(struct fib_rule)) | |
| 54 | + return -EINVAL; | |
| 55 | + | |
| 56 | + if (ops->match == NULL || ops->configure == NULL || | |
| 57 | + ops->compare == NULL || ops->fill == NULL || | |
| 58 | + ops->action == NULL) | |
| 59 | + return -EINVAL; | |
| 60 | + | |
| 61 | + spin_lock(&rules_mod_lock); | |
| 62 | + list_for_each_entry(o, &rules_ops, list) | |
| 63 | + if (ops->family == o->family) | |
| 64 | + goto errout; | |
| 65 | + | |
| 66 | + list_add_tail_rcu(&ops->list, &rules_ops); | |
| 67 | + err = 0; | |
| 68 | +errout: | |
| 69 | + spin_unlock(&rules_mod_lock); | |
| 70 | + | |
| 71 | + return err; | |
| 72 | +} | |
| 73 | + | |
| 74 | +EXPORT_SYMBOL_GPL(fib_rules_register); | |
| 75 | + | |
| 76 | +static void cleanup_ops(struct fib_rules_ops *ops) | |
| 77 | +{ | |
| 78 | + struct fib_rule *rule, *tmp; | |
| 79 | + | |
| 80 | + list_for_each_entry_safe(rule, tmp, ops->rules_list, list) { | |
| 81 | + list_del_rcu(&rule->list); | |
| 82 | + fib_rule_put(rule); | |
| 83 | + } | |
| 84 | +} | |
| 85 | + | |
| 86 | +int fib_rules_unregister(struct fib_rules_ops *ops) | |
| 87 | +{ | |
| 88 | + int err = 0; | |
| 89 | + struct fib_rules_ops *o; | |
| 90 | + | |
| 91 | + spin_lock(&rules_mod_lock); | |
| 92 | + list_for_each_entry(o, &rules_ops, list) { | |
| 93 | + if (o == ops) { | |
| 94 | + list_del_rcu(&o->list); | |
| 95 | + cleanup_ops(ops); | |
| 96 | + goto out; | |
| 97 | + } | |
| 98 | + } | |
| 99 | + | |
| 100 | + err = -ENOENT; | |
| 101 | +out: | |
| 102 | + spin_unlock(&rules_mod_lock); | |
| 103 | + | |
| 104 | + synchronize_rcu(); | |
| 105 | + | |
| 106 | + return err; | |
| 107 | +} | |
| 108 | + | |
| 109 | +EXPORT_SYMBOL_GPL(fib_rules_unregister); | |
| 110 | + | |
| 111 | +int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl, | |
| 112 | + int flags, struct fib_lookup_arg *arg) | |
| 113 | +{ | |
| 114 | + struct fib_rule *rule; | |
| 115 | + int err; | |
| 116 | + | |
| 117 | + rcu_read_lock(); | |
| 118 | + | |
| 119 | + list_for_each_entry_rcu(rule, ops->rules_list, list) { | |
| 120 | + if (rule->ifindex && (rule->ifindex != fl->iif)) | |
| 121 | + continue; | |
| 122 | + | |
| 123 | + if (!ops->match(rule, fl, flags)) | |
| 124 | + continue; | |
| 125 | + | |
| 126 | + err = ops->action(rule, fl, flags, arg); | |
| 127 | + if (err != -EAGAIN) { | |
| 128 | + fib_rule_get(rule); | |
| 129 | + arg->rule = rule; | |
| 130 | + goto out; | |
| 131 | + } | |
| 132 | + } | |
| 133 | + | |
| 134 | + err = -ENETUNREACH; | |
| 135 | +out: | |
| 136 | + rcu_read_unlock(); | |
| 137 | + | |
| 138 | + return err; | |
| 139 | +} | |
| 140 | + | |
| 141 | +EXPORT_SYMBOL_GPL(fib_rules_lookup); | |
| 142 | + | |
| 143 | +int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |
| 144 | +{ | |
| 145 | + struct fib_rule_hdr *frh = nlmsg_data(nlh); | |
| 146 | + struct fib_rules_ops *ops = NULL; | |
| 147 | + struct fib_rule *rule, *r, *last = NULL; | |
| 148 | + struct nlattr *tb[FRA_MAX+1]; | |
| 149 | + int err = -EINVAL; | |
| 150 | + | |
| 151 | + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) | |
| 152 | + goto errout; | |
| 153 | + | |
| 154 | + ops = lookup_rules_ops(frh->family); | |
| 155 | + if (ops == NULL) { | |
| 156 | + err = EAFNOSUPPORT; | |
| 157 | + goto errout; | |
| 158 | + } | |
| 159 | + | |
| 160 | + err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy); | |
| 161 | + if (err < 0) | |
| 162 | + goto errout; | |
| 163 | + | |
| 164 | + rule = kzalloc(ops->rule_size, GFP_KERNEL); | |
| 165 | + if (rule == NULL) { | |
| 166 | + err = -ENOMEM; | |
| 167 | + goto errout; | |
| 168 | + } | |
| 169 | + | |
| 170 | + if (tb[FRA_PRIORITY]) | |
| 171 | + rule->pref = nla_get_u32(tb[FRA_PRIORITY]); | |
| 172 | + | |
| 173 | + if (tb[FRA_IFNAME]) { | |
| 174 | + struct net_device *dev; | |
| 175 | + | |
| 176 | + rule->ifindex = -1; | |
| 177 | + nla_strlcpy(rule->ifname, tb[FRA_IFNAME], IFNAMSIZ); | |
| 178 | + dev = __dev_get_by_name(rule->ifname); | |
| 179 | + if (dev) | |
| 180 | + rule->ifindex = dev->ifindex; | |
| 181 | + } | |
| 182 | + | |
| 183 | + rule->action = frh->action; | |
| 184 | + rule->flags = frh->flags; | |
| 185 | + rule->table = frh_get_table(frh, tb); | |
| 186 | + | |
| 187 | + if (!rule->pref && ops->default_pref) | |
| 188 | + rule->pref = ops->default_pref(); | |
| 189 | + | |
| 190 | + err = ops->configure(rule, skb, nlh, frh, tb); | |
| 191 | + if (err < 0) | |
| 192 | + goto errout_free; | |
| 193 | + | |
| 194 | + list_for_each_entry(r, ops->rules_list, list) { | |
| 195 | + if (r->pref > rule->pref) | |
| 196 | + break; | |
| 197 | + last = r; | |
| 198 | + } | |
| 199 | + | |
| 200 | + fib_rule_get(rule); | |
| 201 | + | |
| 202 | + if (last) | |
| 203 | + list_add_rcu(&rule->list, &last->list); | |
| 204 | + else | |
| 205 | + list_add_rcu(&rule->list, ops->rules_list); | |
| 206 | + | |
| 207 | + notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid); | |
| 208 | + rules_ops_put(ops); | |
| 209 | + return 0; | |
| 210 | + | |
| 211 | +errout_free: | |
| 212 | + kfree(rule); | |
| 213 | +errout: | |
| 214 | + rules_ops_put(ops); | |
| 215 | + return err; | |
| 216 | +} | |
| 217 | + | |
| 218 | +int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |
| 219 | +{ | |
| 220 | + struct fib_rule_hdr *frh = nlmsg_data(nlh); | |
| 221 | + struct fib_rules_ops *ops = NULL; | |
| 222 | + struct fib_rule *rule; | |
| 223 | + struct nlattr *tb[FRA_MAX+1]; | |
| 224 | + int err = -EINVAL; | |
| 225 | + | |
| 226 | + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) | |
| 227 | + goto errout; | |
| 228 | + | |
| 229 | + ops = lookup_rules_ops(frh->family); | |
| 230 | + if (ops == NULL) { | |
| 231 | + err = EAFNOSUPPORT; | |
| 232 | + goto errout; | |
| 233 | + } | |
| 234 | + | |
| 235 | + err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy); | |
| 236 | + if (err < 0) | |
| 237 | + goto errout; | |
| 238 | + | |
| 239 | + list_for_each_entry(rule, ops->rules_list, list) { | |
| 240 | + if (frh->action && (frh->action != rule->action)) | |
| 241 | + continue; | |
| 242 | + | |
| 243 | + if (frh->table && (frh_get_table(frh, tb) != rule->table)) | |
| 244 | + continue; | |
| 245 | + | |
| 246 | + if (tb[FRA_PRIORITY] && | |
| 247 | + (rule->pref != nla_get_u32(tb[FRA_PRIORITY]))) | |
| 248 | + continue; | |
| 249 | + | |
| 250 | + if (tb[FRA_IFNAME] && | |
| 251 | + nla_strcmp(tb[FRA_IFNAME], rule->ifname)) | |
| 252 | + continue; | |
| 253 | + | |
| 254 | + if (!ops->compare(rule, frh, tb)) | |
| 255 | + continue; | |
| 256 | + | |
| 257 | + if (rule->flags & FIB_RULE_PERMANENT) { | |
| 258 | + err = -EPERM; | |
| 259 | + goto errout; | |
| 260 | + } | |
| 261 | + | |
| 262 | + list_del_rcu(&rule->list); | |
| 263 | + synchronize_rcu(); | |
| 264 | + notify_rule_change(RTM_DELRULE, rule, ops, nlh, | |
| 265 | + NETLINK_CB(skb).pid); | |
| 266 | + fib_rule_put(rule); | |
| 267 | + rules_ops_put(ops); | |
| 268 | + return 0; | |
| 269 | + } | |
| 270 | + | |
| 271 | + err = -ENOENT; | |
| 272 | +errout: | |
| 273 | + rules_ops_put(ops); | |
| 274 | + return err; | |
| 275 | +} | |
| 276 | + | |
| 277 | +static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, | |
| 278 | + u32 pid, u32 seq, int type, int flags, | |
| 279 | + struct fib_rules_ops *ops) | |
| 280 | +{ | |
| 281 | + struct nlmsghdr *nlh; | |
| 282 | + struct fib_rule_hdr *frh; | |
| 283 | + | |
| 284 | + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags); | |
| 285 | + if (nlh == NULL) | |
| 286 | + return -1; | |
| 287 | + | |
| 288 | + frh = nlmsg_data(nlh); | |
| 289 | + frh->table = rule->table; | |
| 290 | + NLA_PUT_U32(skb, FRA_TABLE, rule->table); | |
| 291 | + frh->res1 = 0; | |
| 292 | + frh->res2 = 0; | |
| 293 | + frh->action = rule->action; | |
| 294 | + frh->flags = rule->flags; | |
| 295 | + | |
| 296 | + if (rule->ifname[0]) | |
| 297 | + NLA_PUT_STRING(skb, FRA_IFNAME, rule->ifname); | |
| 298 | + | |
| 299 | + if (rule->pref) | |
| 300 | + NLA_PUT_U32(skb, FRA_PRIORITY, rule->pref); | |
| 301 | + | |
| 302 | + if (ops->fill(rule, skb, nlh, frh) < 0) | |
| 303 | + goto nla_put_failure; | |
| 304 | + | |
| 305 | + return nlmsg_end(skb, nlh); | |
| 306 | + | |
| 307 | +nla_put_failure: | |
| 308 | + return nlmsg_cancel(skb, nlh); | |
| 309 | +} | |
| 310 | + | |
| 311 | +int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family) | |
| 312 | +{ | |
| 313 | + int idx = 0; | |
| 314 | + struct fib_rule *rule; | |
| 315 | + struct fib_rules_ops *ops; | |
| 316 | + | |
| 317 | + ops = lookup_rules_ops(family); | |
| 318 | + if (ops == NULL) | |
| 319 | + return -EAFNOSUPPORT; | |
| 320 | + | |
| 321 | + rcu_read_lock(); | |
| 322 | + list_for_each_entry(rule, ops->rules_list, list) { | |
| 323 | + if (idx < cb->args[0]) | |
| 324 | + goto skip; | |
| 325 | + | |
| 326 | + if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid, | |
| 327 | + cb->nlh->nlmsg_seq, RTM_NEWRULE, | |
| 328 | + NLM_F_MULTI, ops) < 0) | |
| 329 | + break; | |
| 330 | +skip: | |
| 331 | + idx++; | |
| 332 | + } | |
| 333 | + rcu_read_unlock(); | |
| 334 | + cb->args[0] = idx; | |
| 335 | + rules_ops_put(ops); | |
| 336 | + | |
| 337 | + return skb->len; | |
| 338 | +} | |
| 339 | + | |
| 340 | +EXPORT_SYMBOL_GPL(fib_rules_dump); | |
| 341 | + | |
| 342 | +static void notify_rule_change(int event, struct fib_rule *rule, | |
| 343 | + struct fib_rules_ops *ops, struct nlmsghdr *nlh, | |
| 344 | + u32 pid) | |
| 345 | +{ | |
| 346 | + struct sk_buff *skb; | |
| 347 | + int err = -ENOBUFS; | |
| 348 | + | |
| 349 | + skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | |
| 350 | + if (skb == NULL) | |
| 351 | + goto errout; | |
| 352 | + | |
| 353 | + err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops); | |
| 354 | + if (err < 0) { | |
| 355 | + kfree_skb(skb); | |
| 356 | + goto errout; | |
| 357 | + } | |
| 358 | + | |
| 359 | + err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL); | |
| 360 | +errout: | |
| 361 | + if (err < 0) | |
| 362 | + rtnl_set_sk_err(ops->nlgroup, err); | |
| 363 | +} | |
| 364 | + | |
| 365 | +static void attach_rules(struct list_head *rules, struct net_device *dev) | |
| 366 | +{ | |
| 367 | + struct fib_rule *rule; | |
| 368 | + | |
| 369 | + list_for_each_entry(rule, rules, list) { | |
| 370 | + if (rule->ifindex == -1 && | |
| 371 | + strcmp(dev->name, rule->ifname) == 0) | |
| 372 | + rule->ifindex = dev->ifindex; | |
| 373 | + } | |
| 374 | +} | |
| 375 | + | |
| 376 | +static void detach_rules(struct list_head *rules, struct net_device *dev) | |
| 377 | +{ | |
| 378 | + struct fib_rule *rule; | |
| 379 | + | |
| 380 | + list_for_each_entry(rule, rules, list) | |
| 381 | + if (rule->ifindex == dev->ifindex) | |
| 382 | + rule->ifindex = -1; | |
| 383 | +} | |
| 384 | + | |
| 385 | + | |
| 386 | +static int fib_rules_event(struct notifier_block *this, unsigned long event, | |
| 387 | + void *ptr) | |
| 388 | +{ | |
| 389 | + struct net_device *dev = ptr; | |
| 390 | + struct fib_rules_ops *ops; | |
| 391 | + | |
| 392 | + ASSERT_RTNL(); | |
| 393 | + rcu_read_lock(); | |
| 394 | + | |
| 395 | + switch (event) { | |
| 396 | + case NETDEV_REGISTER: | |
| 397 | + list_for_each_entry(ops, &rules_ops, list) | |
| 398 | + attach_rules(ops->rules_list, dev); | |
| 399 | + break; | |
| 400 | + | |
| 401 | + case NETDEV_UNREGISTER: | |
| 402 | + list_for_each_entry(ops, &rules_ops, list) | |
| 403 | + detach_rules(ops->rules_list, dev); | |
| 404 | + break; | |
| 405 | + } | |
| 406 | + | |
| 407 | + rcu_read_unlock(); | |
| 408 | + | |
| 409 | + return NOTIFY_DONE; | |
| 410 | +} | |
| 411 | + | |
| 412 | +static struct notifier_block fib_rules_notifier = { | |
| 413 | + .notifier_call = fib_rules_event, | |
| 414 | +}; | |
| 415 | + | |
| 416 | +static int __init fib_rules_init(void) | |
| 417 | +{ | |
| 418 | + return register_netdevice_notifier(&fib_rules_notifier); | |
| 419 | +} | |
| 420 | + | |
| 421 | +subsys_initcall(fib_rules_init); | |
| @@ -422,10 +422,10 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) · 421 unmodified lines | ||
| 422 | 422 | if (!err) { |
| 423 | 423 | struct sk_filter *old_fp; |
| 424 | 424 | |
| 425 | − spin_lock_bh(&sk->sk_lock.slock); | |
| 426 | − old_fp = sk->sk_filter; | |
| 427 | − sk->sk_filter = fp; | |
| 428 | − spin_unlock_bh(&sk->sk_lock.slock); | |
| 425 | + rcu_read_lock_bh(); | |
| 426 | + old_fp = rcu_dereference(sk->sk_filter); | |
| 427 | + rcu_assign_pointer(sk->sk_filter, fp); | |
| 428 | + rcu_read_unlock_bh(); | |
| 429 | 429 | fp = old_fp; |
| 430 | 430 | } |
| 431 | 431 | |
| @@ -32,7 +32,6 @@ struct flow_cache_entry { · 31 unmodified lines | ||
| 32 | 32 | u8 dir; |
| 33 | 33 | struct flowi key; |
| 34 | 34 | u32 genid; |
| 35 | − u32 sk_sid; | |
| 36 | 35 | void *object; |
| 37 | 36 | atomic_t *object_ref; |
| 38 | 37 | }; |
| @@ -165,7 +164,7 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2) · 126 unmodified lines | ||
| 165 | 164 | return 0; |
| 166 | 165 | } |
| 167 | 166 | |
| 168 | −void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir, | |
| 167 | +void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, | |
| 169 | 168 | flow_resolve_t resolver) |
| 170 | 169 | { |
| 171 | 170 | struct flow_cache_entry *fle, **head; |
| @@ -189,7 +188,6 @@ void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir, · 17 unmodified lines | ||
| 189 | 188 | for (fle = *head; fle; fle = fle->next) { |
| 190 | 189 | if (fle->family == family && |
| 191 | 190 | fle->dir == dir && |
| 192 | − fle->sk_sid == sk_sid && | |
| 193 | 191 | flow_key_compare(key, &fle->key) == 0) { |
| 194 | 192 | if (fle->genid == atomic_read(&flow_cache_genid)) { |
| 195 | 193 | void *ret = fle->object; |
| @@ -214,7 +212,6 @@ void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir, · 18 unmodified lines | ||
| 214 | 212 | *head = fle; |
| 215 | 213 | fle->family = family; |
| 216 | 214 | fle->dir = dir; |
| 217 | − fle->sk_sid = sk_sid; | |
| 218 | 215 | memcpy(&fle->key, key, sizeof(*key)); |
| 219 | 216 | fle->object = NULL; |
| 220 | 217 | flow_count(cpu)++; |
| @@ -226,7 +223,7 @@ nocache: · 5 unmodified lines | ||
| 226 | 223 | void *obj; |
| 227 | 224 | atomic_t *obj_ref; |
| 228 | 225 | |
| 229 | − resolver(key, sk_sid, family, dir, &obj, &obj_ref); | |
| 226 | + resolver(key, family, dir, &obj, &obj_ref); | |
| 230 | 227 | |
| 231 | 228 | if (fle) { |
| 232 | 229 | fle->genid = atomic_read(&flow_cache_genid); |
| @@ -346,12 +343,8 @@ static int __init flow_cache_init(void) · 113 unmodified lines | ||
| 346 | 343 | |
| 347 | 344 | flow_cachep = kmem_cache_create("flow_cache", |
| 348 | 345 | sizeof(struct flow_cache_entry), |
| 349 | − 0, SLAB_HWCACHE_ALIGN, | |
| 346 | + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, | |
| 350 | 347 | NULL, NULL); |
| 351 | − | |
| 352 | − if (!flow_cachep) | |
| 353 | − panic("NET: failed to allocate flow cache slab\n"); | |
| 354 | − | |
| 355 | 348 | flow_hash_shift = 10; |
| 356 | 349 | flow_lwm = 2 * flow_hash_size; |
| 357 | 350 | flow_hwm = 4 * flow_hash_size; |
| @@ -30,6 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <net/dst.h> |
| 31 | 31 | #include <net/sock.h> |
| 32 | 32 | #include <net/netevent.h> |
| 33 | +#include <net/netlink.h> | |
| 33 | 34 | #include <linux/rtnetlink.h> |
| 34 | 35 | #include <linux/random.h> |
| 35 | 36 | #include <linux/string.h> |
| @@ -888,7 +889,7 @@ out_unlock_bh: · 852 unmodified lines | ||
| 888 | 889 | return rc; |
| 889 | 890 | } |
| 890 | 891 | |
| 891 | −static __inline__ void neigh_update_hhs(struct neighbour *neigh) | |
| 892 | +static void neigh_update_hhs(struct neighbour *neigh) | |
| 892 | 893 | { |
| 893 | 894 | struct hh_cache *hh; |
| 894 | 895 | void (*update)(struct hh_cache*, struct net_device*, unsigned char *) = |
| @@ -1338,14 +1339,10 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) · 443 unmodified lines | ||
| 1338 | 1339 | neigh_rand_reach_time(tbl->parms.base_reachable_time); |
| 1339 | 1340 | |
| 1340 | 1341 | if (!tbl->kmem_cachep) |
| 1341 | − tbl->kmem_cachep = kmem_cache_create(tbl->id, | |
| 1342 | − tbl->entry_size, | |
| 1343 | − 0, SLAB_HWCACHE_ALIGN, | |
| 1344 | − NULL, NULL); | |
| 1345 | − | |
| 1346 | − if (!tbl->kmem_cachep) | |
| 1347 | − panic("cannot create neighbour cache"); | |
| 1348 | − | |
| 1342 | + tbl->kmem_cachep = | |
| 1343 | + kmem_cache_create(tbl->id, tbl->entry_size, 0, | |
| 1344 | + SLAB_HWCACHE_ALIGN|SLAB_PANIC, | |
| 1345 | + NULL, NULL); | |
| 1349 | 1346 | tbl->stats = alloc_percpu(struct neigh_statistics); |
| 1350 | 1347 | if (!tbl->stats) |
| 1351 | 1348 | panic("cannot create neighbour cache statistics"); |
| @@ -1440,48 +1437,62 @@ int neigh_table_clear(struct neigh_table *tbl) · 88 unmodified lines | ||
| 1440 | 1437 | |
| 1441 | 1438 | int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
| 1442 | 1439 | { |
| 1443 | − struct ndmsg *ndm = NLMSG_DATA(nlh); | |
| 1444 | − struct rtattr **nda = arg; | |
| 1440 | + struct ndmsg *ndm; | |
| 1441 | + struct nlattr *dst_attr; | |
| 1445 | 1442 | struct neigh_table *tbl; |
| 1446 | 1443 | struct net_device *dev = NULL; |
| 1447 | − int err = -ENODEV; | |
| 1444 | + int err = -EINVAL; | |
| 1448 | 1445 | |
| 1449 | − if (ndm->ndm_ifindex && | |
| 1450 | − (dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL) | |
| 1446 | + if (nlmsg_len(nlh) < sizeof(*ndm)) | |
| 1451 | 1447 | goto out; |
| 1452 | 1448 | |
| 1449 | + dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST); | |
| 1450 | + if (dst_attr == NULL) | |
| 1451 | + goto out; | |
| 1452 | + | |
| 1453 | + ndm = nlmsg_data(nlh); | |
| 1454 | + if (ndm->ndm_ifindex) { | |
| 1455 | + dev = dev_get_by_index(ndm->ndm_ifindex); | |
| 1456 | + if (dev == NULL) { | |
| 1457 | + err = -ENODEV; | |
| 1458 | + goto out; | |
| 1459 | + } | |
| 1460 | + } | |
| 1461 | + | |
| 1453 | 1462 | read_lock(&neigh_tbl_lock); |
| 1454 | 1463 | for (tbl = neigh_tables; tbl; tbl = tbl->next) { |
| 1455 | − struct rtattr *dst_attr = nda[NDA_DST - 1]; | |
| 1456 | − struct neighbour *n; | |
| 1464 | + struct neighbour *neigh; | |
| 1457 | 1465 | |
| 1458 | 1466 | if (tbl->family != ndm->ndm_family) |
| 1459 | 1467 | continue; |
| 1460 | 1468 | read_unlock(&neigh_tbl_lock); |
| 1461 | 1469 | |
| 1462 | − err = -EINVAL; | |
| 1463 | − if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len) | |
| 1470 | + if (nla_len(dst_attr) < tbl->key_len) | |
| 1464 | 1471 | goto out_dev_put; |
| 1465 | 1472 | |
| 1466 | 1473 | if (ndm->ndm_flags & NTF_PROXY) { |
| 1467 | − err = pneigh_delete(tbl, RTA_DATA(dst_attr), dev); | |
| 1474 | + err = pneigh_delete(tbl, nla_data(dst_attr), dev); | |
| 1468 | 1475 | goto out_dev_put; |
| 1469 | 1476 | } |
| 1470 | 1477 | |
| 1471 | − if (!dev) | |
| 1472 | − goto out; | |
| 1478 | + if (dev == NULL) | |
| 1479 | + goto out_dev_put; | |
| 1473 | 1480 | |
| 1474 | − n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev); | |
| 1475 | − if (n) { | |
| 1476 | − err = neigh_update(n, NULL, NUD_FAILED, | |
| 1477 | − NEIGH_UPDATE_F_OVERRIDE| | |
| 1478 | − NEIGH_UPDATE_F_ADMIN); | |
| 1479 | − neigh_release(n); | |
| 1481 | + neigh = neigh_lookup(tbl, nla_data(dst_attr), dev); | |
| 1482 | + if (neigh == NULL) { | |
| 1483 | + err = -ENOENT; | |
| 1484 | + goto out_dev_put; | |
| 1480 | 1485 | } |
| 1486 | + | |
| 1487 | + err = neigh_update(neigh, NULL, NUD_FAILED, | |
| 1488 | + NEIGH_UPDATE_F_OVERRIDE | | |
| 1489 | + NEIGH_UPDATE_F_ADMIN); | |
| 1490 | + neigh_release(neigh); | |
| 1481 | 1491 | goto out_dev_put; |
| 1482 | 1492 | } |
| 1483 | 1493 | read_unlock(&neigh_tbl_lock); |
| 1484 | − err = -EADDRNOTAVAIL; | |
| 1494 | + err = -EAFNOSUPPORT; | |
| 1495 | + | |
| 1485 | 1496 | out_dev_put: |
| 1486 | 1497 | if (dev) |
| 1487 | 1498 | dev_put(dev); |
| @@ -1491,76 +1502,93 @@ out: · 3 unmodified lines | ||
| 1491 | 1502 | |
| 1492 | 1503 | int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
| 1493 | 1504 | { |
| 1494 | − struct ndmsg *ndm = NLMSG_DATA(nlh); | |
| 1495 | − struct rtattr **nda = arg; | |
| 1505 | + struct ndmsg *ndm; | |
| 1506 | + struct nlattr *tb[NDA_MAX+1]; | |
| 1496 | 1507 | struct neigh_table *tbl; |
| 1497 | 1508 | struct net_device *dev = NULL; |
| 1498 | − int err = -ENODEV; | |
| 1509 | + int err; | |
| 1499 | 1510 | |
| 1500 | − if (ndm->ndm_ifindex && | |
| 1501 | − (dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL) | |
| 1511 | + err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); | |
| 1512 | + if (err < 0) | |
| 1502 | 1513 | goto out; |
| 1503 | 1514 | |
| 1515 | + err = -EINVAL; | |
| 1516 | + if (tb[NDA_DST] == NULL) | |
| 1517 | + goto out; | |
| 1518 | + | |
| 1519 | + ndm = nlmsg_data(nlh); | |
| 1520 | + if (ndm->ndm_ifindex) { | |
| 1521 | + dev = dev_get_by_index(ndm->ndm_ifindex); | |
| 1522 | + if (dev == NULL) { | |
| 1523 | + err = -ENODEV; | |
| 1524 | + goto out; | |
| 1525 | + } | |
| 1526 | + | |
| 1527 | + if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len) | |
| 1528 | + goto out_dev_put; | |
| 1529 | + } | |
| 1530 | + | |
| 1504 | 1531 | read_lock(&neigh_tbl_lock); |
| 1505 | 1532 | for (tbl = neigh_tables; tbl; tbl = tbl->next) { |
| 1506 | − struct rtattr *lladdr_attr = nda[NDA_LLADDR - 1]; | |
| 1507 | − struct rtattr *dst_attr = nda[NDA_DST - 1]; | |
| 1508 | − int override = 1; | |
| 1509 | − struct neighbour *n; | |
| 1533 | + int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE; | |
| 1534 | + struct neighbour *neigh; | |
| 1535 | + void *dst, *lladdr; | |
| 1510 | 1536 | |
| 1511 | 1537 | if (tbl->family != ndm->ndm_family) |
| 1512 | 1538 | continue; |
| 1513 | 1539 | read_unlock(&neigh_tbl_lock); |
| 1514 | 1540 | |
| 1515 | − err = -EINVAL; | |
| 1516 | − if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len) | |
| 1541 | + if (nla_len(tb[NDA_DST]) < tbl->key_len) | |
| 1517 | 1542 | goto out_dev_put; |
| 1543 | + dst = nla_data(tb[NDA_DST]); | |
| 1544 | + lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL; | |
| 1518 | 1545 | |
| 1519 | 1546 | if (ndm->ndm_flags & NTF_PROXY) { |
| 1547 | + struct pneigh_entry *pn; | |
| 1548 | + | |
| 1520 | 1549 | err = -ENOBUFS; |
| 1521 | − if (pneigh_lookup(tbl, RTA_DATA(dst_attr), dev, 1)) | |
| 1550 | + pn = pneigh_lookup(tbl, dst, dev, 1); | |
| 1551 | + if (pn) { | |
| 1552 | + pn->flags = ndm->ndm_flags; | |
| 1522 | 1553 | err = 0; |
| 1554 | + } | |
| 1523 | 1555 | goto out_dev_put; |
| 1524 | 1556 | } |
| 1525 | 1557 | |
| 1526 | − err = -EINVAL; | |
| 1527 | − if (!dev) | |
| 1528 | − goto out; | |
| 1529 | − if (lladdr_attr && RTA_PAYLOAD(lladdr_attr) < dev->addr_len) | |
| 1558 | + if (dev == NULL) | |
| 1530 | 1559 | goto out_dev_put; |
| 1560 | + | |
| 1561 | + neigh = neigh_lookup(tbl, dst, dev); | |
| 1562 | + if (neigh == NULL) { | |
| 1563 | + if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { | |
| 1564 | + err = -ENOENT; | |
| 1565 | + goto out_dev_put; | |
| 1566 | + } | |
| 1531 | 1567 | |
| 1532 | − n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev); | |
| 1533 | − if (n) { | |
| 1534 | − if (nlh->nlmsg_flags & NLM_F_EXCL) { | |
| 1535 | − err = -EEXIST; | |
| 1536 | − neigh_release(n); | |
| 1568 | + neigh = __neigh_lookup_errno(tbl, dst, dev); | |
| 1569 | + if (IS_ERR(neigh)) { | |
| 1570 | + err = PTR_ERR(neigh); | |
| 1537 | 1571 | goto out_dev_put; |
| 1538 | 1572 | } |
| 1539 | − | |
| 1540 | − override = nlh->nlmsg_flags & NLM_F_REPLACE; | |
| 1541 | − } else if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { | |
| 1542 | − err = -ENOENT; | |
| 1543 | − goto out_dev_put; | |
| 1544 | 1573 | } else { |
| 1545 | − n = __neigh_lookup_errno(tbl, RTA_DATA(dst_attr), dev); | |
| 1546 | − if (IS_ERR(n)) { | |
| 1547 | − err = PTR_ERR(n); | |
| 1574 | + if (nlh->nlmsg_flags & NLM_F_EXCL) { | |
| 1575 | + err = -EEXIST; | |
| 1576 | + neigh_release(neigh); | |
| 1548 | 1577 | goto out_dev_put; |
| 1549 | 1578 | } |
| 1550 | − } | |
| 1551 | 1579 | |
| 1552 | − err = neigh_update(n, | |
| 1553 | − lladdr_attr ? RTA_DATA(lladdr_attr) : NULL, | |
| 1554 | − ndm->ndm_state, | |
| 1555 | − (override ? NEIGH_UPDATE_F_OVERRIDE : 0) | | |
| 1556 | − NEIGH_UPDATE_F_ADMIN); | |
| 1580 | + if (!(nlh->nlmsg_flags & NLM_F_REPLACE)) | |
| 1581 | + flags &= ~NEIGH_UPDATE_F_OVERRIDE; | |
| 1582 | + } | |
| 1557 | 1583 | |
| 1558 | − neigh_release(n); | |
| 1584 | + err = neigh_update(neigh, lladdr, ndm->ndm_state, flags); | |
| 1585 | + neigh_release(neigh); | |
| 1559 | 1586 | goto out_dev_put; |
| 1560 | 1587 | } |
| 1561 | 1588 | |
| 1562 | 1589 | read_unlock(&neigh_tbl_lock); |
| 1563 | − err = -EADDRNOTAVAIL; | |
| 1590 | + err = -EAFNOSUPPORT; | |
| 1591 | + | |
| 1564 | 1592 | out_dev_put: |
| 1565 | 1593 | if (dev) |
| 1566 | 1594 | dev_put(dev); |
| @@ -1570,56 +1598,59 @@ out: · 3 unmodified lines | ||
| 1570 | 1598 | |
| 1571 | 1599 | static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms) |
| 1572 | 1600 | { |
| 1573 | − struct rtattr *nest = NULL; | |
| 1574 | − | |
| 1575 | − nest = RTA_NEST(skb, NDTA_PARMS); | |
| 1601 | + struct nlattr *nest; | |
| 1602 | + | |
| 1603 | + nest = nla_nest_start(skb, NDTA_PARMS); | |
| 1604 | + if (nest == NULL) | |
| 1605 | + return -ENOBUFS; | |
| 1576 | 1606 | |
| 1577 | 1607 | if (parms->dev) |
| 1578 | − RTA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex); | |
| 1579 | − | |
| 1580 | − RTA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)); | |
| 1581 | − RTA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len); | |
| 1582 | − RTA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen); | |
| 1583 | − RTA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes); | |
| 1584 | − RTA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes); | |
| 1585 | − RTA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes); | |
| 1586 | − RTA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time); | |
| 1587 | − RTA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME, | |
| 1608 | + NLA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex); | |
| 1609 | + | |
| 1610 | + NLA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)); | |
| 1611 | + NLA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len); | |
| 1612 | + NLA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen); | |
| 1613 | + NLA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes); | |
| 1614 | + NLA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes); | |
| 1615 | + NLA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes); | |
| 1616 | + NLA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time); | |
| 1617 | + NLA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME, | |
| 1588 | 1618 | parms->base_reachable_time); |
| 1589 | − RTA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime); | |
| 1590 | − RTA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time); | |
| 1591 | − RTA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time); | |
| 1592 | − RTA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay); | |
| 1593 | − RTA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay); | |
| 1594 | − RTA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime); | |
| 1619 | + NLA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime); | |
| 1620 | + NLA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time); | |
| 1621 | + NLA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time); | |
| 1622 | + NLA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay); | |
| 1623 | + NLA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay); | |
| 1624 | + NLA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime); | |
| 1595 | 1625 | |
| 1596 | − return RTA_NEST_END(skb, nest); | |
| 1626 | + return nla_nest_end(skb, nest); | |
| 1597 | 1627 | |
| 1598 | −rtattr_failure: | |
| 1599 | − return RTA_NEST_CANCEL(skb, nest); | |
| 1628 | +nla_put_failure: | |
| 1629 | + return nla_nest_cancel(skb, nest); | |
| 1600 | 1630 | } |
| 1601 | 1631 | |
| 1602 | −static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, | |
| 1603 | − struct netlink_callback *cb) | |
| 1632 | +static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, | |
| 1633 | + u32 pid, u32 seq, int type, int flags) | |
| 1604 | 1634 | { |
| 1605 | 1635 | struct nlmsghdr *nlh; |
| 1606 | 1636 | struct ndtmsg *ndtmsg; |
| 1607 | 1637 | |
| 1608 | − nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg), | |
| 1609 | − NLM_F_MULTI); | |
| 1638 | + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); | |
| 1639 | + if (nlh == NULL) | |
| 1640 | + return -ENOBUFS; | |
| 1610 | 1641 | |
| 1611 | − ndtmsg = NLMSG_DATA(nlh); | |
| 1642 | + ndtmsg = nlmsg_data(nlh); | |
| 1612 | 1643 | |
| 1613 | 1644 | read_lock_bh(&tbl->lock); |
| 1614 | 1645 | ndtmsg->ndtm_family = tbl->family; |
| 1615 | 1646 | ndtmsg->ndtm_pad1 = 0; |
| 1616 | 1647 | ndtmsg->ndtm_pad2 = 0; |
| 1617 | 1648 | |
| 1618 | − RTA_PUT_STRING(skb, NDTA_NAME, tbl->id); | |
| 1619 | − RTA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval); | |
| 1620 | − RTA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1); | |
| 1621 | − RTA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2); | |
| 1622 | − RTA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3); | |
| 1649 | + NLA_PUT_STRING(skb, NDTA_NAME, tbl->id); | |
| 1650 | + NLA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval); | |
| 1651 | + NLA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1); | |
| 1652 | + NLA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2); | |
| 1653 | + NLA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3); | |
| 1623 | 1654 | |
| 1624 | 1655 | { |
| 1625 | 1656 | unsigned long now = jiffies; |
| @@ -1638,7 +1669,7 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, · 12 unmodified lines | ||
| 1638 | 1669 | .ndtc_proxy_qlen = tbl->proxy_queue.qlen, |
| 1639 | 1670 | }; |
| 1640 | 1671 | |
| 1641 | − RTA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); | |
| 1672 | + NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); | |
| 1642 | 1673 | } |
| 1643 | 1674 | |
| 1644 | 1675 | { |
| @@ -1663,55 +1694,50 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, · 18 unmodified lines | ||
| 1663 | 1694 | ndst.ndts_forced_gc_runs += st->forced_gc_runs; |
| 1664 | 1695 | } |
| 1665 | 1696 | |
| 1666 | − RTA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst); | |
| 1697 | + NLA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst); | |
| 1667 | 1698 | } |
| 1668 | 1699 | |
| 1669 | 1700 | BUG_ON(tbl->parms.dev); |
| 1670 | 1701 | if (neightbl_fill_parms(skb, &tbl->parms) < 0) |
| 1671 | − goto rtattr_failure; | |
| 1702 | + goto nla_put_failure; | |
| 1672 | 1703 | |
| 1673 | 1704 | read_unlock_bh(&tbl->lock); |
| 1674 | − return NLMSG_END(skb, nlh); | |
| 1705 | + return nlmsg_end(skb, nlh); | |
| 1675 | 1706 | |
| 1676 | −rtattr_failure: | |
| 1707 | +nla_put_failure: | |
| 1677 | 1708 | read_unlock_bh(&tbl->lock); |
| 1678 | − return NLMSG_CANCEL(skb, nlh); | |
| 1679 | − | |
| 1680 | −nlmsg_failure: | |
| 1681 | − return -1; | |
| 1709 | + return nlmsg_cancel(skb, nlh); | |
| 1682 | 1710 | } |
| 1683 | 1711 | |
| 1684 | −static int neightbl_fill_param_info(struct neigh_table *tbl, | |
| 1712 | +static int neightbl_fill_param_info(struct sk_buff *skb, | |
| 1713 | + struct neigh_table *tbl, | |
| 1685 | 1714 | struct neigh_parms *parms, |
| 1686 | − struct sk_buff *skb, | |
| 1687 | − struct netlink_callback *cb) | |
| 1715 | + u32 pid, u32 seq, int type, | |
| 1716 | + unsigned int flags) | |
| 1688 | 1717 | { |
| 1689 | 1718 | struct ndtmsg *ndtmsg; |
| 1690 | 1719 | struct nlmsghdr *nlh; |
| 1691 | 1720 | |
| 1692 | − nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg), | |
| 1693 | − NLM_F_MULTI); | |
| 1721 | + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); | |
| 1722 | + if (nlh == NULL) | |
| 1723 | + return -ENOBUFS; | |
| 1694 | 1724 | |
| 1695 | − ndtmsg = NLMSG_DATA(nlh); | |
| 1725 | + ndtmsg = nlmsg_data(nlh); | |
| 1696 | 1726 | |
| 1697 | 1727 | read_lock_bh(&tbl->lock); |
| 1698 | 1728 | ndtmsg->ndtm_family = tbl->family; |
| 1699 | 1729 | ndtmsg->ndtm_pad1 = 0; |
| 1700 | 1730 | ndtmsg->ndtm_pad2 = 0; |
| 1701 | − RTA_PUT_STRING(skb, NDTA_NAME, tbl->id); | |
| 1702 | 1731 | |
| 1703 | − if (neightbl_fill_parms(skb, parms) < 0) | |
| 1704 | − goto rtattr_failure; | |
| 1732 | + if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 || | |
| 1733 | + neightbl_fill_parms(skb, parms) < 0) | |
| 1734 | + goto errout; | |
| 1705 | 1735 | |
| 1706 | 1736 | read_unlock_bh(&tbl->lock); |
| 1707 | − return NLMSG_END(skb, nlh); | |
| 1708 | − | |
| 1709 | −rtattr_failure: | |
| 1737 | + return nlmsg_end(skb, nlh); | |
| 1738 | +errout: | |
| 1710 | 1739 | read_unlock_bh(&tbl->lock); |
| 1711 | − return NLMSG_CANCEL(skb, nlh); | |
| 1712 | − | |
| 1713 | −nlmsg_failure: | |
| 1714 | − return -1; | |
| 1740 | + return nlmsg_cancel(skb, nlh); | |
| 1715 | 1741 | } |
| 1716 | 1742 | |
| 1717 | 1743 | static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, |
| @@ -1727,28 +1753,61 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, · 9 unmodified lines | ||
| 1727 | 1753 | return NULL; |
| 1728 | 1754 | } |
| 1729 | 1755 | |
| 1756 | +static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = { | |
| 1757 | + [NDTA_NAME] = { .type = NLA_STRING }, | |
| 1758 | + [NDTA_THRESH1] = { .type = NLA_U32 }, | |
| 1759 | + [NDTA_THRESH2] = { .type = NLA_U32 }, | |
| 1760 | + [NDTA_THRESH3] = { .type = NLA_U32 }, | |
| 1761 | + [NDTA_GC_INTERVAL] = { .type = NLA_U64 }, | |
| 1762 | + [NDTA_PARMS] = { .type = NLA_NESTED }, | |
| 1763 | +}; | |
| 1764 | + | |
| 1765 | +static struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] __read_mostly = { | |
| 1766 | + [NDTPA_IFINDEX] = { .type = NLA_U32 }, | |
| 1767 | + [NDTPA_QUEUE_LEN] = { .type = NLA_U32 }, | |
| 1768 | + [NDTPA_PROXY_QLEN] = { .type = NLA_U32 }, | |
| 1769 | + [NDTPA_APP_PROBES] = { .type = NLA_U32 }, | |
| 1770 | + [NDTPA_UCAST_PROBES] = { .type = NLA_U32 }, | |
| 1771 | + [NDTPA_MCAST_PROBES] = { .type = NLA_U32 }, | |
| 1772 | + [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 }, | |
| 1773 | + [NDTPA_GC_STALETIME] = { .type = NLA_U64 }, | |
| 1774 | + [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 }, | |
| 1775 | + [NDTPA_RETRANS_TIME] = { .type = NLA_U64 }, | |
| 1776 | + [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 }, | |
| 1777 | + [NDTPA_PROXY_DELAY] = { .type = NLA_U64 }, | |
| 1778 | + [NDTPA_LOCKTIME] = { .type = NLA_U64 }, | |
| 1779 | +}; | |
| 1780 | + | |
| 1730 | 1781 | int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
| 1731 | 1782 | { |
| 1732 | 1783 | struct neigh_table *tbl; |
| 1733 | − struct ndtmsg *ndtmsg = NLMSG_DATA(nlh); | |
| 1734 | − struct rtattr **tb = arg; | |
| 1735 | − int err = -EINVAL; | |
| 1784 | + struct ndtmsg *ndtmsg; | |
| 1785 | + struct nlattr *tb[NDTA_MAX+1]; | |
| 1786 | + int err; | |
| 1736 | 1787 | |
| 1737 | − if (!tb[NDTA_NAME - 1] || !RTA_PAYLOAD(tb[NDTA_NAME - 1])) | |
| 1738 | − return -EINVAL; | |
| 1788 | + err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX, | |
| 1789 | + nl_neightbl_policy); | |
| 1790 | + if (err < 0) | |
| 1791 | + goto errout; | |
| 1792 | + | |
| 1793 | + if (tb[NDTA_NAME] == NULL) { | |
| 1794 | + err = -EINVAL; | |
| 1795 | + goto errout; | |
| 1796 | + } | |
| 1739 | 1797 | |
| 1798 | + ndtmsg = nlmsg_data(nlh); | |
| 1740 | 1799 | read_lock(&neigh_tbl_lock); |
| 1741 | 1800 | for (tbl = neigh_tables; tbl; tbl = tbl->next) { |
| 1742 | 1801 | if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family) |
| 1743 | 1802 | continue; |
| 1744 | 1803 | |
| 1745 | − if (!rtattr_strcmp(tb[NDTA_NAME - 1], tbl->id)) | |
| 1804 | + if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) | |
| 1746 | 1805 | break; |
| 1747 | 1806 | } |
| 1748 | 1807 | |
| 1749 | 1808 | if (tbl == NULL) { |
| 1750 | 1809 | err = -ENOENT; |
| 1751 | − goto errout; | |
| 1810 | + goto errout_locked; | |
| 1752 | 1811 | } |
| 1753 | 1812 | |
| 1754 | 1813 | /* |
| @@ -1757,165 +1816,178 @@ int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) · 2 unmodified lines | ||
| 1757 | 1816 | */ |
| 1758 | 1817 | write_lock_bh(&tbl->lock); |
| 1759 | 1818 | |
| 1760 | − if (tb[NDTA_THRESH1 - 1]) | |
| 1761 | − tbl->gc_thresh1 = RTA_GET_U32(tb[NDTA_THRESH1 - 1]); | |
| 1762 | − | |
| 1763 | − if (tb[NDTA_THRESH2 - 1]) | |
| 1764 | − tbl->gc_thresh2 = RTA_GET_U32(tb[NDTA_THRESH2 - 1]); | |
| 1765 | − | |
| 1766 | − if (tb[NDTA_THRESH3 - 1]) | |
| 1767 | − tbl->gc_thresh3 = RTA_GET_U32(tb[NDTA_THRESH3 - 1]); | |
| 1768 | − | |
| 1769 | − if (tb[NDTA_GC_INTERVAL - 1]) | |
| 1770 | − tbl->gc_interval = RTA_GET_MSECS(tb[NDTA_GC_INTERVAL - 1]); | |
| 1771 | − | |
| 1772 | − if (tb[NDTA_PARMS - 1]) { | |
| 1773 | − struct rtattr *tbp[NDTPA_MAX]; | |
| 1819 | + if (tb[NDTA_PARMS]) { | |
| 1820 | + struct nlattr *tbp[NDTPA_MAX+1]; | |
| 1774 | 1821 | struct neigh_parms *p; |
| 1775 | − u32 ifindex = 0; | |
| 1822 | + int i, ifindex = 0; | |
| 1776 | 1823 | |
| 1777 | − if (rtattr_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS - 1]) < 0) | |
| 1778 | − goto rtattr_failure; | |
| 1824 | + err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS], | |
| 1825 | + nl_ntbl_parm_policy); | |
| 1826 | + if (err < 0) | |
| 1827 | + goto errout_tbl_lock; | |
| 1779 | 1828 | |
| 1780 | − if (tbp[NDTPA_IFINDEX - 1]) | |
| 1781 | − ifindex = RTA_GET_U32(tbp[NDTPA_IFINDEX - 1]); | |
| 1829 | + if (tbp[NDTPA_IFINDEX]) | |
| 1830 | + ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]); | |
| 1782 | 1831 | |
| 1783 | 1832 | p = lookup_neigh_params(tbl, ifindex); |
| 1784 | 1833 | if (p == NULL) { |
| 1785 | 1834 | err = -ENOENT; |
| 1786 | − goto rtattr_failure; | |
| 1835 | + goto errout_tbl_lock; | |
| 1787 | 1836 | } |
| 1788 | − | |
| 1789 | − if (tbp[NDTPA_QUEUE_LEN - 1]) | |
| 1790 | − p->queue_len = RTA_GET_U32(tbp[NDTPA_QUEUE_LEN - 1]); | |
| 1791 | − | |
| 1792 | − if (tbp[NDTPA_PROXY_QLEN - 1]) | |
| 1793 | − p->proxy_qlen = RTA_GET_U32(tbp[NDTPA_PROXY_QLEN - 1]); | |
| 1794 | − | |
| 1795 | − if (tbp[NDTPA_APP_PROBES - 1]) | |
| 1796 | − p->app_probes = RTA_GET_U32(tbp[NDTPA_APP_PROBES - 1]); | |
| 1797 | 1837 | |
| 1798 | − if (tbp[NDTPA_UCAST_PROBES - 1]) | |
| 1799 | − p->ucast_probes = | |
| 1800 | − RTA_GET_U32(tbp[NDTPA_UCAST_PROBES - 1]); | |
| 1801 | − | |
| 1802 | − if (tbp[NDTPA_MCAST_PROBES - 1]) | |
| 1803 | − p->mcast_probes = | |
| 1804 | − RTA_GET_U32(tbp[NDTPA_MCAST_PROBES - 1]); | |
| 1805 | − | |
| 1806 | − if (tbp[NDTPA_BASE_REACHABLE_TIME - 1]) | |
| 1807 | − p->base_reachable_time = | |
| 1808 | − RTA_GET_MSECS(tbp[NDTPA_BASE_REACHABLE_TIME - 1]); | |
| 1809 | − | |
| 1810 | − if (tbp[NDTPA_GC_STALETIME - 1]) | |
| 1811 | − p->gc_staletime = | |
| 1812 | − RTA_GET_MSECS(tbp[NDTPA_GC_STALETIME - 1]); | |
| 1838 | + for (i = 1; i <= NDTPA_MAX; i++) { | |
| 1839 | + if (tbp[i] == NULL) | |
| 1840 | + continue; | |
| 1813 | 1841 | |
| 1814 | − if (tbp[NDTPA_DELAY_PROBE_TIME - 1]) | |
| 1815 | − p->delay_probe_time = | |
| 1816 | − RTA_GET_MSECS(tbp[NDTPA_DELAY_PROBE_TIME - 1]); | |
| 1842 | + switch (i) { | |
| 1843 | + case NDTPA_QUEUE_LEN: | |
| 1844 | + p->queue_len = nla_get_u32(tbp[i]); | |
| 1845 | + break; | |
| 1846 | + case NDTPA_PROXY_QLEN: | |
| 1847 | + p->proxy_qlen = nla_get_u32(tbp[i]); | |
| 1848 | + break; | |
| 1849 | + case NDTPA_APP_PROBES: | |
| 1850 | + p->app_probes = nla_get_u32(tbp[i]); | |
| 1851 | + break; | |
| 1852 | + case NDTPA_UCAST_PROBES: | |
| 1853 | + p->ucast_probes = nla_get_u32(tbp[i]); | |
| 1854 | + break; | |
| 1855 | + case NDTPA_MCAST_PROBES: | |
| 1856 | + p->mcast_probes = nla_get_u32(tbp[i]); | |
| 1857 | + break; | |
| 1858 | + case NDTPA_BASE_REACHABLE_TIME: | |
| 1859 | + p->base_reachable_time = nla_get_msecs(tbp[i]); | |
| 1860 | + break; | |
| 1861 | + case NDTPA_GC_STALETIME: | |
| 1862 | + p->gc_staletime = nla_get_msecs(tbp[i]); | |
| 1863 | + break; | |
| 1864 | + case NDTPA_DELAY_PROBE_TIME: | |
| 1865 | + p->delay_probe_time = nla_get_msecs(tbp[i]); | |
| 1866 | + break; | |
| 1867 | + case NDTPA_RETRANS_TIME: | |
| 1868 | + p->retrans_time = nla_get_msecs(tbp[i]); | |
| 1869 | + break; | |
| 1870 | + case NDTPA_ANYCAST_DELAY: | |
| 1871 | + p->anycast_delay = nla_get_msecs(tbp[i]); | |
| 1872 | + break; | |
| 1873 | + case NDTPA_PROXY_DELAY: | |
| 1874 | + p->proxy_delay = nla_get_msecs(tbp[i]); | |
| 1875 | + break; | |
| 1876 | + case NDTPA_LOCKTIME: | |
| 1877 | + p->locktime = nla_get_msecs(tbp[i]); | |
| 1878 | + break; | |
| 1879 | + } | |
| 1880 | + } | |
| 1881 | + } | |
| 1817 | 1882 | |
| 1818 | − if (tbp[NDTPA_RETRANS_TIME - 1]) | |
| 1819 | − p->retrans_time = | |
| 1820 | − RTA_GET_MSECS(tbp[NDTPA_RETRANS_TIME - 1]); | |
| 1883 | + if (tb[NDTA_THRESH1]) | |
| 1884 | + tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]); | |
| 1821 | 1885 | |
| 1822 | − if (tbp[NDTPA_ANYCAST_DELAY - 1]) | |
| 1823 | − p->anycast_delay = | |
| 1824 | − RTA_GET_MSECS(tbp[NDTPA_ANYCAST_DELAY - 1]); | |
| 1886 | + if (tb[NDTA_THRESH2]) | |
| 1887 | + tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]); | |
| 1825 | 1888 | |
| 1826 | − if (tbp[NDTPA_PROXY_DELAY - 1]) | |
| 1827 | − p->proxy_delay = | |
| 1828 | − RTA_GET_MSECS(tbp[NDTPA_PROXY_DELAY - 1]); | |
| 1889 | + if (tb[NDTA_THRESH3]) | |
| 1890 | + tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]); | |
| 1829 | 1891 | |
| 1830 | − if (tbp[NDTPA_LOCKTIME - 1]) | |
| 1831 | − p->locktime = RTA_GET_MSECS(tbp[NDTPA_LOCKTIME - 1]); | |
| 1832 | − } | |
| 1892 | + if (tb[NDTA_GC_INTERVAL]) | |
| 1893 | + tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]); | |
| 1833 | 1894 | |
| 1834 | 1895 | err = 0; |
| 1835 | 1896 | |
| 1836 | −rtattr_failure: | |
| 1897 | +errout_tbl_lock: | |
| 1837 | 1898 | write_unlock_bh(&tbl->lock); |
| 1838 | −errout: | |
| 1899 | +errout_locked: | |
| 1839 | 1900 | read_unlock(&neigh_tbl_lock); |
| 1901 | +errout: | |
| 1840 | 1902 | return err; |
| 1841 | 1903 | } |
| 1842 | 1904 | |
| 1843 | 1905 | int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) |
| 1844 | 1906 | { |
| 1845 | − int idx, family; | |
| 1846 | − int s_idx = cb->args[0]; | |
| 1907 | + int family, tidx, nidx = 0; | |
| 1908 | + int tbl_skip = cb->args[0]; | |
| 1909 | + int neigh_skip = cb->args[1]; | |
| 1847 | 1910 | struct neigh_table *tbl; |
| 1848 | 1911 | |
| 1849 | − family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family; | |
| 1912 | + family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; | |
| 1850 | 1913 | |
| 1851 | 1914 | read_lock(&neigh_tbl_lock); |
| 1852 | − for (tbl = neigh_tables, idx = 0; tbl; tbl = tbl->next) { | |
| 1915 | + for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) { | |
| 1853 | 1916 | struct neigh_parms *p; |
| 1854 | 1917 | |
| 1855 | − if (idx < s_idx || (family && tbl->family != family)) | |
| 1918 | + if (tidx < tbl_skip || (family && tbl->family != family)) | |
| 1856 | 1919 | continue; |
| 1857 | 1920 | |
| 1858 | − if (neightbl_fill_info(tbl, skb, cb) <= 0) | |
| 1921 | + if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).pid, | |
| 1922 | + cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL, | |
| 1923 | + NLM_F_MULTI) <= 0) | |
| 1859 | 1924 | break; |
| 1860 | 1925 | |
| 1861 | − for (++idx, p = tbl->parms.next; p; p = p->next, idx++) { | |
| 1862 | − if (idx < s_idx) | |
| 1926 | + for (nidx = 0, p = tbl->parms.next; p; p = p->next, nidx++) { | |
| 1927 | + if (nidx < neigh_skip) | |
| 1863 | 1928 | continue; |
| 1864 | 1929 | |
| 1865 | − if (neightbl_fill_param_info(tbl, p, skb, cb) <= 0) | |
| 1930 | + if (neightbl_fill_param_info(skb, tbl, p, | |
| 1931 | + NETLINK_CB(cb->skb).pid, | |
| 1932 | + cb->nlh->nlmsg_seq, | |
| 1933 | + RTM_NEWNEIGHTBL, | |
| 1934 | + NLM_F_MULTI) <= 0) | |
| 1866 | 1935 | goto out; |
| 1867 | 1936 | } |
| 1868 | 1937 | |
| 1938 | + neigh_skip = 0; | |
| 1869 | 1939 | } |
| 1870 | 1940 | out: |
| 1871 | 1941 | read_unlock(&neigh_tbl_lock); |
| 1872 | − cb->args[0] = idx; | |
| 1942 | + cb->args[0] = tidx; | |
| 1943 | + cb->args[1] = nidx; | |
| 1873 | 1944 | |
| 1874 | 1945 | return skb->len; |
| 1875 | 1946 | } |
| 1876 | 1947 | |
| 1877 | −static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n, | |
| 1878 | − u32 pid, u32 seq, int event, unsigned int flags) | |
| 1948 | +static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh, | |
| 1949 | + u32 pid, u32 seq, int type, unsigned int flags) | |
| 1879 | 1950 | { |
| 1880 | 1951 | unsigned long now = jiffies; |
| 1881 | − unsigned char *b = skb->tail; | |
| 1882 | 1952 | struct nda_cacheinfo ci; |
| 1883 | − int locked = 0; | |
| 1884 | − u32 probes; | |
| 1885 | − struct nlmsghdr *nlh = NLMSG_NEW(skb, pid, seq, event, | |
| 1886 | − sizeof(struct ndmsg), flags); | |
| 1887 | − struct ndmsg *ndm = NLMSG_DATA(nlh); | |
| 1953 | + struct nlmsghdr *nlh; | |
| 1954 | + struct ndmsg *ndm; | |
| 1955 | + | |
| 1956 | + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags); | |
| 1957 | + if (nlh == NULL) | |
| 1958 | + return -ENOBUFS; | |
| 1888 | 1959 | |
| 1889 | − ndm->ndm_family = n->ops->family; | |
| 1960 | + ndm = nlmsg_data(nlh); | |
| 1961 | + ndm->ndm_family = neigh->ops->family; | |
| 1890 | 1962 | ndm->ndm_pad1 = 0; |
| 1891 | 1963 | ndm->ndm_pad2 = 0; |
| 1892 | − ndm->ndm_flags = n->flags; | |
| 1893 | − ndm->ndm_type = n->type; | |
| 1894 | − ndm->ndm_ifindex = n->dev->ifindex; | |
| 1895 | − RTA_PUT(skb, NDA_DST, n->tbl->key_len, n->primary_key); | |
| 1896 | − read_lock_bh(&n->lock); | |
| 1897 | − locked = 1; | |
| 1898 | − ndm->ndm_state = n->nud_state; | |
| 1899 | − if (n->nud_state & NUD_VALID) | |
| 1900 | − RTA_PUT(skb, NDA_LLADDR, n->dev->addr_len, n->ha); | |
| 1901 | − ci.ndm_used = now - n->used; | |
| 1902 | − ci.ndm_confirmed = now - n->confirmed; | |
| 1903 | − ci.ndm_updated = now - n->updated; | |
| 1904 | − ci.ndm_refcnt = atomic_read(&n->refcnt) - 1; | |
| 1905 | − probes = atomic_read(&n->probes); | |
| 1906 | − read_unlock_bh(&n->lock); | |
| 1907 | − locked = 0; | |
| 1908 | − RTA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci); | |
| 1909 | − RTA_PUT(skb, NDA_PROBES, sizeof(probes), &probes); | |
| 1910 | − nlh->nlmsg_len = skb->tail - b; | |
| 1911 | − return skb->len; | |
| 1964 | + ndm->ndm_flags = neigh->flags; | |
| 1965 | + ndm->ndm_type = neigh->type; | |
| 1966 | + ndm->ndm_ifindex = neigh->dev->ifindex; | |
| 1967 | + | |
| 1968 | + NLA_PUT(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key); | |
| 1912 | 1969 | |
| 1913 | −nlmsg_failure: | |
| 1914 | −rtattr_failure: | |
| 1915 | − if (locked) | |
| 1916 | − read_unlock_bh(&n->lock); | |
| 1917 | − skb_trim(skb, b - skb->data); | |
| 1918 | − return -1; | |
| 1970 | + read_lock_bh(&neigh->lock); | |
| 1971 | + ndm->ndm_state = neigh->nud_state; | |
| 1972 | + if ((neigh->nud_state & NUD_VALID) && | |
| 1973 | + nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, neigh->ha) < 0) { | |
| 1974 | + read_unlock_bh(&neigh->lock); | |
| 1975 | + goto nla_put_failure; | |
| 1976 | + } | |
| 1977 | + | |
| 1978 | + ci.ndm_used = now - neigh->used; | |
| 1979 | + ci.ndm_confirmed = now - neigh->confirmed; | |
| 1980 | + ci.ndm_updated = now - neigh->updated; | |
| 1981 | + ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1; | |
| 1982 | + read_unlock_bh(&neigh->lock); | |
| 1983 | + | |
| 1984 | + NLA_PUT_U32(skb, NDA_PROBES, atomic_read(&neigh->probes)); | |
| 1985 | + NLA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci); | |
| 1986 | + | |
| 1987 | + return nlmsg_end(skb, nlh); | |
| 1988 | + | |
| 1989 | +nla_put_failure: | |
| 1990 | + return nlmsg_cancel(skb, nlh); | |
| 1919 | 1991 | } |
| 1920 | 1992 | |
| 1921 | 1993 | |
| @@ -1959,7 +2031,7 @@ int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) · 37 unmodified lines | ||
| 1959 | 2031 | int t, family, s_t; |
| 1960 | 2032 | |
| 1961 | 2033 | read_lock(&neigh_tbl_lock); |
| 1962 | − family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family; | |
| 2034 | + family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; | |
| 1963 | 2035 | s_t = cb->args[0]; |
| 1964 | 2036 | |
| 1965 | 2037 | for (tbl = neigh_tables, t = 0; tbl; tbl = tbl->next, t++) { |
| @@ -2338,41 +2410,35 @@ static struct file_operations neigh_stat_seq_fops = { · 372 unmodified lines | ||
| 2338 | 2410 | #endif /* CONFIG_PROC_FS */ |
| 2339 | 2411 | |
| 2340 | 2412 | #ifdef CONFIG_ARPD |
| 2341 | −void neigh_app_ns(struct neighbour *n) | |
| 2413 | +static void __neigh_notify(struct neighbour *n, int type, int flags) | |
| 2342 | 2414 | { |
| 2343 | − struct nlmsghdr *nlh; | |
| 2344 | − int size = NLMSG_SPACE(sizeof(struct ndmsg) + 256); | |
| 2345 | − struct sk_buff *skb = alloc_skb(size, GFP_ATOMIC); | |
| 2415 | + struct sk_buff *skb; | |
| 2416 | + int err = -ENOBUFS; | |
| 2346 | 2417 | |
| 2347 | − if (!skb) | |
| 2348 | − return; | |
| 2418 | + skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | |
| 2419 | + if (skb == NULL) | |
| 2420 | + goto errout; | |
| 2349 | 2421 | |
| 2350 | − if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH, 0) < 0) { | |
| 2422 | + err = neigh_fill_info(skb, n, 0, 0, type, flags); | |
| 2423 | + if (err < 0) { | |
| 2351 | 2424 | kfree_skb(skb); |
| 2352 | − return; | |
| 2425 | + goto errout; | |
| 2353 | 2426 | } |
| 2354 | − nlh = (struct nlmsghdr *)skb->data; | |
| 2355 | − nlh->nlmsg_flags = NLM_F_REQUEST; | |
| 2356 | − NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH; | |
| 2357 | − netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC); | |
| 2427 | + | |
| 2428 | + err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); | |
| 2429 | +errout: | |
| 2430 | + if (err < 0) | |
| 2431 | + rtnl_set_sk_err(RTNLGRP_NEIGH, err); | |
| 2358 | 2432 | } |
| 2359 | 2433 | |
| 2360 | −static void neigh_app_notify(struct neighbour *n) | |
| 2434 | +void neigh_app_ns(struct neighbour *n) | |
| 2361 | 2435 | { |
| 2362 | − struct nlmsghdr *nlh; | |
| 2363 | − int size = NLMSG_SPACE(sizeof(struct ndmsg) + 256); | |
| 2364 | − struct sk_buff *skb = alloc_skb(size, GFP_ATOMIC); | |
| 2365 | − | |
| 2366 | − if (!skb) | |
| 2367 | − return; | |
| 2436 | + __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST); | |
| 2437 | +} | |
| 2368 | 2438 | |
| 2369 | − if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH, 0) < 0) { | |
| 2370 | − kfree_skb(skb); | |
| 2371 | − return; | |
| 2372 | − } | |
| 2373 | − nlh = (struct nlmsghdr *)skb->data; | |
| 2374 | − NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH; | |
| 2375 | − netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC); | |
| 2439 | +static void neigh_app_notify(struct neighbour *n) | |
| 2440 | +{ | |
| 2441 | + __neigh_notify(n, RTM_NEWNEIGH, 0); | |
| 2376 | 2442 | } |
| 2377 | 2443 | |
| 2378 | 2444 | #endif /* CONFIG_ARPD */ |
| @@ -2386,7 +2452,7 @@ static struct neigh_sysctl_table { · 7 unmodified lines | ||
| 2386 | 2452 | ctl_table neigh_neigh_dir[2]; |
| 2387 | 2453 | ctl_table neigh_proto_dir[2]; |
| 2388 | 2454 | ctl_table neigh_root_dir[2]; |
| 2389 | −} neigh_sysctl_template = { | |
| 2455 | +} neigh_sysctl_template __read_mostly = { | |
| 2390 | 2456 | .neigh_vars = { |
| 2391 | 2457 | { |
| 2392 | 2458 | .ctl_name = NET_NEIGH_MCAST_SOLICIT, |
| @@ -2659,7 +2725,6 @@ void neigh_sysctl_unregister(struct neigh_parms *p) · 266 unmodified lines | ||
| 2659 | 2725 | #endif /* CONFIG_SYSCTL */ |
| 2660 | 2726 | |
| 2661 | 2727 | EXPORT_SYMBOL(__neigh_event_send); |
| 2662 | −EXPORT_SYMBOL(neigh_add); | |
| 2663 | 2728 | EXPORT_SYMBOL(neigh_changeaddr); |
| 2664 | 2729 | EXPORT_SYMBOL(neigh_compat_output); |
| 2665 | 2730 | EXPORT_SYMBOL(neigh_connected_output); |
| @@ -2679,11 +2744,8 @@ EXPORT_SYMBOL(neigh_table_clear); · 13 unmodified lines | ||
| 2679 | 2744 | EXPORT_SYMBOL(neigh_table_init); |
| 2680 | 2745 | EXPORT_SYMBOL(neigh_table_init_no_netlink); |
| 2681 | 2746 | EXPORT_SYMBOL(neigh_update); |
| 2682 | −EXPORT_SYMBOL(neigh_update_hhs); | |
| 2683 | 2747 | EXPORT_SYMBOL(pneigh_enqueue); |
| 2684 | 2748 | EXPORT_SYMBOL(pneigh_lookup); |
| 2685 | −EXPORT_SYMBOL(neightbl_dump_info); | |
| 2686 | −EXPORT_SYMBOL(neightbl_set); | |
| 2687 | 2749 | |
| 2688 | 2750 | #ifdef CONFIG_ARPD |
| 2689 | 2751 | EXPORT_SYMBOL(neigh_app_ns); |
| @@ -110,7 +110,7 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, · 109 unmodified lines | ||
| 110 | 110 | |
| 111 | 111 | psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); |
| 112 | 112 | |
| 113 | − if (skb->ip_summed == CHECKSUM_HW && | |
| 113 | + if (skb->ip_summed == CHECKSUM_COMPLETE && | |
| 114 | 114 | !(u16)csum_fold(csum_add(psum, skb->csum))) |
| 115 | 115 | return 0; |
| 116 | 116 | |
| @@ -1786,7 +1786,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) · 1785 unmodified lines | ||
| 1786 | 1786 | * use ipv6_get_lladdr if/when it's get exported |
| 1787 | 1787 | */ |
| 1788 | 1788 | |
| 1789 | − read_lock(&addrconf_lock); | |
| 1789 | + rcu_read_lock(); | |
| 1790 | 1790 | if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) { |
| 1791 | 1791 | struct inet6_ifaddr *ifp; |
| 1792 | 1792 | |
| @@ -1805,7 +1805,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) · 12 unmodified lines | ||
| 1805 | 1805 | } |
| 1806 | 1806 | read_unlock_bh(&idev->lock); |
| 1807 | 1807 | } |
| 1808 | − read_unlock(&addrconf_lock); | |
| 1808 | + rcu_read_unlock(); | |
| 1809 | 1809 | if (err) |
| 1810 | 1810 | printk("pktgen: ERROR: IPv6 link address not availble.\n"); |
| 1811 | 1811 | } |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | #include <linux/init.h> |
| 36 | 36 | #include <linux/security.h> |
| 37 | 37 | #include <linux/mutex.h> |
| 38 | +#include <linux/if_addr.h> | |
| 38 | 39 | |
| 39 | 40 | #include <asm/uaccess.h> |
| 40 | 41 | #include <asm/system.h> |
| @@ -49,6 +50,7 @@ · 8 unmodified lines | ||
| 49 | 50 | #include <net/udp.h> |
| 50 | 51 | #include <net/sock.h> |
| 51 | 52 | #include <net/pkt_sched.h> |
| 53 | +#include <net/fib_rules.h> | |
| 52 | 54 | #include <net/netlink.h> |
| 53 | 55 | #ifdef CONFIG_NET_WIRELESS_RTNETLINK |
| 54 | 56 | #include <linux/wireless.h> |
| @@ -56,6 +58,7 @@ · 1 unmodified line | ||
| 56 | 58 | #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ |
| 57 | 59 | |
| 58 | 60 | static DEFINE_MUTEX(rtnl_mutex); |
| 61 | +static struct sock *rtnl; | |
| 59 | 62 | |
| 60 | 63 | void rtnl_lock(void) |
| 61 | 64 | { |
| @@ -93,8 +96,6 @@ int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) · 31 unmodified lines | ||
| 93 | 96 | return 0; |
| 94 | 97 | } |
| 95 | 98 | |
| 96 | −struct sock *rtnl; | |
| 97 | − | |
| 98 | 99 | struct rtnetlink_link * rtnetlink_links[NPROTO]; |
| 99 | 100 | |
| 100 | 101 | static const int rtm_min[RTM_NR_FAMILIES] = |
| @@ -102,8 +103,7 @@ static const int rtm_min[RTM_NR_FAMILIES] = · 1 unmodified line | ||
| 102 | 103 | [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), |
| 103 | 104 | [RTM_FAM(RTM_NEWADDR)] = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), |
| 104 | 105 | [RTM_FAM(RTM_NEWROUTE)] = NLMSG_LENGTH(sizeof(struct rtmsg)), |
| 105 | − [RTM_FAM(RTM_NEWNEIGH)] = NLMSG_LENGTH(sizeof(struct ndmsg)), | |
| 106 | − [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct rtmsg)), | |
| 106 | + [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct fib_rule_hdr)), | |
| 107 | 107 | [RTM_FAM(RTM_NEWQDISC)] = NLMSG_LENGTH(sizeof(struct tcmsg)), |
| 108 | 108 | [RTM_FAM(RTM_NEWTCLASS)] = NLMSG_LENGTH(sizeof(struct tcmsg)), |
| 109 | 109 | [RTM_FAM(RTM_NEWTFILTER)] = NLMSG_LENGTH(sizeof(struct tcmsg)), |
| @@ -111,7 +111,6 @@ static const int rtm_min[RTM_NR_FAMILIES] = · 1 unmodified line | ||
| 111 | 111 | [RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), |
| 112 | 112 | [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), |
| 113 | 113 | [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), |
| 114 | − [RTM_FAM(RTM_NEWNEIGHTBL)] = NLMSG_LENGTH(sizeof(struct ndtmsg)), | |
| 115 | 114 | }; |
| 116 | 115 | |
| 117 | 116 | static const int rta_max[RTM_NR_FAMILIES] = |
| @@ -119,13 +118,11 @@ static const int rta_max[RTM_NR_FAMILIES] = · 1 unmodified line | ||
| 119 | 118 | [RTM_FAM(RTM_NEWLINK)] = IFLA_MAX, |
| 120 | 119 | [RTM_FAM(RTM_NEWADDR)] = IFA_MAX, |
| 121 | 120 | [RTM_FAM(RTM_NEWROUTE)] = RTA_MAX, |
| 122 | − [RTM_FAM(RTM_NEWNEIGH)] = NDA_MAX, | |
| 123 | − [RTM_FAM(RTM_NEWRULE)] = RTA_MAX, | |
| 121 | + [RTM_FAM(RTM_NEWRULE)] = FRA_MAX, | |
| 124 | 122 | [RTM_FAM(RTM_NEWQDISC)] = TCA_MAX, |
| 125 | 123 | [RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX, |
| 126 | 124 | [RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX, |
| 127 | 125 | [RTM_FAM(RTM_NEWACTION)] = TCAA_MAX, |
| 128 | − [RTM_FAM(RTM_NEWNEIGHTBL)] = NDTA_MAX, | |
| 129 | 126 | }; |
| 130 | 127 | |
| 131 | 128 | void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) |
| @@ -168,24 +165,52 @@ int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) · 36 unmodified lines | ||
| 168 | 165 | return err; |
| 169 | 166 | } |
| 170 | 167 | |
| 168 | +int rtnl_unicast(struct sk_buff *skb, u32 pid) | |
| 169 | +{ | |
| 170 | + return nlmsg_unicast(rtnl, skb, pid); | |
| 171 | +} | |
| 172 | + | |
| 173 | +int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group, | |
| 174 | + struct nlmsghdr *nlh, gfp_t flags) | |
| 175 | +{ | |
| 176 | + int report = 0; | |
| 177 | + | |
| 178 | + if (nlh) | |
| 179 | + report = nlmsg_report(nlh); | |
| 180 | + | |
| 181 | + return nlmsg_notify(rtnl, skb, pid, group, report, flags); | |
| 182 | +} | |
| 183 | + | |
| 184 | +void rtnl_set_sk_err(u32 group, int error) | |
| 185 | +{ | |
| 186 | + netlink_set_err(rtnl, 0, group, error); | |
| 187 | +} | |
| 188 | + | |
| 171 | 189 | int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) |
| 172 | 190 | { |
| 173 | − struct rtattr *mx = (struct rtattr*)skb->tail; | |
| 174 | − int i; | |
| 191 | + struct nlattr *mx; | |
| 192 | + int i, valid = 0; | |
| 193 | + | |
| 194 | + mx = nla_nest_start(skb, RTA_METRICS); | |
| 195 | + if (mx == NULL) | |
| 196 | + return -ENOBUFS; | |
| 197 | + | |
| 198 | + for (i = 0; i < RTAX_MAX; i++) { | |
| 199 | + if (metrics[i]) { | |
| 200 | + valid++; | |
| 201 | + NLA_PUT_U32(skb, i+1, metrics[i]); | |
| 202 | + } | |
| 203 | + } | |
| 175 | 204 | |
| 176 | − RTA_PUT(skb, RTA_METRICS, 0, NULL); | |
| 177 | − for (i=0; i<RTAX_MAX; i++) { | |
| 178 | − if (metrics[i]) | |
| 179 | − RTA_PUT(skb, i+1, sizeof(u32), metrics+i); | |
| 205 | + if (!valid) { | |
| 206 | + nla_nest_cancel(skb, mx); | |
| 207 | + return 0; | |
| 180 | 208 | } |
| 181 | − mx->rta_len = skb->tail - (u8*)mx; | |
| 182 | − if (mx->rta_len == RTA_LENGTH(0)) | |
| 183 | − skb_trim(skb, (u8*)mx - skb->data); | |
| 184 | − return 0; | |
| 185 | 209 | |
| 186 | −rtattr_failure: | |
| 187 | − skb_trim(skb, (u8*)mx - skb->data); | |
| 188 | − return -1; | |
| 210 | + return nla_nest_end(skb, mx); | |
| 211 | + | |
| 212 | +nla_put_failure: | |
| 213 | + return nla_nest_cancel(skb, mx); | |
| 189 | 214 | } |
| 190 | 215 | |
| 191 | 216 | |
| @@ -216,41 +241,73 @@ static void set_operstate(struct net_device *dev, unsigned char transition) · 24 unmodified lines | ||
| 216 | 241 | } |
| 217 | 242 | } |
| 218 | 243 | |
| 219 | −static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |
| 220 | − int type, u32 pid, u32 seq, u32 change, | |
| 221 | − unsigned int flags) | |
| 244 | +static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |
| 245 | + struct net_device_stats *b) | |
| 222 | 246 | { |
| 223 | − struct ifinfomsg *r; | |
| 224 | − struct nlmsghdr *nlh; | |
| 225 | − unsigned char *b = skb->tail; | |
| 226 | − | |
| 227 | − nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags); | |
| 228 | − r = NLMSG_DATA(nlh); | |
| 229 | − r->ifi_family = AF_UNSPEC; | |
| 230 | − r->__ifi_pad = 0; | |
| 231 | − r->ifi_type = dev->type; | |
| 232 | − r->ifi_index = dev->ifindex; | |
| 233 | − r->ifi_flags = dev_get_flags(dev); | |
| 234 | − r->ifi_change = change; | |
| 235 | − | |
| 236 | − RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); | |
| 237 | − | |
| 238 | − if (1) { | |
| 239 | − u32 txqlen = dev->tx_queue_len; | |
| 240 | − RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen); | |
| 241 | − } | |
| 247 | + a->rx_packets = b->rx_packets; | |
| 248 | + a->tx_packets = b->tx_packets; | |
| 249 | + a->rx_bytes = b->rx_bytes; | |
| 250 | + a->tx_bytes = b->tx_bytes; | |
| 251 | + a->rx_errors = b->rx_errors; | |
| 252 | + a->tx_errors = b->tx_errors; | |
| 253 | + a->rx_dropped = b->rx_dropped; | |
| 254 | + a->tx_dropped = b->tx_dropped; | |
| 255 | + | |
| 256 | + a->multicast = b->multicast; | |
| 257 | + a->collisions = b->collisions; | |
| 258 | + | |
| 259 | + a->rx_length_errors = b->rx_length_errors; | |
| 260 | + a->rx_over_errors = b->rx_over_errors; | |
| 261 | + a->rx_crc_errors = b->rx_crc_errors; | |
| 262 | + a->rx_frame_errors = b->rx_frame_errors; | |
| 263 | + a->rx_fifo_errors = b->rx_fifo_errors; | |
| 264 | + a->rx_missed_errors = b->rx_missed_errors; | |
| 265 | + | |
| 266 | + a->tx_aborted_errors = b->tx_aborted_errors; | |
| 267 | + a->tx_carrier_errors = b->tx_carrier_errors; | |
| 268 | + a->tx_fifo_errors = b->tx_fifo_errors; | |
| 269 | + a->tx_heartbeat_errors = b->tx_heartbeat_errors; | |
| 270 | + a->tx_window_errors = b->tx_window_errors; | |
| 271 | + | |
| 272 | + a->rx_compressed = b->rx_compressed; | |
| 273 | + a->tx_compressed = b->tx_compressed; | |
| 274 | +}; | |
| 242 | 275 | |
| 243 | − if (1) { | |
| 244 | − u32 weight = dev->weight; | |
| 245 | − RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight); | |
| 246 | − } | |
| 276 | +static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |
| 277 | + void *iwbuf, int iwbuflen, int type, u32 pid, | |
| 278 | + u32 seq, u32 change, unsigned int flags) | |
| 279 | +{ | |
| 280 | + struct ifinfomsg *ifm; | |
| 281 | + struct nlmsghdr *nlh; | |
| 282 | + | |
| 283 | + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); | |
| 284 | + if (nlh == NULL) | |
| 285 | + return -ENOBUFS; | |
| 286 | + | |
| 287 | + ifm = nlmsg_data(nlh); | |
| 288 | + ifm->ifi_family = AF_UNSPEC; | |
| 289 | + ifm->__ifi_pad = 0; | |
| 290 | + ifm->ifi_type = dev->type; | |
| 291 | + ifm->ifi_index = dev->ifindex; | |
| 292 | + ifm->ifi_flags = dev_get_flags(dev); | |
| 293 | + ifm->ifi_change = change; | |
| 294 | + | |
| 295 | + NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); | |
| 296 | + NLA_PUT_U32(skb, IFLA_TXQLEN, dev->tx_queue_len); | |
| 297 | + NLA_PUT_U32(skb, IFLA_WEIGHT, dev->weight); | |
| 298 | + NLA_PUT_U8(skb, IFLA_OPERSTATE, | |
| 299 | + netif_running(dev) ? dev->operstate : IF_OPER_DOWN); | |
| 300 | + NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode); | |
| 301 | + NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); | |
| 302 | + | |
| 303 | + if (dev->ifindex != dev->iflink) | |
| 304 | + NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); | |
| 305 | + | |
| 306 | + if (dev->master) | |
| 307 | + NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex); | |
| 247 | 308 | |
| 248 | − if (1) { | |
| 249 | − u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN; | |
| 250 | − u8 link_mode = dev->link_mode; | |
| 251 | − RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate); | |
| 252 | − RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode); | |
| 253 | − } | |
| 309 | + if (dev->qdisc_sleeping) | |
| 310 | + NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc_sleeping->ops->id); | |
| 254 | 311 | |
| 255 | 312 | if (1) { |
| 256 | 313 | struct rtnl_link_ifmap map = { |
| @@ -261,58 +318,38 @@ static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, · 4 unmodified lines | ||
| 261 | 318 | .dma = dev->dma, |
| 262 | 319 | .port = dev->if_port, |
| 263 | 320 | }; |
| 264 | − RTA_PUT(skb, IFLA_MAP, sizeof(map), &map); | |
| 321 | + NLA_PUT(skb, IFLA_MAP, sizeof(map), &map); | |
| 265 | 322 | } |
| 266 | 323 | |
| 267 | 324 | if (dev->addr_len) { |
| 268 | − RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); | |
| 269 | − RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); | |
| 270 | − } | |
| 271 | − | |
| 272 | − if (1) { | |
| 273 | − u32 mtu = dev->mtu; | |
| 274 | − RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); | |
| 275 | − } | |
| 276 | − | |
| 277 | − if (dev->ifindex != dev->iflink) { | |
| 278 | − u32 iflink = dev->iflink; | |
| 279 | − RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink); | |
| 280 | − } | |
| 281 | − | |
| 282 | − if (dev->qdisc_sleeping) | |
| 283 | − RTA_PUT(skb, IFLA_QDISC, | |
| 284 | − strlen(dev->qdisc_sleeping->ops->id) + 1, | |
| 285 | − dev->qdisc_sleeping->ops->id); | |
| 286 | − | |
| 287 | − if (dev->master) { | |
| 288 | − u32 master = dev->master->ifindex; | |
| 289 | − RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master); | |
| 325 | + NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); | |
| 326 | + NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); | |
| 290 | 327 | } |
| 291 | 328 | |
| 292 | 329 | if (dev->get_stats) { |
| 293 | − unsigned long *stats = (unsigned long*)dev->get_stats(dev); | |
| 330 | + struct net_device_stats *stats = dev->get_stats(dev); | |
| 294 | 331 | if (stats) { |
| 295 | − struct rtattr *a; | |
| 296 | − __u32 *s; | |
| 297 | − int i; | |
| 298 | − int n = sizeof(struct rtnl_link_stats)/4; | |
| 299 | − | |
| 300 | − a = __RTA_PUT(skb, IFLA_STATS, n*4); | |
| 301 | − s = RTA_DATA(a); | |
| 302 | − for (i=0; i<n; i++) | |
| 303 | − s[i] = stats[i]; | |
| 332 | + struct nlattr *attr; | |
| 333 | + | |
| 334 | + attr = nla_reserve(skb, IFLA_STATS, | |
| 335 | + sizeof(struct rtnl_link_stats)); | |
| 336 | + if (attr == NULL) | |
| 337 | + goto nla_put_failure; | |
| 338 | + | |
| 339 | + copy_rtnl_link_stats(nla_data(attr), stats); | |
| 304 | 340 | } |
| 305 | 341 | } |
| 306 | − nlh->nlmsg_len = skb->tail - b; | |
| 307 | − return skb->len; | |
| 308 | 342 | |
| 309 | −nlmsg_failure: | |
| 310 | −rtattr_failure: | |
| 311 | − skb_trim(skb, b - skb->data); | |
| 312 | − return -1; | |
| 343 | + if (iwbuf) | |
| 344 | + NLA_PUT(skb, IFLA_WIRELESS, iwbuflen, iwbuf); | |
| 345 | + | |
| 346 | + return nlmsg_end(skb, nlh); | |
| 347 | + | |
| 348 | +nla_put_failure: | |
| 349 | + return nlmsg_cancel(skb, nlh); | |
| 313 | 350 | } |
| 314 | 351 | |
| 315 | −static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |
| 352 | +static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |
| 316 | 353 | { |
| 317 | 354 | int idx; |
| 318 | 355 | int s_idx = cb->args[0]; |
| @@ -322,10 +359,9 @@ static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *c · 3 unmodified lines | ||
| 322 | 359 | for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) { |
| 323 | 360 | if (idx < s_idx) |
| 324 | 361 | continue; |
| 325 | − if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, | |
| 326 | − NETLINK_CB(cb->skb).pid, | |
| 327 | − cb->nlh->nlmsg_seq, 0, | |
| 328 | − NLM_F_MULTI) <= 0) | |
| 362 | + if (rtnl_fill_ifinfo(skb, dev, NULL, 0, RTM_NEWLINK, | |
| 363 | + NETLINK_CB(cb->skb).pid, | |
| 364 | + cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0) | |
| 329 | 365 | break; |
| 330 | 366 | } |
| 331 | 367 | read_unlock(&dev_base_lock); |
| @@ -334,52 +370,70 @@ static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *c · 2 unmodified lines | ||
| 334 | 370 | return skb->len; |
| 335 | 371 | } |
| 336 | 372 | |
| 337 | −static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |
| 373 | +static struct nla_policy ifla_policy[IFLA_MAX+1] __read_mostly = { | |
| 374 | + [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, | |
| 375 | + [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, | |
| 376 | + [IFLA_MTU] = { .type = NLA_U32 }, | |
| 377 | + [IFLA_TXQLEN] = { .type = NLA_U32 }, | |
| 378 | + [IFLA_WEIGHT] = { .type = NLA_U32 }, | |
| 379 | + [IFLA_OPERSTATE] = { .type = NLA_U8 }, | |
| 380 | + [IFLA_LINKMODE] = { .type = NLA_U8 }, | |
| 381 | +}; | |
| 382 | + | |
| 383 | +static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |
| 338 | 384 | { |
| 339 | − struct ifinfomsg *ifm = NLMSG_DATA(nlh); | |
| 340 | − struct rtattr **ida = arg; | |
| 385 | + struct ifinfomsg *ifm; | |
| 341 | 386 | struct net_device *dev; |
| 342 | − int err, send_addr_notify = 0; | |
| 387 | + int err, send_addr_notify = 0, modified = 0; | |
| 388 | + struct nlattr *tb[IFLA_MAX+1]; | |
| 389 | + char ifname[IFNAMSIZ]; | |
| 390 | + | |
| 391 | + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | |
| 392 | + if (err < 0) | |
| 393 | + goto errout; | |
| 394 | + | |
| 395 | + if (tb[IFLA_IFNAME]) | |
| 396 | + nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | |
| 397 | + else | |
| 398 | + ifname[0] = '\0'; | |
| 343 | 399 | |
| 400 | + err = -EINVAL; | |
| 401 | + ifm = nlmsg_data(nlh); | |
| 344 | 402 | if (ifm->ifi_index >= 0) |
| 345 | 403 | dev = dev_get_by_index(ifm->ifi_index); |
| 346 | − else if (ida[IFLA_IFNAME - 1]) { | |
| 347 | − char ifname[IFNAMSIZ]; | |
| 348 | − | |
| 349 | − if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1], | |
| 350 | − IFNAMSIZ) >= IFNAMSIZ) | |
| 351 | − return -EINVAL; | |
| 404 | + else if (tb[IFLA_IFNAME]) | |
| 352 | 405 | dev = dev_get_by_name(ifname); |
| 353 | − } else | |
| 354 | − return -EINVAL; | |
| 406 | + else | |
| 407 | + goto errout; | |
| 355 | 408 | |
| 356 | − if (!dev) | |
| 357 | − return -ENODEV; | |
| 409 | + if (dev == NULL) { | |
| 410 | + err = -ENODEV; | |
| 411 | + goto errout; | |
| 412 | + } | |
| 358 | 413 | |
| 359 | − err = -EINVAL; | |
| 414 | + if (tb[IFLA_ADDRESS] && | |
| 415 | + nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | |
| 416 | + goto errout_dev; | |
| 360 | 417 | |
| 361 | − if (ifm->ifi_flags) | |
| 362 | − dev_change_flags(dev, ifm->ifi_flags); | |
| 418 | + if (tb[IFLA_BROADCAST] && | |
| 419 | + nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | |
| 420 | + goto errout_dev; | |
| 363 | 421 | |
| 364 | − if (ida[IFLA_MAP - 1]) { | |
| 422 | + if (tb[IFLA_MAP]) { | |
| 365 | 423 | struct rtnl_link_ifmap *u_map; |
| 366 | 424 | struct ifmap k_map; |
| 367 | 425 | |
| 368 | 426 | if (!dev->set_config) { |
| 369 | 427 | err = -EOPNOTSUPP; |
| 370 | − goto out; | |
| 428 | + goto errout_dev; | |
| 371 | 429 | } |
| 372 | 430 | |
| 373 | 431 | if (!netif_device_present(dev)) { |
| 374 | 432 | err = -ENODEV; |
| 375 | − goto out; | |
| 433 | + goto errout_dev; | |
| 376 | 434 | } |
| 377 | − | |
| 378 | − if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map))) | |
| 379 | − goto out; | |
| 380 | − | |
| 381 | − u_map = RTA_DATA(ida[IFLA_MAP - 1]); | |
| 382 | 435 | |
| 436 | + u_map = nla_data(tb[IFLA_MAP]); | |
| 383 | 437 | k_map.mem_start = (unsigned long) u_map->mem_start; |
| 384 | 438 | k_map.mem_end = (unsigned long) u_map->mem_end; |
| 385 | 439 | k_map.base_addr = (unsigned short) u_map->base_addr; |
| @@ -388,200 +442,175 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) · 2 unmodified lines | ||
| 388 | 442 | k_map.port = (unsigned char) u_map->port; |
| 389 | 443 | |
| 390 | 444 | err = dev->set_config(dev, &k_map); |
| 445 | + if (err < 0) | |
| 446 | + goto errout_dev; | |
| 391 | 447 | |
| 392 | − if (err) | |
| 393 | − goto out; | |
| 448 | + modified = 1; | |
| 394 | 449 | } |
| 395 | 450 | |
| 396 | − if (ida[IFLA_ADDRESS - 1]) { | |
| 451 | + if (tb[IFLA_ADDRESS]) { | |
| 397 | 452 | struct sockaddr *sa; |
| 398 | 453 | int len; |
| 399 | 454 | |
| 400 | 455 | if (!dev->set_mac_address) { |
| 401 | 456 | err = -EOPNOTSUPP; |
| 402 | − goto out; | |
| 457 | + goto errout_dev; | |
| 403 | 458 | } |
| 459 | + | |
| 404 | 460 | if (!netif_device_present(dev)) { |
| 405 | 461 | err = -ENODEV; |
| 406 | − goto out; | |
| 462 | + goto errout_dev; | |
| 407 | 463 | } |
| 408 | − if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) | |
| 409 | − goto out; | |
| 410 | 464 | |
| 411 | 465 | len = sizeof(sa_family_t) + dev->addr_len; |
| 412 | 466 | sa = kmalloc(len, GFP_KERNEL); |
| 413 | 467 | if (!sa) { |
| 414 | 468 | err = -ENOMEM; |
| 415 | − goto out; | |
| 469 | + goto errout_dev; | |
| 416 | 470 | } |
| 417 | 471 | sa->sa_family = dev->type; |
| 418 | − memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]), | |
| 472 | + memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), | |
| 419 | 473 | dev->addr_len); |
| 420 | 474 | err = dev->set_mac_address(dev, sa); |
| 421 | 475 | kfree(sa); |
| 422 | 476 | if (err) |
| 423 | − goto out; | |
| 477 | + goto errout_dev; | |
| 424 | 478 | send_addr_notify = 1; |
| 479 | + modified = 1; | |
| 425 | 480 | } |
| 426 | 481 | |
| 427 | − if (ida[IFLA_BROADCAST - 1]) { | |
| 428 | − if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len)) | |
| 429 | − goto out; | |
| 430 | − memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]), | |
| 431 | − dev->addr_len); | |
| 432 | − send_addr_notify = 1; | |
| 482 | + if (tb[IFLA_MTU]) { | |
| 483 | + err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); | |
| 484 | + if (err < 0) | |
| 485 | + goto errout_dev; | |
| 486 | + modified = 1; | |
| 433 | 487 | } |
| 434 | 488 | |
| 435 | − if (ida[IFLA_MTU - 1]) { | |
| 436 | − if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32))) | |
| 437 | − goto out; | |
| 438 | − err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1]))); | |
| 439 | − | |
| 440 | − if (err) | |
| 441 | − goto out; | |
| 442 | − | |
| 489 | + /* | |
| 490 | + * Interface selected by interface index but interface | |
| 491 | + * name provided implies that a name change has been | |
| 492 | + * requested. | |
| 493 | + */ | |
| 494 | + if (ifm->ifi_index >= 0 && ifname[0]) { | |
| 495 | + err = dev_change_name(dev, ifname); | |
| 496 | + if (err < 0) | |
| 497 | + goto errout_dev; | |
| 498 | + modified = 1; | |
| 443 | 499 | } |
| 444 | 500 | |
| 445 | − if (ida[IFLA_TXQLEN - 1]) { | |
| 446 | − if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32))) | |
| 447 | − goto out; | |
| 501 | +#ifdef CONFIG_NET_WIRELESS_RTNETLINK | |
| 502 | + if (tb[IFLA_WIRELESS]) { | |
| 503 | + /* Call Wireless Extensions. | |
| 504 | + * Various stuff checked in there... */ | |
| 505 | + err = wireless_rtnetlink_set(dev, nla_data(tb[IFLA_WIRELESS]), | |
| 506 | + nla_len(tb[IFLA_WIRELESS])); | |
| 507 | + if (err < 0) | |
| 508 | + goto errout_dev; | |
| 509 | + } | |
| 510 | +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ | |
| 448 | 511 | |
| 449 | − dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1])); | |
| 512 | + if (tb[IFLA_BROADCAST]) { | |
| 513 | + nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); | |
| 514 | + send_addr_notify = 1; | |
| 450 | 515 | } |
| 451 | 516 | |
| 452 | − if (ida[IFLA_WEIGHT - 1]) { | |
| 453 | − if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32))) | |
| 454 | − goto out; | |
| 455 | 517 | |
| 456 | − dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1])); | |
| 457 | − } | |
| 518 | + if (ifm->ifi_flags) | |
| 519 | + dev_change_flags(dev, ifm->ifi_flags); | |
| 458 | 520 | |
| 459 | − if (ida[IFLA_OPERSTATE - 1]) { | |
| 460 | − if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) | |
| 461 | − goto out; | |
| 521 | + if (tb[IFLA_TXQLEN]) | |
| 522 | + dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); | |
| 462 | 523 | |
| 463 | − set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1]))); | |
| 464 | − } | |
| 524 | + if (tb[IFLA_WEIGHT]) | |
| 525 | + dev->weight = nla_get_u32(tb[IFLA_WEIGHT]); | |
| 465 | 526 | |
| 466 | − if (ida[IFLA_LINKMODE - 1]) { | |
| 467 | − if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) | |
| 468 | − goto out; | |
| 527 | + if (tb[IFLA_OPERSTATE]) | |
| 528 | + set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); | |
| 469 | 529 | |
| 530 | + if (tb[IFLA_LINKMODE]) { | |
| 470 | 531 | write_lock_bh(&dev_base_lock); |
| 471 | − dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1])); | |
| 532 | + dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); | |
| 472 | 533 | write_unlock_bh(&dev_base_lock); |
| 473 | 534 | } |
| 474 | 535 | |
| 475 | − if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) { | |
| 476 | − char ifname[IFNAMSIZ]; | |
| 477 | − | |
| 478 | − if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1], | |
| 479 | − IFNAMSIZ) >= IFNAMSIZ) | |
| 480 | − goto out; | |
| 481 | − err = dev_change_name(dev, ifname); | |
| 482 | − if (err) | |
| 483 | − goto out; | |
| 484 | − } | |
| 485 | − | |
| 486 | −#ifdef CONFIG_NET_WIRELESS_RTNETLINK | |
| 487 | − if (ida[IFLA_WIRELESS - 1]) { | |
| 488 | − | |
| 489 | − /* Call Wireless Extensions. | |
| 490 | − * Various stuff checked in there... */ | |
| 491 | − err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len); | |
| 492 | − if (err) | |
| 493 | − goto out; | |
| 494 | − } | |
| 495 | −#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ | |
| 496 | − | |
| 497 | 536 | err = 0; |
| 498 | 537 | |
| 499 | −out: | |
| 538 | +errout_dev: | |
| 539 | + if (err < 0 && modified && net_ratelimit()) | |
| 540 | + printk(KERN_WARNING "A link change request failed with " | |
| 541 | + "some changes comitted already. Interface %s may " | |
| 542 | + "have been left with an inconsistent configuration, " | |
| 543 | + "please check.\n", dev->name); | |
| 544 | + | |
| 500 | 545 | if (send_addr_notify) |
| 501 | 546 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
| 502 | 547 | |
| 503 | 548 | dev_put(dev); |
| 549 | +errout: | |
| 504 | 550 | return err; |
| 505 | 551 | } |
| 506 | 552 | |
| 507 | −#ifdef CONFIG_NET_WIRELESS_RTNETLINK | |
| 508 | −static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg) | |
| 553 | +static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |
| 509 | 554 | { |
| 510 | − struct ifinfomsg *ifm = NLMSG_DATA(in_nlh); | |
| 511 | − struct rtattr **ida = arg; | |
| 512 | − struct net_device *dev; | |
| 513 | − struct ifinfomsg *r; | |
| 514 | − struct nlmsghdr *nlh; | |
| 515 | − int err = -ENOBUFS; | |
| 516 | − struct sk_buff *skb; | |
| 517 | − unsigned char *b; | |
| 518 | − char *iw_buf = NULL; | |
| 555 | + struct ifinfomsg *ifm; | |
| 556 | + struct nlattr *tb[IFLA_MAX+1]; | |
| 557 | + struct net_device *dev = NULL; | |
| 558 | + struct sk_buff *nskb; | |
| 559 | + char *iw_buf = NULL, *iw = NULL; | |
| 519 | 560 | int iw_buf_len = 0; |
| 561 | + int err, payload; | |
| 520 | 562 | |
| 521 | − if (ifm->ifi_index >= 0) | |
| 563 | + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | |
| 564 | + if (err < 0) | |
| 565 | + goto errout; | |
| 566 | + | |
| 567 | + ifm = nlmsg_data(nlh); | |
| 568 | + if (ifm->ifi_index >= 0) { | |
| 522 | 569 | dev = dev_get_by_index(ifm->ifi_index); |
| 523 | − else | |
| 570 | + if (dev == NULL) | |
| 571 | + return -ENODEV; | |
| 572 | + } else | |
| 524 | 573 | return -EINVAL; |
| 525 | − if (!dev) | |
| 526 | − return -ENODEV; | |
| 527 | 574 | |
| 528 | −#ifdef CONFIG_NET_WIRELESS_RTNETLINK | |
| 529 | − if (ida[IFLA_WIRELESS - 1]) { | |
| 530 | 575 | |
| 576 | +#ifdef CONFIG_NET_WIRELESS_RTNETLINK | |
| 577 | + if (tb[IFLA_WIRELESS]) { | |
| 531 | 578 | /* Call Wireless Extensions. We need to know the size before |
| 532 | 579 | * we can alloc. Various stuff checked in there... */ |
| 533 | − err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len); | |
| 534 | − if (err) | |
| 535 | − goto out; | |
| 580 | + err = wireless_rtnetlink_get(dev, nla_data(tb[IFLA_WIRELESS]), | |
| 581 | + nla_len(tb[IFLA_WIRELESS]), | |
| 582 | + &iw_buf, &iw_buf_len); | |
| 583 | + if (err < 0) | |
| 584 | + goto errout; | |
| 585 | + | |
| 586 | + iw += IW_EV_POINT_OFF; | |
| 536 | 587 | } |
| 537 | 588 | #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ |
| 538 | 589 | |
| 539 | − /* Create a skb big enough to include all the data. | |
| 540 | − * Some requests are way bigger than 4k... Jean II */ | |
| 541 | − skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)), | |
| 542 | − GFP_KERNEL); | |
| 543 | − if (!skb) | |
| 544 | − goto out; | |
| 545 | − b = skb->tail; | |
| 546 | − | |
| 547 | − /* Put in the message the usual good stuff */ | |
| 548 | − nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq, | |
| 549 | − RTM_NEWLINK, sizeof(*r)); | |
| 550 | − r = NLMSG_DATA(nlh); | |
| 551 | − r->ifi_family = AF_UNSPEC; | |
| 552 | − r->__ifi_pad = 0; | |
| 553 | − r->ifi_type = dev->type; | |
| 554 | − r->ifi_index = dev->ifindex; | |
| 555 | − r->ifi_flags = dev->flags; | |
| 556 | − r->ifi_change = 0; | |
| 557 | − | |
| 558 | − /* Put the wireless payload if it exist */ | |
| 559 | − if(iw_buf != NULL) | |
| 560 | − RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len, | |
| 561 | − iw_buf + IW_EV_POINT_OFF); | |
| 562 | − | |
| 563 | − nlh->nlmsg_len = skb->tail - b; | |
| 564 | − | |
| 565 | − /* Needed ? */ | |
| 566 | − NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; | |
| 567 | − | |
| 568 | − err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); | |
| 569 | − if (err > 0) | |
| 570 | − err = 0; | |
| 571 | −out: | |
| 572 | − if(iw_buf != NULL) | |
| 573 | − kfree(iw_buf); | |
| 590 | + payload = NLMSG_ALIGN(sizeof(struct ifinfomsg) + | |
| 591 | + nla_total_size(iw_buf_len)); | |
| 592 | + nskb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL); | |
| 593 | + if (nskb == NULL) { | |
| 594 | + err = -ENOBUFS; | |
| 595 | + goto errout; | |
| 596 | + } | |
| 597 | + | |
| 598 | + err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK, | |
| 599 | + NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0); | |
| 600 | + if (err <= 0) { | |
| 601 | + kfree_skb(nskb); | |
| 602 | + goto errout; | |
| 603 | + } | |
| 604 | + | |
| 605 | + err = rtnl_unicast(skb, NETLINK_CB(skb).pid); | |
| 606 | +errout: | |
| 607 | + kfree(iw_buf); | |
| 574 | 608 | dev_put(dev); |
| 575 | − return err; | |
| 576 | 609 | |
| 577 | −rtattr_failure: | |
| 578 | −nlmsg_failure: | |
| 579 | − kfree_skb(skb); | |
| 580 | − goto out; | |
| 610 | + return err; | |
| 581 | 611 | } |
| 582 | −#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ | |
| 583 | 612 | |
| 584 | −static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | |
| 613 | +static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | |
| 585 | 614 | { |
| 586 | 615 | int idx; |
| 587 | 616 | int s_idx = cb->family; |
| @@ -608,20 +637,22 @@ static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) · 20 unmodified lines | ||
| 608 | 637 | void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) |
| 609 | 638 | { |
| 610 | 639 | struct sk_buff *skb; |
| 611 | − int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + | |
| 612 | − sizeof(struct rtnl_link_ifmap) + | |
| 613 | − sizeof(struct rtnl_link_stats) + 128); | |
| 640 | + int err = -ENOBUFS; | |
| 614 | 641 | |
| 615 | − skb = alloc_skb(size, GFP_KERNEL); | |
| 616 | − if (!skb) | |
| 617 | − return; | |
| 642 | + skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | |
| 643 | + if (skb == NULL) | |
| 644 | + goto errout; | |
| 618 | 645 | |
| 619 | − if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change, 0) < 0) { | |
| 646 | + err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0); | |
| 647 | + if (err < 0) { | |
| 620 | 648 | kfree_skb(skb); |
| 621 | − return; | |
| 649 | + goto errout; | |
| 622 | 650 | } |
| 623 | − NETLINK_CB(skb).dst_group = RTNLGRP_LINK; | |
| 624 | − netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_KERNEL); | |
| 651 | + | |
| 652 | + err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); | |
| 653 | +errout: | |
| 654 | + if (err < 0) | |
| 655 | + rtnl_set_sk_err(RTNLGRP_LINK, err); | |
| 625 | 656 | } |
| 626 | 657 | |
| 627 | 658 | /* Protected by RTNL sempahore. */ |
| @@ -746,18 +777,19 @@ static void rtnetlink_rcv(struct sock *sk, int len) · 118 unmodified lines | ||
| 746 | 777 | |
| 747 | 778 | static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = |
| 748 | 779 | { |
| 749 | − [RTM_GETLINK - RTM_BASE] = { | |
| 750 | −#ifdef CONFIG_NET_WIRELESS_RTNETLINK | |
| 751 | − .doit = do_getlink, | |
| 752 | −#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ | |
| 753 | − .dumpit = rtnetlink_dump_ifinfo }, | |
| 754 | − [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, | |
| 755 | − [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, | |
| 756 | − [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, | |
| 780 | + [RTM_GETLINK - RTM_BASE] = { .doit = rtnl_getlink, | |
| 781 | + .dumpit = rtnl_dump_ifinfo }, | |
| 782 | + [RTM_SETLINK - RTM_BASE] = { .doit = rtnl_setlink }, | |
| 783 | + [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnl_dump_all }, | |
| 784 | + [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnl_dump_all }, | |
| 757 | 785 | [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add }, |
| 758 | 786 | [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete }, |
| 759 | 787 | [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info }, |
| 760 | − [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, | |
| 788 | +#ifdef CONFIG_FIB_RULES | |
| 789 | + [RTM_NEWRULE - RTM_BASE] = { .doit = fib_nl_newrule }, | |
| 790 | + [RTM_DELRULE - RTM_BASE] = { .doit = fib_nl_delrule }, | |
| 791 | +#endif | |
| 792 | + [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnl_dump_all }, | |
| 761 | 793 | [RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info }, |
| 762 | 794 | [RTM_SETNEIGHTBL - RTM_BASE] = { .doit = neightbl_set }, |
| 763 | 795 | }; |
| @@ -817,7 +849,9 @@ EXPORT_SYMBOL(rtattr_strlcpy); · 53 unmodified lines | ||
| 817 | 849 | EXPORT_SYMBOL(rtattr_parse); |
| 818 | 850 | EXPORT_SYMBOL(rtnetlink_links); |
| 819 | 851 | EXPORT_SYMBOL(rtnetlink_put_metrics); |
| 820 | −EXPORT_SYMBOL(rtnl); | |
| 821 | 852 | EXPORT_SYMBOL(rtnl_lock); |
| 822 | 853 | EXPORT_SYMBOL(rtnl_trylock); |
| 823 | 854 | EXPORT_SYMBOL(rtnl_unlock); |
| 855 | +EXPORT_SYMBOL(rtnl_unicast); | |
| 856 | +EXPORT_SYMBOL(rtnl_notify); | |
| 857 | +EXPORT_SYMBOL(rtnl_set_sk_err); | |
| @@ -1397,7 +1397,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) · 1396 unmodified lines | ||
| 1397 | 1397 | unsigned int csum; |
| 1398 | 1398 | long csstart; |
| 1399 | 1399 | |
| 1400 | − if (skb->ip_summed == CHECKSUM_HW) | |
| 1400 | + if (skb->ip_summed == CHECKSUM_PARTIAL) | |
| 1401 | 1401 | csstart = skb->h.raw - skb->data; |
| 1402 | 1402 | else |
| 1403 | 1403 | csstart = skb_headlen(skb); |
| @@ -1411,7 +1411,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) · 7 unmodified lines | ||
| 1411 | 1411 | csum = skb_copy_and_csum_bits(skb, csstart, to + csstart, |
| 1412 | 1412 | skb->len - csstart, 0); |
| 1413 | 1413 | |
| 1414 | − if (skb->ip_summed == CHECKSUM_HW) { | |
| 1414 | + if (skb->ip_summed == CHECKSUM_PARTIAL) { | |
| 1415 | 1415 | long csstuff = csstart + skb->csum; |
| 1416 | 1416 | |
| 1417 | 1417 | *((unsigned short *)(to + csstuff)) = csum_fold(csum); |
| @@ -1898,10 +1898,10 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, · 480 unmodified lines | ||
| 1898 | 1898 | * @len: length of data pulled |
| 1899 | 1899 | * |
| 1900 | 1900 | * This function performs an skb_pull on the packet and updates |
| 1901 | − * update the CHECKSUM_HW checksum. It should be used on receive | |
| 1902 | − * path processing instead of skb_pull unless you know that the | |
| 1903 | − * checksum difference is zero (e.g., a valid IP header) or you | |
| 1904 | − * are setting ip_summed to CHECKSUM_NONE. | |
| 1901 | + * update the CHECKSUM_COMPLETE checksum. It should be used on | |
| 1902 | + * receive path processing instead of skb_pull unless you know | |
| 1903 | + * that the checksum difference is zero (e.g., a valid IP header) | |
| 1904 | + * or you are setting ip_summed to CHECKSUM_NONE. | |
| 1905 | 1905 | */ |
| 1906 | 1906 | unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) |
| 1907 | 1907 | { |
| @@ -1994,7 +1994,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) · 86 unmodified lines | ||
| 1994 | 1994 | frag = skb_shinfo(nskb)->frags; |
| 1995 | 1995 | k = 0; |
| 1996 | 1996 | |
| 1997 | − nskb->ip_summed = CHECKSUM_HW; | |
| 1997 | + nskb->ip_summed = CHECKSUM_PARTIAL; | |
| 1998 | 1998 | nskb->csum = skb->csum; |
| 1999 | 1999 | memcpy(skb_put(nskb, hsize), skb->data + offset, hsize); |
| 2000 | 2000 | |
| @@ -2046,19 +2046,14 @@ void __init skb_init(void) · 45 unmodified lines | ||
| 2046 | 2046 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", |
| 2047 | 2047 | sizeof(struct sk_buff), |
| 2048 | 2048 | 0, |
| 2049 | − SLAB_HWCACHE_ALIGN, | |
| 2049 | + SLAB_HWCACHE_ALIGN|SLAB_PANIC, | |
| 2050 | 2050 | NULL, NULL); |
| 2051 | − if (!skbuff_head_cache) | |
| 2052 | − panic("cannot create skbuff cache"); | |
| 2053 | − | |
| 2054 | 2051 | skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache", |
| 2055 | 2052 | (2*sizeof(struct sk_buff)) + |
| 2056 | 2053 | sizeof(atomic_t), |
| 2057 | 2054 | 0, |
| 2058 | − SLAB_HWCACHE_ALIGN, | |
| 2055 | + SLAB_HWCACHE_ALIGN|SLAB_PANIC, | |
| 2059 | 2056 | NULL, NULL); |
| 2060 | − if (!skbuff_fclone_cache) | |
| 2061 | − panic("cannot create skbuff cache"); | |
| 2062 | 2057 | } |
| 2063 | 2058 | |
| 2064 | 2059 | EXPORT_SYMBOL(___pskb_trim); |
| @@ -187,13 +187,13 @@ static struct lock_class_key af_callback_keys[AF_MAX]; · 186 unmodified lines | ||
| 187 | 187 | #define SK_RMEM_MAX (_SK_MEM_OVERHEAD * _SK_MEM_PACKETS) |
| 188 | 188 | |
| 189 | 189 | /* Run time adjustable parameters. */ |
| 190 | −__u32 sysctl_wmem_max = SK_WMEM_MAX; | |
| 191 | −__u32 sysctl_rmem_max = SK_RMEM_MAX; | |
| 192 | −__u32 sysctl_wmem_default = SK_WMEM_MAX; | |
| 193 | −__u32 sysctl_rmem_default = SK_RMEM_MAX; | |
| 190 | +__u32 sysctl_wmem_max __read_mostly = SK_WMEM_MAX; | |
| 191 | +__u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX; | |
| 192 | +__u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; | |
| 193 | +__u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; | |
| 194 | 194 | |
| 195 | 195 | /* Maximal space eaten by iovec or ancilliary data plus some space */ |
| 196 | −int sysctl_optmem_max = sizeof(unsigned long)*(2*UIO_MAXIOV + 512); | |
| 196 | +int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); | |
| 197 | 197 | |
| 198 | 198 | static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen) |
| 199 | 199 | { |
| @@ -247,11 +247,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) · 47 unmodified lines | ||
| 247 | 247 | goto out; |
| 248 | 248 | } |
| 249 | 249 | |
| 250 | − /* It would be deadlock, if sock_queue_rcv_skb is used | |
| 251 | − with socket lock! We assume that users of this | |
| 252 | − function are lock free. | |
| 253 | − */ | |
| 254 | − err = sk_filter(sk, skb, 1); | |
| 250 | + err = sk_filter(sk, skb); | |
| 255 | 251 | if (err) |
| 256 | 252 | goto out; |
| 257 | 253 | |
| @@ -278,7 +274,7 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb) · 20 unmodified lines | ||
| 278 | 274 | { |
| 279 | 275 | int rc = NET_RX_SUCCESS; |
| 280 | 276 | |
| 281 | − if (sk_filter(sk, skb, 0)) | |
| 277 | + if (sk_filter(sk, skb)) | |
| 282 | 278 | goto discard_and_relse; |
| 283 | 279 | |
| 284 | 280 | skb->dev = NULL; |
| @@ -606,15 +602,15 @@ set_rcvbuf: · 321 unmodified lines | ||
| 606 | 602 | break; |
| 607 | 603 | |
| 608 | 604 | case SO_DETACH_FILTER: |
| 609 | − spin_lock_bh(&sk->sk_lock.slock); | |
| 610 | − filter = sk->sk_filter; | |
| 605 | + rcu_read_lock_bh(); | |
| 606 | + filter = rcu_dereference(sk->sk_filter); | |
| 611 | 607 | if (filter) { |
| 612 | − sk->sk_filter = NULL; | |
| 613 | − spin_unlock_bh(&sk->sk_lock.slock); | |
| 608 | + rcu_assign_pointer(sk->sk_filter, NULL); | |
| 614 | 609 | sk_filter_release(sk, filter); |
| 610 | + rcu_read_unlock_bh(); | |
| 615 | 611 | break; |
| 616 | 612 | } |
| 617 | − spin_unlock_bh(&sk->sk_lock.slock); | |
| 613 | + rcu_read_unlock_bh(); | |
| 618 | 614 | ret = -ENONET; |
| 619 | 615 | break; |
| 620 | 616 | |
| @@ -884,10 +880,10 @@ void sk_free(struct sock *sk) · 263 unmodified lines | ||
| 884 | 880 | if (sk->sk_destruct) |
| 885 | 881 | sk->sk_destruct(sk); |
| 886 | 882 | |
| 887 | − filter = sk->sk_filter; | |
| 883 | + filter = rcu_dereference(sk->sk_filter); | |
| 888 | 884 | if (filter) { |
| 889 | 885 | sk_filter_release(sk, filter); |
| 890 | − sk->sk_filter = NULL; | |
| 886 | + rcu_assign_pointer(sk->sk_filter, NULL); | |
| 891 | 887 | } |
| 892 | 888 | |
| 893 | 889 | sock_disable_timestamp(sk); |
| @@ -911,7 +907,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) · 17 unmodified lines | ||
| 911 | 907 | if (newsk != NULL) { |
| 912 | 908 | struct sk_filter *filter; |
| 913 | 909 | |
| 914 | − memcpy(newsk, sk, sk->sk_prot->obj_size); | |
| 910 | + sock_copy(newsk, sk); | |
| 915 | 911 | |
| 916 | 912 | /* SANITY */ |
| 917 | 913 | sk_node_init(&newsk->sk_node); |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | * Authors: |
| 5 | 5 | * net_random Alan Cox |
| 6 | 6 | * net_ratelimit Andy Kleen |
| 7 | + * in{4,6}_pton YOSHIFUJI Hideaki, Copyright (C)2006 USAGI/WIDE Project | |
| 7 | 8 | * |
| 8 | 9 | * Created by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> |
| 9 | 10 | * |
| @@ -191,3 +192,215 @@ __be32 in_aton(const char *str) · 181 unmodified lines | ||
| 191 | 192 | } |
| 192 | 193 | |
| 193 | 194 | EXPORT_SYMBOL(in_aton); |
| 195 | + | |
| 196 | +#define IN6PTON_XDIGIT 0x00010000 | |
| 197 | +#define IN6PTON_DIGIT 0x00020000 | |
| 198 | +#define IN6PTON_COLON_MASK 0x00700000 | |
| 199 | +#define IN6PTON_COLON_1 0x00100000 /* single : requested */ | |
| 200 | +#define IN6PTON_COLON_2 0x00200000 /* second : requested */ | |
| 201 | +#define IN6PTON_COLON_1_2 0x00400000 /* :: requested */ | |
| 202 | +#define IN6PTON_DOT 0x00800000 /* . */ | |
| 203 | +#define IN6PTON_DELIM 0x10000000 | |
| 204 | +#define IN6PTON_NULL 0x20000000 /* first/tail */ | |
| 205 | +#define IN6PTON_UNKNOWN 0x40000000 | |
| 206 | + | |
| 207 | +static inline int digit2bin(char c, char delim) | |
| 208 | +{ | |
| 209 | + if (c == delim || c == '\0') | |
| 210 | + return IN6PTON_DELIM; | |
| 211 | + if (c == '.') | |
| 212 | + return IN6PTON_DOT; | |
| 213 | + if (c >= '0' && c <= '9') | |
| 214 | + return (IN6PTON_DIGIT | (c - '0')); | |
| 215 | + return IN6PTON_UNKNOWN; | |
| 216 | +} | |
| 217 | + | |
| 218 | +static inline int xdigit2bin(char c, char delim) | |
| 219 | +{ | |
| 220 | + if (c == delim || c == '\0') | |
| 221 | + return IN6PTON_DELIM; | |
| 222 | + if (c == ':') | |
| 223 | + return IN6PTON_COLON_MASK; | |
| 224 | + if (c == '.') | |
| 225 | + return IN6PTON_DOT; | |
| 226 | + if (c >= '0' && c <= '9') | |
| 227 | + return (IN6PTON_XDIGIT | IN6PTON_DIGIT| (c - '0')); | |
| 228 | + if (c >= 'a' && c <= 'f') | |
| 229 | + return (IN6PTON_XDIGIT | (c - 'a' + 10)); | |
| 230 | + if (c >= 'A' && c <= 'F') | |
| 231 | + return (IN6PTON_XDIGIT | (c - 'A' + 10)); | |
| 232 | + return IN6PTON_UNKNOWN; | |
| 233 | +} | |
| 234 | + | |
| 235 | +int in4_pton(const char *src, int srclen, | |
| 236 | + u8 *dst, | |
| 237 | + char delim, const char **end) | |
| 238 | +{ | |
| 239 | + const char *s; | |
| 240 | + u8 *d; | |
| 241 | + u8 dbuf[4]; | |
| 242 | + int ret = 0; | |
| 243 | + int i; | |
| 244 | + int w = 0; | |
| 245 | + | |
| 246 | + if (srclen < 0) | |
| 247 | + srclen = strlen(src); | |
| 248 | + s = src; | |
| 249 | + d = dbuf; | |
| 250 | + i = 0; | |
| 251 | + while(1) { | |
| 252 | + int c; | |
| 253 | + c = xdigit2bin(srclen > 0 ? *s : '\0', delim); | |
| 254 | + if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM))) { | |
| 255 | + goto out; | |
| 256 | + } | |
| 257 | + if (c & (IN6PTON_DOT | IN6PTON_DELIM)) { | |
| 258 | + if (w == 0) | |
| 259 | + goto out; | |
| 260 | + *d++ = w & 0xff; | |
| 261 | + w = 0; | |
| 262 | + i++; | |
| 263 | + if (c & IN6PTON_DELIM) { | |
| 264 | + if (i != 4) | |
| 265 | + goto out; | |
| 266 | + break; | |
| 267 | + } | |
| 268 | + goto cont; | |
| 269 | + } | |
| 270 | + w = (w * 10) + c; | |
| 271 | + if ((w & 0xffff) > 255) { | |
| 272 | + goto out; | |
| 273 | + } | |
| 274 | +cont: | |
| 275 | + if (i >= 4) | |
| 276 | + goto out; | |
| 277 | + s++; | |
| 278 | + srclen--; | |
| 279 | + } | |
| 280 | + ret = 1; | |
| 281 | + memcpy(dst, dbuf, sizeof(dbuf)); | |
| 282 | +out: | |
| 283 | + if (end) | |
| 284 | + *end = s; | |
| 285 | + return ret; | |
| 286 | +} | |
| 287 | + | |
| 288 | +EXPORT_SYMBOL(in4_pton); | |
| 289 | + | |
| 290 | +int in6_pton(const char *src, int srclen, | |
| 291 | + u8 *dst, | |
| 292 | + char delim, const char **end) | |
| 293 | +{ | |
| 294 | + const char *s, *tok = NULL; | |
| 295 | + u8 *d, *dc = NULL; | |
| 296 | + u8 dbuf[16]; | |
| 297 | + int ret = 0; | |
| 298 | + int i; | |
| 299 | + int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL; | |
| 300 | + int w = 0; | |
| 301 | + | |
| 302 | + memset(dbuf, 0, sizeof(dbuf)); | |
| 303 | + | |
| 304 | + s = src; | |
| 305 | + d = dbuf; | |
| 306 | + if (srclen < 0) | |
| 307 | + srclen = strlen(src); | |
| 308 | + | |
| 309 | + while (1) { | |
| 310 | + int c; | |
| 311 | + | |
| 312 | + c = xdigit2bin(srclen > 0 ? *s : '\0', delim); | |
| 313 | + if (!(c & state)) | |
| 314 | + goto out; | |
| 315 | + if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) { | |
| 316 | + /* process one 16-bit word */ | |
| 317 | + if (!(state & IN6PTON_NULL)) { | |
| 318 | + *d++ = (w >> 8) & 0xff; | |
| 319 | + *d++ = w & 0xff; | |
| 320 | + } | |
| 321 | + w = 0; | |
| 322 | + if (c & IN6PTON_DELIM) { | |
| 323 | + /* We've processed last word */ | |
| 324 | + break; | |
| 325 | + } | |
| 326 | + /* | |
| 327 | + * COLON_1 => XDIGIT | |
| 328 | + * COLON_2 => XDIGIT|DELIM | |
| 329 | + * COLON_1_2 => COLON_2 | |
| 330 | + */ | |
| 331 | + switch (state & IN6PTON_COLON_MASK) { | |
| 332 | + case IN6PTON_COLON_2: | |
| 333 | + dc = d; | |
| 334 | + state = IN6PTON_XDIGIT | IN6PTON_DELIM; | |
| 335 | + if (dc - dbuf >= sizeof(dbuf)) | |
| 336 | + state |= IN6PTON_NULL; | |
| 337 | + break; | |
| 338 | + case IN6PTON_COLON_1|IN6PTON_COLON_1_2: | |
| 339 | + state = IN6PTON_XDIGIT | IN6PTON_COLON_2; | |
| 340 | + break; | |
| 341 | + case IN6PTON_COLON_1: | |
| 342 | + state = IN6PTON_XDIGIT; | |
| 343 | + break; | |
| 344 | + case IN6PTON_COLON_1_2: | |
| 345 | + state = IN6PTON_COLON_2; | |
| 346 | + break; | |
| 347 | + default: | |
| 348 | + state = 0; | |
| 349 | + } | |
| 350 | + tok = s + 1; | |
| 351 | + goto cont; | |
| 352 | + } | |
| 353 | + | |
| 354 | + if (c & IN6PTON_DOT) { | |
| 355 | + ret = in4_pton(tok ? tok : s, srclen + (int)(s - tok), d, delim, &s); | |
| 356 | + if (ret > 0) { | |
| 357 | + d += 4; | |
| 358 | + break; | |
| 359 | + } | |
| 360 | + goto out; | |
| 361 | + } | |
| 362 | + | |
| 363 | + w = (w << 4) | (0xff & c); | |
| 364 | + state = IN6PTON_COLON_1 | IN6PTON_DELIM; | |
| 365 | + if (!(w & 0xf000)) { | |
| 366 | + state |= IN6PTON_XDIGIT; | |
| 367 | + } | |
| 368 | + if (!dc && d + 2 < dbuf + sizeof(dbuf)) { | |
| 369 | + state |= IN6PTON_COLON_1_2; | |
| 370 | + state &= ~IN6PTON_DELIM; | |
| 371 | + } | |
| 372 | + if (d + 2 >= dbuf + sizeof(dbuf)) { | |
| 373 | + state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2); | |
| 374 | + } | |
| 375 | +cont: | |
| 376 | + if ((dc && d + 4 < dbuf + sizeof(dbuf)) || | |
| 377 | + d + 4 == dbuf + sizeof(dbuf)) { | |
| 378 | + state |= IN6PTON_DOT; | |
| 379 | + } | |
| 380 | + if (d >= dbuf + sizeof(dbuf)) { | |
| 381 | + state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK); | |
| 382 | + } | |
| 383 | + s++; | |
| 384 | + srclen--; | |
| 385 | + } | |
| 386 | + | |
| 387 | + i = 15; d--; | |
| 388 | + | |
| 389 | + if (dc) { | |
| 390 | + while(d >= dc) | |
| 391 | + dst[i--] = *d--; | |
| 392 | + while(i >= dc - dbuf) | |
| 393 | + dst[i--] = 0; | |
| 394 | + while(i >= 0) | |
| 395 | + dst[i--] = *d--; | |
| 396 | + } else | |
| 397 | + memcpy(dst, dbuf, sizeof(dbuf)); | |
| 398 | + | |
| 399 | + ret = 1; | |
| 400 | +out: | |
| 401 | + if (end) | |
| 402 | + *end = s; | |
| 403 | + return ret; | |
| 404 | +} | |
| 405 | + | |
| 406 | +EXPORT_SYMBOL(in6_pton); | |
| @@ -72,7 +72,6 @@ · 71 unmodified lines | ||
| 72 | 72 | |
| 73 | 73 | /***************************** INCLUDES *****************************/ |
| 74 | 74 | |
| 75 | −#include <linux/config.h> /* Not needed ??? */ | |
| 76 | 75 | #include <linux/module.h> |
| 77 | 76 | #include <linux/types.h> /* off_t */ |
| 78 | 77 | #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */ |
| @@ -86,6 +85,7 @@ · 7 unmodified lines | ||
| 86 | 85 | |
| 87 | 86 | #include <linux/wireless.h> /* Pretty obvious */ |
| 88 | 87 | #include <net/iw_handler.h> /* New driver API */ |
| 88 | +#include <net/netlink.h> | |
| 89 | 89 | |
| 90 | 90 | #include <asm/uaccess.h> /* copy_to_user() */ |
| 91 | 91 | |
| @@ -1850,7 +1850,7 @@ static void wireless_nlevent_process(unsigned long data) · 1758 unmodified lines | ||
| 1850 | 1850 | struct sk_buff *skb; |
| 1851 | 1851 | |
| 1852 | 1852 | while ((skb = skb_dequeue(&wireless_nlevent_queue))) |
| 1853 | − netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); | |
| 1853 | + rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); | |
| 1854 | 1854 | } |
| 1855 | 1855 | |
| 1856 | 1856 | static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0); |
| @@ -142,14 +142,13 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority) · 141 unmodified lines | ||
| 142 | 142 | struct dccp_ackvec *av = kmem_cache_alloc(dccp_ackvec_slab, priority); |
| 143 | 143 | |
| 144 | 144 | if (av != NULL) { |
| 145 | − av->dccpav_buf_head = | |
| 146 | − av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1; | |
| 145 | + av->dccpav_buf_head = DCCP_MAX_ACKVEC_LEN - 1; | |
| 147 | 146 | av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1; |
| 148 | 147 | av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0; |
| 149 | 148 | av->dccpav_ack_ptr = 0; |
| 150 | 149 | av->dccpav_time.tv_sec = 0; |
| 151 | 150 | av->dccpav_time.tv_usec = 0; |
| 152 | − av->dccpav_sent_len = av->dccpav_vec_len = 0; | |
| 151 | + av->dccpav_vec_len = 0; | |
| 153 | 152 | INIT_LIST_HEAD(&av->dccpav_records); |
| 154 | 153 | } |
| 155 | 154 | |
| @@ -353,11 +352,13 @@ static void dccp_ackvec_throw_record(struct dccp_ackvec *av, · 197 unmodified lines | ||
| 353 | 352 | { |
| 354 | 353 | struct dccp_ackvec_record *next; |
| 355 | 354 | |
| 356 | − av->dccpav_buf_tail = avr->dccpavr_ack_ptr - 1; | |
| 357 | − if (av->dccpav_buf_tail == 0) | |
| 358 | − av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1; | |
| 359 | − | |
| 360 | − av->dccpav_vec_len -= avr->dccpavr_sent_len; | |
| 355 | + /* sort out vector length */ | |
| 356 | + if (av->dccpav_buf_head <= avr->dccpavr_ack_ptr) | |
| 357 | + av->dccpav_vec_len = avr->dccpavr_ack_ptr - av->dccpav_buf_head; | |
| 358 | + else | |
| 359 | + av->dccpav_vec_len = DCCP_MAX_ACKVEC_LEN - 1 | |
| 360 | + - av->dccpav_buf_head | |
| 361 | + + avr->dccpavr_ack_ptr; | |
| 361 | 362 | |
| 362 | 363 | /* free records */ |
| 363 | 364 | list_for_each_entry_safe_from(avr, next, &av->dccpav_records, |
| @@ -434,8 +435,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, · 70 unmodified lines | ||
| 434 | 435 | break; |
| 435 | 436 | found: |
| 436 | 437 | if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) { |
| 437 | − const u8 state = (*vector & | |
| 438 | − DCCP_ACKVEC_STATE_MASK) >> 6; | |
| 438 | + const u8 state = *vector & DCCP_ACKVEC_STATE_MASK; | |
| 439 | 439 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { |
| 440 | 440 | #ifdef CONFIG_IP_DCCP_DEBUG |
| 441 | 441 | struct dccp_sock *dp = dccp_sk(sk); |
| @@ -54,9 +54,7 @@ struct dccp_ackvec { · 53 unmodified lines | ||
| 54 | 54 | struct list_head dccpav_records; |
| 55 | 55 | struct timeval dccpav_time; |
| 56 | 56 | u8 dccpav_buf_head; |
| 57 | − u8 dccpav_buf_tail; | |
| 58 | 57 | u8 dccpav_ack_ptr; |
| 59 | − u8 dccpav_sent_len; | |
| 60 | 58 | u8 dccpav_vec_len; |
| 61 | 59 | u8 dccpav_buf_nonce; |
| 62 | 60 | u8 dccpav_ack_nonce; |
| @@ -107,7 +105,7 @@ extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb); · 44 unmodified lines | ||
| 107 | 105 | |
| 108 | 106 | static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) |
| 109 | 107 | { |
| 110 | − return av->dccpav_sent_len != av->dccpav_vec_len; | |
| 108 | + return av->dccpav_vec_len; | |
| 111 | 109 | } |
| 112 | 110 | #else /* CONFIG_IP_DCCP_ACKVEC */ |
| 113 | 111 | static inline int dccp_ackvec_init(void) |
| @@ -30,6 +30,14 @@ config IP_DCCP_CCID2 · 29 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | If in doubt, say M. |
| 32 | 32 | |
| 33 | +config IP_DCCP_CCID2_DEBUG | |
| 34 | + bool "CCID2 debug" | |
| 35 | + depends on IP_DCCP_CCID2 | |
| 36 | + ---help--- | |
| 37 | + Enable CCID2 debug messages. | |
| 38 | + | |
| 39 | + If in doubt, say N. | |
| 40 | + | |
| 33 | 41 | config IP_DCCP_CCID3 |
| 34 | 42 | tristate "CCID3 (TCP-Friendly) (EXPERIMENTAL)" |
| 35 | 43 | depends on IP_DCCP |
| @@ -27,7 +27,6 @@ · 26 unmodified lines | ||
| 27 | 27 | * |
| 28 | 28 | * BUGS: |
| 29 | 29 | * - sequence number wrapping |
| 30 | − * - jiffies wrapping | |
| 31 | 30 | */ |
| 32 | 31 | |
| 33 | 32 | #include "../ccid.h" |
| @@ -36,8 +35,7 @@ · 2 unmodified lines | ||
| 36 | 35 | |
| 37 | 36 | static int ccid2_debug; |
| 38 | 37 | |
| 39 | −#undef CCID2_DEBUG | |
| 40 | −#ifdef CCID2_DEBUG | |
| 38 | +#ifdef CONFIG_IP_DCCP_CCID2_DEBUG | |
| 41 | 39 | #define ccid2_pr_debug(format, a...) \ |
| 42 | 40 | do { if (ccid2_debug) \ |
| 43 | 41 | printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ |
| @@ -46,9 +44,7 @@ static int ccid2_debug; · 2 unmodified lines | ||
| 46 | 44 | #define ccid2_pr_debug(format, a...) |
| 47 | 45 | #endif |
| 48 | 46 | |
| 49 | −static const int ccid2_seq_len = 128; | |
| 50 | − | |
| 51 | −#ifdef CCID2_DEBUG | |
| 47 | +#ifdef CONFIG_IP_DCCP_CCID2_DEBUG | |
| 52 | 48 | static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) |
| 53 | 49 | { |
| 54 | 50 | int len = 0; |
| @@ -71,8 +67,8 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) · 16 unmodified lines | ||
| 71 | 67 | |
| 72 | 68 | /* packets are sent sequentially */ |
| 73 | 69 | BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq); |
| 74 | − BUG_ON(seqp->ccid2s_sent < prev->ccid2s_sent); | |
| 75 | − BUG_ON(len > ccid2_seq_len); | |
| 70 | + BUG_ON(time_before(seqp->ccid2s_sent, | |
| 71 | + prev->ccid2s_sent)); | |
| 76 | 72 | |
| 77 | 73 | seqp = prev; |
| 78 | 74 | } |
| @@ -84,16 +80,57 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) · 5 unmodified lines | ||
| 84 | 80 | do { |
| 85 | 81 | seqp = seqp->ccid2s_prev; |
| 86 | 82 | len++; |
| 87 | − BUG_ON(len > ccid2_seq_len); | |
| 88 | 83 | } while (seqp != hctx->ccid2hctx_seqh); |
| 89 | 84 | |
| 90 | − BUG_ON(len != ccid2_seq_len); | |
| 91 | 85 | ccid2_pr_debug("total len=%d\n", len); |
| 86 | + BUG_ON(len != hctx->ccid2hctx_seqbufc * CCID2_SEQBUF_LEN); | |
| 92 | 87 | } |
| 93 | 88 | #else |
| 94 | 89 | #define ccid2_hc_tx_check_sanity(hctx) do {} while (0) |
| 95 | 90 | #endif |
| 96 | 91 | |
| 92 | +static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num, | |
| 93 | + gfp_t gfp) | |
| 94 | +{ | |
| 95 | + struct ccid2_seq *seqp; | |
| 96 | + int i; | |
| 97 | + | |
| 98 | + /* check if we have space to preserve the pointer to the buffer */ | |
| 99 | + if (hctx->ccid2hctx_seqbufc >= (sizeof(hctx->ccid2hctx_seqbuf) / | |
| 100 | + sizeof(struct ccid2_seq*))) | |
| 101 | + return -ENOMEM; | |
| 102 | + | |
| 103 | + /* allocate buffer and initialize linked list */ | |
| 104 | + seqp = kmalloc(sizeof(*seqp) * num, gfp); | |
| 105 | + if (seqp == NULL) | |
| 106 | + return -ENOMEM; | |
| 107 | + | |
| 108 | + for (i = 0; i < (num - 1); i++) { | |
| 109 | + seqp[i].ccid2s_next = &seqp[i + 1]; | |
| 110 | + seqp[i + 1].ccid2s_prev = &seqp[i]; | |
| 111 | + } | |
| 112 | + seqp[num - 1].ccid2s_next = seqp; | |
| 113 | + seqp->ccid2s_prev = &seqp[num - 1]; | |
| 114 | + | |
| 115 | + /* This is the first allocation. Initiate the head and tail. */ | |
| 116 | + if (hctx->ccid2hctx_seqbufc == 0) | |
| 117 | + hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqt = seqp; | |
| 118 | + else { | |
| 119 | + /* link the existing list with the one we just created */ | |
| 120 | + hctx->ccid2hctx_seqh->ccid2s_next = seqp; | |
| 121 | + seqp->ccid2s_prev = hctx->ccid2hctx_seqh; | |
| 122 | + | |
| 123 | + hctx->ccid2hctx_seqt->ccid2s_prev = &seqp[num - 1]; | |
| 124 | + seqp[num - 1].ccid2s_next = hctx->ccid2hctx_seqt; | |
| 125 | + } | |
| 126 | + | |
| 127 | + /* store the original pointer to the buffer so we can free it */ | |
| 128 | + hctx->ccid2hctx_seqbuf[hctx->ccid2hctx_seqbufc] = seqp; | |
| 129 | + hctx->ccid2hctx_seqbufc++; | |
| 130 | + | |
| 131 | + return 0; | |
| 132 | +} | |
| 133 | + | |
| 97 | 134 | static int ccid2_hc_tx_send_packet(struct sock *sk, |
| 98 | 135 | struct sk_buff *skb, int len) |
| 99 | 136 | { |
| @@ -122,7 +159,7 @@ static int ccid2_hc_tx_send_packet(struct sock *sk, · 22 unmodified lines | ||
| 122 | 159 | } |
| 123 | 160 | } |
| 124 | 161 | |
| 125 | − return 100; /* XXX */ | |
| 162 | + return 1; /* XXX CCID should dequeue when ready instead of polling */ | |
| 126 | 163 | } |
| 127 | 164 | |
| 128 | 165 | static void ccid2_change_l_ack_ratio(struct sock *sk, int val) |
| @@ -150,10 +187,8 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, int val) · 21 unmodified lines | ||
| 150 | 187 | dp->dccps_l_ack_ratio = val; |
| 151 | 188 | } |
| 152 | 189 | |
| 153 | −static void ccid2_change_cwnd(struct sock *sk, int val) | |
| 190 | +static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, int val) | |
| 154 | 191 | { |
| 155 | − struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); | |
| 156 | − | |
| 157 | 192 | if (val == 0) |
| 158 | 193 | val = 1; |
| 159 | 194 | |
| @@ -164,6 +199,17 @@ static void ccid2_change_cwnd(struct sock *sk, int val) · 4 unmodified lines | ||
| 164 | 199 | hctx->ccid2hctx_cwnd = val; |
| 165 | 200 | } |
| 166 | 201 | |
| 202 | +static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hctx, long val) | |
| 203 | +{ | |
| 204 | + ccid2_pr_debug("change SRTT to %ld\n", val); | |
| 205 | + hctx->ccid2hctx_srtt = val; | |
| 206 | +} | |
| 207 | + | |
| 208 | +static void ccid2_change_pipe(struct ccid2_hc_tx_sock *hctx, long val) | |
| 209 | +{ | |
| 210 | + hctx->ccid2hctx_pipe = val; | |
| 211 | +} | |
| 212 | + | |
| 167 | 213 | static void ccid2_start_rto_timer(struct sock *sk); |
| 168 | 214 | |
| 169 | 215 | static void ccid2_hc_tx_rto_expire(unsigned long data) |
| @@ -193,11 +239,11 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) · 23 unmodified lines | ||
| 193 | 239 | ccid2_start_rto_timer(sk); |
| 194 | 240 | |
| 195 | 241 | /* adjust pipe, cwnd etc */ |
| 196 | − hctx->ccid2hctx_pipe = 0; | |
| 242 | + ccid2_change_pipe(hctx, 0); | |
| 197 | 243 | hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1; |
| 198 | 244 | if (hctx->ccid2hctx_ssthresh < 2) |
| 199 | 245 | hctx->ccid2hctx_ssthresh = 2; |
| 200 | − ccid2_change_cwnd(sk, 1); | |
| 246 | + ccid2_change_cwnd(hctx, 1); | |
| 201 | 247 | |
| 202 | 248 | /* clear state about stuff we sent */ |
| 203 | 249 | hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh; |
| @@ -232,13 +278,14 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) · 28 unmodified lines | ||
| 232 | 278 | { |
| 233 | 279 | struct dccp_sock *dp = dccp_sk(sk); |
| 234 | 280 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); |
| 281 | + struct ccid2_seq *next; | |
| 235 | 282 | u64 seq; |
| 236 | 283 | |
| 237 | 284 | ccid2_hc_tx_check_sanity(hctx); |
| 238 | 285 | |
| 239 | 286 | BUG_ON(!hctx->ccid2hctx_sendwait); |
| 240 | 287 | hctx->ccid2hctx_sendwait = 0; |
| 241 | − hctx->ccid2hctx_pipe++; | |
| 288 | + ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe + 1); | |
| 242 | 289 | BUG_ON(hctx->ccid2hctx_pipe < 0); |
| 243 | 290 | |
| 244 | 291 | /* There is an issue. What if another packet is sent between |
| @@ -251,15 +298,23 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) · 6 unmodified lines | ||
| 251 | 298 | hctx->ccid2hctx_seqh->ccid2s_seq = seq; |
| 252 | 299 | hctx->ccid2hctx_seqh->ccid2s_acked = 0; |
| 253 | 300 | hctx->ccid2hctx_seqh->ccid2s_sent = jiffies; |
| 254 | − hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next; | |
| 255 | 301 | |
| 256 | − ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd, | |
| 257 | − hctx->ccid2hctx_pipe); | |
| 302 | + next = hctx->ccid2hctx_seqh->ccid2s_next; | |
| 303 | + /* check if we need to alloc more space */ | |
| 304 | + if (next == hctx->ccid2hctx_seqt) { | |
| 305 | + int rc; | |
| 306 | + | |
| 307 | + ccid2_pr_debug("allocating more space in history\n"); | |
| 308 | + rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_KERNEL); | |
| 309 | + BUG_ON(rc); /* XXX what do we do? */ | |
| 258 | 310 | |
| 259 | − if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) { | |
| 260 | − /* XXX allocate more space */ | |
| 261 | − WARN_ON(1); | |
| 311 | + next = hctx->ccid2hctx_seqh->ccid2s_next; | |
| 312 | + BUG_ON(next == hctx->ccid2hctx_seqt); | |
| 262 | 313 | } |
| 314 | + hctx->ccid2hctx_seqh = next; | |
| 315 | + | |
| 316 | + ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd, | |
| 317 | + hctx->ccid2hctx_pipe); | |
| 263 | 318 | |
| 264 | 319 | hctx->ccid2hctx_sent++; |
| 265 | 320 | |
| @@ -295,7 +350,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) · 29 unmodified lines | ||
| 295 | 350 | if (!timer_pending(&hctx->ccid2hctx_rtotimer)) |
| 296 | 351 | ccid2_start_rto_timer(sk); |
| 297 | 352 | |
| 298 | −#ifdef CCID2_DEBUG | |
| 353 | +#ifdef CONFIG_IP_DCCP_CCID2_DEBUG | |
| 299 | 354 | ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe); |
| 300 | 355 | ccid2_pr_debug("Sent: seq=%llu\n", seq); |
| 301 | 356 | do { |
| @@ -398,7 +453,7 @@ static inline void ccid2_new_ack(struct sock *sk, · 96 unmodified lines | ||
| 398 | 453 | /* increase every 2 acks */ |
| 399 | 454 | hctx->ccid2hctx_ssacks++; |
| 400 | 455 | if (hctx->ccid2hctx_ssacks == 2) { |
| 401 | − ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); | |
| 456 | + ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd+1); | |
| 402 | 457 | hctx->ccid2hctx_ssacks = 0; |
| 403 | 458 | *maxincr = *maxincr - 1; |
| 404 | 459 | } |
| @@ -411,26 +466,28 @@ static inline void ccid2_new_ack(struct sock *sk, · 6 unmodified lines | ||
| 411 | 466 | hctx->ccid2hctx_acks++; |
| 412 | 467 | |
| 413 | 468 | if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) { |
| 414 | − ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); | |
| 469 | + ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd + 1); | |
| 415 | 470 | hctx->ccid2hctx_acks = 0; |
| 416 | 471 | } |
| 417 | 472 | } |
| 418 | 473 | |
| 419 | 474 | /* update RTO */ |
| 420 | 475 | if (hctx->ccid2hctx_srtt == -1 || |
| 421 | − (jiffies - hctx->ccid2hctx_lastrtt) >= hctx->ccid2hctx_srtt) { | |
| 422 | − unsigned long r = jiffies - seqp->ccid2s_sent; | |
| 476 | + time_after(jiffies, hctx->ccid2hctx_lastrtt + hctx->ccid2hctx_srtt)) { | |
| 477 | + unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent; | |
| 423 | 478 | int s; |
| 424 | 479 | |
| 425 | 480 | /* first measurement */ |
| 426 | 481 | if (hctx->ccid2hctx_srtt == -1) { |
| 427 | 482 | ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", |
| 428 | 483 | r, jiffies, seqp->ccid2s_seq); |
| 429 | − hctx->ccid2hctx_srtt = r; | |
| 484 | + ccid2_change_srtt(hctx, r); | |
| 430 | 485 | hctx->ccid2hctx_rttvar = r >> 1; |
| 431 | 486 | } else { |
| 432 | 487 | /* RTTVAR */ |
| 433 | 488 | long tmp = hctx->ccid2hctx_srtt - r; |
| 489 | + long srtt; | |
| 490 | + | |
| 434 | 491 | if (tmp < 0) |
| 435 | 492 | tmp *= -1; |
| 436 | 493 | |
| @@ -440,10 +497,12 @@ static inline void ccid2_new_ack(struct sock *sk, · 3 unmodified lines | ||
| 440 | 497 | hctx->ccid2hctx_rttvar += tmp; |
| 441 | 498 | |
| 442 | 499 | /* SRTT */ |
| 443 | − hctx->ccid2hctx_srtt *= 7; | |
| 444 | − hctx->ccid2hctx_srtt >>= 3; | |
| 500 | + srtt = hctx->ccid2hctx_srtt; | |
| 501 | + srtt *= 7; | |
| 502 | + srtt >>= 3; | |
| 445 | 503 | tmp = r >> 3; |
| 446 | − hctx->ccid2hctx_srtt += tmp; | |
| 504 | + srtt += tmp; | |
| 505 | + ccid2_change_srtt(hctx, srtt); | |
| 447 | 506 | } |
| 448 | 507 | s = hctx->ccid2hctx_rttvar << 2; |
| 449 | 508 | /* clock granularity is 1 when based on jiffies */ |
| @@ -479,13 +538,29 @@ static void ccid2_hc_tx_dec_pipe(struct sock *sk) · 29 unmodified lines | ||
| 479 | 538 | { |
| 480 | 539 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); |
| 481 | 540 | |
| 482 | − hctx->ccid2hctx_pipe--; | |
| 541 | + ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe-1); | |
| 483 | 542 | BUG_ON(hctx->ccid2hctx_pipe < 0); |
| 484 | 543 | |
| 485 | 544 | if (hctx->ccid2hctx_pipe == 0) |
| 486 | 545 | ccid2_hc_tx_kill_rto_timer(sk); |
| 487 | 546 | } |
| 488 | 547 | |
| 548 | +static void ccid2_congestion_event(struct ccid2_hc_tx_sock *hctx, | |
| 549 | + struct ccid2_seq *seqp) | |
| 550 | +{ | |
| 551 | + if (time_before(seqp->ccid2s_sent, hctx->ccid2hctx_last_cong)) { | |
| 552 | + ccid2_pr_debug("Multiple losses in an RTT---treating as one\n"); | |
| 553 | + return; | |
| 554 | + } | |
| 555 | + | |
| 556 | + hctx->ccid2hctx_last_cong = jiffies; | |
| 557 | + | |
| 558 | + ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd >> 1); | |
| 559 | + hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd; | |
| 560 | + if (hctx->ccid2hctx_ssthresh < 2) | |
| 561 | + hctx->ccid2hctx_ssthresh = 2; | |
| 562 | +} | |
| 563 | + | |
126 more lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 173 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 612 lines aren’t shown here.
This diff is large: its 305 lines aren’t shown here.
This diff is large: its 334 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 1608 lines aren’t shown here.
This diff is large: its 390 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 604 lines aren’t shown here.
This diff is large: its 300 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 727 lines aren’t shown here.
This diff is large: its 806 lines aren’t shown here.
This diff is large: its 284 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 407 lines aren’t shown here.
This diff is large: its 782 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 265 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 400 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 230 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 265 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 219 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 1089 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 157 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 374 lines aren’t shown here.
This diff is large: its 306 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 732 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 168 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 520 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 221 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 1740 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 154 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 164 lines aren’t shown here.
This diff is large: its 214 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 183 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 381 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 340 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 193 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 166 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 264 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 139 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 158 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 138 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 543 lines aren’t shown here.
This diff is large: its 218 lines aren’t shown here.
This diff is large: its 514 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 232 lines aren’t shown here.
This diff is large: its 625 lines aren’t shown here.
This diff is large: its 247 lines aren’t shown here.
This diff is large: its 254 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 159 lines aren’t shown here.
This diff is large: its 216 lines aren’t shown here.
This diff is large: its 178 lines aren’t shown here.
This diff is large: its 184 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 317 lines aren’t shown here.
This diff is large: its 241 lines aren’t shown here.
This diff is large: its 343 lines aren’t shown here.
This diff is large: its 273 lines aren’t shown here.
This diff is large: its 288 lines aren’t shown here.
This diff is large: its 750 lines aren’t shown here.
This diff is large: its 207 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 2127 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 449 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 265 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 2046 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 347 lines aren’t shown here.
This diff is large: its 378 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 142 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 160 lines aren’t shown here.
This diff is large: its 294 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 129 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 1413 lines aren’t shown here.
This diff is large: its 1012 lines aren’t shown here.
This diff is large: its 625 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 447 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 154 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 194 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 659 lines aren’t shown here.
This diff is large: its 321 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 370 lines aren’t shown here.
This diff is large: its 266 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 215 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 206 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 234 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 1092 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 678 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 307 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 622 lines aren’t shown here.
This diff is large: its 191 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 179 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 297 lines aren’t shown here.
This diff is large: its 331 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 743 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 1288 lines aren’t shown here.
This diff is large: its 327 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 114 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 1588 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 138 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.