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