11ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o/*
21ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o * i_block.c --- Manage the i_block field for i_blocks
31ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o *
41ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o * Copyright (C) 2008 Theodore Ts'o.
51ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o *
61ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o * %Begin-Header%
7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library
8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2.
91ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o * %End-Header%
101ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o */
111ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o
121ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#include <stdio.h>
131ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#if HAVE_UNISTD_H
141ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#include <unistd.h>
151ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#endif
161ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#include <time.h>
171ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#include <string.h>
181ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#if HAVE_SYS_STAT_H
191ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#include <sys/stat.h>
201ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#endif
211ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#if HAVE_SYS_TYPES_H
221ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#include <sys/types.h>
231ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#endif
245d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o#include <errno.h>
251ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o
261ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#include "ext2_fs.h"
271ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o#include "ext2fs.h"
281ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o
291ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'oerrcode_t ext2fs_iblk_add_blocks(ext2_filsys fs, struct ext2_inode *inode,
301ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o				 blk64_t num_blocks)
311ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o{
325d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	unsigned long long b = inode->i_blocks;
331ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o
34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
375d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	if (!(fs->super->s_feature_ro_compat &
385d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
395d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
405d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	    num_blocks *= fs->blocksize / 512;
41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
425d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o
435d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	b += num_blocks;
445d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o
45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
461ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o		inode->osd2.linux2.l_i_blocks_hi = b >> 32;
47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	else if (b > 0xFFFFFFFF)
485d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o		return EOVERFLOW;
495d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	inode->i_blocks = b & 0xFFFFFFFF;
501ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o	return 0;
511ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o}
521ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o
531ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'oerrcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode,
541ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o				 blk64_t num_blocks)
551ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o{
565d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	unsigned long long b = inode->i_blocks;
575d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o
58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
615d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	if (!(fs->super->s_feature_ro_compat &
625d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
635d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
645d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	    num_blocks *= fs->blocksize / 512;
65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
661ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o
675d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	if (num_blocks > b)
685d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o		return EOVERFLOW;
695d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o
705d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	b -= num_blocks;
715d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o
72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
731ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o		inode->osd2.linux2.l_i_blocks_hi = b >> 32;
745d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	inode->i_blocks = b & 0xFFFFFFFF;
751ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o	return 0;
761ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o}
771ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o
781ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'oerrcode_t ext2fs_iblk_set(ext2_filsys fs, struct ext2_inode *inode, blk64_t b)
791ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o{
805d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	if (!(fs->super->s_feature_ro_compat &
815d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
825d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
835d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o		b *= fs->blocksize / 512;
84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	b *= EXT2FS_CLUSTER_RATIO(fs);
855d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o
865d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	inode->i_blocks = b & 0xFFFFFFFF;
875d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
881ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o		inode->osd2.linux2.l_i_blocks_hi = b >> 32;
895d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o	else if (b >> 32)
905d10807070ae13a89c2a0cc217e30af6f061d60eTheodore Ts'o		return EOVERFLOW;
911ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o	return 0;
921ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o}
93