diff --git a/c_defs_linux.go b/c_defs_linux.go index abd9fd6..911e4f8 100644 --- a/c_defs_linux.go +++ b/c_defs_linux.go @@ -1,4 +1,4 @@ -// +build ignore +//go:build ignore // Copyright (c) 2018 Versity Software, Inc. // @@ -51,6 +51,8 @@ package scoutfs // typedef struct scoutfs_ioctl_search_xattrs scoutfs_ioctl_search_xattrs_t; // typedef struct scoutfs_ioctl_statfs_more scoutfs_ioctl_statfs_more_t; // typedef struct scoutfs_ioctl_alloc_detail scoutfs_ioctl_alloc_detail_t; +// typedef struct scoutfs_ioctl_read_xattr_totals scoutfs_ioctl_read_xattr_totals_t; +// typedef struct scoutfs_ioctl_xattr_total scoutfs_ioctl_xattr_total_t; // // // Go doesnt handle bitfields in structs, so we need to override the scoutfs // // struct definition here @@ -78,6 +80,7 @@ const IOCSTATFSMORE = C.SCOUTFS_IOC_STATFS_MORE const IOCDATAWAITERR = C.SCOUTFS_IOC_DATA_WAIT_ERR const IOCALLOCDETAIL = C.SCOUTFS_IOC_ALLOC_DETAIL const IOCMOVEBLOCKS = C.SCOUTFS_IOC_MOVE_BLOCKS +const IOCREADXATTRTOTALS = C.SCOUTFS_IOC_READ_XATTR_TOTALS const QUERYINODESMETASEQ = C.SCOUTFS_IOC_WALK_INODES_META_SEQ const QUERYINODESDATASEQ = C.SCOUTFS_IOC_WALK_INODES_DATA_SEQ @@ -106,5 +109,8 @@ type statfsMore C.scoutfs_ioctl_statfs_more_t type allocDetail C.scoutfs_ioctl_alloc_detail_t type allocDetailEntry C.scoutfs_ioctl_alloc_detail_entry_t type moveBlocks C.scoutfs_ioctl_move_blocks_t +type readXattrTotals C.scoutfs_ioctl_read_xattr_totals_t +type xattrTotal C.scoutfs_ioctl_xattr_total_t const sizeofstatfsMore = C.sizeof_scoutfs_ioctl_statfs_more_t +const sizeofxattrTotal = C.sizeof_scoutfs_ioctl_xattr_total_t diff --git a/examples/gettotl/main.go b/examples/gettotl/main.go new file mode 100644 index 0000000..e61f071 --- /dev/null +++ b/examples/gettotl/main.go @@ -0,0 +1,50 @@ +// Copyright (c) 2021 Versity Software, Inc. +// +// Use of this source code is governed by a BSD-3-Clause license +// that can be found in the LICENSE file in the root of the source +// tree. + +package main + +import ( + "fmt" + "log" + "os" + "strconv" + + scoutfs "github.com/versity/scoutfs-go" +) + +func main() { + if len(os.Args) != 5 || os.Args[1] == "-h" { + fmt.Fprintln(os.Stderr, "usage:", os.Args[0], " ") + os.Exit(1) + } + + f, err := os.Open(os.Args[1]) + if err != nil { + log.Fatalln("error open mount:", err) + } + defer f.Close() + + u1, err := strconv.ParseUint(os.Args[2], 10, 64) + if err != nil { + log.Fatalln("error parsing id1:", err) + } + u2, err := strconv.ParseUint(os.Args[3], 10, 64) + if err != nil { + log.Fatalln("error parsing id2:", err) + } + u3, err := strconv.ParseUint(os.Args[4], 10, 64) + if err != nil { + log.Fatalln("error parsing id3:", err) + } + + t, err := scoutfs.ReadXattrTotals(f, u1, u2, u3) + if err != nil { + log.Fatalln("error read totals:", err) + } + + fmt.Println("xattrs match: ", t.Count) + fmt.Println("total value : ", t.Total) +} diff --git a/scoutfs.go b/scoutfs.go index 61e9a89..2c7d633 100644 --- a/scoutfs.go +++ b/scoutfs.go @@ -10,6 +10,7 @@ import ( "bufio" "bytes" "encoding/binary" + "errors" "fmt" "io" "os" @@ -863,3 +864,41 @@ func StageMoveAt(from, to *os.File, len, fromOffset, toOffset, version uint64) e return nil } + +// XattrTotal has the total values matching id triple +type XattrTotal struct { + // Total is sum of all xattr values matching ids + Total uint64 + // Count is number of xattrs matching ids + Count uint64 +} + +var ( + // ErrNoTotal is a special error case indicating that there were + // no xattrs matching the totl ids + ErrNoTotal = errors.New("no totl found") +) + +// ReadXattrTotals returns the XattrTotal for the given id +func ReadXattrTotals(f *os.File, id1, id2, id3 uint64) (XattrTotal, error) { + totls := make([]xattrTotal, 1) + + query := readXattrTotals{ + Pos_name: [3]uint64{id1, id2, id3}, + Totals_ptr: uint64(uintptr(unsafe.Pointer(&totls[0]))), + Totals_bytes: sizeofxattrTotal, + } + + n, err := scoutfsctl(f, IOCREADXATTRTOTALS, unsafe.Pointer(&query)) + if err != nil { + return XattrTotal{}, err + } + if n == 0 { + return XattrTotal{}, ErrNoTotal + } + + return XattrTotal{ + Total: totls[0].Total, + Count: totls[0].Count, + }, nil +} diff --git a/scoutfsdefs.go b/scoutfsdefs.go index 3d2dae8..5b8b880 100644 --- a/scoutfsdefs.go +++ b/scoutfsdefs.go @@ -16,6 +16,7 @@ const IOCSTATFSMORE = 0x8038730a const IOCDATAWAITERR = 0x8030730b const IOCALLOCDETAIL = 0x8010730c const IOCMOVEBLOCKS = 0x8030730d +const IOCREADXATTRTOTALS = 0x8028730f const QUERYINODESMETASEQ = 0x0 const QUERYINODESDATASEQ = 0x1 @@ -148,5 +149,16 @@ type moveBlocks struct { Data_version uint64 Flags uint64 } +type readXattrTotals struct { + Pos_name [3]uint64 + Totals_ptr uint64 + Totals_bytes uint64 +} +type xattrTotal struct { + Name [3]uint64 + Total uint64 + Count uint64 +} const sizeofstatfsMore = 0x38 +const sizeofxattrTotal = 0x28