Blame view

fs/ufs/util.c 6.14 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
  /*
   *  linux/fs/ufs/util.c
   *
   * Copyright (C) 1998
   * Daniel Pirkl <daniel.pirkl@email.cz>
   * Charles University, Faculty of Mathematics and Physics
   */
   
  #include <linux/string.h>
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
  #include <linux/buffer_head.h>
e54205988   Mike Frysinger   drop linux/ufs_fs...
13
  #include "ufs_fs.h"
bcd6d4ecf   Christoph Hellwig   ufs: move non-lay...
14
  #include "ufs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
  #include "swab.h"
  #include "util.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
22
23
24
25
26
27
  struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
  	struct super_block *sb, u64 fragment, u64 size)
  {
  	struct ufs_buffer_head * ubh;
  	unsigned i, j ;
  	u64  count = 0;
  	if (size & ~uspi->s_fmask)
  		return NULL;
  	count = size >> uspi->s_fshift;
  	if (count > UFS_MAXFRAG)
  		return NULL;
194c8767c   Zhang Yanfei   fs: ufs: remove c...
28
  	ubh = kmalloc (sizeof (struct ufs_buffer_head), GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  	if (!ubh)
  		return NULL;
  	ubh->fragment = fragment;
  	ubh->count = count;
  	for (i = 0; i < count; i++)
  		if (!(ubh->bh[i] = sb_bread(sb, fragment + i)))
  			goto failed;
  	for (; i < UFS_MAXFRAG; i++)
  		ubh->bh[i] = NULL;
  	return ubh;
  failed:
  	for (j = 0; j < i; j++)
  		brelse (ubh->bh[j]);
  	kfree(ubh);
  	return NULL;
  }
  
  struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi,
  	struct super_block *sb, u64 fragment, u64 size)
  {
  	unsigned i, j;
  	u64 count = 0;
  	if (size & ~uspi->s_fmask)
  		return NULL;
  	count = size >> uspi->s_fshift;
  	if (count <= 0 || count > UFS_MAXFRAG)
  		return NULL;
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
56
57
  	USPI_UBH(uspi)->fragment = fragment;
  	USPI_UBH(uspi)->count = count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  	for (i = 0; i < count; i++)
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
59
  		if (!(USPI_UBH(uspi)->bh[i] = sb_bread(sb, fragment + i)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
  			goto failed;
  	for (; i < UFS_MAXFRAG; i++)
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
62
63
  		USPI_UBH(uspi)->bh[i] = NULL;
  	return USPI_UBH(uspi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
  failed:
  	for (j = 0; j < i; j++)
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
66
  		brelse (USPI_UBH(uspi)->bh[j]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  	return NULL;
  }
  
  void ubh_brelse (struct ufs_buffer_head * ubh)
  {
  	unsigned i;
  	if (!ubh)
  		return;
  	for (i = 0; i < ubh->count; i++)
  		brelse (ubh->bh[i]);
  	kfree (ubh);
  }
  
  void ubh_brelse_uspi (struct ufs_sb_private_info * uspi)
  {
  	unsigned i;
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
83
  	if (!USPI_UBH(uspi))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  		return;
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
85
86
87
  	for ( i = 0; i < USPI_UBH(uspi)->count; i++ ) {
  		brelse (USPI_UBH(uspi)->bh[i]);
  		USPI_UBH(uspi)->bh[i] = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  	}
  }
  
  void ubh_mark_buffer_dirty (struct ufs_buffer_head * ubh)
  {
  	unsigned i;
  	if (!ubh)
  		return;
  	for ( i = 0; i < ubh->count; i++ )
  		mark_buffer_dirty (ubh->bh[i]);
  }
  
  void ubh_mark_buffer_uptodate (struct ufs_buffer_head * ubh, int flag)
  {
  	unsigned i;
  	if (!ubh)
  		return;
  	if (flag) {
  		for ( i = 0; i < ubh->count; i++ )
  			set_buffer_uptodate (ubh->bh[i]);
  	} else {
  		for ( i = 0; i < ubh->count; i++ )
  			clear_buffer_uptodate (ubh->bh[i]);
  	}
  }
9cb569d60   Christoph Hellwig   remove SWRITE* I/...
113
  void ubh_sync_block(struct ufs_buffer_head *ubh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  {
9cb569d60   Christoph Hellwig   remove SWRITE* I/...
115
116
  	if (ubh) {
  		unsigned i;
098d5af7b   Evgeniy Dushistov   [PATCH] ufs: ubh_...
117

9cb569d60   Christoph Hellwig   remove SWRITE* I/...
118
  		for (i = 0; i < ubh->count; i++)
2a222ca99   Mike Christie   fs: have submit_b...
119
  			write_dirty_buffer(ubh->bh[i], 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120

9cb569d60   Christoph Hellwig   remove SWRITE* I/...
121
122
123
  		for (i = 0; i < ubh->count; i++)
  			wait_on_buffer(ubh->bh[i]);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  void ubh_bforget (struct ufs_buffer_head * ubh)
  {
  	unsigned i;
  	if (!ubh) 
  		return;
  	for ( i = 0; i < ubh->count; i++ ) if ( ubh->bh[i] ) 
  		bforget (ubh->bh[i]);
  }
   
  int ubh_buffer_dirty (struct ufs_buffer_head * ubh)
  {
  	unsigned i;
  	unsigned result = 0;
  	if (!ubh)
  		return 0;
  	for ( i = 0; i < ubh->count; i++ )
  		result |= buffer_dirty(ubh->bh[i]);
  	return result;
  }
  
  void _ubh_ubhcpymem_(struct ufs_sb_private_info * uspi, 
  	unsigned char * mem, struct ufs_buffer_head * ubh, unsigned size)
  {
  	unsigned len, bhno;
  	if (size > (ubh->count << uspi->s_fshift))
  		size = ubh->count << uspi->s_fshift;
  	bhno = 0;
  	while (size) {
  		len = min_t(unsigned int, size, uspi->s_fsize);
  		memcpy (mem, ubh->bh[bhno]->b_data, len);
  		mem += uspi->s_fsize;
  		size -= len;
  		bhno++;
  	}
  }
  
  void _ubh_memcpyubh_(struct ufs_sb_private_info * uspi, 
  	struct ufs_buffer_head * ubh, unsigned char * mem, unsigned size)
  {
  	unsigned len, bhno;
  	if (size > (ubh->count << uspi->s_fshift))
  		size = ubh->count << uspi->s_fshift;
  	bhno = 0;
  	while (size) {
  		len = min_t(unsigned int, size, uspi->s_fsize);
  		memcpy (ubh->bh[bhno]->b_data, mem, len);
  		mem += uspi->s_fsize;
  		size -= len;
  		bhno++;
  	}
  }
  
  dev_t
  ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi)
  {
44aa5359b   Al Viro   [PATCH] ufs endia...
180
  	__u32 fs32;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
  	dev_t dev;
  
  	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
44aa5359b   Al Viro   [PATCH] ufs endia...
184
  		fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[1]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  	else
44aa5359b   Al Viro   [PATCH] ufs endia...
186
  		fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
  	case UFS_ST_SUNx86:
  	case UFS_ST_SUN:
  		if ((fs32 & 0xffff0000) == 0 ||
  		    (fs32 & 0xffff0000) == 0xffff0000)
  			dev = old_decode_dev(fs32 & 0x7fff);
  		else
  			dev = MKDEV(sysv_major(fs32), sysv_minor(fs32));
  		break;
  
  	default:
  		dev = old_decode_dev(fs32);
  		break;
  	}
  	return dev;
  }
  
  void
  ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev)
  {
44aa5359b   Al Viro   [PATCH] ufs endia...
207
  	__u32 fs32;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  
  	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
  	case UFS_ST_SUNx86:
  	case UFS_ST_SUN:
  		fs32 = sysv_encode_dev(dev);
  		if ((fs32 & 0xffff8000) == 0) {
  			fs32 = old_encode_dev(dev);
  		}
  		break;
  
  	default:
  		fs32 = old_encode_dev(dev);
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
44aa5359b   Al Viro   [PATCH] ufs endia...
223
  		ufsi->i_u1.i_data[1] = cpu_to_fs32(sb, fs32);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  	else
44aa5359b   Al Viro   [PATCH] ufs endia...
225
  		ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  }
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  
  /**
   * ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist
   * read it from disk.
   * @mapping: the address_space to search
   * @index: the page index
   *
   * Locates the desired pagecache page, if not exist we'll read it,
   * locks it, increments its reference
   * count and returns its address.
   *
   */
  
  struct page *ufs_get_locked_page(struct address_space *mapping,
  				 pgoff_t index)
  {
267309f39   Al Viro   ufs_get_locked_pa...
243
244
  	struct inode *inode = mapping->host;
  	struct page *page = find_lock_page(mapping, index);
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
245
  	if (!page) {
6fe6900e1   Nick Piggin   mm: make read_cac...
246
  		page = read_mapping_page(mapping, index, NULL);
1fb32b7bd   Evgeniy Dushistov   [PATCH] ufs: ufs_...
247

10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
248
249
  		if (IS_ERR(page)) {
  			printk(KERN_ERR "ufs_change_blocknr: "
6fe6900e1   Nick Piggin   mm: make read_cac...
250
251
  			       "read_mapping_page error: ino %lu, index: %lu
  ",
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
252
  			       mapping->host->i_ino, index);
267309f39   Al Viro   ufs_get_locked_pa...
253
  			return page;
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
254
255
256
  		}
  
  		lock_page(page);
1fb32b7bd   Evgeniy Dushistov   [PATCH] ufs: ufs_...
257
258
259
  		if (unlikely(page->mapping == NULL)) {
  			/* Truncate got there first */
  			unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
260
  			put_page(page);
267309f39   Al Viro   ufs_get_locked_pa...
261
  			return NULL;
1fb32b7bd   Evgeniy Dushistov   [PATCH] ufs: ufs_...
262
  		}
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
263
264
  		if (!PageUptodate(page) || PageError(page)) {
  			unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
265
  			put_page(page);
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
266
267
268
269
  
  			printk(KERN_ERR "ufs_change_blocknr: "
  			       "can not read page: ino %lu, index: %lu
  ",
267309f39   Al Viro   ufs_get_locked_pa...
270
  			       inode->i_ino, index);
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
271

267309f39   Al Viro   ufs_get_locked_pa...
272
  			return ERR_PTR(-EIO);
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
273
274
  		}
  	}
267309f39   Al Viro   ufs_get_locked_pa...
275
276
  	if (!page_has_buffers(page))
  		create_empty_buffers(page, 1 << inode->i_blkbits, 0);
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
277
278
  	return page;
  }