FreeBSD ZFS
The Zettabyte File System
|
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/sysmacros.h>
#include <sys/resource.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/kmem.h>
#include <sys/uio.h>
#include <sys/cmn_err.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include <sys/sunddi.h>
#include <sys/random.h>
#include <sys/policy.h>
#include <sys/kcondvar.h>
#include <sys/callb.h>
#include <sys/smp.h>
#include <sys/zfs_dir.h>
#include <sys/zfs_acl.h>
#include <sys/fs/zfs.h>
#include <sys/zap.h>
#include <sys/dmu.h>
#include <sys/atomic.h>
#include <sys/zfs_ctldir.h>
#include <sys/zfs_fuid.h>
#include <sys/sa.h>
#include <sys/zfs_sa.h>
#include <sys/dnlc.h>
#include <sys/extdirent.h>
Go to the source code of this file.
Functions | |
static int | zfs_match_find (zfsvfs_t *zfsvfs, znode_t *dzp, char *name, boolean_t exact, boolean_t update, int *deflags, pathname_t *rpnp, uint64_t *zoid) |
zfs_match_find() is used by zfs_dirent_lock() to peform zap lookups of names after deciding which is the appropriate lookup interface. | |
int | zfs_dirent_lock (zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp, int flag, int *direntflags, pathname_t *realpnp) |
Lock a directory entry. | |
void | zfs_dirent_unlock (zfs_dirlock_t *dl) |
Unlock this directory entry and wake anyone who was waiting for it. | |
int | zfs_dirlook (znode_t *dzp, char *name, vnode_t **vpp, int flags, int *deflg, pathname_t *rpnp) |
Look up an entry in a directory. | |
void | zfs_unlinked_add (znode_t *zp, dmu_tx_t *tx) |
unlinked Set (formerly known as the "delete queue") Error Handling | |
void | zfs_unlinked_drain (zfsvfs_t *zfsvfs) |
static int | zfs_purgedir (znode_t *dzp) |
Delete the entire contents of a directory. | |
void | zfs_rmnode (znode_t *zp) |
static uint64_t | zfs_dirent (znode_t *zp, uint64_t mode) |
int | zfs_link_create (zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag) |
Link zp into dl. | |
static int | zfs_dropname (zfs_dirlock_t *dl, znode_t *zp, znode_t *dzp, dmu_tx_t *tx, int flag) |
int | zfs_link_destroy (zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag, boolean_t *unlinkedp) |
Unlink zp from dl, and mark zp for deletion if this was the last link. | |
boolean_t | zfs_dirempty (znode_t *dzp) |
Indicate whether the directory is empty. | |
int | zfs_make_xattrdir (znode_t *zp, vattr_t *vap, vnode_t **xvpp, cred_t *cr) |
int | zfs_get_xattrdir (znode_t *zp, vnode_t **xvpp, cred_t *cr, int flags) |
Return a znode for the extended attribute directory for zp. | |
int | zfs_sticky_remove_access (znode_t *zdp, znode_t *zp, cred_t *cr) |
Decide whether it is okay to remove within a sticky directory. |
boolean_t zfs_dirempty | ( | znode_t * | dzp | ) |
static uint64_t zfs_dirent | ( | znode_t * | zp, |
uint64_t | mode | ||
) | [static] |
int zfs_dirent_lock | ( | zfs_dirlock_t ** | dlpp, |
znode_t * | dzp, | ||
char * | name, | ||
znode_t ** | zpp, | ||
int | flag, | ||
int * | direntflags, | ||
pathname_t * | realpnp | ||
) |
Lock a directory entry.
A dirlock on <dzp, name> protects that name in dzp's directory zap object. As long as you hold a dirlock, you can assume two things: (1) dzp cannot be reaped, and (2) no other thread can change the zap entry for (i.e. link or unlink) this name.
Input arguments: dzp - znode for directory name - name of entry to lock flag - ZNEW: if the entry already exists, fail with EEXIST. ZEXISTS: if the entry does not exist, fail with ENOENT. ZSHARED: allow concurrent access with other ZSHARED callers. ZXATTR: we want dzp's xattr directory ZCILOOK: On a mixed sensitivity file system, this lookup should be case-insensitive. ZCIEXACT: On a purely case-insensitive file system, this lookup should be case-sensitive. ZRENAMING: we are locking for renaming, force narrow locks ZHAVELOCK: Don't grab the z_name_lock for this call. The current thread already holds it.
Output arguments: zpp - pointer to the znode for the entry (NULL if there isn't one) dlpp - pointer to the dirlock for this entry (NULL on error) direntflags - (case-insensitive lookup only) flags if multiple case-sensitive matches exist in directory realpnp - (case-insensitive lookup only) actual name matched within the directory
Return value: 0 on success or errno on failure.
NOTE: Always checks for, and rejects, '.' and '..'. NOTE: For case-insensitive file systems we take wide locks (see below), but return znode pointers to a single match.
void zfs_dirent_unlock | ( | zfs_dirlock_t * | dl | ) |
int zfs_dirlook | ( | znode_t * | dzp, |
char * | name, | ||
vnode_t ** | vpp, | ||
int | flags, | ||
int * | deflg, | ||
pathname_t * | rpnp | ||
) |
static int zfs_dropname | ( | zfs_dirlock_t * | dl, |
znode_t * | zp, | ||
znode_t * | dzp, | ||
dmu_tx_t * | tx, | ||
int | flag | ||
) | [static] |
int zfs_get_xattrdir | ( | znode_t * | zp, |
vnode_t ** | xvpp, | ||
cred_t * | cr, | ||
int | flags | ||
) |
Return a znode for the extended attribute directory for zp.
** If the directory does not already exist, it is created **
IN: zp - znode to obtain attribute directory from cr - credentials of caller flags - flags from the VOP_LOOKUP call
OUT: xzpp - pointer to extended attribute znode
RETURN: 0 on success error number on failure
int zfs_link_create | ( | zfs_dirlock_t * | dl, |
znode_t * | zp, | ||
dmu_tx_t * | tx, | ||
int | flag | ||
) |
int zfs_link_destroy | ( | zfs_dirlock_t * | dl, |
znode_t * | zp, | ||
dmu_tx_t * | tx, | ||
int | flag, | ||
boolean_t * | unlinkedp | ||
) |
Unlink zp from dl, and mark zp for deletion if this was the last link.
Can fail if zp is a mount point (EBUSY) or a non-empty directory (EEXIST). If 'unlinkedp' is NULL, we put unlinked znodes on the unlinked list. If it's non-NULL, we use it to indicate whether the znode needs deletion, and it's the caller's job to do it.
int zfs_make_xattrdir | ( | znode_t * | zp, |
vattr_t * | vap, | ||
vnode_t ** | xvpp, | ||
cred_t * | cr | ||
) |
static int zfs_match_find | ( | zfsvfs_t * | zfsvfs, |
znode_t * | dzp, | ||
char * | name, | ||
boolean_t | exact, | ||
boolean_t | update, | ||
int * | deflags, | ||
pathname_t * | rpnp, | ||
uint64_t * | zoid | ||
) | [static] |
zfs_match_find() is used by zfs_dirent_lock() to peform zap lookups of names after deciding which is the appropriate lookup interface.
static int zfs_purgedir | ( | znode_t * | dzp | ) | [static] |
Delete the entire contents of a directory.
Return a count of the number of entries that could not be deleted. If we encounter an error, return a count of at least one so that the directory stays in the unlinked set.
NOTE: this function assumes that the directory is inactive, so there is no need to lock its entries before deletion. Also, it assumes the directory contents is *only* regular files.
Decide whether it is okay to remove within a sticky directory.
In sticky directories, write access is not sufficient; you can remove entries from a directory only if:
you own the directory, you own the entry, the entry is a plain file and you have write access, or you are privileged (checked in secpolicy...).
The function returns 0 if remove access is granted.
unlinked Set (formerly known as the "delete queue") Error Handling
When dealing with the unlinked set, we dmu_tx_hold_zap(), but we don't specify the name of the entry that we will be manipulating. We also fib and say that we won't be adding any new entries to the unlinked set, even though we might (this is to lower the minimum file size that can be deleted in a full filesystem). So on the small chance that the nlink list is using a fat zap (ie. has more than 2000 entries), we *may* not pre-read a block that's needed. Therefore it is remotely possible for some of the assertions regarding the unlinked set below to fail due to i/o error. On a nondebug system, this will result in the space being leaked.