42
"github.com/cubefs/cubefs/blockcache/bcache"
43
cfs "github.com/cubefs/cubefs/client/fs"
44
"github.com/cubefs/cubefs/depends/bazil.org/fuse"
45
"github.com/cubefs/cubefs/depends/bazil.org/fuse/fs"
46
"github.com/cubefs/cubefs/proto"
47
"github.com/cubefs/cubefs/sdk/master"
48
"github.com/cubefs/cubefs/util"
49
"github.com/cubefs/cubefs/util/auditlog"
50
"github.com/cubefs/cubefs/util/buf"
51
"github.com/cubefs/cubefs/util/config"
52
"github.com/cubefs/cubefs/util/errors"
53
"github.com/cubefs/cubefs/util/exporter"
54
"github.com/cubefs/cubefs/util/log"
55
"github.com/cubefs/cubefs/util/stat"
56
sysutil "github.com/cubefs/cubefs/util/sys"
57
"github.com/cubefs/cubefs/util/ump"
58
"github.com/jacobsa/daemonize"
59
_ "go.uber.org/automaxprocs"
63
MaxReadAhead = 512 * 1024
65
defaultRlimit uint64 = 1024000
67
UpdateConfInterval = 2 * time.Minute
74
LoggerPrefix = "client"
75
LoggerOutput = "output.log"
77
ModuleName = "fuseclient"
78
ConfigKeyExporterPort = "exporterKey"
80
ControlCommandSetRate = "/rate/set"
81
ControlCommandGetRate = "/rate/get"
82
ControlCommandFreeOSMemory = "/debug/freeosmemory"
83
ControlCommandSuspend = "/suspend"
84
ControlCommandResume = "/resume"
87
DefaultIP = "127.0.0.1"
88
DynamicUDSNameFormat = "/tmp/CubeFS-fdstore-%v.sock"
89
DefaultUDSName = "/tmp/CubeFS-fdstore.sock"
91
DefaultLogPath = "/var/log/cubefs"
95
configFile = flag.String("c", "", "FUSE client config file")
96
configVersion = flag.Bool("v", false, "show version")
97
configForeground = flag.Bool("f", false, "run foreground")
98
configDynamicUDSName = flag.Bool("n", false, "dynamic unix domain socket filename")
99
configRestoreFuse = flag.Bool("r", false, "restore FUSE instead of mounting")
100
configRestoreFuseUDS = flag.String("s", "", "restore socket addr")
101
configFuseHttpPort = flag.String("p", "", "fuse http service port")
104
var GlobalMountOptions []proto.MountOption
107
GlobalMountOptions = proto.NewMountOptions()
108
proto.InitMountOptions(GlobalMountOptions)
111
func createUDS(sockAddr string) (listener net.Listener, err error) {
112
var addr *net.UnixAddr
114
log.LogInfof("sockaddr: %s\n", sockAddr)
117
if addr, err = net.ResolveUnixAddr("unix", sockAddr); err != nil {
118
log.LogErrorf("cannot resolve unix addr: %v\n", err)
122
if listener, err = net.ListenUnix("unix", addr); err != nil {
123
log.LogErrorf("cannot create unix domain: %v\n", err)
127
if err = os.Chmod(sockAddr, 0o666); err != nil {
128
log.LogErrorf("failed to chmod socket file: %v\n", err)
136
func destroyUDS(listener net.Listener) {
137
sockAddr := listener.Addr().String()
142
func recvFuseFdFromOldClient(udsListener net.Listener) (file *os.File, err error) {
146
if conn, err = udsListener.Accept(); err != nil {
147
log.LogErrorf("unix domain accepts fail: %v\n", err)
152
log.LogInfof("a new connection accepted\n")
153
unixconn := conn.(*net.UnixConn)
154
if socket, err = unixconn.File(); err != nil {
155
log.LogErrorf("failed to get socket file: %v\n", err)
160
if file, err = util.RecvFd(socket); err != nil {
161
log.LogErrorf("failed to receive fd: %v\n", err)
165
log.LogInfof("Received file %s fd %v\n", file.Name(), file.Fd())
169
func sendSuspendRequest(port string, udsListener net.Listener) (err error) {
175
udsFilePath := udsListener.Addr().String()
177
url := fmt.Sprintf("http://%s:%s/suspend?sock=%s", DefaultIP, port, udsFilePath)
178
if req, err = http.NewRequest("POST", url, nil); err != nil {
179
log.LogErrorf("Failed to get new request: %v\n", err)
182
req.Header.Set("Content-Type", "application/text")
184
client := http.DefaultClient
185
client.Timeout = 120 * time.Second
186
if resp, err = client.Do(req); err != nil {
187
log.LogErrorf("Failed to post request: %v\n", err)
190
defer resp.Body.Close()
192
if data, err = io.ReadAll(resp.Body); err != nil {
193
log.LogErrorf("Failed to read response: %v\n", err)
197
if resp.StatusCode == http.StatusOK {
198
log.LogInfof("\n==> %s\n==> Could restore cfs-client now with -r option.\n\n", string(data))
200
log.LogErrorf("\n==> %s\n==> Status: %s\n\n", string(data), resp.Status)
201
return fmt.Errorf(resp.Status)
207
func sendResumeRequest(port string) (err error) {
214
url := fmt.Sprintf("http://%s:%s/resume", DefaultIP, port)
215
if req, err = http.NewRequest("POST", url, nil); err != nil {
216
log.LogErrorf("Failed to get new request: %v\n", err)
219
req.Header.Set("Content-Type", "application/text")
221
client := http.DefaultClient
222
if resp, err = client.Do(req); err != nil {
223
log.LogErrorf("Failed to post request: %v\n", err)
226
defer resp.Body.Close()
228
if data, err = io.ReadAll(resp.Body); err != nil {
229
log.LogErrorf("Failed to read response: %v\n", err)
233
log.LogInfof("data: %s\n", string(data))
237
func doSuspend(uds string, port string) (*os.File, error) {
240
udsListener, err := createUDS(uds)
242
log.LogErrorf("doSuspend: failed to create UDS: %v\n", err)
245
defer destroyUDS(udsListener)
247
if err = sendSuspendRequest(port, udsListener); err != nil {
248
sendResumeRequest(port)
252
if fud, err = recvFuseFdFromOldClient(udsListener); err != nil {
253
sendResumeRequest(port)
264
fmt.Print(proto.DumpVersion(Role))
268
if !*configForeground {
269
if err := startDaemon(); err != nil {
270
fmt.Printf("Mount failed: %v\n", err)
281
cfg, _ := config.LoadConfigFile(*configFile)
282
opt, err := parseMountOption(cfg)
284
err = errors.NewErrorf("parse mount opt failed: %v\n", err)
286
daemonize.SignalOutcome(err)
290
for retry := 0; retry < MasterRetrys; retry++ {
291
err = loadConfFromMaster(opt)
293
time.Sleep(5 * time.Second * time.Duration(retry+1))
299
err = errors.NewErrorf("parse mount opt from master failed: %v\n", err)
301
daemonize.SignalOutcome(err)
306
runtime.GOMAXPROCS(int(opt.MaxCPUs))
310
level := parseLogLevel(opt.Loglvl)
311
_, err = log.InitLog(opt.Logpath, opt.Volname, level, nil, log.DefaultLogLeftSpaceLimit)
313
err = errors.NewErrorf("Init log dir fail: %v\n", err)
315
daemonize.SignalOutcome(err)
320
if _, err = os.Stat(opt.MountPoint); err != nil {
321
if err = os.Mkdir(opt.MountPoint, os.ModePerm); err != nil {
322
err = errors.NewErrorf("Init.MountPoint mkdir failed error %v\n", err)
328
_, err = stat.NewStatistic(opt.Logpath, LoggerPrefix, int64(stat.DefaultStatLogSize),
329
stat.DefaultTimeOutUs, true)
331
err = errors.NewErrorf("Init stat log fail: %v\n", err)
333
daemonize.SignalOutcome(err)
339
_, err = auditlog.InitAuditWithPrefix(opt.Logpath, LoggerPrefix, int64(auditlog.DefaultAuditLogSize),
340
auditlog.NewAuditPrefix(opt.Master, opt.Volname, opt.SubDir, opt.MountPoint))
342
err = errors.NewErrorf("Init audit log fail: %v\n", err)
344
daemonize.SignalOutcome(err)
349
proto.InitBufferPool(opt.BuffersTotalLimit)
350
if proto.IsCold(opt.VolType) {
351
buf.InitCachePool(opt.EbsBlockSize)
353
if opt.EnableBcache {
354
buf.InitbCachePool(bcache.MaxBlockSize)
356
outputFilePath := path.Join(opt.Logpath, LoggerPrefix, LoggerOutput)
357
outputFile, err := os.OpenFile(outputFilePath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0o666)
359
err = errors.NewErrorf("Open output file failed: %v\n", err)
361
daemonize.SignalOutcome(err)
368
syslog.SetOutput(outputFile)
370
if *configRestoreFuse {
371
syslog.Println("NeedAfterAlloc restore fuse")
372
opt.NeedRestoreFuse = true
375
syslog.Println(proto.DumpVersion(Role))
376
syslog.Println("*** Final Mount Options ***")
377
for _, o := range GlobalMountOptions {
380
syslog.Println("*** End ***")
382
changeRlimit(defaultRlimit)
384
if err = sysutil.RedirectFD(int(outputFile.Fd()), int(os.Stderr.Fd())); err != nil {
385
err = errors.NewErrorf("Redirect fd failed: %v\n", err)
387
daemonize.SignalOutcome(err)
391
registerInterceptedSignal(opt.MountPoint)
392
for retry := 0; retry < MasterRetrys; retry++ {
393
err = checkPermission(opt)
395
time.Sleep(5 * time.Second * time.Duration(retry+1))
401
err = errors.NewErrorf("check permission failed: %v", err)
404
_ = daemonize.SignalOutcome(err)
409
if opt.NeedRestoreFuse && *configFuseHttpPort != "" {
410
log.LogInfof("Suspend/Restore by self\n")
412
if *configDynamicUDSName {
413
udsName = fmt.Sprintf(DynamicUDSNameFormat, os.Getpid())
415
udsName = DefaultUDSName
421
if fud, err = doSuspend(udsName, *configFuseHttpPort); err != nil {
422
log.LogErrorf("Failed to tell old cfs-client to suspend: %v\n", err)
423
syslog.Printf("Error: Failed to tell old cfs-client to suspend: %v\n", err)
425
_ = daemonize.SignalOutcome(err)
430
fsConn, super, err := mount(opt)
432
err = errors.NewErrorf("mount failed: %v", err)
435
_ = daemonize.SignalOutcome(err)
438
_ = daemonize.SignalOutcome(nil)
443
syslog.Printf("enable bcache %v", opt.EnableBcache)
445
if cfg.GetString(exporter.ConfigKeyPushAddr) == "" {
446
pushAddr, err := getPushAddrFromMaster(opt.Master)
447
if err == nil && pushAddr != "" {
448
syslog.Printf("use remote push addr %v", pushAddr)
449
cfg.SetString(exporter.ConfigKeyPushAddr, pushAddr)
453
exporter.Init(ModuleName, cfg)
454
exporter.RegistConsul(super.ClusterName(), ModuleName, cfg)
456
err = log.OutputPid(opt.Logpath, ModuleName)
459
syslog.Printf("output pid err(%v)", err)
463
if opt.NeedRestoreFuse {
465
if *configRestoreFuseUDS == "" {
466
super.SetSockAddr(DefaultUDSName)
468
super.SetSockAddr(*configRestoreFuseUDS)
471
fsConn.SetFuseDevFile(fud)
475
if err = fs.Serve(fsConn, super, opt); err != nil {
477
syslog.Printf("fs Serve returns err(%v)", err)
482
if fsConn.MountError != nil {
484
syslog.Printf("fs Serve returns err(%v)\n", err)
489
func getPushAddrFromMaster(masterAddr string) (addr string, err error) {
490
mc := master.NewMasterClientFromString(masterAddr, false)
491
addr, err = mc.AdminAPI().GetMonitorPushAddr()
495
func startDaemon() error {
496
cmdPath, err := os.Executable()
498
return fmt.Errorf("startDaemon failed: cannot get absolute command path, err(%v)", err)
501
if len(os.Args) <= 1 {
502
return fmt.Errorf("startDaemon failed: cannot use null arguments")
505
args := []string{"-f"}
506
args = append(args, os.Args[1:]...)
508
if *configFile != "" {
509
configPath, err := filepath.Abs(*configFile)
511
return fmt.Errorf("startDaemon failed: cannot get absolute command path of config file(%v) , err(%v)", *configFile, err)
513
for i := 0; i < len(args); i++ {
516
args[i+1] = configPath
526
env = append(env, "GODEBUG=madvdontneed=1")
527
err = daemonize.Run(cmdPath, args, env, os.Stdout)
529
return fmt.Errorf("startDaemon failed: daemon start failed, cmd(%v) args(%v) env(%v) err(%v)\n", cmdPath, args, env, err)
535
func waitListenAndServe(statusCh chan error, addr string, handler http.Handler) {
538
var interval int = (1 << 17) - 1
539
var listener net.Listener
547
timeout := time.Now().Add(time.Minute)
549
if listener, err = net.Listen("tcp", addr); err == nil {
554
if strings.Contains(err.Error(), "bind: address already in use") {
555
if loop&interval == 0 {
556
syslog.Printf("address %v is still in use\n", addr)
562
if time.Now().After(timeout) {
563
msg := fmt.Sprintf("address %v is still in use after "+
564
"timeout, choose port automatically\n", addr)
566
msg = "Warning: " + msg
567
daemonize.StatusWriter.Write([]byte(msg))
573
syslog.Printf("address %v wait loop %v\n", addr, loop)
576
ipport := strings.Split(addr, ":")
577
addr = ipport[0] + ":0"
578
listener, err = net.Listen("tcp", addr)
587
msg := fmt.Sprintf("Start pprof with port: %v\n",
588
listener.Addr().(*net.TCPAddr).Port)
591
msg = "Warning: " + msg
592
daemonize.StatusWriter.Write([]byte(msg))
594
http.Serve(listener, handler)
598
func mount(opt *proto.MountOptions) (fsConn *fuse.Conn, super *cfs.Super, err error) {
599
super, err = cfs.NewSuper(opt)
601
log.LogError(errors.Stack(err))
605
http.HandleFunc(ControlCommandSetRate, super.SetRate)
606
http.HandleFunc(ControlCommandGetRate, super.GetRate)
607
http.HandleFunc(log.SetLogLevelPath, log.SetLogLevel)
608
http.HandleFunc(ControlCommandFreeOSMemory, freeOSMemory)
609
http.HandleFunc(log.GetLogPath, log.GetLog)
610
http.HandleFunc(ControlCommandSuspend, super.SetSuspend)
611
http.HandleFunc(ControlCommandResume, super.SetResume)
613
http.HandleFunc(auditlog.EnableAuditLogReqPath, super.EnableAuditLog)
614
http.HandleFunc(auditlog.DisableAuditLogReqPath, auditlog.DisableAuditLog)
615
http.HandleFunc(auditlog.SetAuditLogBufSizeReqPath, auditlog.ResetWriterBuffSize)
617
statusCh := make(chan error)
618
pprofAddr := ":" + opt.Profport
620
pprofAddr = "127.0.0.1:" + opt.Profport
622
mainMux := http.NewServeMux()
623
mux := http.NewServeMux()
624
mux.Handle("/debug/pprof", http.HandlerFunc(pprof.Index))
625
mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
626
mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
627
mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
628
mux.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))
629
mux.Handle("/debug/", http.HandlerFunc(pprof.Index))
630
mainHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
631
if strings.HasPrefix(req.URL.Path, "/debug/") {
632
mux.ServeHTTP(w, req)
634
http.DefaultServeMux.ServeHTTP(w, req)
637
mainMux.Handle("/", mainHandler)
639
go waitListenAndServe(statusCh, pprofAddr, mainMux)
640
if err = <-statusCh; err != nil {
641
daemonize.SignalOutcome(err)
646
mc := master.NewMasterClientFromString(opt.Master, false)
647
t := time.NewTicker(UpdateConfInterval)
650
log.LogDebugf("UpdateVolConf: load conf from master")
651
var volumeInfo *proto.SimpleVolView
652
volumeInfo, err = mc.AdminAPI().GetVolumeSimpleInfo(opt.Volname)
654
log.LogErrorf("UpdateVolConf: get vol info from master failed, err %s", err.Error())
655
if err == proto.ErrVolNotExists {
657
daemonize.SignalOutcome(err)
662
if volumeInfo.Status == proto.VolStatusMarkDelete {
663
err = fmt.Errorf("vol [%s] has been deleted, stop client", volumeInfo.Name)
666
daemonize.SignalOutcome(err)
669
super.SetTransaction(volumeInfo.EnableTransaction, volumeInfo.TxTimeout, volumeInfo.TxConflictRetryNum, volumeInfo.TxConflictRetryInterval)
670
if proto.IsCold(opt.VolType) {
671
super.CacheAction = volumeInfo.CacheAction
672
super.CacheThreshold = volumeInfo.CacheThreshold
673
super.EbsBlockSize = volumeInfo.ObjBlockSize
678
if err = ump.InitUmp(fmt.Sprintf("%v_%v", super.ClusterName(), ModuleName), opt.UmpDatadir); err != nil {
682
options := []fuse.MountOption{
684
fuse.MaxReadahead(MaxReadAhead),
686
fuse.AutoInvalData(opt.AutoInvalData),
687
fuse.FSName(opt.FileSystemName),
688
fuse.Subtype("cubefs"),
690
fuse.VolumeName(opt.FileSystemName),
691
fuse.RequestTimeout(opt.RequestTimeout),
695
options = append(options, fuse.ReadOnly())
699
options = append(options, fuse.WritebackCache())
702
if opt.EnablePosixACL {
703
options = append(options, fuse.PosixACL())
704
options = append(options, fuse.DefaultPermissions())
707
if opt.EnableUnixPermission {
708
options = append(options, fuse.DefaultPermissions())
711
fsConn, err = fuse.Mount(opt.MountPoint, opt.NeedRestoreFuse, options...)
715
func registerInterceptedSignal(mnt string) {
716
sigC := make(chan os.Signal, 1)
717
signal.Notify(sigC, syscall.SIGINT, syscall.SIGTERM)
720
syslog.Printf("Killed due to a received signal (%v)\n", sig)
726
func parseMountOption(cfg *config.Config) (*proto.MountOptions, error) {
728
opt := new(proto.MountOptions)
730
proto.ParseMountOptions(GlobalMountOptions, cfg)
732
rawmnt := GlobalMountOptions[proto.MountPoint].GetString()
733
opt.MountPoint, err = filepath.Abs(rawmnt)
735
return nil, errors.Trace(err, "invalide mount point (%v) ", rawmnt)
737
opt.Volname = GlobalMountOptions[proto.VolName].GetString()
738
opt.Owner = GlobalMountOptions[proto.Owner].GetString()
739
opt.Master = GlobalMountOptions[proto.Master].GetString()
740
logPath := GlobalMountOptions[proto.LogDir].GetString()
741
if len(logPath) == 0 {
742
logPath = DefaultLogPath
744
opt.Logpath = path.Join(logPath, LoggerPrefix)
745
opt.Loglvl = GlobalMountOptions[proto.LogLevel].GetString()
746
opt.Profport = GlobalMountOptions[proto.ProfPort].GetString()
747
opt.LocallyProf = GlobalMountOptions[proto.LocallyProf].GetBool()
748
opt.IcacheTimeout = GlobalMountOptions[proto.IcacheTimeout].GetInt64()
749
opt.LookupValid = GlobalMountOptions[proto.LookupValid].GetInt64()
750
opt.AttrValid = GlobalMountOptions[proto.AttrValid].GetInt64()
751
opt.ReadRate = GlobalMountOptions[proto.ReadRate].GetInt64()
752
opt.WriteRate = GlobalMountOptions[proto.WriteRate].GetInt64()
753
opt.EnSyncWrite = GlobalMountOptions[proto.EnSyncWrite].GetInt64()
754
opt.AutoInvalData = GlobalMountOptions[proto.AutoInvalData].GetInt64()
755
opt.UmpDatadir = GlobalMountOptions[proto.WarnLogDir].GetString()
756
opt.Rdonly = GlobalMountOptions[proto.Rdonly].GetBool()
757
opt.WriteCache = GlobalMountOptions[proto.WriteCache].GetBool()
758
opt.KeepCache = GlobalMountOptions[proto.KeepCache].GetBool()
759
opt.FollowerRead = GlobalMountOptions[proto.FollowerRead].GetBool()
760
opt.Authenticate = GlobalMountOptions[proto.Authenticate].GetBool()
761
if opt.Authenticate {
762
opt.TicketMess.ClientKey = GlobalMountOptions[proto.ClientKey].GetString()
763
ticketHostConfig := GlobalMountOptions[proto.TicketHost].GetString()
764
ticketHosts := strings.Split(ticketHostConfig, ",")
765
opt.TicketMess.TicketHosts = ticketHosts
766
opt.TicketMess.EnableHTTPS = GlobalMountOptions[proto.EnableHTTPS].GetBool()
767
if opt.TicketMess.EnableHTTPS {
768
opt.TicketMess.CertFile = GlobalMountOptions[proto.CertFile].GetString()
771
opt.AccessKey = GlobalMountOptions[proto.AccessKey].GetString()
772
opt.SecretKey = GlobalMountOptions[proto.SecretKey].GetString()
773
opt.DisableDcache = GlobalMountOptions[proto.DisableDcache].GetBool()
774
opt.SubDir = GlobalMountOptions[proto.SubDir].GetString()
775
opt.FsyncOnClose = GlobalMountOptions[proto.FsyncOnClose].GetBool()
776
opt.MaxCPUs = GlobalMountOptions[proto.MaxCPUs].GetInt64()
777
opt.EnableXattr = GlobalMountOptions[proto.EnableXattr].GetBool()
778
opt.NearRead = GlobalMountOptions[proto.NearRead].GetBool()
779
opt.EnablePosixACL = GlobalMountOptions[proto.EnablePosixACL].GetBool()
780
opt.EnableSummary = GlobalMountOptions[proto.EnableSummary].GetBool()
781
opt.EnableUnixPermission = GlobalMountOptions[proto.EnableUnixPermission].GetBool()
782
opt.ReadThreads = GlobalMountOptions[proto.ReadThreads].GetInt64()
783
opt.WriteThreads = GlobalMountOptions[proto.WriteThreads].GetInt64()
785
opt.BcacheDir = GlobalMountOptions[proto.BcacheDir].GetString()
787
opt.BcacheFilterFiles = GlobalMountOptions[proto.BcacheFilterFiles].GetString()
788
opt.BcacheBatchCnt = GlobalMountOptions[proto.BcacheBatchCnt].GetInt64()
789
opt.BcacheCheckIntervalS = GlobalMountOptions[proto.BcacheCheckIntervalS].GetInt64()
790
if _, err := os.Stat(bcache.UnixSocketPath); err == nil && opt.BcacheDir != "" {
791
opt.EnableBcache = true
794
opt.EnableBcache = GlobalMountOptions[proto.EnableBcache].GetBool()
796
verReadSeq := GlobalMountOptions[proto.SnapshotReadVerSeq].GetInt64()
797
if verReadSeq == -1 {
798
opt.VerReadSeq = math.MaxUint64
800
opt.VerReadSeq = uint64(verReadSeq)
802
log.LogDebugf("oonfig.verReadSeq %v opt.VerReadSeq %v", verReadSeq, opt.VerReadSeq)
804
opt.MetaSendTimeout = GlobalMountOptions[proto.MetaSendTimeout].GetInt64()
806
opt.BuffersTotalLimit = GlobalMountOptions[proto.BuffersTotalLimit].GetInt64()
807
opt.MetaSendTimeout = GlobalMountOptions[proto.MetaSendTimeout].GetInt64()
808
opt.MaxStreamerLimit = GlobalMountOptions[proto.MaxStreamerLimit].GetInt64()
809
opt.EnableAudit = GlobalMountOptions[proto.EnableAudit].GetBool()
810
opt.RequestTimeout = GlobalMountOptions[proto.RequestTimeout].GetInt64()
811
opt.MinWriteAbleDataPartitionCnt = int(GlobalMountOptions[proto.MinWriteAbleDataPartitionCnt].GetInt64())
812
opt.FileSystemName = GlobalMountOptions[proto.FileSystemName].GetString()
814
if opt.MountPoint == "" || opt.Volname == "" || opt.Owner == "" || opt.Master == "" {
815
return nil, errors.New(fmt.Sprintf("invalid config file: lack of mandatory fields, mountPoint(%v), volName(%v), owner(%v), masterAddr(%v)", opt.MountPoint, opt.Volname, opt.Owner, opt.Master))
818
if opt.BuffersTotalLimit < 0 {
819
return nil, errors.New(fmt.Sprintf("invalid fields, BuffersTotalLimit(%v) must larger or equal than 0", opt.BuffersTotalLimit))
822
if opt.FileSystemName == "" {
823
opt.FileSystemName = "cubefs-" + opt.Volname
829
func checkPermission(opt *proto.MountOptions) (err error) {
830
mc := master.NewMasterClientFromString(opt.Master, false)
831
localIP, _ := ump.GetLocalIpAddr()
832
if info, err := mc.UserAPI().AclOperation(opt.Volname, localIP, util.AclCheckIP); err != nil || !info.OK {
834
return proto.ErrNoAclPermission
837
if opt.AccessKey != "" {
838
var userInfo *proto.UserInfo
839
if userInfo, err = mc.UserAPI().GetAKInfo(opt.AccessKey); err != nil {
842
if userInfo.SecretKey != opt.SecretKey {
843
err = proto.ErrNoPermission
846
policy := userInfo.Policy
847
if policy.IsOwn(opt.Volname) {
850
if policy.IsAuthorized(opt.Volname, opt.SubDir, proto.POSIXWriteAction) &&
851
policy.IsAuthorized(opt.Volname, opt.SubDir, proto.POSIXReadAction) {
854
if policy.IsAuthorized(opt.Volname, opt.SubDir, proto.POSIXReadAction) &&
855
!policy.IsAuthorized(opt.Volname, opt.SubDir, proto.POSIXWriteAction) {
859
err = proto.ErrNoPermission
865
func parseLogLevel(loglvl string) log.Level {
867
switch strings.ToLower(loglvl) {
869
level = log.DebugLevel
871
level = log.InfoLevel
873
level = log.WarnLevel
875
level = log.ErrorLevel
877
level = log.ErrorLevel
882
func changeRlimit(val uint64) {
883
rlimit := &syscall.Rlimit{Max: val, Cur: val}
884
err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimit)
886
syslog.Printf("Failed to set rlimit to %v \n", val)
888
syslog.Printf("Successfully set rlimit to %v \n", val)
892
func freeOSMemory(w http.ResponseWriter, r *http.Request) {
896
func loadConfFromMaster(opt *proto.MountOptions) (err error) {
897
mc := master.NewMasterClientFromString(opt.Master, false)
898
var volumeInfo *proto.SimpleVolView
899
volumeInfo, err = mc.AdminAPI().GetVolumeSimpleInfo(opt.Volname)
903
opt.VolType = volumeInfo.VolType
904
opt.EbsBlockSize = volumeInfo.ObjBlockSize
905
opt.CacheAction = volumeInfo.CacheAction
906
opt.CacheThreshold = volumeInfo.CacheThreshold
907
opt.EnableQuota = volumeInfo.EnableQuota
908
opt.EnableTransaction = volumeInfo.EnableTransaction
909
opt.TxTimeout = volumeInfo.TxTimeout
910
opt.TxConflictRetryNum = volumeInfo.TxConflictRetryNum
911
opt.TxConflictRetryInterval = volumeInfo.TxConflictRetryInterval
913
var clusterInfo *proto.ClusterInfo
914
clusterInfo, err = mc.AdminAPI().GetClusterInfo()
918
opt.EbsEndpoint = clusterInfo.EbsAddr
919
opt.EbsServicePath = clusterInfo.ServicePath