You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							115 lines
						
					
					
						
							3.3 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							115 lines
						
					
					
						
							3.3 KiB
						
					
					
				
								package mount
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"context"
							 | 
						|
									"fmt"
							 | 
						|
									"github.com/hanwen/go-fuse/v2/fuse"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/glog"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
							 | 
						|
									"math"
							 | 
						|
									"time"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								const blockSize = 512
							 | 
						|
								
							 | 
						|
								type statsCache struct {
							 | 
						|
									filer_pb.StatisticsResponse
							 | 
						|
									lastChecked int64 // unix time in seconds
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (wfs *WFS) StatFs(cancel <-chan struct{}, in *fuse.InHeader, out *fuse.StatfsOut) (code fuse.Status) {
							 | 
						|
								
							 | 
						|
									// glog.V(4).Infof("reading fs stats")
							 | 
						|
								
							 | 
						|
									if wfs.stats.lastChecked < time.Now().Unix()-20 {
							 | 
						|
								
							 | 
						|
										err := wfs.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
							 | 
						|
								
							 | 
						|
											request := &filer_pb.StatisticsRequest{
							 | 
						|
												Collection:  wfs.option.Collection,
							 | 
						|
												Replication: wfs.option.Replication,
							 | 
						|
												Ttl:         fmt.Sprintf("%ds", wfs.option.TtlSec),
							 | 
						|
												DiskType:    string(wfs.option.DiskType),
							 | 
						|
											}
							 | 
						|
								
							 | 
						|
											glog.V(4).Infof("reading filer stats: %+v", request)
							 | 
						|
											resp, err := client.Statistics(context.Background(), request)
							 | 
						|
											if err != nil {
							 | 
						|
												glog.V(0).Infof("reading filer stats %v: %v", request, err)
							 | 
						|
												return err
							 | 
						|
											}
							 | 
						|
											glog.V(4).Infof("read filer stats: %+v", resp)
							 | 
						|
								
							 | 
						|
											wfs.stats.TotalSize = resp.TotalSize
							 | 
						|
											wfs.stats.UsedSize = resp.UsedSize
							 | 
						|
											wfs.stats.FileCount = resp.FileCount
							 | 
						|
											wfs.stats.lastChecked = time.Now().Unix()
							 | 
						|
								
							 | 
						|
											return nil
							 | 
						|
										})
							 | 
						|
										if err != nil {
							 | 
						|
											glog.V(0).Infof("filer Statistics: %v", err)
							 | 
						|
											return fuse.OK
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									totalDiskSize := wfs.stats.TotalSize
							 | 
						|
									usedDiskSize := wfs.stats.UsedSize
							 | 
						|
									actualFileCount := wfs.stats.FileCount
							 | 
						|
								
							 | 
						|
									if wfs.option.Quota > 0 && totalDiskSize > uint64(wfs.option.Quota) {
							 | 
						|
										totalDiskSize = uint64(wfs.option.Quota)
							 | 
						|
										if usedDiskSize > totalDiskSize {
							 | 
						|
											totalDiskSize = usedDiskSize
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// 	http://man.he.net/man2/statfs
							 | 
						|
									/*
							 | 
						|
										   struct statfs {
							 | 
						|
											   __fsword_t f_type;    // Type of filesystem (see below)
							 | 
						|
											   __fsword_t f_bsize;   // Optimal transfer block size
							 | 
						|
											   fsblkcnt_t f_blocks;  // Total data blocks in filesystem
							 | 
						|
											   fsblkcnt_t f_bfree;   // Free blocks in filesystem
							 | 
						|
											   fsblkcnt_t f_bavail;  // Free blocks available to
							 | 
						|
																		unprivileged user
							 | 
						|
											   fsfilcnt_t f_files;   // Total file nodes in filesystem
							 | 
						|
											   fsfilcnt_t f_ffree;   // Free file nodes in filesystem
							 | 
						|
											   fsid_t     f_fsid;    // Filesystem ID
							 | 
						|
											   __fsword_t f_namelen; // Maximum length of filenames
							 | 
						|
											   __fsword_t f_frsize;  // Fragment size (since Linux 2.6)
							 | 
						|
											   __fsword_t f_flags;   // Mount flags of filesystem
							 | 
						|
																		(since Linux 2.6.36)
							 | 
						|
											   __fsword_t f_spare[xxx];
							 | 
						|
															   // Padding bytes reserved for future use
							 | 
						|
										   };
							 | 
						|
									*/
							 | 
						|
								
							 | 
						|
									// Compute the total number of available blocks
							 | 
						|
									out.Blocks = totalDiskSize / blockSize
							 | 
						|
									if out.Blocks <= 0 {
							 | 
						|
										out.Blocks = 1
							 | 
						|
									}
							 | 
						|
									// Compute the number of used blocks
							 | 
						|
									numBlocks := usedDiskSize / blockSize
							 | 
						|
								
							 | 
						|
									remainingBlocks := int64(out.Blocks) - int64(numBlocks)
							 | 
						|
									if remainingBlocks < 0 {
							 | 
						|
										remainingBlocks = 0
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Report the number of free and available blocks for the block size
							 | 
						|
									out.Bfree = uint64(remainingBlocks)
							 | 
						|
									out.Bavail = uint64(remainingBlocks)
							 | 
						|
									out.Bsize = uint32(blockSize)
							 | 
						|
								
							 | 
						|
									// Report the total number of possible files in the file system (and those free)
							 | 
						|
									out.Files = math.MaxInt64
							 | 
						|
									out.Ffree = math.MaxInt64 - actualFileCount
							 | 
						|
								
							 | 
						|
									// Report the maximum length of a name and the minimum fragment size
							 | 
						|
									out.NameLen = 1024
							 | 
						|
									out.Frsize = uint32(blockSize)
							 | 
						|
								
							 | 
						|
									return fuse.OK
							 | 
						|
								}
							 |