func (t *DirTest) resetInode(implicitDirs bool) { if t.in != nil { t.in.Unlock() } t.in = inode.NewDirInode( dirInodeID, dirInodeName, fuseops.InodeAttributes{ Uid: uid, Gid: gid, Mode: dirMode, }, implicitDirs, typeCacheTTL, t.bucket, &t.clock) t.in.Lock() }
// Implementation detail of lookUpOrCreateInodeIfNotStale; do not use outside // of that function. // // LOCKS_REQUIRED(fs.mu) func (fs *fileSystem) mintInode(name string, o *gcs.Object) (in inode.Inode) { // Choose an ID. id := fs.nextInodeID fs.nextInodeID++ // Create the inode. switch { // Explicit directories case o != nil && inode.IsDirName(o.Name): in = inode.NewExplicitDirInode( id, o, fuseops.InodeAttributes{ Uid: fs.uid, Gid: fs.gid, Mode: fs.dirMode, }, fs.implicitDirs, fs.dirTypeCacheTTL, fs.bucket, fs.clock) // Implicit directories case inode.IsDirName(name): in = inode.NewDirInode( id, name, fuseops.InodeAttributes{ Uid: fs.uid, Gid: fs.gid, Mode: fs.dirMode, }, fs.implicitDirs, fs.dirTypeCacheTTL, fs.bucket, fs.clock) case inode.IsSymlink(o): in = inode.NewSymlinkInode( id, o, fuseops.InodeAttributes{ Uid: fs.uid, Gid: fs.gid, Mode: fs.fileMode | os.ModeSymlink, }) default: in = inode.NewFileInode( id, o, fuseops.InodeAttributes{ Uid: fs.uid, Gid: fs.gid, Mode: fs.fileMode, }, fs.gcsChunkSize, fs.bucket, fs.leaser, fs.objectSyncer, fs.clock) } // Place it in our map of IDs to inodes. fs.inodes[in.ID()] = in return }
// Create a fuse file system server according to the supplied configuration. func NewServer(cfg *ServerConfig) (server fuse.Server, err error) { // Check permissions bits. if cfg.FilePerms&^os.ModePerm != 0 { err = fmt.Errorf("Illegal file perms: %v", cfg.FilePerms) return } if cfg.DirPerms&^os.ModePerm != 0 { err = fmt.Errorf("Illegal dir perms: %v", cfg.FilePerms) return } // Disable chunking if set to zero. gcsChunkSize := cfg.GCSChunkSize if gcsChunkSize == 0 { gcsChunkSize = math.MaxUint64 } // Create the file leaser. leaser := lease.NewFileLeaser( cfg.TempDir, cfg.TempDirLimitNumFiles, cfg.TempDirLimitBytes) // Create the object syncer. // Check TmpObjectPrefix. if cfg.TmpObjectPrefix == "" { err = errors.New("You must set TmpObjectPrefix.") return } objectSyncer := gcsproxy.NewObjectSyncer( cfg.AppendThreshold, cfg.TmpObjectPrefix, cfg.Bucket) // Set up the basic struct. fs := &fileSystem{ clock: cfg.Clock, bucket: cfg.Bucket, leaser: leaser, objectSyncer: objectSyncer, gcsChunkSize: gcsChunkSize, implicitDirs: cfg.ImplicitDirectories, dirTypeCacheTTL: cfg.DirTypeCacheTTL, uid: cfg.Uid, gid: cfg.Gid, fileMode: cfg.FilePerms, dirMode: cfg.DirPerms | os.ModeDir, inodes: make(map[fuseops.InodeID]inode.Inode), nextInodeID: fuseops.RootInodeID + 1, generationBackedInodes: make(map[string]GenerationBackedInode), implicitDirInodes: make(map[string]inode.DirInode), handles: make(map[fuseops.HandleID]interface{}), } // Set up the root inode. root := inode.NewDirInode( fuseops.RootInodeID, "", // name fuseops.InodeAttributes{ Uid: fs.uid, Gid: fs.gid, Mode: fs.dirMode, }, fs.implicitDirs, fs.dirTypeCacheTTL, cfg.Bucket, fs.clock) root.Lock() root.IncrementLookupCount() fs.inodes[fuseops.RootInodeID] = root fs.implicitDirInodes[root.Name()] = root root.Unlock() // Set up invariant checking. fs.mu = syncutil.NewInvariantMutex(fs.checkInvariants) // Periodically garbage collect temporary objects. var gcCtx context.Context gcCtx, fs.stopGarbageCollecting = context.WithCancel(context.Background()) go garbageCollect(gcCtx, cfg.TmpObjectPrefix, fs.bucket) server = fuseutil.NewFileSystemServer(fs) return }