diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-21 20:42:00 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-21 20:42:00 -0500 |
| commit | 2182c815f3d430598e172c1c3ac88df775ea120e (patch) | |
| tree | 95c55693e2ca1b71ba5365f3e7d24c324f3b07c5 | |
| parent | 03d11a0e458d7008192585124e4c3313c2829046 (diff) | |
| parent | d57b9c9a999a8f4475fe73fba629c964245800ca (diff) | |
Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw
Pull GFS2 updates from Steven Whitehouse:
"The main topics this time are allocation, in the form of Bob's
improvements when searching resource groups and several updates to
quotas which should increase scalability. The quota changes follow on
from those in the last merge window, and there will likely be further
work to come in this area in due course.
There are also a few patches which help to improve efficiency of
adding entries into directories, and clean up some of that code.
One on-disk change is included this time, which is to write some
additional information which should be useful to fsck and also
potentially for debugging.
Other than that, its just a few small random bug fixes and clean ups"
* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw: (24 commits)
GFS2: revert "GFS2: d_splice_alias() can't return error"
GFS2: Small cleanup
GFS2: Don't use ENOBUFS when ENOMEM is the correct error code
GFS2: Fix kbuild test robot reported warning
GFS2: Move quota bitmap operations under their own lock
GFS2: Clean up quota slot allocation
GFS2: Only run logd and quota when mounted read/write
GFS2: Use RCU/hlist_bl based hash for quotas
GFS2: No need to invalidate pages for a dio read
GFS2: Add initialization for address space in super block
GFS2: Add hints to directory leaf blocks
GFS2: For exhash conversion, only one block is needed
GFS2: Increase i_writecount during gfs2_setattr_chown
GFS2: Remember directory insert point
GFS2: Consolidate transaction blocks calculation for dir add
GFS2: Add directory addition info structure
GFS2: Use only a single address space for rgrps
GFS2: Use range based functions for rgrp sync/invalidation
GFS2: Remove test which is always true
GFS2: Remove gfs2_quota_change_host structure
...
| -rw-r--r-- | fs/gfs2/aops.c | 23 | ||||
| -rw-r--r-- | fs/gfs2/dir.c | 90 | ||||
| -rw-r--r-- | fs/gfs2/dir.h | 19 | ||||
| -rw-r--r-- | fs/gfs2/glock.c | 29 | ||||
| -rw-r--r-- | fs/gfs2/glock.h | 2 | ||||
| -rw-r--r-- | fs/gfs2/glops.c | 26 | ||||
| -rw-r--r-- | fs/gfs2/incore.h | 23 | ||||
| -rw-r--r-- | fs/gfs2/inode.c | 118 | ||||
| -rw-r--r-- | fs/gfs2/lops.c | 5 | ||||
| -rw-r--r-- | fs/gfs2/main.c | 1 | ||||
| -rw-r--r-- | fs/gfs2/meta_io.c | 3 | ||||
| -rw-r--r-- | fs/gfs2/ops_fstype.c | 58 | ||||
| -rw-r--r-- | fs/gfs2/quota.c | 342 | ||||
| -rw-r--r-- | fs/gfs2/quota.h | 1 | ||||
| -rw-r--r-- | fs/gfs2/rgrp.c | 113 | ||||
| -rw-r--r-- | fs/gfs2/rgrp.h | 2 | ||||
| -rw-r--r-- | fs/gfs2/super.c | 43 | ||||
| -rw-r--r-- | include/uapi/linux/gfs2_ondisk.h | 11 |
18 files changed, 550 insertions, 359 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 73f3e4ee4037..49436fa7cd4f 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
| @@ -1032,8 +1032,9 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, | |||
| 1032 | unmap_shared_mapping_range(ip->i_inode.i_mapping, offset, len); | 1032 | unmap_shared_mapping_range(ip->i_inode.i_mapping, offset, len); |
| 1033 | rv = filemap_write_and_wait_range(mapping, lstart, end); | 1033 | rv = filemap_write_and_wait_range(mapping, lstart, end); |
| 1034 | if (rv) | 1034 | if (rv) |
| 1035 | return rv; | 1035 | goto out; |
| 1036 | truncate_inode_pages_range(mapping, lstart, end); | 1036 | if (rw == WRITE) |
| 1037 | truncate_inode_pages_range(mapping, lstart, end); | ||
| 1037 | } | 1038 | } |
| 1038 | 1039 | ||
| 1039 | rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 1040 | rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
| @@ -1080,30 +1081,22 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
| 1080 | bh = bh->b_this_page; | 1081 | bh = bh->b_this_page; |
| 1081 | } while(bh != head); | 1082 | } while(bh != head); |
| 1082 | spin_unlock(&sdp->sd_ail_lock); | 1083 | spin_unlock(&sdp->sd_ail_lock); |
| 1083 | gfs2_log_unlock(sdp); | ||
| 1084 | 1084 | ||
| 1085 | head = bh = page_buffers(page); | 1085 | head = bh = page_buffers(page); |
| 1086 | do { | 1086 | do { |
| 1087 | gfs2_log_lock(sdp); | ||
| 1088 | bd = bh->b_private; | 1087 | bd = bh->b_private; |
| 1089 | if (bd) { | 1088 | if (bd) { |
| 1090 | gfs2_assert_warn(sdp, bd->bd_bh == bh); | 1089 | gfs2_assert_warn(sdp, bd->bd_bh == bh); |
| 1091 | if (!list_empty(&bd->bd_list)) { | 1090 | if (!list_empty(&bd->bd_list)) |
| 1092 | if (!buffer_pinned(bh)) | 1091 | list_del_init(&bd->bd_list); |
| 1093 | list_del_init(&bd->bd_list); | 1092 | bd->bd_bh = NULL; |
| 1094 | else | ||
| 1095 | bd = NULL; | ||
| 1096 | } | ||
| 1097 | if (bd) | ||
| 1098 | bd->bd_bh = NULL; | ||
| 1099 | bh->b_private = NULL; | 1093 | bh->b_private = NULL; |
| 1100 | } | ||
| 1101 | gfs2_log_unlock(sdp); | ||
| 1102 | if (bd) | ||
| 1103 | kmem_cache_free(gfs2_bufdata_cachep, bd); | 1094 | kmem_cache_free(gfs2_bufdata_cachep, bd); |
| 1095 | } | ||
| 1104 | 1096 | ||
| 1105 | bh = bh->b_this_page; | 1097 | bh = bh->b_this_page; |
| 1106 | } while (bh != head); | 1098 | } while (bh != head); |
| 1099 | gfs2_log_unlock(sdp); | ||
| 1107 | 1100 | ||
| 1108 | return try_to_free_buffers(page); | 1101 | return try_to_free_buffers(page); |
| 1109 | 1102 | ||
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 2e5fc268d324..fa32655449c8 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
| @@ -834,6 +834,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, | |||
| 834 | struct gfs2_leaf *leaf; | 834 | struct gfs2_leaf *leaf; |
| 835 | struct gfs2_dirent *dent; | 835 | struct gfs2_dirent *dent; |
| 836 | struct qstr name = { .name = "" }; | 836 | struct qstr name = { .name = "" }; |
| 837 | struct timespec tv = CURRENT_TIME; | ||
| 837 | 838 | ||
| 838 | error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL); | 839 | error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL); |
| 839 | if (error) | 840 | if (error) |
| @@ -850,7 +851,11 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, | |||
| 850 | leaf->lf_entries = 0; | 851 | leaf->lf_entries = 0; |
| 851 | leaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE); | 852 | leaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE); |
| 852 | leaf->lf_next = 0; | 853 | leaf->lf_next = 0; |
| 853 | memset(leaf->lf_reserved, 0, sizeof(leaf->lf_reserved)); | 854 | leaf->lf_inode = cpu_to_be64(ip->i_no_addr); |
| 855 | leaf->lf_dist = cpu_to_be32(1); | ||
| 856 | leaf->lf_nsec = cpu_to_be32(tv.tv_nsec); | ||
| 857 | leaf->lf_sec = cpu_to_be64(tv.tv_sec); | ||
| 858 | memset(leaf->lf_reserved2, 0, sizeof(leaf->lf_reserved2)); | ||
| 854 | dent = (struct gfs2_dirent *)(leaf+1); | 859 | dent = (struct gfs2_dirent *)(leaf+1); |
| 855 | gfs2_qstr2dirent(&name, bh->b_size - sizeof(struct gfs2_leaf), dent); | 860 | gfs2_qstr2dirent(&name, bh->b_size - sizeof(struct gfs2_leaf), dent); |
| 856 | *pbh = bh; | 861 | *pbh = bh; |
| @@ -1612,11 +1617,31 @@ out: | |||
| 1612 | return ret; | 1617 | return ret; |
| 1613 | } | 1618 | } |
| 1614 | 1619 | ||
| 1620 | /** | ||
| 1621 | * dir_new_leaf - Add a new leaf onto hash chain | ||
| 1622 | * @inode: The directory | ||
| 1623 | * @name: The name we are adding | ||
| 1624 | * | ||
| 1625 | * This adds a new dir leaf onto an existing leaf when there is not | ||
| 1626 | * enough space to add a new dir entry. This is a last resort after | ||
| 1627 | * we've expanded the hash table to max size and also split existing | ||
| 1628 | * leaf blocks, so it will only occur for very large directories. | ||
| 1629 | * | ||
| 1630 | * The dist parameter is set to 1 for leaf blocks directly attached | ||
| 1631 | * to the hash table, 2 for one layer of indirection, 3 for two layers | ||
| 1632 | * etc. We are thus able to tell the difference between an old leaf | ||
| 1633 | * with dist set to zero (i.e. "don't know") and a new one where we | ||
| 1634 | * set this information for debug/fsck purposes. | ||
| 1635 | * | ||
| 1636 | * Returns: 0 on success, or -ve on error | ||
| 1637 | */ | ||
| 1638 | |||
| 1615 | static int dir_new_leaf(struct inode *inode, const struct qstr *name) | 1639 | static int dir_new_leaf(struct inode *inode, const struct qstr *name) |
| 1616 | { | 1640 | { |
| 1617 | struct buffer_head *bh, *obh; | 1641 | struct buffer_head *bh, *obh; |
| 1618 | struct gfs2_inode *ip = GFS2_I(inode); | 1642 | struct gfs2_inode *ip = GFS2_I(inode); |
| 1619 | struct gfs2_leaf *leaf, *oleaf; | 1643 | struct gfs2_leaf *leaf, *oleaf; |
| 1644 | u32 dist = 1; | ||
| 1620 | int error; | 1645 | int error; |
| 1621 | u32 index; | 1646 | u32 index; |
| 1622 | u64 bn; | 1647 | u64 bn; |
| @@ -1626,6 +1651,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) | |||
| 1626 | if (error) | 1651 | if (error) |
| 1627 | return error; | 1652 | return error; |
| 1628 | do { | 1653 | do { |
| 1654 | dist++; | ||
| 1629 | oleaf = (struct gfs2_leaf *)obh->b_data; | 1655 | oleaf = (struct gfs2_leaf *)obh->b_data; |
| 1630 | bn = be64_to_cpu(oleaf->lf_next); | 1656 | bn = be64_to_cpu(oleaf->lf_next); |
| 1631 | if (!bn) | 1657 | if (!bn) |
| @@ -1643,6 +1669,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) | |||
| 1643 | brelse(obh); | 1669 | brelse(obh); |
| 1644 | return -ENOSPC; | 1670 | return -ENOSPC; |
| 1645 | } | 1671 | } |
| 1672 | leaf->lf_dist = cpu_to_be32(dist); | ||
| 1646 | oleaf->lf_next = cpu_to_be64(bh->b_blocknr); | 1673 | oleaf->lf_next = cpu_to_be64(bh->b_blocknr); |
| 1647 | brelse(bh); | 1674 | brelse(bh); |
| 1648 | brelse(obh); | 1675 | brelse(obh); |
| @@ -1659,39 +1686,53 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) | |||
| 1659 | 1686 | ||
| 1660 | /** | 1687 | /** |
| 1661 | * gfs2_dir_add - Add new filename into directory | 1688 | * gfs2_dir_add - Add new filename into directory |
| 1662 | * @dip: The GFS2 inode | 1689 | * @inode: The directory inode |
| 1663 | * @filename: The new name | 1690 | * @name: The new name |
| 1664 | * @inode: The inode number of the entry | 1691 | * @nip: The GFS2 inode to be linked in to the directory |
| 1665 | * @type: The type of the entry | 1692 | * @da: The directory addition info |
| 1693 | * | ||
| 1694 | * If the call to gfs2_diradd_alloc_required resulted in there being | ||
| 1695 | * no need to allocate any new directory blocks, then it will contain | ||
| 1696 | * a pointer to the directory entry and the bh in which it resides. We | ||
| 1697 | * can use that without having to repeat the search. If there was no | ||
| 1698 | * free space, then we must now create more space. | ||
| 1666 | * | 1699 | * |
| 1667 | * Returns: 0 on success, error code on failure | 1700 | * Returns: 0 on success, error code on failure |
