From f9c0c897d6652eb54c8b048acc0312706b89079f Mon Sep 17 00:00:00 2001 From: eeb Date: Mon, 1 Dec 2003 16:43:30 +0000 Subject: [PATCH] * Minor socknal cleanup * Added lctl::memhog to allocate kernel memory (freed on request or close) --- lnet/include/linux/kp30.h | 8 +- lnet/include/lnet/lnetctl.h | 1 + lnet/include/lnet/ptlctl.h | 1 + lnet/klnds/socklnd/socklnd_cb.c | 43 +++++---- lnet/libcfs/module.c | 147 +++++++++++++++++++++++++++++- lnet/utils/portals.c | 32 +++++++ lustre/portals/include/linux/kp30.h | 8 +- lustre/portals/include/portals/ptlctl.h | 1 + lustre/portals/knals/socknal/socknal_cb.c | 43 +++++---- lustre/portals/libcfs/module.c | 147 +++++++++++++++++++++++++++++- lustre/portals/utils/portals.c | 32 +++++++ 11 files changed, 415 insertions(+), 48 deletions(-) diff --git a/lnet/include/linux/kp30.h b/lnet/include/linux/kp30.h index 69a95e3..638d281 100644 --- a/lnet/include/linux/kp30.h +++ b/lnet/include/linux/kp30.h @@ -784,6 +784,11 @@ do { \ #endif /* __KERNEL__ */ #endif /* LWT_SUPPORT */ +struct portals_device_userstate +{ + int pdu_memhog_pages; + struct page *pdu_memhog_root_page; +}; #include @@ -1053,7 +1058,8 @@ static inline int portal_ioctl_getdata(char *buf, char *end, void *arg) #define IOC_PORTAL_LWT_CONTROL _IOWR('e', 39, long) #define IOC_PORTAL_LWT_SNAPSHOT _IOWR('e', 40, long) #define IOC_PORTAL_LWT_LOOKUP_STRING _IOWR('e', 41, long) -#define IOC_PORTAL_MAX_NR 41 +#define IOC_PORTAL_MEMHOG _IOWR('e', 42, long) +#define IOC_PORTAL_MAX_NR 42 enum { QSWNAL = 1, diff --git a/lnet/include/lnet/lnetctl.h b/lnet/include/lnet/lnetctl.h index f581e72..12ef47a 100644 --- a/lnet/include/lnet/lnetctl.h +++ b/lnet/include/lnet/lnetctl.h @@ -59,6 +59,7 @@ int jt_ptl_notify_router (int argc, char **argv); int jt_ptl_print_routes (int argc, char **argv); int jt_ptl_fail_nid (int argc, char **argv); int jt_ptl_lwt(int argc, char **argv); +int jt_ptl_memhog(int argc, char **argv); int dbg_initialize(int argc, char **argv); int jt_dbg_filter(int argc, char **argv); diff --git a/lnet/include/lnet/ptlctl.h b/lnet/include/lnet/ptlctl.h index f581e72..12ef47a 100644 --- a/lnet/include/lnet/ptlctl.h +++ b/lnet/include/lnet/ptlctl.h @@ -59,6 +59,7 @@ int jt_ptl_notify_router (int argc, char **argv); int jt_ptl_print_routes (int argc, char **argv); int jt_ptl_fail_nid (int argc, char **argv); int jt_ptl_lwt(int argc, char **argv); +int jt_ptl_memhog(int argc, char **argv); int dbg_initialize(int argc, char **argv); int jt_dbg_filter(int argc, char **argv); diff --git a/lnet/klnds/socklnd/socklnd_cb.c b/lnet/klnds/socklnd/socklnd_cb.c index 6ea4fa8..46b643f 100644 --- a/lnet/klnds/socklnd/socklnd_cb.c +++ b/lnet/klnds/socklnd/socklnd_cb.c @@ -377,17 +377,14 @@ ksocknal_sendmsg (ksock_conn_t *conn, ksock_tx_t *tx) } rc = ksocknal_getconnsock (conn); - if (rc != 0) + if (rc != 0) { + LASSERT (conn->ksnc_closing); return (rc); + } for (;;) { LASSERT (tx->tx_resid != 0); - if (conn->ksnc_closing) { - rc = -ESHUTDOWN; - break; - } - if (tx->tx_niov != 0) rc = ksocknal_send_iov (conn, tx); else @@ -568,15 +565,12 @@ ksocknal_recvmsg (ksock_conn_t *conn) } rc = ksocknal_getconnsock (conn); - if (rc != 0) + if (rc != 0) { + LASSERT (conn->ksnc_closing); return (rc); + } for (;;) { - if (conn->ksnc_closing) { - rc = -ESHUTDOWN; - break; - } - if (conn->ksnc_rx_niov != 0) rc = ksocknal_recv_iov (conn); else @@ -840,8 +834,12 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) unsigned long flags; ksock_sched_t *sched = conn->ksnc_scheduler; - /* called holding global lock (read or irq-write) */ - + /* called holding global lock (read or irq-write) and caller may + * not have dropped this lock between finding conn and calling me, + * so we don't need the {get,put}connsock dance to deref + * ksnc_sock... */ + LASSERT(!conn->ksnc_closing); + CDEBUG (D_NET, "Sending to "LPX64" on port %d\n", conn->ksnc_peer->ksnp_nid, conn->ksnc_port); @@ -854,7 +852,6 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) /* NB this sets 1 ref on zccd, so the callback can only occur after * I've released this ref. */ #endif - spin_lock_irqsave (&sched->kss_lock, flags); conn->ksnc_tx_deadline = jiffies + @@ -1528,6 +1525,8 @@ ksocknal_process_receive (ksock_conn_t *conn) rc = ksocknal_recvmsg(conn); if (rc <= 0) { + LASSERT (rc != -EAGAIN); + if (rc == 0) CWARN ("[%p] EOF from "LPX64" ip %08x:%d\n", conn, conn->ksnc_peer->ksnp_nid, @@ -1766,9 +1765,9 @@ int ksocknal_scheduler (void *arg) * kss_lock. */ conn->ksnc_tx_ready = 0; spin_unlock_irqrestore (&sched->kss_lock, flags); - + rc = ksocknal_process_transmit(conn, tx); - + spin_lock_irqsave (&sched->kss_lock, flags); if (rc != -EAGAIN) { @@ -1851,7 +1850,7 @@ ksocknal_data_ready (struct sock *sk, int n) read_lock (&ksocknal_data.ksnd_global_lock); conn = sk->sk_user_data; - if (conn == NULL) { /* raced with ksocknal_close_sock */ + if (conn == NULL) { /* raced with ksocknal_terminate_conn */ LASSERT (sk->sk_data_ready != &ksocknal_data_ready); sk->sk_data_ready (sk, n); } else { @@ -1900,7 +1899,7 @@ ksocknal_write_space (struct sock *sk) (conn == NULL) ? "" : (list_empty (&conn->ksnc_tx_queue) ? " empty" : " queued")); - if (conn == NULL) { /* raced with ksocknal_close_sock */ + if (conn == NULL) { /* raced with ksocknal_terminate_conn */ LASSERT (sk->sk_write_space != &ksocknal_write_space); sk->sk_write_space (sk); @@ -2136,7 +2135,7 @@ ksocknal_setup_sock (struct socket *sock) int option; struct linger linger; - sock->sk->allocation = GFP_NOFS; + sock->sk->allocation = GFP_MEMALLOC; /* Ensure this socket aborts active sends immediately when we close * it. */ @@ -2421,6 +2420,8 @@ ksocknal_autoconnectd (void *arg) kportal_daemonize (name); kportal_blockallsigs (); + current->flags |= PF_MEMALLOC; + spin_lock_irqsave (&ksocknal_data.ksnd_autoconnectd_lock, flags); while (!ksocknal_data.ksnd_shuttingdown) { @@ -2548,6 +2549,8 @@ ksocknal_reaper (void *arg) init_waitqueue_entry (&wait, current); + current->flags |= PF_MEMALLOC; + spin_lock_irqsave (&ksocknal_data.ksnd_reaper_lock, flags); while (!ksocknal_data.ksnd_shuttingdown) { diff --git a/lnet/libcfs/module.c b/lnet/libcfs/module.c index a9a268b..dad710d 100644 --- a/lnet/libcfs/module.c +++ b/lnet/libcfs/module.c @@ -83,6 +83,115 @@ kportal_daemonize (char *str) } void +kportal_memhog_free (struct portals_device_userstate *pdu) +{ + struct page **level0p = &pdu->pdu_memhog_root_page; + struct page **level1p; + struct page **level2p; + int count1; + int count2; + + if (*level0p != NULL) { + + level1p = (struct page **)page_address(*level0p); + count1 = 0; + + while (count1 < PAGE_SIZE/sizeof(struct page *) && + *level1p != NULL) { + + level2p = (struct page **)page_address(*level1p); + count2 = 0; + + while (count2 < PAGE_SIZE/sizeof(struct page *) && + *level2p != NULL) { + + __free_page(*level2p); + pdu->pdu_memhog_pages--; + level2p++; + count2++; + } + + __free_page(*level1p); + pdu->pdu_memhog_pages--; + level1p++; + count1++; + } + + __free_page(*level0p); + pdu->pdu_memhog_pages--; + + *level0p = NULL; + } + + LASSERT (pdu->pdu_memhog_pages == 0); +} + +int +kportal_memhog_alloc (struct portals_device_userstate *pdu, int npages, int flags) +{ + struct page **level0p; + struct page **level1p; + struct page **level2p; + int count1; + int count2; + + LASSERT (pdu->pdu_memhog_pages == 0); + LASSERT (pdu->pdu_memhog_root_page == NULL); + + if (npages < 0) + return -EINVAL; + + if (npages == 0) + return 0; + + level0p = &pdu->pdu_memhog_root_page; + *level0p = alloc_page(flags); + if (*level0p == NULL) + return -ENOMEM; + pdu->pdu_memhog_pages++; + + level1p = (struct page **)page_address(*level0p); + count1 = 0; + memset(level1p, 0, PAGE_SIZE); + + while (pdu->pdu_memhog_pages < npages && + count1 < PAGE_SIZE/sizeof(struct page *)) { + + if (signal_pending(current)) + return (-EINTR); + + *level1p = alloc_page(flags); + if (*level1p == NULL) + return -ENOMEM; + pdu->pdu_memhog_pages++; + + level2p = (struct page **)page_address(*level1p); + count2 = 0; + memset(level2p, 0, PAGE_SIZE); + + while (pdu->pdu_memhog_pages < npages && + count2 < PAGE_SIZE/sizeof(struct page *)) { + + if (signal_pending(current)) + return (-EINTR); + + *level2p = alloc_page(flags); + if (*level2p == NULL) + return (-ENOMEM); + pdu->pdu_memhog_pages++; + + level2p++; + count2++; + } + + level1p++; + count1++; + } + + return 0; +} + +void kportal_blockallsigs () { unsigned long flags; @@ -96,22 +205,39 @@ kportal_blockallsigs () /* called when opening /dev/device */ static int kportal_psdev_open(struct inode * inode, struct file * file) { + struct portals_device_userstate *pdu; ENTRY; - + if (!inode) RETURN(-EINVAL); + PORTAL_MODULE_USE; + + PORTAL_ALLOC(pdu, sizeof(*pdu)); + if (pdu != NULL) { + pdu->pdu_memhog_pages = 0; + pdu->pdu_memhog_root_page = NULL; + } + file->private_data = pdu; + RETURN(0); } /* called when closing /dev/device */ static int kportal_psdev_release(struct inode * inode, struct file * file) { + struct portals_device_userstate *pdu; ENTRY; if (!inode) RETURN(-EINVAL); + pdu = file->private_data; + if (pdu != NULL) { + kportal_memhog_free(pdu); + PORTAL_FREE(pdu, sizeof(*pdu)); + } + PORTAL_MODULE_UNUSE; RETURN(0); } @@ -529,7 +655,22 @@ static int kportal_ioctl(struct inode *inode, struct file *file, copy_to_user((char *)arg, data, sizeof (*data))) err = -EFAULT; break; -#endif +#endif + case IOC_PORTAL_MEMHOG: + if (!capable (CAP_SYS_ADMIN)) + err = -EPERM; + else if (file->private_data == NULL) { + err = -EINVAL; + } else { + kportal_memhog_free(file->private_data); + err = kportal_memhog_alloc(file->private_data, + data->ioc_count, + GFP_NOFS); + if (err != 0) + kportal_memhog_free(file->private_data); + } + break; + default: err = -EINVAL; break; @@ -613,8 +754,8 @@ static int init_kportals_module(void) cleanup_lwt: #if LWT_SUPPORT lwt_fini(); -#endif cleanup_debug: +#endif portals_debug_cleanup(); return rc; } diff --git a/lnet/utils/portals.c b/lnet/utils/portals.c index c1c3fe5..aa9aa93 100644 --- a/lnet/utils/portals.c +++ b/lnet/utils/portals.c @@ -1688,3 +1688,35 @@ jt_ptl_lwt(int argc, char **argv) free(events); return (0); } + +int jt_ptl_memhog(int argc, char **argv) +{ + struct portal_ioctl_data data; + int rc; + int count; + char *end; + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 0; + } + + count = strtol(argv[1], &end, 0); + if (count < 0 || *end != 0) { + fprintf(stderr, "Can't parse page count '%s'\n", argv[1]); + return -1; + } + + PORTAL_IOC_INIT(data); + data.ioc_count = count; + rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_MEMHOG, &data); + + if (rc != 0) { + fprintf(stderr, "memhog %d failed: %s\n", count, strerror(errno)); + return -1; + } + + printf("memhog %d OK\n", count); + return 0; +} + diff --git a/lustre/portals/include/linux/kp30.h b/lustre/portals/include/linux/kp30.h index 69a95e3..638d281 100644 --- a/lustre/portals/include/linux/kp30.h +++ b/lustre/portals/include/linux/kp30.h @@ -784,6 +784,11 @@ do { \ #endif /* __KERNEL__ */ #endif /* LWT_SUPPORT */ +struct portals_device_userstate +{ + int pdu_memhog_pages; + struct page *pdu_memhog_root_page; +}; #include @@ -1053,7 +1058,8 @@ static inline int portal_ioctl_getdata(char *buf, char *end, void *arg) #define IOC_PORTAL_LWT_CONTROL _IOWR('e', 39, long) #define IOC_PORTAL_LWT_SNAPSHOT _IOWR('e', 40, long) #define IOC_PORTAL_LWT_LOOKUP_STRING _IOWR('e', 41, long) -#define IOC_PORTAL_MAX_NR 41 +#define IOC_PORTAL_MEMHOG _IOWR('e', 42, long) +#define IOC_PORTAL_MAX_NR 42 enum { QSWNAL = 1, diff --git a/lustre/portals/include/portals/ptlctl.h b/lustre/portals/include/portals/ptlctl.h index f581e72..12ef47a 100644 --- a/lustre/portals/include/portals/ptlctl.h +++ b/lustre/portals/include/portals/ptlctl.h @@ -59,6 +59,7 @@ int jt_ptl_notify_router (int argc, char **argv); int jt_ptl_print_routes (int argc, char **argv); int jt_ptl_fail_nid (int argc, char **argv); int jt_ptl_lwt(int argc, char **argv); +int jt_ptl_memhog(int argc, char **argv); int dbg_initialize(int argc, char **argv); int jt_dbg_filter(int argc, char **argv); diff --git a/lustre/portals/knals/socknal/socknal_cb.c b/lustre/portals/knals/socknal/socknal_cb.c index 6ea4fa8..46b643f 100644 --- a/lustre/portals/knals/socknal/socknal_cb.c +++ b/lustre/portals/knals/socknal/socknal_cb.c @@ -377,17 +377,14 @@ ksocknal_sendmsg (ksock_conn_t *conn, ksock_tx_t *tx) } rc = ksocknal_getconnsock (conn); - if (rc != 0) + if (rc != 0) { + LASSERT (conn->ksnc_closing); return (rc); + } for (;;) { LASSERT (tx->tx_resid != 0); - if (conn->ksnc_closing) { - rc = -ESHUTDOWN; - break; - } - if (tx->tx_niov != 0) rc = ksocknal_send_iov (conn, tx); else @@ -568,15 +565,12 @@ ksocknal_recvmsg (ksock_conn_t *conn) } rc = ksocknal_getconnsock (conn); - if (rc != 0) + if (rc != 0) { + LASSERT (conn->ksnc_closing); return (rc); + } for (;;) { - if (conn->ksnc_closing) { - rc = -ESHUTDOWN; - break; - } - if (conn->ksnc_rx_niov != 0) rc = ksocknal_recv_iov (conn); else @@ -840,8 +834,12 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) unsigned long flags; ksock_sched_t *sched = conn->ksnc_scheduler; - /* called holding global lock (read or irq-write) */ - + /* called holding global lock (read or irq-write) and caller may + * not have dropped this lock between finding conn and calling me, + * so we don't need the {get,put}connsock dance to deref + * ksnc_sock... */ + LASSERT(!conn->ksnc_closing); + CDEBUG (D_NET, "Sending to "LPX64" on port %d\n", conn->ksnc_peer->ksnp_nid, conn->ksnc_port); @@ -854,7 +852,6 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) /* NB this sets 1 ref on zccd, so the callback can only occur after * I've released this ref. */ #endif - spin_lock_irqsave (&sched->kss_lock, flags); conn->ksnc_tx_deadline = jiffies + @@ -1528,6 +1525,8 @@ ksocknal_process_receive (ksock_conn_t *conn) rc = ksocknal_recvmsg(conn); if (rc <= 0) { + LASSERT (rc != -EAGAIN); + if (rc == 0) CWARN ("[%p] EOF from "LPX64" ip %08x:%d\n", conn, conn->ksnc_peer->ksnp_nid, @@ -1766,9 +1765,9 @@ int ksocknal_scheduler (void *arg) * kss_lock. */ conn->ksnc_tx_ready = 0; spin_unlock_irqrestore (&sched->kss_lock, flags); - + rc = ksocknal_process_transmit(conn, tx); - + spin_lock_irqsave (&sched->kss_lock, flags); if (rc != -EAGAIN) { @@ -1851,7 +1850,7 @@ ksocknal_data_ready (struct sock *sk, int n) read_lock (&ksocknal_data.ksnd_global_lock); conn = sk->sk_user_data; - if (conn == NULL) { /* raced with ksocknal_close_sock */ + if (conn == NULL) { /* raced with ksocknal_terminate_conn */ LASSERT (sk->sk_data_ready != &ksocknal_data_ready); sk->sk_data_ready (sk, n); } else { @@ -1900,7 +1899,7 @@ ksocknal_write_space (struct sock *sk) (conn == NULL) ? "" : (list_empty (&conn->ksnc_tx_queue) ? " empty" : " queued")); - if (conn == NULL) { /* raced with ksocknal_close_sock */ + if (conn == NULL) { /* raced with ksocknal_terminate_conn */ LASSERT (sk->sk_write_space != &ksocknal_write_space); sk->sk_write_space (sk); @@ -2136,7 +2135,7 @@ ksocknal_setup_sock (struct socket *sock) int option; struct linger linger; - sock->sk->allocation = GFP_NOFS; + sock->sk->allocation = GFP_MEMALLOC; /* Ensure this socket aborts active sends immediately when we close * it. */ @@ -2421,6 +2420,8 @@ ksocknal_autoconnectd (void *arg) kportal_daemonize (name); kportal_blockallsigs (); + current->flags |= PF_MEMALLOC; + spin_lock_irqsave (&ksocknal_data.ksnd_autoconnectd_lock, flags); while (!ksocknal_data.ksnd_shuttingdown) { @@ -2548,6 +2549,8 @@ ksocknal_reaper (void *arg) init_waitqueue_entry (&wait, current); + current->flags |= PF_MEMALLOC; + spin_lock_irqsave (&ksocknal_data.ksnd_reaper_lock, flags); while (!ksocknal_data.ksnd_shuttingdown) { diff --git a/lustre/portals/libcfs/module.c b/lustre/portals/libcfs/module.c index a9a268b..dad710d 100644 --- a/lustre/portals/libcfs/module.c +++ b/lustre/portals/libcfs/module.c @@ -83,6 +83,115 @@ kportal_daemonize (char *str) } void +kportal_memhog_free (struct portals_device_userstate *pdu) +{ + struct page **level0p = &pdu->pdu_memhog_root_page; + struct page **level1p; + struct page **level2p; + int count1; + int count2; + + if (*level0p != NULL) { + + level1p = (struct page **)page_address(*level0p); + count1 = 0; + + while (count1 < PAGE_SIZE/sizeof(struct page *) && + *level1p != NULL) { + + level2p = (struct page **)page_address(*level1p); + count2 = 0; + + while (count2 < PAGE_SIZE/sizeof(struct page *) && + *level2p != NULL) { + + __free_page(*level2p); + pdu->pdu_memhog_pages--; + level2p++; + count2++; + } + + __free_page(*level1p); + pdu->pdu_memhog_pages--; + level1p++; + count1++; + } + + __free_page(*level0p); + pdu->pdu_memhog_pages--; + + *level0p = NULL; + } + + LASSERT (pdu->pdu_memhog_pages == 0); +} + +int +kportal_memhog_alloc (struct portals_device_userstate *pdu, int npages, int flags) +{ + struct page **level0p; + struct page **level1p; + struct page **level2p; + int count1; + int count2; + + LASSERT (pdu->pdu_memhog_pages == 0); + LASSERT (pdu->pdu_memhog_root_page == NULL); + + if (npages < 0) + return -EINVAL; + + if (npages == 0) + return 0; + + level0p = &pdu->pdu_memhog_root_page; + *level0p = alloc_page(flags); + if (*level0p == NULL) + return -ENOMEM; + pdu->pdu_memhog_pages++; + + level1p = (struct page **)page_address(*level0p); + count1 = 0; + memset(level1p, 0, PAGE_SIZE); + + while (pdu->pdu_memhog_pages < npages && + count1 < PAGE_SIZE/sizeof(struct page *)) { + + if (signal_pending(current)) + return (-EINTR); + + *level1p = alloc_page(flags); + if (*level1p == NULL) + return -ENOMEM; + pdu->pdu_memhog_pages++; + + level2p = (struct page **)page_address(*level1p); + count2 = 0; + memset(level2p, 0, PAGE_SIZE); + + while (pdu->pdu_memhog_pages < npages && + count2 < PAGE_SIZE/sizeof(struct page *)) { + + if (signal_pending(current)) + return (-EINTR); + + *level2p = alloc_page(flags); + if (*level2p == NULL) + return (-ENOMEM); + pdu->pdu_memhog_pages++; + + level2p++; + count2++; + } + + level1p++; + count1++; + } + + return 0; +} + +void kportal_blockallsigs () { unsigned long flags; @@ -96,22 +205,39 @@ kportal_blockallsigs () /* called when opening /dev/device */ static int kportal_psdev_open(struct inode * inode, struct file * file) { + struct portals_device_userstate *pdu; ENTRY; - + if (!inode) RETURN(-EINVAL); + PORTAL_MODULE_USE; + + PORTAL_ALLOC(pdu, sizeof(*pdu)); + if (pdu != NULL) { + pdu->pdu_memhog_pages = 0; + pdu->pdu_memhog_root_page = NULL; + } + file->private_data = pdu; + RETURN(0); } /* called when closing /dev/device */ static int kportal_psdev_release(struct inode * inode, struct file * file) { + struct portals_device_userstate *pdu; ENTRY; if (!inode) RETURN(-EINVAL); + pdu = file->private_data; + if (pdu != NULL) { + kportal_memhog_free(pdu); + PORTAL_FREE(pdu, sizeof(*pdu)); + } + PORTAL_MODULE_UNUSE; RETURN(0); } @@ -529,7 +655,22 @@ static int kportal_ioctl(struct inode *inode, struct file *file, copy_to_user((char *)arg, data, sizeof (*data))) err = -EFAULT; break; -#endif +#endif + case IOC_PORTAL_MEMHOG: + if (!capable (CAP_SYS_ADMIN)) + err = -EPERM; + else if (file->private_data == NULL) { + err = -EINVAL; + } else { + kportal_memhog_free(file->private_data); + err = kportal_memhog_alloc(file->private_data, + data->ioc_count, + GFP_NOFS); + if (err != 0) + kportal_memhog_free(file->private_data); + } + break; + default: err = -EINVAL; break; @@ -613,8 +754,8 @@ static int init_kportals_module(void) cleanup_lwt: #if LWT_SUPPORT lwt_fini(); -#endif cleanup_debug: +#endif portals_debug_cleanup(); return rc; } diff --git a/lustre/portals/utils/portals.c b/lustre/portals/utils/portals.c index c1c3fe5..aa9aa93 100644 --- a/lustre/portals/utils/portals.c +++ b/lustre/portals/utils/portals.c @@ -1688,3 +1688,35 @@ jt_ptl_lwt(int argc, char **argv) free(events); return (0); } + +int jt_ptl_memhog(int argc, char **argv) +{ + struct portal_ioctl_data data; + int rc; + int count; + char *end; + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 0; + } + + count = strtol(argv[1], &end, 0); + if (count < 0 || *end != 0) { + fprintf(stderr, "Can't parse page count '%s'\n", argv[1]); + return -1; + } + + PORTAL_IOC_INIT(data); + data.ioc_count = count; + rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_MEMHOG, &data); + + if (rc != 0) { + fprintf(stderr, "memhog %d failed: %s\n", count, strerror(errno)); + return -1; + } + + printf("memhog %d OK\n", count); + return 0; +} + -- 1.8.3.1