Author: asomers
Date: Fri Mar  7 23:30:48 2014
New Revision: 262914
URL: http://svnweb.freebsd.org/changeset/base/262914

Log:
  sbin/devd/devd.8
  sbin/devd/devd.cc
        Add a -q flag to devd that will suppress syslog logging at
        LOG_NOTICE or below.
  
  Requested by: ian@ and imp@
  MFC after:    3 weeks
  Sponsored by: Spectra Logic Corporation

Modified:
  head/sbin/devd/devd.8
  head/sbin/devd/devd.cc
  head/sys/kern/uipc_usrreq.c
  head/sys/sys/sockbuf.h
  head/sys/sys/unpcb.h

Modified: head/sbin/devd/devd.8
==============================================================================
--- head/sbin/devd/devd.8       Fri Mar  7 23:26:14 2014        (r262913)
+++ head/sbin/devd/devd.8       Fri Mar  7 23:30:48 2014        (r262914)
@@ -33,7 +33,7 @@
 .Nd "device state change daemon"
 .Sh SYNOPSIS
 .Nm
-.Op Fl dn
+.Op Fl dnq
 .Op Fl f Ar file
 .Op Fl l Ar num
 .Sh DESCRIPTION
@@ -63,6 +63,8 @@ The default connection limit is 10.
 .It Fl n
 Do not process all pending events before becoming a daemon.
 Instead, call daemon right away.
+.It Fl q
+Quiet mode.  Only log messages at priority LOG_WARNING or above.
 .El
 .Sh IMPLEMENTATION NOTES
 The

Modified: head/sbin/devd/devd.cc
==============================================================================
--- head/sbin/devd/devd.cc      Fri Mar  7 23:26:14 2014        (r262913)
+++ head/sbin/devd/devd.cc      Fri Mar  7 23:30:48 2014        (r262914)
@@ -129,8 +129,9 @@ static const char detach = '-';
 
 static struct pidfh *pfh;
 
-int dflag;
-int nflag;
+static int no_daemon = 0;
+static int daemonize_quick = 0;
+static int quiet_mode = 0;
 static unsigned total_events = 0;
 static volatile sig_atomic_t got_siginfo = 0;
 static volatile sig_atomic_t romeo_must_die = 0;
@@ -291,7 +292,7 @@ match::do_match(config &c)
         * can consume excessive amounts of systime inside of connect().  Only
         * log when we're in -d mode.
         */
-       if (dflag) {
+       if (no_daemon) {
                devdlog(LOG_DEBUG, "Testing %s=%s against %s, invert=%d\n",
                    _var.c_str(), value.c_str(), _re.c_str(), _inv);
        }
@@ -401,7 +402,7 @@ var_list::set_variable(const string &var
         * can consume excessive amounts of systime inside of connect().  Only
         * log when we're in -d mode.
         */
-       if (dflag)
+       if (no_daemon)
                devdlog(LOG_DEBUG, "setting %s=%s\n", var.c_str(), val.c_str());
        _vars[var] = val;
 }
@@ -945,7 +946,7 @@ event_loop(void)
        accepting = 1;
        max_fd = max(fd, server_fd) + 1;
        while (!romeo_must_die) {
-               if (!once && !dflag && !nflag) {
+               if (!once && !no_daemon && !daemonize_quick) {
                        // Check to see if we have any events pending.
                        tv.tv_sec = 0;
                        tv.tv_usec = 0;
@@ -1139,9 +1140,9 @@ devdlog(int priority, const char* fmt, .
        va_list argp;
 
        va_start(argp, fmt);
-       if (dflag)
+       if (no_daemon)
                vfprintf(stderr, fmt, argp);
-       else
+       else if ((! quiet_mode) || (priority <= LOG_WARNING))
                vsyslog(priority, fmt, argp);
        va_end(argp);
 }
@@ -1149,7 +1150,7 @@ devdlog(int priority, const char* fmt, .
 static void
 usage()
 {
-       fprintf(stderr, "usage: %s [-dn] [-l connlimit] [-f file]\n",
+       fprintf(stderr, "usage: %s [-dnq] [-l connlimit] [-f file]\n",
            getprogname());
        exit(1);
 }
@@ -1179,10 +1180,10 @@ main(int argc, char **argv)
        int ch;
 
        check_devd_enabled();
-       while ((ch = getopt(argc, argv, "df:l:n")) != -1) {
+       while ((ch = getopt(argc, argv, "df:l:nq")) != -1) {
                switch (ch) {
                case 'd':
-                       dflag++;
+                       no_daemon = 1;
                        break;
                case 'f':
                        configfile = optarg;
@@ -1191,7 +1192,10 @@ main(int argc, char **argv)
                        max_clients = MAX(1, strtoul(optarg, NULL, 0));
                        break;
                case 'n':
-                       nflag++;
+                       daemonize_quick = 1;
+                       break;
+               case 'q':
+                       quiet_mode = 1;
                        break;
                default:
                        usage();
@@ -1199,7 +1203,7 @@ main(int argc, char **argv)
        }
 
        cfg.parse();
-       if (!dflag && nflag) {
+       if (!no_daemon && daemonize_quick) {
                cfg.open_pidfile();
                daemon(0, 0);
                cfg.write_pidfile();

Modified: head/sys/kern/uipc_usrreq.c
==============================================================================
--- head/sys/kern/uipc_usrreq.c Fri Mar  7 23:26:14 2014        (r262913)
+++ head/sys/kern/uipc_usrreq.c Fri Mar  7 23:30:48 2014        (r262914)
@@ -51,7 +51,6 @@
  *
  * TODO:
  *     RDM
- *     distinguish datagram size limits from flow control limits in SEQPACKET
  *     rethink name space problems
  *     need a proper out-of-band
  */
@@ -789,7 +788,6 @@ uipc_rcvd(struct socket *so, int flags)
        struct unpcb *unp, *unp2;
        struct socket *so2;
        u_int mbcnt, sbcc;
-       u_long newhiwat;
 
        unp = sotounpcb(so);
        KASSERT(unp != NULL, ("uipc_rcvd: unp == NULL"));
@@ -811,6 +809,15 @@ uipc_rcvd(struct socket *so, int flags)
        mbcnt = so->so_rcv.sb_mbcnt;
        sbcc = so->so_rcv.sb_cc;
        SOCKBUF_UNLOCK(&so->so_rcv);
+       /*
+        * There is a benign race condition at this point.  If we're planning to
+        * clear SB_STOP, but uipc_send is called on the connected socket at
+        * this instant, it might add data to the sockbuf and set SB_STOP.  Then
+        * we would erroneously clear SB_STOP below, even though the sockbuf is
+        * full.  The race is benign because the only ill effect is to allow the
+        * sockbuf to exceed its size limit, and the size limits are not
+        * strictly guaranteed anyway.
+        */
        UNP_PCB_LOCK(unp);
        unp2 = unp->unp_conn;
        if (unp2 == NULL) {
@@ -819,13 +826,9 @@ uipc_rcvd(struct socket *so, int flags)
        }
        so2 = unp2->unp_socket;
        SOCKBUF_LOCK(&so2->so_snd);
-       so2->so_snd.sb_mbmax += unp->unp_mbcnt - mbcnt;
-       newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc - sbcc;
-       (void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat,
-           newhiwat, RLIM_INFINITY);
+       if (sbcc < so2->so_snd.sb_hiwat && mbcnt < so2->so_snd.sb_mbmax)
+               so2->so_snd.sb_flags &= ~SB_STOP;
        sowwakeup_locked(so2);
-       unp->unp_mbcnt = mbcnt;
-       unp->unp_cc = sbcc;
        UNP_PCB_UNLOCK(unp);
        return (0);
 }
@@ -836,8 +839,7 @@ uipc_send(struct socket *so, int flags, 
 {
        struct unpcb *unp, *unp2;
        struct socket *so2;
-       u_int mbcnt_delta, sbcc;
-       u_int newhiwat;
+       u_int mbcnt, sbcc;
        int error = 0;
 
        unp = sotounpcb(so);
@@ -991,27 +993,21 @@ uipc_send(struct socket *so, int flags, 
                        }
                }
 
-               /*
-                * XXXRW: While fine for SOCK_STREAM, this conflates maximum
-                * datagram size and back-pressure for SOCK_SEQPACKET, which
-                * can lead to undesired return of EMSGSIZE on send instead
-                * of more desirable blocking.
-                */
-               mbcnt_delta = so2->so_rcv.sb_mbcnt - unp2->unp_mbcnt;
-               unp2->unp_mbcnt = so2->so_rcv.sb_mbcnt;
+               mbcnt = so2->so_rcv.sb_mbcnt;
                sbcc = so2->so_rcv.sb_cc;
                sorwakeup_locked(so2);
 
+               /* 
+                * The PCB lock on unp2 protects the SB_STOP flag.  Without it,
+                * it would be possible for uipc_rcvd to be called at this
+                * point, drain the receiving sockbuf, clear SB_STOP, and then
+                * we would set SB_STOP below.  That could lead to an empty
+                * sockbuf having SB_STOP set
+                */
                SOCKBUF_LOCK(&so->so_snd);
-               if ((int)so->so_snd.sb_hiwat >= (int)(sbcc - unp2->unp_cc))
-                       newhiwat = so->so_snd.sb_hiwat - (sbcc - unp2->unp_cc);
-               else
-                       newhiwat = 0;
-               (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat,
-                   newhiwat, RLIM_INFINITY);
-               so->so_snd.sb_mbmax -= mbcnt_delta;
+               if (sbcc >= so->so_snd.sb_hiwat || mbcnt >= so->so_snd.sb_mbmax)
+                       so->so_snd.sb_flags |= SB_STOP;
                SOCKBUF_UNLOCK(&so->so_snd);
-               unp2->unp_cc = sbcc;
                UNP_PCB_UNLOCK(unp2);
                m = NULL;
                break;
@@ -1049,27 +1045,18 @@ release:
 static int
 uipc_sense(struct socket *so, struct stat *sb)
 {
-       struct unpcb *unp, *unp2;
-       struct socket *so2;
+       struct unpcb *unp;
 
        unp = sotounpcb(so);
        KASSERT(unp != NULL, ("uipc_sense: unp == NULL"));
 
        sb->st_blksize = so->so_snd.sb_hiwat;
-       UNP_LINK_RLOCK();
        UNP_PCB_LOCK(unp);
-       unp2 = unp->unp_conn;
-       if ((so->so_type == SOCK_STREAM || so->so_type == SOCK_SEQPACKET) &&
-           unp2 != NULL) {
-               so2 = unp2->unp_socket;
-               sb->st_blksize += so2->so_rcv.sb_cc;
-       }
        sb->st_dev = NODEV;
        if (unp->unp_ino == 0)
                unp->unp_ino = (++unp_ino == 0) ? ++unp_ino : unp_ino;
        sb->st_ino = unp->unp_ino;
        UNP_PCB_UNLOCK(unp);
-       UNP_LINK_RUNLOCK();
        return (0);
 }
 
@@ -2497,8 +2484,7 @@ DB_SHOW_COMMAND(unpcb, db_show_unpcb)
        /* XXXRW: Would be nice to print the full address, if any. */
        db_printf("unp_addr: %p\n", unp->unp_addr);
 
-       db_printf("unp_cc: %d   unp_mbcnt: %d   unp_gencnt: %llu\n",
-           unp->unp_cc, unp->unp_mbcnt,
+       db_printf("unp_gencnt: %llu\n",
            (unsigned long long)unp->unp_gencnt);
 
        db_printf("unp_flags: %x (", unp->unp_flags);

Modified: head/sys/sys/sockbuf.h
==============================================================================
--- head/sys/sys/sockbuf.h      Fri Mar  7 23:26:14 2014        (r262913)
+++ head/sys/sys/sockbuf.h      Fri Mar  7 23:30:48 2014        (r262914)
@@ -52,6 +52,7 @@
 #define        SB_NOCOALESCE   0x200           /* don't coalesce new data into 
existing mbufs */
 #define        SB_IN_TOE       0x400           /* socket buffer is in the 
middle of an operation */
 #define        SB_AUTOSIZE     0x800           /* automatically size socket 
buffer */
+#define        SB_STOP         0x1000          /* backpressure indicator */
 
 #define        SBS_CANTSENDMORE        0x0010  /* can't send more data to peer 
*/
 #define        SBS_CANTRCVMORE         0x0020  /* can't receive more data from 
peer */
@@ -168,9 +169,19 @@ void       sbunlock(struct sockbuf *sb);
  * still be negative (cc > hiwat or mbcnt > mbmax).  Should detect
  * overflow and return 0.  Should use "lmin" but it doesn't exist now.
  */
-#define        sbspace(sb) \
-    ((long) imin((int)((sb)->sb_hiwat - (sb)->sb_cc), \
-        (int)((sb)->sb_mbmax - (sb)->sb_mbcnt)))
+static __inline
+long
+sbspace(struct sockbuf *sb)
+{
+       long bleft;
+       long mleft;
+
+       if (sb->sb_flags & SB_STOP)
+               return(0);
+       bleft = sb->sb_hiwat - sb->sb_cc;
+       mleft = sb->sb_mbmax - sb->sb_mbcnt;
+       return((bleft < mleft) ? bleft : mleft);
+}
 
 /* adjust counters in sb reflecting allocation of m */
 #define        sballoc(sb, m) { \

Modified: head/sys/sys/unpcb.h
==============================================================================
--- head/sys/sys/unpcb.h        Fri Mar  7 23:26:14 2014        (r262913)
+++ head/sys/sys/unpcb.h        Fri Mar  7 23:30:48 2014        (r262914)
@@ -74,8 +74,8 @@ struct unpcb {
        struct  unp_head unp_refs;      /* referencing socket linked list */
        LIST_ENTRY(unpcb) unp_reflink;  /* link in unp_refs list */
        struct  sockaddr_un *unp_addr;  /* bound address of socket */
-       int     unp_cc;                 /* copy of rcv.sb_cc */
-       int     unp_mbcnt;              /* copy of rcv.sb_mbcnt */
+       int     reserved1;
+       int     reserved2;
        unp_gen_t unp_gencnt;           /* generation count of this instance */
        short   unp_flags;              /* flags */
        short   unp_gcflag;             /* Garbage collector flags. */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to