Section 12.10. Miscellaneous Features


12.10. Miscellaneous Features

In this section, we will look at sundry HFS+ features.

12.10.1. Special System Calls

Noteworthy system calls supported by HFS+ include the following.

  • exchangedata() is used for exchanging the data and resource forks of two files. File attributes and extended attributes, including ACLs, are not exchanged, although modification times are exchanged. The call is atomic in that neither of the two files will be seen in an inconsistent state by any process. After the exchange is complete, all open file descriptors for the original file will access the new data. The primary purpose of exchangedata() is to provide applications that do not edit files in place (for safety) a way to save changes, without modifying the CNID of the original file. This way, CNID-based references to the original file will not break.

  • getattrlist() and setattrlist() are used for retrieving and setting, respectively, attributes of file system objects, including volumes (see Section 12.11).

  • geTDirentriesattr() is used for retrieving file system attributes for items in a given directory. This call is essentially a combination of getdirentries(2) and getattrlist(2). Note that getdirentries(2) is the system call invoked by readdir(3).

  • searchfs() is used for searching the file system based on a variety of criteria.[26]

    [26] The searchfs(2) man page provides details of using this system call.

12.10.2. Freezing and Thawing a Volume

HFS+ provides the file control operations F_FREEZE_FS and F_THAW_FS for freezing and thawing, respectively, a journaled mounted volume. Freezing allows a superuser process to lock down a file system by stopping file system operations. In processing a freeze request, the kernel performs the following operations on the file system corresponding to the given file descriptor.

  • It iterates over all vnodes of the mounted file system and waits for any pending write operations to finish.[27]

    [27] The waiting period uses a timeout of 10 ms.

  • It flushes the journal.

  • It acquires the global volume lock exclusively. This prevents the hfs_start_transaction() function [bsd/hfs/hfs_vfsutils.c] from acquiring this lock. Therefore, any file system functions that call hfs_start_transaction()directly or indirectlywill wait for the lock to be released.

  • It waits for any pending writes to finish on vnodes for the Extents Overflow file, the Catalog file, the Attributes file, and the volume device.

  • It records the identity of the calling process in the hfs_freezing_proc field of the hfsmount structure.

Thawing releases the global volume lock. A frozen volume can be thawed only by the process that froze it.

The fsck_hfs program uses F_FREEZE_FS and F_THAW_FS to support "live" testing (the -l option) of a mounted file system.

12.10.3. Extending and Shrinking a Volume

HFS+ has built-in support for growing or shrinking a mounted journaled file system. The hfs_extendfs() and hfs_truncatefs() kernel-internal functions, both of which are implemented in bsd/hfs/hfs_vfsops.c, provide this functionality. The functionality can be accessed from user space through the HFS_RESIZE_VOLUME command of fsctl(2) or the HFS_EXTEND_FS operation through sysctl(3), for example:

int ret, options = 0; u_int64_t newsize; // initialize this to the new size of the file system ... ret = fsctl(mounted_volume_path, HFS_RESIZE_VOLUME, &newsize, options);


12.10.4. Volume Notifications

HFS+ generates a volume notification through hfs_generate_volume_notifications() [bsd/hfs/hfs_notifications.c] when free space on a volume falls below a warning limit. Another notification is generated when the volume's free space rises above a minimal desired limit. Both limits are stored in the hfsmount structure as the hfs_freespace_notify_warninglimit and hfs_freespace_notify_desiredlevel fields, respectively. The BlockAllocate() and BlockDeallocate() low-level functions in bsd/hfs/hfscommon/Misc/VolumeAllocation.c call the notification function every time they are invoked, allowing notifications to be generated if the current allocation or deallocation operation caused the free space situation to change with respect to the limits.

We can view VFS notifications (including the HFS+ notifications mentioned in this section) by using the program shown in Figure 1233. The KernelEventAgent program (/usr/sbin/KernelEventAgent) receives these notifications and logs them to the system log file.

Figure 1233. Viewing VFS event notifications using kqueue/kevent

// kq_vfswatch.c #include <stdio.h> #include <stdlib.h> #include <sys/event.h> #include <sys/mount.h> #include <unistd.h> #define PROGNAME "kq_vfswatch" struct VfsEventDescriptions{     u_int       event;     const char *description; } VfsEventDescriptions[] = {      { VQ_NOTRESP,      "server is down"                                     },      { VQ_NEEDAUTH,     "server needs authentication"                        },      { VQ_LOWDISK,      "disk space is low"                                  },      { VQ_MOUNT,        "file system mounted"                                },      { VQ_UNMOUNT,      "file system unmounted"                              },      { VQ_DEAD,         "file system is dead (needs force unmount)"          },      { VQ_ASSIST,       "file system needs assistance from external program" },      { VQ_NOTRESPLOCK,  "server locked down"                                 },      { VQ_UPDATE,       "file system information has changed"                }, }; #define NEVENTS sizeof(VfsEventDescriptions)/sizeof(struct VfsEventDescriptions) int process_events(struct kevent *kl) {     int i, ret = 0;     printf("notification received\n");     for (i = 0; i < NEVENTS; i++)         if (VfsEventDescriptions[i].event & kl->fflags)             printf("\t+ %s\n", VfsEventDescriptions[i].description);     return ret; } #define OUT_ON_ERROR(msg, ret) { if (ret < 0) { perror(msg); goto out; } } int main(int argc, char **argv) {     int ret = -1, kqfd = -1;     struct kevent changelist;     ret = kqfd = kqueue();     OUT_ON_ERROR("kqueue", ret);     EV_SET(&changelist, 0, EVFILT_FS, EV_ADD, 0, 0, NULL);     ret = kevent(kqfd, &changelist, 1, NULL, 0, NULL);     OUT_ON_ERROR("kqueue", ret);     while (1) {         ret = kevent(kqfd, NULL, 0, &changelist, 1, NULL);         OUT_ON_ERROR("kevent", ret);         if (ret > 0)             ret = process_events(&changelist);     } out:     if (kqfd >= 0)         close(kqfd);     exit(ret); } $ gcc -Wall -o kq_vfswatch kq_vfswatch.c $ ./kq_vfswatch         # another shell         $ hdiutil create -size 32m -fs HFSJ -volname HFSJ /tmp/hfsj.dmg         ...         $ open /tmp/hfsj.dmg notification received         + file system mounted         $ dd if=/dev/zero of=/Volumes/HFSJ/data bs=4096         dd: /Volumes/HFSJ/data: No space left on device         ... notification received         + disk space is low         $ mount -u -o,perm /Volumes/HFSJ notification received         + file system information has changed         $ umount /Volumes/HFSJ notification received         + file system unmounted

hfs_generate_volume_notifications() calls vfs_event_signal() [bsd/vfs/vfs_subr.c] to generate a kqueue notification. Several HFS+ internal operations also use the kqueue mechanism to generate notifications when file system objects are modified. This allows interested user-space partiesthe prime example being the Finderto learn about these changes.


12.10.5. Support for Sparse Devices

HFS+ allows the device underlying a file system to be sparse. Apple's Disk Images framework uses this feature to support sparse disk imagesit uses the HFS_SETBACKINGSTOREINFO control operation to inform the kernel of the backing store file system. Sparse disk images can be created using hdiutil, either by specifying SPARSE as the disk image type or by providing a disk image name that contains the .sparseimage suffix. Let us look at an example.

$ hdiutil create -size 128m -fs HFSJ -volname HFSSparse /tmp/hfsj.sparseimage created: /tmp/hfsj.sparseimage $ ls -lh /tmp/hfsj.sparseimage -rw-r--r--   1 amit  wheel       12M Oct 13 18:48 /tmp/hfsj.sparseimage $ open /tmp/hfsj.sparseimage


We see that even though the volume's capacity is 128MB, the sparse disk image currently occupies only 12MB. It will be dynamically grown, up to the volume's capacity, when necessary.




Mac OS X Internals. A Systems Approach
Mac OS X Internals: A Systems Approach
ISBN: 0321278542
EAN: 2147483647
Year: 2006
Pages: 161
Authors: Amit Singh

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net