]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/rdwr.c
Merge whitespace changes over
[thirdparty/xfsprogs-dev.git] / libxfs / rdwr.c
1 /*
2 * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <libxfs.h>
34 #include <xfs_log.h>
35 #include <xfs_log_priv.h>
36
37 #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
38 #define BDSTRAT_SIZE (256 * 1024)
39
40 void
41 libxfs_device_zero(dev_t dev, xfs_daddr_t start, uint len)
42 {
43 xfs_daddr_t bno;
44 uint nblks;
45 int size;
46 int fd;
47 char *z;
48
49 size = BDSTRAT_SIZE <= BBTOB(len) ? BDSTRAT_SIZE : BBTOB(len);
50 if ((z = memalign(getpagesize(), size)) == NULL) {
51 fprintf(stderr,
52 _("%s: %s can't memalign %d bytes: %s\n"),
53 progname, __FUNCTION__, size, strerror(errno));
54 exit(1);
55 }
56 memset(z, 0, size);
57 fd = libxfs_device_to_fd(dev);
58 for (bno = start; bno < start + len; ) {
59 nblks = (uint)BTOBB(size);
60 if (bno + nblks > start + len)
61 nblks = (uint)(start + len - bno);
62 if (pwrite64(fd, z, BBTOB(nblks), BBTOOFF64(bno)) <
63 BBTOB(nblks)) {
64 fprintf(stderr,
65 _("%s: %s write failed: %s\n"),
66 progname, __FUNCTION__, strerror(errno));
67 exit(1);
68 }
69 bno += nblks;
70 }
71 free(z);
72 }
73
74 int
75 libxfs_log_clear(
76 dev_t device,
77 xfs_daddr_t start,
78 uint length,
79 uuid_t *fs_uuid,
80 int version,
81 int sunit,
82 int fmt)
83 {
84 xfs_buf_t *buf;
85 xlog_rec_header_t *head;
86 xlog_op_header_t *op;
87 int i, len;
88 /* the data section must be 32 bit size aligned */
89 struct {
90 __uint16_t magic;
91 __uint16_t pad1;
92 __uint32_t pad2; /* may as well make it 64 bits */
93 } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
94
95 if (!device || !fs_uuid)
96 return -EINVAL;
97
98 /* first zero the log */
99 libxfs_device_zero(device, start, length);
100
101 /* then write a log record header */
102 if ((version == 2) && sunit)
103 len = BTOBB(sunit);
104 else
105 len = 1;
106 buf = libxfs_getbuf(device, start, len);
107 if (!buf)
108 return -1;
109
110 memset(XFS_BUF_PTR(buf), 0, BBSIZE * len);
111 head = (xlog_rec_header_t *)XFS_BUF_PTR(buf);
112
113 /* note that oh_tid actually contains the cycle number
114 * and the tid is stored in h_cycle_data[0] - that's the
115 * way things end up on disk.
116 */
117
118 INT_SET(head->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
119 INT_SET(head->h_cycle, ARCH_CONVERT, 1);
120 INT_SET(head->h_version, ARCH_CONVERT, version);
121 if (len != 1)
122 INT_SET(head->h_len, ARCH_CONVERT, sunit - BBSIZE);
123 else
124 INT_SET(head->h_len, ARCH_CONVERT, 20);
125 INT_SET(head->h_chksum, ARCH_CONVERT, 0);
126 INT_SET(head->h_prev_block, ARCH_CONVERT, -1);
127 INT_SET(head->h_num_logops, ARCH_CONVERT, 1);
128 INT_SET(head->h_cycle_data[0], ARCH_CONVERT, 0xb0c0d0d0);
129 INT_SET(head->h_fmt, ARCH_CONVERT, fmt);
130 INT_SET(head->h_size, ARCH_CONVERT, XLOG_HEADER_CYCLE_SIZE);
131
132 ASSIGN_ANY_LSN(head->h_lsn, 1, 0, ARCH_CONVERT);
133 ASSIGN_ANY_LSN(head->h_tail_lsn, 1, 0, ARCH_CONVERT);
134
135 memcpy(head->h_fs_uuid, fs_uuid, sizeof(uuid_t));
136
137 if (len > 1) {
138 xfs_caddr_t dp;
139 uint cycle_lsn;
140
141 cycle_lsn = CYCLE_LSN_NOCONV(head->h_lsn, ARCH_CONVERT);
142 dp = XFS_BUF_PTR(buf) + BBSIZE;
143 for (i = 1; i < len; i++) {
144 *(uint *)dp = cycle_lsn;
145 dp += BBSIZE;
146 }
147 }
148
149 if (libxfs_writebuf(buf, 0))
150 return -1;
151
152 buf = libxfs_getbuf(device, start + 1, 1);
153 if (!buf)
154 return -1;
155
156 /* now a log unmount op */
157 memset(XFS_BUF_PTR(buf), 0, BBSIZE);
158 op = (xlog_op_header_t *)XFS_BUF_PTR(buf);
159 INT_SET(op->oh_tid, ARCH_CONVERT, 1);
160 INT_SET(op->oh_len, ARCH_CONVERT, sizeof(magic));
161 INT_SET(op->oh_clientid, ARCH_CONVERT, XFS_LOG);
162 INT_SET(op->oh_flags, ARCH_CONVERT, XLOG_UNMOUNT_TRANS);
163 INT_SET(op->oh_res2, ARCH_CONVERT, 0);
164
165 /* and the data for this op */
166
167 memcpy(XFS_BUF_PTR(buf) + sizeof(xlog_op_header_t),
168 &magic,
169 sizeof(magic));
170
171 if (libxfs_writebuf(buf, 0))
172 return -1;
173
174 return 0;
175 }
176
177 /*
178 * Simple I/O interface
179 */
180
181 xfs_buf_t *
182 libxfs_getbuf(dev_t device, xfs_daddr_t blkno, int len)
183 {
184 xfs_buf_t *buf;
185 size_t total;
186
187 total = sizeof(xfs_buf_t) + BBTOB(len);
188 if ((buf = calloc(total, 1)) == NULL) {
189 fprintf(stderr, _("%s: buf calloc failed (%ld bytes): %s\n"),
190 progname, (long)total, strerror(errno));
191 exit(1);
192 }
193 /* by default, we allocate buffer directly after the header */
194 buf->b_blkno = blkno;
195 buf->b_bcount = BBTOB(len);
196 buf->b_dev = device;
197 buf->b_addr = (char *)(&buf->b_addr + 1); /* must be last field */
198 #ifdef IO_DEBUG
199 fprintf(stderr, "getbuf allocated %ubytes, blkno=%llu(%llu), %p\n",
200 BBTOB(len), BBTOOFF64(blkno), blkno, buf);
201 #endif
202
203 return(buf);
204 }
205
206 int
207 libxfs_readbufr(dev_t dev, xfs_daddr_t blkno, xfs_buf_t *buf, int len, int flags)
208 {
209 int fd = libxfs_device_to_fd(dev);
210
211 buf->b_dev = dev;
212 buf->b_blkno = blkno;
213 ASSERT(BBTOB(len) <= buf->b_bcount);
214
215 if (pread64(fd, buf->b_addr, BBTOB(len), BBTOOFF64(blkno)) < 0) {
216 fprintf(stderr, _("%s: read failed: %s\n"),
217 progname, strerror(errno));
218 if (flags & LIBXFS_EXIT_ON_FAILURE)
219 exit(1);
220 return errno;
221 }
222 #ifdef IO_DEBUG
223 fprintf(stderr, "readbufr read %ubytes, blkno=%llu(%llu), %p\n",
224 BBTOB(len), BBTOOFF64(blkno), blkno, buf);
225 #endif
226 return 0;
227 }
228
229 xfs_buf_t *
230 libxfs_readbuf(dev_t dev, xfs_daddr_t blkno, int len, int flags)
231 {
232 xfs_buf_t *buf;
233 int error;
234
235 buf = libxfs_getbuf(dev, blkno, len);
236 error = libxfs_readbufr(dev, blkno, buf, len, flags);
237 if (error) {
238 libxfs_putbuf(buf);
239 return NULL;
240 }
241 return buf;
242 }
243
244 xfs_buf_t *
245 libxfs_getsb(xfs_mount_t *mp, int flags)
246 {
247 return libxfs_readbuf(mp->m_dev, XFS_SB_DADDR,
248 XFS_FSB_TO_BB(mp, 1), flags);
249 }
250
251 int
252 libxfs_writebuf_int(xfs_buf_t *buf, int flags)
253 {
254 int sts;
255 int fd = libxfs_device_to_fd(buf->b_dev);
256
257 #ifdef IO_DEBUG
258 fprintf(stderr, "writing %ubytes at blkno=%llu(%llu), %p\n",
259 buf->b_bcount, BBTOOFF64(buf->b_blkno), buf->b_blkno, buf);
260 #endif
261 sts = pwrite64(fd, buf->b_addr, buf->b_bcount, BBTOOFF64(buf->b_blkno));
262 if (sts < 0) {
263 fprintf(stderr, _("%s: pwrite64 failed: %s\n"),
264 progname, strerror(errno));
265 if (flags & LIBXFS_EXIT_ON_FAILURE)
266 exit(1);
267 return errno;
268 }
269 else if (sts != buf->b_bcount) {
270 fprintf(stderr, _("%s: error - wrote only %d of %d bytes\n"),
271 progname, sts, buf->b_bcount);
272 if (flags & LIBXFS_EXIT_ON_FAILURE)
273 exit(1);
274 return EIO;
275 }
276 return 0;
277 }
278
279 int
280 libxfs_writebuf(xfs_buf_t *buf, int flags)
281 {
282 int error = libxfs_writebuf_int(buf, flags);
283 libxfs_putbuf(buf);
284 return error;
285 }
286
287 void
288 libxfs_putbuf(xfs_buf_t *buf)
289 {
290 if (buf != NULL) {
291 xfs_buf_log_item_t *bip;
292 extern xfs_zone_t *xfs_buf_item_zone;
293
294 bip = XFS_BUF_FSPRIVATE(buf, xfs_buf_log_item_t *);
295
296 if (bip)
297 libxfs_zone_free(xfs_buf_item_zone, bip);
298 #ifdef IO_DEBUG
299 fprintf(stderr, "putbuf released %ubytes, %p\n",
300 buf->b_bcount, buf);
301 #endif
302 free(buf);
303 buf = NULL;
304 }
305 }
306
307
308 /*
309 * Simple memory interface
310 */
311
312 xfs_zone_t *
313 libxfs_zone_init(int size, char *name)
314 {
315 xfs_zone_t *ptr;
316
317 if ((ptr = malloc(sizeof(xfs_zone_t))) == NULL) {
318 fprintf(stderr, _("%s: zone init failed (%s, %d bytes): %s\n"),
319 progname, name, (int)sizeof(xfs_zone_t), strerror(errno));
320 exit(1);
321 }
322 ptr->zone_unitsize = size;
323 ptr->zone_name = name;
324 #ifdef MEM_DEBUG
325 ptr->allocated = 0;
326 fprintf(stderr, "new zone %p for \"%s\", size=%d\n", ptr, name, size);
327 #endif
328 return ptr;
329 }
330
331 void *
332 libxfs_zone_zalloc(xfs_zone_t *z)
333 {
334 void *ptr;
335
336 if ((ptr = calloc(z->zone_unitsize, 1)) == NULL) {
337 fprintf(stderr, _("%s: zone calloc failed (%s, %d bytes): %s\n"),
338 progname, z->zone_name, z->zone_unitsize,
339 strerror(errno));
340 exit(1);
341 }
342 #ifdef MEM_DEBUG
343 z->allocated++;
344 fprintf(stderr, "## zone alloc'd item %p from %s (%d bytes) (%d active)\n",
345 ptr, z->zone_name, z->zone_unitsize,
346 z->allocated);
347 #endif
348 return ptr;
349 }
350
351 void
352 libxfs_zone_free(xfs_zone_t *z, void *ptr)
353 {
354 #ifdef MEM_DEBUG
355 z->allocated--;
356 fprintf(stderr, "## zone freed item %p from %s (%d bytes) (%d active)\n",
357 ptr, z->zone_name, z->zone_unitsize,
358 z->allocated);
359 #endif
360 if (ptr != NULL) {
361 free(ptr);
362 ptr = NULL;
363 }
364 }
365
366 void *
367 libxfs_malloc(size_t size)
368 {
369 void *ptr;
370
371 if ((ptr = calloc(1, size)) == NULL) {
372 fprintf(stderr, _("%s: calloc failed (%d bytes): %s\n"),
373 progname, (int)size, strerror(errno));
374 exit(1);
375 }
376 #ifdef MEM_DEBUG
377 fprintf(stderr, "## calloc'd item %p size %d bytes\n",
378 ptr, size);
379 #endif
380 return ptr;
381 }
382
383 void
384 libxfs_free(void *ptr)
385 {
386 #ifdef MEM_DEBUG
387 fprintf(stderr, "## freed item %p\n",
388 ptr);
389 #endif
390 if (ptr != NULL) {
391 free(ptr);
392 ptr = NULL;
393 }
394 }
395
396 void *
397 libxfs_realloc(void *ptr, size_t size)
398 {
399 #ifdef MEM_DEBUG
400 void *optr=ptr;
401 #endif
402 if ((ptr = realloc(ptr, size)) == NULL) {
403 fprintf(stderr, _("%s: realloc failed (%d bytes): %s\n"),
404 progname, (int)size, strerror(errno));
405 exit(1);
406 }
407 #ifdef MEM_DEBUG
408 fprintf(stderr, "## realloc'd item %p now %p size %d bytes\n",
409 optr, ptr, size);
410 #endif
411 return ptr;
412 }
413
414
415 int
416 libxfs_iget(xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, uint lock_flags,
417 xfs_inode_t **ipp, xfs_daddr_t bno)
418 {
419 xfs_inode_t *ip;
420 int error;
421
422 error = libxfs_iread(mp, tp, ino, &ip, bno);
423 if (error)
424 return error;
425 *ipp = ip;
426 return 0;
427 }
428
429 void
430 libxfs_iput(xfs_inode_t *ip, uint lock_flags)
431 {
432 extern xfs_zone_t *xfs_ili_zone;
433 extern xfs_zone_t *xfs_inode_zone;
434
435 if (ip != NULL) {
436
437 /* free attached inode log item */
438 if (ip->i_itemp)
439 libxfs_zone_free(xfs_ili_zone, ip->i_itemp);
440 ip->i_itemp = NULL;
441
442 libxfs_zone_free(xfs_inode_zone, ip);
443 ip = NULL;
444 }
445 }
446
447 /*
448 * libxfs_mod_sb can be used to copy arbitrary changes to the
449 * in-core superblock into the superblock buffer to be logged.
450 *
451 * In user-space, we simply convert to big-endian, and write the
452 * the whole superblock - the in-core changes have all been made
453 * already.
454 */
455 void
456 libxfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
457 {
458 xfs_buf_t *bp;
459 xfs_mount_t *mp;
460
461 mp = tp->t_mountp;
462 bp = libxfs_getbuf(mp->m_dev, XFS_SB_DADDR, 1);
463 libxfs_xlate_sb(XFS_BUF_PTR(bp), &mp->m_sb, -1, ARCH_CONVERT,
464 XFS_SB_ALL_BITS);
465 libxfs_writebuf(bp, LIBXFS_EXIT_ON_FAILURE);
466 }