* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, Whamcloud, Inc.
+ * Copyright (c) 2012, 2014, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
/* For sys_open & sys_close */
#include <linux/syscalls.h>
-int
+#ifndef HAVE_SK_SLEEP
+static inline wait_queue_head_t *sk_sleep(struct sock *sk)
+{
+ return sk->sk_sleep;
+}
+#endif
+
+static int
libcfs_sock_ioctl(int cmd, unsigned long arg)
{
- mm_segment_t oldmm = get_fs();
- struct socket *sock;
- int fd;
- int rc;
- struct file *sock_filp;
+ mm_segment_t oldmm = get_fs();
+ struct socket *sock;
+ int fd = -1;
+ int rc;
+ struct file *sock_filp;
rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
if (rc != 0) {
return rc;
}
-#ifdef HAVE_SOCK_MAP_FD_2ARG
- fd = sock_map_fd(sock,0);
+#if !defined(HAVE_SOCK_ALLOC_FILE) && !defined(HAVE_SOCK_ALLOC_FILE_3ARGS)
+ fd = sock_map_fd(sock, 0);
+ if (fd < 0) {
+ rc = fd;
+ sock_release(sock);
+ goto out;
+ }
+ sock_filp = fget(fd);
#else
- fd = sock_map_fd(sock);
+# ifdef HAVE_SOCK_ALLOC_FILE_3ARGS
+ sock_filp = sock_alloc_file(sock, 0, NULL);
+# else
+ sock_filp = sock_alloc_file(sock, 0);
+# endif
#endif
- if (fd < 0) {
- rc = fd;
- sock_release(sock);
- goto out;
- }
-
- sock_filp = fget(fd);
if (!sock_filp) {
rc = -ENOMEM;
- goto out_fd;
+ sock_release(sock);
+ goto out;
}
- set_fs(KERNEL_DS);
-#ifdef HAVE_UNLOCKED_IOCTL
- if (sock_filp->f_op->unlocked_ioctl)
- rc = sock_filp->f_op->unlocked_ioctl(sock_filp, cmd, arg);
-#else
- lock_kernel();
- rc = sock_filp->f_op->ioctl(sock_filp->f_dentry->d_inode,
- sock_filp, cmd, arg);
- unlock_kernel();
-#endif
- set_fs(oldmm);
+ set_fs(KERNEL_DS);
+ if (sock_filp->f_op->unlocked_ioctl)
+ rc = sock_filp->f_op->unlocked_ioctl(sock_filp, cmd, arg);
+ set_fs(oldmm);
fput(sock_filp);
- out_fd:
- sys_close(fd);
out:
+ if (fd >= 0)
+ sys_close(fd);
+
return rc;
}
CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
- strcpy(ifr.ifr_name, name);
+ if (strlen(name) > sizeof(ifr.ifr_name)-1)
+ return -E2BIG;
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
rc = libcfs_sock_ioctl(SIOCGIFFLAGS, (unsigned long)&ifr);
if (rc != 0) {
*up = 1;
- strcpy(ifr.ifr_name, name);
+ if (strlen(name) > sizeof(ifr.ifr_name)-1)
+ return -E2BIG;
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
ifr.ifr_addr.sa_family = AF_INET;
rc = libcfs_sock_ioctl(SIOCGIFADDR, (unsigned long)&ifr);
val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
*ip = ntohl(val);
- strcpy(ifr.ifr_name, name);
+ if (strlen(name) > sizeof(ifr.ifr_name)-1)
+ return -E2BIG;
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
ifr.ifr_addr.sa_family = AF_INET;
rc = libcfs_sock_ioctl(SIOCGIFNETMASK, (unsigned long)&ifr);
nalloc = 16; /* first guess at max interfaces */
toobig = 0;
for (;;) {
- if (nalloc * sizeof(*ifr) > CFS_PAGE_SIZE) {
- toobig = 1;
- nalloc = CFS_PAGE_SIZE/sizeof(*ifr);
- CWARN("Too many interfaces: only enumerating first %d\n",
- nalloc);
- }
+ if (nalloc * sizeof(*ifr) > PAGE_CACHE_SIZE) {
+ toobig = 1;
+ nalloc = PAGE_CACHE_SIZE/sizeof(*ifr);
+ CWARN("Too many interfaces: only enumerating first %d\n",
+ nalloc);
+ }
LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
if (ifr == NULL) {
rc = -ENOMEM;
goto out1;
}
- /* NULL out all names[i] */
- memset (names, 0, nfound * sizeof(*names));
for (i = 0; i < nfound; i++) {
int
libcfs_sock_write (struct socket *sock, void *buffer, int nob, int timeout)
{
- int rc;
- mm_segment_t oldmm = get_fs();
- long ticks = timeout * HZ;
- unsigned long then;
- struct timeval tv;
-
- LASSERT (nob > 0);
- /* Caller may pass a zero timeout if she thinks the socket buffer is
- * empty enough to take the whole message immediately */
-
- for (;;) {
- struct iovec iov = {
- .iov_base = buffer,
- .iov_len = nob
- };
- struct msghdr msg = {
- .msg_name = NULL,
- .msg_namelen = 0,
- .msg_iov = &iov,
- .msg_iovlen = 1,
- .msg_control = NULL,
- .msg_controllen = 0,
- .msg_flags = (timeout == 0) ? MSG_DONTWAIT : 0
- };
-
- if (timeout != 0) {
- /* Set send timeout to remaining time */
- tv = (struct timeval) {
- .tv_sec = ticks / HZ,
- .tv_usec = ((ticks % HZ) * 1000000) / HZ
- };
+ int rc;
+ mm_segment_t oldmm = get_fs();
+ long jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC);
+ unsigned long then;
+ struct timeval tv;
+
+ LASSERT(nob > 0);
+ /* Caller may pass a zero timeout if she thinks the socket buffer is
+ * empty enough to take the whole message immediately */
+
+ for (;;) {
+ struct kvec iov = {
+ .iov_base = buffer,
+ .iov_len = nob
+ };
+ struct msghdr msg = {
+ .msg_flags = (timeout == 0) ? MSG_DONTWAIT : 0
+ };
+
+ if (timeout != 0) {
+ /* Set send timeout to remaining time */
+ tv = (struct timeval) {
+ .tv_sec = jiffies_left /
+ msecs_to_jiffies(MSEC_PER_SEC),
+ .tv_usec = ((jiffies_left %
+ msecs_to_jiffies(MSEC_PER_SEC)) *
+ USEC_PER_SEC) /
+ msecs_to_jiffies(MSEC_PER_SEC)
+ };
set_fs(KERNEL_DS);
rc = sock_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
(char *)&tv, sizeof(tv));
}
}
- set_fs (KERNEL_DS);
- then = jiffies;
- rc = sock_sendmsg (sock, &msg, iov.iov_len);
- ticks -= jiffies - then;
- set_fs (oldmm);
+ then = jiffies;
+ rc = kernel_sendmsg(sock, &msg, &iov, 1, nob);
+ jiffies_left -= jiffies - then;
if (rc == nob)
return 0;
return (-ECONNABORTED);
}
- if (ticks <= 0)
+ if (jiffies_left <= 0)
return -EAGAIN;
buffer = ((char *)buffer) + rc;
int
libcfs_sock_read (struct socket *sock, void *buffer, int nob, int timeout)
{
- int rc;
- mm_segment_t oldmm = get_fs();
- long ticks = timeout * HZ;
- unsigned long then;
- struct timeval tv;
-
- LASSERT (nob > 0);
- LASSERT (ticks > 0);
-
- for (;;) {
- struct iovec iov = {
- .iov_base = buffer,
- .iov_len = nob
- };
- struct msghdr msg = {
- .msg_name = NULL,
- .msg_namelen = 0,
- .msg_iov = &iov,
- .msg_iovlen = 1,
- .msg_control = NULL,
- .msg_controllen = 0,
- .msg_flags = 0
- };
-
- /* Set receive timeout to remaining time */
- tv = (struct timeval) {
- .tv_sec = ticks / HZ,
- .tv_usec = ((ticks % HZ) * 1000000) / HZ
- };
+ int rc;
+ mm_segment_t oldmm = get_fs();
+ long jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC);
+ unsigned long then;
+ struct timeval tv;
+
+ LASSERT(nob > 0);
+ LASSERT(jiffies_left > 0);
+
+ for (;;) {
+ struct kvec iov = {
+ .iov_base = buffer,
+ .iov_len = nob
+ };
+ struct msghdr msg = {
+ .msg_flags = 0
+ };
+
+ /* Set receive timeout to remaining time */
+ tv = (struct timeval) {
+ .tv_sec = jiffies_left / msecs_to_jiffies(MSEC_PER_SEC),
+ .tv_usec = ((jiffies_left %
+ msecs_to_jiffies(MSEC_PER_SEC)) *
+ USEC_PER_SEC) /
+ msecs_to_jiffies(MSEC_PER_SEC)
+ };
set_fs(KERNEL_DS);
rc = sock_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
(char *)&tv, sizeof(tv));
return rc;
}
- set_fs(KERNEL_DS);
- then = jiffies;
- rc = sock_recvmsg(sock, &msg, iov.iov_len, 0);
- ticks -= jiffies - then;
- set_fs(oldmm);
+ then = jiffies;
+ rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0);
+ jiffies_left -= jiffies - then;
if (rc < 0)
return rc;
if (nob == 0)
return 0;
- if (ticks <= 0)
+ if (jiffies_left <= 0)
return -ETIMEDOUT;
}
}
EXPORT_SYMBOL(libcfs_sock_listen);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
-int sock_create_lite(int family, int type, int protocol, struct socket **res)
-{
- struct socket *sock;
-
- sock = sock_alloc();
- if (sock == NULL)
- return -ENOMEM;
-
- sock->type = type;
- *res = sock;
-
- return 0;
-}
-#endif
-
int
libcfs_sock_accept (struct socket **newsockp, struct socket *sock)
{
newsock->ops = sock->ops;
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(sk_sleep(sock->sk), &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(sk_sleep(sock->sk), &wait);
- rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
- if (rc == -EAGAIN) {
- /* Nothing ready, so wait for activity */
- schedule();
- rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
- }
+ rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
+ if (rc == -EAGAIN) {
+ /* Nothing ready, so wait for activity */
+ schedule();
+ rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
+ }
- remove_wait_queue(sk_sleep(sock->sk), &wait);
- set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk_sleep(sock->sk), &wait);
+ set_current_state(TASK_RUNNING);
if (rc != 0)
goto failed;
void
libcfs_sock_abort_accept (struct socket *sock)
{
- wake_up_all(sk_sleep(sock->sk));
+ wake_up_all(sk_sleep(sock->sk));
}
EXPORT_SYMBOL(libcfs_sock_abort_accept);