diff options
Diffstat (limited to 'fs/jfs/super.c')
-rw-r--r-- | fs/jfs/super.c | 117 |
1 files changed, 114 insertions, 3 deletions
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 4f6cfebc82db..90ee0de829c1 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,112 @@ 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 | err = jfs_get_block(inode, blk, &tmp_bh, 1); | ||
682 | if (err) | ||
683 | goto out; | ||
684 | if (offset || tocopy != sb->s_blocksize) | ||
685 | bh = sb_bread(sb, tmp_bh.b_blocknr); | ||
686 | else | ||
687 | bh = sb_getblk(sb, tmp_bh.b_blocknr); | ||
688 | if (!bh) { | ||
689 | err = -EIO; | ||
690 | goto out; | ||
691 | } | ||
692 | lock_buffer(bh); | ||
693 | memcpy(bh->b_data+offset, data, tocopy); | ||
694 | flush_dcache_page(bh->b_page); | ||
695 | set_buffer_uptodate(bh); | ||
696 | mark_buffer_dirty(bh); | ||
697 | unlock_buffer(bh); | ||
698 | brelse(bh); | ||
699 | offset = 0; | ||
700 | towrite -= tocopy; | ||
701 | data += tocopy; | ||
702 | blk++; | ||
703 | } | ||
704 | out: | ||
705 | if (len == towrite) | ||
706 | return err; | ||
707 | if (inode->i_size < off+len-towrite) | ||
708 | i_size_write(inode, off+len-towrite); | ||
709 | inode->i_version++; | ||
710 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
711 | mark_inode_dirty(inode); | ||
712 | mutex_unlock(&inode->i_mutex); | ||
713 | return len - towrite; | ||
714 | } | ||
715 | |||
716 | #endif | ||
717 | |||
611 | static struct super_operations jfs_super_operations = { | 718 | static struct super_operations jfs_super_operations = { |
612 | .alloc_inode = jfs_alloc_inode, | 719 | .alloc_inode = jfs_alloc_inode, |
613 | .destroy_inode = jfs_destroy_inode, | 720 | .destroy_inode = jfs_destroy_inode, |
@@ -621,7 +728,11 @@ static struct super_operations jfs_super_operations = { | |||
621 | .unlockfs = jfs_unlockfs, | 728 | .unlockfs = jfs_unlockfs, |
622 | .statfs = jfs_statfs, | 729 | .statfs = jfs_statfs, |
623 | .remount_fs = jfs_remount, | 730 | .remount_fs = jfs_remount, |
624 | .show_options = jfs_show_options | 731 | .show_options = jfs_show_options, |
732 | #ifdef CONFIG_QUOTA | ||
733 | .quota_read = jfs_quota_read, | ||
734 | .quota_write = jfs_quota_write, | ||
735 | #endif | ||
625 | }; | 736 | }; |
626 | 737 | ||
627 | static struct export_operations jfs_export_operations = { | 738 | static struct export_operations jfs_export_operations = { |