Skip to content

Commit

Permalink
Merge pull request cubefs#545 from shuoranliu/enhance-eliminate-redun…
Browse files Browse the repository at this point in the history
…dant-inode-struct

enhance: eliminate redundant Inode memory usage
  • Loading branch information
awzhgw authored May 8, 2020
2 parents 2c16484 + aafaba8 commit 8d5f8dc
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 227 deletions.
155 changes: 75 additions & 80 deletions client/fs/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
// Dir defines the structure of a directory
type Dir struct {
super *Super
inode *Inode
info *proto.InodeInfo
dcache *DentryCache
}

Expand All @@ -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
}

Expand All @@ -84,36 +84,35 @@ 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 {
resp.Flags |= fuse.OpenKeepCache
}
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)
}()
Expand All @@ -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
}

Expand All @@ -163,21 +161,21 @@ 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)
log.LogDebugf("Remove: add to orphan inode list, ino(%v)", info.Inode)
}

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
}

Expand All @@ -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
}
Expand All @@ -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)
}

Expand All @@ -265,20 +263,20 @@ 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
}

// Rename handles the rename request.
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()
Expand All @@ -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
}

Expand All @@ -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
Expand All @@ -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
}

Expand All @@ -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
}

Expand Down
Loading

0 comments on commit 8d5f8dc

Please sign in to comment.