diff --git a/client/fs/dir.go b/client/fs/dir.go index f923abfdf8..78ba563ea6 100644 --- a/client/fs/dir.go +++ b/client/fs/dir.go @@ -31,7 +31,7 @@ import ( // Dir defines the structure of a directory type Dir struct { super *Super - inode *Inode + info *proto.InodeInfo dcache *DentryCache } @@ -56,23 +56,23 @@ var ( ) // NewDir returns a new directory. -func NewDir(s *Super, i *Inode) fs.Node { +func NewDir(s *Super, i *proto.InodeInfo) fs.Node { return &Dir{ super: s, - inode: i, + info: i, } } // Attr set the attributes of a directory. func (d *Dir) Attr(ctx context.Context, a *fuse.Attr) error { - ino := d.inode.ino - inode, err := d.super.InodeGet(ino) + ino := d.info.Inode + info, err := d.super.InodeGet(ino) if err != nil { log.LogErrorf("Attr: ino(%v) err(%v)", ino, err) return ParseError(err) } - inode.fillAttr(a) - log.LogDebugf("TRACE Attr: inode(%v)", inode) + fillAttr(info, a) + log.LogDebugf("TRACE Attr: inode(%v)", info) return nil } @@ -84,19 +84,18 @@ func (d *Dir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.Cr metric := exporter.NewTPCnt("filecreate") defer metric.Set(err) - info, err := d.super.mw.Create_ll(d.inode.ino, req.Name, proto.Mode(req.Mode.Perm()), req.Uid, req.Gid, nil) + info, err := d.super.mw.Create_ll(d.info.Inode, req.Name, proto.Mode(req.Mode.Perm()), req.Uid, req.Gid, nil) if err != nil { - log.LogErrorf("Create: parent(%v) req(%v) err(%v)", d.inode.ino, req, err) + log.LogErrorf("Create: parent(%v) req(%v) err(%v)", d.info.Inode, req, err) return nil, nil, ParseError(err) } - inode := NewInode(info) - d.super.ic.Put(inode) - child := NewFile(d.super, inode) - d.super.ec.OpenStream(inode.ino) + d.super.ic.Put(info) + child := NewFile(d.super, info) + d.super.ec.OpenStream(info.Inode) d.super.fslock.Lock() - d.super.nodeCache[inode.ino] = child + d.super.nodeCache[info.Inode] = child d.super.fslock.Unlock() if d.super.keepCache { @@ -104,16 +103,16 @@ func (d *Dir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.Cr } resp.EntryValid = LookupValidDuration - d.super.ic.Delete(d.inode.ino) + d.super.ic.Delete(d.info.Inode) elapsed := time.Since(start) - log.LogDebugf("TRACE Create: parent(%v) req(%v) resp(%v) ino(%v) (%v)ns", d.inode.ino, req, resp, inode.ino, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Create: parent(%v) req(%v) resp(%v) ino(%v) (%v)ns", d.info.Inode, req, resp, info.Inode, elapsed.Nanoseconds()) return child, child, nil } // Forget is called when the evict is invoked from the kernel. func (d *Dir) Forget() { - ino := d.inode.ino + ino := d.info.Inode defer func() { log.LogDebugf("TRACE Forget: ino(%v)", ino) }() @@ -133,24 +132,23 @@ func (d *Dir) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error metric := exporter.NewTPCnt("mkdir") defer metric.Set(err) - info, err := d.super.mw.Create_ll(d.inode.ino, req.Name, proto.Mode(os.ModeDir|req.Mode.Perm()), req.Uid, req.Gid, nil) + info, err := d.super.mw.Create_ll(d.info.Inode, req.Name, proto.Mode(os.ModeDir|req.Mode.Perm()), req.Uid, req.Gid, nil) if err != nil { - log.LogErrorf("Mkdir: parent(%v) req(%v) err(%v)", d.inode.ino, req, err) + log.LogErrorf("Mkdir: parent(%v) req(%v) err(%v)", d.info.Inode, req, err) return nil, ParseError(err) } - inode := NewInode(info) - d.super.ic.Put(inode) - child := NewDir(d.super, inode) + d.super.ic.Put(info) + child := NewDir(d.super, info) d.super.fslock.Lock() - d.super.nodeCache[inode.ino] = child + d.super.nodeCache[info.Inode] = child d.super.fslock.Unlock() - d.super.ic.Delete(d.inode.ino) + d.super.ic.Delete(d.info.Inode) elapsed := time.Since(start) - log.LogDebugf("TRACE Mkdir: parent(%v) req(%v) ino(%v) (%v)ns", d.inode.ino, req, inode.ino, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Mkdir: parent(%v) req(%v) ino(%v) (%v)ns", d.info.Inode, req, info.Inode, elapsed.Nanoseconds()) return child, nil } @@ -163,13 +161,13 @@ func (d *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error { metric := exporter.NewTPCnt("remove") defer metric.Set(err) - info, err := d.super.mw.Delete_ll(d.inode.ino, req.Name, req.Dir) + info, err := d.super.mw.Delete_ll(d.info.Inode, req.Name, req.Dir) if err != nil { - log.LogErrorf("Remove: parent(%v) name(%v) err(%v)", d.inode.ino, req.Name, err) + log.LogErrorf("Remove: parent(%v) name(%v) err(%v)", d.info.Inode, req.Name, err) return ParseError(err) } - d.super.ic.Delete(d.inode.ino) + d.super.ic.Delete(d.info.Inode) if info != nil && info.Nlink == 0 && !proto.IsDir(info.Mode) { d.super.orphan.Put(info.Inode) @@ -177,7 +175,7 @@ func (d *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error { } elapsed := time.Since(start) - log.LogDebugf("TRACE Remove: parent(%v) req(%v) inode(%v) (%v)ns", d.inode.ino, req, info, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Remove: parent(%v) req(%v) inode(%v) (%v)ns", d.info.Inode, req, info, elapsed.Nanoseconds()) return nil } @@ -192,35 +190,35 @@ func (d *Dir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.Lo err error ) - log.LogDebugf("TRACE Lookup: parent(%v) req(%v)", d.inode.ino, req) + log.LogDebugf("TRACE Lookup: parent(%v) req(%v)", d.info.Inode, req) ino, ok := d.dcache.Get(req.Name) if !ok { - ino, _, err = d.super.mw.Lookup_ll(d.inode.ino, req.Name) + ino, _, err = d.super.mw.Lookup_ll(d.info.Inode, req.Name) if err != nil { if err != syscall.ENOENT { - log.LogErrorf("Lookup: parent(%v) name(%v) err(%v)", d.inode.ino, req.Name, err) + log.LogErrorf("Lookup: parent(%v) name(%v) err(%v)", d.info.Inode, req.Name, err) } return nil, ParseError(err) } } - inode, err := d.super.InodeGet(ino) + info, err := d.super.InodeGet(ino) if err != nil { - log.LogErrorf("Lookup: parent(%v) name(%v) ino(%v) err(%v)", d.inode.ino, req.Name, ino, err) - dummyInode := &Inode{ino: ino} - dummyChild := NewFile(d.super, dummyInode) + log.LogErrorf("Lookup: parent(%v) name(%v) ino(%v) err(%v)", d.info.Inode, req.Name, ino, err) + dummyInodeInfo := &proto.InodeInfo{Inode: ino} + dummyChild := NewFile(d.super, dummyInodeInfo) return dummyChild, nil } - mode := inode.mode + mode := proto.OsMode(info.Mode) d.super.fslock.Lock() child, ok := d.super.nodeCache[ino] if !ok { if mode.IsDir() { - child = NewDir(d.super, inode) + child = NewDir(d.super, info) } else { - child = NewFile(d.super, inode) + child = NewFile(d.super, info) } d.super.nodeCache[ino] = child } @@ -238,9 +236,9 @@ func (d *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { metric := exporter.NewTPCnt("readdir") defer metric.Set(err) - children, err := d.super.mw.ReadDir_ll(d.inode.ino) + children, err := d.super.mw.ReadDir_ll(d.info.Inode) if err != nil { - log.LogErrorf("Readdir: ino(%v) err(%v)", d.inode.ino, err) + log.LogErrorf("Readdir: ino(%v) err(%v)", d.info.Inode, err) return make([]fuse.Dirent, 0), ParseError(err) } @@ -265,12 +263,12 @@ func (d *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { infos := d.super.mw.BatchInodeGet(inodes) for _, info := range infos { - d.super.ic.Put(NewInode(info)) + d.super.ic.Put(info) } d.dcache = dcache elapsed := time.Since(start) - log.LogDebugf("TRACE ReadDir: ino(%v) (%v)ns", d.inode.ino, elapsed.Nanoseconds()) + log.LogDebugf("TRACE ReadDir: ino(%v) (%v)ns", d.info.Inode, elapsed.Nanoseconds()) return dirents, nil } @@ -278,7 +276,7 @@ func (d *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { func (d *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fs.Node) error { dstDir, ok := newDir.(*Dir) if !ok { - log.LogErrorf("Rename: NOT DIR, parent(%v) req(%v)", d.inode.ino, req) + log.LogErrorf("Rename: NOT DIR, parent(%v) req(%v)", d.info.Inode, req) return fuse.ENOTSUP } start := time.Now() @@ -288,42 +286,42 @@ func (d *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fs.Nod metric := exporter.NewTPCnt("rename") defer metric.Set(err) - err = d.super.mw.Rename_ll(d.inode.ino, req.OldName, dstDir.inode.ino, req.NewName) + err = d.super.mw.Rename_ll(d.info.Inode, req.OldName, dstDir.info.Inode, req.NewName) if err != nil { - log.LogErrorf("Rename: parent(%v) req(%v) err(%v)", d.inode.ino, req, err) + log.LogErrorf("Rename: parent(%v) req(%v) err(%v)", d.info.Inode, req, err) return ParseError(err) } - d.super.ic.Delete(d.inode.ino) - d.super.ic.Delete(dstDir.inode.ino) + d.super.ic.Delete(d.info.Inode) + d.super.ic.Delete(dstDir.info.Inode) elapsed := time.Since(start) - log.LogDebugf("TRACE Rename: SrcParent(%v) OldName(%v) DstParent(%v) NewName(%v) (%v)ns", d.inode.ino, req.OldName, dstDir.inode.ino, req.NewName, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Rename: SrcParent(%v) OldName(%v) DstParent(%v) NewName(%v) (%v)ns", d.info.Inode, req.OldName, dstDir.info.Inode, req.NewName, elapsed.Nanoseconds()) return nil } // Setattr handles the setattr request. func (d *Dir) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error { - ino := d.inode.ino + ino := d.info.Inode start := time.Now() - inode, err := d.super.InodeGet(ino) + info, err := d.super.InodeGet(ino) if err != nil { log.LogErrorf("Setattr: ino(%v) err(%v)", ino, err) return ParseError(err) } - if valid := inode.setattr(req); valid != 0 { - err = d.super.mw.Setattr(ino, valid, proto.Mode(inode.mode), inode.uid, inode.gid) + if valid := setattr(info, req); valid != 0 { + err = d.super.mw.Setattr(ino, valid, info.Mode, info.Uid, info.Gid) if err != nil { d.super.ic.Delete(ino) return ParseError(err) } } - inode.fillAttr(&resp.Attr) + fillAttr(info, &resp.Attr) elapsed := time.Since(start) - log.LogDebugf("TRACE Setattr: ino(%v) req(%v) inodeSize(%v) (%v)ns", ino, req, inode.size, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Setattr: ino(%v) req(%v) inodeSize(%v) (%v)ns", ino, req, info.Size, elapsed.Nanoseconds()) return nil } @@ -338,28 +336,27 @@ func (d *Dir) Mknod(ctx context.Context, req *fuse.MknodRequest) (fs.Node, error metric := exporter.NewTPCnt("mknod") defer metric.Set(err) - info, err := d.super.mw.Create_ll(d.inode.ino, req.Name, proto.Mode(req.Mode), req.Uid, req.Gid, nil) + info, err := d.super.mw.Create_ll(d.info.Inode, req.Name, proto.Mode(req.Mode), req.Uid, req.Gid, nil) if err != nil { - log.LogErrorf("Mknod: parent(%v) req(%v) err(%v)", d.inode.ino, req, err) + log.LogErrorf("Mknod: parent(%v) req(%v) err(%v)", d.info.Inode, req, err) return nil, ParseError(err) } - inode := NewInode(info) - d.super.ic.Put(inode) - child := NewFile(d.super, inode) + d.super.ic.Put(info) + child := NewFile(d.super, info) d.super.fslock.Lock() - d.super.nodeCache[inode.ino] = child + d.super.nodeCache[info.Inode] = child d.super.fslock.Unlock() elapsed := time.Since(start) - log.LogDebugf("TRACE Mknod: parent(%v) req(%v) ino(%v) (%v)ns", d.inode.ino, req, inode.ino, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Mknod: parent(%v) req(%v) ino(%v) (%v)ns", d.info.Inode, req, info.Inode, elapsed.Nanoseconds()) return child, nil } // Symlink handles the symlink request. func (d *Dir) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (fs.Node, error) { - parentIno := d.inode.ino + parentIno := d.info.Inode start := time.Now() var err error @@ -372,31 +369,30 @@ func (d *Dir) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (fs.Node, e return nil, ParseError(err) } - inode := NewInode(info) - d.super.ic.Put(inode) - child := NewFile(d.super, inode) + d.super.ic.Put(info) + child := NewFile(d.super, info) d.super.fslock.Lock() - d.super.nodeCache[inode.ino] = child + d.super.nodeCache[info.Inode] = child d.super.fslock.Unlock() elapsed := time.Since(start) - log.LogDebugf("TRACE Symlink: parent(%v) req(%v) ino(%v) (%v)ns", parentIno, req, inode.ino, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Symlink: parent(%v) req(%v) ino(%v) (%v)ns", parentIno, req, info.Inode, elapsed.Nanoseconds()) return child, nil } // Link handles the link request. func (d *Dir) Link(ctx context.Context, req *fuse.LinkRequest, old fs.Node) (fs.Node, error) { - var oldInode *Inode + var oldInode *proto.InodeInfo switch old := old.(type) { case *File: - oldInode = old.inode + oldInode = old.info default: return nil, fuse.EPERM } - if !oldInode.mode.IsRegular() { - log.LogErrorf("Link: not regular, parent(%v) name(%v) ino(%v) mode(%v)", d.inode.ino, req.NewName, oldInode.ino, oldInode.mode) + if !proto.IsRegular(oldInode.Mode) { + log.LogErrorf("Link: not regular, parent(%v) name(%v) ino(%v) mode(%v)", d.info.Inode, req.NewName, oldInode.Inode, proto.OsMode(oldInode.Mode)) return nil, fuse.EPERM } @@ -406,25 +402,24 @@ func (d *Dir) Link(ctx context.Context, req *fuse.LinkRequest, old fs.Node) (fs. metric := exporter.NewTPCnt("link") defer metric.Set(err) - info, err := d.super.mw.Link(d.inode.ino, req.NewName, oldInode.ino) + info, err := d.super.mw.Link(d.info.Inode, req.NewName, oldInode.Inode) if err != nil { - log.LogErrorf("Link: parent(%v) name(%v) ino(%v) err(%v)", d.inode.ino, req.NewName, oldInode.ino, err) + log.LogErrorf("Link: parent(%v) name(%v) ino(%v) err(%v)", d.info.Inode, req.NewName, oldInode.Inode, err) return nil, ParseError(err) } - newInode := NewInode(info) - d.super.ic.Put(newInode) + d.super.ic.Put(info) d.super.fslock.Lock() - newFile, ok := d.super.nodeCache[newInode.ino] + newFile, ok := d.super.nodeCache[info.Inode] if !ok { - newFile = NewFile(d.super, newInode) - d.super.nodeCache[newInode.ino] = newFile + newFile = NewFile(d.super, info) + d.super.nodeCache[info.Inode] = newFile } d.super.fslock.Unlock() elapsed := time.Since(start) - log.LogDebugf("TRACE Link: parent(%v) name(%v) ino(%v) (%v)ns", d.inode.ino, req.NewName, newInode.ino, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Link: parent(%v) name(%v) ino(%v) (%v)ns", d.info.Inode, req.NewName, info.Inode, elapsed.Nanoseconds()) return newFile, nil } diff --git a/client/fs/file.go b/client/fs/file.go index 8d477a0719..e23aa373c4 100644 --- a/client/fs/file.go +++ b/client/fs/file.go @@ -33,7 +33,7 @@ import ( // File defines the structure of a file. type File struct { super *Super - inode *Inode + info *proto.InodeInfo sync.RWMutex } @@ -57,14 +57,14 @@ var ( ) // NewFile returns a new file. -func NewFile(s *Super, i *Inode) fs.Node { - return &File{super: s, inode: i} +func NewFile(s *Super, i *proto.InodeInfo) fs.Node { + return &File{super: s, info: i} } // Attr sets the attributes of a file. func (f *File) Attr(ctx context.Context, a *fuse.Attr) error { - ino := f.inode.ino - inode, err := f.super.InodeGet(ino) + ino := f.info.Inode + info, err := f.super.InodeGet(ino) if err != nil { log.LogErrorf("Attr: ino(%v) err(%v)", ino, err) if err == fuse.ENOENT { @@ -74,20 +74,20 @@ func (f *File) Attr(ctx context.Context, a *fuse.Attr) error { return ParseError(err) } - inode.fillAttr(a) + fillAttr(info, a) fileSize, gen := f.fileSize(ino) - log.LogDebugf("Attr: ino(%v) fileSize(%v) gen(%v) inode.gen(%v)", ino, fileSize, gen, inode.gen) - if gen >= inode.gen { + log.LogDebugf("Attr: ino(%v) fileSize(%v) gen(%v) inode.gen(%v)", ino, fileSize, gen, info.Generation) + if gen >= info.Generation { a.Size = uint64(fileSize) } - log.LogDebugf("TRACE Attr: inode(%v) attr(%v)", inode, a) + log.LogDebugf("TRACE Attr: inode(%v) attr(%v)", info, a) return nil } // Forget evicts the inode of the current file. This can only happen when the inode is on the orphan list. func (f *File) Forget() { - ino := f.inode.ino + ino := f.info.Inode defer func() { log.LogDebugf("TRACE Forget: ino(%v)", ino) }() @@ -114,7 +114,7 @@ func (f *File) Forget() { // Open handles the open request. func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (handle fs.Handle, err error) { - ino := f.inode.ino + ino := f.info.Inode start := time.Now() f.super.ec.OpenStream(ino) @@ -130,7 +130,7 @@ func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenR // Release handles the release request. func (f *File) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error) { - ino := f.inode.ino + ino := f.info.Inode log.LogDebugf("TRACE Release enter: ino(%v) req(%v)", ino, req) start := time.Now() @@ -151,22 +151,22 @@ func (f *File) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error // Read handles the read request. func (f *File) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) (err error) { - log.LogDebugf("TRACE Read enter: ino(%v) offset(%v) reqsize(%v) req(%v)", f.inode.ino, req.Offset, req.Size, req) + log.LogDebugf("TRACE Read enter: ino(%v) offset(%v) reqsize(%v) req(%v)", f.info.Inode, req.Offset, req.Size, req) start := time.Now() metric := exporter.NewTPCnt("fileread") defer metric.Set(err) - size, err := f.super.ec.Read(f.inode.ino, resp.Data[fuse.OutHeaderSize:], int(req.Offset), req.Size) + size, err := f.super.ec.Read(f.info.Inode, resp.Data[fuse.OutHeaderSize:], int(req.Offset), req.Size) if err != nil && err != io.EOF { - msg := fmt.Sprintf("Read: ino(%v) req(%v) err(%v) size(%v)", f.inode.ino, req, err, size) + msg := fmt.Sprintf("Read: ino(%v) req(%v) err(%v) size(%v)", f.info.Inode, req, err, size) f.super.handleError("Read", msg) return fuse.EIO } if size > req.Size { - msg := fmt.Sprintf("Read: read size larger than request size, ino(%v) req(%v) size(%v)", f.inode.ino, req, size) + msg := fmt.Sprintf("Read: read size larger than request size, ino(%v) req(%v) size(%v)", f.info.Inode, req, size) f.super.handleError("Read", msg) return fuse.ERANGE } @@ -175,17 +175,17 @@ func (f *File) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadR resp.Data = resp.Data[:size+fuse.OutHeaderSize] } else if size <= 0 { resp.Data = resp.Data[:fuse.OutHeaderSize] - log.LogWarnf("Read: ino(%v) offset(%v) reqsize(%v) req(%v) size(%v)", f.inode.ino, req.Offset, req.Size, req, size) + log.LogWarnf("Read: ino(%v) offset(%v) reqsize(%v) req(%v) size(%v)", f.info.Inode, req.Offset, req.Size, req, size) } elapsed := time.Since(start) - log.LogDebugf("TRACE Read: ino(%v) offset(%v) reqsize(%v) req(%v) size(%v) (%v)ns", f.inode.ino, req.Offset, req.Size, req, size, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Read: ino(%v) offset(%v) reqsize(%v) req(%v) size(%v) (%v)ns", f.info.Inode, req.Offset, req.Size, req, size, elapsed.Nanoseconds()) return nil } // Write handles the write request. func (f *File) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) (err error) { - ino := f.inode.ino + ino := f.info.Inode reqlen := len(req.Data) filesize, _ := f.fileSize(ino) @@ -198,7 +198,7 @@ func (f *File) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.Wri resp.Size = reqlen } - log.LogDebugf("fallocate: ino(%v) origFilesize(%v) req(%v) err(%v)", f.inode.ino, filesize, req, err) + log.LogDebugf("fallocate: ino(%v) origFilesize(%v) req(%v) err(%v)", f.info.Inode, filesize, req, err) return } @@ -248,43 +248,43 @@ func (f *File) Flush(ctx context.Context, req *fuse.FlushRequest) (err error) { if !f.super.fsyncOnClose { return fuse.ENOSYS } - log.LogDebugf("TRACE Flush enter: ino(%v)", f.inode.ino) + log.LogDebugf("TRACE Flush enter: ino(%v)", f.info.Inode) start := time.Now() metric := exporter.NewTPCnt("filesync") defer metric.Set(err) - err = f.super.ec.Flush(f.inode.ino) + err = f.super.ec.Flush(f.info.Inode) if err != nil { - msg := fmt.Sprintf("Flush: ino(%v) err(%v)", f.inode.ino, err) + msg := fmt.Sprintf("Flush: ino(%v) err(%v)", f.info.Inode, err) f.super.handleError("Flush", msg) return fuse.EIO } - f.super.ic.Delete(f.inode.ino) + f.super.ic.Delete(f.info.Inode) elapsed := time.Since(start) - log.LogDebugf("TRACE Flush: ino(%v) (%v)ns", f.inode.ino, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Flush: ino(%v) (%v)ns", f.info.Inode, elapsed.Nanoseconds()) return nil } // Fsync hanldes the fsync request. func (f *File) Fsync(ctx context.Context, req *fuse.FsyncRequest) (err error) { - log.LogDebugf("TRACE Fsync enter: ino(%v)", f.inode.ino) + log.LogDebugf("TRACE Fsync enter: ino(%v)", f.info.Inode) start := time.Now() - err = f.super.ec.Flush(f.inode.ino) + err = f.super.ec.Flush(f.info.Inode) if err != nil { - msg := fmt.Sprintf("Fsync: ino(%v) err(%v)", f.inode.ino, err) + msg := fmt.Sprintf("Fsync: ino(%v) err(%v)", f.info.Inode, err) f.super.handleError("Fsync", msg) return fuse.EIO } - f.super.ic.Delete(f.inode.ino) + f.super.ic.Delete(f.info.Inode) elapsed := time.Since(start) - log.LogDebugf("TRACE Fsync: ino(%v) (%v)ns", f.inode.ino, elapsed.Nanoseconds()) + log.LogDebugf("TRACE Fsync: ino(%v) (%v)ns", f.info.Inode, elapsed.Nanoseconds()) return nil } // Setattr handles the setattr request. func (f *File) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error { - ino := f.inode.ino + ino := f.info.Inode start := time.Now() if req.Valid.Size() { if err := f.super.ec.Flush(ino); err != nil { @@ -299,27 +299,27 @@ func (f *File) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse f.super.ec.RefreshExtentsCache(ino) } - inode, err := f.super.InodeGet(ino) + info, err := f.super.InodeGet(ino) if err != nil { log.LogErrorf("Setattr: InodeGet failed, ino(%v) err(%v)", ino, err) return ParseError(err) } if req.Valid.Size() { - if req.Size != inode.size { - log.LogWarnf("Setattr: truncate ino(%v) reqSize(%v) inodeSize(%v)", ino, req.Size, inode.size) + if req.Size != info.Size { + log.LogWarnf("Setattr: truncate ino(%v) reqSize(%v) inodeSize(%v)", ino, req.Size, info.Size) } } - if valid := inode.setattr(req); valid != 0 { - err = f.super.mw.Setattr(ino, valid, proto.Mode(inode.mode), inode.uid, inode.gid) + if valid := setattr(info, req); valid != 0 { + err = f.super.mw.Setattr(ino, valid, info.Mode, info.Uid, info.Gid) if err != nil { f.super.ic.Delete(ino) return ParseError(err) } } - inode.fillAttr(&resp.Attr) + fillAttr(info, &resp.Attr) elapsed := time.Since(start) log.LogDebugf("TRACE Setattr: ino(%v) req(%v) (%v)ns", ino, req, elapsed.Nanoseconds()) @@ -328,19 +328,19 @@ func (f *File) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse // Readlink handles the readlink request. func (f *File) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (string, error) { - ino := f.inode.ino - inode, err := f.super.InodeGet(ino) + ino := f.info.Inode + info, err := f.super.InodeGet(ino) if err != nil { log.LogErrorf("Readlink: ino(%v) err(%v)", ino, err) return "", ParseError(err) } - log.LogDebugf("TRACE Readlink: ino(%v) target(%v)", ino, string(inode.target)) - return string(inode.target), nil + log.LogDebugf("TRACE Readlink: ino(%v) target(%v)", ino, string(info.Target)) + return string(info.Target), nil } // Getxattr has not been implemented yet. func (f *File) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error { - ino := f.inode.ino + ino := f.info.Inode name := req.Name size := req.Size pos := req.Position @@ -363,7 +363,7 @@ func (f *File) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fu // Listxattr has not been implemented yet. func (f *File) Listxattr(ctx context.Context, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) error { - ino := f.inode.ino + ino := f.info.Inode _ = req.Size // ignore currently _ = req.Position // ignore currently @@ -381,7 +381,7 @@ func (f *File) Listxattr(ctx context.Context, req *fuse.ListxattrRequest, resp * // Setxattr has not been implemented yet. func (f *File) Setxattr(ctx context.Context, req *fuse.SetxattrRequest) error { - ino := f.inode.ino + ino := f.info.Inode name := req.Name value := req.Xattr // TODOļ¼š implement flag to improve compatible (Mofei Zhang) @@ -395,7 +395,7 @@ func (f *File) Setxattr(ctx context.Context, req *fuse.SetxattrRequest) error { // Removexattr has not been implemented yet. func (f *File) Removexattr(ctx context.Context, req *fuse.RemovexattrRequest) error { - ino := f.inode.ino + ino := f.info.Inode name := req.Name if err := f.super.mw.XAttrDel_ll(ino, name); err != nil { log.LogErrorf("Removexattr: ino(%v) name(%v) err(%v)", ino, name, err) @@ -411,9 +411,9 @@ func (f *File) fileSize(ino uint64) (size int, gen uint64) { if !valid { f.super.ic.Delete(ino) - if inode, err := f.super.InodeGet(ino); err == nil { - size = int(inode.size) - gen = inode.gen + if info, err := f.super.InodeGet(ino); err == nil { + size = int(info.Size) + gen = info.Generation } } return diff --git a/client/fs/icache.go b/client/fs/icache.go index 1c1a233dfb..491314389e 100644 --- a/client/fs/icache.go +++ b/client/fs/icache.go @@ -18,6 +18,8 @@ import ( "container/list" "sync" "time" + + "github.com/chubaofs/chubaofs/proto" ) const ( @@ -51,29 +53,27 @@ func NewInodeCache(exp time.Duration, maxElements int) *InodeCache { return ic } -// Put puts the given inode into the inode cache. -func (ic *InodeCache) Put(inode *Inode) { +// Put puts the given inode info into the inode cache. +func (ic *InodeCache) Put(info *proto.InodeInfo) { ic.Lock() - old, ok := ic.cache[inode.ino] + old, ok := ic.cache[info.Inode] if ok { ic.lruList.Remove(old) - delete(ic.cache, inode.ino) + delete(ic.cache, info.Inode) } if ic.lruList.Len() >= ic.maxElements { ic.evict(true) } - inode.setExpiration(ic.expiration) - element := ic.lruList.PushFront(inode) - ic.cache[inode.ino] = element + inodeSetExpiration(info, ic.expiration) + element := ic.lruList.PushFront(info) + ic.cache[info.Inode] = element ic.Unlock() - - //log.LogDebugf("InodeCache PutConnect: inode(%v)", inode) } -// Get returns the inode based on the given inode ID. -func (ic *InodeCache) Get(ino uint64) *Inode { +// Get returns the inode info based on the given inode number. +func (ic *InodeCache) Get(ino uint64) *proto.InodeInfo { ic.RLock() element, ok := ic.cache[ino] if !ok { @@ -81,17 +81,17 @@ func (ic *InodeCache) Get(ino uint64) *Inode { return nil } - inode := element.Value.(*Inode) - if inode.expired() { + info := element.Value.(*proto.InodeInfo) + if inodeExpired(info) { ic.RUnlock() //log.LogDebugf("InodeCache GetConnect expired: now(%v) inode(%v)", time.Now().Format(LogTimeFormat), inode) return nil } ic.RUnlock() - return inode + return info } -// Delete deletes the inode based on the given inode ID. +// Delete deletes the inode info based on the given inode number. func (ic *InodeCache) Delete(ino uint64) { //log.LogDebugf("InodeCache Delete: ino(%v)", ino) ic.Lock() @@ -108,9 +108,7 @@ func (ic *InodeCache) Delete(ino uint64) { // The caller should grab the WRITE lock of the inode cache. func (ic *InodeCache) evict(foreground bool) { var count int - //defer func() { - // log.LogInfof("InodeCache: evict count(%v)", count) - //}() + for i := 0; i < MinInodeCacheEvictNum; i++ { element := ic.lruList.Back() if element == nil { @@ -120,14 +118,13 @@ func (ic *InodeCache) evict(foreground bool) { // For background eviction, if all expired items have been evicted, just return // But for foreground eviction, we need to evict at least MinInodeCacheEvictNum inodes. // The foreground eviction, does not need to care if the inode has expired or not. - inode := element.Value.(*Inode) - if !foreground && !inode.expired() { + info := element.Value.(*proto.InodeInfo) + if !foreground && !inodeExpired(info) { return } ic.lruList.Remove(element) - delete(ic.cache, inode.ino) - //log.LogInfof("InodeCache: evict inode(%v)", inode) + delete(ic.cache, info.Inode) count++ } @@ -141,13 +138,12 @@ func (ic *InodeCache) evict(foreground bool) { if element == nil { break } - inode := element.Value.(*Inode) - if !inode.expired() { + info := element.Value.(*proto.InodeInfo) + if !inodeExpired(info) { break } ic.lruList.Remove(element) - delete(ic.cache, inode.ino) - //log.LogInfof("InodeCache: evict inode(%v)", inode) + delete(ic.cache, info.Inode) count++ } } diff --git a/client/fs/inode.go b/client/fs/inode.go index bc03b6641d..571bf2a1b4 100644 --- a/client/fs/inode.go +++ b/client/fs/inode.go @@ -15,8 +15,6 @@ package fs import ( - "fmt" - "os" "time" "bazil.org/fuse" @@ -29,37 +27,10 @@ const ( LogTimeFormat = "20060102150405000" ) -// Inode defines the structure of an inode. -type Inode struct { - ino uint64 - size uint64 - nlink uint32 - uid uint32 - gid uint32 - gen uint64 - ctime time.Time // time of last inode change - mtime time.Time // time of last modification - atime time.Time // time of last access - mode os.FileMode - target []byte - - // protected under the inode cache lock - expiration int64 -} - -// NewInode returns a new inode. -func NewInode(info *proto.InodeInfo) *Inode { - inode := new(Inode) - inode.fill(info) - return inode -} - -// InodeGet return the inode based on the given inode ID. -func (s *Super) InodeGet(ino uint64) (*Inode, error) { - inode := s.ic.Get(ino) - if inode != nil { - //log.LogDebugf("InodeCache hit: inode(%v)", inode) - return inode, nil +func (s *Super) InodeGet(ino uint64) (*proto.InodeInfo, error) { + info := s.ic.Get(ino) + if info != nil { + return info, nil } info, err := s.mw.InodeGet_ll(ino) @@ -71,71 +42,51 @@ func (s *Super) InodeGet(ino uint64) (*Inode, error) { return nil, fuse.ENOENT } } - inode = NewInode(info) - s.ic.Put(inode) + s.ic.Put(info) s.ec.RefreshExtentsCache(ino) - return inode, nil + return info, nil } -// String returns the string format of the inode. -func (inode *Inode) String() string { - return fmt.Sprintf("ino(%v) mode(%v) size(%v) nlink(%v) gen(%v) uid(%v) gid(%v) exp(%v) mtime(%v) target(%v)", inode.ino, inode.mode, inode.size, inode.nlink, inode.gen, inode.uid, inode.gid, time.Unix(0, inode.expiration).Format(LogTimeFormat), inode.mtime, inode.target) -} - -func (inode *Inode) setattr(req *fuse.SetattrRequest) (valid uint32) { +func setattr(info *proto.InodeInfo, req *fuse.SetattrRequest) (valid uint32) { if req.Valid.Mode() { - inode.mode = req.Mode + info.Mode = proto.Mode(req.Mode) valid |= proto.AttrMode } if req.Valid.Uid() { - inode.uid = req.Uid + info.Uid = req.Uid valid |= proto.AttrUid } if req.Valid.Gid() { - inode.gid = req.Gid + info.Gid = req.Gid valid |= proto.AttrGid } return } -func (inode *Inode) fill(info *proto.InodeInfo) { - inode.ino = info.Inode - inode.size = info.Size - inode.nlink = info.Nlink - inode.uid = info.Uid - inode.gid = info.Gid - inode.gen = info.Generation - inode.ctime = info.CreateTime - inode.atime = info.AccessTime - inode.mtime = info.ModifyTime - inode.target = info.Target - inode.mode = proto.OsMode(info.Mode) -} - -func (inode *Inode) fillAttr(attr *fuse.Attr) { +func fillAttr(info *proto.InodeInfo, attr *fuse.Attr) { attr.Valid = AttrValidDuration - attr.Nlink = inode.nlink - attr.Inode = inode.ino - attr.Mode = inode.mode - attr.Size = inode.size + attr.Nlink = info.Nlink + attr.Inode = info.Inode + attr.Mode = proto.OsMode(info.Mode) + attr.Size = info.Size attr.Blocks = attr.Size >> 9 // In 512 bytes - attr.Atime = inode.atime - attr.Ctime = inode.ctime - attr.Mtime = inode.mtime + attr.Atime = info.AccessTime + attr.Ctime = info.CreateTime + attr.Mtime = info.ModifyTime attr.BlockSize = DefaultBlksize - attr.Uid = inode.uid - attr.Gid = inode.gid + attr.Uid = info.Uid + attr.Gid = info.Gid } -func (inode *Inode) expired() bool { - if time.Now().UnixNano() > inode.expiration { +func inodeExpired(info *proto.InodeInfo) bool { + if time.Now().UnixNano() > info.Expiration() { return true } return false } -func (inode *Inode) setExpiration(t time.Duration) { - inode.expiration = time.Now().Add(t).UnixNano() +func inodeSetExpiration(info *proto.InodeInfo, t time.Duration) { + info.SetExpiration(time.Now().Add(t).UnixNano()) } diff --git a/proto/fs_proto.go b/proto/fs_proto.go index 1f2238ae25..ddae9e8cfb 100644 --- a/proto/fs_proto.go +++ b/proto/fs_proto.go @@ -68,6 +68,16 @@ type InodeInfo struct { CreateTime time.Time `json:"ct"` AccessTime time.Time `json:"at"` Target []byte `json:"tgt"` + + expiration int64 +} + +func (info *InodeInfo) Expiration() int64 { + return info.expiration +} + +func (info *InodeInfo) SetExpiration(e int64) { + info.expiration = e } // String returns the string format of the inode.