func TestGetrlimit(t *testing.T) { var rlim unix.Rlimit err := unix.Getrlimit(unix.RLIMIT_AS, &rlim) if err != nil { t.Fatalf("Getrlimit: %v", err) } }
// Choose a reasonable value for ServerConfig.TempDirLimitNumFiles based on // process limits. func ChooseTempDirLimitNumFiles() (limit int) { // Ask what the process's limit on open files is. Use a default on error. var rlimit unix.Rlimit err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit) if err != nil { const defaultLimit = 512 log.Println( "Warning: failed to query RLIMIT_NOFILE. Using default "+ "file count limit of %d", defaultLimit) limit = defaultLimit return } // Heuristic: Use about 75% of the limit. limit64 := rlimit.Cur/2 + rlimit.Cur/4 // But not too large. const reasonableLimit = 1 << 15 if limit64 > reasonableLimit { limit64 = reasonableLimit } limit = int(limit64) return }
func nfilesSet(n int) int { var rlimit unix.Rlimit _ = unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit) if n <= 0 { rlimit.Cur = rlimit.Max } else if uint64(n) < rlimit.Max { rlimit.Cur = uint64(n) } _ = unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit) return nfilesGet() }
func TestRlimit(t *testing.T) { var rlimit, zero unix.Rlimit err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit) if err != nil { t.Fatalf("Getrlimit: save failed: %v", err) } if zero == rlimit { t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit) } set := rlimit set.Cur = set.Max - 1 err = unix.Setrlimit(unix.RLIMIT_NOFILE, &set) if err != nil { t.Fatalf("Setrlimit: set failed: %#v %v", set, err) } var get unix.Rlimit err = unix.Getrlimit(unix.RLIMIT_NOFILE, &get) if err != nil { t.Fatalf("Getrlimit: get failed: %v", err) } set = rlimit set.Cur = set.Max - 1 if set != get { // Seems like Darwin requires some privilege to // increase the soft limit of rlimit sandbox, though // Setrlimit never reports an error. switch runtime.GOOS { case "darwin": default: t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get) } } err = unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit) if err != nil { t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err) } }
func nfilesGet() int { var rlimit unix.Rlimit _ = unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit) return int(rlimit.Cur) }
// Mount the file system based on the supplied arguments, returning a // fuse.MountedFileSystem that can be joined to wait for unmounting. // // In main, set flagSet to flag.CommandLine and pass in os.Args[1:]. In a test, // pass in a virgin flag set and test arguments. // // Promises to pass on flag.ErrHelp from FlagSet.Parse. func mount( ctx context.Context, args []string, flagSet *flag.FlagSet, conn gcs.Conn) (mfs *fuse.MountedFileSystem, err error) { // Populate and parse flags. flags := populateFlagSet(flagSet) err = flagSet.Parse(args) if err != nil { // Special case: don't mangle ErrHelp. if err != flag.ErrHelp { err = fmt.Errorf("Parsing flags: %v", err) } return } // Extract positional arguments. if flagSet.NArg() != 2 { flagSet.Usage() err = errors.New("Incorrect usage") return } bucketName := flagSet.Arg(0) mountPoint := flagSet.Arg(1) // Sanity check: make sure the temporary directory exists and is writable // currently. This gives a better user experience than harder to debug EIO // errors when reading files in the future. if flags.TempDir != "" { var f *os.File f, err = fsutil.AnonymousFile(flags.TempDir) f.Close() if err != nil { err = fmt.Errorf( "Error writing to temporary directory (%q); are you sure it exists "+ "with the correct permissions?", err.Error()) return } } // The file leaser used by the file system sizes its limit on number of // temporary files based on the process's rlimit. If this is too low, we'll // throw away cached content unnecessarily often. This is particularly a // problem on OS X, which has a crazy low default limit (256 as of OS X // 10.10.3). So print a warning if the limit is low. var rlimit unix.Rlimit if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err == nil { const reasonableLimit = 4096 if rlimit.Cur < reasonableLimit { log.Printf( "Warning: low file rlimit of %d will cause cached content to be "+ "frequently evicted. Consider raising with `ulimit -n`.", rlimit.Cur) } } // Choose UID and GID. uid, gid, err := perms.MyUserAndGroup() if err != nil { err = fmt.Errorf("MyUserAndGroup: %v", err) return } if flags.Uid >= 0 { uid = uint32(flags.Uid) } if flags.Gid >= 0 { gid = uint32(flags.Gid) } // Set up the bucket. bucket, err := setUpBucket( ctx, flags, conn, bucketName) if err != nil { err = fmt.Errorf("setUpBucket: %v", err) return } // Create a file system server. serverCfg := &fs.ServerConfig{ Clock: timeutil.RealClock(), Bucket: bucket, TempDir: flags.TempDir, TempDirLimitNumFiles: fs.ChooseTempDirLimitNumFiles(), TempDirLimitBytes: flags.TempDirLimit, GCSChunkSize: flags.GCSChunkSize, ImplicitDirectories: flags.ImplicitDirs, DirTypeCacheTTL: flags.TypeCacheTTL, Uid: uid, Gid: gid, FilePerms: os.FileMode(flags.FileMode), DirPerms: os.FileMode(flags.DirMode), AppendThreshold: 1 << 21, // 2 MiB, a total guess. TmpObjectPrefix: ".gcsfuse_tmp/", } server, err := fs.NewServer(serverCfg) if err != nil { err = fmt.Errorf("fs.NewServer: %v", err) return } // Mount the file system. mountCfg := &fuse.MountConfig{ FSName: bucket.Name(), Options: flags.MountOptions, ErrorLogger: log.New(os.Stderr, "fuse: ", log.Flags()), } mfs, err = fuse.Mount(mountPoint, server, mountCfg) if err != nil { err = fmt.Errorf("Mount: %v", err) return } return }