Index: head/sys/sys/mount.h =================================================================== --- head/sys/sys/mount.h (revision 62552) +++ head/sys/sys/mount.h (revision 62553) @@ -1,481 +1,490 @@ /* * Copyright (c) 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)mount.h 8.21 (Berkeley) 5/20/95 * $FreeBSD$ */ #ifndef _SYS_MOUNT_H_ #define _SYS_MOUNT_H_ #include #ifndef _KERNEL #if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) #include #endif /* !_POSIX_C_SOURCE */ #endif /* !_KERNEL */ #include #include typedef struct fsid { int32_t val[2]; } fsid_t; /* file system id type */ /* * File identifier. * These are unique per filesystem on a single machine. */ #define MAXFIDSZ 16 struct fid { u_short fid_len; /* length of data in bytes */ u_short fid_reserved; /* force longword alignment */ char fid_data[MAXFIDSZ]; /* data (variable length) */ }; /* * file system statistics */ #define MFSNAMELEN 16 /* length of fs type name, including null */ #ifdef __i386__ #define MNAMELEN 80 /* length of buffer for returned name */ #endif #ifdef __alpha__ #define MNAMELEN 72 /* length of buffer for returned name */ #endif struct statfs { long f_spare2; /* placeholder */ long f_bsize; /* fundamental file system block size */ long f_iosize; /* optimal transfer block size */ long f_blocks; /* total data blocks in file system */ long f_bfree; /* free blocks in fs */ long f_bavail; /* free blocks avail to non-superuser */ long f_files; /* total file nodes in file system */ long f_ffree; /* free file nodes in fs */ fsid_t f_fsid; /* file system id */ uid_t f_owner; /* user that mounted the filesystem */ int f_type; /* type of filesystem */ int f_flags; /* copy of mount exported flags */ long f_syncwrites; /* count of sync writes since mount */ long f_asyncwrites; /* count of async writes since mount */ char f_fstypename[MFSNAMELEN]; /* fs type name */ char f_mntonname[MNAMELEN]; /* directory on which mounted */ long f_syncreads; /* count of sync reads since mount */ long f_asyncreads; /* count of async reads since mount */ short f_spares1; /* unused spare */ char f_mntfromname[MNAMELEN];/* mounted filesystem */ short f_spares2; /* unused spare */ long f_spare[2]; /* unused spare */ }; /* * Structure per mounted file system. Each mounted file system has an * array of operations and an instance record. The file systems are * put on a doubly linked list. */ LIST_HEAD(vnodelst, vnode); struct mount { TAILQ_ENTRY(mount) mnt_list; /* mount list */ struct vfsops *mnt_op; /* operations on fs */ struct vfsconf *mnt_vfc; /* configuration info */ struct vnode *mnt_vnodecovered; /* vnode we mounted on */ struct vnode *mnt_syncer; /* syncer vnode */ struct vnodelst mnt_vnodelist; /* list of vnodes this mount */ struct lock mnt_lock; /* mount structure lock */ + int mnt_writeopcount; /* write syscalls in progress */ int mnt_flag; /* flags shared with user */ int mnt_kern_flag; /* kernel only flags */ int mnt_maxsymlinklen; /* max size of short symlink */ struct statfs mnt_stat; /* cache of filesystem stats */ qaddr_t mnt_data; /* private data */ time_t mnt_time; /* last time written*/ u_int mnt_iosize_max; /* max IO request size */ }; /* * User specifiable flags. */ #define MNT_RDONLY 0x00000001 /* read only filesystem */ #define MNT_SYNCHRONOUS 0x00000002 /* file system written synchronously */ #define MNT_NOEXEC 0x00000004 /* can't exec from filesystem */ #define MNT_NOSUID 0x00000008 /* don't honor setuid bits on fs */ #define MNT_NODEV 0x00000010 /* don't interpret special files */ #define MNT_UNION 0x00000020 /* union with underlying filesystem */ #define MNT_ASYNC 0x00000040 /* file system written asynchronously */ #define MNT_SUIDDIR 0x00100000 /* special handling of SUID on dirs */ #define MNT_SOFTDEP 0x00200000 /* soft updates being done */ #define MNT_NOSYMFOLLOW 0x00400000 /* do not follow symlinks */ #define MNT_NOATIME 0x10000000 /* disable update of file access time */ #define MNT_NOCLUSTERR 0x40000000 /* disable cluster read */ #define MNT_NOCLUSTERW 0x80000000 /* disable cluster write */ /* * NFS export related mount flags. */ #define MNT_EXRDONLY 0x00000080 /* exported read only */ #define MNT_EXPORTED 0x00000100 /* file system is exported */ #define MNT_DEFEXPORTED 0x00000200 /* exported to the world */ #define MNT_EXPORTANON 0x00000400 /* use anon uid mapping for everyone */ #define MNT_EXKERB 0x00000800 /* exported with Kerberos uid mapping */ #define MNT_EXPUBLIC 0x20000000 /* public export (WebNFS) */ /* * Flags set by internal operations, * but visible to the user. * XXX some of these are not quite right.. (I've never seen the root flag set) */ #define MNT_LOCAL 0x00001000 /* filesystem is stored locally */ #define MNT_QUOTA 0x00002000 /* quotas are enabled on filesystem */ #define MNT_ROOTFS 0x00004000 /* identifies the root filesystem */ #define MNT_USER 0x00008000 /* mounted by a user */ #define MNT_IGNORE 0x00800000 /* do not show entry in df */ /* * Mask of flags that are visible to statfs() * XXX I think that this could now become (~(MNT_CMDFLAGS)) * but the 'mount' program may need changing to handle this. - * XXX MNT_EXPUBLIC is presently left out. I don't know why. */ #define MNT_VISFLAGMASK (MNT_RDONLY | MNT_SYNCHRONOUS | MNT_NOEXEC | \ MNT_NOSUID | MNT_NODEV | MNT_UNION | \ MNT_ASYNC | MNT_EXRDONLY | MNT_EXPORTED | \ MNT_DEFEXPORTED | MNT_EXPORTANON| MNT_EXKERB | \ MNT_LOCAL | MNT_USER | MNT_QUOTA | \ MNT_ROOTFS | MNT_NOATIME | MNT_NOCLUSTERR| \ MNT_NOCLUSTERW | MNT_SUIDDIR | MNT_SOFTDEP | \ - MNT_IGNORE \ - /* | MNT_EXPUBLIC */) + MNT_IGNORE | MNT_EXPUBLIC | MNT_NOSYMFOLLOW) /* * External filesystem command modifier flags. * Unmount can use the MNT_FORCE flag. * XXX These are not STATES and really should be somewhere else. */ #define MNT_UPDATE 0x00010000 /* not a real mount, just an update */ #define MNT_DELEXPORT 0x00020000 /* delete export host lists */ #define MNT_RELOAD 0x00040000 /* reload filesystem data */ #define MNT_FORCE 0x00080000 /* force unmount or readonly change */ -#define MNT_CMDFLAGS (MNT_UPDATE|MNT_DELEXPORT|MNT_RELOAD|MNT_FORCE) +#define MNT_SNAPSHOT 0x01000000 /* snapshot the filesystem */ +#define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \ + MNT_FORCE | MNT_SNAPSHOT) /* + * Still available + */ +#define MNT_SPARE1 0x02000000 +#define MNT_SPARE2 0x04000000 +#define MNT_SPARE3 0x08000000 +/* * Internal filesystem control flags stored in mnt_kern_flag. * * MNTK_UNMOUNT locks the mount entry so that name lookup cannot proceed * past the mount point. This keeps the subtree stable during mounts * and unmounts. */ #define MNTK_UNMOUNT 0x01000000 /* unmount in progress */ #define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */ #define MNTK_WANTRDWR 0x04000000 /* upgrade to read/write requested */ +#define MNTK_SUSPEND 0x08000000 /* request write suspension */ +#define MNTK_SUSPENDED 0x10000000 /* write operations are suspended */ /* * Sysctl CTL_VFS definitions. * * Second level identifier specifies which filesystem. Second level * identifier VFS_VFSCONF returns information about all filesystems. * Second level identifier VFS_GENERIC is non-terminal. */ #define VFS_VFSCONF 0 /* get configured filesystems */ #define VFS_GENERIC 0 /* generic filesystem information */ /* * Third level identifiers for VFS_GENERIC are given below; third * level identifiers for specific filesystems are given in their * mount specific header files. */ #define VFS_MAXTYPENUM 1 /* int: highest defined filesystem type */ #define VFS_CONF 2 /* struct: vfsconf for filesystem given as next argument */ /* * Flags for various system call interfaces. * * waitfor flags to vfs_sync() and getfsstat() */ #define MNT_WAIT 1 /* synchronously wait for I/O to complete */ #define MNT_NOWAIT 2 /* start all I/O, but do not wait for it */ #define MNT_LAZY 3 /* push data not written by filesystem syncer */ /* * Generic file handle */ struct fhandle { fsid_t fh_fsid; /* File system id of mount point */ struct fid fh_fid; /* File sys specific id */ }; typedef struct fhandle fhandle_t; /* * Export arguments for local filesystem mount calls. */ struct export_args { int ex_flags; /* export related flags */ uid_t ex_root; /* mapping for root uid */ struct ucred ex_anon; /* mapping for anonymous user */ struct sockaddr *ex_addr; /* net address to which exported */ int ex_addrlen; /* and the net address length */ struct sockaddr *ex_mask; /* mask of valid bits in saddr */ int ex_masklen; /* and the smask length */ char *ex_indexfile; /* index file for WebNFS URLs */ }; /* * Structure holding information for a publicly exported filesystem * (WebNFS). Currently the specs allow just for one such filesystem. */ struct nfs_public { int np_valid; /* Do we hold valid information */ fhandle_t np_handle; /* Filehandle for pub fs (internal) */ struct mount *np_mount; /* Mountpoint of exported fs */ char *np_index; /* Index file */ }; /* * Filesystem configuration information. One of these exists for each * type of filesystem supported by the kernel. These are searched at * mount time to identify the requested filesystem. */ struct vfsconf { struct vfsops *vfc_vfsops; /* filesystem operations vector */ char vfc_name[MFSNAMELEN]; /* filesystem type name */ int vfc_typenum; /* historic filesystem type number */ int vfc_refcount; /* number mounted of this type */ int vfc_flags; /* permanent flags */ struct vfsconf *vfc_next; /* next in list */ }; struct ovfsconf { void *vfc_vfsops; char vfc_name[32]; int vfc_index; int vfc_refcount; int vfc_flags; }; /* * NB: these flags refer to IMPLEMENTATION properties, not properties of * any actual mounts; i.e., it does not make sense to change the flags. */ #define VFCF_STATIC 0x00010000 /* statically compiled into kernel */ #define VFCF_NETWORK 0x00020000 /* may get data over the network */ #define VFCF_READONLY 0x00040000 /* writes are not implemented */ #define VFCF_SYNTHETIC 0x00080000 /* data does not represent real files */ #define VFCF_LOOPBACK 0x00100000 /* aliases some other mounted FS */ #define VFCF_UNICODE 0x00200000 /* stores file names as Unicode*/ #ifdef _KERNEL #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_MOUNT); #endif extern int maxvfsconf; /* highest defined filesystem type */ extern int nfs_mount_type; /* vfc_typenum for nfs, or -1 */ extern struct vfsconf *vfsconf; /* head of list of filesystem types */ /* * Operations supported on mounted file system. */ #ifdef __STDC__ struct nameidata; struct mbuf; #endif struct vfsops { int (*vfs_mount) __P((struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct proc *p)); int (*vfs_start) __P((struct mount *mp, int flags, struct proc *p)); int (*vfs_unmount) __P((struct mount *mp, int mntflags, struct proc *p)); int (*vfs_root) __P((struct mount *mp, struct vnode **vpp)); int (*vfs_quotactl) __P((struct mount *mp, int cmds, uid_t uid, caddr_t arg, struct proc *p)); int (*vfs_statfs) __P((struct mount *mp, struct statfs *sbp, struct proc *p)); int (*vfs_sync) __P((struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)); int (*vfs_vget) __P((struct mount *mp, ino_t ino, struct vnode **vpp)); int (*vfs_fhtovp) __P((struct mount *mp, struct fid *fhp, struct vnode **vpp)); int (*vfs_checkexp) __P((struct mount *mp, struct sockaddr *nam, int *extflagsp, struct ucred **credanonp)); int (*vfs_vptofh) __P((struct vnode *vp, struct fid *fhp)); int (*vfs_init) __P((struct vfsconf *)); int (*vfs_uninit) __P((struct vfsconf *)); int (*vfs_extattrctl) __P((struct mount *mp, int cmd, const char *attrname, caddr_t arg, struct proc *p)); }; #define VFS_MOUNT(MP, PATH, DATA, NDP, P) \ (*(MP)->mnt_op->vfs_mount)(MP, PATH, DATA, NDP, P) #define VFS_START(MP, FLAGS, P) (*(MP)->mnt_op->vfs_start)(MP, FLAGS, P) #define VFS_UNMOUNT(MP, FORCE, P) (*(MP)->mnt_op->vfs_unmount)(MP, FORCE, P) #define VFS_ROOT(MP, VPP) (*(MP)->mnt_op->vfs_root)(MP, VPP) #define VFS_QUOTACTL(MP,C,U,A,P) (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A, P) #define VFS_STATFS(MP, SBP, P) (*(MP)->mnt_op->vfs_statfs)(MP, SBP, P) #define VFS_SYNC(MP, WAIT, C, P) (*(MP)->mnt_op->vfs_sync)(MP, WAIT, C, P) #define VFS_VGET(MP, INO, VPP) (*(MP)->mnt_op->vfs_vget)(MP, INO, VPP) #define VFS_FHTOVP(MP, FIDP, VPP) \ (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP) #define VFS_VPTOFH(VP, FIDP) (*(VP)->v_mount->mnt_op->vfs_vptofh)(VP, FIDP) #define VFS_CHECKEXP(MP, NAM, EXFLG, CRED) \ (*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED) #define VFS_EXTATTRCTL(MP, C, N, A, P) \ (*(MP)->mnt_op->vfs_extattrctl)(MP, C, N, A, P) #include #define VFS_SET(vfsops, fsname, flags) \ static struct vfsconf fsname ## _vfsconf = { \ &vfsops, \ #fsname, \ -1, \ 0, \ flags \ }; \ static moduledata_t fsname ## _mod = { \ #fsname, \ vfs_modevent, \ & fsname ## _vfsconf \ }; \ DECLARE_MODULE(fsname, fsname ## _mod, SI_SUB_VFS, SI_ORDER_MIDDLE) #include #define AF_MAX 33 /* XXX */ /* * Network address lookup element */ struct netcred { struct radix_node netc_rnodes[2]; int netc_exflags; struct ucred netc_anon; }; /* * Network export information */ struct netexport { struct netcred ne_defexported; /* Default export */ struct radix_node_head *ne_rtable[AF_MAX+1]; /* Individual exports */ }; extern char *mountrootfsname; /* * exported vnode operations */ int dounmount __P((struct mount *, int, struct proc *)); int vfs_setpublicfs /* set publicly exported fs */ __P((struct mount *, struct netexport *, struct export_args *)); int vfs_lock __P((struct mount *)); /* lock a vfs */ void vfs_msync __P((struct mount *, int)); void vfs_unlock __P((struct mount *)); /* unlock a vfs */ int vfs_busy __P((struct mount *, int, struct simplelock *, struct proc *)); int vfs_export /* process mount export info */ __P((struct mount *, struct netexport *, struct export_args *)); struct netcred *vfs_export_lookup /* lookup host in fs export list */ __P((struct mount *, struct netexport *, struct sockaddr *)); int vfs_allocate_syncvnode __P((struct mount *)); void vfs_getnewfsid __P((struct mount *)); dev_t vfs_getrootfsid __P((struct mount *)); struct mount *vfs_getvfs __P((fsid_t *)); /* return vfs given fsid */ int vfs_modevent __P((module_t, int, void *)); int vfs_mountedon __P((struct vnode *)); /* is a vfs mounted on vp */ int vfs_rootmountalloc __P((char *, char *, struct mount **)); void vfs_unbusy __P((struct mount *, struct proc *)); void vfs_unmountall __P((void)); int vfs_register __P((struct vfsconf *)); int vfs_unregister __P((struct vfsconf *)); extern TAILQ_HEAD(mntlist, mount) mountlist; /* mounted filesystem list */ extern struct simplelock mountlist_slock; extern struct nfs_public nfs_pub; /* * Declarations for these vfs default operations are located in * kern/vfs_default.c, they should be used instead of making "dummy" * functions or casting entries in the VFS op table to "enopnotsupp()". */ int vfs_stdmount __P((struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct proc *p)); int vfs_stdstart __P((struct mount *mp, int flags, struct proc *p)); int vfs_stdunmount __P((struct mount *mp, int mntflags, struct proc *p)); int vfs_stdroot __P((struct mount *mp, struct vnode **vpp)); int vfs_stdquotactl __P((struct mount *mp, int cmds, uid_t uid, caddr_t arg, struct proc *p)); int vfs_stdstatfs __P((struct mount *mp, struct statfs *sbp, struct proc *p)); int vfs_stdsync __P((struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)); int vfs_stdvget __P((struct mount *mp, ino_t ino, struct vnode **vpp)); int vfs_stdfhtovp __P((struct mount *mp, struct fid *fhp, struct vnode **vpp)); int vfs_stdcheckexp __P((struct mount *mp, struct sockaddr *nam, int *extflagsp, struct ucred **credanonp)); int vfs_stdvptofh __P((struct vnode *vp, struct fid *fhp)); int vfs_stdinit __P((struct vfsconf *)); int vfs_stduninit __P((struct vfsconf *)); int vfs_stdextattrctl __P((struct mount *mp, int cmd, const char *attrname, caddr_t arg, struct proc *p)); int softdep_process_worklist __P((struct mount *)); #else /* !_KERNEL */ #include __BEGIN_DECLS int fstatfs __P((int, struct statfs *)); int getfh __P((const char *, fhandle_t *)); int getfsstat __P((struct statfs *, long, int)); int getmntinfo __P((struct statfs **, int)); int mount __P((const char *, const char *, int, void *)); int statfs __P((const char *, struct statfs *)); int unmount __P((const char *, int)); int fhopen __P((const struct fhandle *, int)); int fhstat __P((const struct fhandle *, struct stat *)); int fhstatfs __P((const struct fhandle *, struct statfs *)); /* C library stuff */ void endvfsent __P((void)); struct ovfsconf *getvfsbyname __P((const char *)); struct ovfsconf *getvfsbytype __P((int)); struct ovfsconf *getvfsent __P((void)); #define getvfsbyname new_getvfsbyname int new_getvfsbyname __P((const char *, struct vfsconf *)); void setvfsent __P((int)); int vfsisloadable __P((const char *)); int vfsload __P((const char *)); __END_DECLS #endif /* _KERNEL */ #endif /* !_SYS_MOUNT_H_ */ Index: head/sys/sys/stat.h =================================================================== --- head/sys/sys/stat.h (revision 62552) +++ head/sys/sys/stat.h (revision 62553) @@ -1,260 +1,261 @@ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)stat.h 8.12 (Berkeley) 6/16/95 * $FreeBSD$ */ #ifndef _SYS_STAT_H_ #define _SYS_STAT_H_ #if !defined(_KERNEL) && !defined(_POSIX_SOURCE) /* * XXX we need this for struct timespec. We get miscellaneous namespace * pollution with it. */ #include #endif #ifdef _KERNEL #define __dev_t udev_t #else #define __dev_t dev_t #endif #ifndef _POSIX_SOURCE struct ostat { u_int16_t st_dev; /* inode's device */ ino_t st_ino; /* inode's number */ mode_t st_mode; /* inode protection mode */ nlink_t st_nlink; /* number of hard links */ u_int16_t st_uid; /* user ID of the file's owner */ u_int16_t st_gid; /* group ID of the file's group */ u_int16_t st_rdev; /* device type */ int32_t st_size; /* file size, in bytes */ struct timespec st_atimespec; /* time of last access */ struct timespec st_mtimespec; /* time of last data modification */ struct timespec st_ctimespec; /* time of last file status change */ int32_t st_blksize; /* optimal blocksize for I/O */ int32_t st_blocks; /* blocks allocated for file */ u_int32_t st_flags; /* user defined flags for file */ u_int32_t st_gen; /* file generation number */ }; #endif /* !_POSIX_SOURCE */ struct stat { __dev_t st_dev; /* inode's device */ ino_t st_ino; /* inode's number */ mode_t st_mode; /* inode protection mode */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of the file's owner */ gid_t st_gid; /* group ID of the file's group */ __dev_t st_rdev; /* device type */ #ifndef _POSIX_SOURCE struct timespec st_atimespec; /* time of last access */ struct timespec st_mtimespec; /* time of last data modification */ struct timespec st_ctimespec; /* time of last file status change */ #else time_t st_atime; /* time of last access */ long st_atimensec; /* nsec of last access */ time_t st_mtime; /* time of last data modification */ long st_mtimensec; /* nsec of last data modification */ time_t st_ctime; /* time of last file status change */ long st_ctimensec; /* nsec of last file status change */ #endif off_t st_size; /* file size, in bytes */ int64_t st_blocks; /* blocks allocated for file */ u_int32_t st_blksize; /* optimal blocksize for I/O */ u_int32_t st_flags; /* user defined flags for file */ u_int32_t st_gen; /* file generation number */ int32_t st_lspare; int64_t st_qspare[2]; }; #ifndef _POSIX_SOURCE struct nstat { __dev_t st_dev; /* inode's device */ ino_t st_ino; /* inode's number */ u_int32_t st_mode; /* inode protection mode */ u_int32_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of the file's owner */ gid_t st_gid; /* group ID of the file's group */ __dev_t st_rdev; /* device type */ #ifndef _POSIX_SOURCE struct timespec st_atimespec; /* time of last access */ struct timespec st_mtimespec; /* time of last data modification */ struct timespec st_ctimespec; /* time of last file status change */ #else time_t st_atime; /* time of last access */ long st_atimensec; /* nsec of last access */ time_t st_mtime; /* time of last data modification */ long st_mtimensec; /* nsec of last data modification */ time_t st_ctime; /* time of last file status change */ long st_ctimensec; /* nsec of last file status change */ #endif off_t st_size; /* file size, in bytes */ int64_t st_blocks; /* blocks allocated for file */ u_int32_t st_blksize; /* optimal blocksize for I/O */ u_int32_t st_flags; /* user defined flags for file */ u_int32_t st_gen; /* file generation number */ int64_t st_qspare[2]; }; #endif #undef __dev_t #ifndef _POSIX_SOURCE #define st_atime st_atimespec.tv_sec #define st_mtime st_mtimespec.tv_sec #define st_ctime st_ctimespec.tv_sec #endif #define S_ISUID 0004000 /* set user id on execution */ #define S_ISGID 0002000 /* set group id on execution */ #ifndef _POSIX_SOURCE #define S_ISTXT 0001000 /* sticky bit */ #endif #define S_IRWXU 0000700 /* RWX mask for owner */ #define S_IRUSR 0000400 /* R for owner */ #define S_IWUSR 0000200 /* W for owner */ #define S_IXUSR 0000100 /* X for owner */ #ifndef _POSIX_SOURCE #define S_IREAD S_IRUSR #define S_IWRITE S_IWUSR #define S_IEXEC S_IXUSR #endif #define S_IRWXG 0000070 /* RWX mask for group */ #define S_IRGRP 0000040 /* R for group */ #define S_IWGRP 0000020 /* W for group */ #define S_IXGRP 0000010 /* X for group */ #define S_IRWXO 0000007 /* RWX mask for other */ #define S_IROTH 0000004 /* R for other */ #define S_IWOTH 0000002 /* W for other */ #define S_IXOTH 0000001 /* X for other */ #ifndef _POSIX_SOURCE #define S_IFMT 0170000 /* type of file mask */ #define S_IFIFO 0010000 /* named pipe (fifo) */ #define S_IFCHR 0020000 /* character special */ #define S_IFDIR 0040000 /* directory */ #define S_IFBLK 0060000 /* block special */ #define S_IFREG 0100000 /* regular */ #define S_IFLNK 0120000 /* symbolic link */ #define S_IFSOCK 0140000 /* socket */ #define S_IFWHT 0160000 /* whiteout */ #define S_ISVTX 0001000 /* save swapped text even after use */ #endif #define S_ISDIR(m) (((m) & 0170000) == 0040000) /* directory */ #define S_ISCHR(m) (((m) & 0170000) == 0020000) /* char special */ #define S_ISBLK(m) (((m) & 0170000) == 0060000) /* block special */ #define S_ISREG(m) (((m) & 0170000) == 0100000) /* regular file */ #define S_ISFIFO(m) (((m) & 0170000) == 0010000) /* fifo or socket */ #ifndef _POSIX_SOURCE #define S_ISLNK(m) (((m) & 0170000) == 0120000) /* symbolic link */ #define S_ISSOCK(m) (((m) & 0170000) == 0140000) /* socket */ #define S_ISWHT(m) (((m) & 0170000) == 0160000) /* whiteout */ #endif #ifndef _POSIX_SOURCE #define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 0777 */ /* 7777 */ #define ALLPERMS (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO) /* 0666 */ #define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) #define S_BLKSIZE 512 /* block size used in the stat struct */ /* * Definitions of flags stored in file flags word. * * Super-user and owner changeable flags. */ #define UF_SETTABLE 0x0000ffff /* mask of owner changeable flags */ #define UF_NODUMP 0x00000001 /* do not dump file */ #define UF_IMMUTABLE 0x00000002 /* file may not be changed */ #define UF_APPEND 0x00000004 /* writes to file may only append */ #define UF_OPAQUE 0x00000008 /* directory is opaque wrt. union */ #define UF_NOUNLINK 0x00000010 /* file may not be removed or renamed */ /* * Super-user changeable flags. */ #define SF_SETTABLE 0xffff0000 /* mask of superuser changeable flags */ #define SF_ARCHIVED 0x00010000 /* file is archived */ #define SF_IMMUTABLE 0x00020000 /* file may not be changed */ #define SF_APPEND 0x00040000 /* writes to file may only append */ #define SF_NOUNLINK 0x00100000 /* file may not be removed or renamed */ +#define SF_SNAPSHOT 0x00200000 /* snapshot inode */ #ifdef _KERNEL /* * Shorthand abbreviations of above. */ #define OPAQUE (UF_OPAQUE) #define APPEND (UF_APPEND | SF_APPEND) #define IMMUTABLE (UF_IMMUTABLE | SF_IMMUTABLE) #define NOUNLINK (UF_NOUNLINK | SF_NOUNLINK) #endif #endif /* !_POSIX_SOURCE */ #ifndef _KERNEL #include __BEGIN_DECLS int chmod __P((const char *, mode_t)); int fstat __P((int, struct stat *)); int mkdir __P((const char *, mode_t)); int mkfifo __P((const char *, mode_t)); int stat __P((const char *, struct stat *)); mode_t umask __P((mode_t)); #ifndef _POSIX_SOURCE int chflags __P((const char *, u_long)); int fchflags __P((int, u_long)); int fchmod __P((int, mode_t)); int lchmod __P((const char *, mode_t)); int lstat __P((const char *, struct stat *)); #endif __END_DECLS #endif /* !_KERNEL */ #endif /* !_SYS_STAT_H_ */ Index: head/sys/ufs/ffs/fs.h =================================================================== --- head/sys/ufs/ffs/fs.h (revision 62552) +++ head/sys/ufs/ffs/fs.h (revision 62553) @@ -1,523 +1,548 @@ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)fs.h 8.13 (Berkeley) 3/21/95 * $FreeBSD$ */ #ifndef _UFS_FFS_FS_H_ #define _UFS_FFS_FS_H_ /* * Each disk drive contains some number of file systems. * A file system consists of a number of cylinder groups. * Each cylinder group has inodes and data. * * A file system is described by its super-block, which in turn * describes the cylinder groups. The super-block is critical * data and is replicated in each cylinder group to protect against * catastrophic loss. This is done at `newfs' time and the critical * super-block data does not change, so the copies need not be * referenced further unless disaster strikes. * * For file system fs, the offsets of the various blocks of interest * are given in the super block as: * [fs->fs_sblkno] Super-block * [fs->fs_cblkno] Cylinder group block * [fs->fs_iblkno] Inode blocks * [fs->fs_dblkno] Data blocks * The beginning of cylinder group cg in fs, is given by * the ``cgbase(fs, cg)'' macro. * * The first boot and super blocks are given in absolute disk addresses. * The byte-offset forms are preferred, as they don't imply a sector size. */ #define BBSIZE 8192 #define SBSIZE 8192 #define BBOFF ((off_t)(0)) #define SBOFF ((off_t)(BBOFF + BBSIZE)) #define BBLOCK ((ufs_daddr_t)(0)) #define SBLOCK ((ufs_daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE)) /* * Addresses stored in inodes are capable of addressing fragments * of `blocks'. File system blocks of at most size MAXBSIZE can * be optionally broken into 2, 4, or 8 pieces, each of which is * addressable; these pieces may be DEV_BSIZE, or some multiple of * a DEV_BSIZE unit. * * Large files consist of exclusively large data blocks. To avoid * undue wasted disk space, the last data block of a small file may be * allocated as only as many fragments of a large block as are * necessary. The file system format retains only a single pointer * to such a fragment, which is a piece of a single large block that * has been divided. The size of such a fragment is determinable from * information in the inode, using the ``blksize(fs, ip, lbn)'' macro. * * The file system records space availability at the fragment level; * to determine block availability, aligned fragments are examined. */ /* * MINBSIZE is the smallest allowable block size. * In order to insure that it is possible to create files of size * 2^32 with only two levels of indirection, MINBSIZE is set to 4096. * MINBSIZE must be big enough to hold a cylinder group block, * thus changes to (struct cg) must keep its size within MINBSIZE. * Note that super blocks are always of size SBSIZE, * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. */ #define MINBSIZE 4096 /* * The path name on which the file system is mounted is maintained * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in * the super block for this name. */ #define MAXMNTLEN 512 /* * The limit on the amount of summary information per file system * is defined by MAXCSBUFS. It is currently parameterized for a * size of 128 bytes (2 million cylinder groups on machines with * 32-bit pointers, and 1 million on 64-bit machines). One pointer * is taken away to point to an array of cluster sizes that is * computed as cylinder groups are inspected. */ #define MAXCSBUFS ((128 / sizeof(void *)) - 1) /* * A summary of contiguous blocks of various sizes is maintained * in each cylinder group. Normally this is set by the initial * value of fs_maxcontig. To conserve space, a maximum summary size * is set by FS_MAXCONTIG. */ #define FS_MAXCONTIG 16 /* * MINFREE gives the minimum acceptable percentage of file system * blocks which may be free. If the freelist drops below this level * only the superuser may continue to allocate blocks. This may * be set to 0 if no reserve of free blocks is deemed necessary, * however throughput drops by fifty percent if the file system * is run at between 95% and 100% full; thus the minimum default * value of fs_minfree is 5%. However, to get good clustering * performance, 10% is a better choice. hence we use 10% as our * default value. With 10% free space, fragmentation is not a * problem, so we choose to optimize for time. */ #define MINFREE 8 #define DEFAULTOPT FS_OPTTIME /* + * The maximum number of snapshot nodes that can be associated + * with each filesystem. This limit affects only the number of + * snapshot files that can be recorded within the superblock so + * that they can be found when the filesystem is mounted. However, + * maintaining too many will slow the filesystem performance, so + * having this limit is a good idea. + */ +#define FSMAXSNAP 20 + +/* + * Used to identify special blocks in snapshots: + * + * BLK_NOCOPY - A block that was unallocated at the time the snapshot + * was taken, hence does not need to be copied when written. + * BLK_SNAP - A block held by another snapshot that is not needed by this + * snapshot. When the other snapshot is freed, the BLK_SNAP entries + * are converted to BLK_NOCOPY. These are needed to allow fsck to + * identify blocks that are in use by other snapshots (which are + * expunged from this snapshot). + */ +#define BLK_NOCOPY ((ufs_daddr_t)(1)) +#define BLK_SNAP ((ufs_daddr_t)(2)) + +/* * Per cylinder group information; summarized in blocks allocated * from first cylinder group data blocks. These blocks have to be * read in from fs_csaddr (size fs_cssize) in addition to the * super block. * * N.B. sizeof(struct csum) must be a power of two in order for * the ``fs_cs'' macro to work (see below). */ struct csum { int32_t cs_ndir; /* number of directories */ int32_t cs_nbfree; /* number of free blocks */ int32_t cs_nifree; /* number of free inodes */ int32_t cs_nffree; /* number of free frags */ }; /* * Super block for an FFS file system. */ struct fs { int32_t fs_firstfield; /* historic file system linked list, */ int32_t fs_unused_1; /* used for incore super blocks */ ufs_daddr_t fs_sblkno; /* addr of super-block in filesys */ ufs_daddr_t fs_cblkno; /* offset of cyl-block in filesys */ ufs_daddr_t fs_iblkno; /* offset of inode-blocks in filesys */ ufs_daddr_t fs_dblkno; /* offset of first data after cg */ int32_t fs_cgoffset; /* cylinder group offset in cylinder */ int32_t fs_cgmask; /* used to calc mod fs_ntrak */ time_t fs_time; /* last time written */ int32_t fs_size; /* number of blocks in fs */ int32_t fs_dsize; /* number of data blocks in fs */ int32_t fs_ncg; /* number of cylinder groups */ int32_t fs_bsize; /* size of basic blocks in fs */ int32_t fs_fsize; /* size of frag blocks in fs */ int32_t fs_frag; /* number of frags in a block in fs */ /* these are configuration parameters */ int32_t fs_minfree; /* minimum percentage of free blocks */ int32_t fs_rotdelay; /* num of ms for optimal next block */ int32_t fs_rps; /* disk revolutions per second */ /* these fields can be computed from the others */ int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */ int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */ int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */ int32_t fs_fshift; /* ``numfrags'' calc number of frags */ /* these are configuration parameters */ int32_t fs_maxcontig; /* max number of contiguous blks */ int32_t fs_maxbpg; /* max number of blks per cyl group */ /* these fields can be computed from the others */ int32_t fs_fragshift; /* block to frag shift */ int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ int32_t fs_sbsize; /* actual size of super block */ int32_t fs_csmask; /* csum block offset */ int32_t fs_csshift; /* csum block number */ int32_t fs_nindir; /* value of NINDIR */ int32_t fs_inopb; /* value of INOPB */ int32_t fs_nspf; /* value of NSPF */ /* yet another configuration parameter */ int32_t fs_optim; /* optimization preference, see below */ /* these fields are derived from the hardware */ int32_t fs_npsect; /* # sectors/track including spares */ int32_t fs_interleave; /* hardware sector interleave */ int32_t fs_trackskew; /* sector 0 skew, per track */ /* fs_id takes the space of the unused fs_headswitch and fs_trkseek fields */ int32_t fs_id[2]; /* unique filesystem id */ /* sizes determined by number of cylinder groups and their sizes */ ufs_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */ int32_t fs_cssize; /* size of cyl grp summary area */ int32_t fs_cgsize; /* cylinder group size */ /* these fields are derived from the hardware */ int32_t fs_ntrak; /* tracks per cylinder */ int32_t fs_nsect; /* sectors per track */ int32_t fs_spc; /* sectors per cylinder */ /* this comes from the disk driver partitioning */ int32_t fs_ncyl; /* cylinders in file system */ /* these fields can be computed from the others */ int32_t fs_cpg; /* cylinders per group */ int32_t fs_ipg; /* inodes per group */ int32_t fs_fpg; /* blocks per group * fs_frag */ /* this data must be re-computed after crashes */ struct csum fs_cstotal; /* cylinder summary information */ /* these fields are cleared at mount time */ int8_t fs_fmod; /* super block modified flag */ int8_t fs_clean; /* file system is clean flag */ int8_t fs_ronly; /* mounted read-only flag */ int8_t fs_flags; /* see FS_ flags below */ u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ /* these fields retain the current block allocation info */ int32_t fs_cgrotor; /* last cg searched */ struct csum *fs_csp[MAXCSBUFS];/* list of fs_cs info buffers */ int32_t *fs_maxcluster; /* max cluster in each cyl group */ int32_t fs_cpc; /* cyl per cycle in postbl */ int16_t fs_opostbl[16][8]; /* old rotation block list head */ - int32_t fs_sparecon[50]; /* reserved for future constants */ + int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */ + int32_t fs_sparecon[30]; /* reserved for future constants */ int32_t fs_contigsumsize; /* size of cluster summary array */ int32_t fs_maxsymlinklen; /* max length of an internal symlink */ int32_t fs_inodefmt; /* format of on-disk inodes */ u_int64_t fs_maxfilesize; /* maximum representable file size */ int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */ int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */ int32_t fs_state; /* validate fs_clean field */ int32_t fs_postblformat; /* format of positional layout tables */ int32_t fs_nrpos; /* number of rotational positions */ int32_t fs_postbloff; /* (u_int16) rotation block list head */ int32_t fs_rotbloff; /* (u_int8) blocks for each rotation */ int32_t fs_magic; /* magic number */ u_int8_t fs_space[1]; /* list of blocks for each rotation */ /* actually longer */ }; /* * Filesystem identification */ #define FS_MAGIC 0x011954 /* the fast filesystem magic number */ #define FS_OKAY 0x7c269d38 /* superblock checksum */ #define FS_42INODEFMT -1 /* 4.2BSD inode format */ #define FS_44INODEFMT 2 /* 4.4BSD inode format */ /* * Preference for optimization. */ #define FS_OPTTIME 0 /* minimize allocation time */ #define FS_OPTSPACE 1 /* minimize disk fragmentation */ /* * Filesystem flags. */ #define FS_UNCLEAN 0x01 /* filesystem not clean at mount */ #define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */ /* * Rotational layout table format types */ #define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ #define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ /* * Macros for access to superblock array structures */ #define fs_postbl(fs, cylno) \ (((fs)->fs_postblformat == FS_42POSTBLFMT) \ ? ((fs)->fs_opostbl[cylno]) \ : ((int16_t *)((u_int8_t *)(fs) + \ (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos)) #define fs_rotbl(fs) \ (((fs)->fs_postblformat == FS_42POSTBLFMT) \ ? ((fs)->fs_space) \ : ((u_int8_t *)((u_int8_t *)(fs) + (fs)->fs_rotbloff))) /* * The size of a cylinder group is calculated by CGSIZE. The maximum size * is limited by the fact that cylinder groups are at most one block. * Its size is derived from the size of the maps maintained in the * cylinder group and the (struct cg) size. */ #define CGSIZE(fs) \ /* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \ /* blktot size */ (fs)->fs_cpg * sizeof(int32_t) + \ /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(int16_t) + \ /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY) +\ /* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \ /* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \ /* cluster map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPB(fs), NBBY))) /* * Convert cylinder group to base address of its global summary info. * * N.B. This macro assumes that sizeof(struct csum) is a power of two. */ #define fs_cs(fs, indx) \ fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask] /* * Cylinder group block for a file system. */ #define CG_MAGIC 0x090255 struct cg { int32_t cg_firstfield; /* historic cyl groups linked list */ int32_t cg_magic; /* magic number */ time_t cg_time; /* time last written */ int32_t cg_cgx; /* we are the cgx'th cylinder group */ int16_t cg_ncyl; /* number of cyl's this cg */ int16_t cg_niblk; /* number of inode blocks this cg */ int32_t cg_ndblk; /* number of data blocks this cg */ struct csum cg_cs; /* cylinder summary information */ int32_t cg_rotor; /* position of last used block */ int32_t cg_frotor; /* position of last used frag */ int32_t cg_irotor; /* position of last used inode */ int32_t cg_frsum[MAXFRAG]; /* counts of available frags */ int32_t cg_btotoff; /* (int32) block totals per cylinder */ int32_t cg_boff; /* (u_int16) free block positions */ int32_t cg_iusedoff; /* (u_int8) used inode map */ int32_t cg_freeoff; /* (u_int8) free block map */ int32_t cg_nextfreeoff; /* (u_int8) next available space */ int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */ int32_t cg_clusteroff; /* (u_int8) free cluster map */ int32_t cg_nclusterblks; /* number of clusters this cg */ int32_t cg_sparecon[13]; /* reserved for future use */ u_int8_t cg_space[1]; /* space for cylinder group maps */ /* actually longer */ }; /* * Macros for access to cylinder group array structures */ #define cg_blktot(cgp) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_btot) \ : ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_btotoff))) #define cg_blks(fs, cgp, cylno) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_b[cylno]) \ : ((int16_t *)((u_int8_t *)(cgp) + \ (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos)) #define cg_inosused(cgp) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_iused) \ : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_iusedoff))) #define cg_blksfree(cgp) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_free) \ : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_freeoff))) #define cg_chkmagic(cgp) \ ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC) #define cg_clustersfree(cgp) \ ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_clusteroff)) #define cg_clustersum(cgp) \ ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_clustersumoff)) /* * The following structure is defined * for compatibility with old file systems. */ struct ocg { int32_t cg_firstfield; /* historic linked list of cyl groups */ int32_t cg_unused_1; /* used for incore cyl groups */ time_t cg_time; /* time last written */ int32_t cg_cgx; /* we are the cgx'th cylinder group */ int16_t cg_ncyl; /* number of cyl's this cg */ int16_t cg_niblk; /* number of inode blocks this cg */ int32_t cg_ndblk; /* number of data blocks this cg */ struct csum cg_cs; /* cylinder summary information */ int32_t cg_rotor; /* position of last used block */ int32_t cg_frotor; /* position of last used frag */ int32_t cg_irotor; /* position of last used inode */ int32_t cg_frsum[8]; /* counts of available frags */ int32_t cg_btot[32]; /* block totals per cylinder */ int16_t cg_b[32][8]; /* positions of free blocks */ u_int8_t cg_iused[256]; /* used inode map */ int32_t cg_magic; /* magic number */ u_int8_t cg_free[1]; /* free block map */ /* actually longer */ }; /* * Turn file system block numbers into disk block addresses. * This maps file system blocks to device size blocks. */ #define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb) #define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) /* * Cylinder group macros to locate things in cylinder groups. * They calc file system addresses of cylinder group data structures. */ #define cgbase(fs, c) ((ufs_daddr_t)((fs)->fs_fpg * (c))) #define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ #define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ #define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ #define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */ #define cgstart(fs, c) \ (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask))) /* * Macros for handling inode numbers: * inode number to file system block offset. * inode number to cylinder group number. * inode number to file system block address. */ #define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg) #define ino_to_fsba(fs, x) \ ((ufs_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) #define ino_to_fsbo(fs, x) ((x) % INOPB(fs)) /* * Give cylinder group number for a file system block. * Give cylinder group block number for a file system block. */ #define dtog(fs, d) ((d) / (fs)->fs_fpg) #define dtogd(fs, d) ((d) % (fs)->fs_fpg) /* * Extract the bits for a block from a map. * Compute the cylinder and rotational position of a cyl block addr. */ #define blkmap(fs, map, loc) \ (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag))) #define cbtocylno(fs, bno) \ ((bno) * NSPF(fs) / (fs)->fs_spc) #define cbtorpos(fs, bno) \ (((bno) * NSPF(fs) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \ (bno) * NSPF(fs) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \ (fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect) /* * The following macros optimize certain frequently calculated * quantities by using shifts and masks in place of divisions * modulos and multiplications. */ #define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ ((loc) & (fs)->fs_qbmask) #define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \ ((loc) & (fs)->fs_qfmask) #define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \ ((off_t)(blk) << (fs)->fs_bshift) /* Use this only when `blk' is known to be small, e.g., < NDADDR. */ #define smalllblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \ ((blk) << (fs)->fs_bshift) #define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ ((loc) >> (fs)->fs_bshift) #define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ ((loc) >> (fs)->fs_fshift) #define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask) #define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) #define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ ((frags) >> (fs)->fs_fragshift) #define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ ((blks) << (fs)->fs_fragshift) #define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ ((fsb) & ((fs)->fs_frag - 1)) #define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ ((fsb) &~ ((fs)->fs_frag - 1)) /* * Determine the number of available frags given a * percentage to hold in reserve. */ #define freespace(fs, percentreserved) \ (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ (fs)->fs_cstotal.cs_nffree - \ ((off_t)((fs)->fs_dsize) * (percentreserved) / 100)) /* * Determining the size of a file block in the file system. */ #define blksize(fs, ip, lbn) \ (((lbn) >= NDADDR || (ip)->i_size >= smalllblktosize(fs, (lbn) + 1)) \ ? (fs)->fs_bsize \ : (fragroundup(fs, blkoff(fs, (ip)->i_size)))) #define dblksize(fs, dip, lbn) \ (((lbn) >= NDADDR || (dip)->di_size >= smalllblktosize(fs, (lbn) + 1)) \ ? (fs)->fs_bsize \ : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) #define sblksize(fs, size, lbn) \ (((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \ ? (fs)->fs_bsize \ : (fragroundup(fs, blkoff(fs, (size))))) /* * Number of disk sectors per block/fragment; assumes DEV_BSIZE byte * sector size. */ #define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift) #define NSPF(fs) ((fs)->fs_nspf) /* * Number of inodes in a secondary storage block/fragment. */ #define INOPB(fs) ((fs)->fs_inopb) #define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) /* * Number of indirects in a file system block. */ #define NINDIR(fs) ((fs)->fs_nindir) extern int inside[], around[]; extern u_char *fragtbl[]; #endif