diff options
author | Josh Wilsdon <jwilsdon@joyent.com> | 2016-02-21 07:38:52 +0000 |
---|---|---|
committer | Josh Wilsdon <jwilsdon@joyent.com> | 2016-02-21 07:38:52 +0000 |
commit | 038ce5502796a7e9220ec1716eb409242250bf09 (patch) | |
tree | 1b847955e9e5d4ba569c9b1034be4bd0cba45781 | |
parent | bfa0d80e3f03620084e3bc6c18283b5c87b89839 (diff) | |
parent | 74b22239b3d05923a5c08d00fc5d82a3fa7d273b (diff) | |
download | illumos-joyent-OS-4903.tar.gz |
Merge branch 'master' into OS-4903OS-4903
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/mount_nfs.c | 38 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/procfs/lx_prvnops.c | 24 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/sysfs/lx_sysfs.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/sysfs/lx_sysvnops.c | 370 | ||||
-rw-r--r-- | usr/src/uts/common/fs/ufs/ufs_subr.c | 2 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/conn_opt.c | 20 | ||||
-rw-r--r-- | usr/src/uts/common/inet/tcp/tcp_opt_data.c | 6 | ||||
-rw-r--r-- | usr/src/uts/sun4u/cpu/common_asm.s | 39 | ||||
-rw-r--r-- | usr/src/uts/sun4v/cpu/common_asm.s | 39 |
9 files changed, 504 insertions, 38 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/common/mount_nfs.c b/usr/src/lib/brand/lx/lx_brand/common/mount_nfs.c index 5bfb2cdaa0..54ce9f6f53 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/mount_nfs.c +++ b/usr/src/lib/brand/lx/lx_brand/common/mount_nfs.c @@ -96,6 +96,7 @@ #define RET_OK 0 #define RET_RETRY 32 #define RET_ERR 33 +#define RET_PROTOUNSUPP 34 #define RET_MNTERR 1000 #define ERR_PROTO_NONE 0 #define ERR_PROTO_INVALID 901 @@ -110,8 +111,10 @@ typedef struct err_ret { } err_ret_t; #define SET_ERR_RET(errst, etype, eval) \ + { \ (errst)->error_type = etype; \ - (errst)->error_value = eval; + (errst)->error_value = eval; \ + } /* * Built-in netconfig table. @@ -413,6 +416,8 @@ mount_nfs(struct mnttab *mntp, int mntflags, err_ret_t *retry_error, /* All attempts failed */ if (r == RET_MNTERR) { r = -EREMOTE; + } else if (r == RET_PROTOUNSUPP) { + r = -EPROTONOSUPPORT; } else if (r != RET_RETRY) { r = -EAGAIN; } @@ -1406,14 +1411,16 @@ get_addr(char *hostname, rpcprog_t prog, rpcvers_t vers, /* nb is NULL - deal with errors */ if (error) { - if (error->error_type == ERR_NOHOST) + if (error->error_type == ERR_NOHOST) { SET_ERR_RET(&errsave_nohost, error->error_type, error->error_value); - if (error->error_type == ERR_RPCERROR) + } + if (error->error_type == ERR_RPCERROR) { SET_ERR_RET(&errsave_rpcerr, error->error_type, error->error_value); + } } /* continue with same protocol selection */ @@ -1447,15 +1454,17 @@ retry: /* nb is NULL - deal with errors */ if (error) { - if (error->error_type == ERR_NOHOST) + if (error->error_type == ERR_NOHOST) { SET_ERR_RET(&errsave_nohost, error->error_type, error->error_value); + } - if (error->error_type == ERR_RPCERROR) + if (error->error_type == ERR_RPCERROR) { SET_ERR_RET(&errsave_rpcerr, error->error_type, error->error_value); + } } /* @@ -1487,16 +1496,18 @@ retry: done: if (nb == NULL) { /* - * Check the saved errors. The RPC error has * + * Check the saved errors. The RPC error has * precedence over the no host error. */ - if (errsave_nohost.error_type != ERR_PROTO_NONE) + if (errsave_nohost.error_type != ERR_PROTO_NONE) { SET_ERR_RET(error, errsave_nohost.error_type, errsave_nohost.error_value); + } - if (errsave_rpcerr.error_type != ERR_PROTO_NONE) + if (errsave_rpcerr.error_type != ERR_PROTO_NONE) { SET_ERR_RET(error, errsave_rpcerr.error_type, errsave_rpcerr.error_value); + } } return (nb); @@ -1607,6 +1618,17 @@ get_fh(struct nfs_args *args, char *fshost, char *fspath, int *versp, } nmdp->nmd_nfsvers_to_use = savevers; + if (retval == RET_ERR && error.error_type == ERR_RPCERROR && + error.error_value == RPC_PROGVERSMISMATCH && + nmdp->nmd_nfsvers != 0) { + /* + * We had an explicit vers=N mount request which locked + * us in to that version, however the server does not + * support that version (and responded to tell us that). + */ + return (RET_PROTOUNSUPP); + } + vers_to_try--; /* If no more versions to try, let the user know. */ if (vers_to_try < vers_min) diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c index 2911a182df..b6197106ec 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c +++ b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c @@ -3709,6 +3709,7 @@ lxpr_read_diskstats(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) for (i = 1; i < nidx; i++) { kstat_t *ksp = &ksr[i]; kstat_io_t *kip; + int major, minor; if (ksp->ks_type != KSTAT_TYPE_IO || strcmp(ksp->ks_class, "disk") != 0) @@ -3754,13 +3755,32 @@ lxpr_read_diskstats(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) * This is also a lie of sorts, but it should be more * immediately clear to the user that reads and writes are * each being double-counted as the other. + * + * Since certain consumers interpret the major/minor numbers to + * infer device names, some translation is required to avoid + * output which results in totally unexpected results. */ + minor = ksp->ks_instance; + if (strncmp(ksp->ks_name, "sd", 2) == 0) { + /* map sd[0-9]+ to sd[a-z]+ */ + major = 8; + minor = minor * 16; + } else if (strncmp(ksp->ks_name, "ram", 3) == 0) { + /* map ramdisk[0-9]+ to ram[0-9]+ */ + major = 1; + } else if (strcmp(ksp->ks_module, "zfs") == 0) { + /* map zfs pools to md[0-9]+ (software RAID) */ + major = 9; + } else { + /* pretend everything else is ide */ + major = 2; + minor = minor * 64; + } lxpr_uiobuf_printf(uiobuf, "%4d %7d %s " "%llu %llu %llu %llu " "%llu %llu %llu %llu " "%llu %llu %llu\n", - mod_name_to_major(ksp->ks_module), - ksp->ks_instance, ksp->ks_name, + major, minor, ksp->ks_name, (uint64_t)kip->reads, 0LL, kip->nread / (uint64_t)LXPR_SECTOR_SIZE, (kip->rtime + kip->wtime) / (uint64_t)(NANOSEC / MILLISEC), diff --git a/usr/src/uts/common/brand/lx/sysfs/lx_sysfs.h b/usr/src/uts/common/brand/lx/sysfs/lx_sysfs.h index b62609dfb1..e46dc0496d 100644 --- a/usr/src/uts/common/brand/lx/sysfs/lx_sysfs.h +++ b/usr/src/uts/common/brand/lx/sysfs/lx_sysfs.h @@ -10,7 +10,7 @@ */ /* - * Copyright 2015 Joyent, Inc. + * Copyright 2016 Joyent, Inc. */ #ifndef _LXSYSFS_H @@ -98,6 +98,8 @@ typedef enum lxsys_nodetype { LXSYS_STATIC, /* Statically defined entries */ LXSYS_CLASS_NET, /* /sys/class/net/<iface> */ LXSYS_DEVICES_NET, /* /sys/devices/virtual/net/<iface> */ + LXSYS_BLOCK, /* /sys/block/<dev> */ + LXSYS_DEVICES_BDI, /* /sys/devices/virtual/bdi/<dev> */ LXSYS_MAXTYPE, /* type limit */ } lxsys_nodetype_t; diff --git a/usr/src/uts/common/brand/lx/sysfs/lx_sysvnops.c b/usr/src/uts/common/brand/lx/sysfs/lx_sysvnops.c index 1202e943b7..70cf0635c7 100644 --- a/usr/src/uts/common/brand/lx/sysfs/lx_sysvnops.c +++ b/usr/src/uts/common/brand/lx/sysfs/lx_sysvnops.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2015 Joyent, Inc. + * Copyright 2016 Joyent, Inc. */ /* @@ -42,6 +42,7 @@ #include <sys/netstack.h> #include <sys/ethernet.h> #include <inet/ip_arp.h> +#include <sys/kstat.h> #include "lx_sysfs.h" @@ -71,14 +72,19 @@ static void lxsys_inactive(vnode_t *, cred_t *, caller_context_t *); static vnode_t *lxsys_lookup_static(lxsys_node_t *, char *); static vnode_t *lxsys_lookup_class_netdir(lxsys_node_t *, char *); static vnode_t *lxsys_lookup_devices_virtual_netdir(lxsys_node_t *, char *); +static vnode_t *lxsys_lookup_blockdir(lxsys_node_t *, char *); +static vnode_t *lxsys_lookup_devices_virtual_bdidir(lxsys_node_t *, char *); static int lxsys_read_devices_virtual_net(lxsys_node_t *, lxsys_uiobuf_t *); static int lxsys_readdir_static(lxsys_node_t *, uio_t *, int *); static int lxsys_readdir_class_netdir(lxsys_node_t *, uio_t *, int *); static int lxsys_readdir_devices_virtual_netdir(lxsys_node_t *, uio_t *, int *); +static int lxsys_readdir_blockdir(lxsys_node_t *, uio_t *, int *); +static int lxsys_readdir_devices_virtual_bdidir(lxsys_node_t *, uio_t *, int *); -static int lxsys_readlink_class_net(lxsys_node_t *lnp, char *buf, size_t len); +static int lxsys_readlink_class_net(lxsys_node_t *, char *, size_t); +static int lxsys_readlink_block(lxsys_node_t *, char *, size_t); /* * The lx /sys vnode operations vector @@ -111,17 +117,21 @@ const fs_operation_def_t lxsys_vnodeops_template[] = { * 1 - SYS_STATIC * 2 - SYS_CLASS_NET * 3 - SYS_DEVICES_NET + * 4 - SYS_BLOCK + * 5 - SYS_DEVICES_BDI * * Static entries will have assigned INSTANCE identifiers: - * - 0: /sys - * - 1: /sys/class - * - 2: /sys/devices - * - 3: /sys/fs - * - 4: /sys/class/net - * - 5: /sys/devices/virtual - * - 7: /sys/devices/system - * - 8: /sys/fs/cgroup - * - 9: /sys/devices/virtual/net + * - 0x00: /sys + * - 0x01: /sys/class + * - 0x02: /sys/devices + * - 0x03: /sys/fs + * - 0x04: /sys/class/net + * - 0x05: /sys/devices/virtual + * - 0x06: /sys/devices/system + * - 0x07: /sys/fs/cgroup + * - 0x08: /sys/devices/virtual/net + * - 0x09: /sys/block + * - 0x0a: /sys/devices/virtual/bdi * * Dynamic /sys/class/net/<interface> symlinks will use an INSTANCE derived * from the corresonding ifindex. @@ -129,21 +139,28 @@ const fs_operation_def_t lxsys_vnodeops_template[] = { * Dynamic /sys/devices/virtual/net/<interface>/<entries> directories will use * an INSTANCE derived from the ifindex and statically assigned ENDPOINT IDs * for the contained entries. + * + * Dynamic /sys/block/<dev> symlinks and /sys/devices/virtual/bdi/<dev> + * directories will use an INSTANCE derived from the device major and instance + * from records listed in kstat. */ -#define LXSYS_INST_CLASSDIR 1 -#define LXSYS_INST_DEVICESDIR 2 -#define LXSYS_INST_FSDIR 3 -#define LXSYS_INST_CLASS_NETDIR 4 -#define LXSYS_INST_DEVICES_VIRTUALDIR 5 -#define LXSYS_INST_DEVICES_SYSTEMDIR 6 -#define LXSYS_INST_FS_CGROUPDIR 7 -#define LXSYS_INST_DEVICES_VIRTUAL_NETDIR 8 +#define LXSYS_INST_CLASSDIR 0x1 +#define LXSYS_INST_DEVICESDIR 0x2 +#define LXSYS_INST_FSDIR 0x3 +#define LXSYS_INST_CLASS_NETDIR 0x4 +#define LXSYS_INST_DEVICES_VIRTUALDIR 0x5 +#define LXSYS_INST_DEVICES_SYSTEMDIR 0x6 +#define LXSYS_INST_FS_CGROUPDIR 0x7 +#define LXSYS_INST_DEVICES_VIRTUAL_NETDIR 0x8 +#define LXSYS_INST_BLOCKDIR 0x9 +#define LXSYS_INST_DEVICES_VIRTUAL_BDIDIR 0xa /* * file contents of an lx /sys directory. */ static lxsys_dirent_t dirlist_root[] = { + { LXSYS_INST_BLOCKDIR, "block" }, { LXSYS_INST_CLASSDIR, "class" }, { LXSYS_INST_DEVICESDIR, "devices" }, { LXSYS_INST_FSDIR, "fs" } @@ -160,6 +177,7 @@ static lxsys_dirent_t dirlist_devices[] = { { LXSYS_INST_DEVICES_VIRTUALDIR, "virtual" } }; static lxsys_dirent_t dirlist_devices_virtual[] = { + { LXSYS_INST_DEVICES_VIRTUAL_BDIDIR, "bdi" }, { LXSYS_INST_DEVICES_VIRTUAL_NETDIR, "net" } }; @@ -204,6 +222,8 @@ static vnode_t *(*lxsys_lookup_function[LXSYS_MAXTYPE])() = { lxsys_lookup_static, /* LXSYS_STATIC */ lxsys_lookup_class_netdir, /* LXSYS_CLASS_NET */ lxsys_lookup_devices_virtual_netdir, /* LXSYS_DEVICES_NET */ + lxsys_lookup_blockdir, /* LXSYS_BLOCK */ + lxsys_lookup_devices_virtual_bdidir, /* LXSYS_DEVICES_BDI */ }; /* @@ -214,6 +234,8 @@ static int (*lxsys_readdir_function[LXSYS_MAXTYPE])() = { lxsys_readdir_static, /* LXSYS_STATIC */ lxsys_readdir_class_netdir, /* LXSYS_CLASS_NET */ lxsys_readdir_devices_virtual_netdir, /* LXSYS_DEVICES_NET */ + lxsys_readdir_blockdir, /* LXSYS_BLOCK */ + lxsys_readdir_devices_virtual_bdidir, /* LXSYS_DEVICES_BDI */ }; /* @@ -224,6 +246,8 @@ static int (*lxsys_read_function[LXSYS_MAXTYPE])() = { NULL, /* LXSYS_STATIC */ NULL, /* LXSYS_CLASS_NET */ lxsys_read_devices_virtual_net, /* LXSYS_DEVICES_NET */ + NULL, /* LXSYS_BLOCK */ + NULL, /* LXSYS_DEVICES_BDI */ }; /* @@ -234,9 +258,106 @@ static int (*lxsys_readlink_function[LXSYS_MAXTYPE])() = { NULL, /* LXSYS_STATIC */ lxsys_readlink_class_net, /* LXSYS_CLASS_NET */ NULL, /* LXSYS_DEVICES_NET */ + lxsys_readlink_block, /* LXSYS_BLOCK */ + NULL, /* LXSYS_DEVICES_BDI */ }; +/* + * Utility functions + */ +static void * +lxsys_kstat_read(kstat_t *kn, boolean_t byname, size_t *size, int *num) +{ + kstat_t *kp; + int i, nrec = 0; + size_t bufsize; + void *buf = NULL; + + if (byname == B_TRUE) { + kp = kstat_hold_byname(kn->ks_module, kn->ks_instance, + kn->ks_name, getzoneid()); + } else { + kp = kstat_hold_bykid(kn->ks_kid, getzoneid()); + } + if (kp == NULL) { + return (NULL); + } + if (kp->ks_flags & KSTAT_FLAG_INVALID) { + kstat_rele(kp); + return (NULL); + } + + bufsize = kp->ks_data_size + 1; + kstat_rele(kp); + + /* + * The kstat in question is released so that kmem_alloc(KM_SLEEP) is + * performed without it held. After the alloc, the kstat is reacquired + * and its size is checked again. If the buffer is no longer large + * enough, the alloc and check are repeated up to three times. + */ + for (i = 0; i < 2; i++) { + buf = kmem_alloc(bufsize, KM_SLEEP); + + /* Check if bufsize still appropriate */ + if (byname == B_TRUE) { + kp = kstat_hold_byname(kn->ks_module, kn->ks_instance, + kn->ks_name, getzoneid()); + } else { + kp = kstat_hold_bykid(kn->ks_kid, getzoneid()); + } + if (kp == NULL || kp->ks_flags & KSTAT_FLAG_INVALID) { + if (kp != NULL) { + kstat_rele(kp); + } + kmem_free(buf, bufsize); + return (NULL); + } + KSTAT_ENTER(kp); + (void) KSTAT_UPDATE(kp, KSTAT_READ); + if (bufsize < kp->ks_data_size) { + kmem_free(buf, bufsize); + buf = NULL; + bufsize = kp->ks_data_size + 1; + KSTAT_EXIT(kp); + kstat_rele(kp); + continue; + } else { + if (KSTAT_SNAPSHOT(kp, buf, KSTAT_READ) != 0) { + kmem_free(buf, bufsize); + buf = NULL; + } + nrec = kp->ks_ndata; + KSTAT_EXIT(kp); + kstat_rele(kp); + break; + } + } + + if (buf != NULL) { + *size = bufsize; + *num = nrec; + } + return (buf); +} + +static int +lxsys_disk_instance(kstat_t *ksp) +{ + int result; + + /* + * Use a naive method to generate the 16-bit disk instance number for + * calculating the inode. This is adequate when module and disk counts + * remain low. + */ + result = (mod_name_to_major(ksp->ks_module) & 0xff) << 8; + result |= (ksp->ks_instance & 0xff); + return (result); +} + + /* * lxsys_open(): Vnode operation for VOP_OPEN() @@ -409,6 +530,37 @@ lxsys_lookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp, return ((*vpp == NULL) ? ENOENT : 0); } +static lxsys_node_t * +lxsys_lookup_disk(lxsys_node_t *ldp, char *comp, lxsys_nodetype_t type) +{ + kstat_t ks0, *ksr; + int nidx, i; + size_t sidx; + lxsys_node_t *lnp = NULL; + + ks0.ks_kid = 0; + ksr = (kstat_t *)lxsys_kstat_read(&ks0, B_FALSE, &sidx, &nidx); + if (ksr == NULL) { + return (NULL); + } + for (i = 1; i < nidx; i++) { + kstat_t *ksp = &ksr[i]; + int inst; + + if (ksp->ks_type != KSTAT_TYPE_IO || + strcmp(ksp->ks_class, "disk") != 0) { + continue; + } + if (strncmp(ksp->ks_name, comp, KSTAT_STRLEN) == 0 && + (inst = lxsys_disk_instance(ksp)) != 0) { + lnp = lxsys_getnode(ldp->lxsys_vnode, type, inst, 0); + break; + } + } + kmem_free(ksr, sidx); + return (lnp); +} + static vnode_t * lxsys_lookup_static(lxsys_node_t *ldp, char *comp) { @@ -433,12 +585,18 @@ lxsys_lookup_static(lxsys_node_t *ldp, char *comp) lxsys_node_t *lnp; switch (dirent[i].d_idnum) { + case LXSYS_INST_BLOCKDIR: + node_type = LXSYS_BLOCK; + break; case LXSYS_INST_CLASS_NETDIR: node_type = LXSYS_CLASS_NET; break; case LXSYS_INST_DEVICES_VIRTUAL_NETDIR: node_type = LXSYS_DEVICES_NET; break; + case LXSYS_INST_DEVICES_VIRTUAL_BDIDIR: + node_type = LXSYS_DEVICES_BDI; + break; default: /* Another static node */ node_instance = dirent[i].d_idnum; @@ -554,6 +712,41 @@ lxsys_lookup_devices_virtual_netdir(lxsys_node_t *ldp, char *comp) return (NULL); } +static vnode_t * +lxsys_lookup_blockdir(lxsys_node_t *ldp, char *comp) +{ + lxsys_node_t *lnp; + + if (ldp->lxsys_instance == 0) { + /* top-level dev listing */ + lnp = lxsys_lookup_disk(ldp, comp, LXSYS_BLOCK); + + if (lnp != NULL) { + lnp->lxsys_vnode->v_type = VLNK; + return (lnp->lxsys_vnode); + } + } + + return (NULL); +} + +static vnode_t * +lxsys_lookup_devices_virtual_bdidir(lxsys_node_t *ldp, char *comp) +{ + lxsys_node_t *lnp; + + if (ldp->lxsys_instance == 0) { + /* top-level dev listing */ + lnp = lxsys_lookup_disk(ldp, comp, LXSYS_DEVICES_BDI); + + if (lnp != NULL) { + return (lnp->lxsys_vnode); + } + } + + return (NULL); +} + static int lxsys_read_devices_virtual_net(lxsys_node_t *lnp, lxsys_uiobuf_t *luio) @@ -927,6 +1120,74 @@ lxsys_readdir_ifaces(lxsys_node_t *ldp, struct uio *uiop, int *eofp, return (error); } +static int +lxsys_readdir_disks(lxsys_node_t *ldp, struct uio *uiop, int *eofp, + lxsys_nodetype_t type) +{ + longlong_t bp[DIRENT64_RECLEN(LXSNSIZ) / sizeof (longlong_t)]; + dirent64_t *dirent = (dirent64_t *)bp; + ssize_t oresid, uresid; + kstat_t ks0, *ksr; + int nidx, i, skip, error; + size_t sidx; + + /* Emit "." and ".." entries */ + oresid = uiop->uio_resid; + error = lxsys_readdir_common(ldp, uiop, eofp, NULL, 0); + if (error != 0 || *eofp == 0) { + return (error); + } + + ks0.ks_kid = 0; + ksr = (kstat_t *)lxsys_kstat_read(&ks0, B_FALSE, &sidx, &nidx); + if (ksr == NULL) { + *eofp = 1; + return (0); + } + skip = (uiop->uio_offset/LXSYS_SDSIZE) - 2; + for (i = 1; i < nidx; i++) { + kstat_t *ksp = &ksr[i]; + uint_t instance; + int reclen; + + if (ksp->ks_type != KSTAT_TYPE_IO || + strcmp(ksp->ks_class, "disk") != 0) { + continue; + } + if ((instance = lxsys_disk_instance(ksp)) == 0) { + continue; + } + if (skip > 0) { + skip--; + continue; + } + + (void) strncpy(dirent->d_name, ksp->ks_name, KSTAT_STRLEN); + dirent->d_ino = lxsys_inode(type, instance, 0); + reclen = DIRENT64_RECLEN(strlen(dirent->d_name)); + + uresid = uiop->uio_resid; + if (reclen > uresid) { + if (uresid == oresid) { + /* Not enough space for one record */ + error = EINVAL; + } + break; + } + if ((error = lxsys_dirent_out(dirent, reclen, uiop)) != 0) { + break; + } + } + + /* Indicate EOF if we reached the end of the kstats. */ + if (i >= nidx) { + *eofp = 1; + } + kmem_free(ksr, sidx); + + return (error); +} + static int lxsys_readdir_static(lxsys_node_t *lnp, uio_t *uiop, int *eofp) @@ -987,6 +1248,42 @@ lxsys_readdir_devices_virtual_netdir(lxsys_node_t *lnp, uio_t *uiop, int *eofp) return (error); } +static int +lxsys_readdir_blockdir(lxsys_node_t *lnp, uio_t *uiop, int *eofp) +{ + if (lnp->lxsys_type != LXSYS_BLOCK || + lnp->lxsys_instance != 0) { + /* + * Since /sys/block contains only symlinks, readdir operations + * should not be performed anywhere except the top level + * (instance == 0). + */ + return (ENOTDIR); + } + + return (lxsys_readdir_disks(lnp, uiop, eofp, LXSYS_BLOCK)); +} + +static int +lxsys_readdir_devices_virtual_bdidir(lxsys_node_t *lnp, uio_t *uiop, int *eofp) +{ + int error; + + if (lnp->lxsys_instance == 0) { + /* top-level dev listing */ + error = lxsys_readdir_disks(lnp, uiop, eofp, + LXSYS_DEVICES_NET); + } else if (lnp->lxsys_endpoint == 0) { + /* disk-level sub-item listing (empty for now) */ + error = lxsys_readdir_subdir(lnp, uiop, eofp, NULL, 0); + } else { + /* there shouldn't be subdirs below this */ + error = ENOTDIR; + } + + return (error); +} + /* * lxsys_readlink(): Vnode operation for VOP_READLINK() */ @@ -1055,6 +1352,41 @@ lxsys_readlink_class_net(lxsys_node_t *lnp, char *buf, size_t len) return (error); } +static int +lxsys_readlink_block(lxsys_node_t *lnp, char *buf, size_t len) +{ + kstat_t *ksr; + kstat_t ks0; + int nidx, i, inst, error = EINVAL; + size_t sidx; + + if ((inst = lnp->lxsys_instance) == 0) { + return (error); + } + + ks0.ks_kid = 0; + ksr = (kstat_t *)lxsys_kstat_read(&ks0, B_FALSE, &sidx, &nidx); + if (ksr == NULL) { + return (error); + } + for (i = 1; i < nidx; i++) { + kstat_t *ksp = &ksr[i]; + + if (ksp->ks_type != KSTAT_TYPE_IO || + strcmp(ksp->ks_class, "disk") != 0) { + continue; + } + if (lxsys_disk_instance(ksp) == inst) { + (void) snprintf(buf, len, + "/sys/devices/virtual/bdi/%s", ksp->ks_name); + error = 0; + break; + } + } + kmem_free(ksr, sidx); + return (error); +} + /* * lxsys_inactive(): Vnode operation for VOP_INACTIVE() * Vnode is no longer referenced, deallocate the file diff --git a/usr/src/uts/common/fs/ufs/ufs_subr.c b/usr/src/uts/common/fs/ufs/ufs_subr.c index 0ef1f8280d..4746d9e15e 100644 --- a/usr/src/uts/common/fs/ufs/ufs_subr.c +++ b/usr/src/uts/common/fs/ufs/ufs_subr.c @@ -602,7 +602,7 @@ ufs_sync_indir(struct inode *ip) } /* Write out all the first level indirect blocks */ - for (i = 0; i <= NIADDR; i++) { + for (i = 0; i < NIADDR; i++) { if ((blkno = ip->i_ib[i]) == 0) continue; blkflush(ip->i_dev, (daddr_t)fsbtodb(fs, blkno)); diff --git a/usr/src/uts/common/inet/ip/conn_opt.c b/usr/src/uts/common/inet/ip/conn_opt.c index 218f9f7154..b4bff4d7b4 100644 --- a/usr/src/uts/common/inet/ip/conn_opt.c +++ b/usr/src/uts/common/inet/ip/conn_opt.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2015 Joyent, Inc. + * Copyright 2016 Joyent, Inc. */ /* Copyright (c) 1990 Mentat Inc. */ @@ -1190,8 +1190,24 @@ conn_opt_set_ip(conn_opt_arg_t *coa, t_scalar_t name, uint_t inlen, ip_stack_t *ipst = connp->conn_netstack->netstack_ip; int error; - if (connp->conn_family != AF_INET) + if (connp->conn_family == AF_INET6 && + connp->conn_ipversion == IPV4_VERSION) { + /* + * Allow certain IPv4 options to be set on an AF_INET6 socket + * if the connection is still IPv4. + */ + switch (name) { + case IP_TOS: + case T_IP_TOS: + case IP_TTL: + case IP_DONTFRAG: + break; + default: + return (EINVAL); + } + } else if (connp->conn_family != AF_INET) { return (EINVAL); + } switch (name) { case IP_TTL: diff --git a/usr/src/uts/common/inet/tcp/tcp_opt_data.c b/usr/src/uts/common/inet/tcp/tcp_opt_data.c index bdc9482b45..861be92c38 100644 --- a/usr/src/uts/common/inet/tcp/tcp_opt_data.c +++ b/usr/src/uts/common/inet/tcp/tcp_opt_data.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright 2015 Joyent, Inc. + * Copyright 2016 Joyent, Inc. */ #include <sys/types.h> @@ -996,10 +996,6 @@ tcp_opt_set(conn_t *connp, uint_t optset_context, int level, int name, } break; case IPPROTO_IP: - if (connp->conn_family != AF_INET) { - *outlenp = 0; - return (EINVAL); - } switch (name) { case IP_SEC_OPT: /* diff --git a/usr/src/uts/sun4u/cpu/common_asm.s b/usr/src/uts/sun4u/cpu/common_asm.s index a3e2343c89..aee74db442 100644 --- a/usr/src/uts/sun4u/cpu/common_asm.s +++ b/usr/src/uts/sun4u/cpu/common_asm.s @@ -808,6 +808,29 @@ kstat_q_panic_msg: QRETURN; \ stx %g1, [%o0 + QTYPE/**/LASTUPDATE]; /* lastupdate = now */ +#if !defined(DEBUG) +/* + * same as KSTAT_Q_UPDATE but without: + * QBR %o1, QZERO; + * to be used only with non-debug build. mimics ASSERT() behaviour. + */ +#define KSTAT_Q_UPDATE_ND(QOP, QRETURN, QTYPE) \ + ld [%o0 + QTYPE/**/CNT], %o1; /* %o1 = old qlen */ \ + QOP %o1, 1, %o2; /* %o2 = new qlen */ \ + st %o2, [%o0 + QTYPE/**/CNT]; /* delay: save qlen */ \ + ldx [%o0 + QTYPE/**/LASTUPDATE], %o3; \ + ldx [%o0 + QTYPE/**/TIME], %o4; /* %o4 = old time */ \ + ldx [%o0 + QTYPE/**/LENTIME], %o5; /* %o5 = old lentime */ \ + sub %g1, %o3, %o2; /* %o2 = time delta */ \ + mulx %o1, %o2, %o3; /* %o3 = cur lentime */ \ + add %o4, %o2, %o4; /* %o4 = new time */ \ + add %o5, %o3, %o5; /* %o5 = new lentime */ \ + stx %o4, [%o0 + QTYPE/**/TIME]; /* save time */ \ + stx %o5, [%o0 + QTYPE/**/LENTIME]; /* save lentime */ \ +QRETURN; \ + stx %g1, [%o0 + QTYPE/**/LASTUPDATE]; /* lastupdate = now */ +#endif + .align 16 ENTRY(kstat_waitq_enter) GET_NATIVE_TIME(%g1, %g2, %g3) @@ -817,7 +840,11 @@ QRETURN; \ .align 16 ENTRY(kstat_waitq_exit) GET_NATIVE_TIME(%g1, %g2, %g3) +#if defined(DEBUG) KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_W) +#else + KSTAT_Q_UPDATE_ND(sub, retl, KSTAT_IO_W) +#endif SET_SIZE(kstat_waitq_exit) .align 16 @@ -829,20 +856,32 @@ QRETURN; \ .align 16 ENTRY(kstat_runq_exit) GET_NATIVE_TIME(%g1, %g2, %g3) +#if defined(DEBUG) KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_R) +#else + KSTAT_Q_UPDATE_ND(sub, retl, KSTAT_IO_R) +#endif SET_SIZE(kstat_runq_exit) .align 16 ENTRY(kstat_waitq_to_runq) GET_NATIVE_TIME(%g1, %g2, %g3) +#if defined(DEBUG) KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_W) +#else + KSTAT_Q_UPDATE_ND(sub, 1:, KSTAT_IO_W) +#endif KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R) SET_SIZE(kstat_waitq_to_runq) .align 16 ENTRY(kstat_runq_back_to_waitq) GET_NATIVE_TIME(%g1, %g2, %g3) +#if defined(DEBUG) KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_R) +#else + KSTAT_Q_UPDATE_ND(sub, 1:, KSTAT_IO_R) +#endif KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W) SET_SIZE(kstat_runq_back_to_waitq) diff --git a/usr/src/uts/sun4v/cpu/common_asm.s b/usr/src/uts/sun4v/cpu/common_asm.s index ff08ef97f6..fda53b4d2a 100644 --- a/usr/src/uts/sun4v/cpu/common_asm.s +++ b/usr/src/uts/sun4v/cpu/common_asm.s @@ -654,6 +654,29 @@ kstat_q_panic_msg: QRETURN; \ stx %g1, [%o0 + QTYPE/**/LASTUPDATE]; /* lastupdate = now */ +#if !defined(DEBUG) +/* + * same as KSTAT_Q_UPDATE but without: + * QBR %o1, QZERO; + * to be used only with non-debug build. mimics ASSERT() behaviour. + */ +#define KSTAT_Q_UPDATE_ND(QOP, QRETURN, QTYPE) \ + ld [%o0 + QTYPE/**/CNT], %o1; /* %o1 = old qlen */ \ + QOP %o1, 1, %o2; /* %o2 = new qlen */ \ + st %o2, [%o0 + QTYPE/**/CNT]; /* delay: save qlen */ \ + ldx [%o0 + QTYPE/**/LASTUPDATE], %o3; \ + ldx [%o0 + QTYPE/**/TIME], %o4; /* %o4 = old time */ \ + ldx [%o0 + QTYPE/**/LENTIME], %o5; /* %o5 = old lentime */ \ + sub %g1, %o3, %o2; /* %o2 = time delta */ \ + mulx %o1, %o2, %o3; /* %o3 = cur lentime */ \ + add %o4, %o2, %o4; /* %o4 = new time */ \ + add %o5, %o3, %o5; /* %o5 = new lentime */ \ + stx %o4, [%o0 + QTYPE/**/TIME]; /* save time */ \ + stx %o5, [%o0 + QTYPE/**/LENTIME]; /* save lentime */ \ +QRETURN; \ + stx %g1, [%o0 + QTYPE/**/LASTUPDATE]; /* lastupdate = now */ +#endif + .align 16 ENTRY(kstat_waitq_enter) GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) @@ -663,7 +686,11 @@ QRETURN; \ .align 16 ENTRY(kstat_waitq_exit) GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) +#if defined(DEBUG) KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_W) +#else + KSTAT_Q_UPDATE_ND(sub, retl, KSTAT_IO_W) +#endif SET_SIZE(kstat_waitq_exit) .align 16 @@ -675,20 +702,32 @@ QRETURN; \ .align 16 ENTRY(kstat_runq_exit) GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) +#if defined(DEBUG) KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_R) +#else + KSTAT_Q_UPDATE_ND(sub, retl, KSTAT_IO_R) +#endif SET_SIZE(kstat_runq_exit) .align 16 ENTRY(kstat_waitq_to_runq) GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) +#if defined(DEBUG) KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_W) +#else + KSTAT_Q_UPDATE_ND(sub, 1:, KSTAT_IO_W) +#endif KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R) SET_SIZE(kstat_waitq_to_runq) .align 16 ENTRY(kstat_runq_back_to_waitq) GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) +#if defined(DEBUG) KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_R) +#else + KSTAT_Q_UPDATE_ND(sub, 1:, KSTAT_IO_R) +#endif KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W) SET_SIZE(kstat_runq_back_to_waitq) |