OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [xfs/] [xfs_fsops.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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 "xfs.h"
34
#include "xfs_macros.h"
35
#include "xfs_types.h"
36
#include "xfs_inum.h"
37
#include "xfs_log.h"
38
#include "xfs_trans.h"
39
#include "xfs_sb.h"
40
#include "xfs_dir.h"
41
#include "xfs_dmapi.h"
42
#include "xfs_mount.h"
43
#include "xfs_ag.h"
44
#include "xfs_alloc_btree.h"
45
#include "xfs_bmap_btree.h"
46
#include "xfs_ialloc_btree.h"
47
#include "xfs_btree.h"
48
#include "xfs_error.h"
49
#include "xfs_alloc.h"
50
#include "xfs_ialloc.h"
51
#include "xfs_fsops.h"
52
#include "xfs_itable.h"
53
#include "xfs_rw.h"
54
#include "xfs_refcache.h"
55
#include "xfs_trans_space.h"
56
#include "xfs_rtalloc.h"
57
#include "xfs_dir2.h"
58
#include "xfs_attr_sf.h"
59
#include "xfs_dir_sf.h"
60
#include "xfs_dir2_sf.h"
61
#include "xfs_dinode.h"
62
#include "xfs_inode.h"
63
#include "xfs_inode_item.h"
64
 
65
/*
66
 * File system operations
67
 */
68
 
69
int
70
xfs_fs_geometry(
71
        xfs_mount_t             *mp,
72
        xfs_fsop_geom_t         *geo,
73
        int                     new_version)
74
{
75
        geo->blocksize = mp->m_sb.sb_blocksize;
76
        geo->rtextsize = mp->m_sb.sb_rextsize;
77
        geo->agblocks = mp->m_sb.sb_agblocks;
78
        geo->agcount = mp->m_sb.sb_agcount;
79
        geo->logblocks = mp->m_sb.sb_logblocks;
80
        geo->sectsize = mp->m_sb.sb_sectsize;
81
        geo->inodesize = mp->m_sb.sb_inodesize;
82
        geo->imaxpct = mp->m_sb.sb_imax_pct;
83
        geo->datablocks = mp->m_sb.sb_dblocks;
84
        geo->rtblocks = mp->m_sb.sb_rblocks;
85
        geo->rtextents = mp->m_sb.sb_rextents;
86
        geo->logstart = mp->m_sb.sb_logstart;
87
        ASSERT(sizeof(geo->uuid)==sizeof(mp->m_sb.sb_uuid));
88
        memcpy(geo->uuid, &mp->m_sb.sb_uuid, sizeof(mp->m_sb.sb_uuid));
89
        if (new_version >= 2) {
90
                geo->sunit = mp->m_sb.sb_unit;
91
                geo->swidth = mp->m_sb.sb_width;
92
        }
93
        if (new_version >= 3) {
94
                geo->version = XFS_FSOP_GEOM_VERSION;
95
                geo->flags =
96
                        (XFS_SB_VERSION_HASATTR(&mp->m_sb) ?
97
                                XFS_FSOP_GEOM_FLAGS_ATTR : 0) |
98
                        (XFS_SB_VERSION_HASNLINK(&mp->m_sb) ?
99
                                XFS_FSOP_GEOM_FLAGS_NLINK : 0) |
100
                        (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) ?
101
                                XFS_FSOP_GEOM_FLAGS_QUOTA : 0) |
102
                        (XFS_SB_VERSION_HASALIGN(&mp->m_sb) ?
103
                                XFS_FSOP_GEOM_FLAGS_IALIGN : 0) |
104
                        (XFS_SB_VERSION_HASDALIGN(&mp->m_sb) ?
105
                                XFS_FSOP_GEOM_FLAGS_DALIGN : 0) |
106
                        (XFS_SB_VERSION_HASSHARED(&mp->m_sb) ?
107
                                XFS_FSOP_GEOM_FLAGS_SHARED : 0) |
108
                        (XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) ?
109
                                XFS_FSOP_GEOM_FLAGS_EXTFLG : 0) |
110
                        (XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ?
111
                                XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) |
112
                        (XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
113
                                XFS_FSOP_GEOM_FLAGS_SECTOR : 0);
114
                geo->logsectsize = XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
115
                                mp->m_sb.sb_logsectsize : BBSIZE;
116
                geo->rtsectsize = mp->m_sb.sb_blocksize;
117
                geo->dirblocksize = mp->m_dirblksize;
118
        }
119
        if (new_version >= 4) {
120
                geo->flags |=
121
                        (XFS_SB_VERSION_HASLOGV2(&mp->m_sb) ?
122
                                XFS_FSOP_GEOM_FLAGS_LOGV2 : 0);
123
                geo->logsunit = mp->m_sb.sb_logsunit;
124
        }
125
        return 0;
126
}
127
 
128
static int
129
xfs_growfs_data_private(
130
        xfs_mount_t             *mp,            /* mount point for filesystem */
131
        xfs_growfs_data_t       *in)            /* growfs data input struct */
132
{
133
        xfs_agf_t               *agf;
134
        xfs_agi_t               *agi;
135
        xfs_agnumber_t          agno;
136
        xfs_extlen_t            agsize;
137
        xfs_extlen_t            tmpsize;
138
        xfs_alloc_rec_t         *arec;
139
        xfs_btree_sblock_t      *block;
140
        xfs_buf_t               *bp;
141
        int                     bucket;
142
        int                     dpct;
143
        int                     error;
144
        xfs_agnumber_t          nagcount;
145
        xfs_rfsblock_t          nb, nb_mod;
146
        xfs_rfsblock_t          new;
147
        xfs_rfsblock_t          nfree;
148
        xfs_agnumber_t          oagcount;
149
        int                     pct;
150
        xfs_sb_t                *sbp;
151
        xfs_trans_t             *tp;
152
 
153
        nb = in->newblocks;
154
        pct = in->imaxpct;
155
        if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100)
156
                return XFS_ERROR(EINVAL);
157
        dpct = pct - mp->m_sb.sb_imax_pct;
158
        error = xfs_read_buf(mp, mp->m_ddev_targp,
159
                        XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
160
                        XFS_FSS_TO_BB(mp, 1), 0, &bp);
161
        if (error)
162
                return error;
163
        ASSERT(bp);
164
        xfs_buf_relse(bp);
165
 
166
        new = nb;       /* use new as a temporary here */
167
        nb_mod = do_div(new, mp->m_sb.sb_agblocks);
168
        nagcount = new + (nb_mod != 0);
169
        if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) {
170
                nagcount--;
171
                nb = nagcount * mp->m_sb.sb_agblocks;
172
                if (nb < mp->m_sb.sb_dblocks)
173
                        return XFS_ERROR(EINVAL);
174
        }
175
        new = nb - mp->m_sb.sb_dblocks;
176
        oagcount = mp->m_sb.sb_agcount;
177
        if (nagcount > oagcount) {
178
                down_write(&mp->m_peraglock);
179
                mp->m_perag = kmem_realloc(mp->m_perag,
180
                        sizeof(xfs_perag_t) * nagcount,
181
                        sizeof(xfs_perag_t) * oagcount,
182
                        KM_SLEEP);
183
                memset(&mp->m_perag[oagcount], 0,
184
                        (nagcount - oagcount) * sizeof(xfs_perag_t));
185
                mp->m_flags |= XFS_MOUNT_32BITINODES;
186
                xfs_initialize_perag(mp, nagcount);
187
                up_write(&mp->m_peraglock);
188
        }
189
        tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
190
        if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp),
191
                        XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) {
192
                xfs_trans_cancel(tp, 0);
193
                return error;
194
        }
195
 
196
        nfree = 0;
197
        for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
198
                /*
199
                 * AG freelist header block
200
                 */
201
                bp = xfs_buf_get(mp->m_ddev_targp,
202
                                  XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
203
                                  XFS_FSS_TO_BB(mp, 1), 0);
204
                agf = XFS_BUF_TO_AGF(bp);
205
                memset(agf, 0, mp->m_sb.sb_sectsize);
206
                INT_SET(agf->agf_magicnum, ARCH_CONVERT, XFS_AGF_MAGIC);
207
                INT_SET(agf->agf_versionnum, ARCH_CONVERT, XFS_AGF_VERSION);
208
                INT_SET(agf->agf_seqno, ARCH_CONVERT, agno);
209
                if (agno == nagcount - 1)
210
                        agsize =
211
                                nb -
212
                                (agno * (xfs_rfsblock_t)mp->m_sb.sb_agblocks);
213
                else
214
                        agsize = mp->m_sb.sb_agblocks;
215
                INT_SET(agf->agf_length, ARCH_CONVERT, agsize);
216
                INT_SET(agf->agf_roots[XFS_BTNUM_BNOi], ARCH_CONVERT,
217
                        XFS_BNO_BLOCK(mp));
218
                INT_SET(agf->agf_roots[XFS_BTNUM_CNTi], ARCH_CONVERT,
219
                        XFS_CNT_BLOCK(mp));
220
                INT_SET(agf->agf_levels[XFS_BTNUM_BNOi], ARCH_CONVERT, 1);
221
                INT_SET(agf->agf_levels[XFS_BTNUM_CNTi], ARCH_CONVERT, 1);
222
                INT_ZERO(agf->agf_flfirst, ARCH_CONVERT);
223
                INT_SET(agf->agf_fllast, ARCH_CONVERT, XFS_AGFL_SIZE(mp) - 1);
224
                INT_ZERO(agf->agf_flcount, ARCH_CONVERT);
225
                tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
226
                INT_SET(agf->agf_freeblks, ARCH_CONVERT, tmpsize);
227
                INT_SET(agf->agf_longest, ARCH_CONVERT, tmpsize);
228
                error = xfs_bwrite(mp, bp);
229
                if (error) {
230
                        goto error0;
231
                }
232
                /*
233
                 * AG inode header block
234
                 */
235
                bp = xfs_buf_get(mp->m_ddev_targp,
236
                                  XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
237
                                  XFS_FSS_TO_BB(mp, 1), 0);
238
                agi = XFS_BUF_TO_AGI(bp);
239
                memset(agi, 0, mp->m_sb.sb_sectsize);
240
                INT_SET(agi->agi_magicnum, ARCH_CONVERT, XFS_AGI_MAGIC);
241
                INT_SET(agi->agi_versionnum, ARCH_CONVERT, XFS_AGI_VERSION);
242
                INT_SET(agi->agi_seqno, ARCH_CONVERT, agno);
243
                INT_SET(agi->agi_length, ARCH_CONVERT, agsize);
244
                INT_ZERO(agi->agi_count, ARCH_CONVERT);
245
                INT_SET(agi->agi_root, ARCH_CONVERT, XFS_IBT_BLOCK(mp));
246
                INT_SET(agi->agi_level, ARCH_CONVERT, 1);
247
                INT_ZERO(agi->agi_freecount, ARCH_CONVERT);
248
                INT_SET(agi->agi_newino, ARCH_CONVERT, NULLAGINO);
249
                INT_SET(agi->agi_dirino, ARCH_CONVERT, NULLAGINO);
250
                for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
251
                        INT_SET(agi->agi_unlinked[bucket], ARCH_CONVERT,
252
                                NULLAGINO);
253
                error = xfs_bwrite(mp, bp);
254
                if (error) {
255
                        goto error0;
256
                }
257
                /*
258
                 * BNO btree root block
259
                 */
260
                bp = xfs_buf_get(mp->m_ddev_targp,
261
                        XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
262
                        BTOBB(mp->m_sb.sb_blocksize), 0);
263
                block = XFS_BUF_TO_SBLOCK(bp);
264
                memset(block, 0, mp->m_sb.sb_blocksize);
265
                INT_SET(block->bb_magic, ARCH_CONVERT, XFS_ABTB_MAGIC);
266
                INT_ZERO(block->bb_level, ARCH_CONVERT);
267
                INT_SET(block->bb_numrecs, ARCH_CONVERT, 1);
268
                INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
269
                INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
270
                arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc,
271
                        block, 1, mp->m_alloc_mxr[0]);
272
                INT_SET(arec->ar_startblock, ARCH_CONVERT,
273
                        XFS_PREALLOC_BLOCKS(mp));
274
                INT_SET(arec->ar_blockcount, ARCH_CONVERT,
275
                        agsize - INT_GET(arec->ar_startblock, ARCH_CONVERT));
276
                error = xfs_bwrite(mp, bp);
277
                if (error) {
278
                        goto error0;
279
                }
280
                /*
281
                 * CNT btree root block
282
                 */
283
                bp = xfs_buf_get(mp->m_ddev_targp,
284
                        XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
285
                        BTOBB(mp->m_sb.sb_blocksize), 0);
286
                block = XFS_BUF_TO_SBLOCK(bp);
287
                memset(block, 0, mp->m_sb.sb_blocksize);
288
                INT_SET(block->bb_magic, ARCH_CONVERT, XFS_ABTC_MAGIC);
289
                INT_ZERO(block->bb_level, ARCH_CONVERT);
290
                INT_SET(block->bb_numrecs, ARCH_CONVERT, 1);
291
                INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
292
                INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
293
                arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc,
294
                        block, 1, mp->m_alloc_mxr[0]);
295
                INT_SET(arec->ar_startblock, ARCH_CONVERT,
296
                        XFS_PREALLOC_BLOCKS(mp));
297
                INT_SET(arec->ar_blockcount, ARCH_CONVERT,
298
                        agsize - INT_GET(arec->ar_startblock, ARCH_CONVERT));
299
                nfree += INT_GET(arec->ar_blockcount, ARCH_CONVERT);
300
                error = xfs_bwrite(mp, bp);
301
                if (error) {
302
                        goto error0;
303
                }
304
                /*
305
                 * INO btree root block
306
                 */
307
                bp = xfs_buf_get(mp->m_ddev_targp,
308
                        XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
309
                        BTOBB(mp->m_sb.sb_blocksize), 0);
310
                block = XFS_BUF_TO_SBLOCK(bp);
311
                memset(block, 0, mp->m_sb.sb_blocksize);
312
                INT_SET(block->bb_magic, ARCH_CONVERT, XFS_IBT_MAGIC);
313
                INT_ZERO(block->bb_level, ARCH_CONVERT);
314
                INT_ZERO(block->bb_numrecs, ARCH_CONVERT);
315
                INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
316
                INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
317
                error = xfs_bwrite(mp, bp);
318
                if (error) {
319
                        goto error0;
320
                }
321
        }
322
        xfs_trans_agblocks_delta(tp, nfree);
323
        /*
324
         * There are new blocks in the old last a.g.
325
         */
326
        if (new) {
327
                /*
328
                 * Change the agi length.
329
                 */
330
                error = xfs_ialloc_read_agi(mp, tp, agno, &bp);
331
                if (error) {
332
                        goto error0;
333
                }
334
                ASSERT(bp);
335
                agi = XFS_BUF_TO_AGI(bp);
336
                INT_MOD(agi->agi_length, ARCH_CONVERT, new);
337
                ASSERT(nagcount == oagcount ||
338
                       INT_GET(agi->agi_length, ARCH_CONVERT) ==
339
                                mp->m_sb.sb_agblocks);
340
                xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH);
341
                /*
342
                 * Change agf length.
343
                 */
344
                error = xfs_alloc_read_agf(mp, tp, agno, 0, &bp);
345
                if (error) {
346
                        goto error0;
347
                }
348
                ASSERT(bp);
349
                agf = XFS_BUF_TO_AGF(bp);
350
                INT_MOD(agf->agf_length, ARCH_CONVERT, new);
351
                ASSERT(INT_GET(agf->agf_length, ARCH_CONVERT) ==
352
                                INT_GET(agi->agi_length, ARCH_CONVERT));
353
                /*
354
                 * Free the new space.
355
                 */
356
                error = xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, agno,
357
                        INT_GET(agf->agf_length, ARCH_CONVERT) - new), new);
358
                if (error) {
359
                        goto error0;
360
                }
361
        }
362
        if (nagcount > oagcount)
363
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, nagcount - oagcount);
364
        if (nb > mp->m_sb.sb_dblocks)
365
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_DBLOCKS,
366
                                 nb - mp->m_sb.sb_dblocks);
367
        if (nfree)
368
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, nfree);
369
        if (dpct)
370
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct);
371
        error = xfs_trans_commit(tp, 0, NULL);
372
        if (error) {
373
                return error;
374
        }
375
        if (mp->m_sb.sb_imax_pct) {
376
                __uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct;
377
                do_div(icount, 100);
378
                mp->m_maxicount = icount << mp->m_sb.sb_inopblog;
379
        } else
380
                mp->m_maxicount = 0;
381
        for (agno = 1; agno < nagcount; agno++) {
382
                error = xfs_read_buf(mp, mp->m_ddev_targp,
383
                                  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
384
                                  XFS_FSS_TO_BB(mp, 1), 0, &bp);
385
                if (error) {
386
                        xfs_fs_cmn_err(CE_WARN, mp,
387
                        "error %d reading secondary superblock for ag %d",
388
                                error, agno);
389
                        break;
390
                }
391
                sbp = XFS_BUF_TO_SBP(bp);
392
                xfs_xlatesb(sbp, &mp->m_sb, -1, ARCH_CONVERT, XFS_SB_ALL_BITS);
393
                /*
394
                 * If we get an error writing out the alternate superblocks,
395
                 * just issue a warning and continue.  The real work is
396
                 * already done and committed.
397
                 */
398
                if (!(error = xfs_bwrite(mp, bp))) {
399
                        continue;
400
                } else {
401
                        xfs_fs_cmn_err(CE_WARN, mp,
402
                "write error %d updating secondary superblock for ag %d",
403
                                error, agno);
404
                        break; /* no point in continuing */
405
                }
406
        }
407
        return 0;
408
 
409
 error0:
410
        xfs_trans_cancel(tp, XFS_TRANS_ABORT);
411
        return error;
412
}
413
 
414
static int
415
xfs_growfs_log_private(
416
        xfs_mount_t             *mp,    /* mount point for filesystem */
417
        xfs_growfs_log_t        *in)    /* growfs log input struct */
418
{
419
        xfs_extlen_t            nb;
420
 
421
        nb = in->newblocks;
422
        if (nb < XFS_MIN_LOG_BLOCKS || nb < XFS_B_TO_FSB(mp, XFS_MIN_LOG_BYTES))
423
                return XFS_ERROR(EINVAL);
424
        if (nb == mp->m_sb.sb_logblocks &&
425
            in->isint == (mp->m_sb.sb_logstart != 0))
426
                return XFS_ERROR(EINVAL);
427
        /*
428
         * Moving the log is hard, need new interfaces to sync
429
         * the log first, hold off all activity while moving it.
430
         * Can have shorter or longer log in the same space,
431
         * or transform internal to external log or vice versa.
432
         */
433
        return XFS_ERROR(ENOSYS);
434
}
435
 
436
/*
437
 * protected versions of growfs function acquire and release locks on the mount
438
 * point - exported through ioctls: XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG,
439
 * XFS_IOC_FSGROWFSRT
440
 */
441
 
442
 
443
int
444
xfs_growfs_data(
445
        xfs_mount_t             *mp,
446
        xfs_growfs_data_t       *in)
447
{
448
        int error;
449
        if (!cpsema(&mp->m_growlock))
450
                return XFS_ERROR(EWOULDBLOCK);
451
        error = xfs_growfs_data_private(mp, in);
452
        vsema(&mp->m_growlock);
453
        return error;
454
}
455
 
456
int
457
xfs_growfs_log(
458
        xfs_mount_t             *mp,
459
        xfs_growfs_log_t        *in)
460
{
461
        int error;
462
        if (!cpsema(&mp->m_growlock))
463
                return XFS_ERROR(EWOULDBLOCK);
464
        error = xfs_growfs_log_private(mp, in);
465
        vsema(&mp->m_growlock);
466
        return error;
467
}
468
 
469
/*
470
 * exported through ioctl XFS_IOC_FSCOUNTS
471
 */
472
 
473
int
474
xfs_fs_counts(
475
        xfs_mount_t             *mp,
476
        xfs_fsop_counts_t       *cnt)
477
{
478
        unsigned long   s;
479
 
480
        s = XFS_SB_LOCK(mp);
481
        cnt->freedata = mp->m_sb.sb_fdblocks;
482
        cnt->freertx = mp->m_sb.sb_frextents;
483
        cnt->freeino = mp->m_sb.sb_ifree;
484
        cnt->allocino = mp->m_sb.sb_icount;
485
        XFS_SB_UNLOCK(mp, s);
486
        return 0;
487
}
488
 
489
/*
490
 * exported through ioctl XFS_IOC_SET_RESBLKS & XFS_IOC_GET_RESBLKS
491
 *
492
 * xfs_reserve_blocks is called to set m_resblks
493
 * in the in-core mount table. The number of unused reserved blocks
494
 * is kept in m_resbls_avail.
495
 *
496
 * Reserve the requested number of blocks if available. Otherwise return
497
 * as many as possible to satisfy the request. The actual number
498
 * reserved are returned in outval
499
 *
500
 * A null inval pointer indicates that only the current reserved blocks
501
 * available  should  be returned no settings are changed.
502
 */
503
 
504
int
505
xfs_reserve_blocks(
506
        xfs_mount_t             *mp,
507
        __uint64_t              *inval,
508
        xfs_fsop_resblks_t      *outval)
509
{
510
        __uint64_t              lcounter, delta;
511
        __uint64_t              request;
512
        unsigned long s;
513
 
514
        /* If inval is null, report current values and return */
515
 
516
        if (inval == (__uint64_t *)NULL) {
517
                outval->resblks = mp->m_resblks;
518
                outval->resblks_avail = mp->m_resblks_avail;
519
                return(0);
520
        }
521
 
522
        request = *inval;
523
        s = XFS_SB_LOCK(mp);
524
 
525
        /*
526
         * If our previous reservation was larger than the current value,
527
         * then move any unused blocks back to the free pool.
528
         */
529
 
530
        if (mp->m_resblks > request) {
531
                lcounter = mp->m_resblks_avail - request;
532
                if (lcounter  > 0) {             /* release unused blocks */
533
                        mp->m_sb.sb_fdblocks += lcounter;
534
                        mp->m_resblks_avail -= lcounter;
535
                }
536
                mp->m_resblks = request;
537
        } else {
538
                delta = request - mp->m_resblks;
539
                lcounter = mp->m_sb.sb_fdblocks;
540
                lcounter -= delta;
541
                if (lcounter < 0) {
542
                        /* We can't satisfy the request, just get what we can */
543
                        mp->m_resblks += mp->m_sb.sb_fdblocks;
544
                        mp->m_resblks_avail += mp->m_sb.sb_fdblocks;
545
                        mp->m_sb.sb_fdblocks = 0;
546
                } else {
547
                        mp->m_sb.sb_fdblocks = lcounter;
548
                        mp->m_resblks = request;
549
                        mp->m_resblks_avail += delta;
550
                }
551
        }
552
 
553
        outval->resblks = mp->m_resblks;
554
        outval->resblks_avail = mp->m_resblks_avail;
555
        XFS_SB_UNLOCK(mp, s);
556
        return(0);
557
}
558
 
559
void
560
xfs_fs_log_dummy(xfs_mount_t *mp)
561
{
562
        xfs_trans_t *tp;
563
        xfs_inode_t *ip;
564
 
565
 
566
        tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
567
        atomic_inc(&mp->m_active_trans);
568
        if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) {
569
                xfs_trans_cancel(tp, 0);
570
                return;
571
        }
572
 
573
        ip = mp->m_rootip;
574
        xfs_ilock(ip, XFS_ILOCK_EXCL);
575
 
576
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
577
        xfs_trans_ihold(tp, ip);
578
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
579
        xfs_trans_commit(tp, XFS_TRANS_SYNC, NULL);
580
 
581
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
582
}
583
 
584
int
585
xfs_fs_freeze(
586
        xfs_mount_t     *mp)
587
{
588
        vfs_t           *vfsp;
589
        /*REFERENCED*/
590
        int             error;
591
 
592
        vfsp = XFS_MTOVFS(mp);
593
 
594
        /* Stop new writers */
595
        xfs_start_freeze(mp, XFS_FREEZE_WRITE);
596
 
597
        /* Flush the refcache */
598
        xfs_refcache_purge_mp(mp);
599
 
600
        /* Flush delalloc and delwri data */
601
        VFS_SYNC(vfsp, SYNC_DELWRI|SYNC_WAIT, NULL, error);
602
 
603
        /* Pause transaction subsystem */
604
        xfs_start_freeze(mp, XFS_FREEZE_TRANS);
605
 
606
        /* Flush any remaining inodes into buffers */
607
        VFS_SYNC(vfsp, SYNC_ATTR|SYNC_WAIT, NULL, error);
608
 
609
        /* Push all buffers out to disk */
610
        xfs_binval(mp->m_ddev_targp);
611
        if (mp->m_rtdev_targp) {
612
                xfs_binval(mp->m_rtdev_targp);
613
        }
614
 
615
        /* Push the superblock and write an unmount record */
616
        xfs_log_unmount_write(mp);
617
        xfs_unmountfs_writesb(mp);
618
 
619
        return 0;
620
}
621
 
622
int
623
xfs_fs_thaw(
624
        xfs_mount_t     *mp)
625
{
626
        xfs_finish_freeze(mp);
627
        return 0;
628
}
629
 
630
int
631
xfs_fs_goingdown(
632
        xfs_mount_t     *mp,
633
        __uint32_t      inflags)
634
{
635
        switch (inflags)
636
        {
637
        case XFS_FSOP_GOING_FLAGS_DEFAULT:
638
                xfs_fs_freeze(mp);
639
                xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
640
                xfs_fs_thaw(mp);
641
                break;
642
        case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
643
                xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
644
                break;
645
        case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:
646
                xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR);
647
                break;
648
        default:
649
                return XFS_ERROR(EINVAL);
650
        }
651
 
652
        return 0;
653
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.