git://git.camperquake.de
/
zfs.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Add snapdev=[hidden|visible] dataset property
[zfs.git]
/
module
/
zfs
/
zfs_ctldir.c
diff --git
a/module/zfs/zfs_ctldir.c
b/module/zfs/zfs_ctldir.c
index
1923934
..
4fa530b
100644
(file)
--- a/
module/zfs/zfs_ctldir.c
+++ b/
module/zfs/zfs_ctldir.c
@@
-90,6
+90,11
@@
*/
int zfs_expire_snapshot = ZFSCTL_EXPIRE_SNAPSHOT;
*/
int zfs_expire_snapshot = ZFSCTL_EXPIRE_SNAPSHOT;
+/*
+ * Dedicated task queue for unmounting snapshots.
+ */
+static taskq_t *zfs_expire_taskq;
+
static zfs_snapentry_t *
zfsctl_sep_alloc(void)
{
static zfs_snapentry_t *
zfsctl_sep_alloc(void)
{
@@
-112,16
+117,15
@@
zfsctl_sep_free(zfs_snapentry_t *sep)
static void
zfsctl_expire_snapshot(void *data)
{
static void
zfsctl_expire_snapshot(void *data)
{
- zfs_snapentry_t *sep;
- zfs_sb_t *zsb;
+ zfs_snapentry_t *sep
= (zfs_snapentry_t *)data
;
+ zfs_sb_t *zsb
= ITOZSB(sep->se_inode)
;
int error;
int error;
- sep = spl_get_work_data(data, zfs_snapentry_t, se_work.work);
- zsb = ITOZSB(sep->se_inode);
-
error = zfsctl_unmount_snapshot(zsb, sep->se_name, MNT_EXPIRE);
if (error == EBUSY)
error = zfsctl_unmount_snapshot(zsb, sep->se_name, MNT_EXPIRE);
if (error == EBUSY)
- schedule_delayed_work(&sep->se_work, zfs_expire_snapshot * HZ);
+ sep->se_taskqid = taskq_dispatch_delay(zfs_expire_taskq,
+ zfsctl_expire_snapshot, sep, TQ_SLEEP,
+ ddi_get_lbolt() + zfs_expire_snapshot * HZ);
}
int
}
int
@@
-193,6
+197,7
@@
zfsctl_inode_alloc(zfs_sb_t *zsb, uint64_t id,
zp->z_is_mapped = B_FALSE;
zp->z_is_ctldir = B_TRUE;
zp->z_is_sa = B_FALSE;
zp->z_is_mapped = B_FALSE;
zp->z_is_ctldir = B_TRUE;
zp->z_is_sa = B_FALSE;
+ zp->z_is_stale = B_FALSE;
ip->i_ino = id;
ip->i_mode = (S_IFDIR | S_IRUGO | S_IXUGO);
ip->i_uid = 0;
ip->i_ino = id;
ip->i_mode = (S_IFDIR | S_IRUGO | S_IXUGO);
ip->i_uid = 0;
@@
-225,13
+230,13
@@
zfsctl_inode_alloc(zfs_sb_t *zsb, uint64_t id,
* Lookup the inode with given id, it will be allocated if needed.
*/
static struct inode *
* Lookup the inode with given id, it will be allocated if needed.
*/
static struct inode *
-zfsctl_inode_lookup(zfs_sb_t *zsb, u
nsigned long
id,
+zfsctl_inode_lookup(zfs_sb_t *zsb, u
int64_t
id,
const struct file_operations *fops, const struct inode_operations *ops)
{
struct inode *ip = NULL;
while (ip == NULL) {
const struct file_operations *fops, const struct inode_operations *ops)
{
struct inode *ip = NULL;
while (ip == NULL) {
- ip = ilookup(zsb->z_sb, id);
+ ip = ilookup(zsb->z_sb,
(unsigned long)
id);
if (ip)
break;
if (ip)
break;
@@
-267,10
+272,14
@@
zfsctl_inode_inactive(struct inode *ip)
* therefore checks against a vfs_count of 2 instead of 1. This reference
* is removed when the ctldir is destroyed in the unmount. All other entities
* under the '.zfs' directory are created dynamically as needed.
* therefore checks against a vfs_count of 2 instead of 1. This reference
* is removed when the ctldir is destroyed in the unmount. All other entities
* under the '.zfs' directory are created dynamically as needed.
+ *
+ * Because the dynamically created '.zfs' directory entries assume the use
+ * of 64-bit inode numbers this support must be disabled on 32-bit systems.
*/
int
zfsctl_create(zfs_sb_t *zsb)
{
*/
int
zfsctl_create(zfs_sb_t *zsb)
{
+#if defined(CONFIG_64BIT)
ASSERT(zsb->z_ctldir == NULL);
zsb->z_ctldir = zfsctl_inode_alloc(zsb, ZFSCTL_INO_ROOT,
ASSERT(zsb->z_ctldir == NULL);
zsb->z_ctldir = zfsctl_inode_alloc(zsb, ZFSCTL_INO_ROOT,
@@
-279,6
+288,9
@@
zfsctl_create(zfs_sb_t *zsb)
return (ENOENT);
return (0);
return (ENOENT);
return (0);
+#else
+ return (EOPNOTSUPP);
+#endif /* CONFIG_64BIT */
}
/*
}
/*
@@
-431,7
+443,7
@@
zfsctl_snapdir_lookup(struct inode *dip, char *name, struct inode **ipp,
ZFS_ENTER(zsb);
ZFS_ENTER(zsb);
- error = dmu_snapshot_
id
(zsb->z_os, name, &id);
+ error = dmu_snapshot_
lookup
(zsb->z_os, name, &id);
if (error) {
ZFS_EXIT(zsb);
return (error);
if (error) {
ZFS_EXIT(zsb);
return (error);
@@
-654,7
+666,7
@@
zfsctl_snapdir_inactive(struct inode *ip)
if (sep->se_inode == ip) {
avl_remove(&zsb->z_ctldir_snaps, sep);
if (sep->se_inode == ip) {
avl_remove(&zsb->z_ctldir_snaps, sep);
-
cancel_delayed_work_sync(&sep->se_work
);
+
taskq_cancel_id(zfs_expire_taskq, sep->se_taskqid
);
zfsctl_sep_free(sep);
break;
}
zfsctl_sep_free(sep);
break;
}
@@
-674,7
+686,7
@@
zfsctl_snapdir_inactive(struct inode *ip)
"exec 0</dev/null " \
" 1>/dev/null " \
" 2>/dev/null; " \
"exec 0</dev/null " \
" 1>/dev/null " \
" 2>/dev/null; " \
- "umount -t zfs -n %s
%s
"
+ "umount -t zfs -n %s
'%s'
"
static int
__zfsctl_unmount_snapshot(zfs_snapentry_t *sep, int flags)
static int
__zfsctl_unmount_snapshot(zfs_snapentry_t *sep, int flags)
@@
-685,7
+697,7
@@
__zfsctl_unmount_snapshot(zfs_snapentry_t *sep, int flags)
argv[2] = kmem_asprintf(SET_UNMOUNT_CMD,
flags & MNT_FORCE ? "-f " : "", sep->se_path);
argv[2] = kmem_asprintf(SET_UNMOUNT_CMD,
flags & MNT_FORCE ? "-f " : "", sep->se_path);
- error = call_usermodehelper(argv[0], argv, envp,
1
);
+ error = call_usermodehelper(argv[0], argv, envp,
UMH_WAIT_PROC
);
strfree(argv[2]);
/*
strfree(argv[2]);
/*
@@
-701,7
+713,8
@@
__zfsctl_unmount_snapshot(zfs_snapentry_t *sep, int flags)
* to prevent zfsctl_expire_snapshot() from attempting a unmount.
*/
if ((error == 0) && !(flags & MNT_EXPIRE))
* to prevent zfsctl_expire_snapshot() from attempting a unmount.
*/
if ((error == 0) && !(flags & MNT_EXPIRE))
- cancel_delayed_work(&sep->se_work);
+ taskq_cancel_id(zfs_expire_taskq, sep->se_taskqid);
+
return (error);
}
return (error);
}
@@
-774,7
+787,7
@@
zfsctl_unmount_snapshots(zfs_sb_t *zsb, int flags, int *count)
"exec 0</dev/null " \
" 1>/dev/null " \
" 2>/dev/null; " \
"exec 0</dev/null " \
" 1>/dev/null " \
" 2>/dev/null; " \
- "mount -t zfs -n
%s %s
"
+ "mount -t zfs -n
'%s' '%s'
"
int
zfsctl_mount_snapshot(struct path *path, int flags)
int
zfsctl_mount_snapshot(struct path *path, int flags)
@@
-810,7
+823,7
@@
zfsctl_mount_snapshot(struct path *path, int flags)
* to safely abort the automount. This should be very rare.
*/
argv[2] = kmem_asprintf(SET_MOUNT_CMD, full_name, full_path);
* to safely abort the automount. This should be very rare.
*/
argv[2] = kmem_asprintf(SET_MOUNT_CMD, full_name, full_path);
- error = call_usermodehelper(argv[0], argv, envp,
1
);
+ error = call_usermodehelper(argv[0], argv, envp,
UMH_WAIT_PROC
);
strfree(argv[2]);
if (error) {
printk("ZFS: Unable to automount %s at %s: %d\n",
strfree(argv[2]);
if (error) {
printk("ZFS: Unable to automount %s at %s: %d\n",
@@
-830,7
+843,7
@@
zfsctl_mount_snapshot(struct path *path, int flags)
sep = avl_find(&zsb->z_ctldir_snaps, &search, NULL);
if (sep) {
avl_remove(&zsb->z_ctldir_snaps, sep);
sep = avl_find(&zsb->z_ctldir_snaps, &search, NULL);
if (sep) {
avl_remove(&zsb->z_ctldir_snaps, sep);
-
cancel_delayed_work_sync(&sep->se_work
);
+
taskq_cancel_id(zfs_expire_taskq, sep->se_taskqid
);
zfsctl_sep_free(sep);
}
zfsctl_sep_free(sep);
}
@@
-840,8
+853,9
@@
zfsctl_mount_snapshot(struct path *path, int flags)
sep->se_inode = ip;
avl_add(&zsb->z_ctldir_snaps, sep);
sep->se_inode = ip;
avl_add(&zsb->z_ctldir_snaps, sep);
- spl_init_delayed_work(&sep->se_work, zfsctl_expire_snapshot, sep);
- schedule_delayed_work(&sep->se_work, zfs_expire_snapshot * HZ);
+ sep->se_taskqid = taskq_dispatch_delay(zfs_expire_taskq,
+ zfsctl_expire_snapshot, sep, TQ_SLEEP,
+ ddi_get_lbolt() + zfs_expire_snapshot * HZ);
mutex_exit(&zsb->z_ctldir_lock);
error:
mutex_exit(&zsb->z_ctldir_lock);
error:
@@
-895,7
+909,7
@@
zfsctl_lookup_objset(struct super_block *sb, uint64_t objsetid, zfs_sb_t **zsbp)
*/
sep = avl_first(&zsb->z_ctldir_snaps);
while (sep != NULL) {
*/
sep = avl_first(&zsb->z_ctldir_snaps);
while (sep != NULL) {
- error = dmu_snapshot_
id
(zsb->z_os, sep->se_name, &id);
+ error = dmu_snapshot_
lookup
(zsb->z_os, sep->se_name, &id);
if (error)
goto out;
if (error)
goto out;
@@
-913,8
+927,8
@@
zfsctl_lookup_objset(struct super_block *sb, uint64_t objsetid, zfs_sb_t **zsbp)
* race cannot occur to an expired mount point because
* we hold the zsb->z_ctldir_lock to prevent the race.
*/
* race cannot occur to an expired mount point because
* we hold the zsb->z_ctldir_lock to prevent the race.
*/
- sbp = sget(&zpl_fs_type, zfsctl_test_super,
- zfsctl_set_super, &id);
+ sbp =
zpl_
sget(&zpl_fs_type, zfsctl_test_super,
+ zfsctl_set_super,
0,
&id);
if (IS_ERR(sbp)) {
error = -PTR_ERR(sbp);
} else {
if (IS_ERR(sbp)) {
error = -PTR_ERR(sbp);
} else {
@@
-945,7
+959,7
@@
zfsctl_shares_lookup(struct inode *dip, char *name, struct inode **ipp,
if (zsb->z_shares_dir == 0) {
ZFS_EXIT(zsb);
if (zsb->z_shares_dir == 0) {
ZFS_EXIT(zsb);
- return (
-
ENOTSUP);
+ return (ENOTSUP);
}
error = zfs_zget(zsb, zsb->z_shares_dir, &dzp);
}
error = zfs_zget(zsb, zsb->z_shares_dir, &dzp);
@@
-970,6
+984,8
@@
zfsctl_shares_lookup(struct inode *dip, char *name, struct inode **ipp,
void
zfsctl_init(void)
{
void
zfsctl_init(void)
{
+ zfs_expire_taskq = taskq_create("z_unmount", 1, maxclsyspri,
+ 1, 8, TASKQ_PREPOPULATE);
}
/*
}
/*
@@
-979,6
+995,7
@@
zfsctl_init(void)
void
zfsctl_fini(void)
{
void
zfsctl_fini(void)
{
+ taskq_destroy(zfs_expire_taskq);
}
module_param(zfs_expire_snapshot, int, 0644);
}
module_param(zfs_expire_snapshot, int, 0644);