aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jfs/Kconfig1
-rw-r--r--fs/jfs/jfs_extent.c63
-rw-r--r--fs/jfs/jfs_imap.c10
-rw-r--r--fs/jfs/jfs_metapage.c18
-rw-r--r--fs/jfs/jfs_types.h29
-rw-r--r--fs/jfs/jfs_xtree.c263
-rw-r--r--fs/jfs/jfs_xtree.h2
-rw-r--r--fs/jfs/super.c4
8 files changed, 46 insertions, 344 deletions
diff --git a/fs/jfs/Kconfig b/fs/jfs/Kconfig
index 9ff619a6f9cc..57cef19951db 100644
--- a/fs/jfs/Kconfig
+++ b/fs/jfs/Kconfig
@@ -1,6 +1,7 @@
1config JFS_FS 1config JFS_FS
2 tristate "JFS filesystem support" 2 tristate "JFS filesystem support"
3 select NLS 3 select NLS
4 select CRC32
4 help 5 help
5 This is a port of IBM's Journaled Filesystem . More information is 6 This is a port of IBM's Journaled Filesystem . More information is
6 available in the file <file:Documentation/filesystems/jfs.txt>. 7 available in the file <file:Documentation/filesystems/jfs.txt>.
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 169802ea07f9..bbbd5f202e37 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -362,11 +362,12 @@ exit:
362int extHint(struct inode *ip, s64 offset, xad_t * xp) 362int extHint(struct inode *ip, s64 offset, xad_t * xp)
363{ 363{
364 struct super_block *sb = ip->i_sb; 364 struct super_block *sb = ip->i_sb;
365 struct xadlist xadl; 365 int nbperpage = JFS_SBI(sb)->nbperpage;
366 struct lxdlist lxdl;
367 lxd_t lxd;
368 s64 prev; 366 s64 prev;
369 int rc, nbperpage = JFS_SBI(sb)->nbperpage; 367 int rc = 0;
368 s64 xaddr;
369 int xlen;
370 int xflag;
370 371
371 /* init the hint as "no hint provided" */ 372 /* init the hint as "no hint provided" */
372 XADaddress(xp, 0); 373 XADaddress(xp, 0);
@@ -376,46 +377,30 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp)
376 */ 377 */
377 prev = ((offset & ~POFFSET) >> JFS_SBI(sb)->l2bsize) - nbperpage; 378 prev = ((offset & ~POFFSET) >> JFS_SBI(sb)->l2bsize) - nbperpage;
378 379
379 /* if the offsets in the first page of the file, 380 /* if the offset is in the first page of the file, no hint provided.
380 * no hint provided.
381 */ 381 */
382 if (prev < 0) 382 if (prev < 0)
383 return (0); 383 goto out;
384
385 /* prepare to lookup the previous page's extent info */
386 lxdl.maxnlxd = 1;
387 lxdl.nlxd = 1;
388 lxdl.lxd = &lxd;
389 LXDoffset(&lxd, prev)
390 LXDlength(&lxd, nbperpage);
391
392 xadl.maxnxad = 1;
393 xadl.nxad = 0;
394 xadl.xad = xp;
395
396 /* perform the lookup */
397 if ((rc = xtLookupList(ip, &lxdl, &xadl, 0)))
398 return (rc);
399
400 /* check if no extent exists for the previous page.
401 * this is possible for sparse files.
402 */
403 if (xadl.nxad == 0) {
404// assert(ISSPARSE(ip));
405 return (0);
406 }
407 384
408 /* only preserve the abnr flag within the xad flags 385 rc = xtLookup(ip, prev, nbperpage, &xflag, &xaddr, &xlen, 0);
409 * of the returned hint.
410 */
411 xp->flag &= XAD_NOTRECORDED;
412 386
413 if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) { 387 if ((rc == 0) && xlen) {
414 jfs_error(ip->i_sb, "extHint: corrupt xtree"); 388 if (xlen != nbperpage) {
415 return -EIO; 389 jfs_error(ip->i_sb, "extHint: corrupt xtree");
416 } 390 rc = -EIO;
391 }
392 XADaddress(xp, xaddr);
393 XADlength(xp, xlen);
394 /*
395 * only preserve the abnr flag within the xad flags
396 * of the returned hint.
397 */
398 xp->flag = xflag & XAD_NOTRECORDED;
399 } else
400 rc = 0;
417 401
418 return (0); 402out:
403 return (rc);
419} 404}
420 405
421 406
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 0f94381ca6d0..346057218edc 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -57,12 +57,6 @@
57#include "jfs_debug.h" 57#include "jfs_debug.h"
58 58
59/* 59/*
60 * __mark_inode_dirty expects inodes to be hashed. Since we don't want
61 * special inodes in the fileset inode space, we make them appear hashed,
62 * but do not put on any lists.
63 */
64
65/*
66 * imap locks 60 * imap locks
67 */ 61 */
68/* iag free list lock */ 62/* iag free list lock */
@@ -497,7 +491,9 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
497 release_metapage(mp); 491 release_metapage(mp);
498 492
499 /* 493 /*
500 * that will look hashed, but won't be on any list; hlist_del() 494 * __mark_inode_dirty expects inodes to be hashed. Since we don't
495 * want special inodes in the fileset inode space, we make them
496 * appear hashed, but do not put on any lists. hlist_del()
501 * will work fine and require no locking. 497 * will work fine and require no locking.
502 */ 498 */
503 ip->i_hash.pprev = &ip->i_hash.next; 499 ip->i_hash.pprev = &ip->i_hash.next;
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index c350057087dd..07b6c5dfb4b6 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -369,6 +369,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc)
369 unsigned long bio_bytes = 0; 369 unsigned long bio_bytes = 0;
370 unsigned long bio_offset = 0; 370 unsigned long bio_offset = 0;
371 int offset; 371 int offset;
372 int bad_blocks = 0;
372 373
373 page_start = (sector_t)page->index << 374 page_start = (sector_t)page->index <<
374 (PAGE_CACHE_SHIFT - inode->i_blkbits); 375 (PAGE_CACHE_SHIFT - inode->i_blkbits);
@@ -394,6 +395,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc)
394 } 395 }
395 396
396 clear_bit(META_dirty, &mp->flag); 397 clear_bit(META_dirty, &mp->flag);
398 set_bit(META_io, &mp->flag);
397 block_offset = offset >> inode->i_blkbits; 399 block_offset = offset >> inode->i_blkbits;
398 lblock = page_start + block_offset; 400 lblock = page_start + block_offset;
399 if (bio) { 401 if (bio) {
@@ -402,7 +404,6 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc)
402 len = min(xlen, blocks_per_mp); 404 len = min(xlen, blocks_per_mp);
403 xlen -= len; 405 xlen -= len;
404 bio_bytes += len << inode->i_blkbits; 406 bio_bytes += len << inode->i_blkbits;
405 set_bit(META_io, &mp->flag);
406 continue; 407 continue;
407 } 408 }
408 /* Not contiguous */ 409 /* Not contiguous */
@@ -424,12 +425,14 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc)
424 xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits; 425 xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits;
425 pblock = metapage_get_blocks(inode, lblock, &xlen); 426 pblock = metapage_get_blocks(inode, lblock, &xlen);
426 if (!pblock) { 427 if (!pblock) {
427 /* Need better error handling */
428 printk(KERN_ERR "JFS: metapage_get_blocks failed\n"); 428 printk(KERN_ERR "JFS: metapage_get_blocks failed\n");
429 dec_io(page, last_write_complete); 429 /*
430 * We already called inc_io(), but can't cancel it
431 * with dec_io() until we're done with the page
432 */
433 bad_blocks++;
430 continue; 434 continue;
431 } 435 }
432 set_bit(META_io, &mp->flag);
433 len = min(xlen, (int)JFS_SBI(inode->i_sb)->nbperpage); 436 len = min(xlen, (int)JFS_SBI(inode->i_sb)->nbperpage);
434 437
435 bio = bio_alloc(GFP_NOFS, 1); 438 bio = bio_alloc(GFP_NOFS, 1);
@@ -459,6 +462,9 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc)
459 462
460 unlock_page(page); 463 unlock_page(page);
461 464
465 if (bad_blocks)
466 goto err_out;
467
462 if (nr_underway == 0) 468 if (nr_underway == 0)
463 end_page_writeback(page); 469 end_page_writeback(page);
464 470
@@ -474,7 +480,9 @@ skip:
474 bio_put(bio); 480 bio_put(bio);
475 unlock_page(page); 481 unlock_page(page);
476 dec_io(page, last_write_complete); 482 dec_io(page, last_write_complete);
477 483err_out:
484 while (bad_blocks--)
485 dec_io(page, last_write_complete);
478 return -EIO; 486 return -EIO;
479} 487}
480 488
diff --git a/fs/jfs/jfs_types.h b/fs/jfs/jfs_types.h
index 649f9817accd..43ea3713c083 100644
--- a/fs/jfs/jfs_types.h
+++ b/fs/jfs/jfs_types.h
@@ -58,35 +58,6 @@ struct timestruc_t {
58#define ONES 0xffffffffu /* all bit on */ 58#define ONES 0xffffffffu /* all bit on */
59 59
60/* 60/*
61 * logical xd (lxd)
62 */
63typedef struct {
64 unsigned len:24;
65 unsigned off1:8;
66 u32 off2;
67} lxd_t;
68
69/* lxd_t field construction */
70#define LXDlength(lxd, length32) ( (lxd)->len = length32 )
71#define LXDoffset(lxd, offset64)\
72{\
73 (lxd)->off1 = ((s64)offset64) >> 32;\
74 (lxd)->off2 = (offset64) & 0xffffffff;\
75}
76
77/* lxd_t field extraction */
78#define lengthLXD(lxd) ( (lxd)->len )
79#define offsetLXD(lxd)\
80 ( ((s64)((lxd)->off1)) << 32 | (lxd)->off2 )
81
82/* lxd list */
83struct lxdlist {
84 s16 maxnlxd;
85 s16 nlxd;
86 lxd_t *lxd;
87};
88
89/*
90 * physical xd (pxd) 61 * physical xd (pxd)
91 */ 62 */
92typedef struct { 63typedef struct {
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index a27e26c90568..d654a6458648 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -164,11 +164,8 @@ int xtLookup(struct inode *ip, s64 lstart,
164 /* is lookup offset beyond eof ? */ 164 /* is lookup offset beyond eof ? */
165 size = ((u64) ip->i_size + (JFS_SBI(ip->i_sb)->bsize - 1)) >> 165 size = ((u64) ip->i_size + (JFS_SBI(ip->i_sb)->bsize - 1)) >>
166 JFS_SBI(ip->i_sb)->l2bsize; 166 JFS_SBI(ip->i_sb)->l2bsize;
167 if (lstart >= size) { 167 if (lstart >= size)
168 jfs_err("xtLookup: lstart (0x%lx) >= size (0x%lx)",
169 (ulong) lstart, (ulong) size);
170 return 0; 168 return 0;
171 }
172 } 169 }
173 170
174 /* 171 /*
@@ -220,264 +217,6 @@ int xtLookup(struct inode *ip, s64 lstart,
220 return rc; 217 return rc;
221} 218}
222 219
223
224/*
225 * xtLookupList()
226 *
227 * function: map a single logical extent into a list of physical extent;
228 *
229 * parameter:
230 * struct inode *ip,
231 * struct lxdlist *lxdlist, lxd list (in)
232 * struct xadlist *xadlist, xad list (in/out)
233 * int flag)
234 *
235 * coverage of lxd by xad under assumption of
236 * . lxd's are ordered and disjoint.
237 * . xad's are ordered and disjoint.
238 *
239 * return:
240 * 0: success
241 *
242 * note: a page being written (even a single byte) is backed fully,
243 * except the last page which is only backed with blocks
244 * required to cover the last byte;
245 * the extent backing a page is fully contained within an xad;
246 */
247int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
248 struct xadlist * xadlist, int flag)
249{
250 int rc = 0;
251 struct btstack btstack;
252 int cmp;
253 s64 bn;
254 struct metapage *mp;
255 xtpage_t *p;
256 int index;
257 lxd_t *lxd;
258 xad_t *xad, *pxd;
259 s64 size, lstart, lend, xstart, xend, pstart;
260 s64 llen, xlen, plen;
261 s64 xaddr, paddr;
262 int nlxd, npxd, maxnpxd;
263
264 npxd = xadlist->nxad = 0;
265 maxnpxd = xadlist->maxnxad;
266 pxd = xadlist->xad;
267
268 nlxd = lxdlist->nlxd;
269 lxd = lxdlist->lxd;
270
271 lstart = offsetLXD(lxd);
272 llen = lengthLXD(lxd);
273 lend = lstart + llen;
274
275 size = (ip->i_size + (JFS_SBI(ip->i_sb)->bsize - 1)) >>
276 JFS_SBI(ip->i_sb)->l2bsize;
277
278 /*
279 * search for the xad entry covering the logical extent
280 */
281 search:
282 if (lstart >= size)
283 return 0;
284
285 if ((rc = xtSearch(ip, lstart, NULL, &cmp, &btstack, 0)))
286 return rc;
287
288 /*
289 * compute the physical extent covering logical extent
290 *
291 * N.B. search may have failed (e.g., hole in sparse file),
292 * and returned the index of the next entry.
293 */
294//map:
295 /* retrieve search result */
296 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
297
298 /* is xad on the next sibling page ? */
299 if (index == le16_to_cpu(p->header.nextindex)) {
300 if (p->header.flag & BT_ROOT)
301 goto mapend;
302
303 if ((bn = le64_to_cpu(p->header.next)) == 0)
304 goto mapend;
305
306 XT_PUTPAGE(mp);
307
308 /* get next sibling page */
309 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
310 if (rc)
311 return rc;
312
313 index = XTENTRYSTART;
314 }
315
316 xad = &p->xad[index];
317
318 /*
319 * is lxd covered by xad ?
320 */
321 compare:
322 xstart = offsetXAD(xad);
323 xlen = lengthXAD(xad);
324 xend = xstart + xlen;
325 xaddr = addressXAD(xad);
326
327 compare1:
328 if (xstart < lstart)
329 goto compare2;
330
331 /* (lstart <= xstart) */
332
333 /* lxd is NOT covered by xad */
334 if (lend <= xstart) {
335 /*
336 * get next lxd
337 */
338 if (--nlxd == 0)
339 goto mapend;
340 lxd++;
341
342 lstart = offsetLXD(lxd);
343 llen = lengthLXD(lxd);
344 lend = lstart + llen;
345 if (lstart >= size)
346 goto mapend;
347
348 /* compare with the current xad */
349 goto compare1;
350 }
351 /* lxd is covered by xad */
352 else { /* (xstart < lend) */
353
354 /* initialize new pxd */
355 pstart = xstart;
356 plen = min(lend - xstart, xlen);
357 paddr = xaddr;
358
359 goto cover;
360 }
361
362 /* (xstart < lstart) */
363 compare2:
364 /* lxd is covered by xad */
365 if (lstart < xend) {
366 /* initialize new pxd */
367 pstart = lstart;
368 plen = min(xend - lstart, llen);
369 paddr = xaddr + (lstart - xstart);
370
371 goto cover;
372 }
373 /* lxd is NOT covered by xad */
374 else { /* (xend <= lstart) */
375
376 /*
377 * get next xad
378 *
379 * linear search next xad covering lxd on
380 * the current xad page, and then tree search
381 */
382 if (index == le16_to_cpu(p->header.nextindex) - 1) {
383 if (p->header.flag & BT_ROOT)
384 goto mapend;
385
386 XT_PUTPAGE(mp);
387 goto search;
388 } else {
389 index++;
390 xad++;
391
392 /* compare with new xad */
393 goto compare;
394 }
395 }
396
397 /*
398 * lxd is covered by xad and a new pxd has been initialized
399 * (lstart <= xstart < lend) or (xstart < lstart < xend)
400 */
401 cover:
402 /* finalize pxd corresponding to current xad */
403 XT_PUTENTRY(pxd, xad->flag, pstart, plen, paddr);
404
405 if (++npxd >= maxnpxd)
406 goto mapend;
407 pxd++;
408
409 /*
410 * lxd is fully covered by xad
411 */
412 if (lend <= xend) {
413 /*
414 * get next lxd
415 */
416 if (--nlxd == 0)
417 goto mapend;
418 lxd++;
419
420 lstart = offsetLXD(lxd);
421 llen = lengthLXD(lxd);
422 lend = lstart + llen;
423 if (lstart >= size)
424 goto mapend;
425
426 /*
427 * test for old xad covering new lxd
428 * (old xstart < new lstart)
429 */
430 goto compare2;
431 }
432 /*
433 * lxd is partially covered by xad
434 */
435 else { /* (xend < lend) */
436
437 /*
438 * get next xad
439 *
440 * linear search next xad covering lxd on
441 * the current xad page, and then next xad page search
442 */
443 if (index == le16_to_cpu(p->header.nextindex) - 1) {
444 if (p->header.flag & BT_ROOT)
445 goto mapend;
446
447 if ((bn = le64_to_cpu(p->header.next)) == 0)
448 goto mapend;
449
450 XT_PUTPAGE(mp);
451
452 /* get next sibling page */
453 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
454 if (rc)
455 return rc;
456
457 index = XTENTRYSTART;
458 xad = &p->xad[index];
459 } else {
460 index++;
461 xad++;
462 }
463
464 /*
465 * test for new xad covering old lxd
466 * (old lstart < new xstart)
467 */
468 goto compare;
469 }
470
471 mapend:
472 xadlist->nxad = npxd;
473
474//out:
475 XT_PUTPAGE(mp);
476
477 return rc;
478}
479
480
481/* 220/*
482 * xtSearch() 221 * xtSearch()
483 * 222 *
diff --git a/fs/jfs/jfs_xtree.h b/fs/jfs/jfs_xtree.h
index 70815c8a3d6a..08c0c749b986 100644
--- a/fs/jfs/jfs_xtree.h
+++ b/fs/jfs/jfs_xtree.h
@@ -110,8 +110,6 @@ typedef union {
110 */ 110 */
111extern int xtLookup(struct inode *ip, s64 lstart, s64 llen, 111extern int xtLookup(struct inode *ip, s64 lstart, s64 llen,
112 int *pflag, s64 * paddr, int *plen, int flag); 112 int *pflag, s64 * paddr, int *plen, int flag);
113extern int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
114 struct xadlist * xadlist, int flag);
115extern void xtInitRoot(tid_t tid, struct inode *ip); 113extern void xtInitRoot(tid_t tid, struct inode *ip);
116extern int xtInsert(tid_t tid, struct inode *ip, 114extern int xtInsert(tid_t tid, struct inode *ip,
117 int xflag, s64 xoff, int xlen, s64 * xaddrp, int flag); 115 int xflag, s64 xoff, int xlen, s64 * xaddrp, int flag);
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index b37d1f78b854..6f21adf9479a 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -29,6 +29,7 @@
29#include <linux/posix_acl.h> 29#include <linux/posix_acl.h>
30#include <linux/buffer_head.h> 30#include <linux/buffer_head.h>
31#include <linux/exportfs.h> 31#include <linux/exportfs.h>
32#include <linux/crc32.h>
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
33#include <linux/seq_file.h> 34#include <linux/seq_file.h>
34 35
@@ -168,6 +169,9 @@ static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf)
168 buf->f_files = maxinodes; 169 buf->f_files = maxinodes;
169 buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) - 170 buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) -
170 atomic_read(&imap->im_numfree)); 171 atomic_read(&imap->im_numfree));
172 buf->f_fsid.val[0] = (u32)crc32_le(0, sbi->uuid, sizeof(sbi->uuid)/2);
173 buf->f_fsid.val[1] = (u32)crc32_le(0, sbi->uuid + sizeof(sbi->uuid)/2,
174 sizeof(sbi->uuid)/2);
171 175
172 buf->f_namelen = JFS_NAME_MAX; 176 buf->f_namelen = JFS_NAME_MAX;
173 return 0; 177 return 0;