mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-21 10:09:07 +00:00
Add 9pudfuse and fuserun.sh for testing remote FUSE file systems
This commit is contained in:
parent
7e8edd35cb
commit
c91006e6e8
@ -15,7 +15,7 @@ RUN \
|
||||
sfdisk lvm2 syslinux \
|
||||
openrc busybox-initscripts \
|
||||
alpine-conf \
|
||||
strace
|
||||
strace fuse
|
||||
|
||||
COPY etc /etc/
|
||||
|
||||
@ -24,6 +24,8 @@ COPY mkinitrd.sh /bin/
|
||||
|
||||
COPY packages/9pudc/9pudc /sbin/
|
||||
COPY packages/9pudc/etc /etc/
|
||||
COPY packages/9pudfuse/9pudfuse /sbin/
|
||||
COPY packages/9pudfuse/etc /etc/
|
||||
COPY packages/mdnstool/mdnstool /sbin/
|
||||
COPY packages/mdnstool/etc /etc/
|
||||
COPY packages/docker/docker /usr/bin/
|
||||
@ -62,6 +64,7 @@ RUN \
|
||||
rc-update add docker default && \
|
||||
rc-update add 9pinit default && \
|
||||
rc-update add 9pudc default && \
|
||||
rc-update add 9pudfuse default && \
|
||||
rc-update add mdnstool default && \
|
||||
rc-update add automount boot && \
|
||||
rc-update add diagnostics default && \
|
||||
|
@ -7,5 +7,7 @@ start()
|
||||
mount -t 9p -o trans=virtio,dfltuid=1001,dfltgid=50,version=9p2000 socket /Socket
|
||||
mkdir -p /Mac
|
||||
mount -t 9p -o trans=virtio,dfltuid=1001,dfltgid=50,version=9p2000.u plan9 /Mac
|
||||
eend 0
|
||||
mkdir -p /Transfuse
|
||||
mount -t 9p -o trans=virtio,dfltuid=1001,dfltgid=50,version=9p2000 fuse /Transfuse
|
||||
eend 0
|
||||
}
|
||||
|
1
alpine/packages/9pudfuse/.gitignore
vendored
Normal file
1
alpine/packages/9pudfuse/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
9pudfuse
|
6
alpine/packages/9pudfuse/.merlin
Normal file
6
alpine/packages/9pudfuse/.merlin
Normal file
@ -0,0 +1,6 @@
|
||||
PKG result
|
||||
PKG stringext
|
||||
PKG fd-send-recv
|
||||
|
||||
S .
|
||||
B .
|
17
alpine/packages/9pudfuse/Dockerfile
Normal file
17
alpine/packages/9pudfuse/Dockerfile
Normal file
@ -0,0 +1,17 @@
|
||||
FROM justincormack/alpine-pkgsrc-ocaml:latest
|
||||
|
||||
ENV \
|
||||
OPAMYES=true \
|
||||
CAML_LD_LIBRARY_PATH="/root/.opam/4.02.3/lib/stublibs:/usr/pkg/lib/ocaml/stublibs" \
|
||||
MANPATH="/root/.opam/4.02.3/man:" \
|
||||
PERL5LIB="/root/.opam/4.02.3/lib/perl5" \
|
||||
OCAML_TOPLEVEL_PATH="/root/.opam/4.02.3/lib/toplevel" \
|
||||
PATH=/root/.opam/4.02.3/bin:$PATH
|
||||
|
||||
RUN mkdir -p /ocaml/src/9pudfuse
|
||||
WORKDIR /ocaml/src/9pudfuse
|
||||
|
||||
COPY . /ocaml/src/9pudfuse
|
||||
RUN opam install result stringext fd-send-recv
|
||||
RUN ocamlbuild -tag debug -use-ocamlfind -package stringext,fd-send-recv,result fuse_socket_9p.native
|
||||
|
10
alpine/packages/9pudfuse/Makefile
Normal file
10
alpine/packages/9pudfuse/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
all: 9pudfuse
|
||||
|
||||
9pudfuse: Dockerfile fuse_socket_9p.ml
|
||||
docker build -t 9pudfuse:test .
|
||||
docker run 9pudfuse:test \
|
||||
cat /ocaml/src/9pudfuse/fuse_socket_9p.native > 9pudfuse
|
||||
chmod 755 9pudfuse
|
||||
|
||||
clean:
|
||||
rm -f 9pudfuse
|
163
alpine/packages/9pudfuse/fuse_socket_9p.ml
Normal file
163
alpine/packages/9pudfuse/fuse_socket_9p.ml
Normal file
@ -0,0 +1,163 @@
|
||||
|
||||
exception ReadClosed
|
||||
|
||||
let fusermount = "fusermount"
|
||||
let path = "/Transfuse"
|
||||
|
||||
module Log = struct
|
||||
let fatal fmt =
|
||||
Printf.ksprintf (fun s -> prerr_endline s; exit 1) fmt
|
||||
let error fmt =
|
||||
Printf.ksprintf (fun s -> prerr_endline s) fmt
|
||||
let info fmt =
|
||||
Printf.ksprintf (fun s -> prerr_endline s) fmt
|
||||
end
|
||||
|
||||
let events_path = path ^ "/events"
|
||||
|
||||
let try_fork caller_name =
|
||||
try
|
||||
Unix.fork ()
|
||||
with Unix.Unix_error (err,"fork",_) ->
|
||||
Log.fatal "%s fork failed: %s" caller_name (Unix.error_message err)
|
||||
|
||||
let check_status = function
|
||||
| Unix.WEXITED 0 -> Result.Ok ()
|
||||
| Unix.WEXITED k ->
|
||||
Result.Error ("exit code "^(string_of_int k))
|
||||
| Unix.WSIGNALED k ->
|
||||
Result.Error ("ocaml kill signal "^(string_of_int k))
|
||||
| Unix.WSTOPPED k ->
|
||||
Result.Error ("ocaml stop signal "^(string_of_int k))
|
||||
|
||||
let finally f at_end =
|
||||
let r = try f () with e -> (at_end (); raise e) in
|
||||
at_end ();
|
||||
r
|
||||
|
||||
let copy description dst src =
|
||||
let sz = 1 lsl 16 in
|
||||
let buf = Bytes.create sz in
|
||||
let pnum = ref 0 in
|
||||
let rec loop () =
|
||||
let n = Unix.read src buf 0 sz in
|
||||
(if n = 0 then raise ReadClosed);
|
||||
|
||||
let fd = Unix.(
|
||||
openfile ("/tmp/"^description^"_"^(string_of_int !pnum))
|
||||
[O_WRONLY; O_CREAT] 0o600) in
|
||||
let k = Unix.write fd buf 0 n in
|
||||
assert (k = n);
|
||||
Unix.close fd;
|
||||
incr pnum;
|
||||
|
||||
let written = Unix.write dst buf 0 n in
|
||||
(if n <> written
|
||||
then Log.error "copy of %s read %d but wrote %d" description n written);
|
||||
loop ()
|
||||
in
|
||||
try loop ()
|
||||
with
|
||||
| ReadClosed -> raise ReadClosed
|
||||
| e -> (Log.error "copy for %s failed" description; raise e)
|
||||
|
||||
let with_reader id f =
|
||||
let read_path = Printf.sprintf "%s/connections/%d/read" path id in
|
||||
let read_fd = Unix.(openfile read_path [O_RDONLY] 0o000) in
|
||||
try finally (fun () ->
|
||||
f read_path read_fd
|
||||
) (fun () ->
|
||||
Unix.close read_fd
|
||||
) with
|
||||
| ReadClosed -> exit 0
|
||||
|
||||
let with_writer id f =
|
||||
let write_path = Printf.sprintf "%s/connections/%d/write" path id in
|
||||
let write_fd = Unix.(openfile write_path [O_WRONLY] 0o000) in
|
||||
finally (fun () ->
|
||||
f write_path write_fd
|
||||
) (fun () ->
|
||||
Unix.close write_fd;
|
||||
Unix.unlink write_path
|
||||
)
|
||||
|
||||
let read_opts id = with_reader id (fun read_path read_fd ->
|
||||
let sz = 512 in
|
||||
let buf = Bytes.create sz in
|
||||
let n = Unix.read read_fd buf 0 sz in
|
||||
let opts = Stringext.split ~on:'\000' (Bytes.sub buf 0 n) in
|
||||
Array.of_list opts
|
||||
)
|
||||
|
||||
let get_fuse_sock opts =
|
||||
let wsock, rsock = Unix.(socketpair PF_UNIX SOCK_STREAM 0) in
|
||||
let wfd = Fd_send_recv.int_of_fd wsock in
|
||||
let opts = Array.append [|fusermount|] opts in
|
||||
let pid = Unix.(create_process_env fusermount opts
|
||||
[|"_FUSE_COMMFD="^(string_of_int wfd)|]
|
||||
stdin stdout stderr) in
|
||||
let _, status = Unix.waitpid [] pid in
|
||||
let () = Unix.(shutdown wsock SHUTDOWN_ALL) in
|
||||
match check_status status with
|
||||
| Result.Error str ->
|
||||
let opts = String.concat " " (Array.to_list opts) in
|
||||
Log.fatal "%s: %s" opts str
|
||||
| Result.Ok () ->
|
||||
(* We must read at least 1 byte, by POSIX! *)
|
||||
let _, _, fd = Fd_send_recv.recv_fd rsock "\000" 0 1 [] in
|
||||
let () = Unix.(shutdown rsock SHUTDOWN_ALL) in
|
||||
fd
|
||||
|
||||
(* readers fork into a new process *)
|
||||
let start_reader id fuse =
|
||||
match try_fork "start_reader" with
|
||||
| 0 -> (* child *)
|
||||
with_reader id (fun _read_path read_fd ->
|
||||
copy ("reader_"^string_of_int id) fuse read_fd
|
||||
)
|
||||
| _child_pid -> (* parent *)
|
||||
()
|
||||
|
||||
(* writers stay in the calling process *)
|
||||
let start_writer id fuse = with_writer id (fun write_path write_fd ->
|
||||
copy ("writer_"^string_of_int id) write_fd fuse
|
||||
)
|
||||
|
||||
let handle_connection id =
|
||||
Log.info "handle_connection %d" id;
|
||||
match try_fork "handle_connection" with
|
||||
| 0 -> (* child *)
|
||||
let opts = read_opts id in
|
||||
let fuse = get_fuse_sock opts in
|
||||
start_reader id fuse;
|
||||
begin try ignore (start_writer id fuse); exit 0
|
||||
with
|
||||
| e -> prerr_endline (Printexc.to_string e); exit 1
|
||||
end
|
||||
| _child_pid -> (* parent *)
|
||||
()
|
||||
|
||||
let connection_loop () =
|
||||
let events = Unix.(openfile events_path [O_RDONLY] 0o000) in
|
||||
(* 512 bytes is easily big enough to read a whole connection id *)
|
||||
let sz = 512 in
|
||||
let buf = Bytes.create sz in
|
||||
let rec recv () =
|
||||
begin try
|
||||
let n = Unix.read events buf 0 sz in
|
||||
let s = String.trim Bytes.(to_string (sub buf 0 n)) in
|
||||
let id = int_of_string s in
|
||||
handle_connection id;
|
||||
with
|
||||
| Unix.Unix_error (err,"read",path) ->
|
||||
Log.fatal "Error reading events file %s: %s"
|
||||
path (Unix.error_message err)
|
||||
| Failure "int_of_string" ->
|
||||
Log.fatal "Failed to parse integer connection id"
|
||||
end;
|
||||
recv ()
|
||||
in
|
||||
recv ()
|
||||
|
||||
;;
|
||||
connection_loop ()
|
@ -1,9 +1,11 @@
|
||||
all:
|
||||
$(MAKE) -C 9pudc
|
||||
$(MAKE) -C 9pudfuse
|
||||
$(MAKE) -C mdnstool
|
||||
$(MAKE) -C docker
|
||||
|
||||
clean:
|
||||
$(MAKE) -C 9pudc clean
|
||||
$(MAKE) -C 9pudfuse clean
|
||||
$(MAKE) -C mdnstool clean
|
||||
$(MAKE) -C docker clean
|
||||
|
26
xhyve/fuserun.sh
Executable file
26
xhyve/fuserun.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
KERNEL="../kernel/vmlinuz64"
|
||||
INITRD="../alpine/initrd.img"
|
||||
CMDLINE="earlyprintk=serial console=ttyS0 virtio_pci.force_legacy=1"
|
||||
|
||||
MEM="-m 1G"
|
||||
#SMP="-c 2"
|
||||
NET=""
|
||||
if (( $EUID != 0 )); then
|
||||
printf "Warning: not running as root will have no networking!\n\n"
|
||||
sleep 1
|
||||
else
|
||||
NET="-s 2:0,virtio-net"
|
||||
fi
|
||||
#IMG_CD="-s 3,ahci-cd,/somepath/somefile.iso"
|
||||
#IMG_HDD="-s 4,virtio-blk,/somepath/somefile.img"
|
||||
PCI_DEV="-s 0:0,hostbridge -s 31,lpc"
|
||||
RND="-s 5,virtio-rnd"
|
||||
FS="-s 6,virtio-9p,path=9pudfuse.sock,tag=fuse"
|
||||
LPC_DEV="-l com1,stdio"
|
||||
ACPI="-A"
|
||||
CLOCK="-u"
|
||||
#UUID="-U deadbeef-dead-dead-dead-deaddeafbeef"
|
||||
|
||||
build/xhyve $ACPI $MEM $SMP $PCI_DEV $LPC_DEV $NET $IMG_CD $IMG_HDD $RND $FS $UUID $CLOCK -f kexec,$KERNEL,$INITRD,"$CMDLINE"
|
Loading…
Reference in New Issue
Block a user