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