789
|
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 2005 Sun Microsystems, Inc. All rights reserved.
|
|
24 |
* Use is subject to license terms.
|
|
25 |
*/
|
|
26 |
|
|
27 |
#pragma ident "%Z%%M% %I% %E% SMI"
|
|
28 |
|
|
29 |
#include <sys/types.h>
|
|
30 |
#include <sys/param.h>
|
|
31 |
#include <sys/systm.h>
|
|
32 |
#include <sys/sysmacros.h>
|
|
33 |
#include <sys/cmn_err.h>
|
|
34 |
#include <sys/kmem.h>
|
|
35 |
#include <sys/thread.h>
|
|
36 |
#include <sys/file.h>
|
|
37 |
#include <sys/vfs.h>
|
|
38 |
#include <sys/zfs_znode.h>
|
|
39 |
#include <sys/zfs_dir.h>
|
|
40 |
#include <sys/zil.h>
|
|
41 |
#include <sys/byteorder.h>
|
|
42 |
#include <sys/policy.h>
|
|
43 |
#include <sys/stat.h>
|
|
44 |
#include <sys/mode.h>
|
|
45 |
#include <sys/acl.h>
|
|
46 |
#include <sys/dmu.h>
|
|
47 |
#include <sys/spa.h>
|
|
48 |
#include <sys/ddi.h>
|
|
49 |
|
|
50 |
/*
|
|
51 |
* All the functions in this file are used to construct the log entries
|
|
52 |
* to record transactions. They allocate * a intent log transaction
|
|
53 |
* structure (itx_t) and save within it all the information necessary to
|
|
54 |
* possibly replay the transaction. The itx is then assigned a sequence
|
|
55 |
* number and inserted in the in-memory list anchored in the zilog.
|
|
56 |
*/
|
|
57 |
|
|
58 |
/*
|
|
59 |
* zfs_log_create() is used to handle TX_CREATE, TX_MKDIR and TX_MKXATTR
|
|
60 |
* transactions.
|
|
61 |
*/
|
|
62 |
uint64_t
|
|
63 |
zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
|
64 |
znode_t *dzp, znode_t *zp, char *name)
|
|
65 |
{
|
|
66 |
itx_t *itx;
|
|
67 |
uint64_t seq;
|
|
68 |
lr_create_t *lr;
|
|
69 |
size_t namesize = strlen(name) + 1;
|
|
70 |
|
|
71 |
if (zilog == NULL)
|
|
72 |
return (0);
|
|
73 |
|
|
74 |
itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
|
|
75 |
lr = (lr_create_t *)&itx->itx_lr;
|
|
76 |
lr->lr_doid = dzp->z_id;
|
|
77 |
lr->lr_foid = zp->z_id;
|
|
78 |
lr->lr_mode = zp->z_phys->zp_mode;
|
|
79 |
lr->lr_uid = zp->z_phys->zp_uid;
|
|
80 |
lr->lr_gid = zp->z_phys->zp_gid;
|
|
81 |
lr->lr_gen = zp->z_phys->zp_gen;
|
|
82 |
lr->lr_crtime[0] = zp->z_phys->zp_crtime[0];
|
|
83 |
lr->lr_crtime[1] = zp->z_phys->zp_crtime[1];
|
|
84 |
lr->lr_rdev = zp->z_phys->zp_rdev;
|
|
85 |
bcopy(name, (char *)(lr + 1), namesize);
|
|
86 |
|
|
87 |
seq = zil_itx_assign(zilog, itx, tx);
|
|
88 |
dzp->z_last_itx = seq;
|
|
89 |
zp->z_last_itx = seq;
|
|
90 |
return (seq);
|
|
91 |
}
|
|
92 |
|
|
93 |
/*
|
|
94 |
* zfs_log_remove() handles both TX_REMOVE and TX_RMDIR transactions.
|
|
95 |
*/
|
|
96 |
uint64_t
|
|
97 |
zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
|
98 |
znode_t *dzp, char *name)
|
|
99 |
{
|
|
100 |
itx_t *itx;
|
|
101 |
uint64_t seq;
|
|
102 |
lr_remove_t *lr;
|
|
103 |
size_t namesize = strlen(name) + 1;
|
|
104 |
|
|
105 |
if (zilog == NULL)
|
|
106 |
return (0);
|
|
107 |
|
|
108 |
itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
|
|
109 |
lr = (lr_remove_t *)&itx->itx_lr;
|
|
110 |
lr->lr_doid = dzp->z_id;
|
|
111 |
bcopy(name, (char *)(lr + 1), namesize);
|
|
112 |
|
|
113 |
seq = zil_itx_assign(zilog, itx, tx);
|
|
114 |
dzp->z_last_itx = seq;
|
|
115 |
return (seq);
|
|
116 |
}
|
|
117 |
|
|
118 |
/*
|
|
119 |
* zfs_log_link() handles TX_LINK transactions.
|
|
120 |
*/
|
|
121 |
uint64_t
|
|
122 |
zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
|
123 |
znode_t *dzp, znode_t *zp, char *name)
|
|
124 |
{
|
|
125 |
itx_t *itx;
|
|
126 |
uint64_t seq;
|
|
127 |
lr_link_t *lr;
|
|
128 |
size_t namesize = strlen(name) + 1;
|
|
129 |
|
|
130 |
if (zilog == NULL)
|
|
131 |
return (0);
|
|
132 |
|
|
133 |
itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
|
|
134 |
lr = (lr_link_t *)&itx->itx_lr;
|
|
135 |
lr->lr_doid = dzp->z_id;
|
|
136 |
lr->lr_link_obj = zp->z_id;
|
|
137 |
bcopy(name, (char *)(lr + 1), namesize);
|
|
138 |
|
|
139 |
seq = zil_itx_assign(zilog, itx, tx);
|
|
140 |
dzp->z_last_itx = seq;
|
|
141 |
zp->z_last_itx = seq;
|
|
142 |
return (seq);
|
|
143 |
}
|
|
144 |
|
|
145 |
/*
|
|
146 |
* zfs_log_symlink() handles TX_SYMLINK transactions.
|
|
147 |
*/
|
|
148 |
uint64_t
|
|
149 |
zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
|
150 |
znode_t *dzp, znode_t *zp, char *name, char *link)
|
|
151 |
{
|
|
152 |
itx_t *itx;
|
|
153 |
uint64_t seq;
|
|
154 |
lr_create_t *lr;
|
|
155 |
size_t namesize = strlen(name) + 1;
|
|
156 |
size_t linksize = strlen(link) + 1;
|
|
157 |
|
|
158 |
if (zilog == NULL)
|
|
159 |
return (0);
|
|
160 |
|
|
161 |
itx = zil_itx_create(txtype, sizeof (*lr) + namesize + linksize);
|
|
162 |
lr = (lr_create_t *)&itx->itx_lr;
|
|
163 |
lr->lr_doid = dzp->z_id;
|
|
164 |
lr->lr_foid = zp->z_id;
|
|
165 |
lr->lr_mode = zp->z_phys->zp_mode;
|
|
166 |
lr->lr_uid = zp->z_phys->zp_uid;
|
|
167 |
lr->lr_gid = zp->z_phys->zp_gid;
|
|
168 |
lr->lr_gen = zp->z_phys->zp_gen;
|
|
169 |
lr->lr_crtime[0] = zp->z_phys->zp_crtime[0];
|
|
170 |
lr->lr_crtime[1] = zp->z_phys->zp_crtime[1];
|
|
171 |
bcopy(name, (char *)(lr + 1), namesize);
|
|
172 |
bcopy(link, (char *)(lr + 1) + namesize, linksize);
|
|
173 |
|
|
174 |
seq = zil_itx_assign(zilog, itx, tx);
|
|
175 |
dzp->z_last_itx = seq;
|
|
176 |
zp->z_last_itx = seq;
|
|
177 |
return (seq);
|
|
178 |
}
|
|
179 |
|
|
180 |
/*
|
|
181 |
* zfs_log_rename() handles TX_RENAME transactions.
|
|
182 |
*/
|
|
183 |
uint64_t
|
|
184 |
zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
|
185 |
znode_t *sdzp, char *sname, znode_t *tdzp, char *dname, znode_t *szp)
|
|
186 |
{
|
|
187 |
itx_t *itx;
|
|
188 |
uint64_t seq;
|
|
189 |
lr_rename_t *lr;
|
|
190 |
size_t snamesize = strlen(sname) + 1;
|
|
191 |
size_t dnamesize = strlen(dname) + 1;
|
|
192 |
|
|
193 |
if (zilog == NULL)
|
|
194 |
return (0);
|
|
195 |
|
|
196 |
itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize);
|
|
197 |
lr = (lr_rename_t *)&itx->itx_lr;
|
|
198 |
lr->lr_sdoid = sdzp->z_id;
|
|
199 |
lr->lr_tdoid = tdzp->z_id;
|
|
200 |
bcopy(sname, (char *)(lr + 1), snamesize);
|
|
201 |
bcopy(dname, (char *)(lr + 1) + snamesize, dnamesize);
|
|
202 |
|
|
203 |
seq = zil_itx_assign(zilog, itx, tx);
|
|
204 |
sdzp->z_last_itx = seq;
|
|
205 |
tdzp->z_last_itx = seq;
|
|
206 |
szp->z_last_itx = seq;
|
|
207 |
return (seq);
|
|
208 |
}
|
|
209 |
|
|
210 |
/*
|
|
211 |
* zfs_log_write() handles TX_WRITE transactions.
|
|
212 |
*
|
|
213 |
* We store data in the log buffers if it small enough.
|
|
214 |
* Otherwise we flush the data out via dmu_sync().
|
|
215 |
*/
|
|
216 |
ssize_t zfs_immediate_write_sz = 65536;
|
|
217 |
|
|
218 |
uint64_t
|
|
219 |
zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
|
220 |
znode_t *zp, offset_t off, ssize_t len, int ioflag, uio_t *uio)
|
|
221 |
{
|
|
222 |
itx_t *itx;
|
|
223 |
uint64_t seq;
|
|
224 |
lr_write_t *lr;
|
|
225 |
int dlen, err;
|
|
226 |
|
|
227 |
if (zilog == NULL || zp->z_reap)
|
|
228 |
return (0);
|
|
229 |
|
|
230 |
dlen = (len <= zfs_immediate_write_sz ? len : 0);
|
|
231 |
itx = zil_itx_create(txtype, sizeof (*lr) + dlen);
|
|
232 |
itx->itx_data_copied = 0;
|
|
233 |
if ((ioflag & FDSYNC) && (dlen != 0)) {
|
|
234 |
err = xcopyin(uio->uio_iov->iov_base - len,
|
|
235 |
(char *)itx + offsetof(itx_t, itx_lr) + sizeof (*lr),
|
|
236 |
len);
|
|
237 |
/*
|
|
238 |
* copyin shouldn't fault as we've already successfully
|
|
239 |
* copied it to a dmu buffer. However if it does we'll get
|
|
240 |
* the data from the dmu later.
|
|
241 |
*/
|
|
242 |
if (!err)
|
|
243 |
itx->itx_data_copied = 1;
|
|
244 |
}
|
|
245 |
lr = (lr_write_t *)&itx->itx_lr;
|
|
246 |
lr->lr_foid = zp->z_id;
|
|
247 |
lr->lr_offset = off;
|
|
248 |
lr->lr_length = len;
|
|
249 |
lr->lr_blkoff = 0;
|
|
250 |
BP_ZERO(&lr->lr_blkptr);
|
|
251 |
|
|
252 |
itx->itx_private = zp->z_zfsvfs;
|
|
253 |
|
|
254 |
seq = zil_itx_assign(zilog, itx, tx);
|
|
255 |
zp->z_last_itx = seq;
|
|
256 |
return (seq);
|
|
257 |
}
|
|
258 |
|
|
259 |
/*
|
|
260 |
* zfs_log_truncate() handles TX_TRUNCATE transactions.
|
|
261 |
*/
|
|
262 |
uint64_t
|
|
263 |
zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
|
264 |
znode_t *zp, uint64_t off, uint64_t len)
|
|
265 |
{
|
|
266 |
itx_t *itx;
|
|
267 |
uint64_t seq;
|
|
268 |
lr_truncate_t *lr;
|
|
269 |
|
|
270 |
if (zilog == NULL || zp->z_reap)
|
|
271 |
return (0);
|
|
272 |
|
|
273 |
itx = zil_itx_create(txtype, sizeof (*lr));
|
|
274 |
lr = (lr_truncate_t *)&itx->itx_lr;
|
|
275 |
lr->lr_foid = zp->z_id;
|
|
276 |
lr->lr_offset = off;
|
|
277 |
lr->lr_length = len;
|
|
278 |
|
|
279 |
seq = zil_itx_assign(zilog, itx, tx);
|
|
280 |
zp->z_last_itx = seq;
|
|
281 |
return (seq);
|
|
282 |
}
|
|
283 |
|
|
284 |
/*
|
|
285 |
* zfs_log_setattr() handles TX_SETATTR transactions.
|
|
286 |
*/
|
|
287 |
uint64_t
|
|
288 |
zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
|
289 |
znode_t *zp, vattr_t *vap, uint_t mask_applied)
|
|
290 |
{
|
|
291 |
itx_t *itx;
|
|
292 |
uint64_t seq;
|
|
293 |
lr_setattr_t *lr;
|
|
294 |
|
|
295 |
if (zilog == NULL || zp->z_reap)
|
|
296 |
return (0);
|
|
297 |
|
|
298 |
itx = zil_itx_create(txtype, sizeof (*lr));
|
|
299 |
lr = (lr_setattr_t *)&itx->itx_lr;
|
|
300 |
lr->lr_foid = zp->z_id;
|
|
301 |
lr->lr_mask = (uint64_t)mask_applied;
|
|
302 |
lr->lr_mode = (uint64_t)vap->va_mode;
|
|
303 |
lr->lr_uid = (uint64_t)vap->va_uid;
|
|
304 |
lr->lr_gid = (uint64_t)vap->va_gid;
|
|
305 |
lr->lr_size = (uint64_t)vap->va_size;
|
|
306 |
ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime);
|
|
307 |
ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime);
|
|
308 |
|
|
309 |
seq = zil_itx_assign(zilog, itx, tx);
|
|
310 |
zp->z_last_itx = seq;
|
|
311 |
return (seq);
|
|
312 |
}
|
|
313 |
|
|
314 |
/*
|
|
315 |
* zfs_log_acl() handles TX_ACL transactions.
|
|
316 |
*/
|
|
317 |
uint64_t
|
|
318 |
zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
|
319 |
znode_t *zp, int aclcnt, ace_t *z_ace)
|
|
320 |
{
|
|
321 |
itx_t *itx;
|
|
322 |
uint64_t seq;
|
|
323 |
lr_acl_t *lr;
|
|
324 |
|
|
325 |
if (zilog == NULL || zp->z_reap)
|
|
326 |
return (0);
|
|
327 |
|
|
328 |
itx = zil_itx_create(txtype, sizeof (*lr) + aclcnt * sizeof (ace_t));
|
|
329 |
lr = (lr_acl_t *)&itx->itx_lr;
|
|
330 |
lr->lr_foid = zp->z_id;
|
|
331 |
lr->lr_aclcnt = (uint64_t)aclcnt;
|
|
332 |
bcopy(z_ace, (ace_t *)(lr + 1), aclcnt * sizeof (ace_t));
|
|
333 |
|
|
334 |
seq = zil_itx_assign(zilog, itx, tx);
|
|
335 |
zp->z_last_itx = seq;
|
|
336 |
return (seq);
|
|
337 |
}
|