]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / cddl / contrib / opensolaris / uts / common / fs / zfs / zfs_log.c
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25
26 #pragma ident   "%Z%%M% %I%     %E% SMI"
27
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/sysmacros.h>
32 #include <sys/cmn_err.h>
33 #include <sys/kmem.h>
34 #include <sys/file.h>
35 #include <sys/vfs.h>
36 #include <sys/zfs_znode.h>
37 #include <sys/zfs_dir.h>
38 #include <sys/zil.h>
39 #include <sys/byteorder.h>
40 #include <sys/policy.h>
41 #include <sys/stat.h>
42 #include <sys/acl.h>
43 #include <sys/dmu.h>
44 #include <sys/spa.h>
45
46 /*
47  * All the functions in this file are used to construct the log entries
48  * to record transactions. They allocate * a intent log transaction
49  * structure (itx_t) and save within it all the information necessary to
50  * possibly replay the transaction. The itx is then assigned a sequence
51  * number and inserted in the in-memory list anchored in the zilog.
52  */
53
54 /*
55  * zfs_log_create() is used to handle TX_CREATE, TX_MKDIR and TX_MKXATTR
56  * transactions.
57  */
58 void
59 zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, int txtype,
60         znode_t *dzp, znode_t *zp, char *name)
61 {
62         itx_t *itx;
63         uint64_t seq;
64         lr_create_t *lr;
65         size_t namesize = strlen(name) + 1;
66
67         if (zilog == NULL)
68                 return;
69
70         itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
71         lr = (lr_create_t *)&itx->itx_lr;
72         lr->lr_doid = dzp->z_id;
73         lr->lr_foid = zp->z_id;
74         lr->lr_mode = zp->z_phys->zp_mode;
75         lr->lr_uid = zp->z_phys->zp_uid;
76         lr->lr_gid = zp->z_phys->zp_gid;
77         lr->lr_gen = zp->z_phys->zp_gen;
78         lr->lr_crtime[0] = zp->z_phys->zp_crtime[0];
79         lr->lr_crtime[1] = zp->z_phys->zp_crtime[1];
80         lr->lr_rdev = zp->z_phys->zp_rdev;
81         bcopy(name, (char *)(lr + 1), namesize);
82
83         seq = zil_itx_assign(zilog, itx, tx);
84         dzp->z_last_itx = seq;
85         zp->z_last_itx = seq;
86 }
87
88 /*
89  * zfs_log_remove() handles both TX_REMOVE and TX_RMDIR transactions.
90  */
91 void
92 zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, int txtype,
93         znode_t *dzp, char *name)
94 {
95         itx_t *itx;
96         uint64_t seq;
97         lr_remove_t *lr;
98         size_t namesize = strlen(name) + 1;
99
100         if (zilog == NULL)
101                 return;
102
103         itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
104         lr = (lr_remove_t *)&itx->itx_lr;
105         lr->lr_doid = dzp->z_id;
106         bcopy(name, (char *)(lr + 1), namesize);
107
108         seq = zil_itx_assign(zilog, itx, tx);
109         dzp->z_last_itx = seq;
110 }
111
112 /*
113  * zfs_log_link() handles TX_LINK transactions.
114  */
115 void
116 zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, int txtype,
117         znode_t *dzp, znode_t *zp, char *name)
118 {
119         itx_t *itx;
120         uint64_t seq;
121         lr_link_t *lr;
122         size_t namesize = strlen(name) + 1;
123
124         if (zilog == NULL)
125                 return;
126
127         itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
128         lr = (lr_link_t *)&itx->itx_lr;
129         lr->lr_doid = dzp->z_id;
130         lr->lr_link_obj = zp->z_id;
131         bcopy(name, (char *)(lr + 1), namesize);
132
133         seq = zil_itx_assign(zilog, itx, tx);
134         dzp->z_last_itx = seq;
135         zp->z_last_itx = seq;
136 }
137
138 /*
139  * zfs_log_symlink() handles TX_SYMLINK transactions.
140  */
141 void
142 zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, int txtype,
143         znode_t *dzp, znode_t *zp, char *name, char *link)
144 {
145         itx_t *itx;
146         uint64_t seq;
147         lr_create_t *lr;
148         size_t namesize = strlen(name) + 1;
149         size_t linksize = strlen(link) + 1;
150
151         if (zilog == NULL)
152                 return;
153
154         itx = zil_itx_create(txtype, sizeof (*lr) + namesize + linksize);
155         lr = (lr_create_t *)&itx->itx_lr;
156         lr->lr_doid = dzp->z_id;
157         lr->lr_foid = zp->z_id;
158         lr->lr_mode = zp->z_phys->zp_mode;
159         lr->lr_uid = zp->z_phys->zp_uid;
160         lr->lr_gid = zp->z_phys->zp_gid;
161         lr->lr_gen = zp->z_phys->zp_gen;
162         lr->lr_crtime[0] = zp->z_phys->zp_crtime[0];
163         lr->lr_crtime[1] = zp->z_phys->zp_crtime[1];
164         bcopy(name, (char *)(lr + 1), namesize);
165         bcopy(link, (char *)(lr + 1) + namesize, linksize);
166
167         seq = zil_itx_assign(zilog, itx, tx);
168         dzp->z_last_itx = seq;
169         zp->z_last_itx = seq;
170 }
171
172 /*
173  * zfs_log_rename() handles TX_RENAME transactions.
174  */
175 void
176 zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, int txtype,
177         znode_t *sdzp, char *sname, znode_t *tdzp, char *dname, znode_t *szp)
178 {
179         itx_t *itx;
180         uint64_t seq;
181         lr_rename_t *lr;
182         size_t snamesize = strlen(sname) + 1;
183         size_t dnamesize = strlen(dname) + 1;
184
185         if (zilog == NULL)
186                 return;
187
188         itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize);
189         lr = (lr_rename_t *)&itx->itx_lr;
190         lr->lr_sdoid = sdzp->z_id;
191         lr->lr_tdoid = tdzp->z_id;
192         bcopy(sname, (char *)(lr + 1), snamesize);
193         bcopy(dname, (char *)(lr + 1) + snamesize, dnamesize);
194
195         seq = zil_itx_assign(zilog, itx, tx);
196         sdzp->z_last_itx = seq;
197         tdzp->z_last_itx = seq;
198         szp->z_last_itx = seq;
199 }
200
201 /*
202  * zfs_log_write() handles TX_WRITE transactions.
203  */
204 ssize_t zfs_immediate_write_sz = 32768;
205
206 void
207 zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
208         znode_t *zp, offset_t off, ssize_t len, int ioflag)
209 {
210         itx_t *itx;
211         uint64_t seq;
212         lr_write_t *lr;
213         itx_wr_state_t write_state;
214         int err;
215
216         if (zilog == NULL || zp->z_unlinked)
217                 return;
218
219         /*
220          * Writes are handled in three different ways:
221          *
222          * WR_INDIRECT:
223          *    If the write is greater than zfs_immediate_write_sz then
224          *    later *if* we need to log the write then dmu_sync() is used
225          *    to immediately write the block and it's block pointer is put
226          *    in the log record.
227          * WR_COPIED:
228          *    If we know we'll immediately be committing the
229          *    transaction (FDSYNC (O_DSYNC)), the we allocate a larger
230          *    log record here for the data and copy the data in.
231          * WR_NEED_COPY:
232          *    Otherwise we don't allocate a buffer, and *if* we need to
233          *    flush the write later then a buffer is allocated and
234          *    we retrieve the data using the dmu.
235          */
236         if (len > zfs_immediate_write_sz)
237                 write_state = WR_INDIRECT;
238         else if (ioflag & FDSYNC)
239                 write_state = WR_COPIED;
240         else
241                 write_state = WR_NEED_COPY;
242
243         itx = zil_itx_create(txtype, sizeof (*lr) +
244             (write_state == WR_COPIED ? len : 0));
245         lr = (lr_write_t *)&itx->itx_lr;
246         if (write_state == WR_COPIED) {
247                 err = dmu_read(zp->z_zfsvfs->z_os, zp->z_id, off, len, lr + 1);
248                 if (err) {
249                         kmem_free(itx, offsetof(itx_t, itx_lr) +
250                             itx->itx_lr.lrc_reclen);
251                         itx = zil_itx_create(txtype, sizeof (*lr));
252                         lr = (lr_write_t *)&itx->itx_lr;
253                         write_state = WR_NEED_COPY;
254                 }
255         }
256
257         itx->itx_wr_state = write_state;
258         lr->lr_foid = zp->z_id;
259         lr->lr_offset = off;
260         lr->lr_length = len;
261         lr->lr_blkoff = 0;
262         BP_ZERO(&lr->lr_blkptr);
263
264         itx->itx_private = zp->z_zfsvfs;
265
266         itx->itx_sync = (zp->z_sync_cnt != 0);
267         seq = zil_itx_assign(zilog, itx, tx);
268         zp->z_last_itx = seq;
269 }
270
271 /*
272  * zfs_log_truncate() handles TX_TRUNCATE transactions.
273  */
274 void
275 zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype,
276         znode_t *zp, uint64_t off, uint64_t len)
277 {
278         itx_t *itx;
279         uint64_t seq;
280         lr_truncate_t *lr;
281
282         if (zilog == NULL || zp->z_unlinked)
283                 return;
284
285         itx = zil_itx_create(txtype, sizeof (*lr));
286         lr = (lr_truncate_t *)&itx->itx_lr;
287         lr->lr_foid = zp->z_id;
288         lr->lr_offset = off;
289         lr->lr_length = len;
290
291         itx->itx_sync = (zp->z_sync_cnt != 0);
292         seq = zil_itx_assign(zilog, itx, tx);
293         zp->z_last_itx = seq;
294 }
295
296 /*
297  * zfs_log_setattr() handles TX_SETATTR transactions.
298  */
299 void
300 zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
301         znode_t *zp, vattr_t *vap, uint_t mask_applied)
302 {
303         itx_t *itx;
304         uint64_t seq;
305         lr_setattr_t *lr;
306
307         if (zilog == NULL || zp->z_unlinked)
308                 return;
309
310         itx = zil_itx_create(txtype, sizeof (*lr));
311         lr = (lr_setattr_t *)&itx->itx_lr;
312         lr->lr_foid = zp->z_id;
313         lr->lr_mask = (uint64_t)mask_applied;
314         lr->lr_mode = (uint64_t)vap->va_mode;
315         lr->lr_uid = (uint64_t)vap->va_uid;
316         lr->lr_gid = (uint64_t)vap->va_gid;
317         lr->lr_size = (uint64_t)vap->va_size;
318         ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime);
319         ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime);
320
321         itx->itx_sync = (zp->z_sync_cnt != 0);
322         seq = zil_itx_assign(zilog, itx, tx);
323         zp->z_last_itx = seq;
324 }
325
326 /*
327  * zfs_log_acl() handles TX_ACL transactions.
328  */
329 void
330 zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, int txtype,
331         znode_t *zp, int aclcnt, ace_t *z_ace)
332 {
333         itx_t *itx;
334         uint64_t seq;
335         lr_acl_t *lr;
336
337         if (zilog == NULL || zp->z_unlinked)
338                 return;
339
340         itx = zil_itx_create(txtype, sizeof (*lr) + aclcnt * sizeof (ace_t));
341         lr = (lr_acl_t *)&itx->itx_lr;
342         lr->lr_foid = zp->z_id;
343         lr->lr_aclcnt = (uint64_t)aclcnt;
344         bcopy(z_ace, (ace_t *)(lr + 1), aclcnt * sizeof (ace_t));
345
346         itx->itx_sync = (zp->z_sync_cnt != 0);
347         seq = zil_itx_assign(zilog, itx, tx);
348         zp->z_last_itx = seq;
349 }