xref: /illumos-gate/usr/src/uts/common/sys/fssnap.h (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #ifndef	_SYS_FSSNAP_H
28*7c478bd9Sstevel@tonic-gate #define	_SYS_FSSNAP_H
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/devops.h>
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
36*7c478bd9Sstevel@tonic-gate extern "C" {
37*7c478bd9Sstevel@tonic-gate #endif
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #include <sys/buf.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/taskq.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate /* snapshot backend interfaces, macros, and data structures */
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate /*
48*7c478bd9Sstevel@tonic-gate  * defines for the number of threads used to handle tasks, the maximum
49*7c478bd9Sstevel@tonic-gate  * number of chunks in memory at a time, and the maximum number of tasks to
50*7c478bd9Sstevel@tonic-gate  * allow before the taskqs start throttling. MAXTASKS should be greater than
51*7c478bd9Sstevel@tonic-gate  * or equal to MAX_MEM_CHUNKS.
52*7c478bd9Sstevel@tonic-gate  */
53*7c478bd9Sstevel@tonic-gate #define	FSSNAP_TASKQ_THREADS	(2)
54*7c478bd9Sstevel@tonic-gate #define	FSSNAP_MAX_MEM_CHUNKS	(32)
55*7c478bd9Sstevel@tonic-gate #define	FSSNAP_TASKQ_MAXTASKS	(FSSNAP_MAX_MEM_CHUNKS)
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate /*
58*7c478bd9Sstevel@tonic-gate  * It is assumed that a chunk is a multiple of a disk sector so that
59*7c478bd9Sstevel@tonic-gate  * the chunk size can be reduced before using it as a conversion
60*7c478bd9Sstevel@tonic-gate  * factor.  Therefore the number of chunks on a file system will
61*7c478bd9Sstevel@tonic-gate  * always be less than the number of blocks it occupies, and these
62*7c478bd9Sstevel@tonic-gate  * conversions will not overflow. (do not convert to bytes first!)
63*7c478bd9Sstevel@tonic-gate  */
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate typedef unsigned long long	chunknumber_t;
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /* disk blocks to snapshot chunks */
68*7c478bd9Sstevel@tonic-gate #define	dbtocowchunk(cmap, dblkno) ((dblkno) / \
69*7c478bd9Sstevel@tonic-gate 	((cmap)->cmap_chunksz >> DEV_BSHIFT))
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate /* snapshot chunks to disk blocks */
72*7c478bd9Sstevel@tonic-gate #define	cowchunktodb(cmap, cowchunk) ((cowchunk) * \
73*7c478bd9Sstevel@tonic-gate 	((cmap)->cmap_chunksz >> DEV_BSHIFT))
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate /*
76*7c478bd9Sstevel@tonic-gate  * A snapshot_id is the shared structure between the snapshot driver
77*7c478bd9Sstevel@tonic-gate  * and the file system.
78*7c478bd9Sstevel@tonic-gate  */
79*7c478bd9Sstevel@tonic-gate typedef struct snapshot_id {
80*7c478bd9Sstevel@tonic-gate 	struct snapshot_id	*sid_next;	/* next snapshot in list */
81*7c478bd9Sstevel@tonic-gate 	krwlock_t		sid_rwlock;	/* protects enable/disable */
82*7c478bd9Sstevel@tonic-gate 	struct cow_info		*sid_cowinfo;	/* pointer to cow state */
83*7c478bd9Sstevel@tonic-gate 	uint_t			sid_snapnumber;	/* snapshot number */
84*7c478bd9Sstevel@tonic-gate 	uint_t			sid_flags;	/* general flags */
85*7c478bd9Sstevel@tonic-gate 	struct vnode		*sid_fvp;	/* root vnode to snapshot */
86*7c478bd9Sstevel@tonic-gate } snapshot_id_t;
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate /* snapshot_id flags */
89*7c478bd9Sstevel@tonic-gate #define	SID_DISABLED	(0x01)	/* this snapshot has been disabled */
90*7c478bd9Sstevel@tonic-gate #define	SID_DISABLING	(0x02)	/* this snapshot is being disabled */
91*7c478bd9Sstevel@tonic-gate #define	SID_BLOCK_BUSY	(0x04)	/* snapshot block driver is attached */
92*7c478bd9Sstevel@tonic-gate #define	SID_CHAR_BUSY	(0x08)	/* snapshot character driver is attached */
93*7c478bd9Sstevel@tonic-gate #define	SID_CREATING	(0x10)	/* snapshot is being created */
94*7c478bd9Sstevel@tonic-gate #define	SID_DELETE	(0x20)	/* error condition found, delete snapshot */
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate /* true if snapshot device is open */
97*7c478bd9Sstevel@tonic-gate #define	SID_BUSY(sidp)	(((sidp)->sid_flags & SID_BLOCK_BUSY) || \
98*7c478bd9Sstevel@tonic-gate 	((sidp)->sid_flags & SID_CHAR_BUSY))
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate /* true if snapshot can not be used */
101*7c478bd9Sstevel@tonic-gate #define	SID_INACTIVE(sidp)	(((sidp)->sid_flags & SID_DISABLED) || \
102*7c478bd9Sstevel@tonic-gate 	((sidp)->sid_flags & SID_DISABLING) || \
103*7c478bd9Sstevel@tonic-gate 	((sidp)->sid_flags & SID_CREATING) || \
104*7c478bd9Sstevel@tonic-gate 	((sidp)->sid_flags & SID_DELETE) || \
105*7c478bd9Sstevel@tonic-gate 	((sidp)->sid_cowinfo == NULL))
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate /* true if snapshot can be reused now */
108*7c478bd9Sstevel@tonic-gate #define	SID_AVAILABLE(sidp)	(!SID_BUSY(sidp) && \
109*7c478bd9Sstevel@tonic-gate 	((sidp)->sid_flags & SID_DISABLED))
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate /*
112*7c478bd9Sstevel@tonic-gate  * The cow_map keeps track of all translations, and two bitmaps to
113*7c478bd9Sstevel@tonic-gate  * determine whether the chunk is eligible for translation, and if so
114*7c478bd9Sstevel@tonic-gate  * whether or not it already has a translation.  The candidate bitmap
115*7c478bd9Sstevel@tonic-gate  * is read-only and does not require a lock, the hastrans bitmap and
116*7c478bd9Sstevel@tonic-gate  * the translation table are protected by the cmap_rwlock.
117*7c478bd9Sstevel@tonic-gate  */
118*7c478bd9Sstevel@tonic-gate typedef struct cow_map {
119*7c478bd9Sstevel@tonic-gate 	krwlock_t	cmap_rwlock;	/* protects this structure */
120*7c478bd9Sstevel@tonic-gate 	ksema_t		cmap_throttle_sem; /* used to throttle writes */
121*7c478bd9Sstevel@tonic-gate 	uint32_t	cmap_waiters;	/* semaphore waiters */
122*7c478bd9Sstevel@tonic-gate 	uint_t		cmap_chunksz;	/* granularity of COW operations */
123*7c478bd9Sstevel@tonic-gate 	chunknumber_t	cmap_chunksperbf; /* chunks in max backing file */
124*7c478bd9Sstevel@tonic-gate 	chunknumber_t	cmap_nchunks;	/* number of chunks in backing file */
125*7c478bd9Sstevel@tonic-gate 	u_offset_t	cmap_maxsize;	/* max bytes allowed (0 is no limit) */
126*7c478bd9Sstevel@tonic-gate 	size_t		cmap_bmsize;	/* size of bitmaps (in bytes) */
127*7c478bd9Sstevel@tonic-gate 	caddr_t		cmap_candidate;	/* 1 = block is a candidate for COW */
128*7c478bd9Sstevel@tonic-gate 	caddr_t		cmap_hastrans;	/* 1 = an entry exists in the table */
129*7c478bd9Sstevel@tonic-gate 	struct cow_map_node	*cmap_table;	/* translation table */
130*7c478bd9Sstevel@tonic-gate } cow_map_t;
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate /*
133*7c478bd9Sstevel@tonic-gate  * The cow_map_node keeps track of chunks that are still in memory.
134*7c478bd9Sstevel@tonic-gate  */
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate typedef struct cow_map_node {
137*7c478bd9Sstevel@tonic-gate 	struct cow_map_node	*cmn_next;
138*7c478bd9Sstevel@tonic-gate 	struct cow_map_node	*cmn_prev;
139*7c478bd9Sstevel@tonic-gate 	struct snapshot_id	*cmn_sid;	/* backpointer to snapshot */
140*7c478bd9Sstevel@tonic-gate 	chunknumber_t		cmn_chunk;	/* original chunk number */
141*7c478bd9Sstevel@tonic-gate 	caddr_t			cmn_buf;	/* the data itself */
142*7c478bd9Sstevel@tonic-gate 	int			release_sem;	/* flag to release */
143*7c478bd9Sstevel@tonic-gate 						/* cmap_throttle_sem */
144*7c478bd9Sstevel@tonic-gate } cow_map_node_t;
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate /*
147*7c478bd9Sstevel@tonic-gate  * The cow_info structure holds basic snapshot state information. It is
148*7c478bd9Sstevel@tonic-gate  * mostly read-only once the snapshot is created so no locking is required.
149*7c478bd9Sstevel@tonic-gate  * The exception is cow_nextchunk, which is ever-increasing and updated with
150*7c478bd9Sstevel@tonic-gate  * atomic_add(). This structure is allocated dynamically, and creation and
151*7c478bd9Sstevel@tonic-gate  * deletion of the snapshot is protected by the snapshot_mutex variable.
152*7c478bd9Sstevel@tonic-gate  */
153*7c478bd9Sstevel@tonic-gate typedef struct cow_info {
154*7c478bd9Sstevel@tonic-gate 	int		cow_backcount;	/* number of backing files */
155*7c478bd9Sstevel@tonic-gate 	vnode_t		**cow_backfile_array; /* array of backing files */
156*7c478bd9Sstevel@tonic-gate 	u_offset_t	cow_backfile_sz;	/* max size of a backfile */
157*7c478bd9Sstevel@tonic-gate 	taskq_t		*cow_taskq;	/* task queue for async writes */
158*7c478bd9Sstevel@tonic-gate 	struct kstat	*cow_kstat_mntpt;	/* kstat for mount point */
159*7c478bd9Sstevel@tonic-gate 	struct kstat	*cow_kstat_bfname;	/* kstat for backing file */
160*7c478bd9Sstevel@tonic-gate 	struct kstat	*cow_kstat_num;	/* named numeric kstats */
161*7c478bd9Sstevel@tonic-gate 	struct cow_map	cow_map;	/* block translation table */
162*7c478bd9Sstevel@tonic-gate } cow_info_t;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate /* kstat information */
165*7c478bd9Sstevel@tonic-gate struct cow_kstat_num {
166*7c478bd9Sstevel@tonic-gate 	kstat_named_t	ckn_state;	/* state of the snapshot device */
167*7c478bd9Sstevel@tonic-gate 	kstat_named_t	ckn_bfsize;	/* sum of sizes of backing files */
168*7c478bd9Sstevel@tonic-gate 	kstat_named_t	ckn_maxsize;	/* maximum backing file size */
169*7c478bd9Sstevel@tonic-gate 	kstat_named_t	ckn_createtime;	/* snapshot creation time */
170*7c478bd9Sstevel@tonic-gate 	kstat_named_t	ckn_chunksize;	/* chunk size */
171*7c478bd9Sstevel@tonic-gate };
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate /* ckn_state values */
174*7c478bd9Sstevel@tonic-gate #define	COWSTATE_CREATING	(0)	/* snapshot being created */
175*7c478bd9Sstevel@tonic-gate #define	COWSTATE_IDLE		(1)	/* snapshot exists, but not open */
176*7c478bd9Sstevel@tonic-gate #define	COWSTATE_ACTIVE		(2)	/* snapshot open */
177*7c478bd9Sstevel@tonic-gate #define	COWSTATE_DISABLED	(3)	/* snapshot deleted (pending close) */
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate extern	uint_t	bypass_snapshot_throttle_key;
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate #endif
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate #endif /* _SYS_FSSNAP_H */
188