file.c 4.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 *  linux/fs/hpfs/file.c
 *
 *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
 *
 *  file VFS functions
 */

#include "hpfs_fn.h"

#define BLOCKS(size) (((size) + 511) >> 9)

static int hpfs_file_release(struct inode *inode, struct file *file)
{
A
Arnd Bergmann 已提交
15
	hpfs_lock(inode->i_sb);
L
Linus Torvalds 已提交
16
	hpfs_write_if_changed(inode);
A
Arnd Bergmann 已提交
17
	hpfs_unlock(inode->i_sb);
L
Linus Torvalds 已提交
18 19 20
	return 0;
}

21
int hpfs_file_fsync(struct file *file, int datasync)
L
Linus Torvalds 已提交
22
{
23
	/*return file_fsync(file, datasync);*/
L
Linus Torvalds 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
	return 0; /* Don't fsync :-) */
}

/*
 * generic_file_read often calls bmap with non-existing sector,
 * so we must ignore such errors.
 */

static secno hpfs_bmap(struct inode *inode, unsigned file_secno)
{
	struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
	unsigned n, disk_secno;
	struct fnode *fnode;
	struct buffer_head *bh;
	if (BLOCKS(hpfs_i(inode)->mmu_private) <= file_secno) return 0;
	n = file_secno - hpfs_inode->i_file_sec;
	if (n < hpfs_inode->i_n_secs) return hpfs_inode->i_disk_sec + n;
	if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) return 0;
	disk_secno = hpfs_bplus_lookup(inode->i_sb, inode, &fnode->btree, file_secno, bh);
	if (disk_secno == -1) return 0;
	if (hpfs_chk_sectors(inode->i_sb, disk_secno, 1, "bmap")) return 0;
	return disk_secno;
}

static void hpfs_truncate(struct inode *i)
{
	if (IS_IMMUTABLE(i)) return /*-EPERM*/;
51 52
	hpfs_lock_assert(i->i_sb);

L
Linus Torvalds 已提交
53 54 55 56 57 58 59 60 61 62
	hpfs_i(i)->i_n_secs = 0;
	i->i_blocks = 1 + ((i->i_size + 511) >> 9);
	hpfs_i(i)->mmu_private = i->i_size;
	hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
	hpfs_write_inode(i);
	hpfs_i(i)->i_n_secs = 0;
}

static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
{
63
	int r;
L
Linus Torvalds 已提交
64
	secno s;
65
	hpfs_lock(inode->i_sb);
L
Linus Torvalds 已提交
66 67 68
	s = hpfs_bmap(inode, iblock);
	if (s) {
		map_bh(bh_result, inode->i_sb, s);
69
		goto ret_0;
L
Linus Torvalds 已提交
70
	}
71
	if (!create) goto ret_0;
L
Linus Torvalds 已提交
72 73
	if (iblock<<9 != hpfs_i(inode)->mmu_private) {
		BUG();
74 75
		r = -EIO;
		goto ret_r;
L
Linus Torvalds 已提交
76 77 78
	}
	if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) {
		hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1);
79 80
		r = -ENOSPC;
		goto ret_r;
L
Linus Torvalds 已提交
81 82 83 84 85
	}
	inode->i_blocks++;
	hpfs_i(inode)->mmu_private += 512;
	set_buffer_new(bh_result);
	map_bh(bh_result, inode->i_sb, s);
86 87 88 89 90
	ret_0:
	r = 0;
	ret_r:
	hpfs_unlock(inode->i_sb);
	return r;
L
Linus Torvalds 已提交
91 92 93 94 95 96
}

static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
{
	return block_write_full_page(page,hpfs_get_block, wbc);
}
N
Nick Piggin 已提交
97

L
Linus Torvalds 已提交
98 99 100 101
static int hpfs_readpage(struct file *file, struct page *page)
{
	return block_read_full_page(page,hpfs_get_block);
}
N
Nick Piggin 已提交
102 103 104 105

static int hpfs_write_begin(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned flags,
			struct page **pagep, void **fsdata)
L
Linus Torvalds 已提交
106
{
107 108
	int ret;

N
Nick Piggin 已提交
109
	*pagep = NULL;
110
	ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
N
Nick Piggin 已提交
111 112
				hpfs_get_block,
				&hpfs_i(mapping->host)->mmu_private);
113 114 115 116 117 118 119
	if (unlikely(ret)) {
		loff_t isize = mapping->host->i_size;
		if (pos + len > isize)
			vmtruncate(mapping->host, isize);
	}

	return ret;
L
Linus Torvalds 已提交
120
}
N
Nick Piggin 已提交
121

L
Linus Torvalds 已提交
122 123 124 125
static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
{
	return generic_block_bmap(mapping,block,hpfs_get_block);
}
N
Nick Piggin 已提交
126

127
const struct address_space_operations hpfs_aops = {
L
Linus Torvalds 已提交
128 129
	.readpage = hpfs_readpage,
	.writepage = hpfs_writepage,
N
Nick Piggin 已提交
130 131
	.write_begin = hpfs_write_begin,
	.write_end = generic_write_end,
L
Linus Torvalds 已提交
132 133 134 135 136 137 138 139
	.bmap = _hpfs_bmap
};

static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
			size_t count, loff_t *ppos)
{
	ssize_t retval;

140
	retval = do_sync_write(file, buf, count, ppos);
141 142
	if (retval > 0) {
		hpfs_lock(file->f_path.dentry->d_sb);
J
Josef Sipek 已提交
143
		hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1;
144 145
		hpfs_unlock(file->f_path.dentry->d_sb);
	}
L
Linus Torvalds 已提交
146 147 148
	return retval;
}

149
const struct file_operations hpfs_file_ops =
L
Linus Torvalds 已提交
150 151
{
	.llseek		= generic_file_llseek,
152 153
	.read		= do_sync_read,
	.aio_read	= generic_file_aio_read,
L
Linus Torvalds 已提交
154
	.write		= hpfs_file_write,
155
	.aio_write	= generic_file_aio_write,
L
Linus Torvalds 已提交
156 157 158
	.mmap		= generic_file_mmap,
	.release	= hpfs_file_release,
	.fsync		= hpfs_file_fsync,
159
	.splice_read	= generic_file_splice_read,
L
Linus Torvalds 已提交
160 161
};

162
const struct inode_operations hpfs_file_iops =
L
Linus Torvalds 已提交
163 164
{
	.truncate	= hpfs_truncate,
165
	.setattr	= hpfs_setattr,
L
Linus Torvalds 已提交
166
};