2014-09-04 3 views
0

Я хочу изменить пространство имен в go. Когда я компилирую и запускаю код на C, он работает нормально, но в go я получил errno 22 в netns syscall. Любая идея, почему это может произойти?Изменение пространства имен linux в go

идут)

$ go build main.go ; ./main 
setns mnt: Invalid argument 
panic: -1 

goroutine 1 [running]: 
runtime.panic(0x423b80, 0xffffffffffffffff) 
    /usr/local/go/src/pkg/runtime/panic.c:266 +0xb6 
main.main() 
    main.go:81 +0x86 
$ 

с)

$ grep ^// main.go | sed 's/\/\///' | sed 's/__main/main/' > main.c; gcc main.c -o main; ./main 
$ 

Код ниже:

package main 

// 
// #define _GNU_SOURCE 
// #include <fcntl.h> 
// #include <sched.h> 
// #include <sys/syscall.h> 
// #include <sys/param.h> 
// #include <sys/mount.h> 
// #include <stdio.h> 
// #include <unistd.h> 
// 
// #define NETNS_RUN_DIR "/run/netns" 
// #define MNTNS_RUN_DIR "/run/mntns" 
// 
// #ifndef HAVE_SETNS 
// 
// int 
// setns(int fd, int nstype) { 
// #ifdef __NR_setns 
// return syscall(__NR_setns, fd, nstype); 
// #else 
// errno = ENOSYS; 
// return -1; 
// #endif 
// } 
// 
// #endif /* HAVE_SETNS */ 
// 
// 
// int 
// ChangeNamespace(char *name) 
// { 
// char net_path[MAXPATHLEN]; 
// char mnt_path[MAXPATHLEN]; 
// int fd; 
// 
// snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); 
// snprintf(mnt_path, sizeof(mnt_path), "%s/%s", MNTNS_RUN_DIR, name); 
// 
// fd = open(net_path, O_RDONLY); 
// if (fd < 0) { 
//  perror("open net"); 
//  return -1; 
// } 
// 
// if (setns(fd, 0) < 0) { 
//  perror("setns net"); 
//  return -1; 
// } 
// 
// fd = open(mnt_path, O_RDONLY); 
// if (fd < 0) { 
//  perror("open mnt"); 
//  return -1; 
// } 
// 
// if (setns(fd, 0) < 0) { 
//  perror("setns mnt"); 
//  return -1; 
// } 
// 
// return 0; 
// } 
// 
// int 
// __main(int argc, char *argv[]) { 
//  ChangeNamespace("ns"); 
//  return 0; 
// } 
// 
import "C" 
import "unsafe" 
func main() { 
    name := C.CString("ns") 
    defer C.free(unsafe.Pointer(name)) 
    i := int(C.ChangeNamespace(name)) 
    if i < 0 { 
     panic(i) 
    } 
} 
+0

Можете ли вы изменить строки 'perror()', чтобы строки говорили, какой вызов завершился неудачно? Просто «Недопустимый аргумент» недостаточно, чтобы объяснить, что происходит. (У меня такое ощущение, что это проблема с переносными стеками ...) – andlabs

+0

Вам также нужно вызвать 'runtime.LockOSThread', чтобы гарантировать, что setns вызывается из ожидаемого потока. – JimB

+0

Вы можете проверить, как docker обрабатывает это в [libcontainer/namespaces] (https://github.com/libcontainer/namespaces). Существует также, по крайней мере, 1 проблема с добавлением дополнительной поддержки предстоящему пакету go.sys: [# 8447] (https://code.google.com/p/go/issues/detail?id=8447) – JimB

ответ

5

Вы могли бы использовать что-то вроде этого пропуская ОЦП все вместе, я не могу проверить это прямо сейчас:

const (
    netNS = "/run/netns/" 
    mntNS = "/run/mntns/" 
) 
func ChangeNamespace(name string) error { 
    fd, err := syscall.Open(netNS+name, syscall.O_RDONLY, 0666) 
    if err != nil { 
     return err 
    } 
    defer syscall.Close(fd) 
    if _, _, err := syscall.RawSyscall(syscall.SYS_SETNS, uintptr(fd), 0, 0); err != nil { 
     return err 
    } 

    fd1, err := syscall.Open(mntNS+name, syscall.O_RDONLY, 0666) 
    if err != nil { 
     return err 
    } 
    defer syscall.Close(fd1) 
    if _, _, err := syscall.RawSyscall(syscall.SYS_SETNS, uintptr(fd1), 0, 0); err != nil { 
     return err 
    } 
    return nil 
} 
+0

Должно быть, я устал вчера при тестировании, но этот доцент решает проблему. По-прежнему такая же ошибка. – KrHubert

+0

@ixos, что говорит об ошибке? – OneOfOne

+0

Те же ошибки: «Неверный аргумент» на setns mnt – KrHubert

Смежные вопросы