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