1/*
2 * i_block.c --- Manage the i_block field for i_blocks
3 *
4 * Copyright (C) 2008 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Library
8 * General Public License, version 2.
9 * %End-Header%
10 */
11
12#include <stdio.h>
13#if HAVE_UNISTD_H
14#include <unistd.h>
15#endif
16#include <time.h>
17#include <string.h>
18#if HAVE_SYS_STAT_H
19#include <sys/stat.h>
20#endif
21#if HAVE_SYS_TYPES_H
22#include <sys/types.h>
23#endif
24#include <errno.h>
25
26#include "ext2_fs.h"
27#include "ext2fs.h"
28
29errcode_t ext2fs_iblk_add_blocks(ext2_filsys fs, struct ext2_inode *inode,
30				 blk64_t num_blocks)
31{
32	unsigned long long b = inode->i_blocks;
33
34	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
35		b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
36
37	if (!(fs->super->s_feature_ro_compat &
38	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
39	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
40	    num_blocks *= fs->blocksize / 512;
41	num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
42
43	b += num_blocks;
44
45	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
46		inode->osd2.linux2.l_i_blocks_hi = b >> 32;
47	else if (b > 0xFFFFFFFF)
48		return EOVERFLOW;
49	inode->i_blocks = b & 0xFFFFFFFF;
50	return 0;
51}
52
53errcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode,
54				 blk64_t num_blocks)
55{
56	unsigned long long b = inode->i_blocks;
57
58	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
59		b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
60
61	if (!(fs->super->s_feature_ro_compat &
62	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
63	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
64	    num_blocks *= fs->blocksize / 512;
65	num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
66
67	if (num_blocks > b)
68		return EOVERFLOW;
69
70	b -= num_blocks;
71
72	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
73		inode->osd2.linux2.l_i_blocks_hi = b >> 32;
74	inode->i_blocks = b & 0xFFFFFFFF;
75	return 0;
76}
77
78errcode_t ext2fs_iblk_set(ext2_filsys fs, struct ext2_inode *inode, blk64_t b)
79{
80	if (!(fs->super->s_feature_ro_compat &
81	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
82	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
83		b *= fs->blocksize / 512;
84	b *= EXT2FS_CLUSTER_RATIO(fs);
85
86	inode->i_blocks = b & 0xFFFFFFFF;
87	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
88		inode->osd2.linux2.l_i_blocks_hi = b >> 32;
89	else if (b >> 32)
90		return EOVERFLOW;
91	return 0;
92}
93