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