Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / fs / hpfs / file.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  linux/fs/hpfs/file.c
4  *
5  *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
6  *
7  *  file VFS functions
8  */
9
10 #include "hpfs_fn.h"
11 #include <linux/mpage.h>
12
13 #define BLOCKS(size) (((size) + 511) >> 9)
14
15 static int hpfs_file_release(struct inode *inode, struct file *file)
16 {
17         hpfs_lock(inode->i_sb);
18         hpfs_write_if_changed(inode);
19         hpfs_unlock(inode->i_sb);
20         return 0;
21 }
22
23 int hpfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
24 {
25         struct inode *inode = file->f_mapping->host;
26         int ret;
27
28         ret = file_write_and_wait_range(file, start, end);
29         if (ret)
30                 return ret;
31         return sync_blockdev(inode->i_sb->s_bdev);
32 }
33
34 /*
35  * generic_file_read often calls bmap with non-existing sector,
36  * so we must ignore such errors.
37  */
38
39 static secno hpfs_bmap(struct inode *inode, unsigned file_secno, unsigned *n_secs)
40 {
41         struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
42         unsigned n, disk_secno;
43         struct fnode *fnode;
44         struct buffer_head *bh;
45         if (BLOCKS(hpfs_i(inode)->mmu_private) <= file_secno) return 0;
46         n = file_secno - hpfs_inode->i_file_sec;
47         if (n < hpfs_inode->i_n_secs) {
48                 *n_secs = hpfs_inode->i_n_secs - n;
49                 return hpfs_inode->i_disk_sec + n;
50         }
51         if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) return 0;
52         disk_secno = hpfs_bplus_lookup(inode->i_sb, inode, &fnode->btree, file_secno, bh);
53         if (disk_secno == -1) return 0;
54         if (hpfs_chk_sectors(inode->i_sb, disk_secno, 1, "bmap")) return 0;
55         n = file_secno - hpfs_inode->i_file_sec;
56         if (n < hpfs_inode->i_n_secs) {
57                 *n_secs = hpfs_inode->i_n_secs - n;
58                 return hpfs_inode->i_disk_sec + n;
59         }
60         *n_secs = 1;
61         return disk_secno;
62 }
63
64 void hpfs_truncate(struct inode *i)
65 {
66         if (IS_IMMUTABLE(i)) return /*-EPERM*/;
67         hpfs_lock_assert(i->i_sb);
68
69         hpfs_i(i)->i_n_secs = 0;
70         i->i_blocks = 1 + ((i->i_size + 511) >> 9);
71         hpfs_i(i)->mmu_private = i->i_size;
72         hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
73         hpfs_write_inode(i);
74         hpfs_i(i)->i_n_secs = 0;
75 }
76
77 static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
78 {
79         int r;
80         secno s;
81         unsigned n_secs;
82         hpfs_lock(inode->i_sb);
83         s = hpfs_bmap(inode, iblock, &n_secs);
84         if (s) {
85                 if (bh_result->b_size >> 9 < n_secs)
86                         n_secs = bh_result->b_size >> 9;
87                 n_secs = hpfs_search_hotfix_map_for_range(inode->i_sb, s, n_secs);
88                 if (unlikely(!n_secs)) {
89                         s = hpfs_search_hotfix_map(inode->i_sb, s);
90                         n_secs = 1;
91                 }
92                 map_bh(bh_result, inode->i_sb, s);
93                 bh_result->b_size = n_secs << 9;
94                 goto ret_0;
95         }
96         if (!create) goto ret_0;
97         if (iblock<<9 != hpfs_i(inode)->mmu_private) {
98                 BUG();
99                 r = -EIO;
100                 goto ret_r;
101         }
102         if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) {
103                 hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1);
104                 r = -ENOSPC;
105                 goto ret_r;
106         }
107         inode->i_blocks++;
108         hpfs_i(inode)->mmu_private += 512;
109         set_buffer_new(bh_result);
110         map_bh(bh_result, inode->i_sb, hpfs_search_hotfix_map(inode->i_sb, s));
111         ret_0:
112         r = 0;
113         ret_r:
114         hpfs_unlock(inode->i_sb);
115         return r;
116 }
117
118 static int hpfs_readpage(struct file *file, struct page *page)
119 {
120         return mpage_readpage(page, hpfs_get_block);
121 }
122
123 static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
124 {
125         return block_write_full_page(page, hpfs_get_block, wbc);
126 }
127
128 static int hpfs_readpages(struct file *file, struct address_space *mapping,
129                           struct list_head *pages, unsigned nr_pages)
130 {
131         return mpage_readpages(mapping, pages, nr_pages, hpfs_get_block);
132 }
133
134 static int hpfs_writepages(struct address_space *mapping,
135                            struct writeback_control *wbc)
136 {
137         return mpage_writepages(mapping, wbc, hpfs_get_block);
138 }
139
140 static void hpfs_write_failed(struct address_space *mapping, loff_t to)
141 {
142         struct inode *inode = mapping->host;
143
144         hpfs_lock(inode->i_sb);
145
146         if (to > inode->i_size) {
147                 truncate_pagecache(inode, inode->i_size);
148                 hpfs_truncate(inode);
149         }
150
151         hpfs_unlock(inode->i_sb);
152 }
153
154 static int hpfs_write_begin(struct file *file, struct address_space *mapping,
155                         loff_t pos, unsigned len, unsigned flags,
156                         struct page **pagep, void **fsdata)
157 {
158         int ret;
159
160         *pagep = NULL;
161         ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
162                                 hpfs_get_block,
163                                 &hpfs_i(mapping->host)->mmu_private);
164         if (unlikely(ret))
165                 hpfs_write_failed(mapping, pos + len);
166
167         return ret;
168 }
169
170 static int hpfs_write_end(struct file *file, struct address_space *mapping,
171                         loff_t pos, unsigned len, unsigned copied,
172                         struct page *pagep, void *fsdata)
173 {
174         struct inode *inode = mapping->host;
175         int err;
176         err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
177         if (err < len)
178                 hpfs_write_failed(mapping, pos + len);
179         if (!(err < 0)) {
180                 /* make sure we write it on close, if not earlier */
181                 hpfs_lock(inode->i_sb);
182                 hpfs_i(inode)->i_dirty = 1;
183                 hpfs_unlock(inode->i_sb);
184         }
185         return err;
186 }
187
188 static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
189 {
190         return generic_block_bmap(mapping, block, hpfs_get_block);
191 }
192
193 static int hpfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len)
194 {
195         return generic_block_fiemap(inode, fieinfo, start, len, hpfs_get_block);
196 }
197
198 const struct address_space_operations hpfs_aops = {
199         .readpage = hpfs_readpage,
200         .writepage = hpfs_writepage,
201         .readpages = hpfs_readpages,
202         .writepages = hpfs_writepages,
203         .write_begin = hpfs_write_begin,
204         .write_end = hpfs_write_end,
205         .bmap = _hpfs_bmap
206 };
207
208 const struct file_operations hpfs_file_ops =
209 {
210         .llseek         = generic_file_llseek,
211         .read_iter      = generic_file_read_iter,
212         .write_iter     = generic_file_write_iter,
213         .mmap           = generic_file_mmap,
214         .release        = hpfs_file_release,
215         .fsync          = hpfs_file_fsync,
216         .splice_read    = generic_file_splice_read,
217         .unlocked_ioctl = hpfs_ioctl,
218 };
219
220 const struct inode_operations hpfs_file_iops =
221 {
222         .setattr        = hpfs_setattr,
223         .fiemap         = hpfs_fiemap,
224 };