From da3d1eecc53f33ca3b05fdf56679ce4b2b4f0ea0 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Sat, 13 Aug 2016 19:54:32 +0000 Subject: [PATCH 01/67] 5396 fix longjmp clobbering errors illumos/illumos-gate@67a4bb8f9ad4c49e9aa9e21e2114a7c093c3a73a Reviewed by: Josef 'Jeff' Sipek Reviewed by: Igor Kozhukhov Approved by: Richard Lowe Author: Gary Mills --- lib/libdtrace/common/dt_cc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/libdtrace/common/dt_cc.c b/lib/libdtrace/common/dt_cc.c index 5d38704ffeb6..0b4ded9ae03c 100644 --- a/lib/libdtrace/common/dt_cc.c +++ b/lib/libdtrace/common/dt_cc.c @@ -23,6 +23,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Joyent Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright 2015 Gary Mills */ /* @@ -2335,7 +2336,7 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg, dt_node_t *dnp; dt_decl_t *ddp; dt_pcb_t pcb; - void *rv; + void *volatile rv; int err; if ((fp == NULL && s == NULL) || (cflags & ~DTRACE_C_MASK) != 0) { From 8a411dff0779efb9e44f705456f33a6ec012c0c6 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Sat, 13 Aug 2016 19:57:36 +0000 Subject: [PATCH 02/67] 7085 add support for "if" and "else" statements in dtrace illumos/illumos-gate@c3bd3abd8856e8e75d820f65c58031cd6cbac818 Add syntactic sugar to dtrace: "if" and "else" statements. The sugar is baked down to standard dtrace features by adding additional clauses with the appropriate predicates. Reviewed by: Adam Leventhal Reviewed by: Sebastien Roy Reviewed by: Paul Dagnelie Reviewed by: Bryan Cantrill Approved by: Richard Lowe Author: Matthew Ahrens --- cmd/dtrace/test/cmd/scripts/dstyle.pl | 9 +- cmd/dtrace/test/tst/common/sugar/tst.else.d | 33 ++ cmd/dtrace/test/tst/common/sugar/tst.if.d | 33 ++ cmd/dtrace/test/tst/common/sugar/tst.if2.d | 33 ++ .../tst/common/sugar/tst.if_before_after.d | 46 ++ .../test/tst/common/sugar/tst.if_nested.d | 38 ++ .../common/sugar/tst.if_trailing_semicolon.d | 30 + .../common/sugar/tst.if_trailing_semicolon2.d | 31 ++ lib/libdtrace/common/dt_cc.c | 27 +- lib/libdtrace/common/dt_grammar.y | 34 +- lib/libdtrace/common/dt_impl.h | 3 +- lib/libdtrace/common/dt_open.c | 8 +- lib/libdtrace/common/dt_parser.c | 282 ++++++++-- lib/libdtrace/common/dt_parser.h | 16 +- lib/libdtrace/common/dt_sugar.c | 516 ++++++++++++++++++ lib/libdtrace/common/dtrace.h | 9 +- 16 files changed, 1094 insertions(+), 54 deletions(-) create mode 100644 cmd/dtrace/test/tst/common/sugar/tst.else.d create mode 100644 cmd/dtrace/test/tst/common/sugar/tst.if.d create mode 100644 cmd/dtrace/test/tst/common/sugar/tst.if2.d create mode 100644 cmd/dtrace/test/tst/common/sugar/tst.if_before_after.d create mode 100644 cmd/dtrace/test/tst/common/sugar/tst.if_nested.d create mode 100644 cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon.d create mode 100644 cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon2.d create mode 100644 lib/libdtrace/common/dt_sugar.c diff --git a/cmd/dtrace/test/cmd/scripts/dstyle.pl b/cmd/dtrace/test/cmd/scripts/dstyle.pl index c1075a364757..d496d23e7a62 100644 --- a/cmd/dtrace/test/cmd/scripts/dstyle.pl +++ b/cmd/dtrace/test/cmd/scripts/dstyle.pl @@ -25,6 +25,10 @@ # Use is subject to license terms. # +# +# Copyright (c) 2014, 2016 by Delphix. All rights reserved. +# + require 5.8.4; $PNAME = $0; @@ -131,7 +135,8 @@ sub dstyle } if (!/^enum/ && !/^\t*struct/ && !/^\t*union/ && !/^typedef/ && - !/^translator/ && !/^provider/) { + !/^translator/ && !/^provider/ && !/\tif / && + !/ else /) { if (/[\w\s]+{/) { err "left brace not on its own line"; } @@ -141,7 +146,7 @@ sub dstyle } } - if (!/;$/) { + if (!/;$/ && !/\t*}$/ && !/ else /) { if (/[\w\s]+}/) { err "right brace not on its own line"; } diff --git a/cmd/dtrace/test/tst/common/sugar/tst.else.d b/cmd/dtrace/test/tst/common/sugar/tst.else.d new file mode 100644 index 000000000000..88da007436fb --- /dev/null +++ b/cmd/dtrace/test/tst/common/sugar/tst.else.d @@ -0,0 +1,33 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "else" statement is executed + */ + +BEGIN +{ + if (0) { + n = 1; + } else { + n = 0; + } + exit(n) +} diff --git a/cmd/dtrace/test/tst/common/sugar/tst.if.d b/cmd/dtrace/test/tst/common/sugar/tst.if.d new file mode 100644 index 000000000000..3da5d2daf695 --- /dev/null +++ b/cmd/dtrace/test/tst/common/sugar/tst.if.d @@ -0,0 +1,33 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "if" statement executes the correct body. + */ + +BEGIN +{ + if (1) { + n = 0; + } else { + n = 1; + } + exit(n) +} diff --git a/cmd/dtrace/test/tst/common/sugar/tst.if2.d b/cmd/dtrace/test/tst/common/sugar/tst.if2.d new file mode 100644 index 000000000000..b56e39929d67 --- /dev/null +++ b/cmd/dtrace/test/tst/common/sugar/tst.if2.d @@ -0,0 +1,33 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "if" statement executes the correct body. + * parses single-statement, braceless bodies correctly. + */ + +BEGIN +{ + if (1) + n = 0; + else + n = 1; + exit(n) +} diff --git a/cmd/dtrace/test/tst/common/sugar/tst.if_before_after.d b/cmd/dtrace/test/tst/common/sugar/tst.if_before_after.d new file mode 100644 index 000000000000..00837eb65c2c --- /dev/null +++ b/cmd/dtrace/test/tst/common/sugar/tst.if_before_after.d @@ -0,0 +1,46 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * statements before and after an if statement are executed. + */ + +BEGIN +{ + i = 1; + if (1) { + i++; + } else { + i++; + } + i++; +} + +BEGIN +/i == 3/ +{ + exit(0); +} + +BEGIN +/i != 3/ +{ + exit(1); +} diff --git a/cmd/dtrace/test/tst/common/sugar/tst.if_nested.d b/cmd/dtrace/test/tst/common/sugar/tst.if_nested.d new file mode 100644 index 000000000000..e8ad443a04bd --- /dev/null +++ b/cmd/dtrace/test/tst/common/sugar/tst.if_nested.d @@ -0,0 +1,38 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * nested "if" statement executes the correct body. + */ + +BEGIN +{ + if (0) { + exit(1); + } else { + if (0) { + exit(1); + } else { + exit(0); + } + exit(1); + } + exit(1); +} diff --git a/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon.d b/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon.d new file mode 100644 index 000000000000..81196c0ca47c --- /dev/null +++ b/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon.d @@ -0,0 +1,30 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "if" body without trailing semicolon parses correctly + */ + +BEGIN +{ + if (1) { + exit(0) + } +} diff --git a/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon2.d b/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon2.d new file mode 100644 index 000000000000..e1bd3895f9f0 --- /dev/null +++ b/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon2.d @@ -0,0 +1,31 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "if" body without trailing semicolon parses correctly + */ + +BEGIN +{ + if (1) { + i = 1; + exit(0) + } +} diff --git a/lib/libdtrace/common/dt_cc.c b/lib/libdtrace/common/dt_cc.c index 0b4ded9ae03c..b5702fc8b5a6 100644 --- a/lib/libdtrace/common/dt_cc.c +++ b/lib/libdtrace/common/dt_cc.c @@ -21,8 +21,8 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. * Copyright 2015 Gary Mills */ @@ -119,7 +119,6 @@ static const dtrace_diftype_t dt_int_rtype = { static void *dt_compile(dtrace_hdl_t *, int, dtrace_probespec_t, void *, uint_t, int, char *const[], FILE *, const char *); - /*ARGSUSED*/ static int dt_idreset(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored) @@ -2418,6 +2417,28 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg, "not referenced)\n", yypcb->pcb_sargv[argc - 1], argc - 1); } + /* + * Perform sugar transformations (for "if" / "else") and replace the + * existing clause chain with the new one. + */ + if (context == DT_CTX_DPROG) { + dt_node_t *dnp, *next_dnp; + dt_node_t *new_list = NULL; + + for (dnp = yypcb->pcb_root->dn_list; + dnp != NULL; dnp = next_dnp) { + /* remove this node from the list */ + next_dnp = dnp->dn_list; + dnp->dn_list = NULL; + + if (dnp->dn_kind == DT_NODE_CLAUSE) + dnp = dt_compile_sugar(dtp, dnp); + /* append node to the new list */ + new_list = dt_node_link(new_list, dnp); + } + yypcb->pcb_root->dn_list = new_list; + } + /* * If we have successfully created a parse tree for a D program, loop * over the clauses and actions and instantiate the corresponding @@ -2438,6 +2459,8 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg, for (; dnp != NULL; dnp = dnp->dn_list) { switch (dnp->dn_kind) { case DT_NODE_CLAUSE: + if (DT_TREEDUMP_PASS(dtp, 4)) + dt_printd(dnp, stderr, 0); dt_compile_clause(dtp, dnp); break; case DT_NODE_XLATOR: diff --git a/lib/libdtrace/common/dt_grammar.y b/lib/libdtrace/common/dt_grammar.y index 07790f4ebc2c..a7e7de7bc134 100644 --- a/lib/libdtrace/common/dt_grammar.y +++ b/lib/libdtrace/common/dt_grammar.y @@ -23,8 +23,9 @@ * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ + /* - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ @@ -155,6 +156,8 @@ %type probe_specifier_list %type probe_specifier %type statement_list +%type statement_list_impl +%type statement_or_block %type statement %type declaration %type init_declarator_list @@ -317,9 +320,11 @@ probe_definition: "or actions following probe description\n"); } $$ = dt_node_clause($1, NULL, NULL); + yybegin(YYS_CLAUSE); } | probe_specifiers '{' statement_list '}' { $$ = dt_node_clause($1, NULL, $3); + yybegin(YYS_CLAUSE); } | probe_specifiers DT_TOK_DIV expression DT_TOK_EPRED { dnerror($3, D_SYNTAX, "expected actions { } following " @@ -328,6 +333,7 @@ probe_definition: | probe_specifiers DT_TOK_DIV expression DT_TOK_EPRED '{' statement_list '}' { $$ = dt_node_clause($1, $3, $6); + yybegin(YYS_CLAUSE); } ; @@ -347,12 +353,30 @@ probe_specifier: | DT_TOK_INT { $$ = dt_node_pdesc_by_id($1); } ; -statement_list: statement { $$ = $1; } - | statement_list ';' statement { $$ = LINK($1, $3); } +statement_list_impl: /* empty */ { $$ = NULL; } + | statement_list_impl statement { $$ = LINK($1, $2); } ; -statement: /* empty */ { $$ = NULL; } - | expression { $$ = dt_node_statement($1); } +statement_list: + statement_list_impl { $$ = $1; } + | statement_list_impl expression { + $$ = LINK($1, dt_node_statement($2)); + } + ; + +statement_or_block: + statement + | '{' statement_list '}' { $$ = $2; } + +statement: ';' { $$ = NULL; } + | expression ';' { $$ = dt_node_statement($1); } + | DT_KEY_IF DT_TOK_LPAR expression DT_TOK_RPAR statement_or_block { + $$ = dt_node_if($3, $5, NULL); + } + | DT_KEY_IF DT_TOK_LPAR expression DT_TOK_RPAR + statement_or_block DT_KEY_ELSE statement_or_block { + $$ = dt_node_if($3, $5, $7); + } ; argument_expression_list: diff --git a/lib/libdtrace/common/dt_impl.h b/lib/libdtrace/common/dt_impl.h index c6ed8ceaacc9..2681709483b5 100644 --- a/lib/libdtrace/common/dt_impl.h +++ b/lib/libdtrace/common/dt_impl.h @@ -26,7 +26,7 @@ /* * Copyright (c) 2013, Joyent, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2011, 2016 by Delphix. All rights reserved. */ #ifndef _DT_IMPL_H @@ -320,6 +320,7 @@ struct dtrace_hdl { int dt_indent; /* recommended flow indent */ dtrace_epid_t dt_last_epid; /* most recently consumed EPID */ uint64_t dt_last_timestamp; /* most recently consumed timestamp */ + boolean_t dt_has_sugar; /* syntactic sugar used? */ }; /* diff --git a/lib/libdtrace/common/dt_open.c b/lib/libdtrace/common/dt_open.c index ffb2fe9a8ff3..38c814603921 100644 --- a/lib/libdtrace/common/dt_open.c +++ b/lib/libdtrace/common/dt_open.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. */ #include @@ -115,8 +115,9 @@ #define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0) #define DT_VERS_1_12 DT_VERSION_NUMBER(1, 12, 0) #define DT_VERS_1_12_1 DT_VERSION_NUMBER(1, 12, 1) -#define DT_VERS_LATEST DT_VERS_1_12_1 -#define DT_VERS_STRING "Sun D 1.12.1" +#define DT_VERS_1_13 DT_VERSION_NUMBER(1, 13, 0) +#define DT_VERS_LATEST DT_VERS_1_13 +#define DT_VERS_STRING "Sun D 1.13" const dt_version_t _dtrace_versions[] = { DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */ @@ -142,6 +143,7 @@ const dt_version_t _dtrace_versions[] = { DT_VERS_1_11, /* D API 1.11 */ DT_VERS_1_12, /* D API 1.12 */ DT_VERS_1_12_1, /* D API 1.12.1 */ + DT_VERS_1_13, /* D API 1.13 */ 0 }; diff --git a/lib/libdtrace/common/dt_parser.c b/lib/libdtrace/common/dt_parser.c index 753009f857f3..7f771a807928 100644 --- a/lib/libdtrace/common/dt_parser.c +++ b/lib/libdtrace/common/dt_parser.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Joyent Inc. All rights reserved. - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. */ /* @@ -2136,6 +2136,17 @@ dt_node_statement(dt_node_t *expr) return (dnp); } +dt_node_t * +dt_node_if(dt_node_t *pred, dt_node_t *acts, dt_node_t *else_acts) +{ + dt_node_t *dnp = dt_node_alloc(DT_NODE_IF); + dnp->dn_conditional = pred; + dnp->dn_body = acts; + dnp->dn_alternate_body = else_acts; + + return (dnp); +} + dt_node_t * dt_node_pdesc_by_name(char *spec) { @@ -2205,7 +2216,6 @@ dt_node_clause(dt_node_t *pdescs, dt_node_t *pred, dt_node_t *acts) dnp->dn_pred = pred; dnp->dn_acts = acts; - yybegin(YYS_CLAUSE); return (dnp); } @@ -3197,8 +3207,9 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags) dt_xcook_ident(lp, dhp, idkind, B_TRUE); else dt_xcook_ident(lp, dhp, idp->di_kind, B_FALSE); - } else + } else { lp = dnp->dn_left = dt_node_cook(lp, 0); + } /* * Switch op to '+' for *(E1 + E2) array mode in these cases: @@ -3212,10 +3223,12 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags) if (lp->dn_ident->di_kind == DT_IDENT_ARRAY) { if (lp->dn_args != NULL) op = DT_TOK_ADD; - } else if (!dt_ident_unref(lp->dn_ident)) + } else if (!dt_ident_unref(lp->dn_ident)) { op = DT_TOK_ADD; - } else if (lp->dn_kind != DT_NODE_AGG) + } + } else if (lp->dn_kind != DT_NODE_AGG) { op = DT_TOK_ADD; + } } switch (op) { @@ -3639,45 +3652,34 @@ asgn_common: case DT_TOK_PTR: /* - * If the left-hand side of operator -> is the name "self", - * then we permit a TLS variable to be created or referenced. + * If the left-hand side of operator -> is one of the scoping + * keywords, permit a local or thread variable to be created or + * referenced. */ - if (lp->dn_kind == DT_NODE_IDENT && - strcmp(lp->dn_string, "self") == 0) { - if (rp->dn_kind != DT_NODE_VAR) { - dt_xcook_ident(rp, dtp->dt_tls, - DT_IDENT_SCALAR, B_TRUE); + if (lp->dn_kind == DT_NODE_IDENT) { + dt_idhash_t *dhp = NULL; + + if (strcmp(lp->dn_string, "self") == 0) { + dhp = dtp->dt_tls; + } else if (strcmp(lp->dn_string, "this") == 0) { + dhp = yypcb->pcb_locals; } + if (dhp != NULL) { + if (rp->dn_kind != DT_NODE_VAR) { + dt_xcook_ident(rp, dhp, + DT_IDENT_SCALAR, B_TRUE); + } - if (idflags != 0) - rp = dt_node_cook(rp, idflags); + if (idflags != 0) + rp = dt_node_cook(rp, idflags); - dnp->dn_right = dnp->dn_left; /* avoid freeing rp */ - dt_node_free(dnp); - return (rp); - } - - /* - * If the left-hand side of operator -> is the name "this", - * then we permit a local variable to be created or referenced. - */ - if (lp->dn_kind == DT_NODE_IDENT && - strcmp(lp->dn_string, "this") == 0) { - if (rp->dn_kind != DT_NODE_VAR) { - dt_xcook_ident(rp, yypcb->pcb_locals, - DT_IDENT_SCALAR, B_TRUE); + /* avoid freeing rp */ + dnp->dn_right = dnp->dn_left; + dt_node_free(dnp); + return (rp); } - - if (idflags != 0) - rp = dt_node_cook(rp, idflags); - - dnp->dn_right = dnp->dn_left; /* avoid freeing rp */ - dt_node_free(dnp); - return (rp); } - /*FALLTHRU*/ - case DT_TOK_DOT: lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); @@ -4496,7 +4498,8 @@ static dt_node_t *(*dt_cook_funcs[])(dt_node_t *, uint_t) = { dt_cook_xlator, /* DT_NODE_XLATOR */ dt_cook_none, /* DT_NODE_PROBE */ dt_cook_provider, /* DT_NODE_PROVIDER */ - dt_cook_none /* DT_NODE_PROG */ + dt_cook_none, /* DT_NODE_PROG */ + dt_cook_none, /* DT_NODE_IF */ }; /* @@ -4511,6 +4514,8 @@ dt_node_cook(dt_node_t *dnp, uint_t idflags) yylineno = dnp->dn_line; + assert(dnp->dn_kind < + sizeof (dt_cook_funcs) / sizeof (dt_cook_funcs[0])); dnp = dt_cook_funcs[dnp->dn_kind](dnp, idflags); dnp->dn_flags |= DT_NF_COOKED; @@ -4613,6 +4618,181 @@ dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp) tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type); } +/* + * Output the parse tree as D. The "-xtree=8" argument will call this + * function to print out the program after any syntactic sugar + * transformations have been applied (e.g. to implement "if"). The + * resulting output can be used to understand the transformations + * applied by these features, or to run such a script on a system that + * does not support these features + * + * Note that the output does not express precisely the same program as + * the input. In particular: + * - Only the clauses are output. #pragma options, variable + * declarations, etc. are excluded. + * - Command argument substitution has already been done, so the output + * will not contain e.g. $$1, but rather the substituted string. + */ +void +dt_printd(dt_node_t *dnp, FILE *fp, int depth) +{ + dt_node_t *arg; + + switch (dnp->dn_kind) { + case DT_NODE_INT: + (void) fprintf(fp, "0x%llx", (u_longlong_t)dnp->dn_value); + if (!(dnp->dn_flags & DT_NF_SIGNED)) + (void) fprintf(fp, "u"); + break; + + case DT_NODE_STRING: { + char *escd = strchr2esc(dnp->dn_string, strlen(dnp->dn_string)); + (void) fprintf(fp, "\"%s\"", escd); + free(escd); + break; + } + + case DT_NODE_IDENT: + (void) fprintf(fp, "%s", dnp->dn_string); + break; + + case DT_NODE_VAR: + (void) fprintf(fp, "%s%s", + (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL) ? "this->" : + (dnp->dn_ident->di_flags & DT_IDFLG_TLS) ? "self->" : "", + dnp->dn_ident->di_name); + + if (dnp->dn_args != NULL) { + (void) fprintf(fp, "["); + + for (arg = dnp->dn_args; arg != NULL; + arg = arg->dn_list) { + dt_printd(arg, fp, 0); + if (arg->dn_list != NULL) + (void) fprintf(fp, ", "); + } + + (void) fprintf(fp, "]"); + } + break; + + case DT_NODE_SYM: { + const dtrace_syminfo_t *dts = dnp->dn_ident->di_data; + (void) fprintf(fp, "%s`%s", dts->dts_object, dts->dts_name); + break; + } + case DT_NODE_FUNC: + (void) fprintf(fp, "%s(", dnp->dn_ident->di_name); + + for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) { + dt_printd(arg, fp, 0); + if (arg->dn_list != NULL) + (void) fprintf(fp, ", "); + } + (void) fprintf(fp, ")"); + break; + + case DT_NODE_OP1: + (void) fprintf(fp, "%s(", opstr(dnp->dn_op)); + dt_printd(dnp->dn_child, fp, 0); + (void) fprintf(fp, ")"); + break; + + case DT_NODE_OP2: + (void) fprintf(fp, "("); + dt_printd(dnp->dn_left, fp, 0); + if (dnp->dn_op == DT_TOK_LPAR) { + (void) fprintf(fp, ")"); + dt_printd(dnp->dn_right, fp, 0); + break; + } + if (dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT || + dnp->dn_op == DT_TOK_LBRAC) + (void) fprintf(fp, "%s", opstr(dnp->dn_op)); + else + (void) fprintf(fp, " %s ", opstr(dnp->dn_op)); + dt_printd(dnp->dn_right, fp, 0); + if (dnp->dn_op == DT_TOK_LBRAC) { + dt_node_t *ln = dnp->dn_right; + while (ln->dn_list != NULL) { + (void) fprintf(fp, ", "); + dt_printd(ln->dn_list, fp, depth); + ln = ln->dn_list; + } + (void) fprintf(fp, "]"); + } + (void) fprintf(fp, ")"); + break; + + case DT_NODE_OP3: + (void) fprintf(fp, "("); + dt_printd(dnp->dn_expr, fp, 0); + (void) fprintf(fp, " ? "); + dt_printd(dnp->dn_left, fp, 0); + (void) fprintf(fp, " : "); + dt_printd(dnp->dn_right, fp, 0); + (void) fprintf(fp, ")"); + break; + + case DT_NODE_DEXPR: + case DT_NODE_DFUNC: + (void) fprintf(fp, "%*s", depth * 8, ""); + dt_printd(dnp->dn_expr, fp, depth + 1); + (void) fprintf(fp, ";\n"); + break; + + case DT_NODE_PDESC: + (void) fprintf(fp, "%s:%s:%s:%s", + dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod, + dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name); + break; + + case DT_NODE_CLAUSE: + for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list) { + dt_printd(arg, fp, 0); + if (arg->dn_list != NULL) + (void) fprintf(fp, ","); + (void) fprintf(fp, "\n"); + } + + if (dnp->dn_pred != NULL) { + (void) fprintf(fp, "/"); + dt_printd(dnp->dn_pred, fp, 0); + (void) fprintf(fp, "/\n"); + } + (void) fprintf(fp, "{\n"); + + for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list) + dt_printd(arg, fp, depth + 1); + (void) fprintf(fp, "}\n"); + (void) fprintf(fp, "\n"); + break; + + case DT_NODE_IF: + (void) fprintf(fp, "%*sif (", depth * 8, ""); + dt_printd(dnp->dn_conditional, fp, 0); + (void) fprintf(fp, ") {\n"); + + for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list) + dt_printd(arg, fp, depth + 1); + if (dnp->dn_alternate_body == NULL) { + (void) fprintf(fp, "%*s}\n", depth * 8, ""); + } else { + (void) fprintf(fp, "%*s} else {\n", depth * 8, ""); + for (arg = dnp->dn_alternate_body; arg != NULL; + arg = arg->dn_list) + dt_printd(arg, fp, depth + 1); + (void) fprintf(fp, "%*s}\n", depth * 8, ""); + } + + break; + + default: + (void) fprintf(fp, "/* bad node %p, kind %d */\n", + (void *)dnp, dnp->dn_kind); + } +} + void dt_node_printr(dt_node_t *dnp, FILE *fp, int depth) { @@ -4723,6 +4903,13 @@ dt_node_printr(dt_node_t *dnp, FILE *fp, int depth) (void) fprintf(fp, "OP2 %s (%s)\n", opstr(dnp->dn_op), buf); dt_node_printr(dnp->dn_left, fp, depth + 1); dt_node_printr(dnp->dn_right, fp, depth + 1); + if (dnp->dn_op == DT_TOK_LBRAC) { + dt_node_t *ln = dnp->dn_right; + while (ln->dn_list != NULL) { + dt_node_printr(ln->dn_list, fp, depth + 1); + ln = ln->dn_list; + } + } break; case DT_NODE_OP3: @@ -4784,6 +4971,7 @@ dt_node_printr(dt_node_t *dnp, FILE *fp, int depth) for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list) dt_node_printr(arg, fp, depth + 1); + (void) fprintf(fp, "\n"); break; case DT_NODE_INLINE: @@ -4834,6 +5022,24 @@ dt_node_printr(dt_node_t *dnp, FILE *fp, int depth) dt_node_printr(arg, fp, depth + 1); break; + case DT_NODE_IF: + (void) fprintf(fp, "IF attr=%s CONDITION:\n", a); + + dt_node_printr(dnp->dn_conditional, fp, depth + 1); + + (void) fprintf(fp, "%*sIF BODY: \n", depth * 2, ""); + for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list) + dt_node_printr(arg, fp, depth + 1); + + if (dnp->dn_alternate_body != NULL) { + (void) fprintf(fp, "%*sIF ELSE: \n", depth * 2, ""); + for (arg = dnp->dn_alternate_body; arg != NULL; + arg = arg->dn_list) + dt_node_printr(arg, fp, depth + 1); + } + + break; + default: (void) fprintf(fp, "\n", (void *)dnp, dnp->dn_kind); diff --git a/lib/libdtrace/common/dt_parser.h b/lib/libdtrace/common/dt_parser.h index 38f21c9f2e9e..3a146c5d2592 100644 --- a/lib/libdtrace/common/dt_parser.h +++ b/lib/libdtrace/common/dt_parser.h @@ -23,7 +23,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2013, 2016 by Delphix. All rights reserved. * Copyright (c) 2013 Joyent, Inc. All rights reserved. */ @@ -105,6 +105,12 @@ typedef struct dt_node { struct dt_node *_probes; /* list of probe nodes */ int _redecl; /* provider redeclared */ } _provider; + + struct { + struct dt_node *_conditional; + struct dt_node *_body; + struct dt_node *_alternate_body; + } _conditional; } dn_u; struct dt_node *dn_list; /* parse tree list link */ @@ -140,6 +146,11 @@ typedef struct dt_node { #define dn_provred dn_u._provider._redecl /* DT_NODE_PROVIDER */ #define dn_probes dn_u._provider._probes /* DT_NODE_PROVIDER */ +/* DT_NODE_IF: */ +#define dn_conditional dn_u._conditional._conditional +#define dn_body dn_u._conditional._body +#define dn_alternate_body dn_u._conditional._alternate_body + #define DT_NODE_FREE 0 /* unused node (waiting to be freed) */ #define DT_NODE_INT 1 /* integer value */ #define DT_NODE_STRING 2 /* string value */ @@ -162,6 +173,7 @@ typedef struct dt_node { #define DT_NODE_PROBE 19 /* probe definition */ #define DT_NODE_PROVIDER 20 /* provider definition */ #define DT_NODE_PROG 21 /* program translation unit */ +#define DT_NODE_IF 22 /* if statement */ #define DT_NF_SIGNED 0x01 /* data is a signed quantity (else unsigned) */ #define DT_NF_COOKED 0x02 /* data is a known type (else still cooking) */ @@ -213,6 +225,7 @@ extern dt_node_t *dt_node_xlator(dt_decl_t *, dt_decl_t *, char *, dt_node_t *); extern dt_node_t *dt_node_probe(char *, int, dt_node_t *, dt_node_t *); extern dt_node_t *dt_node_provider(char *, dt_node_t *); extern dt_node_t *dt_node_program(dt_node_t *); +extern dt_node_t *dt_node_if(dt_node_t *, dt_node_t *, dt_node_t *); extern dt_node_t *dt_node_link(dt_node_t *, dt_node_t *); extern dt_node_t *dt_node_cook(dt_node_t *, uint_t); @@ -237,6 +250,7 @@ extern void dt_node_promote(dt_node_t *, dt_node_t *, dt_node_t *); extern void dt_node_diftype(dtrace_hdl_t *, const dt_node_t *, dtrace_diftype_t *); extern void dt_node_printr(dt_node_t *, FILE *, int); +extern void dt_printd(dt_node_t *, FILE *, int); extern const char *dt_node_name(const dt_node_t *, char *, size_t); extern int dt_node_root(dt_node_t *); diff --git a/lib/libdtrace/common/dt_sugar.c b/lib/libdtrace/common/dt_sugar.c new file mode 100644 index 000000000000..8bd052384d68 --- /dev/null +++ b/lib/libdtrace/common/dt_sugar.c @@ -0,0 +1,516 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. + */ + +/* + * Syntactic sugar features are implemented by transforming the D parse tree + * such that it only uses the subset of D that is supported by the rest of the + * compiler / the kernel. A clause containing these language features is + * referred to as a "super-clause", and its transformation typically entails + * creating several "sub-clauses" to implement it. For diagnosability, the + * sub-clauses will be printed if the "-xtree=8" flag is specified. + * + * Currently, the only syntactic sugar feature is "if/else" statements. Each + * basic block (e.g. the body of the "if" and "else" statements, and the + * statements before and after) is turned into its own sub-clause, with a + * predicate that causes it to be executed only if the code flows to this point. + * Nested if/else statements are supported. + * + * This infrastructure is designed to accommodate other syntactic sugar features + * in the future. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct dt_sugar_parse { + dtrace_hdl_t *dtsp_dtp; /* dtrace handle */ + dt_node_t *dtsp_pdescs; /* probe descriptions */ + int dtsp_num_conditions; /* number of condition variables */ + int dtsp_num_ifs; /* number of "if" statements */ + dt_node_t *dtsp_clause_list; /* list of clauses */ +} dt_sugar_parse_t; + +static void dt_sugar_visit_stmts(dt_sugar_parse_t *, dt_node_t *, int); + +/* + * Return a node for "self->%error". + * + * Note that the "%" is part of the variable name, and is included so that + * this variable name can not collide with any user-specified variable. + * + * This error variable is used to keep track of if there has been an error + * in any of the sub-clauses, and is used to prevent execution of subsequent + * sub-clauses following an error. + */ +static dt_node_t * +dt_sugar_new_error_var(void) +{ + return (dt_node_op2(DT_TOK_PTR, dt_node_ident(strdup("self")), + dt_node_ident(strdup("%error")))); +} + +/* + * Append this clause to the clause list. + */ +static void +dt_sugar_append_clause(dt_sugar_parse_t *dp, dt_node_t *clause) +{ + dp->dtsp_clause_list = dt_node_link(dp->dtsp_clause_list, clause); +} + +/* + * Prepend this clause to the clause list. + */ +static void +dt_sugar_prepend_clause(dt_sugar_parse_t *dp, dt_node_t *clause) +{ + dp->dtsp_clause_list = dt_node_link(clause, dp->dtsp_clause_list); +} + +/* + * Return a node for "this->%condition_", or NULL if condid==0. + * + * Note that the "%" is part of the variable name, and is included so that + * this variable name can not collide with any user-specified variable. + */ +static dt_node_t * +dt_sugar_new_condition_var(int condid) +{ + char *str; + + if (condid == 0) + return (NULL); + assert(condid > 0); + + (void) asprintf(&str, "%%condition_%d", ABS(condid)); + return (dt_node_op2(DT_TOK_PTR, dt_node_ident(strdup("this")), + dt_node_ident(str))); +} + +/* + * Return new clause to evaluate predicate and set newcond. condid is + * the condition that we are already under, or 0 if none. + * The new clause will be of the form: + * + * dp_pdescs + * /!self->%error/ + * { + * this->%condition_ = + * (this->%condition_ && pred); + * } + * + * Note: if condid==0, we will instead do "... = (1 && pred)", to effectively + * convert the pred to a boolean. + * + * Note: Unless an error has been encountered, we always set the condition + * variable (either to 0 or 1). This lets us avoid resetting the condition + * variables back to 0 when the super-clause completes. + */ +static dt_node_t * +dt_sugar_new_condition_impl(dt_sugar_parse_t *dp, + dt_node_t *pred, int condid, int newcond) +{ + dt_node_t *value, *body, *newpred; + + /* predicate is !self->%error */ + newpred = dt_node_op1(DT_TOK_LNEG, dt_sugar_new_error_var()); + + if (condid == 0) { + /* + * value is (1 && pred) + * + * Note, D doesn't allow a probe-local "this" variable to + * be reused as a different type, even from a different probe. + * Therefore, value can't simply be , because then + * its type could be different when we reuse this condid + * in a different meta-clause. + */ + value = dt_node_op2(DT_TOK_LAND, dt_node_int(1), pred); + } else { + /* value is (this->%condition_ && pred) */ + value = dt_node_op2(DT_TOK_LAND, + dt_sugar_new_condition_var(condid), pred); + } + + /* body is "this->%condition_ = ;" */ + body = dt_node_statement(dt_node_op2(DT_TOK_ASGN, + dt_sugar_new_condition_var(newcond), value)); + + return (dt_node_clause(dp->dtsp_pdescs, newpred, body)); +} + +/* + * Generate a new clause to evaluate predicate and set a new condition variable, + * whose ID will be returned. The new clause will be appended to + * dp_first_new_clause. + */ +static int +dt_sugar_new_condition(dt_sugar_parse_t *dp, dt_node_t *pred, int condid) +{ + dp->dtsp_num_conditions++; + dt_sugar_append_clause(dp, dt_sugar_new_condition_impl(dp, + pred, condid, dp->dtsp_num_conditions)); + return (dp->dtsp_num_conditions); +} + +/* + * Visit the specified node and all of its descendants. Currently this is only + * used to count the number of "if" statements (dtsp_num_ifs). + */ +static void +dt_sugar_visit_all(dt_sugar_parse_t *dp, dt_node_t *dnp) +{ + dt_node_t *arg; + + switch (dnp->dn_kind) { + case DT_NODE_FREE: + case DT_NODE_INT: + case DT_NODE_STRING: + case DT_NODE_SYM: + case DT_NODE_TYPE: + case DT_NODE_PROBE: + case DT_NODE_PDESC: + case DT_NODE_IDENT: + break; + + case DT_NODE_FUNC: + for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_OP1: + dt_sugar_visit_all(dp, dnp->dn_child); + break; + + case DT_NODE_OP2: + dt_sugar_visit_all(dp, dnp->dn_left); + dt_sugar_visit_all(dp, dnp->dn_right); + if (dnp->dn_op == DT_TOK_LBRAC) { + dt_node_t *ln = dnp->dn_right; + while (ln->dn_list != NULL) { + dt_sugar_visit_all(dp, ln->dn_list); + ln = ln->dn_list; + } + } + break; + + case DT_NODE_OP3: + dt_sugar_visit_all(dp, dnp->dn_expr); + dt_sugar_visit_all(dp, dnp->dn_left); + dt_sugar_visit_all(dp, dnp->dn_right); + break; + + case DT_NODE_DEXPR: + case DT_NODE_DFUNC: + dt_sugar_visit_all(dp, dnp->dn_expr); + break; + + case DT_NODE_AGG: + for (arg = dnp->dn_aggtup; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + + if (dnp->dn_aggfun) + dt_sugar_visit_all(dp, dnp->dn_aggfun); + break; + + case DT_NODE_CLAUSE: + for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + + if (dnp->dn_pred != NULL) + dt_sugar_visit_all(dp, dnp->dn_pred); + + for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_INLINE: { + const dt_idnode_t *inp = dnp->dn_ident->di_iarg; + + dt_sugar_visit_all(dp, inp->din_root); + break; + } + case DT_NODE_MEMBER: + if (dnp->dn_membexpr) + dt_sugar_visit_all(dp, dnp->dn_membexpr); + break; + + case DT_NODE_XLATOR: + for (arg = dnp->dn_members; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_PROVIDER: + for (arg = dnp->dn_probes; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_PROG: + for (arg = dnp->dn_list; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_IF: + dp->dtsp_num_ifs++; + dt_sugar_visit_all(dp, dnp->dn_conditional); + + for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + for (arg = dnp->dn_alternate_body; arg != NULL; + arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + + break; + + default: + (void) dnerror(dnp, D_UNKNOWN, "bad node %p, kind %d\n", + (void *)dnp, dnp->dn_kind); + } +} + +/* + * Return a new clause which resets the error variable to zero: + * + * dp_pdescs{ self->%error = 0; } + * + * This clause will be executed at the beginning of each meta-clause, to + * ensure the error variable is unset (in case the previous meta-clause + * failed). + */ +static dt_node_t * +dt_sugar_new_clearerror_clause(dt_sugar_parse_t *dp) +{ + dt_node_t *stmt = dt_node_statement(dt_node_op2(DT_TOK_ASGN, + dt_sugar_new_error_var(), dt_node_int(0))); + return (dt_node_clause(dp->dtsp_pdescs, NULL, stmt)); +} + +/* + * Evaluate the conditional, and recursively visit the body of the "if" + * statement (and the "else", if present). + */ +static void +dt_sugar_do_if(dt_sugar_parse_t *dp, dt_node_t *if_stmt, int precondition) +{ + int newid; + + assert(if_stmt->dn_kind == DT_NODE_IF); + + /* condition */ + newid = dt_sugar_new_condition(dp, + if_stmt->dn_conditional, precondition); + + /* body of if */ + dt_sugar_visit_stmts(dp, if_stmt->dn_body, newid); + + /* + * Visit the body of the "else" statement, if present. Note that we + * generate a new condition which is the inverse of the previous + * condition. + */ + if (if_stmt->dn_alternate_body != NULL) { + dt_node_t *pred = + dt_node_op1(DT_TOK_LNEG, dt_sugar_new_condition_var(newid)); + dt_sugar_visit_stmts(dp, if_stmt->dn_alternate_body, + dt_sugar_new_condition(dp, pred, precondition)); + } +} + +/* + * Generate a new clause to evaluate the statements based on the condition. + * The new clause will be appended to dp_first_new_clause. + * + * dp_pdescs + * /!self->%error && this->%condition_/ + * { + * stmts + * } + */ +static void +dt_sugar_new_basic_block(dt_sugar_parse_t *dp, int condid, dt_node_t *stmts) +{ + dt_node_t *pred = NULL; + + if (condid == 0) { + /* + * Don't bother with !error on the first clause, because if + * there is only one clause, we don't add the prelude to + * zero out %error. + */ + if (dp->dtsp_num_conditions != 0) { + pred = dt_node_op1(DT_TOK_LNEG, + dt_sugar_new_error_var()); + } + } else { + pred = dt_node_op2(DT_TOK_LAND, + dt_node_op1(DT_TOK_LNEG, dt_sugar_new_error_var()), + dt_sugar_new_condition_var(condid)); + } + dt_sugar_append_clause(dp, + dt_node_clause(dp->dtsp_pdescs, pred, stmts)); +} + +/* + * Visit all the statements in this list, and break them into basic blocks, + * generating new clauses for "if" and "else" statements. + */ +static void +dt_sugar_visit_stmts(dt_sugar_parse_t *dp, dt_node_t *stmts, int precondition) +{ + dt_node_t *stmt; + dt_node_t *prev_stmt = NULL; + dt_node_t *next_stmt; + dt_node_t *first_stmt_in_basic_block = NULL; + + for (stmt = stmts; stmt != NULL; stmt = next_stmt) { + next_stmt = stmt->dn_list; + + if (stmt->dn_kind != DT_NODE_IF) { + if (first_stmt_in_basic_block == NULL) + first_stmt_in_basic_block = stmt; + prev_stmt = stmt; + continue; + } + + /* + * Remove this and following statements from the previous + * clause. + */ + if (prev_stmt != NULL) + prev_stmt->dn_list = NULL; + + /* + * Generate clause for statements preceding the "if" + */ + if (first_stmt_in_basic_block != NULL) { + dt_sugar_new_basic_block(dp, precondition, + first_stmt_in_basic_block); + } + + dt_sugar_do_if(dp, stmt, precondition); + + first_stmt_in_basic_block = NULL; + + prev_stmt = stmt; + } + + /* generate clause for statements after last "if". */ + if (first_stmt_in_basic_block != NULL) { + dt_sugar_new_basic_block(dp, precondition, + first_stmt_in_basic_block); + } +} + +/* + * Generate a new clause which will set the error variable when an error occurs. + * Only one of these clauses is created per program (e.g. script file). + * The clause is: + * + * dtrace:::ERROR{ self->%error = 1; } + */ +static dt_node_t * +dt_sugar_makeerrorclause(void) +{ + dt_node_t *acts, *pdesc; + + pdesc = dt_node_pdesc_by_name(strdup("dtrace:::ERROR")); + + acts = dt_node_statement(dt_node_op2(DT_TOK_ASGN, + dt_sugar_new_error_var(), dt_node_int(1))); + + return (dt_node_clause(pdesc, NULL, acts)); +} + +/* + * Transform the super-clause into straight-D, returning the new list of + * sub-clauses. + */ +dt_node_t * +dt_compile_sugar(dtrace_hdl_t *dtp, dt_node_t *clause) +{ + dt_sugar_parse_t dp = { 0 }; + int condid = 0; + + dp.dtsp_dtp = dtp; + dp.dtsp_pdescs = clause->dn_pdescs; + + /* make dt_node_int() generate an "int"-typed integer */ + yyintdecimal = B_TRUE; + yyintsuffix[0] = '\0'; + yyintprefix = 0; + + dt_sugar_visit_all(&dp, clause); + + if (dp.dtsp_num_ifs == 0 && dp.dtsp_num_conditions == 0) { + /* + * There is nothing that modifies the number of clauses. Use + * the existing clause as-is, with its predicate intact. This + * ensures that in the absence of D sugar, the body of the + * clause can create a variable that is referenced in the + * predicate. + */ + dt_sugar_append_clause(&dp, dt_node_clause(clause->dn_pdescs, + clause->dn_pred, clause->dn_acts)); + } else { + if (clause->dn_pred != NULL) { + condid = dt_sugar_new_condition(&dp, + clause->dn_pred, condid); + } + + if (clause->dn_acts == NULL) { + /* + * dt_sugar_visit_stmts() does not emit a clause with + * an empty body (e.g. if there's an empty "if" body), + * but we need the empty body here so that we + * continue to get the default tracing action. + */ + dt_sugar_new_basic_block(&dp, condid, NULL); + } else { + dt_sugar_visit_stmts(&dp, clause->dn_acts, condid); + } + } + + if (dp.dtsp_num_conditions != 0) { + dt_sugar_prepend_clause(&dp, + dt_sugar_new_clearerror_clause(&dp)); + } + + if (dp.dtsp_clause_list != NULL && + dp.dtsp_clause_list->dn_list != NULL && !dtp->dt_has_sugar) { + dtp->dt_has_sugar = B_TRUE; + dt_sugar_prepend_clause(&dp, dt_sugar_makeerrorclause()); + } + return (dp.dtsp_clause_list); +} diff --git a/lib/libdtrace/common/dtrace.h b/lib/libdtrace/common/dtrace.h index 065d99f3009c..293ab944af38 100644 --- a/lib/libdtrace/common/dtrace.h +++ b/lib/libdtrace/common/dtrace.h @@ -25,7 +25,7 @@ */ /* - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ @@ -55,6 +55,7 @@ extern "C" { #define DTRACE_VERSION 3 /* library ABI interface version */ struct ps_prochandle; +struct dt_node; typedef struct dtrace_hdl dtrace_hdl_t; typedef struct dtrace_prog dtrace_prog_t; typedef struct dtrace_vector dtrace_vector_t; @@ -111,7 +112,7 @@ typedef struct dtrace_proginfo { #define DTRACE_C_CPP 0x0010 /* Preprocess input file with cpp(1) utility */ #define DTRACE_C_KNODEF 0x0020 /* Permit unresolved kernel symbols in DIFO */ #define DTRACE_C_UNODEF 0x0040 /* Permit unresolved user symbols in DIFO */ -#define DTRACE_C_PSPEC 0x0080 /* Intepret ambiguous specifiers as probes */ +#define DTRACE_C_PSPEC 0x0080 /* Interpret ambiguous specifiers as probes */ #define DTRACE_C_ETAGS 0x0100 /* Prefix error messages with error tags */ #define DTRACE_C_ARGREF 0x0200 /* Do not require all macro args to be used */ #define DTRACE_C_DEFARG 0x0800 /* Use 0/"" as value for unspecified args */ @@ -519,6 +520,10 @@ extern int dtrace_type_strcompile(dtrace_hdl_t *, extern int dtrace_type_fcompile(dtrace_hdl_t *, FILE *, dtrace_typeinfo_t *); +extern struct dt_node *dt_compile_sugar(dtrace_hdl_t *, + struct dt_node *); + + /* * DTrace Probe Interface * From cb916ce7543613efd624e3d36a1a0fcf9ab6fbe9 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Sun, 14 Aug 2016 19:04:37 +0000 Subject: [PATCH 03/67] [mips] convert over =v to =r for the inline assembly. Later gcc and clang have deprecated =v (which maps to a specific temp register) and instead we should just use =r to have the assembler (hopefully!) save/restore things appropriately after choosing a register. Tested: * AR9344 SoC, with userreg support * AR9331 SoC, with no userreg support Sponsored by: Sponsored by: DARPA, AFRL (MIPS TLS user register work) --- lib/libthr/arch/mips/include/pthread_md.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/libthr/arch/mips/include/pthread_md.h b/lib/libthr/arch/mips/include/pthread_md.h index 47c178b02a40..d27ecf073056 100644 --- a/lib/libthr/arch/mips/include/pthread_md.h +++ b/lib/libthr/arch/mips/include/pthread_md.h @@ -84,7 +84,7 @@ _tcb_get(void) ".set\tmips64r2\n\t" "rdhwr\t%0, $29\n\t" ".set\tpop" - : "=v" (_rv)); + : "=r" (_rv)); /* * XXXSS See 'git show c6be4f4d2d1b71c04de5d3bbb6933ce2dbcdb317' @@ -106,7 +106,7 @@ _tcb_get(void) ".set\tmips32r2\n\t" "rdhwr\t%0, $29\n\t" ".set\tpop" - : "=v" (_rv)); + : "=r" (_rv)); /* * XXXSS See 'git show c6be4f4d2d1b71c04de5d3bbb6933ce2dbcdb317' From ce3ee09b538f7d8c90170bc48d2c81f018c4cf03 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 14 Aug 2016 22:00:45 +0000 Subject: [PATCH 04/67] Eliminate unneeded vm_page_xbusy() and vm_page_xunbusy() operations when neither vm_pager_has_page() nor vm_pager_get_pages() is called. Reviewed by: kib, markj MFC after: 3 weeks --- sys/kern/kern_exec.c | 5 +++-- sys/kern/uipc_shm.c | 5 +++-- sys/vm/vm_glue.c | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 3873c5a8f1d9..e573672f9f72 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -984,8 +984,9 @@ exec_map_first_page(imgp) #if VM_NRESERVLEVEL > 0 vm_object_color(object, 0); #endif - ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL); + ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY); if (ma[0]->valid != VM_PAGE_BITS_ALL) { + vm_page_xbusy(ma[0]); if (!vm_pager_has_page(object, 0, NULL, &after)) { vm_page_lock(ma[0]); vm_page_free(ma[0]); @@ -1021,10 +1022,10 @@ exec_map_first_page(imgp) VM_OBJECT_WUNLOCK(object); return (EIO); } + vm_page_xunbusy(ma[0]); for (i = 1; i < initial_pagein; i++) vm_page_readahead_finish(ma[i]); } - vm_page_xunbusy(ma[0]); vm_page_lock(ma[0]); vm_page_hold(ma[0]); vm_page_activate(ma[0]); diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 1096a168f33a..be922edf0b0b 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -182,8 +182,9 @@ uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio) * lock to page out tobj's pages because tobj is a OBJT_SWAP * type object. */ - m = vm_page_grab(obj, idx, VM_ALLOC_NORMAL); + m = vm_page_grab(obj, idx, VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY); if (m->valid != VM_PAGE_BITS_ALL) { + vm_page_xbusy(m); if (vm_pager_has_page(obj, idx, NULL, NULL)) { rv = vm_pager_get_pages(obj, &m, 1, NULL, NULL); if (rv != VM_PAGER_OK) { @@ -198,8 +199,8 @@ uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio) } } else vm_page_zero_invalid(m, TRUE); + vm_page_xunbusy(m); } - vm_page_xunbusy(m); vm_page_lock(m); vm_page_hold(m); if (m->queue == PQ_NONE) { diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 33b997a261f7..60b822e63079 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -236,8 +236,9 @@ vm_imgact_hold_page(vm_object_t object, vm_ooffset_t offset) VM_OBJECT_WLOCK(object); pindex = OFF_TO_IDX(offset); - m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL); + m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY); if (m->valid != VM_PAGE_BITS_ALL) { + vm_page_xbusy(m); rv = vm_pager_get_pages(object, &m, 1, NULL, NULL); if (rv != VM_PAGER_OK) { vm_page_lock(m); @@ -246,8 +247,8 @@ vm_imgact_hold_page(vm_object_t object, vm_ooffset_t offset) m = NULL; goto out; } + vm_page_xunbusy(m); } - vm_page_xunbusy(m); vm_page_lock(m); vm_page_hold(m); vm_page_activate(m); From 854023f054291b7ecebb98ce5d91701caf244713 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Sun, 14 Aug 2016 23:38:50 +0000 Subject: [PATCH 05/67] Add timingsafe_bcmp and timingsafe_memcmp. Obtained from: OpenBSD Reviewed by: trasz MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D7280 --- include/string.h | 2 + lib/libc/string/Makefile.inc | 10 +++- lib/libc/string/Symbol.map | 5 ++ lib/libc/string/bcmp.3 | 5 +- lib/libc/string/memcmp.3 | 3 +- lib/libc/string/timingsafe_bcmp.3 | 92 +++++++++++++++++++++++++++++ lib/libc/string/timingsafe_bcmp.c | 36 +++++++++++ lib/libc/string/timingsafe_memcmp.c | 53 +++++++++++++++++ 8 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 lib/libc/string/timingsafe_bcmp.3 create mode 100644 lib/libc/string/timingsafe_bcmp.c create mode 100644 lib/libc/string/timingsafe_memcmp.c diff --git a/include/string.h b/include/string.h index af8b0d46c86c..9fe1f826d9cd 100644 --- a/include/string.h +++ b/include/string.h @@ -134,6 +134,8 @@ typedef __ssize_t ssize_t; void swab(const void * __restrict, void * __restrict, ssize_t); #endif /* _SWAB_DECLARED */ +int timingsafe_bcmp(const void *, const void *, size_t); +int timingsafe_memcmp(const void *, const void *, size_t); #endif /* __BSD_VISIBLE */ #if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_) diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc index 1217b7bc82d2..7b2b9b734808 100644 --- a/lib/libc/string/Makefile.inc +++ b/lib/libc/string/Makefile.inc @@ -16,7 +16,10 @@ MISRCS+=bcmp.c bcopy.c bzero.c explicit_bzero.c \ strcspn.c strdup.c strerror.c strlcat.c strlcpy.c strlen.c strmode.c \ strncat.c strncmp.c strncpy.c strndup.c strnlen.c strnstr.c \ strpbrk.c strrchr.c strsep.c strsignal.c strspn.c strstr.c strtok.c \ - strxfrm.c swab.c wcpcpy.c wcpncpy.c wcscasecmp.c wcscat.c \ + strxfrm.c swab.c \ + timingsafe_bcmp.c \ + timingsafe_memcmp.c \ + wcpcpy.c wcpncpy.c wcscasecmp.c wcscat.c \ wcschr.c wcscmp.c wcscoll.c wcscpy.c wcscspn.c wcsdup.c \ wcslcat.c wcslcpy.c wcslen.c wcsncasecmp.c wcsncat.c wcsncmp.c \ wcsncpy.c wcsnlen.c wcspbrk.c \ @@ -34,7 +37,9 @@ MAN+= bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \ memcmp.3 memcpy.3 memmem.3 memmove.3 memset.3 strcasecmp.3 strcat.3 \ strchr.3 strcmp.3 strcoll.3 strcpy.3 strdup.3 strerror.3 \ string.3 strlcpy.3 strlen.3 strmode.3 strpbrk.3 strsep.3 \ - strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 wcscoll.3 wcstok.3 \ + strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 \ + timingsafe_bcmp.3 \ + wcscoll.3 wcstok.3 \ wcswidth.3 wcsxfrm.3 wmemchr.3 MLINKS+=bzero.3 explicit_bzero.3 @@ -69,6 +74,7 @@ MLINKS+=strstr.3 strcasestr.3 \ strstr.3 strcasestr_l.3 MLINKS+=strtok.3 strtok_r.3 MLINKS+=strxfrm.3 strxfrm_l.3 +MLINKS+=timingsafe_bcmp.3 timingsafe_memcmp.3 MLINKS+=wmemchr.3 wcpcpy.3 \ wmemchr.3 wcpncpy.3 \ wmemchr.3 wcscasecmp.3 \ diff --git a/lib/libc/string/Symbol.map b/lib/libc/string/Symbol.map index 59610925fe33..cbf80cf9751c 100644 --- a/lib/libc/string/Symbol.map +++ b/lib/libc/string/Symbol.map @@ -104,6 +104,11 @@ FBSD_1.4 { explicit_bzero; }; +FBSD_1.5 { + timingsafe_bcmp; + timingsafe_memcmp; +}; + FBSDprivate_1.0 { __strtok_r; }; diff --git a/lib/libc/string/bcmp.3 b/lib/libc/string/bcmp.3 index fa5666c57ea0..e2d4063a1654 100644 --- a/lib/libc/string/bcmp.3 +++ b/lib/libc/string/bcmp.3 @@ -30,7 +30,7 @@ .\" @(#)bcmp.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd August 15, 2016 .Dt BCMP 3 .Os .Sh NAME @@ -62,7 +62,8 @@ The strings may overlap. .Xr strcasecmp 3 , .Xr strcmp 3 , .Xr strcoll 3 , -.Xr strxfrm 3 +.Xr strxfrm 3 , +.Xr timingsafe_bcmp 3 .Sh HISTORY A .Fn bcmp diff --git a/lib/libc/string/memcmp.3 b/lib/libc/string/memcmp.3 index 00e8e1a1d759..245e2abe1d71 100644 --- a/lib/libc/string/memcmp.3 +++ b/lib/libc/string/memcmp.3 @@ -32,7 +32,7 @@ .\" @(#)memcmp.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd August 15, 2016 .Dt MEMCMP 3 .Os .Sh NAME @@ -75,6 +75,7 @@ Zero-length strings are always identical. .Xr strcmp 3 , .Xr strcoll 3 , .Xr strxfrm 3 , +.Xr timingsafe_memcmp 3 , .Xr wmemcmp 3 .Sh STANDARDS The diff --git a/lib/libc/string/timingsafe_bcmp.3 b/lib/libc/string/timingsafe_bcmp.3 new file mode 100644 index 000000000000..502e57176806 --- /dev/null +++ b/lib/libc/string/timingsafe_bcmp.3 @@ -0,0 +1,92 @@ +.\" $OpenBSD: timingsafe_bcmp.3,v 1.2 2014/06/21 20:22:15 tedu Exp $ +.\" +.\" Copyright (c) 2014 Google Inc. +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" $FreeBSD$ +.Dd August 15, 2016 +.Dt TIMINGSAFE_BCMP 3 +.Os +.Sh NAME +.Nm timingsafe_bcmp , +.Nm timingsafe_memcmp +.Nd timing-safe byte sequence comparisons +.Sh SYNOPSIS +.In string.h +.Ft int +.Fn timingsafe_bcmp "const void *b1" "const void *b2" "size_t len" +.Ft int +.Fn timingsafe_memcmp "const void *b1" "const void *b2" "size_t len" +.Sh DESCRIPTION +The +.Fn timingsafe_bcmp +and +.Fn timingsafe_memcmp +functions lexicographically compare the first +.Fa len +bytes (each interpreted as an +.Vt unsigned char ) +pointed to by +.Fa b1 +and +.Fa b2 . +.Pp +Additionally, their running times are independent of the byte sequences compared, +making them safe to use for comparing secret values such as cryptographic MACs. +In contrast, +.Xr bcmp 3 +and +.Xr memcmp 3 +may short-circuit after finding the first differing byte. +.Sh RETURN VALUES +The +.Fn timingsafe_bcmp +function returns 0 or not zero if the byte sequence pointed to by +.Fa b1 +compares equal to or not equal to (respectively) +the byte sequence pointed to by +.Fa b2 . +.Pp +The +.Fn timingsafe_memcmp +function returns a negative value, 0, or positive value if the byte sequence +pointed to by +.Fa b1 +compares less than, equal to, or greater than (respectively) +the byte sequence pointed to by +.Fa b2 . +.Sh SEE ALSO +.Xr bcmp 3 , +.Xr memcmp 3 +.Sh STANDARDS +The +.Fn timingsafe_bcmp +and +.Fn timingsafe_memcmp +functions are +.Fx +extensions. +.Sh HISTORY +The +.Fn timingsafe_bcmp +function first appeared in +.Ox 4.9 . +.Pp +The +.Fn timingsafe_memcmp +function first appeared in +.Ox 5.6 . +.Pp +Both functions first appeared in +.Fx 12.0 . diff --git a/lib/libc/string/timingsafe_bcmp.c b/lib/libc/string/timingsafe_bcmp.c new file mode 100644 index 000000000000..d098158059f3 --- /dev/null +++ b/lib/libc/string/timingsafe_bcmp.c @@ -0,0 +1,36 @@ +/* $OpenBSD: timingsafe_bcmp.c,v 1.3 2015/08/31 02:53:57 guenther Exp $ */ +/* + * Copyright (c) 2010 Damien Miller. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +int __timingsafe_bcmp(const void *, const void *, size_t); + +int +__timingsafe_bcmp(const void *b1, const void *b2, size_t n) +{ + const unsigned char *p1 = b1, *p2 = b2; + int ret = 0; + + for (; n > 0; n--) + ret |= *p1++ ^ *p2++; + return (ret != 0); +} + +__weak_reference(__timingsafe_bcmp, timingsafe_bcmp); diff --git a/lib/libc/string/timingsafe_memcmp.c b/lib/libc/string/timingsafe_memcmp.c new file mode 100644 index 000000000000..7abfb48045f8 --- /dev/null +++ b/lib/libc/string/timingsafe_memcmp.c @@ -0,0 +1,53 @@ +/* $OpenBSD: timingsafe_memcmp.c,v 1.2 2015/08/31 02:53:57 guenther Exp $ */ +/* + * Copyright (c) 2014 Google Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +int __timingsafe_memcmp(const void *, const void *, size_t); + +int +__timingsafe_memcmp(const void *b1, const void *b2, size_t len) +{ + const unsigned char *p1 = b1, *p2 = b2; + size_t i; + int res = 0, done = 0; + + for (i = 0; i < len; i++) { + /* lt is -1 if p1[i] < p2[i]; else 0. */ + int lt = (p1[i] - p2[i]) >> CHAR_BIT; + + /* gt is -1 if p1[i] > p2[i]; else 0. */ + int gt = (p2[i] - p1[i]) >> CHAR_BIT; + + /* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */ + int cmp = lt - gt; + + /* set res = cmp if !done. */ + res |= cmp & ~done; + + /* set done if p1[i] != p2[i]. */ + done |= lt | gt; + } + + return (res); +} + +__weak_reference(__timingsafe_memcmp, timingsafe_memcmp); From 3539b9b06d4008afb42832bd13277b61b5a8d1f7 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Mon, 15 Aug 2016 04:59:38 +0000 Subject: [PATCH 06/67] Unbreak LINT build. Sponsored by: Microsoft --- sys/conf/options | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/conf/options b/sys/conf/options index 89ce7902f413..f115e7e14212 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -418,6 +418,7 @@ IPFILTER_LOOKUP opt_ipfilter.h IPFIREWALL opt_ipfw.h IPFIREWALL_DEFAULT_TO_ACCEPT opt_ipfw.h IPFIREWALL_NAT opt_ipfw.h +IPFIREWALL_NAT64 opt_ipfw.h IPFIREWALL_NAT64_DIRECT_OUTPUT opt_ipfw.h IPFIREWALL_NPTV6 opt_ipfw.h IPFIREWALL_VERBOSE opt_ipfw.h From a04b666a0410ad10b4af4d9e8c8426a562ff59e3 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Mon, 15 Aug 2016 05:00:37 +0000 Subject: [PATCH 07/67] hyperv/hn: Simplify chimney sending buffer disconnection. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7479 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 29 ++++++++++------------------- sys/dev/hyperv/netvsc/if_hnreg.h | 9 +++++++++ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index c1d1c487fa96..d9c17a8409fb 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -436,33 +436,24 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_dev) static int hv_nv_destroy_send_buffer(netvsc_dev *net_dev) { - nvsp_msg *revoke_pkt; int ret = 0; - /* - * If we got a section count, it means we received a - * send_rx_buf_complete msg - * (ie sent nvsp_msg_1_type_send_rx_buf msg) therefore, - * we need to send a revoke msg here - */ if (net_dev->send_section_size) { - /* Send the revoke send buffer */ - revoke_pkt = &net_dev->revoke_packet; - memset(revoke_pkt, 0, sizeof(nvsp_msg)); + struct hn_nvs_chim_disconn disconn; - revoke_pkt->hdr.msg_type = - nvsp_msg_1_type_revoke_send_buf; - revoke_pkt->msgs.vers_1_msgs.revoke_send_buf.id = - NETVSC_SEND_BUFFER_ID; + /* + * Disconnect chimney sending buffer from NVS. + */ + memset(&disconn, 0, sizeof(disconn)); + disconn.nvs_type = HN_NVS_TYPE_CHIM_DISCONN; + disconn.nvs_sig = HN_NVS_CHIM_SIG; ret = vmbus_chan_send(net_dev->sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg), + VMBUS_CHANPKT_TYPE_INBAND, 0, &disconn, sizeof(disconn), (uint64_t)(uintptr_t)&hn_send_ctx_none); - /* - * If we failed here, we might as well return and have a leak - * rather than continue and a bugchk - */ if (ret != 0) { + if_printf(net_dev->sc->hn_ifp, + "send chim disconn failed: %d\n", ret); return (ret); } } diff --git a/sys/dev/hyperv/netvsc/if_hnreg.h b/sys/dev/hyperv/netvsc/if_hnreg.h index abe371a36915..ac18798af69b 100644 --- a/sys/dev/hyperv/netvsc/if_hnreg.h +++ b/sys/dev/hyperv/netvsc/if_hnreg.h @@ -45,6 +45,7 @@ #define HN_NVS_TYPE_RXBUF_DISCONN 103 #define HN_NVS_TYPE_CHIM_CONN 104 #define HN_NVS_TYPE_CHIM_CONNRESP 105 +#define HN_NVS_TYPE_CHIM_DISCONN 106 #define HN_NVS_TYPE_NDIS_CONF 125 /* @@ -135,4 +136,12 @@ struct hn_nvs_chim_connresp { uint32_t nvs_sectsz; /* section size */ } __packed; +/* No response */ +struct hn_nvs_chim_disconn { + uint32_t nvs_type; /* HN_NVS_TYPE_CHIM_DISCONN */ + uint16_t nvs_sig; /* HN_NVS_CHIM_SIG */ + uint8_t nvs_rsvd[26]; +} __packed; +CTASSERT(sizeof(struct hn_nvs_chim_disconn) >= HN_NVS_REQSIZE_MIN); + #endif /* !_IF_HNREG_H_ */ From 0f9b848541eac48ef8a4661d5dc5cb2d93c0ee18 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Mon, 15 Aug 2016 05:08:41 +0000 Subject: [PATCH 08/67] hyperv/hn: Switch to vmbus xact APIs for sub-channel alloc request. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7480 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 13 ---- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 81 ++++++++++++++++++------- sys/dev/hyperv/netvsc/if_hnreg.h | 18 ++++++ sys/dev/hyperv/netvsc/if_hnvar.h | 2 +- 4 files changed, 77 insertions(+), 37 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index d9c17a8409fb..2288d842859c 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -73,9 +73,6 @@ static void hv_nv_on_receive(netvsc_dev *net_dev, static void hn_nvs_sent_none(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, const struct nvsp_msg_ *msg, int); -static void hn_nvs_sent_xact(struct hn_send_ctx *sndc, - struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, - const struct nvsp_msg_ *msg, int dlen); static struct hn_send_ctx hn_send_ctx_none = HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL); @@ -756,16 +753,6 @@ hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) } void -hn_nvs_sent_wakeup(struct hn_send_ctx *sndc __unused, - struct netvsc_dev_ *net_dev, struct vmbus_channel *chan __unused, - const struct nvsp_msg_ *msg, int dlen __unused) -{ - /* Copy the response back */ - memcpy(&net_dev->channel_init_packet, msg, sizeof(nvsp_msg)); - sema_post(&net_dev->channel_init_sema); -} - -static void hn_nvs_sent_xact(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg, int dlen) diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index 7daf7b282f5f..5e3473b7c1ea 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -46,9 +46,11 @@ __FBSDID("$FreeBSD$"); #include #include -#include "hv_net_vsc.h" -#include "hv_rndis.h" -#include "hv_rndis_filter.h" +#include +#include +#include +#include +#include struct hv_rf_recvinfo { const ndis_8021q_info *vlan_info; @@ -1060,12 +1062,16 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int ret; netvsc_dev *net_dev; rndis_device *rndis_dev; - nvsp_msg *init_pkt; rndis_offload_params offloads; struct rndis_recv_scale_cap rsscaps; uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap); netvsc_device_info *dev_info = (netvsc_device_info *)additl_info; device_t dev = sc->hn_dev; + struct hn_nvs_subch_req *req; + const struct hn_nvs_subch_resp *resp; + size_t resp_len; + struct vmbus_xact *xact; + uint32_t status, nsubch; rndis_dev = hv_get_rndis_device(); if (rndis_dev == NULL) { @@ -1153,36 +1159,65 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, goto out; } - /* request host to create sub channels */ - init_pkt = &net_dev->channel_init_packet; - memset(init_pkt, 0, sizeof(nvsp_msg)); + /* + * Ask NVS to allocate sub-channels. + */ + xact = vmbus_xact_get(sc->hn_xact, sizeof(*req)); + if (xact == NULL) { + if_printf(sc->hn_ifp, "no xact for nvs subch req\n"); + ret = ENXIO; + goto out; + } - init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel; - init_pkt->msgs.vers_5_msgs.subchannel_request.op = - NVSP_SUBCHANNE_ALLOCATE; - init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels = - net_dev->num_channel - 1; + req = vmbus_xact_req_data(xact); + req->nvs_type = HN_NVS_TYPE_SUBCH_REQ; + req->nvs_op = HN_NVS_SUBCH_OP_ALLOC; + req->nvs_nsubch = net_dev->num_channel - 1; + + hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); + vmbus_xact_activate(xact); - hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL); ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc); + req, sizeof(*req), (uint64_t)(uintptr_t)&sndc); if (ret != 0) { - device_printf(dev, "Fail to allocate subchannel\n"); + if_printf(sc->hn_ifp, "send nvs subch req failed: %d\n", ret); + vmbus_xact_deactivate(xact); + vmbus_xact_put(xact); goto out; } - sema_wait(&net_dev->channel_init_sema); - - if (init_pkt->msgs.vers_5_msgs.subchn_complete.status != - nvsp_status_success) { - ret = ENODEV; - device_printf(dev, "sub channel complete error\n"); + resp = vmbus_xact_wait(xact, &resp_len); + if (resp_len < sizeof(*resp)) { + if_printf(sc->hn_ifp, "invalid subch resp length %zu\n", + resp_len); + vmbus_xact_put(xact); + ret = EINVAL; + goto out; + } + if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) { + if_printf(sc->hn_ifp, "not subch resp, type %u\n", + resp->nvs_type); + vmbus_xact_put(xact); + ret = EINVAL; goto out; } - net_dev->num_channel = 1 + - init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels; + status = resp->nvs_status; + nsubch = resp->nvs_nsubch; + vmbus_xact_put(xact); + + if (status != HN_NVS_STATUS_OK) { + if_printf(sc->hn_ifp, "subch req failed: %x\n", status); + ret = EIO; + goto out; + } + if (nsubch > net_dev->num_channel - 1) { + if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n", + nsubch, net_dev->num_channel - 1); + nsubch = net_dev->num_channel - 1; + } + net_dev->num_channel = nsubch + 1; ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel); diff --git a/sys/dev/hyperv/netvsc/if_hnreg.h b/sys/dev/hyperv/netvsc/if_hnreg.h index ac18798af69b..109ece03f8de 100644 --- a/sys/dev/hyperv/netvsc/if_hnreg.h +++ b/sys/dev/hyperv/netvsc/if_hnreg.h @@ -47,6 +47,8 @@ #define HN_NVS_TYPE_CHIM_CONNRESP 105 #define HN_NVS_TYPE_CHIM_DISCONN 106 #define HN_NVS_TYPE_NDIS_CONF 125 +#define HN_NVS_TYPE_SUBCH_REQ 133 +#define HN_NVS_TYPE_SUBCH_RESP 133 /* same as SUBCH_REQ */ /* * Any size less than this one will _not_ work, e.g. hn_nvs_init @@ -144,4 +146,20 @@ struct hn_nvs_chim_disconn { } __packed; CTASSERT(sizeof(struct hn_nvs_chim_disconn) >= HN_NVS_REQSIZE_MIN); +#define HN_NVS_SUBCH_OP_ALLOC 1 + +struct hn_nvs_subch_req { + uint32_t nvs_type; /* HN_NVS_TYPE_SUBCH_REQ */ + uint32_t nvs_op; /* HN_NVS_SUBCH_OP_ */ + uint32_t nvs_nsubch; + uint8_t nvs_rsvd[20]; +} __packed; +CTASSERT(sizeof(struct hn_nvs_subch_req) >= HN_NVS_REQSIZE_MIN); + +struct hn_nvs_subch_resp { + uint32_t nvs_type; /* HN_NVS_TYPE_SUBCH_RESP */ + uint32_t nvs_status; /* HN_NVS_STATUS_ */ + uint32_t nvs_nsubch; +} __packed; + #endif /* !_IF_HNREG_H_ */ diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h index 9d2c1267ff73..39f01fffadaf 100644 --- a/sys/dev/hyperv/netvsc/if_hnvar.h +++ b/sys/dev/hyperv/netvsc/if_hnvar.h @@ -75,7 +75,7 @@ hn_send_ctx_init_simple(struct hn_send_ctx *sndc, hn_sent_callback_t cb, NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX, 0); } -void hn_nvs_sent_wakeup(struct hn_send_ctx *sndc, +void hn_nvs_sent_xact(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, const struct nvsp_msg_ *msg, int dlen); void hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx); From 2bafd72fdb93ff006377e0ec7d55725156ca4621 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Mon, 15 Aug 2016 09:23:08 +0000 Subject: [PATCH 09/67] Add the ARMv8.1 identification registers to the list we print when booting. MFC after: 1 week Sponsored by: ABT Systems Ltd --- sys/arm64/arm64/identcpu.c | 105 ++++++++++++++++++++++++++++++++++++- sys/arm64/include/armreg.h | 48 ++++++++++++++++- 2 files changed, 150 insertions(+), 3 deletions(-) diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c index 72e2021e6dc1..70a2d84183f2 100644 --- a/sys/arm64/arm64/identcpu.c +++ b/sys/arm64/arm64/identcpu.c @@ -188,6 +188,27 @@ print_cpu_features(u_int cpu) if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR0) != 0) { printed = 0; printf(" Instruction Set Attributes 0 = <"); + + switch (ID_AA64ISAR0_RDM(cpu_desc[cpu].id_aa64isar0)) { + case ID_AA64ISAR0_RDM_NONE: + break; + case ID_AA64ISAR0_RDM_IMPL: + printf("%sRDM", SEP_STR); + break; + default: + printf("%sUnknown RDM", SEP_STR); + } + + switch (ID_AA64ISAR0_ATOMIC(cpu_desc[cpu].id_aa64isar0)) { + case ID_AA64ISAR0_ATOMIC_NONE: + break; + case ID_AA64ISAR0_ATOMIC_IMPL: + printf("%sAtomic", SEP_STR); + break; + default: + printf("%sUnknown Atomic", SEP_STR); + } + switch (ID_AA64ISAR0_AES(cpu_desc[cpu].id_aa64isar0)) { case ID_AA64ISAR0_AES_NONE: break; @@ -466,8 +487,82 @@ print_cpu_features(u_int cpu) /* AArch64 Memory Model Feature Register 1 */ if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR1) != 0) { - printf(" Memory Model Features 1 = <%#lx>\n", - cpu_desc[cpu].id_aa64mmfr1); + printed = 0; + printf(" Memory Model Features 1 = <"); + + switch (ID_AA64MMFR1_PAN(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_PAN_NONE: + break; + case ID_AA64MMFR1_PAN_IMPL: + printf("%sPAN", SEP_STR); + break; + default: + printf("%sUnknown PAN", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_LO(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_LO_NONE: + break; + case ID_AA64MMFR1_LO_IMPL: + printf("%sLO", SEP_STR); + break; + default: + printf("%sUnknown LO", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_HPDS(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_HPDS_NONE: + break; + case ID_AA64MMFR1_HPDS_IMPL: + printf("%sHPDS", SEP_STR); + break; + default: + printf("%sUnknown HPDS", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_VH(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_VH_NONE: + break; + case ID_AA64MMFR1_VH_IMPL: + printf("%sVHE", SEP_STR); + break; + default: + printf("%sUnknown VHE", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_VMIDBITS(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_VMIDBITS_8: + break; + case ID_AA64MMFR1_VMIDBITS_16: + printf("%s16 VMID bits", SEP_STR); + break; + default: + printf("%sUnknown VMID bits", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_HAFDBS(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_HAFDBS_NONE: + break; + case ID_AA64MMFR1_HAFDBS_AF: + printf("%sAF", SEP_STR); + break; + case ID_AA64MMFR1_HAFDBS_AF_DBS: + printf("%sAF+DBS", SEP_STR); + break; + default: + printf("%sUnknown Hardware update AF/DBS", SEP_STR); + break; + } + + if ((cpu_desc[cpu].id_aa64mmfr1 & ~ID_AA64MMFR1_MASK) != 0) + printf("%s%#lx", SEP_STR, + cpu_desc[cpu].id_aa64mmfr1 & ~ID_AA64MMFR1_MASK); + printf(">\n"); } /* AArch64 Debug Feature Register 0 */ @@ -489,6 +584,9 @@ print_cpu_features(u_int cpu) case ID_AA64DFR0_PMU_VER_3: printf("%sPMUv3", SEP_STR); break; + case ID_AA64DFR0_PMU_VER_3_1: + printf("%sPMUv3+16 bit evtCount", SEP_STR); + break; case ID_AA64DFR0_PMU_VER_IMPL: printf("%sImplementation defined PMU", SEP_STR); break; @@ -512,6 +610,9 @@ print_cpu_features(u_int cpu) case ID_AA64DFR0_DEBUG_VER_8: printf("%sDebug v8", SEP_STR); break; + case ID_AA64DFR0_DEBUG_VER_8_VHE: + printf("%sDebug v8+VHE", SEP_STR); + break; default: printf("%sUnknown Debug", SEP_STR); break; diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index 392a2b3721e3..d812124f869d 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -172,6 +172,7 @@ #define ID_AA64DFR0_DEBUG_VER_MASK (0xf << ID_AA64DFR0_DEBUG_VER_SHIFT) #define ID_AA64DFR0_DEBUG_VER(x) ((x) & ID_AA64DFR0_DEBUG_VER_MASK) #define ID_AA64DFR0_DEBUG_VER_8 (0x6 << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_DEBUG_VER_8_VHE (0x7 << ID_AA64DFR0_DEBUG_VER_SHIFT) #define ID_AA64DFR0_TRACE_VER_SHIFT 4 #define ID_AA64DFR0_TRACE_VER_MASK (0xf << ID_AA64DFR0_TRACE_VER_SHIFT) #define ID_AA64DFR0_TRACE_VER(x) ((x) & ID_AA64DFR0_TRACE_VER_MASK) @@ -182,6 +183,7 @@ #define ID_AA64DFR0_PMU_VER(x) ((x) & ID_AA64DFR0_PMU_VER_MASK) #define ID_AA64DFR0_PMU_VER_NONE (0x0 << ID_AA64DFR0_PMU_VER_SHIFT) #define ID_AA64DFR0_PMU_VER_3 (0x1 << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_3_1 (0x4 << ID_AA64DFR0_PMU_VER_SHIFT) #define ID_AA64DFR0_PMU_VER_IMPL (0xf << ID_AA64DFR0_PMU_VER_SHIFT) #define ID_AA64DFR0_BRPS_SHIFT 12 #define ID_AA64DFR0_BRPS_MASK (0xf << ID_AA64DFR0_BRPS_SHIFT) @@ -197,7 +199,7 @@ ((((x) >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) + 1) /* ID_AA64ISAR0_EL1 */ -#define ID_AA64ISAR0_MASK 0x000ffff0 +#define ID_AA64ISAR0_MASK 0xf0fffff0 #define ID_AA64ISAR0_AES_SHIFT 4 #define ID_AA64ISAR0_AES_MASK (0xf << ID_AA64ISAR0_AES_SHIFT) #define ID_AA64ISAR0_AES(x) ((x) & ID_AA64ISAR0_AES_MASK) @@ -219,6 +221,16 @@ #define ID_AA64ISAR0_CRC32(x) ((x) & ID_AA64ISAR0_CRC32_MASK) #define ID_AA64ISAR0_CRC32_NONE (0x0 << ID_AA64ISAR0_CRC32_SHIFT) #define ID_AA64ISAR0_CRC32_BASE (0x1 << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_ATOMIC_SHIFT 20 +#define ID_AA64ISAR0_ATOMIC_MASK (0xf << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_ATOMIC(x) ((x) & ID_AA64ISAR0_ATOMIC_MASK) +#define ID_AA64ISAR0_ATOMIC_NONE (0x0 << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_ATOMIC_IMPL (0x2 << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_RDM_SHIFT 28 +#define ID_AA64ISAR0_RDM_MASK (0xf << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_RDM(x) ((x) & ID_AA64ISAR0_RDM_MASK) +#define ID_AA64ISAR0_RDM_NONE (0x0 << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_RDM_IMPL (0x1 << ID_AA64ISAR0_RDM_SHIFT) /* ID_AA64MMFR0_EL1 */ #define ID_AA64MMFR0_MASK 0xffffffff @@ -267,6 +279,40 @@ #define ID_AA64MMFR0_TGRAN4_IMPL (0x0 << ID_AA64MMFR0_TGRAN4_SHIFT) #define ID_AA64MMFR0_TGRAN4_NONE (0xf << ID_AA64MMFR0_TGRAN4_SHIFT) +/* ID_AA64MMFR1_EL1 */ +#define ID_AA64MMFR1_MASK 0x00ffffff +#define ID_AA64MMFR1_HAFDBS_SHIFT 0 +#define ID_AA64MMFR1_HAFDBS_MASK (0xf << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS(x) ((x) & ID_AA64MMFR1_HAFDBS_MASK) +#define ID_AA64MMFR1_HAFDBS_NONE (0x0 << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS_AF (0x1 << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS_AF_DBS (0x2 << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS_SHIFT 4 +#define ID_AA64MMFR1_VMIDBITS_MASK (0xf << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS(x) ((x) & ID_AA64MMFR1_VMIDBITS_MASK) +#define ID_AA64MMFR1_VMIDBITS_8 (0x0 << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS_16 (0x2 << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VH_SHIFT 8 +#define ID_AA64MMFR1_VH_MASK (0xf << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_VH(x) ((x) & ID_AA64MMFR1_VH_MASK) +#define ID_AA64MMFR1_VH_NONE (0x0 << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_VH_IMPL (0x1 << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_HPDS_SHIFT 12 +#define ID_AA64MMFR1_HPDS_MASK (0xf << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_HPDS(x) ((x) & ID_AA64MMFR1_HPDS_MASK) +#define ID_AA64MMFR1_HPDS_NONE (0x0 << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_HPDS_IMPL (0x1 << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_LO_SHIFT 16 +#define ID_AA64MMFR1_LO_MASK (0xf << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_LO(x) ((x) & ID_AA64MMFR1_LO_MASK) +#define ID_AA64MMFR1_LO_NONE (0x0 << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_LO_IMPL (0x1 << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_PAN_SHIFT 20 +#define ID_AA64MMFR1_PAN_MASK (0xf << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN(x) ((x) & ID_AA64MMFR1_PAN_MASK) +#define ID_AA64MMFR1_PAN_NONE (0x0 << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN_IMPL (0x1 << ID_AA64MMFR1_PAN_SHIFT) + /* ID_AA64PFR0_EL1 */ #define ID_AA64PFR0_MASK 0x0fffffff #define ID_AA64PFR0_EL0_SHIFT 0 From 47ead00d5ba986ee615123b2fba1d2af3e7bf1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Mon, 15 Aug 2016 09:30:21 +0000 Subject: [PATCH 10/67] Ensure that the sector size is a multiple of 4096 to avoid creating unaligned partitions when the actual sector size is hidden from us. PR: 211361 MFC after: 3 days --- usr.sbin/bsdinstall/partedit/gpart_ops.c | 26 ++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/usr.sbin/bsdinstall/partedit/gpart_ops.c b/usr.sbin/bsdinstall/partedit/gpart_ops.c index 04c8ceac994f..89d75294e2a3 100644 --- a/usr.sbin/bsdinstall/partedit/gpart_ops.c +++ b/usr.sbin/bsdinstall/partedit/gpart_ops.c @@ -795,6 +795,7 @@ gpart_max_free(struct ggeom *geom, intmax_t *npartstart) { struct gconfig *gc; struct gprovider *pp, **providers; + intmax_t sectorsize, stripesize, offset; intmax_t lastend; intmax_t start, end; intmax_t maxsize, maxstart; @@ -845,12 +846,25 @@ gpart_max_free(struct ggeom *geom, intmax_t *npartstart) pp = LIST_FIRST(&geom->lg_consumer)->lg_provider; - /* Compute beginning of new partition and maximum available space */ - if (pp->lg_stripesize > 0 && - (maxstart*pp->lg_sectorsize % pp->lg_stripesize) != 0) { - intmax_t offset = (pp->lg_stripesize - - ((maxstart*pp->lg_sectorsize) % pp->lg_stripesize)) / - pp->lg_sectorsize; + /* + * Round the start and size of the largest available space up to + * the nearest multiple of the adjusted stripe size. + * + * The adjusted stripe size is the least common multiple of the + * actual stripe size, or the sector size if no stripe size was + * reported, and 4096. The reason for this is that contemporary + * disks often have 4096-byte physical sectors but report 512 + * bytes instead for compatibility with older / broken operating + * systems and BIOSes. For the same reasons, virtualized storage + * may also report a 512-byte stripe size, or none at all. + */ + sectorsize = pp->lg_sectorsize; + if ((stripesize = pp->lg_stripesize) == 0) + stripesize = sectorsize; + while (stripesize % 4096 != 0) + stripesize *= 2; + if ((offset = maxstart * sectorsize % stripesize) != 0) { + offset = (stripesize - offset) / sectorsize; maxstart += offset; maxsize -= offset; } From dcb436c9360574009f18b3cdedd6b1709b7a883c Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Mon, 15 Aug 2016 10:16:08 +0000 Subject: [PATCH 11/67] Ensure that sctp_it_ctl.cur_it does not point to a free object (during a small time window). Thanks to Byron Campen for reporting the issue and suggesting a fix. MFC after: 3 days --- sys/netinet/sctputil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 148b0478a1fb..6d263ed63be3 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1280,6 +1280,7 @@ sctp_iterator_work(struct sctp_iterator *it) SCTP_INP_INFO_RLOCK(); SCTP_ITERATOR_LOCK(); + sctp_it_ctl.cur_it = it; if (it->inp) { SCTP_INP_RLOCK(it->inp); SCTP_INP_DECR_REF(it->inp); @@ -1287,6 +1288,7 @@ sctp_iterator_work(struct sctp_iterator *it) if (it->inp == NULL) { /* iterator is complete */ done_with_iterator: + sctp_it_ctl.cur_it = NULL; SCTP_ITERATOR_UNLOCK(); SCTP_INP_INFO_RUNLOCK(); if (it->function_atend != NULL) { @@ -1427,13 +1429,11 @@ sctp_iterator_worker(void) sctp_it_ctl.iterator_running = 1; TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { - sctp_it_ctl.cur_it = it; /* now lets work on this one */ TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); SCTP_IPI_ITERATOR_WQ_UNLOCK(); CURVNET_SET(it->vn); sctp_iterator_work(it); - sctp_it_ctl.cur_it = NULL; CURVNET_RESTORE(); SCTP_IPI_ITERATOR_WQ_LOCK(); /* sa_ignore FREED_MEMORY */ From 5bd90da0ef775f549d42eeb4bff36cab3e446771 Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 15 Aug 2016 10:46:33 +0000 Subject: [PATCH 12/67] Remove duplicate definition of get_pcb_td(). gcc works for detecting this error. --- sys/i386/include/md_var.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index c4c9ca96c36f..c3caf07a9106 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -69,6 +69,5 @@ void ppro_reenable_apic(void); void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec); union savefpu *get_pcb_user_save_td(struct thread *td); union savefpu *get_pcb_user_save_pcb(struct pcb *pcb); -struct pcb *get_pcb_td(struct thread *td); #endif /* !_MACHINE_MD_VAR_H_ */ From e760e292ae8fb467c034ee73935e257a740a0bd8 Mon Sep 17 00:00:00 2001 From: Sean Bruno Date: Mon, 15 Aug 2016 11:24:30 +0000 Subject: [PATCH 13/67] e1000: Add support for Kaby Lake IDs Fixup some errors when transitioning to/from low power states. Submitted by: erj Reviewed by: Jeffery Piper (jeffrey.e.piper@intel.com) MFC after: 3 days Relnotes: yes Sponsored by: Intel Corporation Differential Revision: https://reviews.freebsd.org/D7478 --- sys/dev/e1000/e1000_api.c | 4 ++++ sys/dev/e1000/e1000_hw.h | 8 ++++++++ sys/dev/e1000/e1000_ich8lan.c | 17 ++++++++++++++--- sys/dev/e1000/e1000_ich8lan.h | 2 +- sys/dev/e1000/e1000_phy.c | 22 ++++++++++++---------- sys/dev/e1000/if_em.c | 6 ++++++ 6 files changed, 45 insertions(+), 14 deletions(-) diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c index 28379cc572d3..52e260950d24 100644 --- a/sys/dev/e1000/e1000_api.c +++ b/sys/dev/e1000/e1000_api.c @@ -304,6 +304,10 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_PCH_SPT_I219_LM2: case E1000_DEV_ID_PCH_SPT_I219_V2: case E1000_DEV_ID_PCH_LBG_I219_LM3: + case E1000_DEV_ID_PCH_SPT_I219_LM4: + case E1000_DEV_ID_PCH_SPT_I219_V4: + case E1000_DEV_ID_PCH_SPT_I219_LM5: + case E1000_DEV_ID_PCH_SPT_I219_V5: mac->type = e1000_pch_spt; break; case E1000_DEV_ID_82575EB_COPPER: diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h index 1792e14ef38a..e1464a7b655a 100644 --- a/sys/dev/e1000/e1000_hw.h +++ b/sys/dev/e1000/e1000_hw.h @@ -142,6 +142,10 @@ struct e1000_hw; #define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 /* Sunrise Point-H PCH */ #define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 /* Sunrise Point-H PCH */ #define E1000_DEV_ID_PCH_LBG_I219_LM3 0x15B9 /* LEWISBURG PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_LM4 0x15D7 +#define E1000_DEV_ID_PCH_SPT_I219_V4 0x15D8 +#define E1000_DEV_ID_PCH_SPT_I219_LM5 0x15E3 +#define E1000_DEV_ID_PCH_SPT_I219_V5 0x15D6 #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 @@ -957,9 +961,13 @@ struct e1000_dev_spec_ich8lan { E1000_MUTEX nvm_mutex; E1000_MUTEX swflag_mutex; bool nvm_k1_enabled; + bool disable_k1_off; bool eee_disable; u16 eee_lp_ability; enum e1000_ulp_state ulp_state; + bool ulp_capability_disabled; + bool during_suspend_flow; + bool during_dpg_exit; }; struct e1000_dev_spec_82575 { diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c index ae97a8c0d389..4c50ce296385 100644 --- a/sys/dev/e1000/e1000_ich8lan.c +++ b/sys/dev/e1000/e1000_ich8lan.c @@ -288,7 +288,7 @@ static void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw) mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; E1000_WRITE_REG(hw, E1000_CTRL, mac_reg); E1000_WRITE_FLUSH(hw); - usec_delay(10); + msec_delay(1); mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; E1000_WRITE_REG(hw, E1000_CTRL, mac_reg); E1000_WRITE_FLUSH(hw); @@ -1625,7 +1625,17 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) hw->phy.ops.write_reg_locked(hw, I217_PLL_CLOCK_GATE_REG, phy_reg); - } + + if (speed == SPEED_1000) { + hw->phy.ops.read_reg_locked(hw, HV_PM_CTRL, + &phy_reg); + + phy_reg |= HV_PM_CTRL_K1_CLK_REQ; + + hw->phy.ops.write_reg_locked(hw, HV_PM_CTRL, + phy_reg); + } + } hw->phy.ops.release(hw); if (ret_val) @@ -1718,7 +1728,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG); u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); - if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE) + if ((pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE) && + (hw->dev_spec.ich8lan.disable_k1_off == FALSE)) fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE; else fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE; diff --git a/sys/dev/e1000/e1000_ich8lan.h b/sys/dev/e1000/e1000_ich8lan.h index edc1dd14ccc9..6d812911e8b8 100644 --- a/sys/dev/e1000/e1000_ich8lan.h +++ b/sys/dev/e1000/e1000_ich8lan.h @@ -239,7 +239,7 @@ /* PHY Power Management Control */ #define HV_PM_CTRL PHY_REG(770, 17) -#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 +#define HV_PM_CTRL_K1_CLK_REQ 0x200 #define HV_PM_CTRL_K1_ENABLE 0x4000 #define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28) diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c index 847d3155e2af..9684b43f5503 100644 --- a/sys/dev/e1000/e1000_phy.c +++ b/sys/dev/e1000/e1000_phy.c @@ -4146,12 +4146,13 @@ s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data) *data = E1000_READ_REG(hw, E1000_MPHY_DATA); /* Disable access to mPHY if it was originally disabled */ - if (locked) { + if (locked) ready = e1000_is_mphy_ready(hw); - if (!ready) - return -E1000_ERR_PHY; - } - E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, E1000_MPHY_DIS_ACCESS); + if (!ready) + return -E1000_ERR_PHY; + E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, + E1000_MPHY_DIS_ACCESS); + return E1000_SUCCESS; } @@ -4210,12 +4211,13 @@ s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data, E1000_WRITE_REG(hw, E1000_MPHY_DATA, data); /* Disable access to mPHY if it was originally disabled */ - if (locked) { + if (locked) ready = e1000_is_mphy_ready(hw); - if (!ready) - return -E1000_ERR_PHY; - } - E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, E1000_MPHY_DIS_ACCESS); + if (!ready) + return -E1000_ERR_PHY; + E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, + E1000_MPHY_DIS_ACCESS); + return E1000_SUCCESS; } diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index b8e9750efa37..7e2690eae084 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -193,6 +193,12 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V2, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH_LBG_I219_LM3, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM4, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V4, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM5, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V5, PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} }; From 07410fe461f461bccb0d1da02baf482484d85ae8 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Mon, 15 Aug 2016 11:54:39 +0000 Subject: [PATCH 14/67] elfcopy: silence GCC 5.3 unitialized variable warning Although it's a false positive there is little cost to initializing it always. Submitted by: adrian --- contrib/elftoolchain/elfcopy/ascii.c | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/elftoolchain/elfcopy/ascii.c b/contrib/elftoolchain/elfcopy/ascii.c index fb1edb3cce46..747c66bd0c5b 100644 --- a/contrib/elftoolchain/elfcopy/ascii.c +++ b/contrib/elftoolchain/elfcopy/ascii.c @@ -251,6 +251,7 @@ create_elf_from_srec(struct elfcopy *ecp, int ifd) sec_index = 1; sec_addr = entry = 0; while (fgets(line, _LINE_BUFSZ, ifp) != NULL) { + sz = 0; /* Silence GCC 5.3 unintialized variable warning */ if (line[0] == '\r' || line[0] == '\n') continue; if (line[0] == '$' && line[1] == '$') { From 0df377cbb8747aee4e6460e16fa41ce84ad34e00 Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Mon, 15 Aug 2016 12:13:14 +0000 Subject: [PATCH 15/67] pf: Add missing byte-order swap to pf_match_addr_range Without this, rules using address ranges (e.g. "10.1.1.1 - 10.1.1.5") did not match addresses correctly on little-endian systems. PR: 211796 Obtained from: OpenBSD (sthen) MFC after: 3 days --- sys/netpfil/pf/pf.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 0efc396062ad..2d32b7a288cc 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -2600,8 +2600,8 @@ pf_match_addr_range(struct pf_addr *b, struct pf_addr *e, switch (af) { #ifdef INET case AF_INET: - if ((a->addr32[0] < b->addr32[0]) || - (a->addr32[0] > e->addr32[0])) + if ((ntohl(a->addr32[0]) < ntohl(b->addr32[0])) || + (ntohl(a->addr32[0]) > ntohl(e->addr32[0]))) return (0); break; #endif /* INET */ @@ -2611,15 +2611,15 @@ pf_match_addr_range(struct pf_addr *b, struct pf_addr *e, /* check a >= b */ for (i = 0; i < 4; ++i) - if (a->addr32[i] > b->addr32[i]) + if (ntohl(a->addr32[i]) > ntohl(b->addr32[i])) break; - else if (a->addr32[i] < b->addr32[i]) + else if (ntohl(a->addr32[i]) < ntohl(b->addr32[i])) return (0); /* check a <= e */ for (i = 0; i < 4; ++i) - if (a->addr32[i] < e->addr32[i]) + if (ntohl(a->addr32[i]) < ntohl(e->addr32[i])) break; - else if (a->addr32[i] > e->addr32[i]) + else if (ntohl(a->addr32[i]) > ntohl(e->addr32[i])) return (0); break; } From 40de550ba7ddd143d894df50928634f8225abc0c Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 15 Aug 2016 12:56:45 +0000 Subject: [PATCH 16/67] Quick fix for locking fixes in r172250. The lock added there was per- virtual-device, but needs to be per-physical-device so that it protects shared data. Usually, scp->sc->write_in_progress got corrupted first and further corruption was limited when this variable was left at nonzero with no write in progress. Attempt to fix missing lock destruction in r162285. Put it with the lock destruction for r172250 after moving the latter. Both might be unreachable. To demonstrate the bug, find a buggy syscall or sysctl that calls printf(9) and run this often. Run hd /dev/zero >/dev/ttyvN for any N != 0. The console spam goes to ttyv0 and the non-console spam goes to ttyvN, so the lock provided no protection (but it helped for N == 0). --- sys/dev/syscons/syscons.c | 15 ++++++++------- sys/dev/syscons/syscons.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 063083e0b41d..a05300917198 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -2688,13 +2688,13 @@ sc_puts(scr_stat *scp, u_char *buf, int len, int kernel) #endif if (scp->tsw) { - if (!kdb_active && !mtx_owned(&scp->scr_lock)) { + if (!kdb_active && !mtx_owned(&scp->sc->scr_lock)) { need_unlock = 1; - mtx_lock_spin(&scp->scr_lock); + mtx_lock_spin(&scp->sc->scr_lock); } (*scp->tsw->te_puts)(scp, buf, len, kernel); if (need_unlock) - mtx_unlock_spin(&scp->scr_lock); + mtx_unlock_spin(&scp->sc->scr_lock); } if (scp->sc->delayed_next_scr) @@ -2859,8 +2859,10 @@ scinit(int unit, int flags) * disappeared... */ sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE); - if ((sc->flags & SC_INIT_DONE) == 0) + if ((sc->flags & SC_INIT_DONE) == 0) { + mtx_init(&sc->scr_lock, "scrlock", NULL, MTX_SPIN); SC_VIDEO_LOCKINIT(sc); + } adp = NULL; if (sc->adapter >= 0) { @@ -3077,7 +3079,8 @@ scterm(int unit, int flags) (*scp->tsw->te_term)(scp, &scp->ts); if (scp->ts != NULL) free(scp->ts, M_DEVBUF); - mtx_destroy(&scp->scr_lock); + mtx_destroy(&sc->scr_lock); + mtx_destroy(&sc->video_mtx); /* clear the structure */ if (!(flags & SC_KERNEL_CONSOLE)) { @@ -3302,8 +3305,6 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp) scp->history = NULL; scp->history_pos = 0; scp->history_size = 0; - - mtx_init(&scp->scr_lock, "scrlock", NULL, MTX_SPIN); } int diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h index 06e104595c2e..077a1067539e 100644 --- a/sys/dev/syscons/syscons.h +++ b/sys/dev/syscons/syscons.h @@ -230,6 +230,7 @@ typedef struct sc_softc { char switch_in_progress; char write_in_progress; char blink_in_progress; + struct mtx scr_lock; /* mutex for sc_puts() */ struct mtx video_mtx; long scrn_time_stamp; @@ -344,7 +345,6 @@ typedef struct scr_stat { int splash_save_mode; /* saved mode for splash screen */ int splash_save_status; /* saved status for splash screen */ - struct mtx scr_lock; /* mutex for sc_puts() */ #ifdef _SCR_MD_STAT_DECLARED_ scr_md_stat_t md; /* machine dependent vars */ #endif From e7560c836fd0857536482e51644e54a5ee9c8a74 Mon Sep 17 00:00:00 2001 From: Oleg Bulyzhin Date: Mon, 15 Aug 2016 13:06:29 +0000 Subject: [PATCH 17/67] Fix command: ipfw set (enable|disable) N (where N > 4). enable_sets() expects set bitmasks, not set numbers. MFC after: 3 days --- sys/netpfil/ipfw/ip_fw_sockopt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index 8031e311e89d..0823316e0884 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -1420,8 +1420,10 @@ manage_sets(struct ip_fw_chain *chain, ip_fw3_opheader *op3, if (rh->range.head.length != sizeof(ipfw_range_tlv)) return (1); - if (rh->range.set >= IPFW_MAX_SETS || - rh->range.new_set >= IPFW_MAX_SETS) + /* enable_sets() expects bitmasks. */ + if (op3->opcode != IP_FW_SET_ENABLE && + (rh->range.set >= IPFW_MAX_SETS || + rh->range.new_set >= IPFW_MAX_SETS)) return (EINVAL); ret = 0; From e85c2b0b126d3b224995ef6e2f568a2d36b20fc4 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Mon, 15 Aug 2016 14:28:08 +0000 Subject: [PATCH 18/67] elfcopy: add elf64-littleaarch64 output target support Sponsored by: The FreeBSD Foundation --- contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 | 1 + contrib/elftoolchain/libelftc/libelftc_bfdtarget.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 index 20dea3cb97d9..c340c0c5b68d 100644 --- a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 +++ b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 @@ -89,6 +89,7 @@ Known descriptor names and their properties include: .It Li elf64-ia64-big Ta ELF Ta MSB Ta 64 .It Li elf64-ia64-little Ta ELF Ta LSB Ta 64 .It Li elf64-little Ta ELF Ta LSB Ta 64 +.It Li elf64-littleaarch64 Ta ELF Ta LSB Ta 64 .It Li elf64-littlemips Ta ELF Ta LSB Ta 64 .It Li elf64-powerpc Ta ELF Ta MSB Ta 64 .It Li elf64-powerpcle Ta ELF Ta LSB Ta 64 diff --git a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c index 88f3220df0b0..d6a031e73090 100644 --- a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c +++ b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c @@ -249,6 +249,14 @@ struct _Elftc_Bfd_Target _libelftc_targets[] = { .bt_elfclass = ELFCLASS64, }, + { + .bt_name = "elf64-littleaarch64", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_AARCH64, + }, + { .bt_name = "elf64-littlemips", .bt_type = ETF_ELF, From abf3a584b6d126d74b5f947a76ee7d31d21a3ebf Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 15 Aug 2016 14:28:16 +0000 Subject: [PATCH 19/67] Change all uses of 'debugger' to kdb_active and remove this variable. This restores avoidance of doing dangerous things like calling wakeup() and callouts while in ddb. Initialization of 'debugger' was broken by removing the cndbctl() console method that was used mainly in this driver to initialize 'debugger' and switch to the console screen on entry to ddb. The screen switch was restored using the cngrab() method, but cngrab() is more general so it should not initialize 'debugger' and never did. 'debugger' was just an over-engineered alias for kdb_active anyway. It existed because kdb_active (when it was named ddb_active) was considered as a private kdb variable, and there are ordering problems initializing the variables atomically with the state that they represent, but an extra variable and method to set it increased these problems. The bug caused LORs, but WITNESS is normally misconfigured with WITNESS_SKIPSIN so it doesn't check the spinlocks used by wakeup() and callouts. --- sys/dev/syscons/syscons.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index a05300917198..549c94a0c410 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -172,8 +172,6 @@ SYSCTL_INT(_machdep, OID_AUTO, enable_panic_key, CTLFLAG_RW, &enable_panic_key, #define VTY_WCHAN(sc, vty) (&SC_DEV(sc, vty)) -static int debugger; - /* prototypes */ static int sc_allocate_keyboard(sc_softc_t *sc, int unit); static int scvidprobe(int unit, int flags, int cons); @@ -1815,7 +1813,7 @@ sccnupdate(scr_stat *scp) if (suspend_in_progress || scp->sc->font_loading_in_progress) return; - if (debugger > 0 || panicstr || shutdown_in_progress) { + if (kdb_active || panicstr || shutdown_in_progress) { sc_touch_scrn_saver(); } else if (scp != scp->sc->cur_scp) { return; @@ -1884,7 +1882,7 @@ scrn_timer(void *arg) #endif /* PC98 */ /* should we stop the screen saver? */ - if (debugger > 0 || panicstr || shutdown_in_progress) + if (kdb_active || panicstr || shutdown_in_progress) sc_touch_scrn_saver(); if (run_scrn_saver) { if (time_uptime > sc->scrn_time_stamp + scrn_blank_time) @@ -2279,7 +2277,7 @@ stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int)) mark_all(sc->cur_scp); if (sc->delayed_next_scr) sc_switch_scr(sc, sc->delayed_next_scr - 1); - if (debugger == 0) + if (!kdb_active) wakeup(&scrn_blanked); } @@ -2474,7 +2472,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr) DPRINTF(5, ("error 2, requested vty isn't open!\n")); return EINVAL; } - if ((debugger > 0) && (SC_STAT(tp)->smode.mode == VT_PROCESS)) { + if (kdb_active && SC_STAT(tp)->smode.mode == VT_PROCESS) { splx(s); DPRINTF(5, ("error 3, requested vty is in the VT_PROCESS mode\n")); return EINVAL; @@ -2495,7 +2493,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr) * is supposed to be locked by splhigh(), but the debugger may * be invoked at splhigh(). */ - if (debugger == 0) + if (!kdb_active) wakeup(VTY_WCHAN(sc,next_scr)); splx(s); DPRINTF(5, ("switch done (new == old)\n")); @@ -2518,7 +2516,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr) s = spltty(); /* wake up processes waiting for this vty */ - if (debugger == 0) + if (!kdb_active) wakeup(VTY_WCHAN(sc,next_scr)); /* wait for the controlling process to acknowledge, if necessary */ From 55f27b093d79fbfdc873218ef145d2350d6dd025 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Mon, 15 Aug 2016 14:58:25 +0000 Subject: [PATCH 20/67] Decrease the anti-congestion sleep in 480.leapfile-ntpd to 1 hour 24 hours is too long. Periodic scripts are executed serially, so when combined with the sleep in 410.pkg-audit periodic could actually take more than 24 hours and block the next invocation. Reviewed by: cy MFC after: 4 weeks Sponsored by: Spectra Logic Corp Differential Revision: https://reviews.freebsd.org/D7481 --- etc/periodic/daily/480.leapfile-ntpd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/periodic/daily/480.leapfile-ntpd b/etc/periodic/daily/480.leapfile-ntpd index 5a3ccceadf07..8a3836427b4e 100755 --- a/etc/periodic/daily/480.leapfile-ntpd +++ b/etc/periodic/daily/480.leapfile-ntpd @@ -16,7 +16,7 @@ case "$daily_ntpd_leapfile_enable" in case "$daily_ntpd_avoid_congestion" in [Yy][Ee][Ss]) # Avoid dogpiling - (sleep $(jot -r 1 0 86400); service ntpd onefetch) & + (sleep $(jot -r 1 0 3600); service ntpd onefetch) & ;; *) service ntpd onefetch From 304c3654d7d44aa6525d3bcdc33fd74deb2d858c Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 15 Aug 2016 15:34:53 +0000 Subject: [PATCH 21/67] Disable some more unsafe things in (low level) console mode: - never call up to the tty layer to restart output for keyboard input in console mode. This was already disallowed in kdb mode. Other cases are rarely reached. - disable the reboot, halt and powerdown keys in console mode. The suspend, standby and panic keys are still allowed, and aren't even conditonal on excessive configuration options. Some of these actions are still available in ddb mode as ddb commands which are equally unsafe. Some are useful at input prompts and should be restored when the locking is fixed. - disallow bells in kdb mode (should be in console mode, but the flag for that is not available). Visual bell gives very alarming behaviour by trying to use callouts which don't work in kdb mode. Audio bell uses timeouts and hardware resources with mutexes that can deadlock in reasonable use of ddb. Screen switches in kdb mode are not very safe, but they are important functionality and there is a lot of code to make them sort of work. --- sys/dev/syscons/syscons.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 549c94a0c410..f2840df3041b 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -3505,8 +3505,9 @@ next_code: scp->status |= CURSOR_ENABLED; sc_draw_cursor_image(scp); } + /* Only safe in Giant-locked context. */ tp = SC_DEV(sc, scp->index); - if (!kdb_active && tty_opened_ns(tp)) + if (!(flags & SCGETC_CN) && tty_opened_ns(tp)) sctty_outwakeup(tp); #endif } @@ -3557,21 +3558,21 @@ next_code: case RBT: #ifndef SC_DISABLE_REBOOT - if (enable_reboot) + if (enable_reboot && !(flags & SCGETC_CN)) shutdown_nice(0); #endif break; case HALT: #ifndef SC_DISABLE_REBOOT - if (enable_reboot) + if (enable_reboot && !(flags & SCGETC_CN)) shutdown_nice(RB_HALT); #endif break; case PDWN: #ifndef SC_DISABLE_REBOOT - if (enable_reboot) + if (enable_reboot && !(flags & SCGETC_CN)) shutdown_nice(RB_HALT|RB_POWEROFF); #endif break; @@ -3842,7 +3843,7 @@ sc_respond(scr_stat *scp, const u_char *p, int count, int wakeup) void sc_bell(scr_stat *scp, int pitch, int duration) { - if (cold || shutdown_in_progress || !enable_bell) + if (cold || kdb_active || shutdown_in_progress || !enable_bell) return; if (scp != scp->sc->cur_scp && (scp->sc->flags & SC_QUIET_BELL)) From 71e40e4a49782c11b31e38a624cc005f98b78ba8 Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 15 Aug 2016 17:08:25 +0000 Subject: [PATCH 22/67] Like scr_lock, the grab count needs to be per-physical-device to work. This bug corrupted the grab count on both vtys if the ungrabbed vty is different from the console, and failed to restore the keyboard state on the ungrabbed vty, but not restoring the latter usually left the keyboard mode part of it uncorrupted at 1 (K_XLATE), while after this fix the keyboard mode part is usually corrupted to 0 (K_RAW). While here, rename the grab count from 'grabbed' to grab_level. --- sys/dev/syscons/syscons.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index f2840df3041b..eb8fc1889b12 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -1661,7 +1661,7 @@ sc_cngrab(struct consdev *cp) if (scp->sc->kbd == NULL) return; - if (scp->grabbed++ > 0) + if (scp->sc->grab_level++ > 0) return; /* @@ -1687,7 +1687,7 @@ sc_cnungrab(struct consdev *cp) if (scp->sc->kbd == NULL) return; - if (--scp->grabbed > 0) + if (--scp->sc->grab_level > 0) return; kbdd_poll(scp->sc->kbd, FALSE); From 1388e8b13e19d13839b98046f332d98232f084c2 Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 15 Aug 2016 17:11:05 +0000 Subject: [PATCH 23/67] [Oops, the previous commit was missing the update to syscons.h.] Like scr_lock, the grab count needs to be per-physical-device to work. This bug corrupted the grab count on both vtys if the ungrabbed vty is different from the console, and failed to restore the keyboard state on the ungrabbed vty, but not restoring it usually left the keyboard mode part of the keyboard state uncorrupted at 1 (K_XLATE), while after this fix the keyboard mode part is usually corrupted to 0 (K_RAW). While here, rename the grab count from grabbed to grab_level. --- sys/dev/syscons/syscons.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h index 077a1067539e..af5fb9f45acf 100644 --- a/sys/dev/syscons/syscons.h +++ b/sys/dev/syscons/syscons.h @@ -230,6 +230,7 @@ typedef struct sc_softc { char switch_in_progress; char write_in_progress; char blink_in_progress; + int grab_level; struct mtx scr_lock; /* mutex for sc_puts() */ struct mtx video_mtx; @@ -304,7 +305,6 @@ typedef struct scr_stat { void *ts; int status; /* status (bitfield) */ - int grabbed; int kbd_mode; /* keyboard I/O mode */ int kbd_prev_mode; /* keyboard I/O mode */ From 59c1e950b95f27144ab0f6440235d5ecdcbf9666 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 15 Aug 2016 17:40:05 +0000 Subject: [PATCH 24/67] Make SGE parameter handling more VF-friendly. Add fields to hold the SGE control register and free list buffer sizes to the sge_params structure. Populate these new fields in t4_init_sge_params() for PF devices and change t4_read_chip_settings() to pull these values out of the params structure instead of reading registers directly. This will permit t4_read_chip_settings() to be reused for VF devices which cannot read SGE registers directly. While here, move the call to t4_init_sge_params() to get_params__post_init(). The VF driver will populate the SGE parameters structure via a different method before calling t4_read_chip_settings(). Reviewed by: np Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D7476 --- sys/dev/cxgbe/common/common.h | 2 ++ sys/dev/cxgbe/common/t4_hw.c | 5 +++++ sys/dev/cxgbe/t4_main.c | 2 ++ sys/dev/cxgbe/t4_sge.c | 6 ++---- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h index cc6edf32a3c7..1cbdf8ee059a 100644 --- a/sys/dev/cxgbe/common/common.h +++ b/sys/dev/cxgbe/common/common.h @@ -215,6 +215,8 @@ struct sge_params { int pad_boundary; int pack_boundary; int fl_pktshift; + u32 sge_control; + u32 sge_fl_buffer_size[SGE_FLBUF_SIZES]; }; struct tp_params { diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index 7ecdb81a44b8..689a7ab4f29c 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -7644,6 +7644,7 @@ int t4_init_sge_params(struct adapter *adapter) { u32 r; struct sge_params *sp = &adapter->params.sge; + unsigned i; r = t4_read_reg(adapter, A_SGE_INGRESS_RX_THRESHOLD); sp->counter_val[0] = G_THRESHOLD_0(r); @@ -7686,6 +7687,7 @@ int t4_init_sge_params(struct adapter *adapter) sp->page_shift = (r & M_HOSTPAGESIZEPF0) + 10; r = t4_read_reg(adapter, A_SGE_CONTROL); + sp->sge_control = r; sp->spg_len = r & F_EGRSTATUSPAGESIZE ? 128 : 64; sp->fl_pktshift = G_PKTSHIFT(r); sp->pad_boundary = 1 << (G_INGPADBOUNDARY(r) + 5); @@ -7698,6 +7700,9 @@ int t4_init_sge_params(struct adapter *adapter) else sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(r) + 5); } + for (i = 0; i < SGE_FLBUF_SIZES; i++) + sp->sge_fl_buffer_size[i] = t4_read_reg(adapter, + A_SGE_FL_BUFFER_SIZE0 + (4 * i)); return 0; } diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 31c5796587d6..089cdda04e71 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -3332,6 +3332,8 @@ get_params__post_init(struct adapter *sc) sc->vres.iscsi.size = val[1] - val[0] + 1; } + t4_init_sge_params(sc); + /* * We've got the params we wanted to query via the firmware. Now grab * some others directly from the chip. diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 51185f7e9d64..bd949b097fa0 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -625,11 +625,9 @@ t4_read_chip_settings(struct adapter *sc) struct sw_zone_info *swz, *safe_swz; struct hw_buf_info *hwb; - t4_init_sge_params(sc); - m = F_RXPKTCPLMODE; v = F_RXPKTCPLMODE; - r = t4_read_reg(sc, A_SGE_CONTROL); + r = sc->params.sge.sge_control; if ((r & m) != v) { device_printf(sc->dev, "invalid SGE_CONTROL(0x%x)\n", r); rc = EINVAL; @@ -647,7 +645,7 @@ t4_read_chip_settings(struct adapter *sc) /* Filter out unusable hw buffer sizes entirely (mark with -2). */ hwb = &s->hw_buf_info[0]; for (i = 0; i < nitems(s->hw_buf_info); i++, hwb++) { - r = t4_read_reg(sc, A_SGE_FL_BUFFER_SIZE0 + (4 * i)); + r = sc->params.sge.sge_fl_buffer_size[i]; hwb->size = r; hwb->zidx = hwsz_ok(sc, r) ? -1 : -2; hwb->next = -1; From e5e9897c5fb46f14ec5220b5fbbbb3c1a5bff7e6 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 15 Aug 2016 17:41:34 +0000 Subject: [PATCH 25/67] Update mailbox writes to work with VF devices. - Use alternate register locations for the data and control registers for VFs. - Do a dummy read to force the writes to the mailbox data registers to post before the write to the control register on VFs. - Do not check the PCI-e firmware register for errors on VFs. Reviewed by: np Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D7483 --- sys/dev/cxgbe/common/t4_hw.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index 689a7ab4f29c..a96538779d52 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -289,6 +289,14 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd, if ((size & 15) || size > MBOX_LEN) return -EINVAL; + if (adap->flags & IS_VF) { + if (is_t6(adap)) + data_reg = FW_T6VF_MBDATA_BASE_ADDR; + else + data_reg = FW_T4VF_MBDATA_BASE_ADDR; + ctl_reg = VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL); + } + /* * If we have a negative timeout, that implies that we can't sleep. */ @@ -343,6 +351,22 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd, for (i = 0; i < size; i += 8, p++) t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p)); + if (adap->flags & IS_VF) { + /* + * For the VFs, the Mailbox Data "registers" are + * actually backed by T4's "MA" interface rather than + * PL Registers (as is the case for the PFs). Because + * these are in different coherency domains, the write + * to the VF's PL-register-backed Mailbox Control can + * race in front of the writes to the MA-backed VF + * Mailbox Data "registers". So we need to do a + * read-back on at least one byte of the VF Mailbox + * Data registers before doing the write to the VF + * Mailbox Control register. + */ + t4_read_reg(adap, data_reg); + } + CH_DUMP_MBOX(adap, mbox, data_reg); t4_write_reg(adap, ctl_reg, F_MBMSGVALID | V_MBOWNER(X_MBOWNER_FW)); @@ -355,10 +379,13 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd, * Loop waiting for the reply; bail out if we time out or the firmware * reports an error. */ - for (i = 0; - !((pcie_fw = t4_read_reg(adap, A_PCIE_FW)) & F_PCIE_FW_ERR) && - i < timeout; - i += ms) { + pcie_fw = 0; + for (i = 0; i < timeout; i += ms) { + if (!(adap->flags & IS_VF)) { + pcie_fw = t4_read_reg(adap, A_PCIE_FW); + if (pcie_fw & F_PCIE_FW_ERR) + break; + } if (sleep_ok) { ms = delay[delay_idx]; /* last element may repeat */ if (delay_idx < ARRAY_SIZE(delay) - 1) From 8b2246b3494dd1d453d2f2d125c24119c7dd08a5 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 15 Aug 2016 17:42:54 +0000 Subject: [PATCH 26/67] Add support for register dumps on VF devices. - Add handling of VF register sets to t4_get_regs_len() and t4_get_regs(). - While here, use t4_get_regs_len() in the ioctl handler for regdump instead of inlining it. Reviewed by: np Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D7484 --- sys/dev/cxgbe/common/t4_hw.c | 67 ++++++++++++++++++++++++++++++++---- sys/dev/cxgbe/t4_main.c | 2 +- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index a96538779d52..ca6d2069a5f0 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -725,10 +725,14 @@ unsigned int t4_get_regs_len(struct adapter *adapter) switch (chip_version) { case CHELSIO_T4: + if (adapter->flags & IS_VF) + return FW_T4VF_REGMAP_SIZE; return T4_REGMAP_SIZE; case CHELSIO_T5: case CHELSIO_T6: + if (adapter->flags & IS_VF) + return FW_T4VF_REGMAP_SIZE; return T5_REGMAP_SIZE; } @@ -1207,6 +1211,18 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) 0x27e00, 0x27e04, }; + static const unsigned int t4vf_reg_ranges[] = { + VF_SGE_REG(A_SGE_VF_KDOORBELL), VF_SGE_REG(A_SGE_VF_GTS), + VF_MPS_REG(A_MPS_VF_CTL), + VF_MPS_REG(A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H), + VF_PL_REG(A_PL_VF_WHOAMI), VF_PL_REG(A_PL_VF_WHOAMI), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_STATUS), + FW_T4VF_MBDATA_BASE_ADDR, + FW_T4VF_MBDATA_BASE_ADDR + + ((NUM_CIM_PF_MAILBOX_DATA_INSTANCES - 1) * 4), + }; + static const unsigned int t5_reg_ranges[] = { 0x1008, 0x10c0, 0x10cc, 0x10f8, @@ -1982,6 +1998,18 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) 0x51300, 0x51308, }; + static const unsigned int t5vf_reg_ranges[] = { + VF_SGE_REG(A_SGE_VF_KDOORBELL), VF_SGE_REG(A_SGE_VF_GTS), + VF_MPS_REG(A_MPS_VF_CTL), + VF_MPS_REG(A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H), + VF_PL_REG(A_PL_VF_WHOAMI), VF_PL_REG(A_PL_VF_REVISION), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_STATUS), + FW_T4VF_MBDATA_BASE_ADDR, + FW_T4VF_MBDATA_BASE_ADDR + + ((NUM_CIM_PF_MAILBOX_DATA_INSTANCES - 1) * 4), + }; + static const unsigned int t6_reg_ranges[] = { 0x1008, 0x101c, 0x1024, 0x10a8, @@ -2559,6 +2587,18 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) 0x51300, 0x51324, }; + static const unsigned int t6vf_reg_ranges[] = { + VF_SGE_REG(A_SGE_VF_KDOORBELL), VF_SGE_REG(A_SGE_VF_GTS), + VF_MPS_REG(A_MPS_VF_CTL), + VF_MPS_REG(A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H), + VF_PL_REG(A_PL_VF_WHOAMI), VF_PL_REG(A_PL_VF_REVISION), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_STATUS), + FW_T6VF_MBDATA_BASE_ADDR, + FW_T6VF_MBDATA_BASE_ADDR + + ((NUM_CIM_PF_MAILBOX_DATA_INSTANCES - 1) * 4), + }; + u32 *buf_end = (u32 *)(buf + buf_size); const unsigned int *reg_ranges; int reg_ranges_size, range; @@ -2570,18 +2610,33 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) */ switch (chip_version) { case CHELSIO_T4: - reg_ranges = t4_reg_ranges; - reg_ranges_size = ARRAY_SIZE(t4_reg_ranges); + if (adap->flags & IS_VF) { + reg_ranges = t4vf_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t4vf_reg_ranges); + } else { + reg_ranges = t4_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t4_reg_ranges); + } break; case CHELSIO_T5: - reg_ranges = t5_reg_ranges; - reg_ranges_size = ARRAY_SIZE(t5_reg_ranges); + if (adap->flags & IS_VF) { + reg_ranges = t5vf_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t5vf_reg_ranges); + } else { + reg_ranges = t5_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t5_reg_ranges); + } break; case CHELSIO_T6: - reg_ranges = t6_reg_ranges; - reg_ranges_size = ARRAY_SIZE(t6_reg_ranges); + if (adap->flags & IS_VF) { + reg_ranges = t6vf_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t6vf_reg_ranges); + } else { + reg_ranges = t6_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t6_reg_ranges); + } break; default: diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 089cdda04e71..6b7edaf215d2 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -8765,7 +8765,7 @@ t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag, } case CHELSIO_T4_REGDUMP: { struct t4_regdump *regs = (struct t4_regdump *)data; - int reglen = is_t4(sc) ? T4_REGDUMP_SIZE : T5_REGDUMP_SIZE; + int reglen = t4_get_regs_len(sc); uint8_t *buf; if (regs->len < reglen) { From 430320729da032d40d9b6515a5e9582ff230bcba Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 15 Aug 2016 18:02:37 +0000 Subject: [PATCH 27/67] Fix restoring the kbd_mode part of the keyboard state in grab/ungrab. Simply change the mode to K_XLATE using a local variable and use the grab level as a flag to tell screen switches not to change it again, so that we don't need to switch scp->kbd_mode. We did the latter, but didn't have the complications to update the keyboard mode switch for every screen switch. sc->kbd_mode remains at its user setting for all scp's and ungrabbing restores to it. --- sys/dev/syscons/syscons.c | 17 ++++++++--------- sys/dev/syscons/syscons.h | 1 - 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index eb8fc1889b12..fe7472806103 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -1649,6 +1649,7 @@ static void sc_cngrab(struct consdev *cp) { scr_stat *scp; + int kbd_mode; if (!cold && sc_console->sc->cur_scp->index != sc_console->index && @@ -1670,11 +1671,9 @@ sc_cngrab(struct consdev *cp) */ kbdd_enable(scp->sc->kbd); - /* we shall always use the keyboard in the XLATE mode here */ - scp->kbd_prev_mode = scp->kbd_mode; - scp->kbd_mode = K_XLATE; - (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); - + /* Switch the keyboard to console mode (K_XLATE, polled) on all scp's. */ + kbd_mode = K_XLATE; + (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&kbd_mode); kbdd_poll(scp->sc->kbd, TRUE); } @@ -1690,10 +1689,10 @@ sc_cnungrab(struct consdev *cp) if (--scp->sc->grab_level > 0) return; + /* Restore keyboard mode (for the current, possibly-changed scp). */ kbdd_poll(scp->sc->kbd, FALSE); - - scp->kbd_mode = scp->kbd_prev_mode; (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); + kbdd_disable(scp->sc->kbd); } @@ -2667,7 +2666,7 @@ exchange_scr(sc_softc_t *sc) sc_set_border(scp, scp->border); /* set up the keyboard for the new screen */ - if (sc->old_scp->kbd_mode != scp->kbd_mode) + if (sc->grab_level == 0 && sc->old_scp->kbd_mode != scp->kbd_mode) (void)kbdd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); update_kbd_state(scp, scp->status, LOCK_MASK); @@ -3412,7 +3411,7 @@ next_code: if (!(flags & SCGETC_CN)) random_harvest_queue(&c, sizeof(c), 1, RANDOM_KEYBOARD); - if (scp->kbd_mode != K_XLATE) + if (sc->grab_level == 0 && scp->kbd_mode != K_XLATE) return KEYCHAR(c); /* if scroll-lock pressed allow history browsing */ diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h index af5fb9f45acf..e0aa0beb4328 100644 --- a/sys/dev/syscons/syscons.h +++ b/sys/dev/syscons/syscons.h @@ -306,7 +306,6 @@ typedef struct scr_stat { int status; /* status (bitfield) */ int kbd_mode; /* keyboard I/O mode */ - int kbd_prev_mode; /* keyboard I/O mode */ int cursor_pos; /* cursor buffer position */ int cursor_oldpos; /* cursor old buffer position */ From c73fb331154c72722d6e883c123b11d1bb9a9a7d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 15 Aug 2016 18:55:33 +0000 Subject: [PATCH 28/67] VOP_FSYNC() does not take cred as an argument. Correct comment. Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/kern/vfs_default.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 8679ad782a74..46443c6112b9 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -640,7 +640,6 @@ int vop_stdfsync(ap) struct vop_fsync_args /* { struct vnode *a_vp; - struct ucred *a_cred; int a_waitfor; struct thread *a_td; } */ *ap; From 576a9e496f956ab17d829716a29e5972e7d3f899 Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Mon, 15 Aug 2016 19:05:41 +0000 Subject: [PATCH 29/67] Disable tests for non-standard behaviour of dirname(3)/basename(3). The NetBSD ATF tests explicitly check that these functions do not modify their input. These tests are NetBSD-specific. They test for something that is not part of POSIX. PR: 211873 Reviewed by: ngie Differential Revision: https://reviews.freebsd.org/D7506 --- contrib/netbsd-tests/lib/libc/gen/t_basedirname.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrib/netbsd-tests/lib/libc/gen/t_basedirname.c b/contrib/netbsd-tests/lib/libc/gen/t_basedirname.c index 6c82cb471c27..184e660cc017 100644 --- a/contrib/netbsd-tests/lib/libc/gen/t_basedirname.c +++ b/contrib/netbsd-tests/lib/libc/gen/t_basedirname.c @@ -111,6 +111,7 @@ ATF_TC_BODY(basename_posix, tc) } else base = basename(NULL); +#ifdef __NetBSD__ /* * basename(3) is allowed to modify the input buffer. * However, that is considered hostile by some programs, @@ -127,6 +128,7 @@ ATF_TC_BODY(basename_posix, tc) test_basename_table[i].input); atf_tc_fail("Input buffer was modified."); } +#endif /* Make sure the result is correct. */ if (strcmp(test_basename_table[i].output, base) != 0) { @@ -162,6 +164,7 @@ ATF_TC_BODY(dirname_posix, tc) } else base = dirname(NULL); +#ifdef __NetBSD__ /* * dirname(3) is allowed to modify the input buffer. * However, that is considered hostile by some programs, @@ -178,6 +181,7 @@ ATF_TC_BODY(dirname_posix, tc) test_dirname_table[i].input); atf_tc_fail("Input buffer was modified."); } +#endif /* Make sure the result is correct. */ if (strcmp(test_dirname_table[i].output, base) != 0) { From 295af703a0d7987c6cf4987e7b7f5f07b3ca1221 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 15 Aug 2016 19:08:51 +0000 Subject: [PATCH 30/67] Add an implementation of fdatasync(2). The syscall is a trivial wrapper around new VOP_FDATASYNC(), sharing code with fsync(2). For all filesystems, this commit provides the implementation which delegates the work of VOP_FDATASYNC() to VOP_FSYNC(). This is functionally correct but not efficient. This is not yet POSIX-compliant implementation, because it does not ensure that queued AIO requests are completed before returning. Reviewed by: mckusick Discussed with: avg (ZFS), jhb (AIO part) Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D7471 --- include/unistd.h | 1 + lib/libc/sys/Symbol.map | 6 ++++ sys/compat/freebsd32/syscalls.master | 1 + sys/kern/syscalls.master | 5 +-- sys/kern/vfs_default.c | 9 +++++ sys/kern/vfs_syscalls.c | 49 ++++++++++++++++++---------- sys/kern/vnode_if.src | 8 +++++ 7 files changed, 59 insertions(+), 20 deletions(-) diff --git a/include/unistd.h b/include/unistd.h index 0fb36e50e050..eab79f20eb7d 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -384,6 +384,7 @@ extern int optind, opterr, optopt; /* ISO/IEC 9945-1: 1996 */ #if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE int fsync(int); +int fdatasync(int); /* * ftruncate() was in the POSIX Realtime Extension (it's used for shared diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index c1532ac94bc4..312b3660cfdc 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -400,6 +400,10 @@ FBSD_1.4 { recvmmsg; }; +FBSD_1.5 { + fdatasync; +}; + FBSDprivate_1.0 { ___acl_aclcheck_fd; __sys___acl_aclcheck_fd; @@ -594,6 +598,8 @@ FBSDprivate_1.0 { __sys_fstatfs; _fsync; __sys_fsync; + _fdatasync; + __sys_fdatasync; _futimes; __sys_futimes; _getaudit; diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 4b4ff2713382..3172db49d93d 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -1081,3 +1081,4 @@ 549 AUE_NULL NOPROTO { int numa_setaffinity(cpuwhich_t which, \ id_t id, \ const struct vm_domain_policy *policy); } +550 AUE_FSYNC NOPROTO { int fdatasync(int fd); } diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 08c0e0e533fc..2c5840639077 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -993,8 +993,9 @@ id_t id, \ struct vm_domain_policy_entry *policy); } 549 AUE_NULL STD { int numa_setaffinity(cpuwhich_t which, \ - id_t id, \ - const struct vm_domain_policy_entry *policy); } + id_t id, const struct \ + vm_domain_policy_entry *policy); } +550 AUE_FSYNC STD { int fdatasync(int fd); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 46443c6112b9..0e74b41d03ee 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -83,6 +83,7 @@ static int vop_stdset_text(struct vop_set_text_args *ap); static int vop_stdunset_text(struct vop_unset_text_args *ap); static int vop_stdget_writecount(struct vop_get_writecount_args *ap); static int vop_stdadd_writecount(struct vop_add_writecount_args *ap); +static int vop_stdfdatasync(struct vop_fdatasync_args *ap); static int vop_stdgetpages_async(struct vop_getpages_async_args *ap); /* @@ -111,6 +112,7 @@ struct vop_vector default_vnodeops = { .vop_bmap = vop_stdbmap, .vop_close = VOP_NULL, .vop_fsync = VOP_NULL, + .vop_fdatasync = vop_stdfdatasync, .vop_getpages = vop_stdgetpages, .vop_getpages_async = vop_stdgetpages_async, .vop_getwritemount = vop_stdgetwritemount, @@ -726,6 +728,13 @@ loop2: return (error); } +static int +vop_stdfdatasync(struct vop_fdatasync_args *ap) +{ + + return (VOP_FSYNC(ap->a_vp, MNT_WAIT, ap->a_td)); +} + /* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */ int vop_stdgetpages(ap) diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 68950e127e05..8419e360e559 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3354,20 +3354,8 @@ freebsd6_ftruncate(struct thread *td, struct freebsd6_ftruncate_args *uap) } #endif -/* - * Sync an open file. - */ -#ifndef _SYS_SYSPROTO_H_ -struct fsync_args { - int fd; -}; -#endif -int -sys_fsync(td, uap) - struct thread *td; - struct fsync_args /* { - int fd; - } */ *uap; +static int +kern_fsync(struct thread *td, int fd, bool fullsync) { struct vnode *vp; struct mount *mp; @@ -3375,11 +3363,15 @@ sys_fsync(td, uap) cap_rights_t rights; int error, lock_flags; - AUDIT_ARG_FD(uap->fd); - error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_FSYNC), &fp); + AUDIT_ARG_FD(fd); + error = getvnode(td, fd, cap_rights_init(&rights, CAP_FSYNC), &fp); if (error != 0) return (error); vp = fp->f_vnode; +#if 0 + if (!fullsync) + /* XXXKIB: compete outstanding aio writes */; +#endif error = vn_start_write(vp, &mp, V_WAIT | PCATCH); if (error != 0) goto drop; @@ -3396,8 +3388,7 @@ sys_fsync(td, uap) vm_object_page_clean(vp->v_object, 0, 0, 0); VM_OBJECT_WUNLOCK(vp->v_object); } - error = VOP_FSYNC(vp, MNT_WAIT, td); - + error = fullsync ? VOP_FSYNC(vp, MNT_WAIT, td) : VOP_FDATASYNC(vp, td); VOP_UNLOCK(vp, 0); vn_finished_write(mp); drop: @@ -3405,6 +3396,28 @@ drop: return (error); } +/* + * Sync an open file. + */ +#ifndef _SYS_SYSPROTO_H_ +struct fsync_args { + int fd; +}; +#endif +int +sys_fsync(struct thread *td, struct fsync_args *uap) +{ + + return (kern_fsync(td, uap->fd, true)); +} + +int +sys_fdatasync(struct thread *td, struct fdatasync_args *uap) +{ + + return (kern_fsync(td, uap->fd, false)); +} + /* * Rename files. Source and destination must either both be directories, or * both not be directories. If target is a directory, it must be empty. diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 9f3aa140d7ed..648de9a11263 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -703,6 +703,14 @@ vop_add_writecount { IN int inc; }; +%% fdatasync vp L L L + +vop_fdatasync { + IN struct vnode *vp; + IN struct thread *td; +}; + + # The VOPs below are spares at the end of the table to allow new VOPs to be # added in stable branches without breaking the KBI. New VOPs in HEAD should # be added above these spares. When merging a new VOP to a stable branch, From 1d2537a26a377b89497422b26f32e18d2dcead8d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 15 Aug 2016 19:15:46 +0000 Subject: [PATCH 31/67] Regen after r304176, fdatasync(2) addition. --- sys/compat/freebsd32/freebsd32_proto.h | 2 +- sys/compat/freebsd32/freebsd32_syscall.h | 5 +++-- sys/compat/freebsd32/freebsd32_syscalls.c | 3 ++- sys/compat/freebsd32/freebsd32_sysent.c | 3 ++- .../freebsd32/freebsd32_systrace_args.c | 22 +++++++++++++++++++ sys/kern/init_sysent.c | 3 ++- sys/kern/syscalls.c | 3 ++- sys/kern/systrace_args.c | 22 +++++++++++++++++++ sys/sys/syscall.h | 5 +++-- sys/sys/syscall.mk | 5 +++-- sys/sys/sysproto.h | 7 +++++- 11 files changed, 68 insertions(+), 12 deletions(-) diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h index 894d2ac67c73..538892efc44f 100644 --- a/sys/compat/freebsd32/freebsd32_proto.h +++ b/sys/compat/freebsd32/freebsd32_proto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 303699 2016-08-03 06:33:04Z ed + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #ifndef _FREEBSD32_SYSPROTO_H_ diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h index 6493561c7bc8..54292f7a4b4e 100644 --- a/sys/compat/freebsd32/freebsd32_syscall.h +++ b/sys/compat/freebsd32/freebsd32_syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 303699 2016-08-03 06:33:04Z ed + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #define FREEBSD32_SYS_syscall 0 @@ -457,4 +457,5 @@ #define FREEBSD32_SYS_freebsd32_utimensat 547 #define FREEBSD32_SYS_numa_getaffinity 548 #define FREEBSD32_SYS_numa_setaffinity 549 -#define FREEBSD32_SYS_MAXSYSCALL 550 +#define FREEBSD32_SYS_fdatasync 550 +#define FREEBSD32_SYS_MAXSYSCALL 551 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index 239ec7405210..27f361c65107 100644 --- a/sys/compat/freebsd32/freebsd32_syscalls.c +++ b/sys/compat/freebsd32/freebsd32_syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 303699 2016-08-03 06:33:04Z ed + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 304176 2016-08-15 19:08:51Z kib */ const char *freebsd32_syscallnames[] = { @@ -583,4 +583,5 @@ const char *freebsd32_syscallnames[] = { "freebsd32_utimensat", /* 547 = freebsd32_utimensat */ "numa_getaffinity", /* 548 = numa_getaffinity */ "numa_setaffinity", /* 549 = numa_setaffinity */ + "fdatasync", /* 550 = fdatasync */ }; diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index 0b0195149639..5a98f2a6385b 100644 --- a/sys/compat/freebsd32/freebsd32_sysent.c +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 303699 2016-08-03 06:33:04Z ed + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #include "opt_compat.h" @@ -626,4 +626,5 @@ struct sysent freebsd32_sysent[] = { { AS(freebsd32_utimensat_args), (sy_call_t *)freebsd32_utimensat, AUE_FUTIMESAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 547 = freebsd32_utimensat */ { AS(numa_getaffinity_args), (sy_call_t *)sys_numa_getaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 548 = numa_getaffinity */ { AS(numa_setaffinity_args), (sy_call_t *)sys_numa_setaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 549 = numa_setaffinity */ + { AS(fdatasync_args), (sy_call_t *)sys_fdatasync, AUE_FSYNC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 550 = fdatasync */ }; diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c index 72d3a78fa310..0bc7f515a6ad 100644 --- a/sys/compat/freebsd32/freebsd32_systrace_args.c +++ b/sys/compat/freebsd32/freebsd32_systrace_args.c @@ -3316,6 +3316,13 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 3; break; } + /* fdatasync */ + case 550: { + struct fdatasync_args *p = params; + iarg[0] = p->fd; /* int */ + *n_args = 1; + break; + } default: *n_args = 0; break; @@ -8902,6 +8909,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; + /* fdatasync */ + case 550: + switch(ndx) { + case 0: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10783,6 +10800,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; + /* fdatasync */ + case 550: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 091305205101..d0a0daa77233 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery + * created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #include "opt_compat.h" @@ -596,4 +596,5 @@ struct sysent sysent[] = { { AS(utimensat_args), (sy_call_t *)sys_utimensat, AUE_FUTIMESAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 547 = utimensat */ { AS(numa_getaffinity_args), (sy_call_t *)sys_numa_getaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 548 = numa_getaffinity */ { AS(numa_setaffinity_args), (sy_call_t *)sys_numa_setaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 549 = numa_setaffinity */ + { AS(fdatasync_args), (sy_call_t *)sys_fdatasync, AUE_FSYNC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 550 = fdatasync */ }; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 3463236f4e1d..8b5f1897b6ac 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery + * created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib */ const char *syscallnames[] = { @@ -557,4 +557,5 @@ const char *syscallnames[] = { "utimensat", /* 547 = utimensat */ "numa_getaffinity", /* 548 = numa_getaffinity */ "numa_setaffinity", /* 549 = numa_setaffinity */ + "fdatasync", /* 550 = fdatasync */ }; diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c index 38e1924dfcac..82ec68449296 100644 --- a/sys/kern/systrace_args.c +++ b/sys/kern/systrace_args.c @@ -3326,6 +3326,13 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 3; break; } + /* fdatasync */ + case 550: { + struct fdatasync_args *p = params; + iarg[0] = p->fd; /* int */ + *n_args = 1; + break; + } default: *n_args = 0; break; @@ -8862,6 +8869,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; + /* fdatasync */ + case 550: + switch(ndx) { + case 0: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10778,6 +10795,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; + /* fdatasync */ + case 550: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index d2cc1bfe479d..599524be83cc 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery + * created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #define SYS_syscall 0 @@ -467,4 +467,5 @@ #define SYS_utimensat 547 #define SYS_numa_getaffinity 548 #define SYS_numa_setaffinity 549 -#define SYS_MAXSYSCALL 550 +#define SYS_fdatasync 550 +#define SYS_MAXSYSCALL 551 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 9332dcda230c..7c7f8af1ef8e 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -1,7 +1,7 @@ # FreeBSD system call object files. # DO NOT EDIT-- this file is automatically generated. # $FreeBSD$ -# created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery +# created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib MIASM = \ syscall.o \ exit.o \ @@ -395,4 +395,5 @@ MIASM = \ futimens.o \ utimensat.o \ numa_getaffinity.o \ - numa_setaffinity.o + numa_setaffinity.o \ + fdatasync.o diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index fab19ad6570e..5e9a8d37aace 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery + * created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #ifndef _SYS_SYSPROTO_H_ @@ -1788,6 +1788,9 @@ struct numa_setaffinity_args { char id_l_[PADL_(id_t)]; id_t id; char id_r_[PADR_(id_t)]; char policy_l_[PADL_(const struct vm_domain_policy_entry *)]; const struct vm_domain_policy_entry * policy; char policy_r_[PADR_(const struct vm_domain_policy_entry *)]; }; +struct fdatasync_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_sys_exit(struct thread *, struct sys_exit_args *); int sys_fork(struct thread *, struct fork_args *); @@ -2174,6 +2177,7 @@ int sys_futimens(struct thread *, struct futimens_args *); int sys_utimensat(struct thread *, struct utimensat_args *); int sys_numa_getaffinity(struct thread *, struct numa_getaffinity_args *); int sys_numa_setaffinity(struct thread *, struct numa_setaffinity_args *); +int sys_fdatasync(struct thread *, struct fdatasync_args *); #ifdef COMPAT_43 @@ -2951,6 +2955,7 @@ int freebsd10_pipe(struct thread *, struct freebsd10_pipe_args *); #define SYS_AUE_utimensat AUE_FUTIMESAT #define SYS_AUE_numa_getaffinity AUE_NULL #define SYS_AUE_numa_setaffinity AUE_NULL +#define SYS_AUE_fdatasync AUE_FSYNC #undef PAD_ #undef PADL_ From 47e61f6cc65e644d7e954d01642e2462fbe246c5 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 15 Aug 2016 19:17:00 +0000 Subject: [PATCH 32/67] Implement VOP_FDATASYNC() for msdosfs. Standard VOP_FSYNC() implementation just syncs data buffers, and due to this, is the correct and efficient implementation for msdosfs or any other filesystem which uses bufer cache trivially. Provide globally visible wrapper vop_stdfdatasync_buf() for future consumption by other filesystems. Reviewed by: mckusick Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D7471 --- sys/fs/msdosfs/msdosfs_vnops.c | 1 + sys/kern/vfs_default.c | 11 +++++++++++ sys/sys/vnode.h | 1 + 3 files changed, 13 insertions(+) diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index 04be9672deb3..9ab5db614ded 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -1897,6 +1897,7 @@ struct vop_vector msdosfs_vnodeops = { .vop_close = msdosfs_close, .vop_create = msdosfs_create, .vop_fsync = msdosfs_fsync, + .vop_fdatasync = vop_stdfdatasync_buf, .vop_getattr = msdosfs_getattr, .vop_inactive = msdosfs_inactive, .vop_link = msdosfs_link, diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 0e74b41d03ee..b4e5a9d28358 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -735,6 +735,17 @@ vop_stdfdatasync(struct vop_fdatasync_args *ap) return (VOP_FSYNC(ap->a_vp, MNT_WAIT, ap->a_td)); } +int +vop_stdfdatasync_buf(struct vop_fdatasync_args *ap) +{ + struct vop_fsync_args apf; + + apf.a_vp = ap->a_vp; + apf.a_waitfor = MNT_WAIT; + apf.a_td = ap->a_td; + return (vop_stdfsync(&apf)); +} + /* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */ int vop_stdgetpages(ap) diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 02707117d21b..181ec7f1d5e0 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -720,6 +720,7 @@ int vfs_write_suspend(struct mount *mp, int flags); int vfs_write_suspend_umnt(struct mount *mp); void vnlru_free(int, struct vfsops *); int vop_stdbmap(struct vop_bmap_args *); +int vop_stdfdatasync_buf(struct vop_fdatasync_args *); int vop_stdfsync(struct vop_fsync_args *); int vop_stdgetwritemount(struct vop_getwritemount_args *); int vop_stdgetpages(struct vop_getpages_args *); From 2f514f92cf07ce21737ac4fb6ef832f503f4a7af Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 15 Aug 2016 19:22:23 +0000 Subject: [PATCH 33/67] Implement VOP_FDATASYNC() for UFS. Reviewed by: mckusick Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D7471 --- sys/ufs/ffs/ffs_extern.h | 5 +++ sys/ufs/ffs/ffs_vnops.c | 85 +++++++++++++++++++++++++++++----------- 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index b4ec348f3329..203bc6684d01 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -174,6 +174,11 @@ void softdep_freework(struct workhead *); * deadlock when flushing snapshot inodes while holding snaplk. */ #define NO_INO_UPDT 0x00000001 +/* + * Request data sync only from ffs_syncvnode(), not touching even more + * metadata than NO_INO_UPDT. + */ +#define DATA_ONLY 0x00000002 int ffs_rdonly(struct inode *); diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 69182850ffe2..27654804046d 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -103,6 +103,7 @@ __FBSDID("$FreeBSD$"); extern int ffs_rawread(struct vnode *vp, struct uio *uio, int *workdone); #endif static vop_fsync_t ffs_fsync; +static vop_fdatasync_t ffs_fdatasync; static vop_lock1_t ffs_lock; static vop_read_t ffs_read; static vop_write_t ffs_write; @@ -123,6 +124,7 @@ static vop_vptofh_t ffs_vptofh; struct vop_vector ffs_vnodeops1 = { .vop_default = &ufs_vnodeops, .vop_fsync = ffs_fsync, + .vop_fdatasync = ffs_fdatasync, .vop_getpages = vnode_pager_local_getpages, .vop_getpages_async = vnode_pager_local_getpages_async, .vop_lock1 = ffs_lock, @@ -135,6 +137,7 @@ struct vop_vector ffs_vnodeops1 = { struct vop_vector ffs_fifoops1 = { .vop_default = &ufs_fifoops, .vop_fsync = ffs_fsync, + .vop_fdatasync = ffs_fdatasync, .vop_reallocblks = ffs_reallocblks, /* XXX: really ??? */ .vop_vptofh = ffs_vptofh, }; @@ -143,6 +146,7 @@ struct vop_vector ffs_fifoops1 = { struct vop_vector ffs_vnodeops2 = { .vop_default = &ufs_vnodeops, .vop_fsync = ffs_fsync, + .vop_fdatasync = ffs_fdatasync, .vop_getpages = vnode_pager_local_getpages, .vop_getpages_async = vnode_pager_local_getpages_async, .vop_lock1 = ffs_lock, @@ -161,6 +165,7 @@ struct vop_vector ffs_vnodeops2 = { struct vop_vector ffs_fifoops2 = { .vop_default = &ufs_fifoops, .vop_fsync = ffs_fsync, + .vop_fdatasync = ffs_fdatasync, .vop_lock1 = ffs_lock, .vop_reallocblks = ffs_reallocblks, .vop_strategy = ffsext_strategy, @@ -216,10 +221,10 @@ ffs_syncvnode(struct vnode *vp, int waitfor, int flags) { struct inode *ip; struct bufobj *bo; - struct buf *bp; - struct buf *nbp; + struct buf *bp, *nbp; ufs_lbn_t lbn; - int error, wait, passes; + int error, passes; + bool still_dirty, wait; ip = VTOI(vp); ip->i_flag &= ~IN_NEEDSYNC; @@ -238,7 +243,7 @@ ffs_syncvnode(struct vnode *vp, int waitfor, int flags) */ error = 0; passes = 0; - wait = 0; /* Always do an async pass first. */ + wait = false; /* Always do an async pass first. */ lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1)); BO_LOCK(bo); loop: @@ -254,15 +259,23 @@ loop: if ((bp->b_vflags & BV_SCANNED) != 0) continue; bp->b_vflags |= BV_SCANNED; - /* Flush indirects in order. */ + /* + * Flush indirects in order, if requested. + * + * Note that if only datasync is requested, we can + * skip indirect blocks when softupdates are not + * active. Otherwise we must flush them with data, + * since dependencies prevent data block writes. + */ if (waitfor == MNT_WAIT && bp->b_lblkno <= -NDADDR && - lbn_level(bp->b_lblkno) >= passes) + (lbn_level(bp->b_lblkno) >= passes || + ((flags & DATA_ONLY) != 0 && !DOINGSOFTDEP(vp)))) continue; if (bp->b_lblkno > lbn) panic("ffs_syncvnode: syncing truncated data."); if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL) == 0) { BO_UNLOCK(bo); - } else if (wait != 0) { + } else if (wait) { if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK, BO_LOCKPTR(bo)) != 0) { @@ -330,30 +343,58 @@ next: * these will be done with one sync and one async pass. */ if (bo->bo_dirty.bv_cnt > 0) { - /* Write the inode after sync passes to flush deps. */ - if (wait && DOINGSOFTDEP(vp) && (flags & NO_INO_UPDT) == 0) { - BO_UNLOCK(bo); - ffs_update(vp, 1); - BO_LOCK(bo); + if ((flags & DATA_ONLY) == 0) { + still_dirty = true; + } else { + /* + * For data-only sync, dirty indirect buffers + * are ignored. + */ + still_dirty = false; + TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) { + if (bp->b_lblkno > -NDADDR) { + still_dirty = true; + break; + } + } } - /* switch between sync/async. */ - wait = !wait; - if (wait == 1 || ++passes < NIADDR + 2) - goto loop; + + if (still_dirty) { + /* Write the inode after sync passes to flush deps. */ + if (wait && DOINGSOFTDEP(vp) && + (flags & NO_INO_UPDT) == 0) { + BO_UNLOCK(bo); + ffs_update(vp, 1); + BO_LOCK(bo); + } + /* switch between sync/async. */ + wait = !wait; + if (wait || ++passes < NIADDR + 2) + goto loop; #ifdef INVARIANTS - if (!vn_isdisk(vp, NULL)) - vn_printf(vp, "ffs_fsync: dirty "); + if (!vn_isdisk(vp, NULL)) + vn_printf(vp, "ffs_fsync: dirty "); #endif + } } BO_UNLOCK(bo); error = 0; - if ((flags & NO_INO_UPDT) == 0) - error = ffs_update(vp, 1); - if (DOINGSUJ(vp)) - softdep_journal_fsync(VTOI(vp)); + if ((flags & DATA_ONLY) == 0) { + if ((flags & NO_INO_UPDT) == 0) + error = ffs_update(vp, 1); + if (DOINGSUJ(vp)) + softdep_journal_fsync(VTOI(vp)); + } return (error); } +static int +ffs_fdatasync(struct vop_fdatasync_args *ap) +{ + + return (ffs_syncvnode(ap->a_vp, MNT_WAIT, DATA_ONLY)); +} + static int ffs_lock(ap) struct vop_lock1_args /* { From 43e5b7b6b3f6d207ea8a72102a7a000e1f4e577f Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 15 Aug 2016 19:37:18 +0000 Subject: [PATCH 34/67] Restructure the grabbing functions into mere wrappers of new open and close functions. Scattered calls to sc_cnputc() and sc_cngetc() were broken by turning the semi-reentrant inline context-switching code in these functions into the grabbing functions. cncheckc() calls for panic dumps are the main broken case. The grabbing functions have special behaviour (mainly screen switching in sc_cngrab()) which makes them unsuitable as replacements for the inline code. --- sys/dev/syscons/syscons.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index fe7472806103..4b7c14dac030 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -1645,8 +1645,12 @@ sc_cnterm(struct consdev *cp) sc_console = NULL; } +struct sc_cnstate; /* not used yet */ +static void sccnclose(sc_softc_t *sc, struct sc_cnstate *sp); +static void sccnopen(sc_softc_t *sc, struct sc_cnstate *sp, int flags); + static void -sc_cngrab(struct consdev *cp) +sccnopen(sc_softc_t *sc, struct sc_cnstate *sp, int flags) { scr_stat *scp; int kbd_mode; @@ -1662,9 +1666,6 @@ sc_cngrab(struct consdev *cp) if (scp->sc->kbd == NULL) return; - if (scp->sc->grab_level++ > 0) - return; - /* * Make sure the keyboard is accessible even when the kbd device * driver is disabled. @@ -1678,7 +1679,7 @@ sc_cngrab(struct consdev *cp) } static void -sc_cnungrab(struct consdev *cp) +sccnclose(sc_softc_t *sc, struct sc_cnstate *sp) { scr_stat *scp; @@ -1686,9 +1687,6 @@ sc_cnungrab(struct consdev *cp) if (scp->sc->kbd == NULL) return; - if (--scp->sc->grab_level > 0) - return; - /* Restore keyboard mode (for the current, possibly-changed scp). */ kbdd_poll(scp->sc->kbd, FALSE); (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); @@ -1696,6 +1694,26 @@ sc_cnungrab(struct consdev *cp) kbdd_disable(scp->sc->kbd); } +static void +sc_cngrab(struct consdev *cp) +{ + sc_softc_t *sc; + + sc = sc_console->sc; + if (sc->grab_level++ == 0) + sccnopen(sc, NULL, 0); +} + +static void +sc_cnungrab(struct consdev *cp) +{ + sc_softc_t *sc; + + sc = sc_console->sc; + if (--sc->grab_level == 0) + sccnclose(sc, NULL); +} + static void sc_cnputc(struct consdev *cd, int c) { From 2256eed3eb0503203262b85a4591e7fc502598e9 Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Mon, 15 Aug 2016 19:42:21 +0000 Subject: [PATCH 35/67] Let CloudABI use fdatasync() as well. Now that FreeBSD supports fdatasync() natively, we can tidy up CloudABI's equivalent system call to use that instead. --- sys/compat/cloudabi/cloudabi_fd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sys/compat/cloudabi/cloudabi_fd.c b/sys/compat/cloudabi/cloudabi_fd.c index c044adcdf1d8..ae99bb410dc1 100644 --- a/sys/compat/cloudabi/cloudabi_fd.c +++ b/sys/compat/cloudabi/cloudabi_fd.c @@ -172,12 +172,11 @@ int cloudabi_sys_fd_datasync(struct thread *td, struct cloudabi_sys_fd_datasync_args *uap) { - struct fsync_args fsync_args = { + struct fdatasync_args fdatasync_args = { .fd = uap->fd }; - /* Call into fsync(), as FreeBSD lacks fdatasync(). */ - return (sys_fsync(td, &fsync_args)); + return (sys_fdatasync(td, &fdatasync_args)); } int From ed12504ac7ffd19518fe0345575abe476a31163c Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Mon, 15 Aug 2016 19:47:04 +0000 Subject: [PATCH 36/67] dtraceUtil/tst.DataModel32.d.ksh passes on amd64. --- cddl/usr.sbin/dtrace/tests/tools/exclude.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh index 33c9efca0f45..38180da97c69 100755 --- a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh +++ b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh @@ -27,7 +27,6 @@ exclude() } exclude EXFAIL common/aggs/tst.subr.d -exclude EXFAIL common/dtraceUtil/tst.DataModel32.d.ksh exclude EXFAIL common/dtraceUtil/tst.ELFGenerationOut.d.ksh exclude EXFAIL common/dtraceUtil/tst.ELFGenerationWithO.d.ksh exclude EXFAIL common/funcs/tst.copyin.d From b0f2185bbefaf7e9fdaa50ecb658b9790e835bd9 Mon Sep 17 00:00:00 2001 From: Eric Badger Date: Mon, 15 Aug 2016 20:09:09 +0000 Subject: [PATCH 37/67] sem_post(): wake up the sleeper only after adjusting has_waiters If the caller of sem_post() wakes up a thread sleeping via sem_wait() before it clears the has_waiters flag, the caller of sem_wait() has no way of knowing when it is safe to destroy the semaphore and reuse the memory. This is because the caller of sem_post() may be interrupted between the wake step and the clearing of has_waiters. It will then write into the has_waiters flag in userspace after being preempted for some unknown amount of time. Reviewed by: jhb, kib, vangyzen Approved by: kib (mentor), vangyzen (mentor) MFC after: 2 weeks Sponsored by: Dell Inc. Differential Revision: https://reviews.freebsd.org/D7505 --- sys/kern/kern_umtx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index 8471591e648d..33eb8bca43cc 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -3123,7 +3123,6 @@ do_sem_wake(struct thread *td, struct _usem *sem) umtxq_busy(&key); cnt = umtxq_count(&key); if (cnt > 0) { - umtxq_signal(&key, 1); /* * Check if count is greater than 0, this means the memory is * still being referenced by user code, so we can safely @@ -3136,6 +3135,7 @@ do_sem_wake(struct thread *td, struct _usem *sem) if (error == -1) error = EFAULT; } + umtxq_signal(&key, 1); } umtxq_unbusy(&key); umtxq_unlock(&key); @@ -3235,8 +3235,6 @@ do_sem2_wake(struct thread *td, struct _usem2 *sem) umtxq_busy(&key); cnt = umtxq_count(&key); if (cnt > 0) { - umtxq_signal(&key, 1); - /* * If this was the last sleeping thread, clear the waiters * flag in _count. @@ -3251,6 +3249,8 @@ do_sem2_wake(struct thread *td, struct _usem2 *sem) error = EFAULT; umtxq_lock(&key); } + + umtxq_signal(&key, 1); } umtxq_unbusy(&key); umtxq_unlock(&key); From 93d9ebd82ebb0ac1507706f865cb39690980a2aa Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Mon, 15 Aug 2016 20:11:52 +0000 Subject: [PATCH 38/67] Eliminate use of sys_fsync() and sys_fdatasync(). Make the kern_fsync() function public, so that it can be used by other parts of the kernel. Fix up existing consumers to make use of it. Requested by: kib --- sys/compat/cloudabi/cloudabi_fd.c | 10 ++-------- sys/compat/linux/linux_file.c | 4 +--- sys/kern/vfs_syscalls.c | 2 +- sys/sys/syscallsubr.h | 1 + 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/sys/compat/cloudabi/cloudabi_fd.c b/sys/compat/cloudabi/cloudabi_fd.c index ae99bb410dc1..5500e3920e17 100644 --- a/sys/compat/cloudabi/cloudabi_fd.c +++ b/sys/compat/cloudabi/cloudabi_fd.c @@ -172,11 +172,8 @@ int cloudabi_sys_fd_datasync(struct thread *td, struct cloudabi_sys_fd_datasync_args *uap) { - struct fdatasync_args fdatasync_args = { - .fd = uap->fd - }; - return (sys_fdatasync(td, &fdatasync_args)); + return (kern_fsync(td, uap->fd, false)); } int @@ -556,9 +553,6 @@ cloudabi_sys_fd_stat_put(struct thread *td, int cloudabi_sys_fd_sync(struct thread *td, struct cloudabi_sys_fd_sync_args *uap) { - struct fsync_args fsync_args = { - .fd = uap->fd - }; - return (sys_fsync(td, &fsync_args)); + return (kern_fsync(td, uap->fd, true)); } diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index d3af86093db7..b5126f4b6cbc 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -1013,10 +1013,8 @@ linux_fdatasync(td, uap) struct thread *td; struct linux_fdatasync_args *uap; { - struct fsync_args bsd; - bsd.fd = uap->fd; - return (sys_fsync(td, &bsd)); + return (kern_fsync(td, uap->fd, false)); } int diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 8419e360e559..bcf74853b823 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3354,7 +3354,7 @@ freebsd6_ftruncate(struct thread *td, struct freebsd6_ftruncate_args *uap) } #endif -static int +int kern_fsync(struct thread *td, int fd, bool fullsync) { struct vnode *vp; diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index a0e58e9e79c1..42ee5159e977 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -100,6 +100,7 @@ int kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf); int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf); int kern_fstat(struct thread *td, int fd, struct stat *sbp); int kern_fstatfs(struct thread *td, int fd, struct statfs *buf); +int kern_fsync(struct thread *td, int fd, bool fullsync); int kern_ftruncate(struct thread *td, int fd, off_t length); int kern_futimes(struct thread *td, int fd, struct timeval *tptr, enum uio_seg tptrseg); From 79ef07d4c022bfc80f274fd77127cd5b9e7dc32c Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 15 Aug 2016 20:17:48 +0000 Subject: [PATCH 39/67] Clean up the new sc cn open and close functions (old sc cn grab and ungrab functions). Mainly, spell sc as itself instead of as scp->sc. --- sys/dev/syscons/syscons.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 4b7c14dac030..58d6a0c43efc 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -1652,46 +1652,40 @@ static void sccnopen(sc_softc_t *sc, struct sc_cnstate *sp, int flags); static void sccnopen(sc_softc_t *sc, struct sc_cnstate *sp, int flags) { - scr_stat *scp; int kbd_mode; if (!cold && - sc_console->sc->cur_scp->index != sc_console->index && - sc_console->sc->cur_scp->smode.mode == VT_AUTO && + sc->cur_scp->index != sc_console->index && + sc->cur_scp->smode.mode == VT_AUTO && sc_console->smode.mode == VT_AUTO) - sc_switch_scr(sc_console->sc, sc_console->index); + sc_switch_scr(sc, sc_console->index); - scp = sc_console->sc->cur_scp; - - if (scp->sc->kbd == NULL) + if (sc->kbd == NULL) return; /* * Make sure the keyboard is accessible even when the kbd device * driver is disabled. */ - kbdd_enable(scp->sc->kbd); + kbdd_enable(sc->kbd); /* Switch the keyboard to console mode (K_XLATE, polled) on all scp's. */ kbd_mode = K_XLATE; - (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&kbd_mode); - kbdd_poll(scp->sc->kbd, TRUE); + (void)kbdd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&kbd_mode); + kbdd_poll(sc->kbd, TRUE); } static void sccnclose(sc_softc_t *sc, struct sc_cnstate *sp) { - scr_stat *scp; - - scp = sc_console->sc->cur_scp; /* XXX */ - if (scp->sc->kbd == NULL) + if (sc->kbd == NULL) return; /* Restore keyboard mode (for the current, possibly-changed scp). */ - kbdd_poll(scp->sc->kbd, FALSE); - (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); + kbdd_poll(sc->kbd, FALSE); + (void)kbdd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&sc->cur_scp->kbd_mode); - kbdd_disable(scp->sc->kbd); + kbdd_disable(sc->kbd); } static void From 061ae3c51943536f7349ed1d1c29fe107b0da0aa Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 15 Aug 2016 20:38:02 +0000 Subject: [PATCH 40/67] Remove the mcd(4) driver for Mitsumi CD-ROM players. This is a driver for a pre-ATAPI ISA CD-ROM adapter. As noted in the manpage, this driver is only useful as a backend to cdcontrol to play audio CDs since it doesn't use DMA, so its data performance is "abysmal" (and that was true in the mid 90's). --- ObsoleteFiles.inc | 2 + share/man/man4/Makefile | 1 - share/man/man4/mcd.4 | 165 ---- sys/conf/NOTES | 5 - sys/conf/files | 2 - sys/dev/mcd/mcd.c | 1652 -------------------------------------- sys/dev/mcd/mcd_isa.c | 202 ----- sys/dev/mcd/mcdreg.h | 219 ----- sys/dev/mcd/mcdvar.h | 71 -- sys/modules/Makefile | 1 - sys/modules/mcd/Makefile | 9 - 11 files changed, 2 insertions(+), 2327 deletions(-) delete mode 100644 share/man/man4/mcd.4 delete mode 100644 sys/dev/mcd/mcd.c delete mode 100644 sys/dev/mcd/mcd_isa.c delete mode 100644 sys/dev/mcd/mcdreg.h delete mode 100644 sys/dev/mcd/mcdvar.h delete mode 100644 sys/modules/mcd/Makefile diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index d5e71e9c6e6b..02a55b608cb1 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,8 @@ # xargs -n1 | sort | uniq -d; # done +# 20160815: Remove mcd(4) +OLD_FILES+=usr/share/man/man4/mcd.4.gz # 20160703: POSIXify locales with variants OLD_FILES+=usr/share/locale/zh_Hant_TW.UTF-8/LC_COLLATE OLD_FILES+=usr/share/locale/zh_Hant_TW.UTF-8/LC_CTYPE diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 1cd099b0b5a4..e85e531aa802 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -269,7 +269,6 @@ MAN= aac.4 \ mac_stub.4 \ mac_test.4 \ malo.4 \ - mcd.4 \ md.4 \ mdio.4 \ me.4 \ diff --git a/share/man/man4/mcd.4 b/share/man/man4/mcd.4 deleted file mode 100644 index 3a79eee41799..000000000000 --- a/share/man/man4/mcd.4 +++ /dev/null @@ -1,165 +0,0 @@ -.\" -.\" Copyright (c) 1994 Keith E. Walker -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd December 8, 1994 -.Dt MCD 4 -.Os -.Sh NAME -.Nm mcd -.Nd Mitsumi CD-ROM driver -.Sh SYNOPSIS -.Cd "device mcd" -.Pp -In -.Pa /boot/device.hints : -.Cd hint.mcd.0.at="isa" -.Cd hint.mcd.0.port="0x300" -.Cd hint.mcd.0.irq="10" -.Sh DESCRIPTION -The -.Nm -driver provides a data and audio interface to the Mitsumi-brand CD-ROM -player. -The CD-ROM player must be interfaced to the ISA bus through -one of the Mitsumi proprietary controller boards. -The controller -boards supported are the LU002S, LU005S, the FX001 and the quite -common FX001D. -.Pp -The -.Nm -driver responds to disk-specific -.Fn ioctl -commands, namely the -.Dv DIOCGPART -command. -Other disk-specific -.Fn ioctl -commands will return an error. -.Pp -The -.Nm -driver also responds to special CD-ROM -.Fn ioctl -commands. -These commands -control the CD-ROM player's audio features. -The commands are: -.Pp -.Bl -tag -width CDIOCREADSUBCHANNEL -compact -offset indent -.It CDIOCREADSUBCHANNEL -get sub-channel information on current status of disc playing -.It CDIOCREADTOCHEADER -get table of contents header -.It CDIOCREADTOCENTRYS -gets all of the table of contents -.It CDIOCPLAYTRACKS -begins audio playing at location specified -.It CDIOCPLAYBLOCKS -fails with error -.Er EINVAL -.It CDIOCPLAYMSF -begins audio playing at location specified -.It CDIOCRESUME -resumes playing a previously paused disc -.It CDIOCPAUSE -pauses a playing disc -.It CDIOCSTART -begins playing a disc -.It CDIOCSTOP -stops a previously playing disc -.It CDIOCEJECT -opens the disc tray (there is no support for a corresponding un-eject -command). -.It CDIOCRESET -stops any play and resets the Mitsumi controller board -.It CDIOCSETDEBUG -cause the kernel to print debug messages to the console about the -.Nm -driver -.It CDIOCCLRDEBUG -cause the kernel to quit printing debug messages about the -.Nm -driver -.El -.Pp -The -.Fn ioctl -commands defined above are the only ones that the -.Nm -driver supports. -There are other CD-ROM related -.Fn ioctl -commands (such as -.Dv CDIOCSETVOL -and -.Dv CDIOCSETSTERIO ) -which are available -and may be supported by future versions of the driver. -.Sh FILES -.Bl -tag -width /dev/(r)mcd0a -compact -.It Pa /dev/(r)mcd0a -accesses -.Bx -partition on the disc. -Normally, there is only -one file system on a CD-ROM disc. -.It Pa /dev/(r)mcd0c -accesses raw device. -.El -.Sh NOTES -The character-mode devices for the -.Nm -driver should only be used for accessing the audio features of the -CD-ROM player as the performance on data is abysmal. -.Pp -The current version of the driver uses neither the DMA or IRQ -features of the interface board, although it has an interrupt handler -for any IRQ requests that are generated. -Until the DMA features are -supported, the only interrupts that the board generates are those that -are not supported by the driver anyway. -.Sh SEE ALSO -.In sys/cdio.h -.Sh HISTORY -An -.Nm -driver appeared in -.Fx 1.0 . -.Sh AUTHORS -.An -nosplit -The driver was written by -.An Holger Veit -(data part) and -.An Brian Moore -(audio part). -Changes were provided by -.An Gary Clark II , -.An Andrew A. Chernov , -and -.An Jordan K. Hubbard . diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 9b7d8cd95482..dda8211d44a3 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2412,15 +2412,10 @@ options SND_OLDSTEREO # Miscellaneous hardware: # # scd: Sony CD-ROM using proprietary (non-ATAPI) interface -# mcd: Mitsumi CD-ROM using proprietary (non-ATAPI) interface # bktr: Brooktree bt848/848a/849a/878/879 video capture and TV Tuner board # joy: joystick (including IO DATA PCJOY PC Card joystick) # cmx: OmniKey CardMan 4040 pccard smartcard reader -# Mitsumi CD-ROM -device mcd -hint.mcd.0.at="isa" -hint.mcd.0.port="0x300" # for the Sony CDU31/33A CDROM device scd hint.scd.0.at="isa" diff --git a/sys/conf/files b/sys/conf/files index 5da337273bcd..40c5281b3baf 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2018,8 +2018,6 @@ dev/malo/if_malohal.c optional malo dev/malo/if_malo_pci.c optional malo pci dev/mc146818/mc146818.c optional mc146818 dev/mca/mca_bus.c optional mca -dev/mcd/mcd.c optional mcd isa nowerror -dev/mcd/mcd_isa.c optional mcd isa nowerror dev/md/md.c optional md dev/mdio/mdio_if.m optional miiproxy | mdio dev/mdio/mdio.c optional miiproxy | mdio diff --git a/sys/dev/mcd/mcd.c b/sys/dev/mcd/mcd.c deleted file mode 100644 index dacbb3d3e2f0..000000000000 --- a/sys/dev/mcd/mcd.c +++ /dev/null @@ -1,1652 +0,0 @@ -/*- - * Copyright 1993 by Holger Veit (data part) - * Copyright 1993 by Brian Moore (audio part) - * Changes Copyright 1993 by Gary Clark II - * Changes Copyright (C) 1994-1995 by Andrey A. Chernov, Moscow, Russia - * - * Rewrote probe routine to work on newer Mitsumi drives. - * Additional changes (C) 1994 by Jordan K. Hubbard - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This software was developed by Holger Veit and Brian Moore - * for use with "386BSD" and similar operating systems. - * "Similar operating systems" includes mainly non-profit oriented - * systems for research and education, including but not restricted to - * "NetBSD", "FreeBSD", "Mach" (by CMU). - * 4. Neither the name of the developer(s) nor the name "386BSD" - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -__FBSDID("$FreeBSD$"); -static const char __used COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -#define MCD_TRACE(format, args...) \ -{ \ - if (sc->debug) { \ - device_printf(sc->dev, "status=0x%02x: ", \ - sc->data.status); \ - printf(format, ## args); \ - } \ -} - -#define RAW_PART 2 - -/* flags */ -#define MCDVALID 0x0001 /* parameters loaded */ -#define MCDINIT 0x0002 /* device is init'd */ -#define MCDNEWMODEL 0x0004 /* device is new model */ -#define MCDLABEL 0x0008 /* label is read */ -#define MCDPROBING 0x0010 /* probing */ -#define MCDREADRAW 0x0020 /* read raw mode (2352 bytes) */ -#define MCDVOLINFO 0x0040 /* already read volinfo */ -#define MCDTOC 0x0080 /* already read toc */ -#define MCDMBXBSY 0x0100 /* local mbx is busy */ - -/* status */ -#define MCDAUDIOBSY MCD_ST_AUDIOBSY /* playing audio */ -#define MCDDSKCHNG MCD_ST_DSKCHNG /* sensed change of disk */ -#define MCDDSKIN MCD_ST_DSKIN /* sensed disk in drive */ -#define MCDDOOROPEN MCD_ST_DOOROPEN /* sensed door open */ - -/* These are apparently the different states a mitsumi can get up to */ -#define MCDCDABSENT 0x0030 -#define MCDCDPRESENT 0x0020 -#define MCDSCLOSED 0x0080 -#define MCDSOPEN 0x00a0 - -#define MCD_MD_UNKNOWN (-1) - -#define MCD_TYPE_UNKNOWN 0 -#define MCD_TYPE_LU002S 1 -#define MCD_TYPE_LU005S 2 -#define MCD_TYPE_LU006S 3 -#define MCD_TYPE_FX001 4 -#define MCD_TYPE_FX001D 5 - -/* reader state machine */ -#define MCD_S_BEGIN 0 -#define MCD_S_BEGIN1 1 -#define MCD_S_WAITSTAT 2 -#define MCD_S_WAITMODE 3 -#define MCD_S_WAITREAD 4 - -/* prototypes */ -static void mcd_start(struct mcd_softc *); -#ifdef NOTYET -static void mcd_configure(struct mcd_softc *sc); -#endif -static int mcd_get(struct mcd_softc *, char *buf, int nmax); -static int mcd_setflags(struct mcd_softc *); -static int mcd_getstat(struct mcd_softc *,int sflg); -static int mcd_send(struct mcd_softc *, int cmd,int nretrys); -static void hsg2msf(int hsg, bcd_t *msf); -static int msf2hsg(bcd_t *msf, int relative); -static int mcd_volinfo(struct mcd_softc *); -static int mcd_waitrdy(struct mcd_softc *,int dly); -static void mcd_timeout(void *arg); -static void mcd_doread(struct mcd_softc *, int state, struct mcd_mbx *mbxin); -static void mcd_soft_reset(struct mcd_softc *); -static int mcd_hard_reset(struct mcd_softc *); -static int mcd_setmode(struct mcd_softc *, int mode); -static int mcd_getqchan(struct mcd_softc *, struct mcd_qchninfo *q); -static int mcd_subchan(struct mcd_softc *, struct ioc_read_subchannel *sc, - int nocopyout); -static int mcd_toc_header(struct mcd_softc *, struct ioc_toc_header *th); -static int mcd_read_toc(struct mcd_softc *); -static int mcd_toc_entrys(struct mcd_softc *, struct ioc_read_toc_entry *te); -#if 0 -static int mcd_toc_entry(struct mcd_softc *, struct ioc_read_toc_single_entry *te); -#endif -static int mcd_stop(struct mcd_softc *); -static int mcd_eject(struct mcd_softc *); -static int mcd_inject(struct mcd_softc *); -static int mcd_playtracks(struct mcd_softc *, struct ioc_play_track *pt); -static int mcd_play(struct mcd_softc *, struct mcd_read2 *pb); -static int mcd_playmsf(struct mcd_softc *, struct ioc_play_msf *pt); -static int mcd_playblocks(struct mcd_softc *, struct ioc_play_blocks *); -static int mcd_pause(struct mcd_softc *); -static int mcd_resume(struct mcd_softc *); -static int mcd_lock_door(struct mcd_softc *, int lock); -static int mcd_close_tray(struct mcd_softc *); -static int mcd_size(struct cdev *dev); - -static d_open_t mcdopen; -static d_close_t mcdclose; -static d_ioctl_t mcdioctl; -static d_strategy_t mcdstrategy; - -static struct cdevsw mcd_cdevsw = { - .d_version = D_VERSION, - .d_open = mcdopen, - .d_close = mcdclose, - .d_read = physread, - .d_ioctl = mcdioctl, - .d_strategy = mcdstrategy, - .d_name = "mcd", - .d_flags = D_DISK, -}; - -#define MCD_RETRYS 5 -#define MCD_RDRETRYS 8 - -#define CLOSE_TRAY_SECS 8 -#define DISK_SENSE_SECS 3 -#define WAIT_FRAC 4 - -/* several delays */ -#define RDELAY_WAITSTAT 300 -#define RDELAY_WAITMODE 300 -#define RDELAY_WAITREAD 800 - -#define MIN_DELAY 15 -#define DELAY_GETREPLY 5000000 - -int -mcd_attach(struct mcd_softc *sc) -{ - int unit; - - unit = device_get_unit(sc->dev); - - MCD_LOCK(sc); - sc->data.flags |= MCDINIT; - mcd_soft_reset(sc); - bioq_init(&sc->data.head); - -#ifdef NOTYET - /* wire controller for interrupts and dma */ - mcd_configure(sc); -#endif - MCD_UNLOCK(sc); - /* name filled in probe */ - sc->mcd_dev_t = make_dev(&mcd_cdevsw, 8 * unit, - UID_ROOT, GID_OPERATOR, 0640, "mcd%d", unit); - - sc->mcd_dev_t->si_drv1 = (void *)sc; - callout_init_mtx(&sc->timer, &sc->mtx, 0); - - return (0); -} - -static int -mcdopen(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - struct mcd_softc *sc; - int r,retry; - - sc = (struct mcd_softc *)dev->si_drv1; - - /* invalidated in the meantime? mark all open part's invalid */ - MCD_LOCK(sc); - if (!(sc->data.flags & MCDVALID) && sc->data.openflags) { - MCD_UNLOCK(sc); - return (ENXIO); - } - - if (mcd_getstat(sc, 1) == -1) { - MCD_UNLOCK(sc); - return (EIO); - } - - if ( (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN)) - || !(sc->data.status & MCDDSKIN)) - for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) { - (void) mtx_sleep(sc, &sc->mtx, PSOCK | PCATCH, - "mcdsn1", hz/WAIT_FRAC); - if ((r = mcd_getstat(sc, 1)) == -1) { - MCD_UNLOCK(sc); - return (EIO); - } - if (r != -2) - break; - } - - if (sc->data.status & MCDDOOROPEN) { - MCD_UNLOCK(sc); - device_printf(sc->dev, "door is open\n"); - return (ENXIO); - } - if (!(sc->data.status & MCDDSKIN)) { - MCD_UNLOCK(sc); - device_printf(sc->dev, "no CD inside\n"); - return (ENXIO); - } - if (sc->data.status & MCDDSKCHNG) { - MCD_UNLOCK(sc); - device_printf(sc->dev, "CD not sensed\n"); - return (ENXIO); - } - - if (mcd_size(dev) < 0) { - MCD_UNLOCK(sc); - device_printf(sc->dev, "failed to get disk size\n"); - return (ENXIO); - } - - sc->data.openflags = 1; - sc->data.partflags |= MCDREADRAW; - sc->data.flags |= MCDVALID; - - (void) mcd_lock_door(sc, MCD_LK_LOCK); - if (!(sc->data.flags & MCDVALID)) { - MCD_UNLOCK(sc); - return (ENXIO); - } - - r = mcd_read_toc(sc); - MCD_UNLOCK(sc); - return (r); -} - -static int -mcdclose(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - struct mcd_softc *sc; - - sc = (struct mcd_softc *)dev->si_drv1; - - MCD_LOCK(sc); - KASSERT(sc->data.openflags, ("device not open")); - - (void) mcd_lock_door(sc, MCD_LK_UNLOCK); - sc->data.openflags = 0; - sc->data.partflags &= ~MCDREADRAW; - MCD_UNLOCK(sc); - - return (0); -} - -static void -mcdstrategy(struct bio *bp) -{ - struct mcd_softc *sc; - - sc = (struct mcd_softc *)bp->bio_dev->si_drv1; - - /* if device invalidated (e.g. media change, door open), error */ - MCD_LOCK(sc); - if (!(sc->data.flags & MCDVALID)) { - device_printf(sc->dev, "media changed\n"); - bp->bio_error = EIO; - goto bad; - } - - /* read only */ - if (!(bp->bio_cmd == BIO_READ)) { - bp->bio_error = EROFS; - goto bad; - } - - /* no data to read */ - if (bp->bio_bcount == 0) - goto done; - - if (!(sc->data.flags & MCDTOC)) { - bp->bio_error = EIO; - goto bad; - } - - bp->bio_resid = 0; - - /* queue it */ - bioq_disksort(&sc->data.head, bp); - - /* now check whether we can perform processing */ - mcd_start(sc); - MCD_UNLOCK(sc); - return; - -bad: - bp->bio_flags |= BIO_ERROR; -done: - MCD_UNLOCK(sc); - bp->bio_resid = bp->bio_bcount; - biodone(bp); - return; -} - -static void -mcd_start(struct mcd_softc *sc) -{ - struct bio *bp; - - MCD_ASSERT_LOCKED(sc); - if (sc->data.flags & MCDMBXBSY) { - return; - } - - bp = bioq_takefirst(&sc->data.head); - if (bp != 0) { - /* block found to process, dequeue */ - /*MCD_TRACE("mcd_start: found block bp=0x%x\n",bp,0,0,0);*/ - sc->data.flags |= MCDMBXBSY; - } else { - /* nothing to do */ - return; - } - - sc->data.mbx.retry = MCD_RETRYS; - sc->data.mbx.bp = bp; - - mcd_doread(sc, MCD_S_BEGIN,&(sc->data.mbx)); - return; -} - -static int -mcdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) -{ - struct mcd_softc *sc; - int retry,r; - - sc = (struct mcd_softc *)dev->si_drv1; - - MCD_LOCK(sc); - if (mcd_getstat(sc, 1) == -1) { /* detect disk change too */ - MCD_UNLOCK(sc); - return (EIO); - } -MCD_TRACE("ioctl called 0x%lx\n", cmd); - - switch (cmd) { - case CDIOCSETPATCH: - case CDIOCGETVOL: - case CDIOCSETVOL: - case CDIOCSETMONO: - case CDIOCSETSTERIO: - case CDIOCSETMUTE: - case CDIOCSETLEFT: - case CDIOCSETRIGHT: - MCD_UNLOCK(sc); - return (EINVAL); - case CDIOCEJECT: - r = mcd_eject(sc); - MCD_UNLOCK(sc); - return (r); - case CDIOCSETDEBUG: - sc->data.debug = 1; - MCD_UNLOCK(sc); - return (0); - case CDIOCCLRDEBUG: - sc->data.debug = 0; - MCD_UNLOCK(sc); - return (0); - case CDIOCRESET: - r = mcd_hard_reset(sc); - MCD_UNLOCK(sc); - return (r); - case CDIOCALLOW: - r = mcd_lock_door(sc, MCD_LK_UNLOCK); - MCD_UNLOCK(sc); - return (r); - case CDIOCPREVENT: - r = mcd_lock_door(sc, MCD_LK_LOCK); - MCD_UNLOCK(sc); - return (r); - case CDIOCCLOSE: - r = mcd_inject(sc); - MCD_UNLOCK(sc); - return (r); - } - - if (!(sc->data.flags & MCDVALID)) { - if ( (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN)) - || !(sc->data.status & MCDDSKIN)) - for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) { - (void) mtx_sleep(sc, &sc->mtx, PSOCK | PCATCH, - "mcdsn2", hz/WAIT_FRAC); - if ((r = mcd_getstat(sc, 1)) == -1) { - MCD_UNLOCK(sc); - return (EIO); - } - if (r != -2) - break; - } - if ( (sc->data.status & (MCDDOOROPEN|MCDDSKCHNG)) - || !(sc->data.status & MCDDSKIN) - || mcd_size(dev) < 0 - ) { - MCD_UNLOCK(sc); - return (ENXIO); - } - sc->data.flags |= MCDVALID; - sc->data.partflags |= MCDREADRAW; - (void) mcd_lock_door(sc, MCD_LK_LOCK); - if (!(sc->data.flags & MCDVALID)) { - MCD_UNLOCK(sc); - return (ENXIO); - } - } - - switch (cmd) { - case DIOCGMEDIASIZE: - *(off_t *)addr = (off_t)sc->data.disksize * sc->data.blksize; - r = 0; - break; - case DIOCGSECTORSIZE: - *(u_int *)addr = sc->data.blksize; - r = 0; - break; - case CDIOCPLAYTRACKS: - r = mcd_playtracks(sc, (struct ioc_play_track *) addr); - break; - case CDIOCPLAYBLOCKS: - r = mcd_playblocks(sc, (struct ioc_play_blocks *) addr); - break; - case CDIOCPLAYMSF: - r = mcd_playmsf(sc, (struct ioc_play_msf *) addr); - break; - case CDIOCREADSUBCHANNEL_SYSSPACE: - return mcd_subchan(sc, (struct ioc_read_subchannel *) addr, 1); - case CDIOCREADSUBCHANNEL: - return mcd_subchan(sc, (struct ioc_read_subchannel *) addr, 0); - case CDIOREADTOCHEADER: - r = mcd_toc_header(sc, (struct ioc_toc_header *) addr); - break; - case CDIOREADTOCENTRYS: - return mcd_toc_entrys(sc, (struct ioc_read_toc_entry *) addr); - case CDIOCRESUME: - r = mcd_resume(sc); - break; - case CDIOCPAUSE: - r = mcd_pause(sc); - break; - case CDIOCSTART: - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - r = EIO; - else - r = 0; - break; - case CDIOCSTOP: - r = mcd_stop(sc); - break; - default: - r = ENOTTY; - } - MCD_UNLOCK(sc); - return (r); -} - -static int -mcd_size(struct cdev *dev) -{ - struct mcd_softc *sc; - int size; - - sc = (struct mcd_softc *)dev->si_drv1; - - if (mcd_volinfo(sc) == 0) { - sc->data.blksize = MCDBLK; - size = msf2hsg(sc->data.volinfo.vol_msf, 0); - sc->data.disksize = size * (MCDBLK/DEV_BSIZE); - return (0); - } - return (-1); -} - -/*************************************************************** - * lower level of driver starts here - **************************************************************/ - -#ifdef NOTDEF -static char -irqs[] = { - 0x00,0x00,0x10,0x20,0x00,0x30,0x00,0x00, - 0x00,0x10,0x40,0x50,0x00,0x00,0x00,0x00 -}; - -static char -drqs[] = { - 0x00,0x01,0x00,0x03,0x00,0x05,0x06,0x07, -}; -#endif - -#ifdef NOT_YET -static void -mcd_configure(struct mcd_softc *sc) -{ - MCD_WRITE(sc, MCD_REG_CONFIG, sc->data.config); -} -#endif - -/* Wait for non-busy - return 0 on timeout */ -static int -twiddle_thumbs(struct mcd_softc *sc, int count, char *whine) -{ - int i; - - for (i = 0; i < count; i++) { - if (!(MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL)) - return (1); - } - if (bootverbose) - device_printf(sc->dev, "timeout %s\n", whine); - return (0); -} - -/* check to see if a Mitsumi CD-ROM is attached to the ISA bus */ - -int -mcd_probe(struct mcd_softc *sc) -{ - int i, j; - unsigned char stbytes[3]; - - sc->data.flags = MCDPROBING; - -#ifdef NOTDEF - /* get irq/drq configuration word */ - sc->data.config = irqs[dev->id_irq]; /* | drqs[dev->id_drq];*/ -#else - sc->data.config = 0; -#endif - - /* send a reset */ - MCD_WRITE(sc, MCD_FLAGS, M_RESET); - - /* - * delay awhile by getting any pending garbage (old data) and - * throwing it away. - */ - for (i = 1000000; i != 0; i--) - (void)MCD_READ(sc, MCD_FLAGS); - - /* Get status */ - MCD_WRITE(sc, MCD_DATA, MCD_CMDGETSTAT); - if (!twiddle_thumbs(sc, 1000000, "getting status")) - return (ENXIO); /* Timeout */ - /* Get version information */ - MCD_WRITE(sc, MCD_DATA, MCD_CMDCONTINFO); - for (j = 0; j < 3; j++) { - if (!twiddle_thumbs(sc, 3000, "getting version info")) - return (ENXIO); - stbytes[j] = (MCD_READ(sc, MCD_DATA) & 0xFF); - } - if (stbytes[1] == stbytes[2]) - return (ENXIO); - if (stbytes[2] >= 4 || stbytes[1] != 'M') { - MCD_WRITE(sc, MCD_CTRL, M_PICKLE); - sc->data.flags |= MCDNEWMODEL; - } - sc->data.read_command = MCD_CMDSINGLESPEEDREAD; - switch (stbytes[1]) { - case 'M': - if (stbytes[2] <= 2) { - sc->data.type = MCD_TYPE_LU002S; - sc->data.name = "Mitsumi LU002S"; - } else if (stbytes[2] <= 5) { - sc->data.type = MCD_TYPE_LU005S; - sc->data.name = "Mitsumi LU005S"; - } else { - sc->data.type = MCD_TYPE_LU006S; - sc->data.name = "Mitsumi LU006S"; - } - break; - case 'F': - sc->data.type = MCD_TYPE_FX001; - sc->data.name = "Mitsumi FX001"; - break; - case 'D': - sc->data.type = MCD_TYPE_FX001D; - sc->data.name = "Mitsumi FX001D"; - sc->data.read_command = MCD_CMDDOUBLESPEEDREAD; - break; - default: - sc->data.type = MCD_TYPE_UNKNOWN; - sc->data.name = "Mitsumi ???"; - break; - } - - if (bootverbose) - device_printf(sc->dev, "type %s, version info: %c %x\n", - sc->data.name, stbytes[1], stbytes[2]); - - return (0); -} - - -static int -mcd_waitrdy(struct mcd_softc *sc, int dly) -{ - int i; - - /* wait until flag port senses status ready */ - for (i=0; idev, "timeout getreply\n"); - return (-1); - } - - /* get the data */ - return (MCD_READ(sc, MCD_REG_STATUS) & 0xFF); -} - -static int -mcd_getstat(struct mcd_softc *sc, int sflg) -{ - int i; - - /* get the status */ - if (sflg) - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDGETSTAT); - i = mcd_getreply(sc, DELAY_GETREPLY); - if (i<0 || (i & MCD_ST_CMDCHECK)) { - sc->data.curr_mode = MCD_MD_UNKNOWN; - return (-1); - } - - sc->data.status = i; - - if (mcd_setflags(sc) < 0) - return (-2); - return (sc->data.status); -} - -static int -mcd_setflags(struct mcd_softc *sc) -{ - - /* check flags */ - if ( (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN)) - || !(sc->data.status & MCDDSKIN)) { - MCD_TRACE("setflags: sensed DSKCHNG or DOOROPEN or !DSKIN\n"); - mcd_soft_reset(sc); - return (-1); - } - - if (sc->data.status & MCDAUDIOBSY) - sc->data.audio_status = CD_AS_PLAY_IN_PROGRESS; - else if (sc->data.audio_status == CD_AS_PLAY_IN_PROGRESS) - sc->data.audio_status = CD_AS_PLAY_COMPLETED; - return (0); -} - -static int -mcd_get(struct mcd_softc *sc, char *buf, int nmax) -{ - int i,k; - - for (i=0; idev, "timeout mcd_get\n"); - return (-1); - } - buf[i] = k; - } - return (i); -} - -static int -mcd_send(struct mcd_softc *sc, int cmd,int nretrys) -{ - int i,k=0; - -/*MCD_TRACE("mcd_send: command = 0x%02x\n",cmd,0,0,0);*/ - for (i=0; idev, "media changed\n"); - return (-1); - } - if (i == nretrys) { - device_printf(sc->dev, "mcd_send retry cnt exceeded\n"); - return (-1); - } -/*MCD_TRACE("mcd_send: done\n",0,0,0,0);*/ - return (0); -} - -static void -hsg2msf(int hsg, bcd_t *msf) -{ - hsg += 150; - F_msf(msf) = bin2bcd(hsg % 75); - hsg /= 75; - S_msf(msf) = bin2bcd(hsg % 60); - hsg /= 60; - M_msf(msf) = bin2bcd(hsg); -} - -static int -msf2hsg(bcd_t *msf, int relative) -{ - return (bcd2bin(M_msf(msf)) * 60 + bcd2bin(S_msf(msf))) * 75 + - bcd2bin(F_msf(msf)) - (!relative) * 150; -} - -static int -mcd_volinfo(struct mcd_softc *sc) -{ - - /* Just return if we already have it */ - if (sc->data.flags & MCDVOLINFO) return (0); - -/*MCD_TRACE("mcd_volinfo: enter\n",0,0,0,0);*/ - - /* send volume info command */ - if (mcd_send(sc, MCD_CMDGETVOLINFO,MCD_RETRYS) < 0) - return (EIO); - - /* get data */ - if (mcd_get(sc, (char*) &sc->data.volinfo,sizeof(struct mcd_volinfo)) < 0) { - device_printf(sc->dev, "mcd_volinfo: error read data\n"); - return (EIO); - } - - if (sc->data.volinfo.trk_low > 0 && - sc->data.volinfo.trk_high >= sc->data.volinfo.trk_low - ) { - sc->data.flags |= MCDVOLINFO; /* volinfo is OK */ - return (0); - } - - return (EINVAL); -} - -/* state machine to process read requests - * initialize with MCD_S_BEGIN: calculate sizes, and read status - * MCD_S_WAITSTAT: wait for status reply, set mode - * MCD_S_WAITMODE: waits for status reply from set mode, set read command - * MCD_S_WAITREAD: wait for read ready, read data - */ -static void -mcd_timeout(void *arg) -{ - struct mcd_softc *sc; - - sc = (struct mcd_softc *)arg; - - MCD_ASSERT_LOCKED(sc); - mcd_doread(sc, sc->ch_state, sc->ch_mbxsave); -} - -static void -mcd_doread(struct mcd_softc *sc, int state, struct mcd_mbx *mbxin) -{ - struct mcd_mbx *mbx; - struct bio *bp; - int rm, i, k; - struct mcd_read2 rbuf; - int blknum; - caddr_t addr; - - MCD_ASSERT_LOCKED(sc); - mbx = (state!=MCD_S_BEGIN) ? sc->ch_mbxsave : mbxin; - bp = mbx->bp; - -loop: - switch (state) { - case MCD_S_BEGIN: - mbx = sc->ch_mbxsave = mbxin; - - case MCD_S_BEGIN1: -retry_status: - /* get status */ - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDGETSTAT); - mbx->count = RDELAY_WAITSTAT; - sc->ch_state = MCD_S_WAITSTAT; - callout_reset(&sc->timer, hz/100, mcd_timeout, sc); /* XXX */ - return; - case MCD_S_WAITSTAT: - sc->ch_state = MCD_S_WAITSTAT; - callout_stop(&sc->timer); - if (mbx->count-- >= 0) { - if (MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL) { - sc->ch_state = MCD_S_WAITSTAT; - callout_reset(&sc->timer, hz/100, - mcd_timeout, sc); /* XXX */ - return; - } - sc->data.status = MCD_READ(sc, MCD_REG_STATUS) & 0xFF; - if (sc->data.status & MCD_ST_CMDCHECK) - goto retry_status; - if (mcd_setflags(sc) < 0) - goto changed; - MCD_TRACE("got WAITSTAT delay=%d\n", - RDELAY_WAITSTAT-mbx->count); - /* reject, if audio active */ - if (sc->data.status & MCDAUDIOBSY) { - device_printf(sc->dev, "audio is active\n"); - goto readerr; - } - -retry_mode: - /* to check for raw/cooked mode */ - if (sc->data.flags & MCDREADRAW) { - rm = MCD_MD_RAW; - mbx->sz = MCDRBLK; - } else { - rm = MCD_MD_COOKED; - mbx->sz = sc->data.blksize; - } - - if (rm == sc->data.curr_mode) - goto modedone; - - mbx->count = RDELAY_WAITMODE; - - sc->data.curr_mode = MCD_MD_UNKNOWN; - mbx->mode = rm; - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDSETMODE); - MCD_WRITE(sc, MCD_REG_COMMAND, rm); - - sc->ch_state = MCD_S_WAITMODE; - callout_reset(&sc->timer, hz / 100, mcd_timeout, sc); /* XXX */ - return; - } else { - device_printf(sc->dev, "timeout getstatus\n"); - goto readerr; - } - - case MCD_S_WAITMODE: - sc->ch_state = MCD_S_WAITMODE; - callout_stop(&sc->timer); - if (mbx->count-- < 0) { - device_printf(sc->dev, "timeout set mode\n"); - goto readerr; - } - if (MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL) { - sc->ch_state = MCD_S_WAITMODE; - callout_reset(&sc->timer, hz / 100, mcd_timeout, sc); - return; - } - sc->data.status = MCD_READ(sc, MCD_REG_STATUS) & 0xFF; - if (sc->data.status & MCD_ST_CMDCHECK) { - sc->data.curr_mode = MCD_MD_UNKNOWN; - goto retry_mode; - } - if (mcd_setflags(sc) < 0) - goto changed; - sc->data.curr_mode = mbx->mode; - MCD_TRACE("got WAITMODE delay=%d\n", - RDELAY_WAITMODE-mbx->count); -modedone: - /* for first block */ - mbx->nblk = howmany(bp->bio_bcount, mbx->sz); - mbx->skip = 0; - -nextblock: - blknum = bp->bio_offset / mbx->sz + mbx->skip/mbx->sz; - - MCD_TRACE("mcd_doread: read blknum=%d for bp=%p\n", - blknum, bp); - - /* build parameter block */ - hsg2msf(blknum,rbuf.start_msf); -retry_read: - /* send the read command */ - MCD_WRITE(sc, MCD_REG_COMMAND, sc->data.read_command); - MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[0]); - MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[1]); - MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[2]); - MCD_WRITE(sc, MCD_REG_COMMAND, 0); - MCD_WRITE(sc, MCD_REG_COMMAND, 0); - MCD_WRITE(sc, MCD_REG_COMMAND, 1); - - /* Spin briefly (<= 2ms) to avoid missing next block */ - for (i = 0; i < 20; i++) { - k = MCD_READ(sc, MCD_FLAGS); - if (!(k & MFL_DATA_NOT_AVAIL)) - goto got_it; - DELAY(100); - } - - mbx->count = RDELAY_WAITREAD; - sc->ch_state = MCD_S_WAITREAD; - callout_reset(&sc->timer, hz / 100, mcd_timeout, sc); /* XXX */ - return; - case MCD_S_WAITREAD: - sc->ch_state = MCD_S_WAITREAD; - callout_stop(&sc->timer); - if (mbx->count-- > 0) { - k = MCD_READ(sc, MCD_FLAGS); - if (!(k & MFL_DATA_NOT_AVAIL)) { /* XXX */ - MCD_TRACE("got data delay=%d\n", - RDELAY_WAITREAD-mbx->count); - got_it: - /* data is ready */ - addr = bp->bio_data + mbx->skip; - - MCD_WRITE(sc, MCD_REG_CTL2,0x04); /* XXX */ - for (i=0; isz; i++) - *addr++ = MCD_READ(sc, MCD_REG_RDATA); - MCD_WRITE(sc, MCD_REG_CTL2,0x0c); /* XXX */ - - k = MCD_READ(sc, MCD_FLAGS); - /* If we still have some junk, read it too */ - if (!(k & MFL_DATA_NOT_AVAIL)) { - MCD_WRITE(sc, MCD_REG_CTL2, 0x04); /* XXX */ - (void)MCD_READ(sc, MCD_REG_RDATA); - (void)MCD_READ(sc, MCD_REG_RDATA); - MCD_WRITE(sc, MCD_REG_CTL2, 0x0c); /* XXX */ - } - - if (--mbx->nblk > 0) { - mbx->skip += mbx->sz; - goto nextblock; - } - - /* return buffer */ - bp->bio_resid = 0; - biodone(bp); - - sc->data.flags &= ~(MCDMBXBSY|MCDREADRAW); - mcd_start(sc); - return; - } - if (!(k & MFL_STATUS_NOT_AVAIL)) { - sc->data.status = MCD_READ(sc, MCD_REG_STATUS) & 0xFF; - if (sc->data.status & MCD_ST_CMDCHECK) - goto retry_read; - if (mcd_setflags(sc) < 0) - goto changed; - } - sc->ch_state = MCD_S_WAITREAD; - callout_reset(&sc->timer, hz / 100, mcd_timeout, sc); /* XXX */ - return; - } else { - device_printf(sc->dev, "timeout read data\n"); - goto readerr; - } - } - -readerr: - if (mbx->retry-- > 0) { - device_printf(sc->dev, "retrying\n"); - state = MCD_S_BEGIN1; - goto loop; - } -harderr: - /* invalidate the buffer */ - bp->bio_flags |= BIO_ERROR; - bp->bio_resid = bp->bio_bcount; - biodone(bp); - - sc->data.flags &= ~(MCDMBXBSY|MCDREADRAW); - mcd_start(sc); - return; - -changed: - device_printf(sc->dev, "media changed\n"); - goto harderr; - -#ifdef NOTDEF - device_printf(sc->dev, "unit timeout, resetting\n"); - MCD_WRITE(sc, MCD_REG_RESET, MCD_CMDRESET); - DELAY(300000); - (void)mcd_getstat(sc, 1); - (void)mcd_getstat(sc, 1); - /*sc->data.status &= ~MCDDSKCHNG; */ - sc->data.debug = 1; /* preventive set debug mode */ - -#endif - -} - -static int -mcd_lock_door(struct mcd_softc *sc, int lock) -{ - - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDLOCKDRV); - MCD_WRITE(sc, MCD_REG_COMMAND, lock); - if (mcd_getstat(sc, 0) == -1) - return (EIO); - return (0); -} - -static int -mcd_close_tray(struct mcd_softc *sc) -{ - int retry, r; - - if (mcd_getstat(sc, 1) == -1) - return (EIO); - if (sc->data.status & MCDDOOROPEN) { - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDCLOSETRAY); - for (retry = 0; retry < CLOSE_TRAY_SECS * WAIT_FRAC; retry++) { - if (MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL) - (void) mtx_sleep(sc, &sc->mtx, PSOCK | PCATCH, - "mcdcls", hz/WAIT_FRAC); - else { - if ((r = mcd_getstat(sc, 0)) == -1) - return (EIO); - return (0); - } - } - return (ENXIO); - } - return (0); -} - -static int -mcd_eject(struct mcd_softc *sc) -{ - int r; - - if (mcd_getstat(sc, 1) == -1) /* detect disk change too */ - return (EIO); - if (sc->data.status & MCDDOOROPEN) - return (0); - if ((r = mcd_stop(sc)) == EIO) - return (r); - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDEJECTDISK); - if (mcd_getstat(sc, 0) == -1) - return (EIO); - return (0); -} - -static int -mcd_inject(struct mcd_softc *sc) -{ - - if (mcd_getstat(sc, 1) == -1) /* detect disk change too */ - return (EIO); - if (sc->data.status & MCDDOOROPEN) - return mcd_close_tray(sc); - return (0); -} - -static int -mcd_hard_reset(struct mcd_softc *sc) -{ - - MCD_WRITE(sc, MCD_REG_RESET, MCD_CMDRESET); - sc->data.curr_mode = MCD_MD_UNKNOWN; - sc->data.audio_status = CD_AS_AUDIO_INVALID; - return (0); -} - -static void -mcd_soft_reset(struct mcd_softc *sc) -{ - - sc->data.flags &= (MCDINIT|MCDPROBING|MCDNEWMODEL); - sc->data.curr_mode = MCD_MD_UNKNOWN; - sc->data.partflags = 0; - sc->data.audio_status = CD_AS_AUDIO_INVALID; -} - -static int -mcd_setmode(struct mcd_softc *sc, int mode) -{ - int retry, st; - - if (sc->data.curr_mode == mode) - return (0); - if (sc->data.debug) - device_printf(sc->dev, "setting mode to %d\n", mode); - for(retry=0; retrydata.curr_mode = MCD_MD_UNKNOWN; - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDSETMODE); - MCD_WRITE(sc, MCD_REG_COMMAND, mode); - if ((st = mcd_getstat(sc, 0)) >= 0) { - sc->data.curr_mode = mode; - return (0); - } - if (st == -2) { - device_printf(sc->dev, "media changed\n"); - break; - } - } - - return (-1); -} - -static int -mcd_toc_header(struct mcd_softc *sc, struct ioc_toc_header *th) -{ - int r; - - if ((r = mcd_volinfo(sc)) != 0) - return (r); - - th->starting_track = bcd2bin(sc->data.volinfo.trk_low); - th->ending_track = bcd2bin(sc->data.volinfo.trk_high); - th->len = 2 * sizeof(u_char) /* start & end tracks */ + - (th->ending_track + 1 - th->starting_track + 1) * - sizeof(struct cd_toc_entry); - - return (0); -} - -static int -mcd_read_toc(struct mcd_softc *sc) -{ - struct ioc_toc_header th; - struct mcd_qchninfo q; - int rc, trk, idx, retry; - - /* Only read TOC if needed */ - if (sc->data.flags & MCDTOC) - return (0); - - if (sc->data.debug) - device_printf(sc->dev, "reading toc header\n"); - - if ((rc = mcd_toc_header(sc, &th)) != 0) - return (rc); - - if (mcd_send(sc, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0) - return (EIO); - - if (mcd_setmode(sc, MCD_MD_TOC) != 0) - return (EIO); - - if (sc->data.debug) - device_printf(sc->dev, "get_toc reading qchannel info\n"); - - for(trk=th.starting_track; trk<=th.ending_track; trk++) - sc->data.toc[trk].idx_no = 0; - trk = th.ending_track - th.starting_track + 1; - for(retry=0; retry<600 && trk>0; retry++) - { - if (mcd_getqchan(sc, &q) < 0) break; - idx = bcd2bin(q.idx_no); - if (idx>=th.starting_track && idx<=th.ending_track && q.trk_no==0) { - if (sc->data.toc[idx].idx_no == 0) { - sc->data.toc[idx] = q; - trk--; - } - } - } - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - if (trk != 0) - return (ENXIO); - - /* add a fake last+1 */ - idx = th.ending_track + 1; - sc->data.toc[idx].control = sc->data.toc[idx-1].control; - sc->data.toc[idx].addr_type = sc->data.toc[idx-1].addr_type; - sc->data.toc[idx].trk_no = 0; - sc->data.toc[idx].idx_no = MCD_LASTPLUS1; - sc->data.toc[idx].hd_pos_msf[0] = sc->data.volinfo.vol_msf[0]; - sc->data.toc[idx].hd_pos_msf[1] = sc->data.volinfo.vol_msf[1]; - sc->data.toc[idx].hd_pos_msf[2] = sc->data.volinfo.vol_msf[2]; - - if (sc->data.debug) - { int i; - for (i = th.starting_track; i <= idx; i++) - device_printf(sc->dev, "trk %d idx %d pos %d %d %d\n", - i, - sc->data.toc[i].idx_no > 0x99 ? sc->data.toc[i].idx_no : - bcd2bin(sc->data.toc[i].idx_no), - bcd2bin(sc->data.toc[i].hd_pos_msf[0]), - bcd2bin(sc->data.toc[i].hd_pos_msf[1]), - bcd2bin(sc->data.toc[i].hd_pos_msf[2])); - } - - sc->data.flags |= MCDTOC; - - return (0); -} - -#if 0 -static int -mcd_toc_entry(struct mcd_softc *sc, struct ioc_read_toc_single_entry *te) -{ - struct ioc_toc_header th; - int rc, trk; - - if (te->address_format != CD_MSF_FORMAT - && te->address_format != CD_LBA_FORMAT) - return (EINVAL); - - /* Copy the toc header */ - if ((rc = mcd_toc_header(sc, &th)) != 0) - return (rc); - - /* verify starting track */ - trk = te->track; - if (trk == 0) - trk = th.starting_track; - else if (trk == MCD_LASTPLUS1) - trk = th.ending_track + 1; - else if (trk < th.starting_track || trk > th.ending_track + 1) - return (EINVAL); - - /* Make sure we have a valid toc */ - if ((rc=mcd_read_toc(sc)) != 0) - return (rc); - - /* Copy the TOC data. */ - if (sc->data.toc[trk].idx_no == 0) - return (EIO); - - te->entry.control = sc->data.toc[trk].control; - te->entry.addr_type = sc->data.toc[trk].addr_type; - te->entry.track = - sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no : - bcd2bin(sc->data.toc[trk].idx_no); - switch (te->address_format) { - case CD_MSF_FORMAT: - te->entry.addr.msf.unused = 0; - te->entry.addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0]); - te->entry.addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1]); - te->entry.addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2]); - break; - case CD_LBA_FORMAT: - te->entry.addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0)); - break; - } - return (0); -} -#endif - -static int -mcd_toc_entrys(struct mcd_softc *sc, struct ioc_read_toc_entry *te) -{ - struct cd_toc_entry entries[MCD_MAXTOCS]; - struct ioc_toc_header th; - int rc, n, trk, len; - - if ( te->data_len < sizeof(entries[0]) - || (te->data_len % sizeof(entries[0])) != 0 - || (te->address_format != CD_MSF_FORMAT - && te->address_format != CD_LBA_FORMAT) - ) - return (EINVAL); - - /* Copy the toc header */ - if ((rc = mcd_toc_header(sc, &th)) != 0) - return (rc); - - /* verify starting track */ - trk = te->starting_track; - if (trk == 0) - trk = th.starting_track; - else if (trk == MCD_LASTPLUS1) - trk = th.ending_track + 1; - else if (trk < th.starting_track || trk > th.ending_track + 1) - return (EINVAL); - - len = ((th.ending_track + 1 - trk) + 1) * - sizeof(entries[0]); - if (te->data_len < len) - len = te->data_len; - if (len > sizeof(entries)) - return (EINVAL); - - /* Make sure we have a valid toc */ - if ((rc=mcd_read_toc(sc)) != 0) - return (rc); - - /* Copy the TOC data. */ - for (n = 0; len > 0 && trk <= th.ending_track + 1; trk++) { - if (sc->data.toc[trk].idx_no == 0) - continue; - entries[n].control = sc->data.toc[trk].control; - entries[n].addr_type = sc->data.toc[trk].addr_type; - entries[n].track = - sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no : - bcd2bin(sc->data.toc[trk].idx_no); - switch (te->address_format) { - case CD_MSF_FORMAT: - entries[n].addr.msf.unused = 0; - entries[n].addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0]); - entries[n].addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1]); - entries[n].addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2]); - break; - case CD_LBA_FORMAT: - entries[n].addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0)); - break; - } - len -= sizeof(struct cd_toc_entry); - n++; - } - - /* copy the data back */ - MCD_UNLOCK(sc); - return copyout(entries, te->data, n * sizeof(struct cd_toc_entry)); -} - -static int -mcd_stop(struct mcd_softc *sc) -{ - - /* Verify current status */ - if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS && - sc->data.audio_status != CD_AS_PLAY_PAUSED && - sc->data.audio_status != CD_AS_PLAY_COMPLETED) { - if (sc->data.debug) - device_printf(sc->dev, - "stop attempted when not playing, audio status %d\n", - sc->data.audio_status); - return (EINVAL); - } - if (sc->data.audio_status == CD_AS_PLAY_IN_PROGRESS) - if (mcd_send(sc, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0) - return (EIO); - sc->data.audio_status = CD_AS_PLAY_COMPLETED; - return (0); -} - -static int -mcd_getqchan(struct mcd_softc *sc, struct mcd_qchninfo *q) -{ - - if (mcd_send(sc, MCD_CMDGETQCHN, MCD_RETRYS) < 0) - return (-1); - if (mcd_get(sc, (char *) q, sizeof(struct mcd_qchninfo)) < 0) - return (-1); - if (sc->data.debug) { - device_printf(sc->dev, - "getqchan control=0x%x addr_type=0x%x trk=%d ind=%d ttm=%d:%d.%d dtm=%d:%d.%d\n", - q->control, q->addr_type, - bcd2bin(q->trk_no), - bcd2bin(q->idx_no), - bcd2bin(q->trk_size_msf[0]), - bcd2bin(q->trk_size_msf[1]), - bcd2bin(q->trk_size_msf[2]), - bcd2bin(q->hd_pos_msf[0]), - bcd2bin(q->hd_pos_msf[1]), - bcd2bin(q->hd_pos_msf[2])); - } - return (0); -} - -static int -mcd_subchan(struct mcd_softc *sc, struct ioc_read_subchannel *sch, int nocopyout) -{ - struct mcd_qchninfo q; - struct cd_sub_channel_info data; - int lba; - - if (sc->data.debug) - device_printf(sc->dev, "subchan af=%d, df=%d\n", - sch->address_format, - sch->data_format); - - if (sch->address_format != CD_MSF_FORMAT && - sch->address_format != CD_LBA_FORMAT) - return (EINVAL); - - if (sch->data_format != CD_CURRENT_POSITION && - sch->data_format != CD_MEDIA_CATALOG) - return (EINVAL); - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - if (mcd_getqchan(sc, &q) < 0) - return (EIO); - - data.header.audio_status = sc->data.audio_status; - data.what.position.data_format = sch->data_format; - - switch (sch->data_format) { - case CD_MEDIA_CATALOG: - data.what.media_catalog.mc_valid = 1; - data.what.media_catalog.mc_number[0] = '\0'; - break; - - case CD_CURRENT_POSITION: - data.what.position.control = q.control; - data.what.position.addr_type = q.addr_type; - data.what.position.track_number = bcd2bin(q.trk_no); - data.what.position.index_number = bcd2bin(q.idx_no); - switch (sch->address_format) { - case CD_MSF_FORMAT: - data.what.position.reladdr.msf.unused = 0; - data.what.position.reladdr.msf.minute = bcd2bin(q.trk_size_msf[0]); - data.what.position.reladdr.msf.second = bcd2bin(q.trk_size_msf[1]); - data.what.position.reladdr.msf.frame = bcd2bin(q.trk_size_msf[2]); - data.what.position.absaddr.msf.unused = 0; - data.what.position.absaddr.msf.minute = bcd2bin(q.hd_pos_msf[0]); - data.what.position.absaddr.msf.second = bcd2bin(q.hd_pos_msf[1]); - data.what.position.absaddr.msf.frame = bcd2bin(q.hd_pos_msf[2]); - break; - case CD_LBA_FORMAT: - lba = msf2hsg(q.trk_size_msf, 1); - /* - * Pre-gap has index number of 0, and decreasing MSF - * address. Must be converted to negative LBA, per - * SCSI spec. - */ - if (data.what.position.index_number == 0) - lba = -lba; - data.what.position.reladdr.lba = htonl(lba); - data.what.position.absaddr.lba = htonl(msf2hsg(q.hd_pos_msf, 0)); - break; - } - break; - } - - MCD_UNLOCK(sc); - if (nocopyout == 0) - return copyout(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len)); - bcopy(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len)); - return (0); -} - -static int -mcd_playmsf(struct mcd_softc *sc, struct ioc_play_msf *p) -{ - struct mcd_read2 pb; - - if (sc->data.debug) - device_printf(sc->dev, "playmsf: from %d:%d.%d to %d:%d.%d\n", - p->start_m, p->start_s, p->start_f, - p->end_m, p->end_s, p->end_f); - - if ((p->start_m * 60 * 75 + p->start_s * 75 + p->start_f) >= - (p->end_m * 60 * 75 + p->end_s * 75 + p->end_f) || - (p->end_m * 60 * 75 + p->end_s * 75 + p->end_f) > - M_msf(sc->data.volinfo.vol_msf) * 60 * 75 + - S_msf(sc->data.volinfo.vol_msf) * 75 + - F_msf(sc->data.volinfo.vol_msf)) - return (EINVAL); - - pb.start_msf[0] = bin2bcd(p->start_m); - pb.start_msf[1] = bin2bcd(p->start_s); - pb.start_msf[2] = bin2bcd(p->start_f); - pb.end_msf[0] = bin2bcd(p->end_m); - pb.end_msf[1] = bin2bcd(p->end_s); - pb.end_msf[2] = bin2bcd(p->end_f); - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - return mcd_play(sc, &pb); -} - -static int -mcd_playtracks(struct mcd_softc *sc, struct ioc_play_track *pt) -{ - struct mcd_read2 pb; - int a = pt->start_track; - int z = pt->end_track; - int rc, i; - - if ((rc = mcd_read_toc(sc)) != 0) - return (rc); - - if (sc->data.debug) - device_printf(sc->dev, "playtracks from %d:%d to %d:%d\n", - a, pt->start_index, z, pt->end_index); - - if ( a < bcd2bin(sc->data.volinfo.trk_low) - || a > bcd2bin(sc->data.volinfo.trk_high) - || a > z - || z < bcd2bin(sc->data.volinfo.trk_low) - || z > bcd2bin(sc->data.volinfo.trk_high)) - return (EINVAL); - - for (i = 0; i < 3; i++) { - pb.start_msf[i] = sc->data.toc[a].hd_pos_msf[i]; - pb.end_msf[i] = sc->data.toc[z+1].hd_pos_msf[i]; - } - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - return mcd_play(sc, &pb); -} - -static int -mcd_playblocks(struct mcd_softc *sc, struct ioc_play_blocks *p) -{ - struct mcd_read2 pb; - - if (sc->data.debug) - device_printf(sc->dev, "playblocks: blkno %d length %d\n", - p->blk, p->len); - - if (p->blk > sc->data.disksize || p->len > sc->data.disksize || - p->blk < 0 || p->len < 0 || - (p->blk + p->len) > sc->data.disksize) - return (EINVAL); - - hsg2msf(p->blk, pb.start_msf); - hsg2msf(p->blk + p->len, pb.end_msf); - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - return mcd_play(sc, &pb); -} - -static int -mcd_play(struct mcd_softc *sc, struct mcd_read2 *pb) -{ - int retry, st = -1, status; - - sc->data.lastpb = *pb; - for(retry=0; retrystart_msf[0]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->start_msf[1]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->start_msf[2]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->end_msf[0]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->end_msf[1]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->end_msf[2]); - critical_exit(); - - status=mcd_getstat(sc, 0); - if (status == -1) - continue; - else if (status != -2) - st = 0; - break; - } - - if (status == -2) { - device_printf(sc->dev, "media changed\n"); - return (ENXIO); - } - if (sc->data.debug) - device_printf(sc->dev, - "mcd_play retry=%d, status=0x%02x\n", retry, status); - if (st < 0) - return (ENXIO); - sc->data.audio_status = CD_AS_PLAY_IN_PROGRESS; - return (0); -} - -static int -mcd_pause(struct mcd_softc *sc) -{ - struct mcd_qchninfo q; - int rc; - - /* Verify current status */ - if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS && - sc->data.audio_status != CD_AS_PLAY_PAUSED) { - if (sc->data.debug) - device_printf(sc->dev, - "pause attempted when not playing, audio status %d\n", - sc->data.audio_status); - return (EINVAL); - } - - /* Get the current position */ - if (mcd_getqchan(sc, &q) < 0) - return (EIO); - - /* Copy it into lastpb */ - sc->data.lastpb.start_msf[0] = q.hd_pos_msf[0]; - sc->data.lastpb.start_msf[1] = q.hd_pos_msf[1]; - sc->data.lastpb.start_msf[2] = q.hd_pos_msf[2]; - - /* Stop playing */ - if ((rc=mcd_stop(sc)) != 0) - return (rc); - - /* Set the proper status and exit */ - sc->data.audio_status = CD_AS_PLAY_PAUSED; - return (0); -} - -static int -mcd_resume(struct mcd_softc *sc) -{ - - if (sc->data.audio_status != CD_AS_PLAY_PAUSED) - return (EINVAL); - return mcd_play(sc, &sc->data.lastpb); -} diff --git a/sys/dev/mcd/mcd_isa.c b/sys/dev/mcd/mcd_isa.c deleted file mode 100644 index 92e8adb57192..000000000000 --- a/sys/dev/mcd/mcd_isa.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include - -#include -#include - -static int mcd_isa_probe (device_t); -static int mcd_isa_attach (device_t); -static int mcd_isa_detach (device_t); - -static int mcd_alloc_resources (device_t); -static void mcd_release_resources (device_t); - -static int -mcd_isa_probe (device_t dev) -{ - struct mcd_softc * sc; - int error; - - /* No pnp support */ - if (isa_get_vendorid(dev)) - return (ENXIO); - - /* IO port must be configured. */ - if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) - return (ENXIO); - - sc = device_get_softc(dev); - sc->dev = dev; - sc->port_rid = 0; - sc->port_type = SYS_RES_IOPORT; - error = mcd_alloc_resources(dev); - if (error) - goto fail; - - error = mcd_probe(sc); - if (error) { - device_printf(dev, "Probe failed.\n"); - goto fail; - } - - device_set_desc(dev, sc->data.name); - -fail: - mcd_release_resources(dev); - return (error); -} - -static int -mcd_isa_attach (device_t dev) -{ - struct mcd_softc * sc; - int error; - - sc = device_get_softc(dev); - error = 0; - - sc->dev = dev; - sc->port_rid = 0; - sc->port_type = SYS_RES_IOPORT; - error = mcd_alloc_resources(dev); - if (error) - goto fail; - - error = mcd_probe(sc); - if (error) { - device_printf(dev, "Re-Probe failed.\n"); - goto fail; - } - - error = mcd_attach(sc); - if (error) { - device_printf(dev, "Attach failed.\n"); - goto fail; - } - - return (0); -fail: - mcd_release_resources(dev); - return (error); -} - -static int -mcd_isa_detach (device_t dev) -{ - struct mcd_softc * sc; - int error; - - sc = device_get_softc(dev); - error = 0; - - destroy_dev(sc->mcd_dev_t); - - mcd_release_resources(dev); - - return (error); -} - -static int -mcd_alloc_resources (device_t dev) -{ - struct mcd_softc * sc; - int error; - - sc = device_get_softc(dev); - error = 0; - mtx_init(&sc->mtx, "mcd", NULL, MTX_DEF); - - if (sc->port_type) { - sc->port = bus_alloc_resource_any(dev, sc->port_type, - &sc->port_rid, RF_ACTIVE); - if (sc->port == NULL) { - device_printf(dev, "Unable to allocate PORT resource.\n"); - error = ENOMEM; - goto bad; - } - } - - if (sc->irq_type) { - sc->irq = bus_alloc_resource_any(dev, sc->irq_type, - &sc->irq_rid, RF_ACTIVE); - if (sc->irq == NULL) { - device_printf(dev, "Unable to allocate IRQ resource.\n"); - error = ENOMEM; - goto bad; - } - } - - if (sc->drq_type) { - sc->drq = bus_alloc_resource_any(dev, sc->drq_type, - &sc->drq_rid, RF_ACTIVE); - if (sc->drq == NULL) { - device_printf(dev, "Unable to allocate DRQ resource.\n"); - error = ENOMEM; - goto bad; - } - } - -bad: - return (error); -} - -static void -mcd_release_resources (device_t dev) -{ - struct mcd_softc * sc; - - sc = device_get_softc(dev); - - if (sc->irq_ih) - bus_teardown_intr(dev, sc->irq, sc->irq_ih); - if (sc->port) - bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port); - if (sc->irq) - bus_release_resource(dev, sc->irq_type, sc->irq_rid, sc->irq); - if (sc->drq) - bus_release_resource(dev, sc->drq_type, sc->drq_rid, sc->drq); - - mtx_destroy(&sc->mtx); - - return; -} - -static device_method_t mcd_isa_methods[] = { - DEVMETHOD(device_probe, mcd_isa_probe), - DEVMETHOD(device_attach, mcd_isa_attach), - DEVMETHOD(device_detach, mcd_isa_detach), - - { 0, 0 } -}; - -static driver_t mcd_isa_driver = { - "mcd", - mcd_isa_methods, - sizeof(struct mcd_softc) -}; - -static devclass_t mcd_devclass; - -DRIVER_MODULE(mcd, isa, mcd_isa_driver, mcd_devclass, NULL, 0); diff --git a/sys/dev/mcd/mcdreg.h b/sys/dev/mcd/mcdreg.h deleted file mode 100644 index 451fc5de76c3..000000000000 --- a/sys/dev/mcd/mcdreg.h +++ /dev/null @@ -1,219 +0,0 @@ -/*- - * Copyright 1993 by Holger Veit (data part) - * Copyright 1993 by Brian Moore (audio part) - * Changes Copyright 1993 by Gary Clark II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This software was developed by Holger Veit and Brian Moore - * for use with "386BSD" and similar operating systems. - * "Similar operating systems" includes mainly non-profit oriented - * systems for research and education, including but not restricted to - * "NetBSD", "FreeBSD", "Mach" (by CMU). - * 4. Neither the name of the developer(s) nor the name "386BSD" - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This file contains definitions for some cdrom control commands - * and status codes. This info was "inherited" from the DOS MTMCDE.SYS - * driver, and is thus not complete (and may even be wrong). Some day - * the manufacturer or anyone else might provide better documentation, - * so this file (and the driver) will then have a better quality. - * - * $FreeBSD$ - */ - -#ifndef MCD_H -#define MCD_H - -/* toc */ -#define MCD_MAXTOCS 104 /* from the Linux driver */ -#define MCD_LASTPLUS1 170 /* special toc entry */ - -typedef unsigned char bcd_t; -#define M_msf(msf) msf[0] -#define S_msf(msf) msf[1] -#define F_msf(msf) msf[2] - -/* io lines used */ -#define MCD_IO_BASE 0x300 - -#define MCD_REG_COMMAND 0 -#define MCD_REG_STATUS 0 -#define MCD_REG_RDATA 0 - -#define MCD_REG_RESET 1 -#define MCD_REG_CTL2 2 /* XXX Is this right? */ -#define MCD_REG_CONFIG 3 - -#define MCD_MASK_DMA 0x07 /* bits 2-0 = DMA channel */ -#define MCD_MASK_IRQ 0x70 /* bits 6-4 = INT number */ - /* 001 = int 2,9 */ - /* 010 = int 3 */ - /* 011 = int 5 */ - /* 100 = int 10 */ - /* 101 = int 11 */ -/* flags */ -#define MFL_DATA_NOT_AVAIL 0x02 -#define MFL_STATUS_NOT_AVAIL 0x04 - -/* New Commands */ -#define M_RESET 0x00 -#define M_PICKLE 0x04 - -/* ports */ -#define MCD_DATA 0 -#define MCD_FLAGS 1 -#define MCD_CTRL 2 -#define CHANNEL 3 /* XXX ??? */ - -/* Status bits */ -#define MCD_ST_DOOROPEN 0x80 -#define MCD_ST_DSKIN 0x40 -#define MCD_ST_DSKCHNG 0x20 -#define MCD_ST_SPINNING 0x10 -#define MCD_ST_AUDIODISK 0x08 /* Audio Disk is in */ -#define MCD_ST_BUSY 0x04 -#define MCD_ST_AUDIOBSY 0x02 /* Audio Disk is Playing */ -#define MCD_ST_CMDCHECK 0x01 /* Command error */ - -/* commands known by the controller */ -#define MCD_CMDRESET 0x00 -#define MCD_CMDGETVOLINFO 0x10 /* gets mcd_volinfo */ -#define MCD_CMDGETDISKINFO 0x11 /* gets mcd_disk information */ -#define MCD_CMDGETQCHN 0x20 /* gets mcd_qchninfo */ -#define MCD_CMDGETSENSE 0x30 /* gets sense info */ -#define MCD_CMDGETSTAT 0x40 /* gets a byte of status */ - -#define MCD_CMDSETMODE 0x50 /* set transmission mode, needs byte */ - -#define MCD_MDBIT_TESTMODE 0x80 /* 0 = DATALENGTH setting is valid */ -#define MCD_MDBIT_DATALENGTH 0x40 /* 0 = Read User Data Only */ - /* 1 = Read Raw sectors (2352 bytes) */ - -#define MCDBLK 2048 /* for cooked mode */ -#define MCDRBLK sizeof(struct mcd_rawsector) /* for raw mode */ - -#define MCD_MDBIT_ECCMODE 0x20 /* 0 = Use secondary correction */ - /* 1 = Don't use secondary ECC */ -#define MCD_MDBIT_SPINDOWN 0x08 /* 0 = Spin Up, 1 = Spin Down */ -#define MCD_MDBIT_GET_TOC 0x04 /* 0 = Get UPC on next GETQCHAN */ - /* 1 = Get TOC on GETQCHAN */ -#define MCD_MDBIT_MUTEDATA 0x01 /* 1 = Don't play back Data as audio */ - -#define MCD_MD_RAW (MCD_MDBIT_DATALENGTH|MCD_MDBIT_ECCMODE|MCD_MDBIT_MUTEDATA) -#define MCD_MD_COOKED (MCD_MDBIT_MUTEDATA) -#define MCD_MD_TOC (MCD_MDBIT_GET_TOC|MCD_MDBIT_MUTEDATA) - -#define MCD_CMDSTOPAUDIO 0x70 -#define MCD_CMDSTOPAUDIOTIME 0x80 -#define MCD_CMDGETVOLUME 0x8E /* gets mcd_volume */ -#define MCD_CMDSETDRIVEMODE 0xA0 /* Set drive mode */ -#define MCD_READUPC 0xA2 /* Get UPC info */ -#define MCD_CMDSETVOLUME 0xAE /* sets mcd_volume */ -#define MCD_CMDREAD1 0xB0 /* read n sectors */ -#define MCD_CMDSINGLESPEEDREAD 0xC0 /* read from-to */ -#define MCD_CMDSTARTAUDIOMSF 0xC1 /* read audio data */ -#define MCD_CMDDOUBLESPEEDREAD 0xC1 /* Read lots of data from the drive */ -#define MCD_CMDGETDRIVEMODE 0xC2 /* Get the drive mode */ -#define MCD_CMDREAD 0xC3 /* Read data from the drive */ -#define MCD_CMDSETINTERLEAVE 0xC8 /* Adjust the interleave */ -#define MCD_CMDCONTINFO 0xDC /* Get controller info */ -#define MCD_CMDSTOP 0xF0 /* Stop everything */ -#define MCD_CMDEJECTDISK 0xF6 -#define MCD_CMDCLOSETRAY 0xF8 - -#define MCD_CMDLOCKDRV 0xFE /* needs byte */ -#define MCD_LK_UNLOCK 0x00 -#define MCD_LK_LOCK 0x01 -#define MCD_LK_TEST 0x02 - -/* DMA Enable Stuff */ -#define MCD_DMA_IRQFLAGS 0x10 /* Set data0 for IRQ click */ - -#define MCD_DMA_PREIRQ 0x01 /* All of these are for */ -#define MCD_DMA_POSTIRQ 0x02 /* MCD_DMA_IRQFLAG... */ -#define MCD_DMA_ERRIRQ 0x04 /* */ - -#define MCD_DMA_TIMEOUT 0x08 /* Set data0 for DMA timeout */ -#define MCD_DMA_UPCFLAG 0x04 /* 1 = Next command will be READUPC */ - -#define MCD_DMA_DMAMODE 0x02 /* 1 = Data uses DMA */ -#define MCD_DMA_TRANSFERLENGTH 0x01 /* data0 = MSB, data1 = LSB of block length */ - -struct mcd_dma_mode { - u_char dma_mode; - u_char data0; /* If dma_mode & 0x10: Use IRQ settings */ - u_char data1; /* Used if dma_mode & 0x01 */ -} __packed; - -struct mcd_volinfo { - bcd_t trk_low; - bcd_t trk_high; - bcd_t vol_msf[3]; - bcd_t trk1_msf[3]; -} __packed; - -struct mcd_qchninfo { - u_char addr_type:4; - u_char control:4; - u_char trk_no; - u_char idx_no; - bcd_t trk_size_msf[3]; - u_char :8; - bcd_t hd_pos_msf[3]; -} __packed; - -struct mcd_volume { - u_char v0l; - u_char v0rs; - u_char v0r; - u_char v0ls; -} __packed; - -struct mcd_holdtime { - u_char units_of_ten_seconds; - /* If this is 0, the default (12) is used */ -} __packed; - -struct mcd_read1 { - bcd_t start_msf[3]; - u_char nsec[3]; -} __packed; - -struct mcd_read2 { - bcd_t start_msf[3]; - bcd_t end_msf[3]; -} __packed; - -struct mcd_rawsector { - u_char sync1[12]; - u_char header[4]; - u_char subheader1[4]; - u_char subheader2[4]; - u_char data[MCDBLK]; - u_char ecc_bits[280]; -} __packed; - -#endif /* MCD_H */ diff --git a/sys/dev/mcd/mcdvar.h b/sys/dev/mcd/mcdvar.h deleted file mode 100644 index 71e45d0b0bd2..000000000000 --- a/sys/dev/mcd/mcdvar.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * $FreeBSD$ - */ - -struct mcd_mbx { - short retry; - short nblk; - int sz; - u_long skip; - struct bio * bp; - short count; - short mode; -}; - -struct mcd_data { - short type; - char * name; - short config; - short flags; - u_char read_command; - short status; - int blksize; - u_long disksize; - int partflags; - int openflags; - struct mcd_volinfo volinfo; - struct mcd_qchninfo toc[MCD_MAXTOCS]; - short audio_status; - short curr_mode; - struct mcd_read2 lastpb; - short debug; - struct bio_queue_head head; /* head of bio queue */ - struct mcd_mbx mbx; -}; - -struct mcd_softc { - device_t dev; - struct cdev *mcd_dev_t; - int debug; - - struct resource * port; - int port_rid; - int port_type; - - struct resource * irq; - int irq_rid; - int irq_type; - void * irq_ih; - - struct resource * drq; - int drq_rid; - int drq_type; - - struct mtx mtx; - - struct callout timer; - int ch_state; - struct mcd_mbx * ch_mbxsave; - - struct mcd_data data; -}; - -#define MCD_LOCK(_sc) mtx_lock(&_sc->mtx) -#define MCD_UNLOCK(_sc) mtx_unlock(&_sc->mtx) -#define MCD_ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED) - -#define MCD_READ(_sc, _reg) bus_read_1(_sc->port, _reg) -#define MCD_WRITE(_sc, _reg, _val) bus_write_1(_sc->port, _reg, _val) - -int mcd_probe (struct mcd_softc *); -int mcd_attach (struct mcd_softc *); diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 93d33d948abf..c6c76f90d215 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -224,7 +224,6 @@ SUBDIR= \ mac_stub \ mac_test \ malo \ - mcd \ md \ mdio \ mem \ diff --git a/sys/modules/mcd/Makefile b/sys/modules/mcd/Makefile deleted file mode 100644 index 1602c0304c7f..000000000000 --- a/sys/modules/mcd/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../dev/mcd - -KMOD= mcd -SRCS= mcd.c mcd_isa.c \ - bus_if.h device_if.h isa_if.h - -.include From d4a12237eb348aa79a522acc087f47252f823ddb Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Mon, 15 Aug 2016 23:20:55 +0000 Subject: [PATCH 41/67] elfcopy: correct comment typo in r304151 --- contrib/elftoolchain/elfcopy/ascii.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/elftoolchain/elfcopy/ascii.c b/contrib/elftoolchain/elfcopy/ascii.c index 747c66bd0c5b..6adecf8d347a 100644 --- a/contrib/elftoolchain/elfcopy/ascii.c +++ b/contrib/elftoolchain/elfcopy/ascii.c @@ -251,7 +251,7 @@ create_elf_from_srec(struct elfcopy *ecp, int ifd) sec_index = 1; sec_addr = entry = 0; while (fgets(line, _LINE_BUFSZ, ifp) != NULL) { - sz = 0; /* Silence GCC 5.3 unintialized variable warning */ + sz = 0; /* Silence GCC 5.3 uninitialized variable warning */ if (line[0] == '\r' || line[0] == '\n') continue; if (line[0] == '$' && line[1] == '$') { From bb3860fbd07caf50fc889985569d8aba8809c807 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Tue, 16 Aug 2016 00:15:15 +0000 Subject: [PATCH 42/67] Fix ko_KR, zh_CN, zh_HK, and zh_TW locales. r304045 did not fully revert date/time formats for these locales. --- share/timedef/ko_KR.UTF-8.src | 24 ++++---- share/timedef/ko_KR.eucKR.src | 24 ++++---- share/timedef/zh_CN.GB2312.src | 108 ++++++++++++++++----------------- share/timedef/zh_CN.GBK.src | 24 ++++---- share/timedef/zh_CN.UTF-8.src | 24 ++++---- share/timedef/zh_CN.eucCN.src | 24 ++++---- share/timedef/zh_HK.UTF-8.src | 24 ++++---- share/timedef/zh_TW.Big5.src | 73 +++++++++++----------- share/timedef/zh_TW.UTF-8.src | 24 ++++---- 9 files changed, 175 insertions(+), 174 deletions(-) diff --git a/share/timedef/ko_KR.UTF-8.src b/share/timedef/ko_KR.UTF-8.src index 6623233d6e74..98e512a7761e 100644 --- a/share/timedef/ko_KR.UTF-8.src +++ b/share/timedef/ko_KR.UTF-8.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1ì›” - 2ì›” - 3ì›” - 4ì›” - 5ì›” - 6ì›” - 7ì›” - 8ì›” - 9ì›” -10ì›” -11ì›” -12ì›” + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 1ì›” diff --git a/share/timedef/ko_KR.eucKR.src b/share/timedef/ko_KR.eucKR.src index 096e484b07f6..b85195371a95 100644 --- a/share/timedef/ko_KR.eucKR.src +++ b/share/timedef/ko_KR.eucKR.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1¿ù - 2¿ù - 3¿ù - 4¿ù - 5¿ù - 6¿ù - 7¿ù - 8¿ù - 9¿ù -10¿ù -11¿ù -12¿ù + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 1¿ù diff --git a/share/timedef/zh_CN.GB2312.src b/share/timedef/zh_CN.GB2312.src index bcc7b3793c64..e98dc5fc28fa 100644 --- a/share/timedef/zh_CN.GB2312.src +++ b/share/timedef/zh_CN.GB2312.src @@ -4,53 +4,53 @@ # ----------------------------------------------------------------------------- # # Short month names -!!#1TB -!!#2TB -!!#3TB -!!#4TB -!!#5TB -!!#6TB -!!#7TB -!!#8TB -!!#9TB -#1#0TB -#1#1TB -#1#2TB + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) -R;TB -6~TB -H}TB -KDTB -NeTB -AyTB -F_TB -0KTB ->ETB -J.TB -J.R;TB -J.6~TB +Ò»Ô +¶þÔ +ÈýÔ +ËÄÔ +ÎåÔ +ÁùÔ +ÆßÔ +°ËÔ +¾ÅÔ +ʮԠ+ʮһÔ +Ê®¶þÔ # # Short weekday names -V\HU -V\R; -V\6~ -V\H} -V\KD -V\Ne -V\Ay +ÖÜÈÕ +ÖÜÒ» +Öܶþ +ÖÜÈý +ÖÜËÄ +ÖÜÎå +ÖÜÁù # # Long weekday names -PGFZHU -PGFZR; -PGFZ6~ -PGFZH} -PGFZKD -PGFZNe -PGFZAy +ÐÇÆÚÈÕ +ÐÇÆÚÒ» +ÐÇÆÚ¶þ +ÐÇÆÚÈý +ÐÇÆÚËÄ +ÐÇÆÚÎå +ÐÇÆÚÁù # # X_fmt -%Hʱ%M·Ö%SÃë +%Hʱ%M·Ö%SÃë # # x_fmt %Y/%m/%d @@ -59,25 +59,25 @@ PGFZAy %a %b/%e %T %Y # # AM/PM -IONg -OBNg +ÉÏÎç +ÏÂÎç # # date_fmt -%YÄê%bÔÂ%eÈÕ %A %X %Z +%YÄê%bÔÂ%eÈÕ %A %X %Z # # Long month names (without case ending) -R;TB -6~TB -H}TB -KDTB -NeTB -AyTB -F_TB -0KTB ->ETB -J.TB -J.R;TB -J.6~TB +Ò»Ô +¶þÔ +ÈýÔ +ËÄÔ +ÎåÔ +ÁùÔ +ÆßÔ +°ËÔ +¾ÅÔ +ʮԠ+ʮһÔ +Ê®¶þÔ # # md_order md diff --git a/share/timedef/zh_CN.GBK.src b/share/timedef/zh_CN.GBK.src index 9130d83797f3..e98dc5fc28fa 100644 --- a/share/timedef/zh_CN.GBK.src +++ b/share/timedef/zh_CN.GBK.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1Ô - 2Ô - 3Ô - 4Ô - 5Ô - 6Ô - 7Ô - 8Ô - 9Ô -10Ô -11Ô -12Ô + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) Ò»Ô diff --git a/share/timedef/zh_CN.UTF-8.src b/share/timedef/zh_CN.UTF-8.src index e87f300b0692..2460706f3bf3 100644 --- a/share/timedef/zh_CN.UTF-8.src +++ b/share/timedef/zh_CN.UTF-8.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1月 - 2月 - 3月 - 4月 - 5月 - 6月 - 7月 - 8月 - 9月 -10月 -11月 -12月 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 一月 diff --git a/share/timedef/zh_CN.eucCN.src b/share/timedef/zh_CN.eucCN.src index a654ee23643a..e98dc5fc28fa 100644 --- a/share/timedef/zh_CN.eucCN.src +++ b/share/timedef/zh_CN.eucCN.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names -¡¡£±Ô -¡¡£²Ô -¡¡£³Ô -¡¡£´Ô -¡¡£µÔ -¡¡£¶Ô -¡¡£·Ô -¡¡£¸Ô -¡¡£¹Ô -£±£°Ô -£±£±Ô -£±£²Ô + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) Ò»Ô diff --git a/share/timedef/zh_HK.UTF-8.src b/share/timedef/zh_HK.UTF-8.src index 390c9bdddaec..9800bcf231eb 100644 --- a/share/timedef/zh_HK.UTF-8.src +++ b/share/timedef/zh_HK.UTF-8.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1月 - 2月 - 3月 - 4月 - 5月 - 6月 - 7月 - 8月 - 9月 -10月 -11月 -12月 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 1月 diff --git a/share/timedef/zh_TW.Big5.src b/share/timedef/zh_TW.Big5.src index e22bd18f0584..4ed7cdeeda12 100644 --- a/share/timedef/zh_TW.Big5.src +++ b/share/timedef/zh_TW.Big5.src @@ -4,32 +4,32 @@ # ----------------------------------------------------------------------------- # # Short month names -¡@¢°¤ë -¡@¢±¤ë -¡@¢²¤ë -¡@¢³¤ë -¡@¢´¤ë -¡@¢µ¤ë -¡@¢¶¤ë -¡@¢·¤ë -¡@¢¸¤ë -¢°¢¯¤ë -¢°¢°¤ë -¢°¢±¤ë + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) -¢°¤ë -¢±¤ë -¢²¤ë -¢³¤ë -¢´¤ë -¢µ¤ë -¢¶¤ë -¢·¤ë -¢¸¤ë -¢°¢¯¤ë -¢°¢°¤ë -¢°¢±¤ë +1¤ë +2¤ë +3¤ë +4¤ë +5¤ë +6¤ë +7¤ë +8¤ë +9¤ë +10¤ë +11¤ë +12¤ë # # Short weekday names ¶g¤é @@ -62,21 +62,22 @@ ¤W¤È ¤U¤È # +# date_fmt %Y¦~%b¤ë%e¤é %A %X %Z # # Long month names (without case ending) -¢°¤ë -¢±¤ë -¢²¤ë -¢³¤ë -¢´¤ë -¢µ¤ë -¢¶¤ë -¢·¤ë -¢¸¤ë -¢°¢¯¤ë -¢°¢°¤ë -¢°¢±¤ë +1¤ë +2¤ë +3¤ë +4¤ë +5¤ë +6¤ë +7¤ë +8¤ë +9¤ë +10¤ë +11¤ë +12¤ë # # md_order md diff --git a/share/timedef/zh_TW.UTF-8.src b/share/timedef/zh_TW.UTF-8.src index 8eb552159b0e..3121d4a4f4fc 100644 --- a/share/timedef/zh_TW.UTF-8.src +++ b/share/timedef/zh_TW.UTF-8.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1月 - 2月 - 3月 - 4月 - 5月 - 6月 - 7月 - 8月 - 9月 -10月 -11月 -12月 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 1月 From 684d18c9ae39dae5bed91bf80a0a73691ef992f7 Mon Sep 17 00:00:00 2001 From: Rick Macklem Date: Tue, 16 Aug 2016 00:48:13 +0000 Subject: [PATCH 43/67] Fix r304026 so that it builds for gcc. Reported by: np Tested by: np MFC after: 1 month --- usr.bin/nfsstat/nfsstat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/usr.bin/nfsstat/nfsstat.c b/usr.bin/nfsstat/nfsstat.c index d0bda7d6f911..90be2953ffd8 100644 --- a/usr.bin/nfsstat/nfsstat.c +++ b/usr.bin/nfsstat/nfsstat.c @@ -130,7 +130,8 @@ static void compute_new_stats(struct nfsstatsv1 *cur_stats, struct stattypes { int stat_type; int nfs_type; -} static statstruct[] = { +}; +static struct stattypes statstruct[] = { {STAT_TYPE_READ, NFSV4OP_READ}, {STAT_TYPE_WRITE, NFSV4OP_WRITE}, {STAT_TYPE_COMMIT, NFSV4OP_COMMIT} From 5968c001542bec9d0e873710c35a72f6decfe76c Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Tue, 16 Aug 2016 02:34:25 +0000 Subject: [PATCH 44/67] Regenerate DTrace tests. --- cddl/usr.sbin/dtrace/tests/common/Makefile | 1 + .../dtrace/tests/common/scalars/Makefile | 2 ++ .../dtrace/tests/common/sugar/Makefile | 25 +++++++++++++++++++ etc/mtree/BSD.tests.dist | 2 ++ 4 files changed, 30 insertions(+) create mode 100644 cddl/usr.sbin/dtrace/tests/common/sugar/Makefile diff --git a/cddl/usr.sbin/dtrace/tests/common/Makefile b/cddl/usr.sbin/dtrace/tests/common/Makefile index 7c7bb1718d05..4c0ad4b50bdb 100644 --- a/cddl/usr.sbin/dtrace/tests/common/Makefile +++ b/cddl/usr.sbin/dtrace/tests/common/Makefile @@ -69,6 +69,7 @@ TESTS_SUBDIRS+= aggs \ strlen \ strtoll \ struct \ + sugar \ syscall \ tick-n \ trace \ diff --git a/cddl/usr.sbin/dtrace/tests/common/scalars/Makefile b/cddl/usr.sbin/dtrace/tests/common/scalars/Makefile index 8a08eac05375..9f019068da35 100644 --- a/cddl/usr.sbin/dtrace/tests/common/scalars/Makefile +++ b/cddl/usr.sbin/dtrace/tests/common/scalars/Makefile @@ -18,6 +18,8 @@ ${PACKAGE}FILES= \ err.D_SYNTAX.declare.d \ err.bigglobal.d \ err.biglocal.d \ + tst.16kglobal.d \ + tst.16klocal.d \ tst.basicvar.d \ tst.basicvar.d.out \ tst.localvar.d \ diff --git a/cddl/usr.sbin/dtrace/tests/common/sugar/Makefile b/cddl/usr.sbin/dtrace/tests/common/sugar/Makefile new file mode 100644 index 000000000000..40fc86a45ce0 --- /dev/null +++ b/cddl/usr.sbin/dtrace/tests/common/sugar/Makefile @@ -0,0 +1,25 @@ +# $FreeBSD$ + +# +# This Makefile was generated by $srcdir/cddl/usr.sbin/dtrace/tests/tools/genmakefiles.sh. +# + +PACKAGE= tests + +${PACKAGE}FILES= \ + tst.else.d \ + tst.if.d \ + tst.if2.d \ + tst.if_before_after.d \ + tst.if_nested.d \ + tst.if_trailing_semicolon.d \ + tst.if_trailing_semicolon2.d \ + +TESTEXES= \ + + +CFILES= \ + + + +.include "../../dtrace.test.mk" diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 1f45fcd3c76a..27d52ca85568 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -183,6 +183,8 @@ .. struct .. + sugar + .. syscall .. sysevent From 8452c1b345ae98bf2fbd249a81917d64d3ce8531 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Tue, 16 Aug 2016 06:40:27 +0000 Subject: [PATCH 45/67] tcp/lro: Make # of LRO entries tunable Reviewed by: hps, gallatin Obtained from: rrs, gallatin MFC after: 2 weeks Sponsored by: Netflix (rrs, gallatin), Microsoft (sephe) Differential Revision: https://reviews.freebsd.org/D7499 --- sys/netinet/tcp_lro.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c index c09b8b9aa1d2..01d5c0adeae5 100644 --- a/sys/netinet/tcp_lro.c +++ b/sys/netinet/tcp_lro.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -55,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -71,6 +73,14 @@ static void tcp_lro_rx_done(struct lro_ctrl *lc); static int tcp_lro_rx2(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum, int use_hash); +SYSCTL_NODE(_net_inet_tcp, OID_AUTO, lro, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, + "TCP LRO"); + +static unsigned tcp_lro_entries = TCP_LRO_ENTRIES; +SYSCTL_UINT(_net_inet_tcp_lro, OID_AUTO, entries, + CTLFLAG_RDTUN | CTLFLAG_MPSAFE, &tcp_lro_entries, 0, + "default number of LRO entries"); + static __inline void tcp_lro_active_insert(struct lro_ctrl *lc, struct lro_head *bucket, struct lro_entry *le) @@ -91,7 +101,7 @@ tcp_lro_active_remove(struct lro_entry *le) int tcp_lro_init(struct lro_ctrl *lc) { - return (tcp_lro_init_args(lc, NULL, TCP_LRO_ENTRIES, 0)); + return (tcp_lro_init_args(lc, NULL, tcp_lro_entries, 0)); } int From 5ac4acb202a3e94473f69cd52e172e868eb1a7ce Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Tue, 16 Aug 2016 07:26:53 +0000 Subject: [PATCH 46/67] hyperv/hn: Factor out hn_nvs_send/hn_nvs_send_sglist Avoid unnecessary message type setting and centralize the send context to transaction id cast. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7500 --- sys/dev/hyperv/include/vmbus.h | 1 + sys/dev/hyperv/netvsc/hv_net_vsc.c | 48 ++++++++++++------------- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 5 ++- sys/dev/hyperv/netvsc/if_hnvar.h | 22 ++++++++++++ 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/sys/dev/hyperv/include/vmbus.h b/sys/dev/hyperv/include/vmbus.h index 0a16e6e8957d..5843f0345e0a 100644 --- a/sys/dev/hyperv/include/vmbus.h +++ b/sys/dev/hyperv/include/vmbus.h @@ -83,6 +83,7 @@ struct vmbus_chanpkt_hdr { #define VMBUS_CHANPKT_TYPE_GPA 0x0009 #define VMBUS_CHANPKT_TYPE_COMP 0x000b +#define VMBUS_CHANPKT_FLAG_NONE 0 #define VMBUS_CHANPKT_FLAG_RC 0x0001 /* report completion */ #define VMBUS_CHANPKT_CONST_DATA(pkt) \ diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 2288d842859c..b42051bbf84a 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -206,9 +206,8 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); vmbus_xact_activate(xact); - error = vmbus_chan_send(sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - conn, sizeof(*conn), (uint64_t)(uintptr_t)&sndc); + error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, + conn, sizeof(*conn), &sndc); if (error != 0) { if_printf(sc->hn_ifp, "send nvs rxbuf conn failed: %d\n", error); @@ -313,9 +312,8 @@ hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); vmbus_xact_activate(xact); - error = vmbus_chan_send(sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - chim, sizeof(*chim), (uint64_t)(uintptr_t)&sndc); + error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, + chim, sizeof(*chim), &sndc); if (error) { if_printf(sc->hn_ifp, "send nvs chim conn failed: %d\n", error); @@ -393,9 +391,10 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_dev) disconn.nvs_type = HN_NVS_TYPE_RXBUF_DISCONN; disconn.nvs_sig = HN_NVS_RXBUF_SIG; - ret = vmbus_chan_send(net_dev->sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, 0, &disconn, sizeof(disconn), - (uint64_t)(uintptr_t)&hn_send_ctx_none); + /* NOTE: No response. */ + ret = hn_nvs_send(net_dev->sc->hn_prichan, + VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn), + &hn_send_ctx_none); if (ret != 0) { if_printf(net_dev->sc->hn_ifp, "send rxbuf disconn failed: %d\n", ret); @@ -445,9 +444,10 @@ hv_nv_destroy_send_buffer(netvsc_dev *net_dev) disconn.nvs_type = HN_NVS_TYPE_CHIM_DISCONN; disconn.nvs_sig = HN_NVS_CHIM_SIG; - ret = vmbus_chan_send(net_dev->sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, 0, &disconn, sizeof(disconn), - (uint64_t)(uintptr_t)&hn_send_ctx_none); + /* NOTE: No response. */ + ret = hn_nvs_send(net_dev->sc->hn_prichan, + VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn), + &hn_send_ctx_none); if (ret != 0) { if_printf(net_dev->sc->hn_ifp, "send chim disconn failed: %d\n", ret); @@ -509,9 +509,8 @@ hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev, vmbus_xact_activate(xact); hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); - error = vmbus_chan_send(sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - init, sizeof(*init), (uint64_t)(uintptr_t)&sndc); + error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, + init, sizeof(*init), &sndc); if (error) { if_printf(sc->hn_ifp, "send nvs init failed: %d\n", error); vmbus_xact_deactivate(xact); @@ -560,8 +559,9 @@ hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu) conf.nvs_mtu = mtu; conf.nvs_caps = HN_NVS_NDIS_CONF_VLAN; - error = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, - &conf, sizeof(conf), (uint64_t)(uintptr_t)&hn_send_ctx_none); + /* NOTE: No response. */ + error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE, + &conf, sizeof(conf), &hn_send_ctx_none); if (error) if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error); return (error); @@ -627,8 +627,9 @@ hv_nv_connect_to_vsp(struct hn_softc *sc) else ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_30; - ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, - &ndis, sizeof(ndis), (uint64_t)(uintptr_t)&hn_send_ctx_none); + /* NOTE: No response. */ + ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE, + &ndis, sizeof(ndis), &hn_send_ctx_none); if (ret != 0) { if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", ret); goto cleanup; @@ -834,12 +835,11 @@ hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt, sndc->hn_chim_sz; if (gpa_cnt) { - ret = vmbus_chan_send_sglist(chan, gpa, gpa_cnt, - &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)sndc); + ret = hn_nvs_send_sglist(chan, gpa, gpa_cnt, + &send_msg, sizeof(nvsp_msg), sndc); } else { - ret = vmbus_chan_send(chan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)sndc); + ret = hn_nvs_send(chan, VMBUS_CHANPKT_FLAG_RC, + &send_msg, sizeof(nvsp_msg), sndc); } return (ret); diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index 5e3473b7c1ea..dd9e06689365 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -1177,9 +1177,8 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); vmbus_xact_activate(xact); - ret = vmbus_chan_send(sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - req, sizeof(*req), (uint64_t)(uintptr_t)&sndc); + ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, + req, sizeof(*req), &sndc); if (ret != 0) { if_printf(sc->hn_ifp, "send nvs subch req failed: %d\n", ret); vmbus_xact_deactivate(xact); diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h index 39f01fffadaf..60ec33de1641 100644 --- a/sys/dev/hyperv/netvsc/if_hnvar.h +++ b/sys/dev/hyperv/netvsc/if_hnvar.h @@ -30,6 +30,8 @@ #define _IF_HNVAR_H_ #include + +#include #include struct netvsc_dev_; @@ -61,6 +63,7 @@ static __inline void hn_send_ctx_init(struct hn_send_ctx *sndc, hn_sent_callback_t cb, void *cbarg, uint32_t chim_idx, int chim_sz) { + sndc->hn_cb = cb; sndc->hn_cbarg = cbarg; sndc->hn_chim_idx = chim_idx; @@ -71,10 +74,29 @@ static __inline void hn_send_ctx_init_simple(struct hn_send_ctx *sndc, hn_sent_callback_t cb, void *cbarg) { + hn_send_ctx_init(sndc, cb, cbarg, NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX, 0); } +static __inline int +hn_nvs_send(struct vmbus_channel *chan, uint16_t flags, + void *nvs_msg, int nvs_msglen, struct hn_send_ctx *sndc) +{ + + return (vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_INBAND, flags, + nvs_msg, nvs_msglen, (uint64_t)(uintptr_t)sndc)); +} + +static __inline int +hn_nvs_send_sglist(struct vmbus_channel *chan, struct vmbus_gpa sg[], int sglen, + void *nvs_msg, int nvs_msglen, struct hn_send_ctx *sndc) +{ + + return (vmbus_chan_send_sglist(chan, sg, sglen, nvs_msg, nvs_msglen, + (uint64_t)(uintptr_t)sndc)); +} + void hn_nvs_sent_xact(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, const struct nvsp_msg_ *msg, int dlen); From 62c4e6e992126816f3cce25de771ccf7fbd50a7b Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Tue, 16 Aug 2016 07:37:02 +0000 Subject: [PATCH 47/67] hyperv/hn: Simplify RNDIS NVS message sending. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7501 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 27 ++++++----------- sys/dev/hyperv/netvsc/hv_net_vsc.h | 2 +- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 11 ++++--- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 13 ++++----- sys/dev/hyperv/netvsc/if_hnreg.h | 29 +++++++++++++++++++ sys/dev/hyperv/netvsc/if_hnvar.h | 17 +++++------ 6 files changed, 58 insertions(+), 41 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index b42051bbf84a..ee47965dd6a4 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -118,7 +118,7 @@ hv_nv_get_next_send_section(netvsc_dev *net_dev) unsigned long bitsmap_words = net_dev->bitsmap_words; unsigned long *bitsmap = net_dev->send_section_bitsmap; unsigned long idx; - int ret = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; + int ret = HN_NVS_CHIM_IDX_INVALID; int i; for (i = 0; i < bitsmap_words; i++) { @@ -814,32 +814,23 @@ hv_nv_on_send_completion(netvsc_dev *net_dev, struct vmbus_channel *chan, * Returns 0 on success, non-zero on failure. */ int -hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt, +hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt) { - nvsp_msg send_msg; + struct hn_nvs_rndis rndis; int ret; - send_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt; - if (is_data_pkt) { - /* 0 is RMC_DATA */ - send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 0; - } else { - /* 1 is RMC_CONTROL */ - send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 1; - } - - send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_idx = - sndc->hn_chim_idx; - send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size = - sndc->hn_chim_sz; + rndis.nvs_type = HN_NVS_TYPE_RNDIS; + rndis.nvs_rndis_mtype = rndis_mtype; + rndis.nvs_chim_idx = sndc->hn_chim_idx; + rndis.nvs_chim_sz = sndc->hn_chim_sz; if (gpa_cnt) { ret = hn_nvs_send_sglist(chan, gpa, gpa_cnt, - &send_msg, sizeof(nvsp_msg), sndc); + &rndis, sizeof(rndis), sndc); } else { ret = hn_nvs_send(chan, VMBUS_CHANPKT_FLAG_RC, - &send_msg, sizeof(nvsp_msg), sndc); + &rndis, sizeof(rndis), sndc); } return (ret); diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index a861c3e18d53..c5dc3b2b9adb 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1256,7 +1256,7 @@ netvsc_dev *hv_nv_on_device_add(struct hn_softc *sc, void *additional_info, struct hn_rx_ring *rxr); int hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel); -int hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt, +int hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt); int hv_nv_get_next_send_section(netvsc_dev *net_dev); void hv_nv_subchan_attach(struct vmbus_channel *chan, diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 4653e776da92..7cf9c54f60d9 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -798,7 +798,7 @@ hn_tx_done(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, struct hn_txdesc *txd = sndc->hn_cbarg; struct hn_tx_ring *txr; - if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) + if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) hn_chim_free(net_dev, sndc->hn_chim_idx); txr = txd->txr; @@ -988,8 +988,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) txr->hn_tx_chimney_tried++; send_buf_section_idx = hv_nv_get_next_send_section(net_dev); - if (send_buf_section_idx != - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { + if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) { uint8_t *dest = ((uint8_t *)net_dev->send_buf + (send_buf_section_idx * net_dev->send_section_size)); @@ -1045,7 +1044,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) gpa->gpa_len = segs[i].ds_len; } - send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; + send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID; send_buf_section_size = 0; done: txd->m = m_head; @@ -1072,8 +1071,8 @@ again: * Make sure that txd is not freed before ETHER_BPF_MTAP. */ hn_txdesc_hold(txd); - error = hv_nv_on_send(txr->hn_chan, true, &txd->send_ctx, - txr->hn_gpa, txr->hn_gpa_cnt); + error = hv_nv_on_send(txr->hn_chan, HN_NVS_RNDIS_MTYPE_DATA, + &txd->send_ctx, txr->hn_gpa, txr->hn_gpa_cnt); if (!error) { ETHER_BPF_MTAP(ifp, txd->m); if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index dd9e06689365..644b017c0516 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -277,8 +277,7 @@ hv_rf_send_request(rndis_device *device, rndis_request *request, if (tot_data_buf_len < net_dev->send_section_size) { send_buf_section_idx = hv_nv_get_next_send_section(net_dev); - if (send_buf_section_idx != - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { + if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) { char *dest = ((char *)net_dev->send_buf + send_buf_section_idx * net_dev->send_section_size); @@ -289,14 +288,14 @@ hv_rf_send_request(rndis_device *device, rndis_request *request, } /* Failed to allocate chimney send buffer; move on */ } - send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; + send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID; send_buf_section_size = 0; sendit: hn_send_ctx_init(&request->send_ctx, cb, request, send_buf_section_idx, send_buf_section_size); - return hv_nv_on_send(device->net_dev->sc->hn_prichan, false, - &request->send_ctx, gpa, gpa_cnt); + return hv_nv_on_send(device->net_dev->sc->hn_prichan, + HN_NVS_RNDIS_MTYPE_CTRL, &request->send_ctx, gpa, gpa_cnt); } /* @@ -1276,7 +1275,7 @@ hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused, int dlen __unused) { - if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) + if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) hn_chim_free(net_dev, sndc->hn_chim_idx); } @@ -1287,7 +1286,7 @@ hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, { rndis_request *request = sndc->hn_cbarg; - if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) + if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) hn_chim_free(net_dev, sndc->hn_chim_idx); /* diff --git a/sys/dev/hyperv/netvsc/if_hnreg.h b/sys/dev/hyperv/netvsc/if_hnreg.h index 109ece03f8de..47e1abf09f41 100644 --- a/sys/dev/hyperv/netvsc/if_hnreg.h +++ b/sys/dev/hyperv/netvsc/if_hnreg.h @@ -35,8 +35,19 @@ #define HN_NVS_RXBUF_SIG 0xcafe #define HN_NVS_CHIM_SIG 0xface +#define HN_NVS_CHIM_IDX_INVALID 0xffffffff + +#define HN_NVS_RNDIS_MTYPE_DATA 0 +#define HN_NVS_RNDIS_MTYPE_CTRL 1 + +/* + * NVS message transacion status codes. + */ #define HN_NVS_STATUS_OK 1 +/* + * NVS request/response message types. + */ #define HN_NVS_TYPE_INIT 1 #define HN_NVS_TYPE_INIT_RESP 2 #define HN_NVS_TYPE_NDIS_INIT 100 @@ -46,6 +57,7 @@ #define HN_NVS_TYPE_CHIM_CONN 104 #define HN_NVS_TYPE_CHIM_CONNRESP 105 #define HN_NVS_TYPE_CHIM_DISCONN 106 +#define HN_NVS_TYPE_RNDIS 107 #define HN_NVS_TYPE_NDIS_CONF 125 #define HN_NVS_TYPE_SUBCH_REQ 133 #define HN_NVS_TYPE_SUBCH_RESP 133 /* same as SUBCH_REQ */ @@ -162,4 +174,21 @@ struct hn_nvs_subch_resp { uint32_t nvs_nsubch; } __packed; +struct hn_nvs_rndis { + uint32_t nvs_type; /* HN_NVS_TYPE_RNDIS */ + uint32_t nvs_rndis_mtype;/* HN_NVS_RNDIS_MTYPE_ */ + /* + * Chimney sending buffer index and size. + * + * NOTE: + * If nvs_chim_idx is set to HN_NVS_CHIM_IDX_INVALID + * and nvs_chim_sz is set to 0, then chimney sending + * buffer is _not_ used by this RNDIS message. + */ + uint32_t nvs_chim_idx; + uint32_t nvs_chim_sz; + uint8_t nvs_rsvd[16]; +} __packed; +CTASSERT(sizeof(struct hn_nvs_rndis) >= HN_NVS_REQSIZE_MIN); + #endif /* !_IF_HNREG_H_ */ diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h index 60ec33de1641..d6aef5fb81ca 100644 --- a/sys/dev/hyperv/netvsc/if_hnvar.h +++ b/sys/dev/hyperv/netvsc/if_hnvar.h @@ -32,7 +32,7 @@ #include #include -#include +#include struct netvsc_dev_; struct nvsp_msg_; @@ -51,12 +51,12 @@ struct hn_send_ctx { int hn_chim_sz; }; -#define HN_SEND_CTX_INITIALIZER(cb, cbarg) \ -{ \ - .hn_cb = cb, \ - .hn_cbarg = cbarg, \ - .hn_chim_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX, \ - .hn_chim_sz = 0 \ +#define HN_SEND_CTX_INITIALIZER(cb, cbarg) \ +{ \ + .hn_cb = cb, \ + .hn_cbarg = cbarg, \ + .hn_chim_idx = HN_NVS_CHIM_IDX_INVALID, \ + .hn_chim_sz = 0 \ } static __inline void @@ -75,8 +75,7 @@ hn_send_ctx_init_simple(struct hn_send_ctx *sndc, hn_sent_callback_t cb, void *cbarg) { - hn_send_ctx_init(sndc, cb, cbarg, - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX, 0); + hn_send_ctx_init(sndc, cb, cbarg, HN_NVS_CHIM_IDX_INVALID, 0); } static __inline int From de56155fe07cdb25353961e4f9c642127da62508 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Tue, 16 Aug 2016 07:45:35 +0000 Subject: [PATCH 48/67] hyperv/hn: Simplify RNDIS message checks on RX path. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7502 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 13 ++++++------- sys/dev/hyperv/netvsc/if_hnreg.h | 5 +++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index ee47965dd6a4..38242ceba10f 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -847,19 +847,18 @@ hv_nv_on_receive(netvsc_dev *net_dev, struct hn_rx_ring *rxr, struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) { const struct vmbus_chanpkt_rxbuf *pkt; - const nvsp_msg *nvsp_msg_pkt; + const struct hn_nvs_hdr *nvs_hdr; netvsc_packet vsc_pkt; netvsc_packet *net_vsc_pkt = &vsc_pkt; int count = 0; int i = 0; int status = nvsp_status_success; - nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkthdr); - - /* Make sure this is a valid nvsp packet */ - if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) { - if_printf(rxr->hn_ifp, "packet hdr type %u is invalid!\n", - nvsp_msg_pkt->hdr.msg_type); + /* Make sure that this is a RNDIS message. */ + nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr); + if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) { + if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n", + nvs_hdr->nvs_type); return; } diff --git a/sys/dev/hyperv/netvsc/if_hnreg.h b/sys/dev/hyperv/netvsc/if_hnreg.h index 47e1abf09f41..7d86e9e18d02 100644 --- a/sys/dev/hyperv/netvsc/if_hnreg.h +++ b/sys/dev/hyperv/netvsc/if_hnreg.h @@ -69,6 +69,11 @@ */ #define HN_NVS_REQSIZE_MIN 32 +/* NVS message common header */ +struct hn_nvs_hdr { + uint32_t nvs_type; +} __packed; + struct hn_nvs_init { uint32_t nvs_type; /* HN_NVS_TYPE_INIT */ uint32_t nvs_ver_min; From b0754a31cfa10fa27b1fad91461c55929577c929 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Tue, 16 Aug 2016 07:51:05 +0000 Subject: [PATCH 49/67] [mips] fix use-before-initialised. Found by: gcc-5.3 --- sys/mips/mips/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/mips/mips/cpu.c b/sys/mips/mips/cpu.c index c43ba08c61b8..05f546467e3d 100644 --- a/sys/mips/mips/cpu.c +++ b/sys/mips/mips/cpu.c @@ -164,6 +164,8 @@ mips_get_identity(struct mips_cpuinfo *cpuinfo) cfg1 = mips_rd_config1(); /* Get the Config2 and Config3 registers as well. */ + cfg2 = 0; + cfg3 = 0; if (cfg1 & MIPS_CONFIG1_M) { cfg2 = mips_rd_config2(); if (cfg2 & MIPS_CONFIG2_M) From 1c1cc89580f0fbfabaf6f6c7f0f6440eef0c128e Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 16 Aug 2016 08:27:03 +0000 Subject: [PATCH 50/67] The fdatasync(2) call must be cancellation point. Sponsored by: The FreeBSD Foundation MFC after: 13 days --- lib/libc/include/libc_private.h | 2 ++ lib/libc/sys/Makefile.inc | 1 + lib/libc/sys/fdatasync.c | 46 +++++++++++++++++++++++++++++ lib/libc/sys/interposing_table.c | 1 + lib/libthr/thread/thr_syscalls.c | 15 ++++++++++ share/man/man3/pthread_testcancel.3 | 3 +- 6 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 lib/libc/sys/fdatasync.c diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index 8c4d72d14093..cf346f1367f0 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -228,6 +228,7 @@ enum { INTERPOS_wait6, INTERPOS_ppoll, INTERPOS_map_stacks_exec, + INTERPOS_fdatasync, INTERPOS_MAX }; @@ -318,6 +319,7 @@ int __sys_clock_gettime(__clockid_t, struct timespec *ts); int __sys_close(int); int __sys_connect(int, const struct sockaddr *, __socklen_t); int __sys_fcntl(int, int, ...); +int __sys_fdatasync(int); int __sys_fsync(int); __pid_t __sys_fork(void); int __sys_ftruncate(int, __off_t); diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index a2be249e7e62..a37c5661c720 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -37,6 +37,7 @@ INTERPOSED = \ close \ connect \ fcntl \ + fdatasync \ fsync \ fork \ kevent \ diff --git a/lib/libc/sys/fdatasync.c b/lib/libc/sys/fdatasync.c new file mode 100644 index 000000000000..fed97913d31e --- /dev/null +++ b/lib/libc/sys/fdatasync.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 The FreeBSD Foundation. + * All rights reserved. + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "libc_private.h" + +int +fdatasync(int fd) +{ + + return (((int (*)(int))__libc_interposing[INTERPOS_fdatasync])(fd)); +} diff --git a/lib/libc/sys/interposing_table.c b/lib/libc/sys/interposing_table.c index 75bb2804b759..1447e42ef238 100644 --- a/lib/libc/sys/interposing_table.c +++ b/lib/libc/sys/interposing_table.c @@ -79,6 +79,7 @@ interpos_func_t __libc_interposing[INTERPOS_MAX] = { SLOT(wait6, __sys_wait6), SLOT(ppoll, __sys_ppoll), SLOT(map_stacks_exec, __libc_map_stacks_exec), + SLOT(fdatasync, __sys_fdatasync), }; #undef SLOT diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c index 712249b1e573..362826ca2f91 100644 --- a/lib/libthr/thread/thr_syscalls.c +++ b/lib/libthr/thread/thr_syscalls.c @@ -227,6 +227,20 @@ __thr_fsync(int fd) return (ret); } +static int +__thr_fdatasync(int fd) +{ + struct pthread *curthread; + int ret; + + curthread = _get_curthread(); + _thr_cancel_enter2(curthread, 0); + ret = __sys_fdatasync(fd); + _thr_cancel_leave(curthread, 1); + + return (ret); +} + /* * Cancellation behavior: * Thread may be canceled after system call. @@ -653,6 +667,7 @@ __thr_interpose_libc(void) SLOT(wait6); SLOT(ppoll); SLOT(map_stacks_exec); + SLOT(fdatasync); #undef SLOT *(__libc_interposing_slot( INTERPOS__pthread_mutex_init_calloc_cb)) = diff --git a/share/man/man3/pthread_testcancel.3 b/share/man/man3/pthread_testcancel.3 index fc412de5b1ae..1dfc96483445 100644 --- a/share/man/man3/pthread_testcancel.3 +++ b/share/man/man3/pthread_testcancel.3 @@ -1,5 +1,5 @@ .\" $FreeBSD$ -.Dd April 16, 2015 +.Dd August 16, 2016 .Dt PTHREAD_TESTCANCEL 3 .Os .Sh NAME @@ -114,6 +114,7 @@ function is a cancellation point if .Fa cmd is .Dv F_SETLKW . +.It Fn fdatasync .It Fn fsync .It Fn kevent The From 3bb0c17d3ea0361d23368ec287141ea291316851 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Tue, 16 Aug 2016 11:38:45 +0000 Subject: [PATCH 51/67] Don't conflate enum nss_status return values values with int (NS_SUCCESS, NS_RETURN) values. Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D6046 --- lib/libc/net/nss_compat.c | 76 +++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/lib/libc/net/nss_compat.c b/lib/libc/net/nss_compat.c index ba1e95198ced..be2f75762bc2 100644 --- a/lib/libc/net/nss_compat.c +++ b/lib/libc/net/nss_compat.c @@ -97,9 +97,9 @@ __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) const char *name; struct group *grp; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; fn = mdata; name = va_arg(ap, const char *); @@ -107,11 +107,11 @@ __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(name, grp, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(name, grp, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct group **)retval = grp; - return (status); + return (ns_status); } @@ -122,9 +122,9 @@ __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) gid_t gid; struct group *grp; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; fn = mdata; gid = va_arg(ap, gid_t); @@ -132,11 +132,11 @@ __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(gid, grp, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(gid, grp, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct group **)retval = grp; - return (status); + return (ns_status); } @@ -146,9 +146,9 @@ __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) int (*fn)(struct group *, char *, size_t, int *); struct group *grp; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; if (CHECK_TERMINATOR(group)) return (NS_NOTFOUND); @@ -157,13 +157,13 @@ __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(grp, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(grp, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct group **)retval = grp; - else if (status != NS_RETURN) + else if (ns_status != NS_RETURN) SET_TERMINATOR(group, &terminator); - return (status); + return (ns_status); } @@ -198,9 +198,9 @@ __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) const char *name; struct passwd *pwd; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; fn = mdata; name = va_arg(ap, const char *); @@ -208,11 +208,11 @@ __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(name, pwd, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(name, pwd, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct passwd **)retval = pwd; - return (status); + return (ns_status); } @@ -223,9 +223,9 @@ __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) uid_t uid; struct passwd *pwd; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; fn = mdata; uid = va_arg(ap, uid_t); @@ -233,11 +233,11 @@ __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(uid, pwd, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(uid, pwd, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct passwd **)retval = pwd; - return (status); + return (ns_status); } @@ -247,9 +247,9 @@ __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) int (*fn)(struct passwd *, char *, size_t, int *); struct passwd *pwd; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; if (CHECK_TERMINATOR(passwd)) return (NS_NOTFOUND); @@ -258,13 +258,13 @@ __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(pwd, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(pwd, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct passwd **)retval = pwd; - else if (status != NS_RETURN) + else if (ns_status != NS_RETURN) SET_TERMINATOR(passwd, &terminator); - return (status); + return (ns_status); } From 0295d98c14398be863841d4c5f2b9c911cbee733 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Tue, 16 Aug 2016 12:13:12 +0000 Subject: [PATCH 52/67] Trim unneeded bootstrap after r301470 made 9.1 the minimum supported release. MFC after: 3 days Sponsored by: EMC / Isilon Storage Division --- Makefile.inc1 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index 14b553a9058b..1d858d2cf5bc 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1581,10 +1581,6 @@ _groff= gnu/usr.bin/groff \ _vtfontcvt= usr.bin/vtfontcvt .endif -.if ${BOOTSTRAPPING} < 900002 -_sed= usr.bin/sed -.endif - .if ${BOOTSTRAPPING} < 1000033 _libopenbsd= lib/libopenbsd _m4= usr.bin/m4 @@ -1623,10 +1619,6 @@ _crunchide= usr.sbin/crunch/crunchide _crunchgen= usr.sbin/crunch/crunchgen .endif -.if ${BOOTSTRAPPING} >= 900040 && ${BOOTSTRAPPING} < 900041 -_awk= usr.bin/awk -.endif - # r296926 -P keymap search path, MFC to stable/10 in r298297 .if ${BOOTSTRAPPING} < 1003501 || \ (${BOOTSTRAPPING} >= 1100000 && ${BOOTSTRAPPING} < 1100103) @@ -1694,7 +1686,6 @@ bootstrap-tools: .PHONY ${_gperf} \ ${_groff} \ ${_dtc} \ - ${_awk} \ ${_cat} \ ${_dd} \ ${_kbdcontrol} \ @@ -1702,7 +1693,6 @@ bootstrap-tools: .PHONY ${_libopenbsd} \ ${_makewhatis} \ usr.bin/rpcgen \ - ${_sed} \ ${_yacc} \ ${_m4} \ ${_lex} \ From b07fef500b4d2829cb310d101455b3b7a4def353 Mon Sep 17 00:00:00 2001 From: Randall Stewart Date: Tue, 16 Aug 2016 12:40:56 +0000 Subject: [PATCH 53/67] This cleans up the timer code in TCP and also makes it so we do not take the INFO lock *unless* we are really going to delete the TCB. Differential Revision: D7136 --- sys/netinet/tcp_timer.c | 188 +++++++++++++++++++--------------------- sys/netinet/tcp_timer.h | 3 + 2 files changed, 93 insertions(+), 98 deletions(-) diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 837913e190eb..183271cfd1ac 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -294,11 +294,6 @@ tcp_timer_delack(void *xtp) CURVNET_RESTORE(); return; } - KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, - ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_DELACK) != 0, - ("%s: tp %p delack callout should be running", __func__, tp)); - tp->t_flags |= TF_ACKNOW; TCPSTAT_INC(tcps_delack); (void) tp->t_fb->tfb_tcp_output(tp); @@ -306,6 +301,39 @@ tcp_timer_delack(void *xtp) CURVNET_RESTORE(); } +int +tcp_inpinfo_lock_add(struct inpcb *inp) +{ + in_pcbref(inp); + INP_WUNLOCK(inp); + INP_INFO_RLOCK(&V_tcbinfo); + INP_WLOCK(inp); + if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { + return(1); + } + return(0); + +} + +void +tcp_inpinfo_lock_del(struct inpcb *inp, struct tcpcb *tp) +{ + INP_INFO_RUNLOCK(&V_tcbinfo); + if (inp && (tp == NULL)) { + /* + * If tcp_close/drop() gets called and tp + * returns NULL, then the function dropped + * the inp lock, we hold a reference keeping + * this around, so we must re-aquire the + * INP_WLOCK() in order to proceed with + * our dropping the inp reference. + */ + INP_WLOCK(inp); + } + if (inp && in_pcbrele_wlocked(inp) == 0) + INP_WUNLOCK(inp); +} + void tcp_timer_2msl(void *xtp) { @@ -317,7 +345,6 @@ tcp_timer_2msl(void *xtp) ostate = tp->t_state; #endif - INP_INFO_RLOCK(&V_tcbinfo); inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); INP_WLOCK(inp); @@ -325,21 +352,17 @@ tcp_timer_2msl(void *xtp) if (callout_pending(&tp->t_timers->tt_2msl) || !callout_active(&tp->t_timers->tt_2msl)) { INP_WUNLOCK(tp->t_inpcb); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } callout_deactivate(&tp->t_timers->tt_2msl); if ((inp->inp_flags & INP_DROPPED) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_2MSL) != 0, - ("%s: tp %p 2msl callout should be running", __func__, tp)); /* * 2 MSL timeout in shutdown went off. If we're closed but * still waiting for peer to close and connection has been idle @@ -355,7 +378,6 @@ tcp_timer_2msl(void *xtp) */ if ((inp->inp_flags & INP_TIMEWAIT) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } @@ -363,15 +385,26 @@ tcp_timer_2msl(void *xtp) tp->t_inpcb && tp->t_inpcb->inp_socket && (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) { TCPSTAT_INC(tcps_finwait2_drops); + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_close(tp); + tcp_inpinfo_lock_del(inp, tp); + goto out; } else { if (ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) { - if (!callout_reset(&tp->t_timers->tt_2msl, - TP_KEEPINTVL(tp), tcp_timer_2msl, tp)) { - tp->t_timers->tt_flags &= ~TT_2MSL_RST; + callout_reset(&tp->t_timers->tt_2msl, + TP_KEEPINTVL(tp), tcp_timer_2msl, tp); + } else { + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; } - } else - tp = tcp_close(tp); + tp = tcp_close(tp); + tcp_inpinfo_lock_del(inp, tp); + goto out; + } } #ifdef TCPDEBUG @@ -383,7 +416,7 @@ tcp_timer_2msl(void *xtp) if (tp != NULL) INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); +out: CURVNET_RESTORE(); } @@ -399,28 +432,23 @@ tcp_timer_keep(void *xtp) ostate = tp->t_state; #endif - INP_INFO_RLOCK(&V_tcbinfo); inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); INP_WLOCK(inp); if (callout_pending(&tp->t_timers->tt_keep) || !callout_active(&tp->t_timers->tt_keep)) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } callout_deactivate(&tp->t_timers->tt_keep); if ((inp->inp_flags & INP_DROPPED) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_KEEP) != 0, - ("%s: tp %p keep callout should be running", __func__, tp)); /* * Keep-alive timer went off; send something * or drop connection if idle for too long. @@ -452,14 +480,11 @@ tcp_timer_keep(void *xtp) tp->rcv_nxt, tp->snd_una - 1, 0); free(t_template, M_TEMP); } - if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp), - tcp_timer_keep, tp)) { - tp->t_timers->tt_flags &= ~TT_KEEP_RST; - } - } else if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp), - tcp_timer_keep, tp)) { - tp->t_timers->tt_flags &= ~TT_KEEP_RST; - } + callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp), + tcp_timer_keep, tp); + } else + callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp), + tcp_timer_keep, tp); #ifdef TCPDEBUG if (inp->inp_socket->so_options & SO_DEBUG) @@ -468,12 +493,16 @@ tcp_timer_keep(void *xtp) #endif TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; dropit: TCPSTAT_INC(tcps_keepdrops); + + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_drop(tp, ETIMEDOUT); #ifdef TCPDEBUG @@ -482,9 +511,8 @@ dropit: PRU_SLOWTIMO); #endif TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); - if (tp != NULL) - INP_WUNLOCK(tp->t_inpcb); - INP_INFO_RUNLOCK(&V_tcbinfo); + tcp_inpinfo_lock_del(inp, tp); +out: CURVNET_RESTORE(); } @@ -499,28 +527,23 @@ tcp_timer_persist(void *xtp) ostate = tp->t_state; #endif - INP_INFO_RLOCK(&V_tcbinfo); inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); INP_WLOCK(inp); if (callout_pending(&tp->t_timers->tt_persist) || !callout_active(&tp->t_timers->tt_persist)) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } callout_deactivate(&tp->t_timers->tt_persist); if ((inp->inp_flags & INP_DROPPED) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_PERSIST) != 0, - ("%s: tp %p persist callout should be running", __func__, tp)); /* * Persistence timer into zero window. * Force a byte to be output, if possible. @@ -537,7 +560,12 @@ tcp_timer_persist(void *xtp) (ticks - tp->t_rcvtime >= tcp_maxpersistidle || ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) { TCPSTAT_INC(tcps_persistdrop); + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_drop(tp, ETIMEDOUT); + tcp_inpinfo_lock_del(inp, tp); goto out; } /* @@ -547,7 +575,12 @@ tcp_timer_persist(void *xtp) if (tp->t_state > TCPS_CLOSE_WAIT && (ticks - tp->t_rcvtime) >= TCPTV_PERSMAX) { TCPSTAT_INC(tcps_persistdrop); + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_drop(tp, ETIMEDOUT); + tcp_inpinfo_lock_del(inp, tp); goto out; } tcp_setpersist(tp); @@ -555,15 +588,13 @@ tcp_timer_persist(void *xtp) (void) tp->t_fb->tfb_tcp_output(tp); tp->t_flags &= ~TF_FORCEDATA; -out: #ifdef TCPDEBUG if (tp != NULL && tp->t_inpcb->inp_socket->so_options & SO_DEBUG) tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO); #endif TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); - if (tp != NULL) - INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); + INP_WUNLOCK(inp); +out: CURVNET_RESTORE(); } @@ -573,36 +604,29 @@ tcp_timer_rexmt(void * xtp) struct tcpcb *tp = xtp; CURVNET_SET(tp->t_vnet); int rexmt; - int headlocked; struct inpcb *inp; #ifdef TCPDEBUG int ostate; ostate = tp->t_state; #endif - - INP_INFO_RLOCK(&V_tcbinfo); inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); INP_WLOCK(inp); if (callout_pending(&tp->t_timers->tt_rexmt) || !callout_active(&tp->t_timers->tt_rexmt)) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } callout_deactivate(&tp->t_timers->tt_rexmt); if ((inp->inp_flags & INP_DROPPED) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_REXMT) != 0, - ("%s: tp %p rexmt callout should be running", __func__, tp)); tcp_free_sackholes(tp); if (tp->t_fb->tfb_tcp_rexmit_tmr) { /* The stack has a timer action too. */ @@ -616,14 +640,15 @@ tcp_timer_rexmt(void * xtp) if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { tp->t_rxtshift = TCP_MAXRXTSHIFT; TCPSTAT_INC(tcps_timeoutdrop); - + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_drop(tp, tp->t_softerror ? tp->t_softerror : ETIMEDOUT); - headlocked = 1; + tcp_inpinfo_lock_del(inp, tp); goto out; } - INP_INFO_RUNLOCK(&V_tcbinfo); - headlocked = 0; if (tp->t_state == TCPS_SYN_SENT) { /* * If the SYN was retransmitted, indicate CWND to be @@ -811,17 +836,14 @@ tcp_timer_rexmt(void * xtp) (void) tp->t_fb->tfb_tcp_output(tp); -out: #ifdef TCPDEBUG if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0, PRU_SLOWTIMO); #endif TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); - if (tp != NULL) - INP_WUNLOCK(inp); - if (headlocked) - INP_INFO_RUNLOCK(&V_tcbinfo); + INP_WUNLOCK(inp); +out: CURVNET_RESTORE(); } @@ -832,7 +854,6 @@ tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) timeout_t *f_callout; struct inpcb *inp = tp->t_inpcb; int cpu = inp_to_cpuid(inp); - uint32_t f_reset; #ifdef TCP_OFFLOAD if (tp->t_flags & TF_TOE) @@ -846,27 +867,22 @@ tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) case TT_DELACK: t_callout = &tp->t_timers->tt_delack; f_callout = tcp_timer_delack; - f_reset = TT_DELACK_RST; break; case TT_REXMT: t_callout = &tp->t_timers->tt_rexmt; f_callout = tcp_timer_rexmt; - f_reset = TT_REXMT_RST; break; case TT_PERSIST: t_callout = &tp->t_timers->tt_persist; f_callout = tcp_timer_persist; - f_reset = TT_PERSIST_RST; break; case TT_KEEP: t_callout = &tp->t_timers->tt_keep; f_callout = tcp_timer_keep; - f_reset = TT_KEEP_RST; break; case TT_2MSL: t_callout = &tp->t_timers->tt_2msl; f_callout = tcp_timer_2msl; - f_reset = TT_2MSL_RST; break; default: if (tp->t_fb->tfb_tcp_timer_activate) { @@ -876,24 +892,9 @@ tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) panic("tp %p bad timer_type %#x", tp, timer_type); } if (delta == 0) { - if ((tp->t_timers->tt_flags & timer_type) && - (callout_stop(t_callout) > 0) && - (tp->t_timers->tt_flags & f_reset)) { - tp->t_timers->tt_flags &= ~(timer_type | f_reset); - } + callout_stop(t_callout); } else { - if ((tp->t_timers->tt_flags & timer_type) == 0) { - tp->t_timers->tt_flags |= (timer_type | f_reset); - callout_reset_on(t_callout, delta, f_callout, tp, cpu); - } else { - /* Reset already running callout on the same CPU. */ - if (!callout_reset(t_callout, delta, f_callout, tp)) { - /* - * Callout not cancelled, consider it as not - * properly restarted. */ - tp->t_timers->tt_flags &= ~f_reset; - } - } + callout_reset_on(t_callout, delta, f_callout, tp, cpu); } } @@ -931,30 +932,23 @@ void tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type) { struct callout *t_callout; - uint32_t f_reset; tp->t_timers->tt_flags |= TT_STOPPED; - switch (timer_type) { case TT_DELACK: t_callout = &tp->t_timers->tt_delack; - f_reset = TT_DELACK_RST; break; case TT_REXMT: t_callout = &tp->t_timers->tt_rexmt; - f_reset = TT_REXMT_RST; break; case TT_PERSIST: t_callout = &tp->t_timers->tt_persist; - f_reset = TT_PERSIST_RST; break; case TT_KEEP: t_callout = &tp->t_timers->tt_keep; - f_reset = TT_KEEP_RST; break; case TT_2MSL: t_callout = &tp->t_timers->tt_2msl; - f_reset = TT_2MSL_RST; break; default: if (tp->t_fb->tfb_tcp_timer_stop) { @@ -968,15 +962,13 @@ tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type) panic("tp %p bad timer_type %#x", tp, timer_type); } - if (tp->t_timers->tt_flags & timer_type) { - if (callout_async_drain(t_callout, tcp_timer_discard) == 0) { - /* - * Can't stop the callout, defer tcpcb actual deletion - * to the last one. We do this using the async drain - * function and incrementing the count in - */ - tp->t_timers->tt_draincnt++; - } + if (callout_async_drain(t_callout, tcp_timer_discard) == 0) { + /* + * Can't stop the callout, defer tcpcb actual deletion + * to the last one. We do this using the async drain + * function and incrementing the count in + */ + tp->t_timers->tt_draincnt++; } } diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h index 12481b5708a8..bb78062ddea4 100644 --- a/sys/netinet/tcp_timer.h +++ b/sys/netinet/tcp_timer.h @@ -191,6 +191,9 @@ extern int tcp_syn_backoff[]; extern int tcp_finwait2_timeout; extern int tcp_fast_finwait2_recycle; +int tcp_inpinfo_lock_add(struct inpcb *inp); +void tcp_inpinfo_lock_del(struct inpcb *inp, struct tcpcb *tp); + void tcp_timer_init(void); void tcp_timer_2msl(void *xtp); void tcp_timer_discard(void *); From 0fa047b98c07b0e555ac3b0c2898de82abb44a0a Mon Sep 17 00:00:00 2001 From: Randall Stewart Date: Tue, 16 Aug 2016 13:08:03 +0000 Subject: [PATCH 54/67] Comments describing how to properly use the new lock_add functions and its respective companion. Sponsored by: Netflix Inc. --- sys/netinet/tcp_timer.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 183271cfd1ac..1be20ce8643f 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -301,6 +301,25 @@ tcp_timer_delack(void *xtp) CURVNET_RESTORE(); } +/* + * When a timer wants to remove a TCB it must + * hold the INP_INFO_RLOCK(). The timer function + * should only have grabbed the INP_WLOCK() when + * it entered. To safely switch to holding both the + * INP_INFO_RLOCK() and the INP_WLOCK() we must first + * grab a reference on the inp, this will hold the inp + * so that it can't be removed. We then unlock and grab + * the info-read lock. Once we have the INP_INFO_RLOCK() we + * proceed again to get the INP_WLOCK() but after that + * we must check if someone else deleted the pcb i.e. + * the inp_flags check. If so we return 1 otherwise + * we return 0. + * + * No matter which the tcp_inpinfo_lock_add() function + * returns the caller must afterwards call tcp_inpinfo_lock_del() + * to drop the locks and reference properly. + */ + int tcp_inpinfo_lock_add(struct inpcb *inp) { From 80a29058832fc0077e285b748cf89c7a186bd8e1 Mon Sep 17 00:00:00 2001 From: Sofian Brabez Date: Tue, 16 Aug 2016 14:15:09 +0000 Subject: [PATCH 55/67] tty: Use proper definition of exit status code and stdin macro Reviewed by: bapt, bdrewery Differential Revision: https://reviews.freebsd.org/D6828 --- usr.bin/tty/tty.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/usr.bin/tty/tty.c b/usr.bin/tty/tty.c index 450722a66984..fac74d034b5d 100644 --- a/usr.bin/tty/tty.c +++ b/usr.bin/tty/tty.c @@ -63,17 +63,18 @@ main(int argc, char *argv[]) case '?': default: usage(); + /* NOTREACHED */ } - t = ttyname(0); + t = ttyname(STDIN_FILENO); if (!sflag) puts(t ? t : "not a tty"); - exit(t ? 0 : 1); + exit(t ? EXIT_SUCCESS : EXIT_FAILURE); } static void usage(void) { - fprintf(stderr, "usage: tty [-s]\n"); + fprintf(stderr, "usage: %s [-s]\n", getprogname()); exit(2); } From 5f306327fe1d57c1c7740c928559bb2dd7c1c328 Mon Sep 17 00:00:00 2001 From: Emmanuel Vadot Date: Tue, 16 Aug 2016 14:23:35 +0000 Subject: [PATCH 56/67] Use %ju modifier for u_int64_t and %jd modifier for off_t. off_t is long long on arm32 and long on amd64 MFC after: 1 week --- sys/boot/efi/boot1/ufs_module.c | 2 +- sys/boot/efi/boot1/zfs_module.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/boot/efi/boot1/ufs_module.c b/sys/boot/efi/boot1/ufs_module.c index ae3e9ac4b6f6..2efdfc7e69e5 100644 --- a/sys/boot/efi/boot1/ufs_module.c +++ b/sys/boot/efi/boot1/ufs_module.c @@ -56,7 +56,7 @@ dskread(void *buf, u_int64_t lba, int nblk) devinfo->dev->Media->MediaId, lba, size, buf); if (status != EFI_SUCCESS) { - DPRINTF("dskread: failed dev: %p, id: %u, lba: %lu, size: %d, " + DPRINTF("dskread: failed dev: %p, id: %u, lba: %zu, size: %d, " "status: %lu\n", devinfo->dev, devinfo->dev->Media->MediaId, lba, size, EFI_ERROR_CODE(status)); diff --git a/sys/boot/efi/boot1/zfs_module.c b/sys/boot/efi/boot1/zfs_module.c index 07d66bbd8ca1..60ad7c0eac0c 100644 --- a/sys/boot/efi/boot1/zfs_module.c +++ b/sys/boot/efi/boot1/zfs_module.c @@ -53,7 +53,7 @@ vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes) status = devinfo->dev->ReadBlocks(devinfo->dev, devinfo->dev->Media->MediaId, lba, bytes, buf); if (status != EFI_SUCCESS) { - DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %zu, size: %zu," + DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %jd, size: %zu," " status: %lu\n", devinfo->dev, devinfo->dev->Media->MediaId, lba, bytes, EFI_ERROR_CODE(status)); From 858a3f496fd101a71c8842edfd9e2770fce87aea Mon Sep 17 00:00:00 2001 From: Emmanuel Vadot Date: Tue, 16 Aug 2016 14:33:25 +0000 Subject: [PATCH 57/67] Only use WaitForKeys event if it exists, this is not the case in u-boot efi implementation. Reviewed by: jhb, emaste MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6781 --- sys/boot/efi/libefi/efi_console.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sys/boot/efi/libefi/efi_console.c b/sys/boot/efi/libefi/efi_console.c index 838becc5d2a6..6ad5d3c1e142 100644 --- a/sys/boot/efi/libefi/efi_console.c +++ b/sys/boot/efi/libefi/efi_console.c @@ -438,8 +438,10 @@ efi_cons_getchar() /* Try to read a key stroke. We wait for one if none is pending. */ status = conin->ReadKeyStroke(conin, &key); - if (status == EFI_NOT_READY) { - BS->WaitForEvent(1, &conin->WaitForKey, &junk); + while (status == EFI_NOT_READY) { + /* Some EFI implementation (u-boot for example) do not support WaitForKey */ + if (conin->WaitForKey != NULL) + BS->WaitForEvent(1, &conin->WaitForKey, &junk); status = conin->ReadKeyStroke(conin, &key); } switch (key.ScanCode) { @@ -454,6 +456,9 @@ efi_cons_getchar() int efi_cons_poll() { + + if (conin->WaitForKey == NULL) + return (1); /* This can clear the signaled state. */ return (BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS); } From 587d67c008444a7d35d918763708b7aba40a9509 Mon Sep 17 00:00:00 2001 From: Randall Stewart Date: Tue, 16 Aug 2016 15:11:46 +0000 Subject: [PATCH 58/67] Here we update the modular tcp to be able to switch to an alternate TCP stack in other then the closed state (pre-listen/connect). The idea is that *if* that is supported by the alternate stack, it is asked if its ok to switch. If it approves the "handoff" then we allow the switch to happen. Also the fini() function now gets a flag to tell if you are switching away *or* the tcb is destroyed. The init() call into the alternate stack is moved to the end so the tcb is more fully formed before the init transpires. Sponsored by: Netflix Inc. Differential Revision: D6790 --- share/man/man4/tcp.4 | 3 +- share/man/man9/tcp_functions.9 | 52 ++++++++++++++++++++++++-- sys/netinet/tcp_subr.c | 14 +++---- sys/netinet/tcp_syncache.c | 2 +- sys/netinet/tcp_usrreq.c | 67 ++++++++++++++++++++++------------ sys/netinet/tcp_var.h | 15 +++++++- 6 files changed, 116 insertions(+), 37 deletions(-) diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4 index f275a4da45f9..54f503f5c2c8 100644 --- a/share/man/man4/tcp.4 +++ b/share/man/man4/tcp.4 @@ -633,7 +633,8 @@ when trying to use a TCP function block that is not available; .Xr mod_cc 4 , .Xr siftr 4 , .Xr syncache 4 , -.Xr setkey 8 +.Xr setkey 8 , +.Xr tcp_functions 9 .Rs .%A "V. Jacobson" .%A "R. Braden" diff --git a/share/man/man9/tcp_functions.9 b/share/man/man9/tcp_functions.9 index 06c42ff0fa60..b998dd0dd7df 100644 --- a/share/man/man9/tcp_functions.9 +++ b/share/man/man9/tcp_functions.9 @@ -114,14 +114,17 @@ struct tcp_function_block { struct inpcb *inp, struct tcpcb *tp); /* Optional memory allocation/free routine */ void (*tfb_tcp_fb_init)(struct tcpcb *); - void (*tfb_tcp_fb_fini)(struct tcpcb *); + void (*tfb_tcp_fb_fini)(struct tcpcb *, int); /* Optional timers, must define all if you define one */ int (*tfb_tcp_timer_stop_all)(struct tcpcb *); void (*tfb_tcp_timer_activate)(struct tcpcb *, uint32_t, u_int); int (*tfb_tcp_timer_active)(struct tcpcb *, uint32_t); void (*tfb_tcp_timer_stop)(struct tcpcb *, uint32_t); + /* Optional functions */ void (*tfb_tcp_rexmit_tmr)(struct tcpcb *); + void (*tfb_tcp_handoff_ok)(struct tcpcb *); + /* System use */ volatile uint32_t tfb_refcnt; uint32_t tfb_flags; }; @@ -157,6 +160,16 @@ in the .Va tfb_tcp_fb_fini field. .Pp +If the +.Va tfb_tcp_fb_fini +argument is non-NULL, the function to which it points is called when the +kernel is destroying the TCP control block or when the socket is transitioning +to use a different TCP stack. +The function is called with arguments of the TCP control block and an integer +flag. +The flag will be zero if the socket is transitioning to use another TCP stack +or one if the TCP control block is being destroyed. +.Pp If the TCP stack implements additional timers, the TCP stack should set a non-NULL pointer in the .Va tfb_tcp_timer_stop_all , @@ -193,6 +206,37 @@ However, care must be taken to ensure the retransmit timer leaves the TCP control block in a valid state for the remainder of the retransmit timer logic. .Pp +A user may select a new TCP stack before calling +.Xr connect 2 +or +.Xr listen 2 . +Optionally, a TCP stack may also allow a user to begin using the TCP stack for +a connection that is in a later state by setting a non-NULL function pointer in +the +.Va tfb_tcp_handoff_ok +field. +If this field is non-NULL and a user attempts to select that TCP stack after +calling +.Xr connect 2 +or +.Xr listen 2 +for that socket, the kernel will call the function pointed to by the +.Va tfb_tcp_handoff_ok +field. +The function should return 0 if the user is allowed to switch the socket to use +the TCP stack. Otherwise, the function should return an error code, which will +be returned to the user. +If the +.Va tfb_tcp_handoff_ok +field is +.Dv NULL +and a user attempts to select the TCP stack after calling +.Xr connect 2 +or +.Xr listen 2 +for that socket, the operation will fail and the kernel will return +.Er EINVAL . +.Pp The .Va tfb_refcnt and @@ -269,8 +313,10 @@ The .Fa blk argument references a function block that is not currently registered. .Sh SEE ALSO -.Xr malloc 9 , -.Xr tcp 4 +.Xr connect 2 , +.Xr listen 2 , +.Xr tcp 4 , +.Xr malloc 9 .Sh HISTORY This framework first appeared in .Fx 11.0 . diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index a9cd81925dac..097a1e3bbf84 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1187,9 +1187,6 @@ tcp_newtcpcb(struct inpcb *inp) tp->t_fb = tcp_func_set_ptr; refcount_acquire(&tp->t_fb->tfb_refcnt); rw_runlock(&tcp_function_lock); - if (tp->t_fb->tfb_tcp_fb_init) { - (*tp->t_fb->tfb_tcp_fb_init)(tp); - } /* * Use the current system default CC algorithm. */ @@ -1201,7 +1198,7 @@ tcp_newtcpcb(struct inpcb *inp) if (CC_ALGO(tp)->cb_init != NULL) if (CC_ALGO(tp)->cb_init(tp->ccv) > 0) { if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); uma_zfree(V_tcpcb_zone, tm); return (NULL); @@ -1210,7 +1207,7 @@ tcp_newtcpcb(struct inpcb *inp) tp->osd = &tm->osd; if (khelp_init_osd(HELPER_CLASS_TCP, tp->osd)) { if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); uma_zfree(V_tcpcb_zone, tm); return (NULL); @@ -1271,6 +1268,9 @@ tcp_newtcpcb(struct inpcb *inp) */ tcp_pcap_tcpcb_init(tp); #endif + if (tp->t_fb->tfb_tcp_fb_init) { + (*tp->t_fb->tfb_tcp_fb_init)(tp); + } return (tp); /* XXX */ } @@ -1484,7 +1484,7 @@ tcp_discardcb(struct tcpcb *tp) if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on tcpcb, let's free it. */ if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); tp->t_inpcb = NULL; uma_zfree(V_tcpcb_zone, tp); @@ -1513,7 +1513,7 @@ tcp_timer_discard(void *ptp) if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on this tcpcb, let's free it. */ if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); tp->t_inpcb = NULL; uma_zfree(V_tcpcb_zone, tp); diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 5bb18b0d8d35..e74db3adda50 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -842,7 +842,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) KASSERT(rblk != NULL, ("cannot find blk %p out of syncache?", blk)); if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 0); refcount_release(&tp->t_fb->tfb_refcnt); tp->t_fb = rblk; if (tp->t_fb->tfb_tcp_fb_init) { diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 204c354ccfb2..ce5cbee7ee1b 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1420,40 +1420,59 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt) if (error) return (error); INP_WLOCK_RECHECK(inp); - if (tp->t_state != TCPS_CLOSED) { - /* - * The user has advanced the state - * past the initial point, we can't - * switch since we are down the road - * and a new set of functions may - * not be compatibile. - */ - INP_WUNLOCK(inp); - return(EINVAL); - } blk = find_and_ref_tcp_functions(&fsn); if (blk == NULL) { INP_WUNLOCK(inp); return (ENOENT); } - if (tp->t_fb != blk) { - if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) { + if (tp->t_fb == blk) { + /* You already have this */ + refcount_release(&blk->tfb_refcnt); + INP_WUNLOCK(inp); + return (0); + } + if (tp->t_state != TCPS_CLOSED) { + int error=EINVAL; + /* + * The user has advanced the state + * past the initial point, we may not + * be able to switch. + */ + if (blk->tfb_tcp_handoff_ok != NULL) { + /* + * Does the stack provide a + * query mechanism, if so it may + * still be possible? + */ + error = (*blk->tfb_tcp_handoff_ok)(tp); + } + if (error) { refcount_release(&blk->tfb_refcnt); INP_WUNLOCK(inp); - return (ENOENT); + return(error); } + } + if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) { + refcount_release(&blk->tfb_refcnt); + INP_WUNLOCK(inp); + return (ENOENT); + } + /* + * Release the old refcnt, the + * lookup acquired a ref on the + * new one already. + */ + if (tp->t_fb->tfb_tcp_fb_fini) { /* - * Release the old refcnt, the - * lookup acquires a ref on the - * new one. + * Tell the stack to cleanup with 0 i.e. + * the tcb is not going away. */ - if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); - refcount_release(&tp->t_fb->tfb_refcnt); - tp->t_fb = blk; - if (tp->t_fb->tfb_tcp_fb_init) { - (*tp->t_fb->tfb_tcp_fb_init)(tp); - } + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 0); + } + refcount_release(&tp->t_fb->tfb_refcnt); + tp->t_fb = blk; + if (tp->t_fb->tfb_tcp_fb_init) { + (*tp->t_fb->tfb_tcp_fb_init)(tp); } #ifdef TCP_OFFLOAD if (tp->t_flags & TF_TOE) { diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index abfa21ab216f..5dcd35b8979f 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -116,6 +116,18 @@ struct socket; * does not know your callbacks you must provide a * stop_all function that loops through and calls * tcp_timer_stop() with each of your defined timers. + * Adding a tfb_tcp_handoff_ok function allows the socket + * option to change stacks to query you even if the + * connection is in a later stage. You return 0 to + * say you can take over and run your stack, you return + * non-zero (an error number) to say no you can't. + * If the function is undefined you can only change + * in the early states (before connect or listen). + * tfb_tcp_fb_fini is changed to add a flag to tell + * the old stack if the tcb is being destroyed or + * not. A one in the flag means the TCB is being + * destroyed, a zero indicates its transitioning to + * another stack (via socket option). */ struct tcp_function_block { char tfb_tcp_block_name[TCP_FUNCTION_NAME_LEN_MAX]; @@ -128,7 +140,7 @@ struct tcp_function_block { struct inpcb *inp, struct tcpcb *tp); /* Optional memory allocation/free routine */ void (*tfb_tcp_fb_init)(struct tcpcb *); - void (*tfb_tcp_fb_fini)(struct tcpcb *); + void (*tfb_tcp_fb_fini)(struct tcpcb *, int); /* Optional timers, must define all if you define one */ int (*tfb_tcp_timer_stop_all)(struct tcpcb *); void (*tfb_tcp_timer_activate)(struct tcpcb *, @@ -136,6 +148,7 @@ struct tcp_function_block { int (*tfb_tcp_timer_active)(struct tcpcb *, uint32_t); void (*tfb_tcp_timer_stop)(struct tcpcb *, uint32_t); void (*tfb_tcp_rexmit_tmr)(struct tcpcb *); + int (*tfb_tcp_handoff_ok)(struct tcpcb *); volatile uint32_t tfb_refcnt; uint32_t tfb_flags; }; From eadd00f81ad281cc2bdf08d070f96733f912c618 Mon Sep 17 00:00:00 2001 From: Randall Stewart Date: Tue, 16 Aug 2016 15:17:36 +0000 Subject: [PATCH 59/67] A few more wording tweaks as suggested (with some modifications as well) by Ravi Pokala. Thanks for the comments :-) Sponsored by: Netflix Inc. --- sys/netinet/tcp_timer.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 1be20ce8643f..5f231c079784 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -307,15 +307,15 @@ tcp_timer_delack(void *xtp) * should only have grabbed the INP_WLOCK() when * it entered. To safely switch to holding both the * INP_INFO_RLOCK() and the INP_WLOCK() we must first - * grab a reference on the inp, this will hold the inp - * so that it can't be removed. We then unlock and grab - * the info-read lock. Once we have the INP_INFO_RLOCK() we - * proceed again to get the INP_WLOCK() but after that - * we must check if someone else deleted the pcb i.e. - * the inp_flags check. If so we return 1 otherwise - * we return 0. + * grab a reference on the inp, which will hold the inp + * so that it can't be removed. We then unlock the INP_WLOCK(), + * and grab the INP_INFO_RLOCK() lock. Once we have the INP_INFO_RLOCK() + * we proceed again to get the INP_WLOCK() (this preserves proper + * lock order). After acquiring the INP_WLOCK we must check if someone + * else deleted the pcb i.e. the inp_flags check. + * If so we return 1 otherwise we return 0. * - * No matter which the tcp_inpinfo_lock_add() function + * No matter what the tcp_inpinfo_lock_add() function * returns the caller must afterwards call tcp_inpinfo_lock_del() * to drop the locks and reference properly. */ From 4c59a8860a03f90a1c0f62be12b29f7e431c5ddb Mon Sep 17 00:00:00 2001 From: Marcelo Araujo Date: Tue, 16 Aug 2016 15:52:10 +0000 Subject: [PATCH 60/67] Use nitems() from sys/param.h. MFC after: 2 weeks. --- usr.bin/systat/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c index 4c55ff4cfe29..74195f606aec 100644 --- a/usr.bin/systat/main.c +++ b/usr.bin/systat/main.c @@ -261,7 +261,7 @@ display(void) int i, j; /* Get the load average over the last minute. */ - (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); + (void) getloadavg(avenrun, nitems(avenrun)); (*curcmd->c_fetch)(); if (curcmd->c_flags & CF_LOADAV) { j = 5.0*avenrun[0] + 0.5; @@ -293,7 +293,7 @@ display(void) GETSYSCTL("kstat.zfs.misc.arcstats.l2_hdr_size", arc[5]); GETSYSCTL("kstat.zfs.misc.arcstats.other_size", arc[6]); wmove(wload, 0, 0); wclrtoeol(wload); - for (i = 0 ; i < sizeof(arc) / sizeof(arc[0]) ; i++) { + for (i = 0 ; i < nitems(arc); i++) { if (arc[i] > 10llu * 1024 * 1024 * 1024 ) { wprintw(wload, "%7lluG", arc[i] >> 30); } @@ -318,7 +318,7 @@ void load(void) { - (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])); + (void) getloadavg(avenrun, nitems(avenrun)); mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f", avenrun[0], avenrun[1], avenrun[2]); clrtoeol(); From 4b61b26b28de236e2699d44c262dfe18d3dfe554 Mon Sep 17 00:00:00 2001 From: Marcelo Araujo Date: Tue, 16 Aug 2016 15:53:05 +0000 Subject: [PATCH 61/67] Use nitems() from sys/param.h. MFC after: 2 weeks. --- usr.bin/rpcgen/rpc_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr.bin/rpcgen/rpc_main.c b/usr.bin/rpcgen/rpc_main.c index 32e47a07e6f9..78bc610ae8e0 100644 --- a/usr.bin/rpcgen/rpc_main.c +++ b/usr.bin/rpcgen/rpc_main.c @@ -82,11 +82,11 @@ static char pathbuf[MAXPATHLEN + 1]; static const char *allv[] = { "rpcgen", "-s", "udp", "-s", "tcp", }; -static int allc = sizeof (allv)/sizeof (allv[0]); +static int allc = nitems(allv); static const char *allnv[] = { "rpcgen", "-s", "netpath", }; -static int allnc = sizeof (allnv)/sizeof (allnv[0]); +static int allnc = nitems(allnv); /* * machinations for handling expanding argument list From f1503c5a498a501da335f180176b326ffc77a085 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 16 Aug 2016 16:49:56 +0000 Subject: [PATCH 62/67] In ffs_balloc_ufs{1,2} routines, assert that unwind records do not overflow local arrays. This is not immediately obvious from the static code inspection, due to retry logic. Reviewed by: mckusick Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/ufs/ffs/ffs_balloc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 8551085b50a7..b78a7caed3e4 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -255,6 +255,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, } pref = newb + fs->fs_frag; nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = indirs[1].in_lbn; bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, gbflags); @@ -325,6 +327,8 @@ retry: } pref = newb + fs->fs_frag; nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = indirs[i].in_lbn; nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0, 0); @@ -401,6 +405,8 @@ retry: goto fail; } nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = lbn; nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, gbflags); @@ -818,6 +824,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, } pref = newb + fs->fs_frag; nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = indirs[1].in_lbn; bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, @@ -889,6 +897,8 @@ retry: } pref = newb + fs->fs_frag; nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = indirs[i].in_lbn; nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0, @@ -966,6 +976,8 @@ retry: goto fail; } nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = lbn; nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, gbflags); From 554248587e865153963a6b8e6ffa8d417732cfde Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 16 Aug 2016 16:50:48 +0000 Subject: [PATCH 63/67] When block allocation fails in UFS_BALLOC(), and the volume does not have SU enabled, there is no point in calling softdep_request_cleanup(). The call cannot produce free blocks, but we unecessarily lock ufsmount and do inode block write. Usual point of not doing optimizations for the corner case of the full volume is not applicable there, the work is easily avoidable, and the addition CPU and disk io load do not lead to succeeding retry. Reviewed by: mckusick Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/ufs/ffs/ffs_balloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index b78a7caed3e4..e1188327d9ca 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -311,7 +311,7 @@ retry: if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags | IO_BUFLOCKED, cred, &newb)) != 0) { brelse(bp); - if (++reclaimed == 1) { + if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); @@ -390,7 +390,7 @@ retry: flags | IO_BUFLOCKED, cred, &newb); if (error) { brelse(bp); - if (++reclaimed == 1) { + if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); @@ -881,7 +881,7 @@ retry: if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags | IO_BUFLOCKED, cred, &newb)) != 0) { brelse(bp); - if (++reclaimed == 1) { + if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); @@ -961,7 +961,7 @@ retry: flags | IO_BUFLOCKED, cred, &newb); if (error) { brelse(bp); - if (++reclaimed == 1) { + if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); From 39f7cbe9ab1fc835a08e3eb73895afdba4701719 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 16 Aug 2016 17:05:15 +0000 Subject: [PATCH 64/67] When looking up dandling buffers for unwing after failing block allocation in UFS_BALLOC(), there is no need to map them. Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/ufs/ffs/ffs_balloc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index e1188327d9ca..79df83d64b65 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -484,7 +484,8 @@ fail: * We shall not leave the freed blocks on the vnode * buffer object lists. */ - bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, GB_NOCREAT); + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, + GB_NOCREAT | GB_UNMAPPED); if (bp != NULL) { bp->b_flags |= (B_INVAL | B_RELBUF); bp->b_flags &= ~B_ASYNC; @@ -1061,7 +1062,8 @@ fail: * We shall not leave the freed blocks on the vnode * buffer object lists. */ - bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, GB_NOCREAT); + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, + GB_NOCREAT | GB_UNMAPPED); if (bp != NULL) { bp->b_flags |= (B_INVAL | B_RELBUF); bp->b_flags &= ~B_ASYNC; From 65d31997461adff86f191e2842413b0b07181432 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Tue, 16 Aug 2016 17:07:48 +0000 Subject: [PATCH 65/67] Add two new macros, SLIST_CONCAT and LIST_CONCAT. Note in both the queue.h header file and in the queue.3 manual page that they are O(n) so should be used only in low-usage paths with short lists (otherwise an STAILQ or TAILQ should be used). Reviewed by: kib --- share/man/man3/queue.3 | 42 +++++++++++++++++++++++++++++++++++++++++- sys/sys/queue.h | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/share/man/man3/queue.3 b/share/man/man3/queue.3 index 87cfc8bd6ea9..1023c65a5640 100644 --- a/share/man/man3/queue.3 +++ b/share/man/man3/queue.3 @@ -28,12 +28,13 @@ .\" @(#)queue.3 8.2 (Berkeley) 1/24/94 .\" $FreeBSD$ .\" -.Dd June 24, 2015 +.Dd August 15, 2016 .Dt QUEUE 3 .Os .Sh NAME .Nm SLIST_CLASS_ENTRY , .Nm SLIST_CLASS_HEAD , +.Nm SLIST_CONCAT , .Nm SLIST_EMPTY , .Nm SLIST_ENTRY , .Nm SLIST_FIRST , @@ -75,6 +76,7 @@ .Nm STAILQ_SWAP , .Nm LIST_CLASS_ENTRY , .Nm LIST_CLASS_HEAD , +.Nm LIST_CONCAT , .Nm LIST_EMPTY , .Nm LIST_ENTRY , .Nm LIST_FIRST , @@ -125,6 +127,7 @@ lists and tail queues .\" .Fn SLIST_CLASS_ENTRY "CLASSTYPE" .Fn SLIST_CLASS_HEAD "HEADNAME" "CLASSTYPE" +.Fn SLIST_CONCAT "SLIST_HEAD *head1" "SLIST_HEAD *head2" "TYPE" "SLIST_ENTRY NAME" .Fn SLIST_EMPTY "SLIST_HEAD *head" .Fn SLIST_ENTRY "TYPE" .Fn SLIST_FIRST "SLIST_HEAD *head" @@ -168,6 +171,7 @@ lists and tail queues .\" .Fn LIST_CLASS_ENTRY "CLASSTYPE" .Fn LIST_CLASS_HEAD "HEADNAME" "CLASSTYPE" +.Fn LIST_CONCAT "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME" .Fn LIST_EMPTY "LIST_HEAD *head" .Fn LIST_ENTRY "TYPE" .Fn LIST_FIRST "LIST_HEAD *head" @@ -249,6 +253,8 @@ Singly-linked lists add the following functionality: .Bl -enum -compact -offset indent .It O(n) removal of any entry in the list. +.It +O(n) concatenation of two lists. .El .Pp Singly-linked tail queues add the following functionality: @@ -296,6 +302,8 @@ Linked lists are the simplest of the doubly linked data structures. They add the following functionality over the above: .Bl -enum -compact -offset indent .It +O(n) concatenation of two lists. +.It They may be traversed backwards. .El However: @@ -401,6 +409,19 @@ evaluates to an initializer for the list .Fa head . .Pp The macro +.Nm SLIST_CONCAT +concatenates the list headed by +.Fa head2 +onto the end of the one headed by +.Fa head1 +removing all entries from the former. +Use of this macro should be avoided as it traverses the entirety of the +.Fa head1 +list. +A singly-linked tail queue should be used if this macro is needed in +high-usage code paths or to operate on long lists. +.Pp +The macro .Nm SLIST_EMPTY evaluates to true if there are no elements in the list. .Pp @@ -508,6 +529,9 @@ The macro removes the element .Fa elm from the list. +Use of this macro should be avoided as it traverses the entire list. +A doubly-linked list should be used if this macro is needed in +high-usage code paths or to operate on long lists. .Pp The macro .Nm SLIST_SWAP @@ -724,6 +748,9 @@ The macro removes the element .Fa elm from the tail queue. +Use of this macro should be avoided as it traverses the entire list. +A doubly-linked tail queue should be used if this macro is needed in +high-usage code paths or to operate on long tail queues. .Pp The macro .Nm STAILQ_SWAP @@ -823,6 +850,19 @@ evaluates to an initializer for the list .Fa head . .Pp The macro +.Nm LIST_CONCAT +concatenates the list headed by +.Fa head2 +onto the end of the one headed by +.Fa head1 +removing all entries from the former. +Use of this macro should be avoided as it traverses the entirety of the +.Fa head1 +list. +A tail queue should be used if this macro is needed in +high-usage code paths or to operate on long lists. +.Pp +The macro .Nm LIST_EMPTY evaluates to true if there are no elements in the list. .Pp diff --git a/sys/sys/queue.h b/sys/sys/queue.h index 1be9e9cc737d..f26c492af1c7 100644 --- a/sys/sys/queue.h +++ b/sys/sys/queue.h @@ -76,6 +76,10 @@ * * For details on the use of these macros, see the queue(3) manual page. * + * Below is a summary of implemented functions where: + * + means the macro is available + * - means the macro is not available + * s means the macro is available but is slow (runs in O(n) time) * * SLIST LIST STAILQ TAILQ * _HEAD + + + + @@ -101,10 +105,10 @@ * _INSERT_BEFORE - + - + * _INSERT_AFTER + + + + * _INSERT_TAIL - - + + - * _CONCAT - - + + + * _CONCAT s s + + * _REMOVE_AFTER + - + - * _REMOVE_HEAD + - + - - * _REMOVE + + + + + * _REMOVE s + s + * _SWAP + + + + * */ @@ -183,6 +187,19 @@ struct { \ /* * Singly-linked List functions. */ +#define SLIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ + SLIST_INIT(head2); \ + } else if (SLIST_FIRST(head2) != NULL) { \ + while (SLIST_NEXT(curelm, field) != NULL) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ + SLIST_INIT(head2); \ + } \ +} while (0) + #define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_FIRST(head) ((head)->slh_first) @@ -447,6 +464,23 @@ struct { \ #define QMD_LIST_CHECK_PREV(elm, field) #endif /* (_KERNEL && INVARIANTS) */ +#define LIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ + LIST_FIRST(head2)->field.le_prev = \ + &LIST_FIRST((head1)); \ + LIST_INIT(head2); \ + } \ + } else if (LIST_FIRST(head2) != NULL) { \ + while (LIST_NEXT(curelm, field) != NULL) \ + curelm = LIST_NEXT(curelm, field); \ + LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ + LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ + LIST_INIT(head2); \ + } \ +} while (0) + #define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_FIRST(head) ((head)->lh_first) From 2da4bcb82b5d74a106381cf8a0a98df33c243e71 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 16 Aug 2016 17:18:38 +0000 Subject: [PATCH 66/67] On unwind after failed block allocation in ffs_balloc_ufs{1,2}, assert that recorded allocated blocks numbers match the physical block numbers of dandling buffers which are released. When finally freeing the blocks during unwind, assert that dandling buffers where not re-allocated. They shouldn't, because the vnode lock is owned exclusive. Reviewed by: mckusick Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/ufs/ffs/ffs_balloc.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 79df83d64b65..73fa051b51eb 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -487,6 +487,11 @@ fail: bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, GB_NOCREAT | GB_UNMAPPED); if (bp != NULL) { + KASSERT(bp->b_blkno == fsbtodb(fs, *blkp), + ("mismatch1 l %jd %jd b %ju %ju", + (intmax_t)bp->b_lblkno, (uintmax_t)*lbns_remfree, + (uintmax_t)bp->b_blkno, + (uintmax_t)fsbtodb(fs, *blkp))); bp->b_flags |= (B_INVAL | B_RELBUF); bp->b_flags &= ~B_ASYNC; brelse(bp); @@ -531,6 +536,18 @@ fail: * cleared, free the blocks. */ for (blkp = allociblk; blkp < allocblk; blkp++) { +#ifdef INVARIANTS + if (blkp == allociblk) + lbns_remfree = lbns; + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, + GB_NOCREAT | GB_UNMAPPED); + if (bp != NULL) { + panic("zombie1 %jd %ju %ju", + (intmax_t)bp->b_lblkno, (uintmax_t)bp->b_blkno, + (uintmax_t)fsbtodb(fs, *blkp)); + } + lbns_remfree++; +#endif ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number, vp->v_type, NULL); } @@ -1065,6 +1082,11 @@ fail: bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, GB_NOCREAT | GB_UNMAPPED); if (bp != NULL) { + KASSERT(bp->b_blkno == fsbtodb(fs, *blkp), + ("mismatch2 l %jd %jd b %ju %ju", + (intmax_t)bp->b_lblkno, (uintmax_t)*lbns_remfree, + (uintmax_t)bp->b_blkno, + (uintmax_t)fsbtodb(fs, *blkp))); bp->b_flags |= (B_INVAL | B_RELBUF); bp->b_flags &= ~B_ASYNC; brelse(bp); @@ -1109,6 +1131,18 @@ fail: * cleared, free the blocks. */ for (blkp = allociblk; blkp < allocblk; blkp++) { +#ifdef INVARIANTS + if (blkp == allociblk) + lbns_remfree = lbns; + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, + GB_NOCREAT | GB_UNMAPPED); + if (bp != NULL) { + panic("zombie2 %jd %ju %ju", + (intmax_t)bp->b_lblkno, (uintmax_t)bp->b_blkno, + (uintmax_t)fsbtodb(fs, *blkp)); + } + lbns_remfree++; +#endif ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number, vp->v_type, NULL); } From 948137db101e7b0c7276b74b5445d646626d3e4c Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 16 Aug 2016 17:30:58 +0000 Subject: [PATCH 67/67] In UFS_BALLOC(), invalidate pages of indirect buffers on failed block allocation unwinding. Dandling buffers are released on UFS_BALLOC() failure to ensure that later attempt to allocate blocks in close range do not find the blocks with invalid content, since possible partial block allocations are unwound. As such, it is not enough to just release the buffers, the pages must also invalidated and removed from the vnode vm_object queue. Otherwise the pages might be found later and used to reconstruct indirect buffers when doing allocations at offset close to the failure point, and their stale content compromise the filesystem integrity. Note that just marking the buffer as B_INVAL is not enough, B_NOCACHE is required. To be sure, clear the B_CACHE flag as well. This complements the r174973, which started releasing buffers. Reported and tested by: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/ufs/ffs/ffs_balloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 73fa051b51eb..04e0ae93b232 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -492,8 +492,8 @@ fail: (intmax_t)bp->b_lblkno, (uintmax_t)*lbns_remfree, (uintmax_t)bp->b_blkno, (uintmax_t)fsbtodb(fs, *blkp))); - bp->b_flags |= (B_INVAL | B_RELBUF); - bp->b_flags &= ~B_ASYNC; + bp->b_flags |= B_INVAL | B_RELBUF | B_NOCACHE; + bp->b_flags &= ~(B_ASYNC | B_CACHE); brelse(bp); } deallocated += fs->fs_bsize; @@ -1087,8 +1087,8 @@ fail: (intmax_t)bp->b_lblkno, (uintmax_t)*lbns_remfree, (uintmax_t)bp->b_blkno, (uintmax_t)fsbtodb(fs, *blkp))); - bp->b_flags |= (B_INVAL | B_RELBUF); - bp->b_flags &= ~B_ASYNC; + bp->b_flags |= B_INVAL | B_RELBUF | B_NOCACHE; + bp->b_flags &= ~(B_ASYNC | B_CACHE); brelse(bp); } deallocated += fs->fs_bsize;