summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/fssnap.h
blob: 28a250481c8916bf5cadacd67bea892469495c2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FSSNAP_H
#define	_SYS_FSSNAP_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <sys/sysmacros.h>
#include <sys/devops.h>

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/buf.h>
#include <sys/taskq.h>
#include <sys/fs/ufs_inode.h>

/* snapshot backend interfaces, macros, and data structures */

#if defined(_KERNEL)

/*
 * defines for the number of threads used to handle tasks, the maximum
 * number of chunks in memory at a time, and the maximum number of tasks to
 * allow before the taskqs start throttling. MAXTASKS should be greater than
 * or equal to MAX_MEM_CHUNKS.
 */
#define	FSSNAP_TASKQ_THREADS	(2)
#define	FSSNAP_MAX_MEM_CHUNKS	(32)
#define	FSSNAP_TASKQ_MAXTASKS	(FSSNAP_MAX_MEM_CHUNKS)

/*
 * It is assumed that a chunk is a multiple of a disk sector so that
 * the chunk size can be reduced before using it as a conversion
 * factor.  Therefore the number of chunks on a file system will
 * always be less than the number of blocks it occupies, and these
 * conversions will not overflow. (do not convert to bytes first!)
 */

typedef unsigned long long	chunknumber_t;

/* disk blocks to snapshot chunks */
#define	dbtocowchunk(cmap, dblkno) ((dblkno) / \
	((cmap)->cmap_chunksz >> DEV_BSHIFT))

/* snapshot chunks to disk blocks */
#define	cowchunktodb(cmap, cowchunk) ((cowchunk) * \
	((cmap)->cmap_chunksz >> DEV_BSHIFT))

/*
 * A snapshot_id is the shared structure between the snapshot driver
 * and the file system.
 */
typedef struct snapshot_id {
	struct snapshot_id	*sid_next;	/* next snapshot in list */
	krwlock_t		sid_rwlock;	/* protects enable/disable */
	struct cow_info		*sid_cowinfo;	/* pointer to cow state */
	uint_t			sid_snapnumber;	/* snapshot number */
	uint_t			sid_flags;	/* general flags */
	struct vnode		*sid_fvp;	/* root vnode to snapshot */
} snapshot_id_t;

/* snapshot_id flags */
#define	SID_DISABLED	(0x01)	/* this snapshot has been disabled */
#define	SID_DISABLING	(0x02)	/* this snapshot is being disabled */
#define	SID_BLOCK_BUSY	(0x04)	/* snapshot block driver is attached */
#define	SID_CHAR_BUSY	(0x08)	/* snapshot character driver is attached */
#define	SID_CREATING	(0x10)	/* snapshot is being created */
#define	SID_DELETE	(0x20)	/* error condition found, delete snapshot */

/* true if snapshot device is open */
#define	SID_BUSY(sidp)	(((sidp)->sid_flags & SID_BLOCK_BUSY) || \
	((sidp)->sid_flags & SID_CHAR_BUSY))

/* true if snapshot can not be used */
#define	SID_INACTIVE(sidp)	(((sidp)->sid_flags & SID_DISABLED) || \
	((sidp)->sid_flags & SID_DISABLING) || \
	((sidp)->sid_flags & SID_CREATING) || \
	((sidp)->sid_flags & SID_DELETE) || \
	((sidp)->sid_cowinfo == NULL))

/* true if snapshot can be reused now */
#define	SID_AVAILABLE(sidp)	(!SID_BUSY(sidp) && \
	((sidp)->sid_flags & SID_DISABLED))

/*
 * The cow_map keeps track of all translations, and two bitmaps to
 * determine whether the chunk is eligible for translation, and if so
 * whether or not it already has a translation.  The candidate bitmap
 * is read-only and does not require a lock, the hastrans bitmap and
 * the translation table are protected by the cmap_rwlock.
 */
typedef struct cow_map {
	krwlock_t	cmap_rwlock;	/* protects this structure */
	ksema_t		cmap_throttle_sem; /* used to throttle writes */
	uint32_t	cmap_waiters;	/* semaphore waiters */
	uint_t		cmap_chunksz;	/* granularity of COW operations */
	chunknumber_t	cmap_chunksperbf; /* chunks in max backing file */
	chunknumber_t	cmap_nchunks;	/* number of chunks in backing file */
	u_offset_t	cmap_maxsize;	/* max bytes allowed (0 is no limit) */
	size_t		cmap_bmsize;	/* size of bitmaps (in bytes) */
	caddr_t		cmap_candidate;	/* 1 = block is a candidate for COW */
	caddr_t		cmap_hastrans;	/* 1 = an entry exists in the table */
	struct cow_map_node	*cmap_table;	/* translation table */
} cow_map_t;

/*
 * The cow_map_node keeps track of chunks that are still in memory.
 */

typedef struct cow_map_node {
	struct cow_map_node	*cmn_next;
	struct cow_map_node	*cmn_prev;
	struct snapshot_id	*cmn_sid;	/* backpointer to snapshot */
	chunknumber_t		cmn_chunk;	/* original chunk number */
	caddr_t			cmn_buf;	/* the data itself */
	int			release_sem;	/* flag to release */
						/* cmap_throttle_sem */
} cow_map_node_t;

/*
 * The cow_info structure holds basic snapshot state information. It is
 * mostly read-only once the snapshot is created so no locking is required.
 * The exception is cow_nextchunk, which is ever-increasing and updated with
 * atomic_add(). This structure is allocated dynamically, and creation and
 * deletion of the snapshot is protected by the snapshot_mutex variable.
 */
typedef struct cow_info {
	int		cow_backcount;	/* number of backing files */
	vnode_t		**cow_backfile_array; /* array of backing files */
	u_offset_t	cow_backfile_sz;	/* max size of a backfile */
	taskq_t		*cow_taskq;	/* task queue for async writes */
	struct kstat	*cow_kstat_mntpt;	/* kstat for mount point */
	struct kstat	*cow_kstat_bfname;	/* kstat for backing file */
	struct kstat	*cow_kstat_num;	/* named numeric kstats */
	struct cow_map	cow_map;	/* block translation table */
} cow_info_t;

/* kstat information */
struct cow_kstat_num {
	kstat_named_t	ckn_state;	/* state of the snapshot device */
	kstat_named_t	ckn_bfsize;	/* sum of sizes of backing files */
	kstat_named_t	ckn_maxsize;	/* maximum backing file size */
	kstat_named_t	ckn_createtime;	/* snapshot creation time */
	kstat_named_t	ckn_chunksize;	/* chunk size */
};

/* ckn_state values */
#define	COWSTATE_CREATING	(0)	/* snapshot being created */
#define	COWSTATE_IDLE		(1)	/* snapshot exists, but not open */
#define	COWSTATE_ACTIVE		(2)	/* snapshot open */
#define	COWSTATE_DISABLED	(3)	/* snapshot deleted (pending close) */

extern	uint_t	bypass_snapshot_throttle_key;

#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif /* _SYS_FSSNAP_H */