]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/rdwr.c
2 * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
35 #include <xfs_log_priv.h>
37 #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
38 #define BDSTRAT_SIZE (256 * 1024)
41 libxfs_device_zero(dev_t dev
, xfs_daddr_t start
, uint len
)
49 size
= BDSTRAT_SIZE
<= BBTOB(len
) ? BDSTRAT_SIZE
: BBTOB(len
);
50 if ((z
= memalign(getpagesize(), size
)) == NULL
) {
52 _("%s: %s can't memalign %d bytes: %s\n"),
53 progname
, __FUNCTION__
, size
, strerror(errno
));
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
)) <
65 _("%s: %s write failed: %s\n"),
66 progname
, __FUNCTION__
, strerror(errno
));
85 xlog_rec_header_t
*head
;
88 /* the data section must be 32 bit size aligned */
92 __uint32_t pad2
; /* may as well make it 64 bits */
93 } magic
= { XLOG_UNMOUNT_TYPE
, 0, 0 };
95 if (!device
|| !fs_uuid
)
98 /* first zero the log */
99 libxfs_device_zero(device
, start
, length
);
101 /* then write a log record header */
102 if ((version
== 2) && sunit
)
106 buf
= libxfs_getbuf(device
, start
, len
);
110 memset(XFS_BUF_PTR(buf
), 0, BBSIZE
* len
);
111 head
= (xlog_rec_header_t
*)XFS_BUF_PTR(buf
);
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.
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
);
122 INT_SET(head
->h_len
, ARCH_CONVERT
, sunit
- BBSIZE
);
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
);
132 ASSIGN_ANY_LSN(head
->h_lsn
, 1, 0, ARCH_CONVERT
);
133 ASSIGN_ANY_LSN(head
->h_tail_lsn
, 1, 0, ARCH_CONVERT
);
135 memcpy(head
->h_fs_uuid
, fs_uuid
, sizeof(uuid_t
));
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
;
149 if (libxfs_writebuf(buf
, 0))
152 buf
= libxfs_getbuf(device
, start
+ 1, 1);
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);
165 /* and the data for this op */
167 memcpy(XFS_BUF_PTR(buf
) + sizeof(xlog_op_header_t
),
171 if (libxfs_writebuf(buf
, 0))
178 * Simple I/O interface
182 libxfs_getbuf(dev_t device
, xfs_daddr_t blkno
, int len
)
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
));
193 /* by default, we allocate buffer directly after the header */
194 buf
->b_blkno
= blkno
;
195 buf
->b_bcount
= BBTOB(len
);
197 buf
->b_addr
= (char *)(&buf
->b_addr
+ 1); /* must be last field */
199 fprintf(stderr
, "getbuf allocated %ubytes, blkno=%llu(%llu), %p\n",
200 BBTOB(len
), BBTOOFF64(blkno
), blkno
, buf
);
207 libxfs_readbufr(dev_t dev
, xfs_daddr_t blkno
, xfs_buf_t
*buf
, int len
, int flags
)
209 int fd
= libxfs_device_to_fd(dev
);
212 buf
->b_blkno
= blkno
;
213 ASSERT(BBTOB(len
) <= buf
->b_bcount
);
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
)
223 fprintf(stderr
, "readbufr read %ubytes, blkno=%llu(%llu), %p\n",
224 BBTOB(len
), BBTOOFF64(blkno
), blkno
, buf
);
230 libxfs_readbuf(dev_t dev
, xfs_daddr_t blkno
, int len
, int flags
)
235 buf
= libxfs_getbuf(dev
, blkno
, len
);
236 error
= libxfs_readbufr(dev
, blkno
, buf
, len
, flags
);
245 libxfs_getsb(xfs_mount_t
*mp
, int flags
)
247 return libxfs_readbuf(mp
->m_dev
, XFS_SB_DADDR
,
248 XFS_FSB_TO_BB(mp
, 1), flags
);
252 libxfs_writebuf_int(xfs_buf_t
*buf
, int flags
)
255 int fd
= libxfs_device_to_fd(buf
->b_dev
);
258 fprintf(stderr
, "writing %ubytes at blkno=%llu(%llu), %p\n",
259 buf
->b_bcount
, BBTOOFF64(buf
->b_blkno
), buf
->b_blkno
, buf
);
261 sts
= pwrite64(fd
, buf
->b_addr
, buf
->b_bcount
, BBTOOFF64(buf
->b_blkno
));
263 fprintf(stderr
, _("%s: pwrite64 failed: %s\n"),
264 progname
, strerror(errno
));
265 if (flags
& LIBXFS_EXIT_ON_FAILURE
)
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
)
280 libxfs_writebuf(xfs_buf_t
*buf
, int flags
)
282 int error
= libxfs_writebuf_int(buf
, flags
);
288 libxfs_putbuf(xfs_buf_t
*buf
)
291 xfs_buf_log_item_t
*bip
;
292 extern xfs_zone_t
*xfs_buf_item_zone
;
294 bip
= XFS_BUF_FSPRIVATE(buf
, xfs_buf_log_item_t
*);
297 libxfs_zone_free(xfs_buf_item_zone
, bip
);
299 fprintf(stderr
, "putbuf released %ubytes, %p\n",
309 * Simple memory interface
313 libxfs_zone_init(int size
, char *name
)
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
));
322 ptr
->zone_unitsize
= size
;
323 ptr
->zone_name
= name
;
326 fprintf(stderr
, "new zone %p for \"%s\", size=%d\n", ptr
, name
, size
);
332 libxfs_zone_zalloc(xfs_zone_t
*z
)
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
,
344 fprintf(stderr
, "## zone alloc'd item %p from %s (%d bytes) (%d active)\n",
345 ptr
, z
->zone_name
, z
->zone_unitsize
,
352 libxfs_zone_free(xfs_zone_t
*z
, void *ptr
)
356 fprintf(stderr
, "## zone freed item %p from %s (%d bytes) (%d active)\n",
357 ptr
, z
->zone_name
, z
->zone_unitsize
,
367 libxfs_malloc(size_t size
)
371 if ((ptr
= calloc(1, size
)) == NULL
) {
372 fprintf(stderr
, _("%s: calloc failed (%d bytes): %s\n"),
373 progname
, (int)size
, strerror(errno
));
377 fprintf(stderr
, "## calloc'd item %p size %d bytes\n",
384 libxfs_free(void *ptr
)
387 fprintf(stderr
, "## freed item %p\n",
397 libxfs_realloc(void *ptr
, size_t size
)
402 if ((ptr
= realloc(ptr
, size
)) == NULL
) {
403 fprintf(stderr
, _("%s: realloc failed (%d bytes): %s\n"),
404 progname
, (int)size
, strerror(errno
));
408 fprintf(stderr
, "## realloc'd item %p now %p size %d bytes\n",
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
)
422 error
= libxfs_iread(mp
, tp
, ino
, &ip
, bno
);
430 libxfs_iput(xfs_inode_t
*ip
, uint lock_flags
)
432 extern xfs_zone_t
*xfs_ili_zone
;
433 extern xfs_zone_t
*xfs_inode_zone
;
437 /* free attached inode log item */
439 libxfs_zone_free(xfs_ili_zone
, ip
->i_itemp
);
442 libxfs_zone_free(xfs_inode_zone
, ip
);
448 * libxfs_mod_sb can be used to copy arbitrary changes to the
449 * in-core superblock into the superblock buffer to be logged.
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
456 libxfs_mod_sb(xfs_trans_t
*tp
, __int64_t fields
)
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
,
465 libxfs_writebuf(bp
, LIBXFS_EXIT_ON_FAILURE
);