func fillEntryOut(out *raw.EntryOut, i *maggiefs.Inode) { // fill out out.NodeId = i.Inodeid out.Generation = i.Generation out.EntryValid = uint64(0) out.AttrValid = uint64(0) out.EntryValidNsec = uint32(100) out.AttrValidNsec = uint32(100) //Inode out.Ino = i.Inodeid out.Size = i.Length out.Blocks = numBlocks(i.Length, maggiefs.PAGESIZE) out.Atime = uint64(0) // always 0 for atime out.Mtime = uint64(i.Mtime) // Mtime is user modifiable and is the last time data changed out.Ctime = uint64(i.Ctime) // Ctime is tracked by the FS and changes when attrs or data change out.Atimensec = uint32(0) out.Mtimensec = uint32(0) out.Ctimensec = uint32(0) out.Mode = i.FullMode() out.Nlink = i.Nlink out.Uid = i.Uid out.Gid = i.Gid out.Rdev = uint32(0) // regular file, not block dvice out.Blksize = maggiefs.PAGESIZE }
// seta an inode func (nd *NameData) SetInode(i *maggiefs.Inode) (err error) { nd.inodeStripeLock[i.Inodeid%STRIPE_SIZE].Lock() defer nd.inodeStripeLock[i.Inodeid%STRIPE_SIZE].Unlock() key := make([]byte, 8) binary.LittleEndian.PutUint64(key, i.Inodeid) // do the write and send OK binsize := i.BinSize() b := make([]byte, binsize) i.ToBytes(b) err = nd.inodb.Put(WriteOpts, key, b) return err }
// adds an inode persistent store, setting its inode ID to the generated ID, and returning // the generated id and error func (nd *NameData) AddInode(i *maggiefs.Inode) (uint64, error) { newNodeId, err := nd.GetIncrCounter(COUNTER_INODE, 1) if err != nil { return 0, err } i.Inodeid = newNodeId err = nd.SetInode(i) return i.Inodeid, err }
func (m *MaggieFuse) Mkdir(out *raw.EntryOut, header *raw.InHeader, input *raw.MkdirIn, name string) (code fuse.Status) { // make new child currTime := time.Now().Unix() i := maggiefs.Inode{ 0, // id 0 to start, we get id when inserting 0, maggiefs.FTYPE_DIR, 0, 07777 & input.Mode, currTime, currTime, 0, header.Uid, header.Gid, "", make([]maggiefs.Block, 0, 0), make(map[string]maggiefs.Dentry), make(map[string][]byte), } // save id, err := m.names.AddInode(&i) if err != nil { return fuse.EROFS } i.Inodeid = id // link parent err = m.names.Link(header.NodeId, id, name, false) if err != nil { // garbage collector will clean up our 0 reference node if err == maggiefs.E_EXISTS { return fuse.Status(syscall.EEXIST) } if err == maggiefs.E_NOTDIR { return fuse.ENOTDIR } return fuse.EROFS } // send entry back to child fillEntryOut(out, &i) return fuse.OK }
func (m *MaggieFuse) Mknod(out *raw.EntryOut, header *raw.InHeader, input *raw.MknodIn, name string) (code fuse.Status) { //build node currTime := time.Now().Unix() i := maggiefs.Inode{ 0, // id 0 to start 0, // gen 0 maggiefs.FTYPE_REG, 0, input.Mode & 07777, currTime, currTime, 1, header.Uid, header.Gid, "", make([]maggiefs.Block, 0, 0), make(map[string]maggiefs.Dentry), make(map[string][]byte), } // save new node id, err := m.names.AddInode(&i) if err != nil { return fuse.EROFS } i.Inodeid = id // link parent err = m.names.Link(header.NodeId, i.Inodeid, name, false) if err != nil { if err == maggiefs.E_EXISTS { return fuse.Status(syscall.EEXIST) } else { return fuse.EROFS } } // output fillEntryOut(out, &i) return fuse.OK }
// acquires lease, then adds the blocks to the namenode, // patching up the referenced inode to match func (w *InodeWriter) addBlocksForFileWrite(inode *maggiefs.Inode, off uint64, length uint32) error { // fmt.Printf("Adding/extending blocks for write at off %d length %d\n", off, length) newEndPos := off + uint64(length) if newEndPos > inode.Length { // if we have a last block and it's less than max length, // extend last block to max block length first // fmt.Printf("Adding/extending blocks for file write to inode %+v\n", inode) if inode.Blocks != nil && len(inode.Blocks) > 0 { idx := int(len(inode.Blocks) - 1) lastBlock := inode.Blocks[idx] if lastBlock.Length() < BLOCKLENGTH { extendLength := BLOCKLENGTH - lastBlock.Length() if lastBlock.EndPos+extendLength > off+uint64(length) { // only extend as much as we need to extendLength = off + uint64(length) - lastBlock.EndPos } lastBlock.EndPos = lastBlock.EndPos + extendLength inode.Blocks[idx] = lastBlock inode.Length += extendLength } } // and add new blocks as necessary for newEndPos > inode.Length { // fmt.Printf("New end pos %d still greater than inode length %d\n", newEndPos, inode.Length) newBlockLength := newEndPos - inode.Length if newBlockLength > BLOCKLENGTH { newBlockLength = BLOCKLENGTH } newBlock, err := w.names.AddBlock(inode.Inodeid, uint32(newBlockLength)) if err != nil { return err } inode.Blocks = append(inode.Blocks, newBlock) inode.Length += newBlockLength } } inode.Mtime = time.Now().Unix() err := w.names.SetInode(inode) return err }
func (m *MaggieFuse) Symlink(out *raw.EntryOut, header *raw.InHeader, pointedTo string, linkName string) (code fuse.Status) { // new inode type symlink currTime := time.Now().Unix() i := maggiefs.Inode{ 0, // id 0 to start, we get id when inserting 0, maggiefs.FTYPE_LNK, 0, 0777, currTime, currTime, 0, header.Uid, header.Gid, pointedTo, make([]maggiefs.Block, 0, 0), make(map[string]maggiefs.Dentry), make(map[string][]byte), } // save id, err := m.names.AddInode(&i) if err != nil { return fuse.EROFS } i.Inodeid = id // link parent err = m.names.Link(header.NodeId, i.Inodeid, linkName, false) if err != nil { if err == maggiefs.E_EXISTS { return fuse.Status(syscall.EEXIST) } else if err == maggiefs.E_NOTDIR { return fuse.ENOTDIR } return fuse.EROFS } // send entry back to child fillEntryOut(out, &i) return fuse.OK }
func fillAttrOut(out *raw.AttrOut, i *maggiefs.Inode) { // raw.Attr out.Ino = i.Inodeid out.Size = i.Length out.Blocks = numBlocks(i.Length, maggiefs.PAGESIZE) out.Atime = uint64(0) // always 0 for atime out.Mtime = uint64(i.Mtime) // Mtime is user modifiable and is the last time data changed out.Ctime = uint64(i.Ctime) // Ctime is tracked by the FS and changes when attrs or data change out.Atimensec = uint32(0) out.Mtimensec = uint32(0) out.Ctimensec = uint32(0) out.Mode = i.FullMode() out.Nlink = i.Nlink out.Uid = i.Uid out.Gid = i.Gid out.Rdev = uint32(0) // regular file, not block dvice out.Blksize = maggiefs.PAGESIZE // raw.AttrOut out.AttrValid = uint64(0) out.AttrValidNsec = uint32(100) fmt.Printf("Filled attrOut %v with inode %v\n", out, i) }