diff options
| author | Dan McDonald <danmcd@joyent.com> | 2022-01-27 11:13:17 -0500 |
|---|---|---|
| committer | Dan McDonald <danmcd@joyent.com> | 2022-01-27 11:13:17 -0500 |
| commit | b036b26396dfdd49970aee9117736298d09b281b (patch) | |
| tree | a7d6c632b40890a876fc0173141856b0f86e5077 | |
| parent | bdda732b87814197ddde2f7e2e2e5f47799f5451 (diff) | |
| parent | 907c2824088edd487e0b231d3df0654a81aec933 (diff) | |
| download | illumos-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.c | 8 | ||||
| -rw-r--r-- | usr/src/uts/common/fs/ufs/ufs_dir.c | 21 | ||||
| -rw-r--r-- | usr/src/uts/common/io/ksocket/ksocket.c | 2 | ||||
| -rw-r--r-- | usr/src/uts/common/io/ksocket/ksocket_impl.h | 2 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/fs/ufs_fsdir.h | 13 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/ksocket.h | 49 |
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); |
