chrislu
3 years ago
1 changed files with 93 additions and 0 deletions
@ -0,0 +1,93 @@ |
|||||
|
package mount |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"github.com/chrislusf/seaweedfs/weed/filer" |
||||
|
"github.com/chrislusf/seaweedfs/weed/glog" |
||||
|
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb" |
||||
|
"github.com/chrislusf/seaweedfs/weed/util" |
||||
|
"github.com/hanwen/go-fuse/v2/fuse" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
const ( |
||||
|
HARD_LINK_MARKER = '\x01' |
||||
|
) |
||||
|
|
||||
|
/** Create a hard link to a file */ |
||||
|
func (wfs *WFS) Link(cancel <-chan struct{}, in *fuse.LinkIn, name string, out *fuse.EntryOut) (code fuse.Status) { |
||||
|
|
||||
|
if s := checkName(name); s != fuse.OK { |
||||
|
return s |
||||
|
} |
||||
|
|
||||
|
newParentPath := wfs.inodeToPath.GetPath(in.NodeId) |
||||
|
oldEntryPath := wfs.inodeToPath.GetPath(in.Oldnodeid) |
||||
|
oldParentPath, _ := oldEntryPath.DirAndName() |
||||
|
|
||||
|
oldEntry, status := wfs.maybeLoadEntry(oldEntryPath) |
||||
|
if status != fuse.OK { |
||||
|
return status |
||||
|
} |
||||
|
|
||||
|
// update old file to hardlink mode
|
||||
|
if len(oldEntry.HardLinkId) == 0 { |
||||
|
oldEntry.HardLinkId = append(util.RandomBytes(16), HARD_LINK_MARKER) |
||||
|
oldEntry.HardLinkCounter = 1 |
||||
|
} |
||||
|
oldEntry.HardLinkCounter++ |
||||
|
updateOldEntryRequest := &filer_pb.UpdateEntryRequest{ |
||||
|
Directory: oldParentPath, |
||||
|
Entry: oldEntry, |
||||
|
Signatures: []int32{wfs.signature}, |
||||
|
} |
||||
|
|
||||
|
// CreateLink 1.2 : update new file to hardlink mode
|
||||
|
oldEntry.Attributes.Mtime = time.Now().Unix() |
||||
|
request := &filer_pb.CreateEntryRequest{ |
||||
|
Directory: string(newParentPath), |
||||
|
Entry: &filer_pb.Entry{ |
||||
|
Name: name, |
||||
|
IsDirectory: false, |
||||
|
Attributes: oldEntry.Attributes, |
||||
|
Chunks: oldEntry.Chunks, |
||||
|
Extended: oldEntry.Extended, |
||||
|
HardLinkId: oldEntry.HardLinkId, |
||||
|
HardLinkCounter: oldEntry.HardLinkCounter, |
||||
|
}, |
||||
|
Signatures: []int32{wfs.signature}, |
||||
|
} |
||||
|
|
||||
|
// apply changes to the filer, and also apply to local metaCache
|
||||
|
err := wfs.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error { |
||||
|
|
||||
|
wfs.mapPbIdFromLocalToFiler(request.Entry) |
||||
|
defer wfs.mapPbIdFromFilerToLocal(request.Entry) |
||||
|
|
||||
|
if err := filer_pb.UpdateEntry(client, updateOldEntryRequest); err != nil { |
||||
|
return err |
||||
|
} |
||||
|
wfs.metaCache.UpdateEntry(context.Background(), filer.FromPbEntry(updateOldEntryRequest.Directory, updateOldEntryRequest.Entry)) |
||||
|
|
||||
|
if err := filer_pb.CreateEntry(client, request); err != nil { |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
wfs.metaCache.InsertEntry(context.Background(), filer.FromPbEntry(request.Directory, request.Entry)) |
||||
|
|
||||
|
return nil |
||||
|
}) |
||||
|
|
||||
|
newEntryPath := newParentPath.Child(name) |
||||
|
|
||||
|
if err != nil { |
||||
|
glog.V(0).Infof("Link %v -> %s: %v", oldEntryPath, newEntryPath, err) |
||||
|
return fuse.EIO |
||||
|
} |
||||
|
|
||||
|
inode := wfs.inodeToPath.GetInode(newEntryPath) |
||||
|
|
||||
|
wfs.outputPbEntry(out, inode, request.Entry) |
||||
|
|
||||
|
return fuse.OK |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue