• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   *  linux/fs/ufs/util.c
3   *
4   * Copyright (C) 1998
5   * Daniel Pirkl <daniel.pirkl@email.cz>
6   * Charles University, Faculty of Mathematics and Physics
7   */
8  
9  #include <linux/string.h>
10  #include <linux/slab.h>
11  #include <linux/buffer_head.h>
12  
13  #include "ufs_fs.h"
14  #include "ufs.h"
15  #include "swab.h"
16  #include "util.h"
17  
_ubh_bread_(struct ufs_sb_private_info * uspi,struct super_block * sb,u64 fragment,u64 size)18  struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
19  	struct super_block *sb, u64 fragment, u64 size)
20  {
21  	struct ufs_buffer_head * ubh;
22  	unsigned i, j ;
23  	u64  count = 0;
24  	if (size & ~uspi->s_fmask)
25  		return NULL;
26  	count = size >> uspi->s_fshift;
27  	if (count > UFS_MAXFRAG)
28  		return NULL;
29  	ubh = kmalloc (sizeof (struct ufs_buffer_head), GFP_NOFS);
30  	if (!ubh)
31  		return NULL;
32  	ubh->fragment = fragment;
33  	ubh->count = count;
34  	for (i = 0; i < count; i++)
35  		if (!(ubh->bh[i] = sb_bread(sb, fragment + i)))
36  			goto failed;
37  	for (; i < UFS_MAXFRAG; i++)
38  		ubh->bh[i] = NULL;
39  	return ubh;
40  failed:
41  	for (j = 0; j < i; j++)
42  		brelse (ubh->bh[j]);
43  	kfree(ubh);
44  	return NULL;
45  }
46  
ubh_bread_uspi(struct ufs_sb_private_info * uspi,struct super_block * sb,u64 fragment,u64 size)47  struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi,
48  	struct super_block *sb, u64 fragment, u64 size)
49  {
50  	unsigned i, j;
51  	u64 count = 0;
52  	if (size & ~uspi->s_fmask)
53  		return NULL;
54  	count = size >> uspi->s_fshift;
55  	if (count <= 0 || count > UFS_MAXFRAG)
56  		return NULL;
57  	USPI_UBH(uspi)->fragment = fragment;
58  	USPI_UBH(uspi)->count = count;
59  	for (i = 0; i < count; i++)
60  		if (!(USPI_UBH(uspi)->bh[i] = sb_bread(sb, fragment + i)))
61  			goto failed;
62  	for (; i < UFS_MAXFRAG; i++)
63  		USPI_UBH(uspi)->bh[i] = NULL;
64  	return USPI_UBH(uspi);
65  failed:
66  	for (j = 0; j < i; j++)
67  		brelse (USPI_UBH(uspi)->bh[j]);
68  	return NULL;
69  }
70  
ubh_brelse(struct ufs_buffer_head * ubh)71  void ubh_brelse (struct ufs_buffer_head * ubh)
72  {
73  	unsigned i;
74  	if (!ubh)
75  		return;
76  	for (i = 0; i < ubh->count; i++)
77  		brelse (ubh->bh[i]);
78  	kfree (ubh);
79  }
80  
ubh_brelse_uspi(struct ufs_sb_private_info * uspi)81  void ubh_brelse_uspi (struct ufs_sb_private_info * uspi)
82  {
83  	unsigned i;
84  	if (!USPI_UBH(uspi))
85  		return;
86  	for ( i = 0; i < USPI_UBH(uspi)->count; i++ ) {
87  		brelse (USPI_UBH(uspi)->bh[i]);
88  		USPI_UBH(uspi)->bh[i] = NULL;
89  	}
90  }
91  
ubh_mark_buffer_dirty(struct ufs_buffer_head * ubh)92  void ubh_mark_buffer_dirty (struct ufs_buffer_head * ubh)
93  {
94  	unsigned i;
95  	if (!ubh)
96  		return;
97  	for ( i = 0; i < ubh->count; i++ )
98  		mark_buffer_dirty (ubh->bh[i]);
99  }
100  
ubh_mark_buffer_uptodate(struct ufs_buffer_head * ubh,int flag)101  void ubh_mark_buffer_uptodate (struct ufs_buffer_head * ubh, int flag)
102  {
103  	unsigned i;
104  	if (!ubh)
105  		return;
106  	if (flag) {
107  		for ( i = 0; i < ubh->count; i++ )
108  			set_buffer_uptodate (ubh->bh[i]);
109  	} else {
110  		for ( i = 0; i < ubh->count; i++ )
111  			clear_buffer_uptodate (ubh->bh[i]);
112  	}
113  }
114  
ubh_sync_block(struct ufs_buffer_head * ubh)115  void ubh_sync_block(struct ufs_buffer_head *ubh)
116  {
117  	if (ubh) {
118  		unsigned i;
119  
120  		for (i = 0; i < ubh->count; i++)
121  			write_dirty_buffer(ubh->bh[i], 0);
122  
123  		for (i = 0; i < ubh->count; i++)
124  			wait_on_buffer(ubh->bh[i]);
125  	}
126  }
127  
ubh_bforget(struct ufs_buffer_head * ubh)128  void ubh_bforget (struct ufs_buffer_head * ubh)
129  {
130  	unsigned i;
131  	if (!ubh)
132  		return;
133  	for ( i = 0; i < ubh->count; i++ ) if ( ubh->bh[i] )
134  		bforget (ubh->bh[i]);
135  }
136  
ubh_buffer_dirty(struct ufs_buffer_head * ubh)137  int ubh_buffer_dirty (struct ufs_buffer_head * ubh)
138  {
139  	unsigned i;
140  	unsigned result = 0;
141  	if (!ubh)
142  		return 0;
143  	for ( i = 0; i < ubh->count; i++ )
144  		result |= buffer_dirty(ubh->bh[i]);
145  	return result;
146  }
147  
_ubh_ubhcpymem_(struct ufs_sb_private_info * uspi,unsigned char * mem,struct ufs_buffer_head * ubh,unsigned size)148  void _ubh_ubhcpymem_(struct ufs_sb_private_info * uspi,
149  	unsigned char * mem, struct ufs_buffer_head * ubh, unsigned size)
150  {
151  	unsigned len, bhno;
152  	if (size > (ubh->count << uspi->s_fshift))
153  		size = ubh->count << uspi->s_fshift;
154  	bhno = 0;
155  	while (size) {
156  		len = min_t(unsigned int, size, uspi->s_fsize);
157  		memcpy (mem, ubh->bh[bhno]->b_data, len);
158  		mem += uspi->s_fsize;
159  		size -= len;
160  		bhno++;
161  	}
162  }
163  
_ubh_memcpyubh_(struct ufs_sb_private_info * uspi,struct ufs_buffer_head * ubh,unsigned char * mem,unsigned size)164  void _ubh_memcpyubh_(struct ufs_sb_private_info * uspi,
165  	struct ufs_buffer_head * ubh, unsigned char * mem, unsigned size)
166  {
167  	unsigned len, bhno;
168  	if (size > (ubh->count << uspi->s_fshift))
169  		size = ubh->count << uspi->s_fshift;
170  	bhno = 0;
171  	while (size) {
172  		len = min_t(unsigned int, size, uspi->s_fsize);
173  		memcpy (ubh->bh[bhno]->b_data, mem, len);
174  		mem += uspi->s_fsize;
175  		size -= len;
176  		bhno++;
177  	}
178  }
179  
180  dev_t
ufs_get_inode_dev(struct super_block * sb,struct ufs_inode_info * ufsi)181  ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi)
182  {
183  	__u32 fs32;
184  	dev_t dev;
185  
186  	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
187  		fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[1]);
188  	else
189  		fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[0]);
190  	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
191  	case UFS_ST_SUNx86:
192  	case UFS_ST_SUN:
193  		if ((fs32 & 0xffff0000) == 0 ||
194  		    (fs32 & 0xffff0000) == 0xffff0000)
195  			dev = old_decode_dev(fs32 & 0x7fff);
196  		else
197  			dev = MKDEV(sysv_major(fs32), sysv_minor(fs32));
198  		break;
199  
200  	default:
201  		dev = old_decode_dev(fs32);
202  		break;
203  	}
204  	return dev;
205  }
206  
207  void
ufs_set_inode_dev(struct super_block * sb,struct ufs_inode_info * ufsi,dev_t dev)208  ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev)
209  {
210  	__u32 fs32;
211  
212  	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
213  	case UFS_ST_SUNx86:
214  	case UFS_ST_SUN:
215  		fs32 = sysv_encode_dev(dev);
216  		if ((fs32 & 0xffff8000) == 0) {
217  			fs32 = old_encode_dev(dev);
218  		}
219  		break;
220  
221  	default:
222  		fs32 = old_encode_dev(dev);
223  		break;
224  	}
225  	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
226  		ufsi->i_u1.i_data[1] = cpu_to_fs32(sb, fs32);
227  	else
228  		ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32);
229  }
230  
231  /**
232   * ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist
233   * read it from disk.
234   * @mapping: the address_space to search
235   * @index: the page index
236   *
237   * Locates the desired pagecache page, if not exist we'll read it,
238   * locks it, increments its reference
239   * count and returns its address.
240   *
241   */
242  
ufs_get_locked_page(struct address_space * mapping,pgoff_t index)243  struct page *ufs_get_locked_page(struct address_space *mapping,
244  				 pgoff_t index)
245  {
246  	struct page *page;
247  
248  	page = find_lock_page(mapping, index);
249  	if (!page) {
250  		page = read_mapping_page(mapping, index, NULL);
251  
252  		if (IS_ERR(page)) {
253  			printk(KERN_ERR "ufs_change_blocknr: "
254  			       "read_mapping_page error: ino %lu, index: %lu\n",
255  			       mapping->host->i_ino, index);
256  			goto out;
257  		}
258  
259  		lock_page(page);
260  
261  		if (unlikely(page->mapping == NULL)) {
262  			/* Truncate got there first */
263  			unlock_page(page);
264  			put_page(page);
265  			page = NULL;
266  			goto out;
267  		}
268  
269  		if (!PageUptodate(page) || PageError(page)) {
270  			unlock_page(page);
271  			put_page(page);
272  
273  			printk(KERN_ERR "ufs_change_blocknr: "
274  			       "can not read page: ino %lu, index: %lu\n",
275  			       mapping->host->i_ino, index);
276  
277  			page = ERR_PTR(-EIO);
278  		}
279  	}
280  out:
281  	return page;
282  }
283