/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#ifdef KERNEL
#ifdef __APPLE_API_PRIVATE
#include <sys/param.h>
-#include <sys/lock.h>
#include <sys/queue.h>
#include <sys/mount.h>
-#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/quota.h>
#include <sys/dirent.h>
#include <sys/event.h>
+#include <kern/locks.h>
+
#include <vfs/vfs_journal.h>
#include <hfs/hfs_format.h>
#include <hfs/hfs_encodings.h>
#include <hfs/hfs_hotfiles.h>
-
-struct uio; // This is more effective than #include <sys/uio.h> in case KERNEL is undefined...
-struct hfslockf; /* For advisory locking */
-
/*
* Just reported via MIG interface.
*/
enum { kMasterDirectoryBlock = 2 }; /* MDB offset on disk in 512-byte blocks */
enum { kMDBOffset = kMasterDirectoryBlock * 512 }; /* MDB offset on disk in bytes */
-enum {
- kUnknownID = 0,
- kRootParID = 1,
- kRootDirID = 2
-};
+#define kRootDirID kHFSRootFolderID
-enum {
- kDataFork,
- kRsrcFork,
- kDirectory
-};
/* number of locked buffer caches to hold for b-tree meta data */
#define kMaxLockedMetaBuffers 32
/* Internal Data structures*/
-struct vcb_t {
- u_int16_t vcbSigWord;
- int16_t vcbAtrb;
- int16_t vcbFlags;
- int16_t vcbspare;
- u_int32_t vcbJinfoBlock;
-
- u_int32_t vcbCrDate;
- u_int32_t vcbLsMod;
- u_int32_t vcbVolBkUp;
-
- int32_t vcbFilCnt;
- int32_t vcbDirCnt;
- u_int32_t blockSize; /* size of allocation blocks */
- u_int32_t totalBlocks; /* total allocation blocks */
- u_int32_t freeBlocks; /* free allocation blocks */
- u_int32_t nextAllocation; /* start of next allocation search */
- int32_t vcbClpSiz;
- u_int32_t vcbNxtCNID;
- u_int32_t vcbCNIDGen;
- int32_t vcbWrCnt;
-
- int32_t vcbFndrInfo[8];
-
- u_int64_t encodingsBitmap; /* HFS Plus only */
-
- u_int16_t vcbNmFls; /* HFS only */
- u_int16_t vcbNmRtDirs; /* HFS only */
- int16_t vcbVBMSt; /* HFS only */
- int16_t vcbAlBlSt; /* HFS only */
-
- struct vnode * extentsRefNum;
- struct vnode * catalogRefNum;
- struct vnode * allocationsRefNum;
-
- u_int8_t vcbVN[256]; /* volume name in UTF-8 */
- u_int32_t volumeNameEncodingHint;
- u_int32_t hfsPlusIOPosOffset; /* Disk block where HFS+ starts */
- u_int32_t vcbVBMIOSize; /* volume bitmap I/O size */
-
- /* cache of largest known free extents */
- u_int32_t vcbFreeExtCnt;
- HFSPlusExtentDescriptor vcbFreeExt[kMaxFreeExtents];
-
- u_int32_t reserveBlocks; /* free block reserve */
- u_int32_t loanedBlocks; /* blocks on loan for delayed allocations */
-
- u_int32_t localCreateDate; /* creation times for HFS+ volumes are in local time */
- simple_lock_data_t vcbSimpleLock; /* simple lock to allow concurrent access to vcb data */
-};
-typedef struct vcb_t ExtendedVCB;
-
#define kHFS_DamagedVolume 0x1 /* This volume has errors, unmount dirty */
/* XXX */
#define MARK_VOLUMEDAMAGED(fcb)
-/*
- * NOTE: The code relies on being able to cast an ExtendedVCB* to a vfsVCB* in order
- * to gain access to the mount point pointer from a pointer
- * to an ExtendedVCB. DO NOT INSERT OTHER FIELDS BEFORE THE vcb FIELD!!
- *
- * vcbFlags, vcbLsMod, vcbFilCnt, vcbDirCnt, vcbNxtCNID, etc
- * are locked by the hfs_lock simple lock.
- */
-typedef struct vfsVCB {
- ExtendedVCB vcb_vcb;
- struct hfsmount *vcb_hfsmp; /* Pointer to hfsmount structure */
-} vfsVCB_t;
-
-
/* This structure describes the HFS specific mount structure data. */
typedef struct hfsmount {
- u_int32_t hfs_flags; /* see below */
-
+ u_int32_t hfs_flags; /* see below */
+
/* Physical Description */
- u_long hfs_phys_block_count; /* Num of PHYSICAL blocks of volume */
- u_long hfs_phys_block_size; /* Always a multiple of 512 */
+ u_long hfs_phys_block_size; /* Always a multiple of 512 */
+ daddr64_t hfs_phys_block_count; /* Num of PHYSICAL blocks of volume */
+ daddr64_t hfs_alt_id_sector; /* location of alternate VH/MDB */
/* Access to VFS and devices */
struct mount *hfs_mp; /* filesystem vfs structure */
struct vnode *hfs_devvp; /* block device mounted vnode */
- dev_t hfs_raw_dev; /* device mounted */
- struct netexport hfs_export; /* Export information */
- u_int32_t hfs_logBlockSize; /* Size of buffer cache buffer for I/O */
+ struct vnode * hfs_extents_vp;
+ struct vnode * hfs_catalog_vp;
+ struct vnode * hfs_allocation_vp;
+ struct vnode * hfs_attribute_vp;
+ dev_t hfs_raw_dev; /* device mounted */
+ u_int32_t hfs_logBlockSize; /* Size of buffer cache buffer for I/O */
/* Default values for HFS standard and non-init access */
- uid_t hfs_uid; /* uid to set as owner of the files */
- gid_t hfs_gid; /* gid to set as owner of the files */
- mode_t hfs_dir_mask; /* mask to and with directory protection bits */
- mode_t hfs_file_mask; /* mask to and with file protection bits */
- u_long hfs_encoding; /* Defualt encoding for non hfs+ volumes */
-
- /* HFS Specific */
- struct vfsVCB hfs_vcb;
+ uid_t hfs_uid; /* uid to set as owner of the files */
+ gid_t hfs_gid; /* gid to set as owner of the files */
+ mode_t hfs_dir_mask; /* mask to and with directory protection bits */
+ mode_t hfs_file_mask; /* mask to and with file protection bits */
+ u_long hfs_encoding; /* Defualt encoding for non hfs+ volumes */
+
+ /* Persistent fields (on disk, dynamic) */
+ time_t hfs_mtime; /* file system last modification time */
+ u_int32_t hfs_filecount; /* number of files in file system */
+ u_int32_t hfs_dircount; /* number of directories in file system */
+ u_int32_t freeBlocks; /* free allocation blocks */
+ u_int32_t nextAllocation; /* start of next allocation search */
+ u_int32_t vcbNxtCNID; /* next unused catalog node ID */
+ u_int32_t vcbWrCnt; /* file system write count */
+ u_int64_t encodingsBitmap; /* in-use encodings */
+ u_int16_t vcbNmFls; /* HFS Only - root dir file count */
+ u_int16_t vcbNmRtDirs; /* HFS Only - root dir directory count */
+
+ /* Persistent fields (on disk, static) */
+ u_int16_t vcbSigWord;
+ int16_t vcbFlags;
+ u_int32_t vcbAtrb;
+ u_int32_t vcbJinfoBlock;
+ time_t hfs_itime; /* file system creation time */
+ time_t hfs_btime; /* file system last backup time */
+ u_int32_t blockSize; /* size of allocation blocks */
+ u_int32_t totalBlocks; /* total allocation blocks */
+ int32_t vcbClpSiz;
+ u_int32_t vcbFndrInfo[8];
+ int16_t vcbVBMSt; /* HFS only */
+ int16_t vcbAlBlSt; /* HFS only */
+
+ /* vcb stuff */
+ u_int8_t vcbVN[256]; /* volume name in UTF-8 */
+ u_int32_t volumeNameEncodingHint;
+ u_int32_t hfsPlusIOPosOffset; /* Disk block where HFS+ starts */
+ u_int32_t vcbVBMIOSize; /* volume bitmap I/O size */
+
+ /* cache of largest known free extents */
+ u_int32_t vcbFreeExtCnt;
+ HFSPlusExtentDescriptor vcbFreeExt[kMaxFreeExtents];
+
+ u_int32_t reserveBlocks; /* free block reserve */
+ u_int32_t loanedBlocks; /* blocks on loan for delayed allocations */
+
+ u_int32_t localCreateDate; /* creation times for HFS+ volumes are in local time */
struct cat_desc hfs_privdir_desc;
struct cat_attr hfs_privdir_attr;
u_int32_t hfs_metadata_createdate;
u_int32_t jnl_size;
u_int32_t hfs_jnlfileid;
u_int32_t hfs_jnlinfoblkid;
- volatile int readers;
- volatile int blocker;
+ lck_rw_t hfs_global_lock;
+ u_int32_t hfs_global_lock_nesting;
/* Notification variables: */
unsigned long hfs_notification_conditions;
u_int32_t hfs_freespace_notify_warninglimit;
u_int32_t hfs_freespace_notify_desiredlevel;
+ /* time mounted and last mounted mod time "snapshot" */
+ time_t hfs_mount_time;
+ time_t hfs_last_mounted_mtime;
+
/* Metadata allocation zone variables: */
u_int32_t hfs_metazone_start;
u_int32_t hfs_metazone_end;
int hfs_catalog_maxblks;
/* Hot File Clustering variables: */
+ lck_mtx_t hfc_mutex; /* serialize hot file stages */
enum hfc_stage hfc_stage; /* what are we up to... */
time_t hfc_timebase; /* recording period start time */
time_t hfc_timeout; /* recording period stop time */
struct vnode * hfs_backingfs_rootvp;
int hfs_sparsebandblks;
#endif
+ size_t hfs_max_inline_attrsize;
+
+ lck_mtx_t hfs_mutex; /* protects access to hfsmount data */
+ void *hfs_freezing_proc; /* who froze the fs */
+ lck_rw_t hfs_insync; /* protects sync/freeze interaction */
+
+ /* Resize variables: */
+ u_int32_t hfs_resize_filesmoved;
+ u_int32_t hfs_resize_totalfiles;
} hfsmount_t;
+typedef hfsmount_t ExtendedVCB;
+
+/* Aliases for legacy field names */
+#define vcbCrDate hfs_itime
+#define vcbLsMod hfs_mtime
+#define vcbVolBkUp hfs_btime
+#define extentsRefNum hfs_extents_vp
+#define catalogRefNum hfs_catalog_vp
+#define allocationsRefNum hfs_allocation_vp
+#define vcbFilCnt hfs_filecount
+#define vcbDirCnt hfs_dircount
+
/* HFS mount point flags */
#define HFS_READ_ONLY 0x001
#define HFS_METADATA_ZONE 0x080
#define HFS_FRAGMENTED_FREESPACE 0x100
#define HFS_NEED_JNL_RESET 0x200
-
-#ifdef HFS_SPARSE_DEV
#define HFS_HAS_SPARSE_DEVICE 0x400
-#endif
+#define HFS_RESIZE_IN_PROGRESS 0x800
-#define hfs_global_shared_lock_acquire(hfsmp) \
- do { \
- if (hfsmp->blocker) { \
- tsleep((caddr_t)&hfsmp->blocker, PRIBIO, "journal_blocker", 0); \
- continue; \
- } \
- hfsmp->readers++; \
- break; \
- } while (1)
-
-#define hfs_global_shared_lock_release(hfsmp) \
- do { \
- hfsmp->readers--; \
- if (hfsmp->readers == 0) { \
- wakeup((caddr_t)&hfsmp->readers); \
- } \
- } while (0)
-
-#define hfs_global_exclusive_lock_acquire(hfsmp) \
- do { \
- if (hfsmp->blocker) { \
- tsleep((caddr_t)&hfsmp->blocker, PRIBIO, "journal_blocker", 0); \
- continue; \
- } \
- if (hfsmp->readers != 0) { \
- tsleep((caddr_t)&hfsmp->readers, PRIBIO, "journal_enable/disble", 0); \
- continue; \
- } \
- hfsmp->blocker = 1; \
- break; \
- } while (1)
-
-#define hfs_global_exclusive_lock_release(hfsmp) \
- hfsmp->blocker = 0; \
- wakeup((caddr_t)&hfsmp->blocker)
+#define HFS_MOUNT_LOCK(hfsmp, metadata) \
+ { \
+ if ((metadata) && 1) \
+ lck_mtx_lock(&(hfsmp)->hfs_mutex); \
+ } \
+
+#define HFS_MOUNT_UNLOCK(hfsmp, metadata) \
+ { \
+ if ((metadata) && 1) \
+ lck_mtx_unlock(&(hfsmp)->hfs_mutex); \
+ } \
+
+#define hfs_global_exclusive_lock_acquire(hfsmp) lck_rw_lock_exclusive(&(hfsmp)->hfs_global_lock)
+#define hfs_global_exclusive_lock_release(hfsmp) lck_rw_done(&(hfsmp)->hfs_global_lock)
+
#define MAXHFSVNODELEN 31
#define MAKE_INODE_NAME(name,linkno) \
(void) sprintf((name), "%s%d", HFS_INODE_PREFIX, (linkno))
+#define HFS_INODE_PREFIX_LEN 5
-/* structure to hold a "." or ".." directory entry (12 bytes) */
-typedef struct hfsdotentry {
- u_int32_t d_fileno; /* unique file number */
- u_int16_t d_reclen; /* length of this structure */
- u_int8_t d_type; /* dirent file type */
- u_int8_t d_namelen; /* len of filename */
- char d_name[4]; /* "." or ".." */
-} hfsdotentry;
#define HFS_AVERAGE_NAME_SIZE 22
#define AVERAGE_HFSDIRENTRY_SIZE (8+HFS_AVERAGE_NAME_SIZE+4)
-#define MAX_HFSDIRENTRY_SIZE sizeof(struct dirent)
-#define DIRENTRY_SIZE(namlen) \
- ((sizeof(struct dirent) - (NAME_MAX+1)) + (((namlen)+1 + 3) &~ 3))
+#define STD_DIRENT_LEN(namlen) \
+ ((sizeof(struct dirent) - (NAME_MAX+1)) + (((namlen)+1 + 3) &~ 3))
+#define EXT_DIRENT_LEN(namlen) \
+ ((sizeof(struct direntry) + (namlen) - (MAXPATHLEN-1) + 3) & ~3)
enum { kHFSPlusMaxFileNameBytes = kHFSPlusMaxFileNameChars * 3 };
-enum { kdirentMaxNameBytes = NAME_MAX };
-
/* macro to determine if hfs or hfsplus */
#define ISHFSPLUS(VCB) ((VCB)->vcbSigWord == kHFSPlusSigWord)
/*
* Various ways to acquire a VFS mount point pointer:
*/
-#define VTOVFS(VP) ((VP)->v_mount)
+#define VTOVFS(VP) vnode_mount((VP))
#define HFSTOVFS(HFSMP) ((HFSMP)->hfs_mp)
-#define VCBTOVFS(VCB) (((struct vfsVCB *)(VCB))->vcb_hfsmp->hfs_mp)
+#define VCBTOVFS(VCB) HFSTOVFS(VCB)
/*
* Various ways to acquire an HFS mount point pointer:
*/
-#define VTOHFS(VP) ((struct hfsmount *)((VP)->v_mount->mnt_data))
-#define VFSTOHFS(MP) ((struct hfsmount *)(MP)->mnt_data)
-#define VCBTOHFS(VCB) (((struct vfsVCB *)(VCB))->vcb_hfsmp)
-#define FCBTOHFS(FCB) ((struct hfsmount *)(FCB)->ff_cp->c_vp->v_mount->mnt_data)
+#define VTOHFS(VP) ((struct hfsmount *)vfs_fsprivate(vnode_mount((VP))))
+#define VFSTOHFS(MP) ((struct hfsmount *)vfs_fsprivate((MP)))
+#define VCBTOHFS(VCB) (VCB)
+#define FCBTOHFS(FCB) ((struct hfsmount *)vfs_fsprivate(vnode_mount((FCB)->ff_cp->c_vp)))
/*
- * Various ways to acquire a VCB pointer:
+ * Various ways to acquire a VCB (legacy) pointer:
*/
-#define VTOVCB(VP) (&(((struct hfsmount *)((VP)->v_mount->mnt_data))->hfs_vcb.vcb_vcb))
-#define VFSTOVCB(MP) (&(((struct hfsmount *)(MP)->mnt_data)->hfs_vcb.vcb_vcb))
-#define HFSTOVCB(HFSMP) (&(HFSMP)->hfs_vcb.vcb_vcb)
-#define FCBTOVCB(FCB) (&(((struct hfsmount *)((FCB)->ff_cp->c_vp->v_mount->mnt_data))->hfs_vcb.vcb_vcb))
+#define VTOVCB(VP) VTOHFS(VP)
+#define VFSTOVCB(MP) VFSTOHFS(MP)
+#define HFSTOVCB(HFSMP) (HFSMP)
+#define FCBTOVCB(FCB) FCBTOHFS(FCB)
#define HFS_KNOTE(vp, hint) KNOTE(&VTOC(vp)->c_knotes, (hint))
#define HFS_ALT_SECTOR(blksize, blkcnt) (((blkcnt) - 1) - (512 / (blksize)))
#define HFS_ALT_OFFSET(blksize) ((blksize) > 1024 ? (blksize) - 1024 : 0)
+
+/*
+ * HFS specific fcntl()'s
+ */
+#define HFS_BULKACCESS (FCNTL_FS_SPECIFIC_BASE + 0x00001)
+#define HFS_GET_MOUNT_TIME (FCNTL_FS_SPECIFIC_BASE + 0x00002)
+#define HFS_GET_LAST_MTIME (FCNTL_FS_SPECIFIC_BASE + 0x00003)
+#define HFS_GET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00004)
+#define HFS_SET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00005)
+
+
/*
* This is the straight GMT conversion constant:
* 00:00:00 January 1, 1970 - 00:00:00 January 1, 1904
#define MAC_GMT_FACTOR 2082844800UL
-u_int32_t to_bsd_time(u_int32_t hfs_time);
-u_int32_t to_hfs_time(u_int32_t bsd_time);
+time_t to_bsd_time(u_int32_t hfs_time);
+u_int32_t to_hfs_time(time_t bsd_time);
int hfs_flushvolumeheader(struct hfsmount *hfsmp, int waitfor, int altflush);
#define HFS_ALTFLUSH 1
extern int hfsUnmount(struct hfsmount *hfsmp, struct proc *p);
-
-extern int hfs_getcnode(struct hfsmount *hfsmp, cnid_t cnid, struct cat_desc *descp,
- int wantrsrc, struct cat_attr *attrp, struct cat_fork *forkp,
- struct vnode **vpp);
-
-extern int hfs_getnewvnode(struct hfsmount *hfsmp, struct cnode *cp,
+extern int hfs_getnewvnode(struct hfsmount *hfsmp, struct vnode *dvp, struct componentname *cnp,
struct cat_desc *descp, int wantrsrc, struct cat_attr *attrp,
struct cat_fork *forkp, struct vnode **vpp);
-extern int hfs_metafilelocking(struct hfsmount *hfsmp, u_long fileID, u_int flags, struct proc *p);
-
extern u_int32_t hfs_freeblks(struct hfsmount * hfsmp, int wantreserve);
extern void hfs_remove_orphans(struct hfsmount *);
OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb,
struct proc *p);
OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,
- off_t embeddedOffset, u_int64_t disksize, struct proc *p, void *args);
+ off_t embeddedOffset, u_int64_t disksize, struct proc *p, void *args, kauth_cred_t cred);
extern int hfs_early_journal_init(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,
- void *_args, int embeddedOffset, int mdb_offset,
+ void *_args, off_t embeddedOffset, daddr64_t mdb_offset,
HFSMasterDirectoryBlock *mdbp, struct ucred *cred);
-extern u_long GetFileInfo(ExtendedVCB *vcb, u_int32_t dirid, char *name,
- struct cat_attr *fattr, struct cat_fork *forkinfo);
+extern u_long GetFileInfo(ExtendedVCB *vcb, u_int32_t dirid, const char *name,
+ struct cat_attr *fattr, struct cat_fork *forkinfo);
int hfs_getconverter(u_int32_t encoding, hfs_to_unicode_func_t *get_unicode,
unicode_to_hfs_func_t *get_hfsname);
void hfs_generate_volume_notifications(struct hfsmount *hfsmp);
+__private_extern__ u_int32_t hfs_getencodingbias(void);
+__private_extern__ void hfs_setencodingbias(u_int32_t bias);
+
+extern int hfs_vgetrsrc(struct hfsmount *hfsmp, struct vnode *vp,
+ struct vnode **rvpp, struct proc *p);
+
+extern int hfs_update(struct vnode *, int);
+
+extern int hfs_truncate(struct vnode *, off_t, int, int, vfs_context_t);
+
+extern int hfs_fsync(struct vnode *, int, int, struct proc *);
+
+extern int hfs_access(struct vnode *, mode_t, struct ucred *, struct proc *);
+
+extern int hfs_vget(struct hfsmount *, cnid_t, struct vnode **, int);
+
+extern int hfs_bmap(struct vnode *, daddr_t, struct vnode **, daddr64_t *, int *);
+
+extern int hfs_removeallattr(struct hfsmount *hfsmp, u_int32_t fileid);
+
+__private_extern__ int hfs_start_transaction(struct hfsmount *hfsmp);
+__private_extern__ int hfs_end_transaction(struct hfsmount *hfsmp);
+
+extern int hfs_setextendedsecurity(struct hfsmount *hfsmp, int state);
+extern void hfs_checkextendedsecurity(struct hfsmount *hfsmp);
+
+extern int hfs_extendfs(struct hfsmount *, u_int64_t, vfs_context_t);
+extern int hfs_truncatefs(struct hfsmount *, u_int64_t, vfs_context_t);
+extern int hfs_resize_progress(struct hfsmount *, u_int32_t *);
+
+extern int hfs_isallocated(struct hfsmount *, u_long, u_long);
+
+
+/* HFS System file locking */
+#define SFL_CATALOG 0x0001
+#define SFL_EXTENTS 0x0002
+#define SFL_BITMAP 0x0004
+#define SFL_ATTRIBUTE 0x0008
+#define SFL_VALIDMASK (SFL_CATALOG | SFL_EXTENTS | SFL_BITMAP | SFL_ATTRIBUTE)
+
+extern int hfs_systemfile_lock(struct hfsmount *, int, enum hfslocktype);
+extern void hfs_systemfile_unlock(struct hfsmount *, int);
#endif /* __APPLE_API_PRIVATE */
#endif /* KERNEL */