FreeBSD ZFS
The Zettabyte File System
|
ZFS control directory (a.k.a. More...
#include <sys/zfs_context.h>
#include <sys/zfs_ctldir.h>
#include <sys/zfs_ioctl.h>
#include <sys/zfs_vfsops.h>
#include <sys/namei.h>
#include <sys/gfs.h>
#include <sys/stat.h>
#include <sys/dmu.h>
#include <sys/dsl_deleg.h>
#include <sys/mount.h>
#include <sys/sunddi.h>
#include "zfs_namecheck.h"
Go to the source code of this file.
Data Structures | |
struct | zfsctl_node |
struct | zfsctl_snapdir |
struct | zfs_snapentry_t |
Defines | |
#define | NROOT_ENTRIES |
#define | ZFSCTL_INO_SNAP(id) (id) |
.zfs inode namespace | |
Typedefs | |
typedef struct zfsctl_node | zfsctl_node_t |
typedef struct zfsctl_snapdir | zfsctl_snapdir_t |
Functions | |
static int | snapentry_compare (const void *a, const void *b) |
static vnode_t * | zfsctl_mknode_snapdir (vnode_t *pvp) |
Creates vp, which is '.zfs/snapshot' (zfsctl_snapdir_t). | |
static vnode_t * | zfsctl_mknode_shares (vnode_t *) |
static vnode_t * | zfsctl_snapshot_mknode (vnode_t *pvp, uint64_t objset) |
This creates a GFS node under '.zfs/snapshot' representing each snapshot. | |
static int | zfsctl_unmount_snap (zfs_snapentry_t *, int, cred_t *) |
void | zfsctl_init (void) |
Initialize the various GFS pieces we'll need to create and manipulate .zfs directories. | |
void | zfsctl_fini (void) |
boolean_t | zfsctl_is_node (vnode_t *vp) |
static ino64_t | zfsctl_root_inode_cb (vnode_t *vp, int index) |
Return the inode number associated with the 'snapshot' or 'shares' directory. | |
void | zfsctl_create (zfsvfs_t *zfsvfs) |
Create the '.zfs' directory. | |
void | zfsctl_destroy (zfsvfs_t *zfsvfs) |
Destroy the '.zfs' directory. | |
vnode_t * | zfsctl_root (znode_t *zp) |
Given a root znode, retrieve the associated .zfs directory. | |
static int | zfsctl_common_open (struct vop_open_args *ap) |
Common open routine. | |
static int | zfsctl_common_close (struct vop_close_args *ap) |
Common close routine. | |
static int | zfsctl_common_access (struct vop_access_args *ap) |
Common access routine. | |
static void | zfsctl_common_getattr (vnode_t *vp, vattr_t *vap) |
Common getattr function. | |
static int | zfsctl_common_fid (struct vop_fid_args *ap) |
static int | zfsctl_shares_fid (struct vop_fid_args *ap) |
static int | zfsctl_common_reclaim (struct vop_reclaim_args *ap) |
static int | zfsctl_root_getattr (struct vop_getattr_args *ap) |
Get root directory attributes. | |
int | zfsctl_root_lookup (vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct, int *direntflags, pathname_t *realpnp) |
Special case the handling of "..". | |
int | zfsctl_freebsd_root_lookup (struct vop_lookup_args *ap) |
Special case the handling of "..". | |
static int | zfsctl_snapshot_zname (vnode_t *vp, const char *name, int len, char *zname) |
static int | zfsctl_snapdir_mkdir (vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr, caller_context_t *cc, int flags, vsecattr_t *vsecp) |
This creates a snapshot under '.zfs/snapshot'. | |
static int | zfsctl_freebsd_snapdir_mkdir (struct vop_mkdir_args *ap) |
int | zfsctl_snapdir_lookup (struct vop_lookup_args *ap) |
Lookup entry point for the 'snapshot' directory. | |
int | zfsctl_shares_lookup (struct vop_lookup_args *ap) |
static int | zfsctl_snapdir_readdir_cb (vnode_t *vp, void *dp, int *eofp, offset_t *offp, offset_t *nextp, void *data, int flags) |
static int | zfsctl_shares_readdir (struct vop_readdir_args *ap) |
static int | zfsctl_shares_getattr (struct vop_getattr_args *ap) |
static int | zfsctl_snapdir_getattr (struct vop_getattr_args *ap) |
static int | zfsctl_snapdir_inactive (struct vop_inactive_args *ap) |
static int | zfsctl_snapshot_inactive (struct vop_inactive_args *ap) |
static int | zfsctl_traverse_begin (vnode_t **vpp, int lktype) |
static void | zfsctl_traverse_end (vnode_t *vp, int err) |
static int | zfsctl_snapshot_getattr (struct vop_getattr_args *ap) |
static int | zfsctl_snapshot_fid (struct vop_fid_args *ap) |
static int | zfsctl_snapshot_lookup (struct vop_lookup_args *ap) |
static int | zfsctl_snapshot_vptocnp (struct vop_vptocnp_args *ap) |
int | zfsctl_lookup_objset (vfs_t *vfsp, uint64_t objsetid, zfsvfs_t **zfsvfsp) |
int | zfsctl_umount_snapshots (vfs_t *vfsp, int fflags, cred_t *cr) |
Unmount any snapshots for the given filesystem. | |
Variables | |
static struct vop_vector | zfsctl_ops_root |
static struct vop_vector | zfsctl_ops_snapdir |
static struct vop_vector | zfsctl_ops_snapshot |
These VP's should never see the light of day. | |
static struct vop_vector | zfsctl_ops_shares |
static struct vop_vector | zfsctl_ops_shares_dir |
static gfs_dirent_t | zfsctl_root_entries [] |
Root directory elements. |
ZFS control directory (a.k.a.
".zfs")
This directory provides a common location for all ZFS meta-objects. Currently, this is only the 'snapshot' directory, but this may expand in the future. The elements are built using the GFS primitives, as the hierarchy does not actually exist on disk.
For 'snapshot', we don't want to have all snapshots always mounted, because this would take up a huge amount of space in /etc/mnttab. We have three types of objects:
ctldir ------> snapshotdir -------> snapshot | | V mounted fs
The 'snapshot' node contains just enough information to lookup '..' and act as a mountpoint for the snapshot. Whenever we lookup a specific snapshot, we perform an automount of the underlying filesystem and return the corresponding vnode.
All mounts are handled automatically by the kernel, but unmounts are (currently) handled from user land. The main reason is that there is no reliable way to auto-unmount the filesystem when it's "no longer in use". When the user unmounts a filesystem, we call zfsctl_unmount(), which unmounts any snapshots within the snapshot directory.
The '.zfs', '.zfs/snapshot', and all directories created under '.zfs/snapshot' (ie: '.zfs/snapshot/<snapname>') are all GFS nodes and share the same vfs_t as the head filesystem (what '.zfs' lives under).
File systems mounted ontop of the GFS nodes '.zfs/snapshot/<snapname>' (ie: snapshots) are ZFS nodes and have their own unique vfs_t. However, vnodes within these mounted on file systems have their v_vfsp fields set to the head filesystem to make NFS happy (see zfsctl_snapdir_lookup()). We VFS_HOLD the head filesystem's vfs_t so that it cannot be freed until all snapshots have been unmounted.
Definition in file zfs_ctldir.c.
#define NROOT_ENTRIES |
((sizeof (zfsctl_root_entries) / \ sizeof (gfs_dirent_t)) + 1)
Definition at line 164 of file zfs_ctldir.c.
#define ZFSCTL_INO_SNAP | ( | id | ) | (id) |
.zfs inode namespace
We need to generate unique inode numbers for all files and directories within the .zfs pseudo-filesystem. We use the following scheme:
ENTRY ZFSCTL_INODE .zfs 1 .zfs/snapshot 2 .zfs/snapshot/<snap> objectid(snap)
Definition at line 482 of file zfs_ctldir.c.
typedef struct zfsctl_node zfsctl_node_t |
typedef struct zfsctl_snapdir zfsctl_snapdir_t |
static int snapentry_compare | ( | const void * | a, |
const void * | b | ||
) | [static] |
Definition at line 104 of file zfs_ctldir.c.
static int zfsctl_common_access | ( | struct vop_access_args * | ap | ) | [static] |
static int zfsctl_common_close | ( | struct vop_close_args * | ap | ) | [static] |
static int zfsctl_common_fid | ( | struct vop_fid_args * | ap | ) | [static] |
Definition at line 387 of file zfs_ctldir.c.
static void zfsctl_common_getattr | ( | vnode_t * | vp, |
vattr_t * | vap | ||
) | [static] |
static int zfsctl_common_open | ( | struct vop_open_args * | ap | ) | [static] |
static int zfsctl_common_reclaim | ( | struct vop_reclaim_args * | ap | ) | [static] |
Definition at line 452 of file zfs_ctldir.c.
void zfsctl_create | ( | zfsvfs_t * | zfsvfs | ) |
Create the '.zfs' directory.
This directory is cached as part of the VFS structure. This results in a hold on the vfs_t. The code in zfs_umount() therefore checks against a vfs_count of 2 instead of 1. This reference is removed when the ctldir is destroyed in the unmount.
Definition at line 243 of file zfs_ctldir.c.
void zfsctl_destroy | ( | zfsvfs_t * | zfsvfs | ) |
Destroy the '.zfs' directory.
Only called when the filesystem is unmounted. There might still be more references if we were force unmounted, but only new zfs_inactive() calls can occur and they don't reference .zfs
Definition at line 281 of file zfs_ctldir.c.
void zfsctl_fini | ( | void | ) |
Definition at line 182 of file zfs_ctldir.c.
int zfsctl_freebsd_root_lookup | ( | struct vop_lookup_args * | ap | ) |
Special case the handling of "..".
Definition at line 587 of file zfs_ctldir.c.
static int zfsctl_freebsd_snapdir_mkdir | ( | struct vop_mkdir_args * | ap | ) | [static] |
Definition at line 901 of file zfs_ctldir.c.
void zfsctl_init | ( | void | ) |
Initialize the various GFS pieces we'll need to create and manipulate .zfs directories.
This is called from the ZFS init routine, and initializes the vnode ops vectors that we'll be using.
Definition at line 174 of file zfs_ctldir.c.
boolean_t zfsctl_is_node | ( | vnode_t * | vp | ) |
Definition at line 208 of file zfs_ctldir.c.
int zfsctl_lookup_objset | ( | vfs_t * | vfsp, |
uint64_t | objsetid, | ||
zfsvfs_t ** | zfsvfsp | ||
) |
Definition at line 1625 of file zfs_ctldir.c.
vnode_t * zfsctl_mknode_shares | ( | vnode_t * | pvp | ) | [static] |
Definition at line 1236 of file zfs_ctldir.c.
vnode_t * zfsctl_mknode_snapdir | ( | vnode_t * | pvp | ) | [static] |
Creates vp, which is '.zfs/snapshot' (zfsctl_snapdir_t).
This function is the callback to create a GFS vnode for '.zfs/snapshot' when a lookup is performed on .zfs for "snapshot".
pvp | the '.zfs' directory (zfsctl_node_t) |
Definition at line 1217 of file zfs_ctldir.c.
vnode_t* zfsctl_root | ( | znode_t * | zp | ) |
Given a root znode, retrieve the associated .zfs directory.
Add a hold to the vnode and return it.
Definition at line 292 of file zfs_ctldir.c.
static int zfsctl_root_getattr | ( | struct vop_getattr_args * | ap | ) | [static] |
Get root directory attributes.
Definition at line 489 of file zfs_ctldir.c.
static ino64_t zfsctl_root_inode_cb | ( | vnode_t * | vp, |
int | index | ||
) | [static] |
Return the inode number associated with the 'snapshot' or 'shares' directory.
Definition at line 224 of file zfs_ctldir.c.
int zfsctl_root_lookup | ( | vnode_t * | dvp, |
char * | nm, | ||
vnode_t ** | vpp, | ||
pathname_t * | pnp, | ||
int | flags, | ||
vnode_t * | rdir, | ||
cred_t * | cr, | ||
caller_context_t * | ct, | ||
int * | direntflags, | ||
pathname_t * | realpnp | ||
) |
Special case the handling of "..".
Definition at line 518 of file zfs_ctldir.c.
static int zfsctl_shares_fid | ( | struct vop_fid_args * | ap | ) | [static] |
Definition at line 423 of file zfs_ctldir.c.
static int zfsctl_shares_getattr | ( | struct vop_getattr_args * | ap | ) | [static] |
Definition at line 1253 of file zfs_ctldir.c.
int zfsctl_shares_lookup | ( | struct vop_lookup_args * | ap | ) |
Definition at line 1087 of file zfs_ctldir.c.
static int zfsctl_shares_readdir | ( | struct vop_readdir_args * | ap | ) | [static] |
Definition at line 1171 of file zfs_ctldir.c.
static int zfsctl_snapdir_getattr | ( | struct vop_getattr_args * | ap | ) | [static] |
Definition at line 1286 of file zfs_ctldir.c.
static int zfsctl_snapdir_inactive | ( | struct vop_inactive_args * | ap | ) | [static] |
Definition at line 1311 of file zfs_ctldir.c.
int zfsctl_snapdir_lookup | ( | struct vop_lookup_args * | ap | ) |
Lookup entry point for the 'snapshot' directory.
Try to open the snapshot if it exist, creating the pseudo filesystem vnode as necessary. Perform a mount of the associated dataset on top of the vnode.
Definition at line 923 of file zfs_ctldir.c.
static int zfsctl_snapdir_mkdir | ( | vnode_t * | dvp, |
char * | dirname, | ||
vattr_t * | vap, | ||
vnode_t ** | vpp, | ||
cred_t * | cr, | ||
caller_context_t * | cc, | ||
int | flags, | ||
vsecattr_t * | vsecp | ||
) | [static] |
This creates a snapshot under '.zfs/snapshot'.
Definition at line 869 of file zfs_ctldir.c.
static int zfsctl_snapdir_readdir_cb | ( | vnode_t * | vp, |
void * | dp, | ||
int * | eofp, | ||
offset_t * | offp, | ||
offset_t * | nextp, | ||
void * | data, | ||
int | flags | ||
) | [static] |
Definition at line 1127 of file zfs_ctldir.c.
static int zfsctl_snapshot_fid | ( | struct vop_fid_args * | ap | ) | [static] |
Definition at line 1522 of file zfs_ctldir.c.
static int zfsctl_snapshot_getattr | ( | struct vop_getattr_args * | ap | ) | [static] |
Definition at line 1504 of file zfs_ctldir.c.
static int zfsctl_snapshot_inactive | ( | struct vop_inactive_args * | ap | ) | [static] |
Definition at line 1426 of file zfs_ctldir.c.
static int zfsctl_snapshot_lookup | ( | struct vop_lookup_args * | ap | ) | [static] |
Definition at line 1539 of file zfs_ctldir.c.
static vnode_t * zfsctl_snapshot_mknode | ( | vnode_t * | pvp, |
uint64_t | objset | ||
) | [static] |
This creates a GFS node under '.zfs/snapshot' representing each snapshot.
This newly created GFS node is what we mount snapshot vfs_t's ontop of.
pvp | the GFS vnode '.zfs/snapshot' |
Definition at line 1410 of file zfs_ctldir.c.
static int zfsctl_snapshot_vptocnp | ( | struct vop_vptocnp_args * | ap | ) | [static] |
Definition at line 1569 of file zfs_ctldir.c.
static int zfsctl_snapshot_zname | ( | vnode_t * | vp, |
const char * | name, | ||
int | len, | ||
char * | zname | ||
) | [static] |
Definition at line 632 of file zfs_ctldir.c.
static int zfsctl_traverse_begin | ( | vnode_t ** | vpp, |
int | lktype | ||
) | [static] |
Definition at line 1483 of file zfs_ctldir.c.
static void zfsctl_traverse_end | ( | vnode_t * | vp, |
int | err | ||
) | [static] |
Definition at line 1494 of file zfs_ctldir.c.
int zfsctl_umount_snapshots | ( | vfs_t * | vfsp, |
int | fflags, | ||
cred_t * | cr | ||
) |
Unmount any snapshots for the given filesystem.
This is called from zfs_umount() - if we have a ctldir, then go through and unmount all the snapshots.
Definition at line 1688 of file zfs_ctldir.c.
static int zfsctl_unmount_snap | ( | zfs_snapentry_t * | sep, |
int | fflags, | ||
cred_t * | cr | ||
) | [static] |
Definition at line 647 of file zfs_ctldir.c.
static struct vop_vector zfsctl_ops_root [static] |
{ .vop_default = &default_vnodeops, .vop_open = zfsctl_common_open, .vop_close = zfsctl_common_close, .vop_ioctl = VOP_EINVAL, .vop_getattr = zfsctl_root_getattr, .vop_access = zfsctl_common_access, .vop_readdir = gfs_vop_readdir, .vop_lookup = zfsctl_freebsd_root_lookup, .vop_inactive = gfs_vop_inactive, .vop_reclaim = zfsctl_common_reclaim, .vop_fid = zfsctl_common_fid, }
Definition at line 130 of file zfs_ctldir.c.
static struct vop_vector zfsctl_ops_shares [static] |
{ .vop_default = &default_vnodeops, .vop_open = zfsctl_common_open, .vop_close = zfsctl_common_close, .vop_ioctl = VOP_EINVAL, .vop_getattr = zfsctl_shares_getattr, .vop_access = zfsctl_common_access, .vop_readdir = zfsctl_shares_readdir, .vop_lookup = zfsctl_shares_lookup, .vop_inactive = gfs_vop_inactive, .vop_reclaim = zfsctl_common_reclaim, .vop_fid = zfsctl_shares_fid, }
Definition at line 133 of file zfs_ctldir.c.
struct vop_vector zfsctl_ops_shares_dir [static] |
Definition at line 134 of file zfs_ctldir.c.
static struct vop_vector zfsctl_ops_snapdir [static] |
{ .vop_default = &default_vnodeops, .vop_open = zfsctl_common_open, .vop_close = zfsctl_common_close, .vop_ioctl = VOP_EINVAL, .vop_getattr = zfsctl_snapdir_getattr, .vop_access = zfsctl_common_access, .vop_mkdir = zfsctl_freebsd_snapdir_mkdir, .vop_readdir = gfs_vop_readdir, .vop_lookup = zfsctl_snapdir_lookup, .vop_inactive = zfsctl_snapdir_inactive, .vop_reclaim = zfsctl_common_reclaim, .vop_fid = zfsctl_common_fid, }
Definition at line 131 of file zfs_ctldir.c.
static struct vop_vector zfsctl_ops_snapshot [static] |
{ .vop_default = &default_vnodeops, .vop_inactive = zfsctl_snapshot_inactive, .vop_lookup = zfsctl_snapshot_lookup, .vop_reclaim = zfsctl_common_reclaim, .vop_getattr = zfsctl_snapshot_getattr, .vop_fid = zfsctl_snapshot_fid, .vop_vptocnp = zfsctl_snapshot_vptocnp, }
These VP's should never see the light of day.
They should always be covered.
Definition at line 132 of file zfs_ctldir.c.
gfs_dirent_t zfsctl_root_entries[] [static] |
{ { "snapshot", zfsctl_mknode_snapdir, GFS_CACHE_VNODE }, { "shares", zfsctl_mknode_shares, GFS_CACHE_VNODE }, { NULL } }
Root directory elements.
We only have two entries snapshot and shares.
Definition at line 157 of file zfs_ctldir.c.