1433d6423SLionel Sambuc #include "fs.h"
2433d6423SLionel Sambuc #include <string.h>
3433d6423SLionel Sambuc #include <sys/stat.h>
4433d6423SLionel Sambuc #include <sys/statvfs.h>
5433d6423SLionel Sambuc #include "inode.h"
6433d6423SLionel Sambuc #include "super.h"
7433d6423SLionel Sambuc
8433d6423SLionel Sambuc /*===========================================================================*
9433d6423SLionel Sambuc * estimate_blocks *
10433d6423SLionel Sambuc *===========================================================================*/
estimate_blocks(struct inode * rip)11433d6423SLionel Sambuc static blkcnt_t estimate_blocks(struct inode *rip)
12433d6423SLionel Sambuc {
13433d6423SLionel Sambuc /* Return the number of 512-byte blocks used by this file. This includes space
14433d6423SLionel Sambuc * used by data zones and indirect blocks (actually also zones). Reading in all
15433d6423SLionel Sambuc * indirect blocks is too costly for a stat call, so we disregard holes and
16433d6423SLionel Sambuc * return a conservative estimation.
17433d6423SLionel Sambuc */
18433d6423SLionel Sambuc blkcnt_t zones, sindirs, dindirs, nr_indirs, sq_indirs;
19433d6423SLionel Sambuc unsigned int zone_size;
20433d6423SLionel Sambuc
21433d6423SLionel Sambuc /* Compute the number of zones used by the file. */
22433d6423SLionel Sambuc zone_size = rip->i_sp->s_block_size << rip->i_sp->s_log_zone_size;
23433d6423SLionel Sambuc
24433d6423SLionel Sambuc zones = (blkcnt_t) ((rip->i_size + zone_size - 1) / zone_size);
25433d6423SLionel Sambuc
26433d6423SLionel Sambuc /* Compute the number of indirect blocks needed for that zone count. */
27433d6423SLionel Sambuc nr_indirs = (blkcnt_t) rip->i_nindirs;
28433d6423SLionel Sambuc sq_indirs = nr_indirs * nr_indirs;
29433d6423SLionel Sambuc
30433d6423SLionel Sambuc sindirs = (zones - (blkcnt_t) rip->i_ndzones + nr_indirs - 1) / nr_indirs;
31433d6423SLionel Sambuc dindirs = (sindirs - 1 + sq_indirs - 1) / sq_indirs;
32433d6423SLionel Sambuc
33433d6423SLionel Sambuc /* Return the number of 512-byte blocks corresponding to the number of data
34433d6423SLionel Sambuc * zones and indirect blocks.
35433d6423SLionel Sambuc */
36433d6423SLionel Sambuc return (zones + sindirs + dindirs) * (blkcnt_t) (zone_size / 512);
37433d6423SLionel Sambuc }
38433d6423SLionel Sambuc
39433d6423SLionel Sambuc
40ccaeedb2SDavid van Moolenbroek /*===========================================================================*
41ccaeedb2SDavid van Moolenbroek * fs_stat *
42ccaeedb2SDavid van Moolenbroek *===========================================================================*/
fs_stat(ino_t ino_nr,struct stat * statbuf)43ccaeedb2SDavid van Moolenbroek int fs_stat(ino_t ino_nr, struct stat *statbuf)
44ccaeedb2SDavid van Moolenbroek {
45ccaeedb2SDavid van Moolenbroek struct inode *rip;
46433d6423SLionel Sambuc mode_t mo;
47ccaeedb2SDavid van Moolenbroek int s;
48ccaeedb2SDavid van Moolenbroek
49ccaeedb2SDavid van Moolenbroek if ((rip = get_inode(fs_dev, ino_nr)) == NULL)
50ccaeedb2SDavid van Moolenbroek return(EINVAL);
51433d6423SLionel Sambuc
52433d6423SLionel Sambuc /* Update the atime, ctime, and mtime fields in the inode, if need be. */
53433d6423SLionel Sambuc if (rip->i_update) update_times(rip);
54433d6423SLionel Sambuc
55433d6423SLionel Sambuc /* Fill in the statbuf struct. */
56433d6423SLionel Sambuc mo = rip->i_mode & I_TYPE;
57433d6423SLionel Sambuc
58433d6423SLionel Sambuc /* true iff special */
59433d6423SLionel Sambuc s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL);
60433d6423SLionel Sambuc
61ccaeedb2SDavid van Moolenbroek statbuf->st_mode = (mode_t) rip->i_mode;
62ccaeedb2SDavid van Moolenbroek statbuf->st_nlink = (nlink_t) rip->i_nlinks;
63ccaeedb2SDavid van Moolenbroek statbuf->st_uid = rip->i_uid;
64ccaeedb2SDavid van Moolenbroek statbuf->st_gid = rip->i_gid;
65ccaeedb2SDavid van Moolenbroek statbuf->st_rdev = (s ? (dev_t)rip->i_zone[0] : NO_DEV);
66ccaeedb2SDavid van Moolenbroek statbuf->st_size = rip->i_size;
67ccaeedb2SDavid van Moolenbroek statbuf->st_atime = rip->i_atime;
68ccaeedb2SDavid van Moolenbroek statbuf->st_mtime = rip->i_mtime;
69ccaeedb2SDavid van Moolenbroek statbuf->st_ctime = rip->i_ctime;
70ccaeedb2SDavid van Moolenbroek statbuf->st_blksize = lmfs_fs_block_size();
71ccaeedb2SDavid van Moolenbroek statbuf->st_blocks = estimate_blocks(rip);
72433d6423SLionel Sambuc
73ccaeedb2SDavid van Moolenbroek put_inode(rip); /* release the inode */
74433d6423SLionel Sambuc
75ccaeedb2SDavid van Moolenbroek return(OK);
76433d6423SLionel Sambuc }
77433d6423SLionel Sambuc
78ccaeedb2SDavid van Moolenbroek
79433d6423SLionel Sambuc /*===========================================================================*
80433d6423SLionel Sambuc * fs_statvfs *
81433d6423SLionel Sambuc *===========================================================================*/
fs_statvfs(struct statvfs * st)82ccaeedb2SDavid van Moolenbroek int fs_statvfs(struct statvfs *st)
83433d6423SLionel Sambuc {
84433d6423SLionel Sambuc struct super_block *sp;
85ccaeedb2SDavid van Moolenbroek int scale;
86433d6423SLionel Sambuc
87*4472b590SDavid van Moolenbroek sp = &superblock;
88433d6423SLionel Sambuc
89433d6423SLionel Sambuc scale = sp->s_log_zone_size;
90433d6423SLionel Sambuc
911311233cSDavid van Moolenbroek st->f_blocks = sp->s_zones;
921311233cSDavid van Moolenbroek st->f_bfree = sp->s_zones - used_zones;
93ccaeedb2SDavid van Moolenbroek st->f_bavail = st->f_bfree;
94433d6423SLionel Sambuc
95ccaeedb2SDavid van Moolenbroek st->f_bsize = sp->s_block_size << scale;
96ccaeedb2SDavid van Moolenbroek st->f_frsize = sp->s_block_size;
97ccaeedb2SDavid van Moolenbroek st->f_iosize = st->f_frsize;
98ccaeedb2SDavid van Moolenbroek st->f_files = sp->s_ninodes;
99ccaeedb2SDavid van Moolenbroek st->f_ffree = count_free_bits(sp, IMAP);
100ccaeedb2SDavid van Moolenbroek st->f_favail = st->f_ffree;
101ccaeedb2SDavid van Moolenbroek st->f_namemax = MFS_DIRSIZ;
102433d6423SLionel Sambuc
103ccaeedb2SDavid van Moolenbroek return(OK);
104433d6423SLionel Sambuc }
105