HBASE-4391 Add ability to start RS as root and call mlockall (Matteo Bertozzi)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1353289 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Zhihong Yu 2012-06-24 16:20:28 +00:00
parent 9cfae9f15f
commit f8f60a8360
5 changed files with 241 additions and 0 deletions

View File

@ -63,6 +63,21 @@ do
hosts=$1
shift
HBASE_REGIONSERVERS=$hosts
elif [ "--mlock" = "$1" ]
then
shift
mlock_opts=$1
shift
mlock_agent="$HBASE_HOME/native/libmlockall_agent.so"
echo $mlock_agent
if [ -e $mlock_agent ]; then
HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -agentpath:$mlock_agent=$mlock_opts"
else
cat 1>&2 <<EOF
Unable to find mlockall_agent, hbase must be compiled with -Pnative
EOF
exit 1
fi
else
# Presume we are at end of options and break
break

View File

@ -515,6 +515,39 @@
</dependency>
</dependencies>
</profile>
<profile>
<id>native</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>make</id>
<phase>compile</phase>
<goals><goal>run</goal></goals>
<configuration>
<target>
<mkdir dir="${project.build.directory}/native"/>
<exec executable="cmake" dir="${project.build.directory}/native"
failonerror="true">
<arg line="${basedir}/src/main/native -DJVM_ARCH_DATA_MODEL=${sun.arch.data.model}"/>
</exec>
<exec executable="make" dir="${project.build.directory}/native" failonerror="true">
<arg line="VERBOSE=1"/>
</exec>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- Profiles for building against different hadoop versions -->
<!-- There are a lot of common dependencies used here, should investigate
if we can combine these profiles somehow -->

View File

@ -0,0 +1,35 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
# If JVM_ARCH_DATA_MODEL is 32, compile all binaries as 32-bit.
# This variable is set by maven.
if (JVM_ARCH_DATA_MODEL EQUAL 32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
set(CMAKE_LD_FLAGS "${CMAKE_LD_FLAGS} -m32")
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
set(CMAKE_SYSTEM_PROCESSOR "i686")
endif ()
endif (JVM_ARCH_DATA_MODEL EQUAL 32)
FIND_PACKAGE(JNI REQUIRED)
INCLUDE_DIRECTORIES(${JAVA_INCLUDE_PATH})
INCLUDE_DIRECTORIES(${JAVA_INCLUDE_PATH2})
add_library (mlockall_agent SHARED src/mlockall_agent/mlockall_agent.c)

View File

@ -0,0 +1,148 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* mlockall_agent is a simple VM Agent that allows to lock the address space of
* the process. This avoids the process' memory eviction under pressure.
*
* One example is when on the same machine you run the Region Server and
* some map-reduce tasks, some unused data in the region server may get swapped
* and this affects the region server performance.
*
* You can load the agent by adding it as a jvm option:
* export HBASE_REGIONSERVER_OPTS="-agentpath:./libmlockall_agent.so=user=hbase"
*/
#include <libgen.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "jvmti.h"
typedef struct opts {
char *setuid_user;
} opts_t;
#define PREFIX "mlockall_agent: "
#define LOG(fmt, ...) { fprintf(stderr, PREFIX fmt, #__VA_ARGS__); }
static int parse_options (const char *options, opts_t *parsed) {
char *optr, *opts_dup;
char *save2 = NULL;
char *save = NULL;
char *key, *val;
int ret = 0;
char *tok;
memset(parsed, 0, sizeof(opts_t));
if ((opts_dup = strdup(options)) == NULL)
return(-1);
optr = opts_dup;
while ((tok = strtok_r(optr, ",", &save)) != NULL) {
optr = NULL;
save2 = NULL;
key = strtok_r(tok, "=", &save2);
val = strtok_r(NULL, "=", &save2);
if (!strcmp(key, "user")) {
parsed->setuid_user = strdup(val);
} else {
LOG("Unknown agent parameter '%s'\n", key);
ret = 1;
}
}
free(opts_dup);
return(ret);
}
static void warn_unless_root() {
if (geteuid() != 0) {
LOG("(this may be because java was not run as root!)\n");
}
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *init_str, void *reserved) {
struct passwd *pwd = NULL;
opts_t opts;
if (parse_options(init_str, &opts)) {
return(1);
}
// Check that the target user for setuid is specified if current user is root
if (opts.setuid_user == NULL) {
LOG("Unable to setuid: specify a target username as the agent option user=<username>\n");
return(1);
}
// Check that this user exists
if ((pwd = getpwnam(opts.setuid_user)) == NULL) {
LOG("Unable to setuid: could not find user '%s'\n", opts.setuid_user);
return(1);
}
// Boost the mlock limit up to infinity
struct rlimit lim;
lim.rlim_max = RLIM_INFINITY;
lim.rlim_cur = lim.rlim_max;
if (setrlimit(RLIMIT_MEMLOCK, &lim)) {
perror(PREFIX "Unable to boost memlock resource limit");
warn_unless_root();
return(1);
}
// Actually lock our memory, including future allocations.
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
perror(PREFIX "Unable to lock memory.");
warn_unless_root();
return(1);
}
// Drop down to the user's supplemental group list
if (initgroups(opts.setuid_user, pwd->pw_gid)) {
perror(PREFIX "Unable to initgroups");
warn_unless_root();
return(1);
}
// And primary group ID
if (setgid(pwd->pw_gid)) {
perror(PREFIX "Unable to setgid");
warn_unless_root();
return(1);
}
// And user ID
if (setuid(pwd->pw_uid)) {
perror(PREFIX "Unable to setuid");
warn_unless_root();
return(1);
}
LOG("Successfully locked memory and setuid to %s\n", opts.setuid_user);
return(0);
}

View File

@ -90,6 +90,16 @@
<fileMode>0644</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
<!-- Include native libraries -->
<fileSet>
<directory>hbase-server/target/native</directory>
<outputDirectory>native</outputDirectory>
<fileMode>0755</fileMode>
<directoryMode>0755</directoryMode>
<includes>
<include>*.so</include>
</includes>
</fileSet>
<!-- This is only necessary until maven fixes the intra-project dependency bug
in maven 3.0. Until then, we have to include the test jars for sub-projects. When
fixed, the below dependencySet stuff is sufficient for pulling in the test jars as