func (fs isoFS) ReleaseDirHandle(ctx context.Context, op *fuseops.ReleaseDirHandleOp) error {
	return nil
}
ReleaseDirHandle is a nop added to avoid error logs. sent by kernel when there are
no more references to dir handle and all file descriptor are closed.
package isofuse
import (
	"context"
	"os"
	"time"
	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseops"
	"github.com/jacobsa/fuse/fuseutil"
	"go.uber.org/zap"
	"github.com/NVIDIA/vdisc/pkg/iso9660"
	"github.com/NVIDIA/vdisc/pkg/safecast"
)
func (fs *isoFS) GetInodeAttributes(ctx context.Context, op *fuseops.GetInodeAttributesOp) error {
	fs.finfosMU.RLock()
	entry, ok := fs.finfos[op.Inode]
	if !ok {
		fs.finfosMU.RUnlock()
		fs.logger.Error("get inode attributes", zap.Uint64("ino", uint64(op.Inode)), zap.Error(errUnknownInode))
		return fuse.EINVAL
	}
	fs.finfosMU.RUnlock()
	op.Attributes = fuseops.InodeAttributes{
		Size:  safecast.Int64ToUint64(entry.Info.Size()),
		Nlink: entry.Info.Nlink(),
		Mode:  entry.Info.Mode(),
		Ctime: entry.Info.ModTime(),
		Mtime: entry.Info.ModTime(),
		Uid:   entry.Info.Uid(),
		Gid:   entry.Info.Gid(),
	}
	op.AttributesExpiration = time.Now().Add(1 * time.Minute)
	return nil
}
func (fs *isoFS) LookUpInode(ctx context.Context, op *fuseops.LookUpInodeOp) error {
	set := func(child *iso9660.FileInfo) {
		childIno := fuseops.InodeID(child.Ino())
		fs.finfosMU.Lock()
		defer fs.finfosMU.Unlock()
		centry, ok := fs.finfos[childIno]
		if !ok {
			centry = &finfosEntry{
				Info: child,
			}
			fs.finfos[childIno] = centry
		}
		centry.RefCnt++
		op.Entry = fuseops.ChildInodeEntry{
			Child: childIno,
			Attributes: fuseops.InodeAttributes{
				Size:  safecast.Int64ToUint64(child.Size()),
				Nlink: child.Nlink(),
				Mode:  child.Mode(),
				Ctime: child.ModTime(),
				Mtime: child.ModTime(),
				Uid:   child.Uid(),
				Gid:   child.Gid(),
			},
			AttributesExpiration: time.Now().Add(1 * time.Minute),
			EntryExpiration:      time.Now().Add(1 * time.Hour),
		}
	}
	cachedFi, ok := fs.finfoCache.Get(op.Parent, op.Name)
	if ok {
		set(cachedFi)
		return nil
	}
	fs.finfosMU.RLock()
	entry, ok := fs.finfos[op.Parent]
	if !ok {
		fs.finfosMU.RUnlock()
		fs.logger.Info("lookup inode", zap.Uint64("parent", uint64(op.Parent)), zap.String("name", op.Name), zap.Error(errUnknownInode))
		return fuse.EINVAL
	}
	fs.finfosMU.RUnlock()
	it := iso9660.NewReadDirIterator(fs.volume.Image(), entry.Info.Extent(), entry.Info.Size(), 0)
	for it.Next() {
		child, _ := it.FileInfoAndLen()
		fs.finfoCache.Put(op.Parent, child.Name(), child)
		if child.Name() == op.Name {
			set(child)
			return nil
		}
	}
	if err := it.Err(); err != nil {
		fs.logger.Error("lookup inode", zap.Uint64("parent", uint64(op.Parent)), zap.String("name", op.Name), zap.Error(err))
		return fuse.EIO
	}
	return fuse.ENOENT
}
func (fs *isoFS) ForgetInode(ctx context.Context, op *fuseops.ForgetInodeOp) error {
	if op.Inode == 1 {
		return nil
	}
	fs.finfosMU.Lock()
	defer fs.finfosMU.Unlock()
	entry, ok := fs.finfos[op.Inode]
	if !ok {
		fs.logger.Error("forget inode", zap.Uint64("ino", uint64(op.Inode)), zap.Error(errUnknownInode))
		return fuse.EINVAL
	}
	if entry.RefCnt > op.N {
		entry.RefCnt = entry.RefCnt - op.N
	} else {
		delete(fs.finfos, op.Inode)
	}
	return nil
}
func (fs *isoFS) OpenDir(ctx context.Context, op *fuseops.OpenDirOp) error {
	return nil
}