~ubuntu-branches/ubuntu/utopic/xfsprogs/utopic-proposed

« back to all changes in this revision

Viewing changes to libxfs/rdwr.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathan Scott
  • Date: 2002-04-13 09:45:06 UTC
  • Revision ID: james.westby@ubuntu.com-20020413094506-t8dhemv41gkeg4kx
Tags: 2.0.3-1
New upstream bugfix release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2000 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 <malloc.h>
 
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
 
 
41
void
 
42
libxfs_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
 
 
77
int
 
78
libxfs_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
 
 
161
xfs_buf_t *
 
162
libxfs_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) {
 
169
                fprintf(stderr, "%s: buf calloc failed (%ld bytes): %s\n",
 
170
                        progname, (long)total, strerror(errno));
 
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
 
 
186
int
 
187
libxfs_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) {
 
196
                fprintf(stderr, "%s: lseek64 to %llu failed: %s\n", progname,
 
197
                        (unsigned long long)BBTOOFF64(blkno), strerror(errno));
 
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
 
 
217
xfs_buf_t *
 
218
libxfs_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
 
 
232
xfs_buf_t *
 
233
libxfs_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
 
 
239
int
 
240
libxfs_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) {
 
246
                fprintf(stderr, "%s: lseek64 to %llu failed: %s\n", progname,
 
247
                        (unsigned long long)BBTOOFF64(buf->b_blkno), strerror(errno));
 
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
 
 
276
int
 
277
libxfs_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
 
 
284
void
 
285
libxfs_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
 
 
309
xfs_zone_t *
 
310
libxfs_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",
 
316
                        progname, name, (int)sizeof(xfs_zone_t), strerror(errno));
 
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
 
 
328
void *
 
329
libxfs_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
 
 
349
void
 
350
libxfs_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
 
 
364
void *
 
365
libxfs_malloc(size_t size)
 
366
{
 
367
        void    *ptr;
 
368
 
 
369
        if ((ptr = calloc(1, size)) == NULL) {
 
370
                fprintf(stderr, "%s: calloc failed (%d bytes): %s\n",
 
371
                        progname, (int)size, strerror(errno));
 
372
                exit(1);
 
373
        }
 
374
#ifdef MEM_DEBUG
 
375
        fprintf(stderr, "## calloc'd item %p size %d bytes\n", 
 
376
                ptr, size);
 
377
#endif
 
378
        return ptr;
 
379
}
 
380
 
 
381
void
 
382
libxfs_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
 
 
394
void *
 
395
libxfs_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",
 
402
                        progname, (int)size, strerror(errno));
 
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
 
 
413
int
 
414
libxfs_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
 
 
427
void
 
428
libxfs_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
 */
 
453
void
 
454
libxfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
 
455
{
 
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
}