Blame view

fs/hpfs/file.c 5.53 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  /*
   *  linux/fs/hpfs/file.c
   *
   *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
   *
   *  file VFS functions
   */
  
  #include "hpfs_fn.h"
a0c1b7596   Mikulas Patocka   hpfs: use mpage
10
  #include <linux/mpage.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
  
  #define BLOCKS(size) (((size) + 511) >> 9)
  
  static int hpfs_file_release(struct inode *inode, struct file *file)
  {
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
16
  	hpfs_lock(inode->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  	hpfs_write_if_changed(inode);
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
18
  	hpfs_unlock(inode->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  	return 0;
  }
02c24a821   Josef Bacik   fs: push i_mutex ...
21
  int hpfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  {
bc8728ee5   Mikulas Patocka   HPFS: Implement f...
23
  	struct inode *inode = file->f_mapping->host;
02c24a821   Josef Bacik   fs: push i_mutex ...
24
25
26
27
28
  	int ret;
  
  	ret = filemap_write_and_wait_range(file->f_mapping, start, end);
  	if (ret)
  		return ret;
bc8728ee5   Mikulas Patocka   HPFS: Implement f...
29
  	return sync_blockdev(inode->i_sb->s_bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
  }
  
  /*
   * generic_file_read often calls bmap with non-existing sector,
   * so we must ignore such errors.
   */
a0c1b7596   Mikulas Patocka   hpfs: use mpage
36
  static secno hpfs_bmap(struct inode *inode, unsigned file_secno, unsigned *n_secs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
43
  {
  	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;
a0c1b7596   Mikulas Patocka   hpfs: use mpage
44
45
46
47
  	if (n < hpfs_inode->i_n_secs) {
  		*n_secs = hpfs_inode->i_n_secs - n;
  		return hpfs_inode->i_disk_sec + n;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
  	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;
a0c1b7596   Mikulas Patocka   hpfs: use mpage
52
53
54
55
56
57
  	n = file_secno - hpfs_inode->i_file_sec;
  	if (n < hpfs_inode->i_n_secs) {
  		*n_secs = hpfs_inode->i_n_secs - n;
  		return hpfs_inode->i_disk_sec + n;
  	}
  	*n_secs = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  	return disk_secno;
  }
70b31c4c8   Marco Stornelli   hpfs: drop vmtrun...
60
  void hpfs_truncate(struct inode *i)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
  {
  	if (IS_IMMUTABLE(i)) return /*-EPERM*/;
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
63
  	hpfs_lock_assert(i->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
  	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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
  }
  
  static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
  {
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
74
  	int r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  	secno s;
a0c1b7596   Mikulas Patocka   hpfs: use mpage
76
  	unsigned n_secs;
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
77
  	hpfs_lock(inode->i_sb);
a0c1b7596   Mikulas Patocka   hpfs: use mpage
78
  	s = hpfs_bmap(inode, iblock, &n_secs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
  	if (s) {
a0c1b7596   Mikulas Patocka   hpfs: use mpage
80
81
  		if (bh_result->b_size >> 9 < n_secs)
  			n_secs = bh_result->b_size >> 9;
a64eefaac   Mikulas Patocka   hpfs: support hot...
82
83
84
85
86
  		n_secs = hpfs_search_hotfix_map_for_range(inode->i_sb, s, n_secs);
  		if (unlikely(!n_secs)) {
  			s = hpfs_search_hotfix_map(inode->i_sb, s);
  			n_secs = 1;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  		map_bh(bh_result, inode->i_sb, s);
a0c1b7596   Mikulas Patocka   hpfs: use mpage
88
  		bh_result->b_size = n_secs << 9;
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
89
  		goto ret_0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  	}
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
91
  	if (!create) goto ret_0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
  	if (iblock<<9 != hpfs_i(inode)->mmu_private) {
  		BUG();
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
94
95
  		r = -EIO;
  		goto ret_r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
  	}
  	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);
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
99
100
  		r = -ENOSPC;
  		goto ret_r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
104
  	}
  	inode->i_blocks++;
  	hpfs_i(inode)->mmu_private += 512;
  	set_buffer_new(bh_result);
a64eefaac   Mikulas Patocka   hpfs: support hot...
105
  	map_bh(bh_result, inode->i_sb, hpfs_search_hotfix_map(inode->i_sb, s));
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
106
107
108
109
110
  	ret_0:
  	r = 0;
  	ret_r:
  	hpfs_unlock(inode->i_sb);
  	return r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  }
a0c1b7596   Mikulas Patocka   hpfs: use mpage
112
113
114
115
  static int hpfs_readpage(struct file *file, struct page *page)
  {
  	return mpage_readpage(page, hpfs_get_block);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
  static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
  {
a0c1b7596   Mikulas Patocka   hpfs: use mpage
118
  	return block_write_full_page(page, hpfs_get_block, wbc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  }
d6091b720   Nick Piggin   hpfs: convert to ...
120

a0c1b7596   Mikulas Patocka   hpfs: use mpage
121
122
123
124
125
126
127
128
  static int hpfs_readpages(struct file *file, struct address_space *mapping,
  			  struct list_head *pages, unsigned nr_pages)
  {
  	return mpage_readpages(mapping, pages, nr_pages, hpfs_get_block);
  }
  
  static int hpfs_writepages(struct address_space *mapping,
  			   struct writeback_control *wbc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  {
a0c1b7596   Mikulas Patocka   hpfs: use mpage
130
  	return mpage_writepages(mapping, wbc, hpfs_get_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  }
d6091b720   Nick Piggin   hpfs: convert to ...
132

70b31c4c8   Marco Stornelli   hpfs: drop vmtrun...
133
134
135
  static void hpfs_write_failed(struct address_space *mapping, loff_t to)
  {
  	struct inode *inode = mapping->host;
bbd465df7   Mikulas Patocka   hpfs: fix warning...
136
  	hpfs_lock(inode->i_sb);
70b31c4c8   Marco Stornelli   hpfs: drop vmtrun...
137
  	if (to > inode->i_size) {
7caef2676   Kirill A. Shutemov   truncate: drop 'o...
138
  		truncate_pagecache(inode, inode->i_size);
70b31c4c8   Marco Stornelli   hpfs: drop vmtrun...
139
140
  		hpfs_truncate(inode);
  	}
bbd465df7   Mikulas Patocka   hpfs: fix warning...
141
142
  
  	hpfs_unlock(inode->i_sb);
70b31c4c8   Marco Stornelli   hpfs: drop vmtrun...
143
  }
d6091b720   Nick Piggin   hpfs: convert to ...
144
145
146
  static int hpfs_write_begin(struct file *file, struct address_space *mapping,
  			loff_t pos, unsigned len, unsigned flags,
  			struct page **pagep, void **fsdata)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  {
282dc1788   Christoph Hellwig   get rid of cont_w...
148
  	int ret;
d6091b720   Nick Piggin   hpfs: convert to ...
149
  	*pagep = NULL;
282dc1788   Christoph Hellwig   get rid of cont_w...
150
  	ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
d6091b720   Nick Piggin   hpfs: convert to ...
151
152
  				hpfs_get_block,
  				&hpfs_i(mapping->host)->mmu_private);
70b31c4c8   Marco Stornelli   hpfs: drop vmtrun...
153
154
  	if (unlikely(ret))
  		hpfs_write_failed(mapping, pos + len);
282dc1788   Christoph Hellwig   get rid of cont_w...
155
156
  
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  }
d6091b720   Nick Piggin   hpfs: convert to ...
158

5f2e354f5   Al Viro   hpfs: move settin...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  static int hpfs_write_end(struct file *file, struct address_space *mapping,
  			loff_t pos, unsigned len, unsigned copied,
  			struct page *pagep, void *fsdata)
  {
  	struct inode *inode = mapping->host;
  	int err;
  	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
  	if (err < len)
  		hpfs_write_failed(mapping, pos + len);
  	if (!(err < 0)) {
  		/* make sure we write it on close, if not earlier */
  		hpfs_lock(inode->i_sb);
  		hpfs_i(inode)->i_dirty = 1;
  		hpfs_unlock(inode->i_sb);
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
  static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
  {
a64eefaac   Mikulas Patocka   hpfs: support hot...
178
  	return generic_block_bmap(mapping, block, hpfs_get_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  }
d6091b720   Nick Piggin   hpfs: convert to ...
180

f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
181
  const struct address_space_operations hpfs_aops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
  	.readpage = hpfs_readpage,
  	.writepage = hpfs_writepage,
a0c1b7596   Mikulas Patocka   hpfs: use mpage
184
185
  	.readpages = hpfs_readpages,
  	.writepages = hpfs_writepages,
d6091b720   Nick Piggin   hpfs: convert to ...
186
  	.write_begin = hpfs_write_begin,
5f2e354f5   Al Viro   hpfs: move settin...
187
  	.write_end = hpfs_write_end,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
  	.bmap = _hpfs_bmap
  };
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
190
  const struct file_operations hpfs_file_ops =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
  {
  	.llseek		= generic_file_llseek,
aad4f8bb4   Al Viro   switch simple gen...
193
  	.read_iter	= generic_file_read_iter,
8174202b3   Al Viro   write_iter varian...
194
  	.write_iter	= generic_file_write_iter,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
  	.mmap		= generic_file_mmap,
  	.release	= hpfs_file_release,
  	.fsync		= hpfs_file_fsync,
5ffc4ef45   Jens Axboe   sendfile: remove ...
198
  	.splice_read	= generic_file_splice_read,
a27b5b97d   Mikulas Patocka   hpfs: add fstrim ...
199
  	.unlocked_ioctl	= hpfs_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  };
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
201
  const struct inode_operations hpfs_file_iops =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  {
ca30bc995   Christoph Hellwig   [PATCH] hpfs: cle...
203
  	.setattr	= hpfs_setattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  };