summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McDonald <danmcd@joyent.com>2022-01-27 11:13:17 -0500
committerDan McDonald <danmcd@joyent.com>2022-01-27 11:13:17 -0500
commitb036b26396dfdd49970aee9117736298d09b281b (patch)
treea7d6c632b40890a876fc0173141856b0f86e5077
parentbdda732b87814197ddde2f7e2e2e5f47799f5451 (diff)
parent907c2824088edd487e0b231d3df0654a81aec933 (diff)
downloadillumos-joyent-b036b26396dfdd49970aee9117736298d09b281b.tar.gz
[illumos-gate merge]
commit 907c2824088edd487e0b231d3df0654a81aec933 14202 Need direct callbacks from socket upcalls via ksocket commit 7939798324de96253652dd33a2a42e25e4ab61f9 14343 ufs: array subscript 'struct direct[0]' is partly outside array bounds Conflicts: usr/src/uts/common/io/ksocket/ksocket.c usr/src/uts/common/sys/ksocket.h
-rw-r--r--usr/src/uts/common/fs/sockfs/sockcommon.c8
-rw-r--r--usr/src/uts/common/fs/ufs/ufs_dir.c21
-rw-r--r--usr/src/uts/common/io/ksocket/ksocket.c2
-rw-r--r--usr/src/uts/common/io/ksocket/ksocket_impl.h2
-rw-r--r--usr/src/uts/common/sys/fs/ufs_fsdir.h13
-rw-r--r--usr/src/uts/common/sys/ksocket.h49
6 files changed, 62 insertions, 33 deletions
diff --git a/usr/src/uts/common/fs/sockfs/sockcommon.c b/usr/src/uts/common/fs/sockfs/sockcommon.c
index e7d69f9896..edcb41951c 100644
--- a/usr/src/uts/common/fs/sockfs/sockcommon.c
+++ b/usr/src/uts/common/fs/sockfs/sockcommon.c
@@ -458,16 +458,16 @@ sonode_constructor(void *buf, void *cdrarg, int kmflags)
vp->v_data = so;
vn_setops(vp, socket_vnodeops);
- so->so_priv = NULL;
+ so->so_priv = NULL;
so->so_oobmsg = NULL;
so->so_proto_handle = NULL;
- so->so_peercred = NULL;
+ so->so_peercred = NULL;
so->so_rcv_queued = 0;
- so->so_rcv_q_head = NULL;
- so->so_rcv_q_last_head = NULL;
+ so->so_rcv_q_head = NULL;
+ so->so_rcv_q_last_head = NULL;
so->so_rcv_head = NULL;
so->so_rcv_last_head = NULL;
so->so_rcv_wanted = 0;
diff --git a/usr/src/uts/common/fs/ufs/ufs_dir.c b/usr/src/uts/common/fs/ufs/ufs_dir.c
index 8035e76025..02f7e57fcd 100644
--- a/usr/src/uts/common/fs/ufs/ufs_dir.c
+++ b/usr/src/uts/common/fs/ufs/ufs_dir.c
@@ -2870,9 +2870,6 @@ ufs_dirpurgedotdot(
* Scan the directoy. If clr_dotdot is true clear the ..
* directory else check to see if the directory is empty.
*
- * Using a struct dirtemplate here is not precisely
- * what we want, but better than using a struct direct.
- *
* clr_dotdot is used as a flag to tell us if we need
* to clear the dotdot entry
*
@@ -2886,20 +2883,19 @@ ufs_dirscan(
int clr_dotdot)
{
offset_t off;
- struct dirtemplate dbuf;
- struct direct *dp = (struct direct *)&dbuf;
+ struct tmp_dir dbuf, *dp;
int err, count;
int empty = 1; /* Assume it's empty */
-#define MINDIRSIZ (sizeof (struct dirtemplate) / 2)
+ dp = &dbuf;
ASSERT(RW_LOCK_HELD(&ip->i_contents));
ASSERT(ip->i_size <= (offset_t)MAXOFF_T);
for (off = 0; off < ip->i_size; off += dp->d_reclen) {
err = ufs_rdwri(UIO_READ, FREAD, ip, (caddr_t)dp,
- (ssize_t)MINDIRSIZ, off, UIO_SYSSPACE, &count, cr);
+ sizeof (struct tmp_dir), off, UIO_SYSSPACE, &count, cr);
/*
- * Since we read MINDIRSIZ, residual must
+ * Since we read sizeof (struct tmp_dir), residual must
* be 0 unless we're at end of file.
*/
if (err || count != 0 || dp->d_reclen == 0) {
@@ -3108,20 +3104,19 @@ int
ufs_xattrdirempty(struct inode *ip, ino_t parentino, struct cred *cr)
{
offset_t off;
- struct dirtemplate dbuf;
- struct direct *dp = (struct direct *)&dbuf;
+ struct tmp_dir dbuf, *dp;
int err, count;
int empty = 1; /* Assume it's empty */
-#define MINDIRSIZ (sizeof (struct dirtemplate) / 2)
+ dp = &dbuf;
ASSERT(RW_LOCK_HELD(&ip->i_contents));
ASSERT(ip->i_size <= (offset_t)MAXOFF_T);
for (off = 0; off < ip->i_size; off += dp->d_reclen) {
err = ufs_rdwri(UIO_READ, FREAD, ip, (caddr_t)dp,
- (ssize_t)MINDIRSIZ, off, UIO_SYSSPACE, &count, cr);
+ sizeof (struct tmp_dir), off, UIO_SYSSPACE, &count, cr);
/*
- * Since we read MINDIRSIZ, residual must
+ * Since we read sizeof (struct tmp_dir), residual must
* be 0 unless we're at end of file.
*/
diff --git a/usr/src/uts/common/io/ksocket/ksocket.c b/usr/src/uts/common/io/ksocket/ksocket.c
index 0a5eec209f..10293941a2 100644
--- a/usr/src/uts/common/io/ksocket/ksocket.c
+++ b/usr/src/uts/common/io/ksocket/ksocket.c
@@ -942,5 +942,5 @@ ksocket_krecv_set(ksocket_t ks, ksocket_krecv_f cb, void *arg)
void
ksocket_krecv_unblock(ksocket_t ks)
{
- so_krecv_unblock(KSTOSO(ks));
+ return (so_krecv_unblock(KSTOSO(ks)));
}
diff --git a/usr/src/uts/common/io/ksocket/ksocket_impl.h b/usr/src/uts/common/io/ksocket/ksocket_impl.h
index 516a68d358..2b685008e3 100644
--- a/usr/src/uts/common/io/ksocket/ksocket_impl.h
+++ b/usr/src/uts/common/io/ksocket/ksocket_impl.h
@@ -51,7 +51,7 @@
#define __KSOCKET_EV_cantrecvmore KSOCKET_EV_CANTRECVMORE
#define __KSOCKET_EV_error KSOCKET_EV_ERROR
-#define KSOCKET_CALLBACK(so, cbfn, arg) \
+#define KSOCKET_CALLBACK(so, cbfn, arg) \
if ((so)->so_ksock_callbacks.ksock_cb_##cbfn != NULL) { \
(*(so)->so_ksock_callbacks.ksock_cb_##cbfn)(SOTOKS(so), \
__KSOCKET_EV_##cbfn, (so)->so_ksock_cb_arg, (arg)); \
diff --git a/usr/src/uts/common/sys/fs/ufs_fsdir.h b/usr/src/uts/common/sys/fs/ufs_fsdir.h
index d0719c6f02..8e1c8a7d06 100644
--- a/usr/src/uts/common/sys/fs/ufs_fsdir.h
+++ b/usr/src/uts/common/sys/fs/ufs_fsdir.h
@@ -105,6 +105,19 @@ struct dirtemplate {
short dotdot_namlen;
char dotdot_name[4]; /* ditto */
};
+
+/*
+ * Reduced structure for manipulating directories.
+ * Note, we are using __packed here to ensure the size of structure
+ * without changing the alignment.
+ */
+struct tmp_dir {
+ uint32_t d_ino; /* inode number of entry */
+ ushort_t d_reclen; /* length of this record */
+ ushort_t d_namlen; /* length of string in d_name */
+ char d_name[4]; /* name must be no longer than this */
+} __packed;
+
#endif
#ifdef __cplusplus
diff --git a/usr/src/uts/common/sys/ksocket.h b/usr/src/uts/common/sys/ksocket.h
index d720caa631..abf6bccfa5 100644
--- a/usr/src/uts/common/sys/ksocket.h
+++ b/usr/src/uts/common/sys/ksocket.h
@@ -84,47 +84,68 @@ typedef struct ksocket_callbacks {
#define KSOCKET_SLEEP SOCKET_SLEEP
#define KSOCKET_NOSLEEP SOCKET_NOSLEEP
-extern int ksocket_socket(ksocket_t *, int, int, int, int, struct cred *);
-extern int ksocket_bind(ksocket_t, struct sockaddr *, socklen_t,
+extern int ksocket_socket(ksocket_t *, int, int, int, int, struct cred *);
+extern int ksocket_bind(ksocket_t, struct sockaddr *, socklen_t,
struct cred *);
-extern int ksocket_listen(ksocket_t, int, struct cred *);
-extern int ksocket_accept(ksocket_t, struct sockaddr *, socklen_t *,
+extern int ksocket_listen(ksocket_t, int, struct cred *);
+extern int ksocket_accept(ksocket_t, struct sockaddr *, socklen_t *,
ksocket_t *, struct cred *);
-extern int ksocket_connect(ksocket_t, struct sockaddr *, socklen_t,
+extern int ksocket_connect(ksocket_t, struct sockaddr *, socklen_t,
struct cred *);
-extern int ksocket_send(ksocket_t, void *, size_t, int, size_t *,
+extern int ksocket_send(ksocket_t, void *, size_t, int, size_t *,
struct cred *);
extern int ksocket_sendto(ksocket_t, void *, size_t, int,
struct sockaddr *, socklen_t, size_t *, struct cred *);
-extern int ksocket_sendmsg(ksocket_t, struct nmsghdr *, int, size_t *,
+extern int ksocket_sendmsg(ksocket_t, struct nmsghdr *, int, size_t *,
struct cred *);
extern int ksocket_sendmblk(ksocket_t, struct nmsghdr *, int,
struct msgb **, struct cred *);
-extern int ksocket_recv(ksocket_t, void *, size_t, int, size_t *,
+extern int ksocket_recv(ksocket_t, void *, size_t, int, size_t *,
struct cred *);
extern int ksocket_recvfrom(ksocket_t, void *, size_t, int,
struct sockaddr *, socklen_t *, size_t *, struct cred *);
extern int ksocket_recvmsg(ksocket_t, struct nmsghdr *, int, size_t *,
struct cred *);
extern int ksocket_shutdown(ksocket_t, int, struct cred *);
-extern int ksocket_setsockopt(ksocket_t, int, int, const void *, int,
+extern int ksocket_setsockopt(ksocket_t, int, int, const void *, int,
struct cred *);
-extern int ksocket_getsockopt(ksocket_t, int, int, void *, int *,
+extern int ksocket_getsockopt(ksocket_t, int, int, void *, int *,
struct cred *);
-extern int ksocket_getpeername(ksocket_t, struct sockaddr *, socklen_t *,
+extern int ksocket_getpeername(ksocket_t, struct sockaddr *, socklen_t *,
struct cred *);
-extern int ksocket_getsockname(ksocket_t, struct sockaddr *, socklen_t *,
+extern int ksocket_getsockname(ksocket_t, struct sockaddr *, socklen_t *,
struct cred *);
extern int ksocket_ioctl(ksocket_t, int, intptr_t, int *, struct cred *);
extern int ksocket_spoll(ksocket_t, int, short, short *, struct cred *);
extern int ksocket_setcallbacks(ksocket_t, ksocket_callbacks_t *, void *,
struct cred *);
-extern int ksocket_close(ksocket_t, struct cred *);
+extern int ksocket_close(ksocket_t, struct cred *);
extern void ksocket_hold(ksocket_t);
extern void ksocket_rele(ksocket_t);
+/*
+ * These functions allow an alternative way for a ksocket to directly
+ * receive data when it arrives in sockfs rather than having it queued
+ * in a socket buffer that it must separately poll. The use of this
+ * results in no data being queued in sockfs.
+ *
+ * When the receive function receives data, it is responsible for always
+ * consuming all of the data. The return value of the callback function
+ * is used to indicate flow control and backpressure (similar to
+ * mac_tx(9E)). If, after processing the data, additional data can be
+ * received and processed, then the callback function should return
+ * B_TRUE. Otherwise it should return B_FALSE. This will result in the
+ * lower level socket interfaces (e.g. TCP) understanding that
+ * backpressure has been asserted (as though the sockfs buffer is full).
+ *
+ * Once whatever conditions that caused the callback function to assert
+ * that it needed to assert flow control are done, then it must call
+ * ksocket_krecv_unblock() to allow the flow to continue. If the receive
+ * callback ever returns B_FALSE there will generally be no additional
+ * data received until this is called.
+ */
typedef boolean_t (*ksocket_krecv_f)(ksocket_t, struct msgb *, size_t, int,
- void *);
+ void *);
extern int ksocket_krecv_set(ksocket_t, ksocket_krecv_f, void *);
extern void ksocket_krecv_unblock(ksocket_t);