#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "cgroup_helpers.h" /* * To avoid relying on the system setup, when setup_cgroup_env is called * we create a new mount namespace, and cgroup namespace. The cgroup2 * root is mounted at CGROUP_MOUNT_PATH * * Unfortunately, most people don't have cgroupv2 enabled at this point in time. * It's easier to create our own mount namespace and manage it ourselves. * * We assume /mnt exists. */ #define WALK_FD_LIMIT 16 #define CGROUP_MOUNT_PATH "/mnt" #define CGROUP_WORK_DIR "/cgroup-test-work-dir" #define format_cgroup_path(buf, path) \ snprintf(buf, sizeof(buf), "%s%s%s", CGROUP_MOUNT_PATH, \ CGROUP_WORK_DIR, path) /** * setup_cgroup_environment() - Setup the cgroup environment * * After calling this function, cleanup_cgroup_environment should be called * once testing is complete. * * This function will print an error to stderr and return 1 if it is unable * to setup the cgroup environment. If setup is successful, 0 is returned. */ int setup_cgroup_environment(void) { char cgroup_workdir[PATH_MAX + 1]; format_cgroup_path(cgroup_workdir, ""); if (unshare(CLONE_NEWNS)) { log_err("unshare"); return 1; } if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL)) { log_err("mount fakeroot"); return 1; } if (mount("none", CGROUP_MOUNT_PATH, "cgroup2", 0, NULL)) { log_err("mount cgroup2"); return 1; } /* Cleanup existing failed runs, now that the environment is setup */ cleanup_cgroup_environment(); if (mkdir(cgroup_workdir, 0777) && errno != EEXIST) { log_err("mkdir cgroup work dir"); return 1; } return 0; } static int nftwfunc(const char *filename, const struct stat *statptr, int fileflags, struct FTW *pfwt) { if ((fileflags & FTW_D) && rmdir(filename)) log_err("Removing cgroup: %s", filename); return 0; } static int join_cgroup_from_top(char *cgroup_path) { char cgroup_procs_path[PATH_MAX + 1]; pid_t pid = getpid(); int fd, rc = 0; snprintf(cgroup_procs_path, sizeof(cgroup_procs_path), "%s/cgroup.procs", cgroup_path); fd = open(cgroup_procs_path, O_WRONLY); if (fd < 0) { log_err("Opening Cgroup Procs: %s", cgroup_procs_path); return 1; } if (dprintf(fd, "%d\n", pid) < 0) { log_err("Joining Cgroup"); rc = 1; } close(fd); return rc; } /** * join_cgroup() - Join a cgroup * @path: The cgroup path, relative to the workdir, to join * * This function expects a cgroup to already be created, relative to the cgroup * work dir, and it joins it. For example, passing "/my-cgroup" as the path * would actually put the calling process into the cgroup * "/cgroup-test-work-dir/my-cgroup" * * On success, it returns 0, otherwise on failure it returns 1. */ int join_cgroup(char *path) { char cgroup_path[PATH_MAX + 1]; format_cgroup_path(cgroup_path, path); return join_cgroup_from_top(cgroup_path); } /** * cleanup_cgroup_environment() - Cleanup Cgroup Testing Environment * * This is an idempotent function to delete all temporary cgroups that * have been created during the test, including the cgroup testing work * directory. * * At call time, it moves the calling process to the root cgroup, and then * runs the deletion process. It is idempotent, and should not fail, unless * a process is lingering. * * On failure, it will print an error to stderr, and try to continue. */ void cleanup_cgroup_environment(void) { char cgroup_workdir[PATH_MAX + 1]; format_cgroup_path(cgroup_workdir, ""); join_cgroup_from_top(CGROUP_MOUNT_PATH); nftw(cgroup_workdir, nftwfunc, WALK_FD_LIMIT, FTW_DEPTH | FTW_MOUNT); } /** * create_and_get_cgroup() - Create a cgroup, relative to workdir, and get the FD * @path: The cgroup path, relative to the workdir, to join * * This function creates a cgroup under the top level workdir and returns the * file descriptor. It is idempotent. * * On success, it returns the file descriptor. On failure it returns 0. * If there is a failure, it prints the error to stderr. */ int create_and_get_cgroup(char *path) { char cgroup_path[PATH_MAX + 1]; int fd; format_cgroup_path(cgroup_path, path); if (mkdir(cgroup_path, 0777) && errno != EEXIST) { log_err("mkdiring cgroup"); return 0; } fd = open(cgroup_path, O_RDONLY); if (fd < 0) { log_err("Opening Cgroup"); return 0; } return fd; } >
authorKinglong Mee <kinglongmee@gmail.com>2017-01-20 16:48:39 +0800
committerTrond Myklebust <trond.myklebust@primarydata.com>2017-01-24 15:29:24 -0500
commitc929ea0b910355e1876c64431f3d5802f95b3d75 (patch)
tree94339f18c2be5b9308b9f44ac8b450fe58bcc645 /net/dccp
parenta430607b2ef7c3be090f88c71cfcb1b3988aa7c0 (diff)
SUNRPC: cleanup ida information when removing sunrpc module
After removing sunrpc module, I get many kmemleak information as, unreferenced object 0xffff88003316b1e0 (size 544): comm "gssproxy", pid 2148, jiffies 4294794465 (age 4200.081s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffffb0cfb58a>] kmemleak_alloc+0x4a/0xa0 [<ffffffffb03507fe>] kmem_cache_alloc+0x15e/0x1f0 [<ffffffffb0639baa>] ida_pre_get+0xaa/0x150 [<ffffffffb0639cfd>] ida_simple_get+0xad/0x180 [<ffffffffc06054fb>] nlmsvc_lookup_host+0x4ab/0x7f0 [lockd] [<ffffffffc0605e1d>] lockd+0x4d/0x270 [lockd] [<ffffffffc06061e5>] param_set_timeout+0x55/0x100 [lockd] [<ffffffffc06cba24>] svc_defer+0x114/0x3f0 [sunrpc] [<ffffffffc06cbbe7>] svc_defer+0x2d7/0x3f0 [sunrpc] [<ffffffffc06c71da>] rpc_show_info+0x8a/0x110 [sunrpc] [<ffffffffb044a33f>] proc_reg_write+0x7f/0xc0 [<ffffffffb038e41f>] __vfs_write+0xdf/0x3c0 [<ffffffffb0390f1f>] vfs_write+0xef/0x240 [<ffffffffb0392fbd>] SyS_write+0xad/0x130 [<ffffffffb0d06c37>] entry_SYSCALL_64_fastpath+0x1a/0xa9 [<ffffffffffffffff>] 0xffffffffffffffff I found, the ida information (dynamic memory) isn't cleanup. Signed-off-by: Kinglong Mee <kinglongmee@gmail.com> Fixes: 2f048db4680a ("SUNRPC: Add an identifier for struct rpc_clnt") Cc: stable@vger.kernel.org # v3.12+ Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net/dccp')