1 #include "fs.h" 2 #include <string.h> 3 #include <sys/stat.h> 4 #include <sys/statvfs.h> 5 #include "inode.h" 6 #include "super.h" 7 8 /*===========================================================================* 9 * estimate_blocks * 10 *===========================================================================*/ 11 static blkcnt_t estimate_blocks(struct inode *rip) 12 { 13 /* Return the number of 512-byte blocks used by this file. This includes space 14 * used by data zones and indirect blocks (actually also zones). Reading in all 15 * indirect blocks is too costly for a stat call, so we disregard holes and 16 * return a conservative estimation. 17 */ 18 blkcnt_t zones, sindirs, dindirs, nr_indirs, sq_indirs; 19 unsigned int zone_size; 20 21 /* Compute the number of zones used by the file. */ 22 zone_size = rip->i_sp->s_block_size << rip->i_sp->s_log_zone_size; 23 24 zones = (blkcnt_t) ((rip->i_size + zone_size - 1) / zone_size); 25 26 /* Compute the number of indirect blocks needed for that zone count. */ 27 nr_indirs = (blkcnt_t) rip->i_nindirs; 28 sq_indirs = nr_indirs * nr_indirs; 29 30 sindirs = (zones - (blkcnt_t) rip->i_ndzones + nr_indirs - 1) / nr_indirs; 31 dindirs = (sindirs - 1 + sq_indirs - 1) / sq_indirs; 32 33 /* Return the number of 512-byte blocks corresponding to the number of data 34 * zones and indirect blocks. 35 */ 36 return (zones + sindirs + dindirs) * (blkcnt_t) (zone_size / 512); 37 } 38 39 40 /*===========================================================================* 41 * fs_stat * 42 *===========================================================================*/ 43 int fs_stat(ino_t ino_nr, struct stat *statbuf) 44 { 45 struct inode *rip; 46 mode_t mo; 47 int s; 48 49 if ((rip = get_inode(fs_dev, ino_nr)) == NULL) 50 return(EINVAL); 51 52 /* Update the atime, ctime, and mtime fields in the inode, if need be. */ 53 if (rip->i_update) update_times(rip); 54 55 /* Fill in the statbuf struct. */ 56 mo = rip->i_mode & I_TYPE; 57 58 /* true iff special */ 59 s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL); 60 61 statbuf->st_mode = (mode_t) rip->i_mode; 62 statbuf->st_nlink = (nlink_t) rip->i_nlinks; 63 statbuf->st_uid = rip->i_uid; 64 statbuf->st_gid = rip->i_gid; 65 statbuf->st_rdev = (s ? (dev_t)rip->i_zone[0] : NO_DEV); 66 statbuf->st_size = rip->i_size; 67 statbuf->st_atime = rip->i_atime; 68 statbuf->st_mtime = rip->i_mtime; 69 statbuf->st_ctime = rip->i_ctime; 70 statbuf->st_blksize = lmfs_fs_block_size(); 71 statbuf->st_blocks = estimate_blocks(rip); 72 73 put_inode(rip); /* release the inode */ 74 75 return(OK); 76 } 77 78 79 /*===========================================================================* 80 * fs_statvfs * 81 *===========================================================================*/ 82 int fs_statvfs(struct statvfs *st) 83 { 84 struct super_block *sp; 85 int scale; 86 87 sp = &superblock; 88 89 scale = sp->s_log_zone_size; 90 91 st->f_blocks = sp->s_zones; 92 st->f_bfree = sp->s_zones - used_zones; 93 st->f_bavail = st->f_bfree; 94 95 st->f_bsize = sp->s_block_size << scale; 96 st->f_frsize = sp->s_block_size; 97 st->f_iosize = st->f_frsize; 98 st->f_files = sp->s_ninodes; 99 st->f_ffree = count_free_bits(sp, IMAP); 100 st->f_favail = st->f_ffree; 101 st->f_namemax = MFS_DIRSIZ; 102 103 return(OK); 104 } 105