27
"github.com/cubefs/cubefs/depends/bazil.org/fuse/fs"
28
"github.com/cubefs/cubefs/proto"
29
"github.com/cubefs/cubefs/util"
33
optFuseHttpPort = flag.String("p", "", "FUSE client http server port")
34
optDynamicUDS = flag.Bool("n", false, "use dynamic UDS file name")
35
optSuspend = flag.Bool("s", false, "suspend fuse")
36
optResume = flag.Bool("r", false, "resume fuse")
37
optDump = flag.String("d", "", "dump nodes/handles list files, <nodes list>,<handles list>")
38
optVersion = flag.Bool("v", false, "show version")
42
DefaultUDS string = "/tmp/CubeFS-fdstore.sock"
43
DefaultIP string = "127.0.0.1"
46
func createUDS() (listener net.Listener, err error) {
48
var addr *net.UnixAddr
51
sockAddr = fmt.Sprintf("/tmp/CubeFS-fdstore-%v.sock", os.Getpid())
55
fmt.Printf("sockaddr: %s\n", sockAddr)
57
if addr, err = net.ResolveUnixAddr("unix", sockAddr); err != nil {
58
fmt.Printf("cannot resolve unix addr: %v\n", err)
62
if listener, err = net.ListenUnix("unix", addr); err != nil {
63
fmt.Printf("cannot create unix domain: %v\n", err)
67
if err = os.Chmod(sockAddr, 0o666); err != nil {
68
fmt.Printf("failed to chmod socket file: %v\n", err)
76
func destroyUDS(listener net.Listener) {
77
sockAddr := listener.Addr().String()
82
func RecvFuseFdFromOldClient(udsListener net.Listener) (file *os.File, err error) {
86
if conn, err = udsListener.Accept(); err != nil {
87
fmt.Fprintf(os.Stderr, "unix domain accepts fail: %v\n", err)
92
fmt.Printf("a new connection accepted\n")
93
unixconn := conn.(*net.UnixConn)
94
if socket, err = unixconn.File(); err != nil {
95
fmt.Fprintf(os.Stderr, "failed to get socket file: %v\n", err)
100
if file, err = util.RecvFd(socket); err != nil {
101
fmt.Fprintf(os.Stderr, "failed to receive fd: %v\n", err)
105
fmt.Printf("Received file %s fd %v\n", file.Name(), file.Fd())
109
func SendFuseFdToNewClient(udsListener net.Listener, file *os.File) (err error) {
113
if conn, err = udsListener.Accept(); err != nil {
114
fmt.Fprintf(os.Stderr, "unix domain accepts fail: %v\n", err)
119
fmt.Printf("a new connection accepted\n")
120
unixconn := conn.(*net.UnixConn)
121
if socket, err = unixconn.File(); err != nil {
122
fmt.Fprintf(os.Stderr, "failed to get socket file: %v\n", err)
128
err = fmt.Errorf("no file is received")
129
fmt.Fprintf(os.Stderr, err.Error())
132
if err = util.SendFd(socket, file.Name(), file.Fd()); err != nil {
133
fmt.Fprintf(os.Stderr, "failed to send fd %v: %v\n", file.Fd(), err)
138
fmt.Printf("Sent file %s fd %v\n", file.Name(), file.Fd())
142
func SendSuspendRequest(port string, udsListener net.Listener) (err error) {
148
udsFilePath := udsListener.Addr().String()
150
url := fmt.Sprintf("http://%s:%s/suspend?sock=%s", DefaultIP, port, udsFilePath)
151
if req, err = http.NewRequest("POST", url, nil); err != nil {
152
fmt.Fprintf(os.Stderr, "Failed to get new request: %v\n", err)
155
req.Header.Set("Content-Type", "application/text")
157
client := http.DefaultClient
158
if resp, err = client.Do(req); err != nil {
159
fmt.Fprintf(os.Stderr, "Failed to post request: %v\n", err)
162
defer resp.Body.Close()
164
if data, err = io.ReadAll(resp.Body); err != nil {
165
fmt.Fprintf(os.Stderr, "Failed to read response: %v\n", err)
169
if resp.StatusCode == http.StatusOK {
170
fmt.Printf("\n==> %s\n==> Could restore cfs-client now with -r option.\n\n", string(data))
172
fmt.Printf("\n==> %s\n==> Status: %s\n\n", string(data), resp.Status)
173
return fmt.Errorf(resp.Status)
179
func WaitSuspendFinish(ch chan error) error {
184
func doSuspend(port string) error {
187
udsListener, err := createUDS()
189
fmt.Fprintf(os.Stderr, "doSuspend: failed to create UDS: %v\n", err)
192
defer destroyUDS(udsListener)
194
if err = SendSuspendRequest(port, udsListener); err != nil {
199
if fud, err = RecvFuseFdFromOldClient(udsListener); err != nil {
204
if err = SendFuseFdToNewClient(udsListener, fud); err != nil {
212
func SendResumeRequest(port string) (err error) {
219
url := fmt.Sprintf("http://%s:%s/resume", DefaultIP, port)
220
if req, err = http.NewRequest("POST", url, nil); err != nil {
221
fmt.Fprintf(os.Stderr, "Failed to get new request: %v\n", err)
224
req.Header.Set("Content-Type", "application/text")
226
client := http.DefaultClient
227
if resp, err = client.Do(req); err != nil {
228
fmt.Fprintf(os.Stderr, "Failed to post request: %v\n", err)
231
defer resp.Body.Close()
233
if data, err = io.ReadAll(resp.Body); err != nil {
234
fmt.Fprintf(os.Stderr, "Failed to read response: %v\n", err)
238
fmt.Printf("data: %s\n", string(data))
242
func doResume(port string) error {
243
err := SendResumeRequest(port)
247
func doDump(filePathes string) {
248
pathes := strings.Split(filePathes, ",")
249
if len(pathes) != 2 {
250
fmt.Fprintf(os.Stderr, "Invalid dump parameter '%s'\n", filePathes)
254
nodes := make([]*fs.ContextNode, 0)
255
handles := make([]*fs.ContextHandle, 0)
257
nodeListFile, err := os.OpenFile(pathes[0], os.O_RDONLY, 0o644)
259
fmt.Fprintf(os.Stderr, "failed to open nodes list file: %v\n", err)
262
defer nodeListFile.Close()
264
cnVer, err := fs.ReadVersion(nodeListFile)
266
fmt.Fprintf(os.Stderr, "failed to read nodes version: %v\n", err)
273
data []byte = make([]byte, unsafe.Sizeof(fs.ContextNode{}))
278
rsize, err = nodeListFile.Read(data)
279
if rsize == 0 || err == io.EOF {
283
if cnVer == fs.ContextNodeVersionV1 {
284
cn := fs.ContextNodeFromBytes(data)
285
for uint64(len(nodes)) < cn.NodeID {
286
nodes = append(nodes, nil)
291
fmt.Printf("[... skipped %d]\n", skipped)
294
fmt.Printf("[%d] snode(%s)\n", i, cn)
295
nodes = append(nodes, cn)
300
handleListFile, err := os.OpenFile(pathes[1], os.O_RDONLY, 0o644)
302
fmt.Fprintf(os.Stderr, "failed to open handles list file: %v\n", err)
305
defer handleListFile.Close()
307
chVer, err := fs.ReadVersion(handleListFile)
309
fmt.Fprintf(os.Stderr, "failed to read handles version: %v\n", err)
316
data []byte = make([]byte, unsafe.Sizeof(fs.ContextHandle{}))
320
rsize, err = handleListFile.Read(data)
321
if rsize == 0 || err == io.EOF {
326
if chVer == fs.ContextHandleVersionV1 {
327
ch := fs.ContextHandleFromBytes(data)
329
for uint64(len(handles)) < ch.HandleID {
330
handles = append(handles, nil)
335
fmt.Printf("[... skipped %d]\n", skipped)
338
if ch.NodeID > uint64(len(nodes)) {
339
fmt.Printf("[%d] shandle(handleid:%v nodeid:%v) [out of nodes range]\n",
340
i, ch.HandleID, ch.NodeID)
341
} else if nodes[ch.NodeID] == nil {
342
fmt.Printf("[%d] shandle(handleid:%v nodeid:%v) [no associated node]\n",
343
i, ch.HandleID, ch.NodeID)
345
fmt.Printf("[%d] shandle(handleid:%v nodeid:%v)\n", i, ch.HandleID, ch.NodeID)
348
handles = append(handles, ch)
360
fmt.Printf(proto.DumpVersion("fdstore"))
365
if *optFuseHttpPort == "" || (!*optSuspend && !*optResume) {
371
fmt.Printf("Fuse address: %s:%s\n", DefaultIP, *optFuseHttpPort)
375
} else if *optSuspend {
376
fmt.Printf("Do suspend ...\n")
377
err = doSuspend(*optFuseHttpPort)
378
} else if *optResume {
379
fmt.Printf("Do Resume ...\n")
380
err = doResume(*optFuseHttpPort)
384
fmt.Printf("Done FAILED\n")
388
fmt.Printf("Done Successfully\n")