diff options
Diffstat (limited to 'fs/jfs/super.c')
| -rw-r--r-- | fs/jfs/super.c | 118 |
1 files changed, 115 insertions, 3 deletions
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 4f6cfebc82db..143bcd1d5eaa 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/moduleparam.h> | 26 | #include <linux/moduleparam.h> |
| 27 | #include <linux/kthread.h> | 27 | #include <linux/kthread.h> |
| 28 | #include <linux/posix_acl.h> | 28 | #include <linux/posix_acl.h> |
| 29 | #include <linux/buffer_head.h> | ||
| 29 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
| 30 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
| 31 | 32 | ||
| @@ -298,7 +299,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, | |||
| 298 | break; | 299 | break; |
| 299 | } | 300 | } |
| 300 | 301 | ||
| 301 | #if defined(CONFIG_QUOTA) | 302 | #ifdef CONFIG_QUOTA |
| 302 | case Opt_quota: | 303 | case Opt_quota: |
| 303 | case Opt_usrquota: | 304 | case Opt_usrquota: |
| 304 | *flag |= JFS_USRQUOTA; | 305 | *flag |= JFS_USRQUOTA; |
| @@ -597,7 +598,7 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 597 | if (sbi->flag & JFS_NOINTEGRITY) | 598 | if (sbi->flag & JFS_NOINTEGRITY) |
| 598 | seq_puts(seq, ",nointegrity"); | 599 | seq_puts(seq, ",nointegrity"); |
| 599 | 600 | ||
| 600 | #if defined(CONFIG_QUOTA) | 601 | #ifdef CONFIG_QUOTA |
| 601 | if (sbi->flag & JFS_USRQUOTA) | 602 | if (sbi->flag & JFS_USRQUOTA) |
| 602 | seq_puts(seq, ",usrquota"); | 603 | seq_puts(seq, ",usrquota"); |
| 603 | 604 | ||
| @@ -608,6 +609,113 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 608 | return 0; | 609 | return 0; |
| 609 | } | 610 | } |
| 610 | 611 | ||
| 612 | #ifdef CONFIG_QUOTA | ||
| 613 | |||
| 614 | /* Read data from quotafile - avoid pagecache and such because we cannot afford | ||
| 615 | * acquiring the locks... As quota files are never truncated and quota code | ||
| 616 | * itself serializes the operations (and noone else should touch the files) | ||
| 617 | * we don't have to be afraid of races */ | ||
| 618 | static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data, | ||
| 619 | size_t len, loff_t off) | ||
| 620 | { | ||
| 621 | struct inode *inode = sb_dqopt(sb)->files[type]; | ||
| 622 | sector_t blk = off >> sb->s_blocksize_bits; | ||
| 623 | int err = 0; | ||
| 624 | int offset = off & (sb->s_blocksize - 1); | ||
| 625 | int tocopy; | ||
| 626 | size_t toread; | ||
| 627 | struct buffer_head tmp_bh; | ||
| 628 | struct buffer_head *bh; | ||
| 629 | loff_t i_size = i_size_read(inode); | ||
| 630 | |||
| 631 | if (off > i_size) | ||
| 632 | return 0; | ||
| 633 | if (off+len > i_size) | ||
| 634 | len = i_size-off; | ||
| 635 | toread = len; | ||
| 636 | while (toread > 0) { | ||
| 637 | tocopy = sb->s_blocksize - offset < toread ? | ||
| 638 | sb->s_blocksize - offset : toread; | ||
| 639 | |||
| 640 | tmp_bh.b_state = 0; | ||
| 641 | tmp_bh.b_size = 1 << inode->i_blkbits; | ||
| 642 | err = jfs_get_block(inode, blk, &tmp_bh, 0); | ||
| 643 | if (err) | ||
| 644 | return err; | ||
| 645 | if (!buffer_mapped(&tmp_bh)) /* A hole? */ | ||
| 646 | memset(data, 0, tocopy); | ||
| 647 | else { | ||
| 648 | bh = sb_bread(sb, tmp_bh.b_blocknr); | ||
| 649 | if (!bh) | ||
| 650 | return -EIO; | ||
| 651 | memcpy(data, bh->b_data+offset, tocopy); | ||
| 652 | brelse(bh); | ||
| 653 | } | ||
| 654 | offset = 0; | ||
| 655 | toread -= tocopy; | ||
| 656 | data += tocopy; | ||
| 657 | blk++; | ||
| 658 | } | ||
| 659 | return len; | ||
| 660 | } | ||
| 661 | |||
| 662 | /* Write to quotafile */ | ||
| 663 | static ssize_t jfs_quota_write(struct super_block *sb, int type, | ||
| 664 | const char *data, size_t len, loff_t off) | ||
| 665 | { | ||
| 666 | struct inode *inode = sb_dqopt(sb)->files[type]; | ||
| 667 | sector_t blk = off >> sb->s_blocksize_bits; | ||
| 668 | int err = 0; | ||
| 669 | int offset = off & (sb->s_blocksize - 1); | ||
| 670 | int tocopy; | ||
| 671 | size_t towrite = len; | ||
| 672 | struct buffer_head tmp_bh; | ||
| 673 | struct buffer_head *bh; | ||
| 674 | |||
| 675 | mutex_lock(&inode->i_mutex); | ||
| 676 | while (towrite > 0) { | ||
| 677 | tocopy = sb->s_blocksize - offset < towrite ? | ||
| 678 | sb->s_blocksize - offset : towrite; | ||
| 679 | |||
| 680 | tmp_bh.b_state = 0; | ||
| 681 | tmp_bh.b_size = 1 << inode->i_blkbits; | ||
| 682 | err = jfs_get_block(inode, blk, &tmp_bh, 1); | ||
| 683 | if (err) | ||
| 684 | goto out; | ||
| 685 | if (offset || tocopy != sb->s_blocksize) | ||
| 686 | bh = sb_bread(sb, tmp_bh.b_blocknr); | ||
| 687 | else | ||
| 688 | bh = sb_getblk(sb, tmp_bh.b_blocknr); | ||
| 689 | if (!bh) { | ||
| 690 | err = -EIO; | ||
| 691 | goto out; | ||
| 692 | } | ||
| 693 | lock_buffer(bh); | ||
| 694 | memcpy(bh->b_data+offset, data, tocopy); | ||
| 695 | flush_dcache_page(bh->b_page); | ||
| 696 | set_buffer_uptodate(bh); | ||
| 697 | mark_buffer_dirty(bh); | ||
| 698 | unlock_buffer(bh); | ||
| 699 | brelse(bh); | ||
| 700 | offset = 0; | ||
| 701 | towrite -= tocopy; | ||
| 702 | data += tocopy; | ||
| 703 | blk++; | ||
| 704 | } | ||
| 705 | out: | ||
| 706 | if (len == towrite) | ||
| 707 | return err; | ||
| 708 | if (inode->i_size < off+len-towrite) | ||
| 709 | i_size_write(inode, off+len-towrite); | ||
| 710 | inode->i_version++; | ||
| 711 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 712 | mark_inode_dirty(inode); | ||
| 713 | mutex_unlock(&inode->i_mutex); | ||
| 714 | return len - towrite; | ||
| 715 | } | ||
| 716 | |||
| 717 | #endif | ||
| 718 | |||
| 611 | static struct super_operations jfs_super_operations = { | 719 | static struct super_operations jfs_super_operations = { |
| 612 | .alloc_inode = jfs_alloc_inode, | 720 | .alloc_inode = jfs_alloc_inode, |
| 613 | .destroy_inode = jfs_destroy_inode, | 721 | .destroy_inode = jfs_destroy_inode, |
| @@ -621,7 +729,11 @@ static struct super_operations jfs_super_operations = { | |||
| 621 | .unlockfs = jfs_unlockfs, | 729 | .unlockfs = jfs_unlockfs, |
| 622 | .statfs = jfs_statfs, | 730 | .statfs = jfs_statfs, |
| 623 | .remount_fs = jfs_remount, | 731 | .remount_fs = jfs_remount, |
| 624 | .show_options = jfs_show_options | 732 | .show_options = jfs_show_options, |
| 733 | #ifdef CONFIG_QUOTA | ||
| 734 | .quota_read = jfs_quota_read, | ||
| 735 | .quota_write = jfs_quota_write, | ||
| 736 | #endif | ||
| 625 | }; | 737 | }; |
| 626 | 738 | ||
| 627 | static struct export_operations jfs_export_operations = { | 739 | static struct export_operations jfs_export_operations = { |
