diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/extents.c | 9 | ||||
-rw-r--r-- | fs/jfs/resize.c | 6 | ||||
-rw-r--r-- | fs/nfs/client.c | 2 | ||||
-rw-r--r-- | fs/nfs/dir.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 8 | ||||
-rw-r--r-- | fs/ocfs2/buffer_head_io.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmfs.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 1 | ||||
-rw-r--r-- | fs/ocfs2/refcounttree.c | 3 | ||||
-rw-r--r-- | fs/proc/base.c | 2 | ||||
-rw-r--r-- | fs/reiserfs/dir.c | 2 | ||||
-rw-r--r-- | fs/reiserfs/xattr.c | 19 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 5 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.c | 107 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.h | 7 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm_syscalls.c | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_ag.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 1 |
18 files changed, 148 insertions, 34 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index c56877972b0e..cae75c122ea4 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -3767,7 +3767,6 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
3767 | __u64 start, __u64 len) | 3767 | __u64 start, __u64 len) |
3768 | { | 3768 | { |
3769 | ext4_lblk_t start_blk; | 3769 | ext4_lblk_t start_blk; |
3770 | ext4_lblk_t len_blks; | ||
3771 | int error = 0; | 3770 | int error = 0; |
3772 | 3771 | ||
3773 | /* fallback to generic here if not in extents fmt */ | 3772 | /* fallback to generic here if not in extents fmt */ |
@@ -3781,8 +3780,14 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
3781 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { | 3780 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { |
3782 | error = ext4_xattr_fiemap(inode, fieinfo); | 3781 | error = ext4_xattr_fiemap(inode, fieinfo); |
3783 | } else { | 3782 | } else { |
3783 | ext4_lblk_t len_blks; | ||
3784 | __u64 last_blk; | ||
3785 | |||
3784 | start_blk = start >> inode->i_sb->s_blocksize_bits; | 3786 | start_blk = start >> inode->i_sb->s_blocksize_bits; |
3785 | len_blks = len >> inode->i_sb->s_blocksize_bits; | 3787 | last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits; |
3788 | if (last_blk >= EXT_MAX_BLOCK) | ||
3789 | last_blk = EXT_MAX_BLOCK-1; | ||
3790 | len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1; | ||
3786 | 3791 | ||
3787 | /* | 3792 | /* |
3788 | * Walk the extent tree gathering extent information. | 3793 | * Walk the extent tree gathering extent information. |
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c index 7f24a0bb08ca..1aba0039f1c9 100644 --- a/fs/jfs/resize.c +++ b/fs/jfs/resize.c | |||
@@ -81,6 +81,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) | |||
81 | struct inode *iplist[1]; | 81 | struct inode *iplist[1]; |
82 | struct jfs_superblock *j_sb, *j_sb2; | 82 | struct jfs_superblock *j_sb, *j_sb2; |
83 | uint old_agsize; | 83 | uint old_agsize; |
84 | int agsizechanged = 0; | ||
84 | struct buffer_head *bh, *bh2; | 85 | struct buffer_head *bh, *bh2; |
85 | 86 | ||
86 | /* If the volume hasn't grown, get out now */ | 87 | /* If the volume hasn't grown, get out now */ |
@@ -333,6 +334,9 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) | |||
333 | */ | 334 | */ |
334 | if ((rc = dbExtendFS(ipbmap, XAddress, nblocks))) | 335 | if ((rc = dbExtendFS(ipbmap, XAddress, nblocks))) |
335 | goto error_out; | 336 | goto error_out; |
337 | |||
338 | agsizechanged |= (bmp->db_agsize != old_agsize); | ||
339 | |||
336 | /* | 340 | /* |
337 | * the map now has extended to cover additional nblocks: | 341 | * the map now has extended to cover additional nblocks: |
338 | * dn_mapsize = oldMapsize + nblocks; | 342 | * dn_mapsize = oldMapsize + nblocks; |
@@ -432,7 +436,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) | |||
432 | * will correctly identify the new ag); | 436 | * will correctly identify the new ag); |
433 | */ | 437 | */ |
434 | /* if new AG size the same as old AG size, done! */ | 438 | /* if new AG size the same as old AG size, done! */ |
435 | if (bmp->db_agsize != old_agsize) { | 439 | if (agsizechanged) { |
436 | if ((rc = diExtendFS(ipimap, ipbmap))) | 440 | if ((rc = diExtendFS(ipimap, ipbmap))) |
437 | goto error_out; | 441 | goto error_out; |
438 | 442 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index bd39abc51508..37d555c32cd8 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -965,6 +965,8 @@ out_error: | |||
965 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) | 965 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) |
966 | { | 966 | { |
967 | target->flags = source->flags; | 967 | target->flags = source->flags; |
968 | target->rsize = source->rsize; | ||
969 | target->wsize = source->wsize; | ||
968 | target->acregmin = source->acregmin; | 970 | target->acregmin = source->acregmin; |
969 | target->acregmax = source->acregmax; | 971 | target->acregmax = source->acregmax; |
970 | target->acdirmin = source->acdirmin; | 972 | target->acdirmin = source->acdirmin; |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index d896d3e55024..01a0b9acb1f8 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -837,6 +837,8 @@ out_zap_parent: | |||
837 | /* If we have submounts, don't unhash ! */ | 837 | /* If we have submounts, don't unhash ! */ |
838 | if (have_submounts(dentry)) | 838 | if (have_submounts(dentry)) |
839 | goto out_valid; | 839 | goto out_valid; |
840 | if (dentry->d_flags & DCACHE_DISCONNECTED) | ||
841 | goto out_valid; | ||
840 | shrink_dcache_parent(dentry); | 842 | shrink_dcache_parent(dentry); |
841 | } | 843 | } |
842 | d_drop(dentry); | 844 | d_drop(dentry); |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index bbf72d8f9fc0..718f3fb312d0 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -160,10 +160,10 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) | |||
160 | argp->p = page_address(argp->pagelist[0]); | 160 | argp->p = page_address(argp->pagelist[0]); |
161 | argp->pagelist++; | 161 | argp->pagelist++; |
162 | if (argp->pagelen < PAGE_SIZE) { | 162 | if (argp->pagelen < PAGE_SIZE) { |
163 | argp->end = p + (argp->pagelen>>2); | 163 | argp->end = argp->p + (argp->pagelen>>2); |
164 | argp->pagelen = 0; | 164 | argp->pagelen = 0; |
165 | } else { | 165 | } else { |
166 | argp->end = p + (PAGE_SIZE>>2); | 166 | argp->end = argp->p + (PAGE_SIZE>>2); |
167 | argp->pagelen -= PAGE_SIZE; | 167 | argp->pagelen -= PAGE_SIZE; |
168 | } | 168 | } |
169 | memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); | 169 | memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); |
@@ -1425,10 +1425,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
1425 | argp->p = page_address(argp->pagelist[0]); | 1425 | argp->p = page_address(argp->pagelist[0]); |
1426 | argp->pagelist++; | 1426 | argp->pagelist++; |
1427 | if (argp->pagelen < PAGE_SIZE) { | 1427 | if (argp->pagelen < PAGE_SIZE) { |
1428 | argp->end = p + (argp->pagelen>>2); | 1428 | argp->end = argp->p + (argp->pagelen>>2); |
1429 | argp->pagelen = 0; | 1429 | argp->pagelen = 0; |
1430 | } else { | 1430 | } else { |
1431 | argp->end = p + (PAGE_SIZE>>2); | 1431 | argp->end = argp->p + (PAGE_SIZE>>2); |
1432 | argp->pagelen -= PAGE_SIZE; | 1432 | argp->pagelen -= PAGE_SIZE; |
1433 | } | 1433 | } |
1434 | } | 1434 | } |
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index 21c808f752d8..b18c6d677f9d 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c | |||
@@ -407,6 +407,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, | |||
407 | struct buffer_head *bh) | 407 | struct buffer_head *bh) |
408 | { | 408 | { |
409 | int ret = 0; | 409 | int ret = 0; |
410 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; | ||
410 | 411 | ||
411 | mlog_entry_void(); | 412 | mlog_entry_void(); |
412 | 413 | ||
@@ -426,6 +427,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, | |||
426 | 427 | ||
427 | get_bh(bh); /* for end_buffer_write_sync() */ | 428 | get_bh(bh); /* for end_buffer_write_sync() */ |
428 | bh->b_end_io = end_buffer_write_sync; | 429 | bh->b_end_io = end_buffer_write_sync; |
430 | ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &di->i_check); | ||
429 | submit_bh(WRITE, bh); | 431 | submit_bh(WRITE, bh); |
430 | 432 | ||
431 | wait_on_buffer(bh); | 433 | wait_on_buffer(bh); |
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 02bf17808bdc..18bc101d603f 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c | |||
@@ -205,7 +205,7 @@ static ssize_t dlmfs_file_read(struct file *filp, | |||
205 | if ((count + *ppos) > i_size_read(inode)) | 205 | if ((count + *ppos) > i_size_read(inode)) |
206 | readlen = i_size_read(inode) - *ppos; | 206 | readlen = i_size_read(inode) - *ppos; |
207 | else | 207 | else |
208 | readlen = count - *ppos; | 208 | readlen = count; |
209 | 209 | ||
210 | lvb_buf = kmalloc(readlen, GFP_NOFS); | 210 | lvb_buf = kmalloc(readlen, GFP_NOFS); |
211 | if (!lvb_buf) | 211 | if (!lvb_buf) |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 88459bdd1ff3..ec4d97faffbf 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -559,6 +559,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, | |||
559 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | 559 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); |
560 | if (IS_ERR(handle)) { | 560 | if (IS_ERR(handle)) { |
561 | status = PTR_ERR(handle); | 561 | status = PTR_ERR(handle); |
562 | handle = NULL; | ||
562 | mlog_errno(status); | 563 | mlog_errno(status); |
563 | goto out; | 564 | goto out; |
564 | } | 565 | } |
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 8ae65c9c020c..a8e85720d1f4 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
@@ -4083,6 +4083,9 @@ static int ocfs2_complete_reflink(struct inode *s_inode, | |||
4083 | di->i_attr = s_di->i_attr; | 4083 | di->i_attr = s_di->i_attr; |
4084 | 4084 | ||
4085 | if (preserve) { | 4085 | if (preserve) { |
4086 | t_inode->i_uid = s_inode->i_uid; | ||
4087 | t_inode->i_gid = s_inode->i_gid; | ||
4088 | t_inode->i_mode = s_inode->i_mode; | ||
4086 | di->i_uid = s_di->i_uid; | 4089 | di->i_uid = s_di->i_uid; |
4087 | di->i_gid = s_di->i_gid; | 4090 | di->i_gid = s_di->i_gid; |
4088 | di->i_mode = s_di->i_mode; | 4091 | di->i_mode = s_di->i_mode; |
diff --git a/fs/proc/base.c b/fs/proc/base.c index d59e279874c7..6ab0bd692968 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2912,7 +2912,7 @@ out_no_task: | |||
2912 | */ | 2912 | */ |
2913 | static const struct pid_entry tid_base_stuff[] = { | 2913 | static const struct pid_entry tid_base_stuff[] = { |
2914 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), | 2914 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), |
2915 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fd_operations), | 2915 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), |
2916 | REG("environ", S_IRUSR, proc_environ_operations), | 2916 | REG("environ", S_IRUSR, proc_environ_operations), |
2917 | INF("auxv", S_IRUSR, proc_pid_auxv), | 2917 | INF("auxv", S_IRUSR, proc_pid_auxv), |
2918 | ONE("status", S_IRUGO, proc_pid_status), | 2918 | ONE("status", S_IRUGO, proc_pid_status), |
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index c094f58c7448..1e686eeb2867 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c | |||
@@ -45,8 +45,6 @@ static inline bool is_privroot_deh(struct dentry *dir, | |||
45 | struct reiserfs_de_head *deh) | 45 | struct reiserfs_de_head *deh) |
46 | { | 46 | { |
47 | struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root; | 47 | struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root; |
48 | if (reiserfs_expose_privroot(dir->d_sb)) | ||
49 | return 0; | ||
50 | return (dir == dir->d_parent && privroot->d_inode && | 48 | return (dir == dir->d_parent && privroot->d_inode && |
51 | deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid); | 49 | deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid); |
52 | } | 50 | } |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 75f4c0bf0506..1347e9f32c52 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -557,7 +557,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, | |||
557 | if (!err && new_size < i_size_read(dentry->d_inode)) { | 557 | if (!err && new_size < i_size_read(dentry->d_inode)) { |
558 | struct iattr newattrs = { | 558 | struct iattr newattrs = { |
559 | .ia_ctime = current_fs_time(inode->i_sb), | 559 | .ia_ctime = current_fs_time(inode->i_sb), |
560 | .ia_size = buffer_size, | 560 | .ia_size = new_size, |
561 | .ia_valid = ATTR_SIZE | ATTR_CTIME, | 561 | .ia_valid = ATTR_SIZE | ATTR_CTIME, |
562 | }; | 562 | }; |
563 | 563 | ||
@@ -976,21 +976,13 @@ int reiserfs_permission(struct inode *inode, int mask) | |||
976 | return generic_permission(inode, mask, NULL); | 976 | return generic_permission(inode, mask, NULL); |
977 | } | 977 | } |
978 | 978 | ||
979 | /* This will catch lookups from the fs root to .reiserfs_priv */ | 979 | static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) |
980 | static int | ||
981 | xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) | ||
982 | { | 980 | { |
983 | struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root; | 981 | return -EPERM; |
984 | if (container_of(q1, struct dentry, d_name) == priv_root) | ||
985 | return -ENOENT; | ||
986 | if (q1->len == name->len && | ||
987 | !memcmp(q1->name, name->name, name->len)) | ||
988 | return 0; | ||
989 | return 1; | ||
990 | } | 982 | } |
991 | 983 | ||
992 | static const struct dentry_operations xattr_lookup_poison_ops = { | 984 | static const struct dentry_operations xattr_lookup_poison_ops = { |
993 | .d_compare = xattr_lookup_poison, | 985 | .d_revalidate = xattr_hide_revalidate, |
994 | }; | 986 | }; |
995 | 987 | ||
996 | int reiserfs_lookup_privroot(struct super_block *s) | 988 | int reiserfs_lookup_privroot(struct super_block *s) |
@@ -1004,8 +996,7 @@ int reiserfs_lookup_privroot(struct super_block *s) | |||
1004 | strlen(PRIVROOT_NAME)); | 996 | strlen(PRIVROOT_NAME)); |
1005 | if (!IS_ERR(dentry)) { | 997 | if (!IS_ERR(dentry)) { |
1006 | REISERFS_SB(s)->priv_root = dentry; | 998 | REISERFS_SB(s)->priv_root = dentry; |
1007 | if (!reiserfs_expose_privroot(s)) | 999 | dentry->d_op = &xattr_lookup_poison_ops; |
1008 | s->s_root->d_op = &xattr_lookup_poison_ops; | ||
1009 | if (dentry->d_inode) | 1000 | if (dentry->d_inode) |
1010 | dentry->d_inode->i_flags |= S_PRIVATE; | 1001 | dentry->d_inode->i_flags |= S_PRIVATE; |
1011 | } else | 1002 | } else |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 5eddd6fcc3ab..64e92454ef1a 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -1160,6 +1160,7 @@ xfs_fs_put_super( | |||
1160 | 1160 | ||
1161 | xfs_unmountfs(mp); | 1161 | xfs_unmountfs(mp); |
1162 | xfs_freesb(mp); | 1162 | xfs_freesb(mp); |
1163 | xfs_inode_shrinker_unregister(mp); | ||
1163 | xfs_icsb_destroy_counters(mp); | 1164 | xfs_icsb_destroy_counters(mp); |
1164 | xfs_close_devices(mp); | 1165 | xfs_close_devices(mp); |
1165 | xfs_dmops_put(mp); | 1166 | xfs_dmops_put(mp); |
@@ -1523,6 +1524,8 @@ xfs_fs_fill_super( | |||
1523 | if (error) | 1524 | if (error) |
1524 | goto fail_vnrele; | 1525 | goto fail_vnrele; |
1525 | 1526 | ||
1527 | xfs_inode_shrinker_register(mp); | ||
1528 | |||
1526 | kfree(mtpt); | 1529 | kfree(mtpt); |
1527 | return 0; | 1530 | return 0; |
1528 | 1531 | ||
@@ -1767,6 +1770,7 @@ init_xfs_fs(void) | |||
1767 | goto out_cleanup_procfs; | 1770 | goto out_cleanup_procfs; |
1768 | 1771 | ||
1769 | vfs_initquota(); | 1772 | vfs_initquota(); |
1773 | xfs_inode_shrinker_init(); | ||
1770 | 1774 | ||
1771 | error = register_filesystem(&xfs_fs_type); | 1775 | error = register_filesystem(&xfs_fs_type); |
1772 | if (error) | 1776 | if (error) |
@@ -1794,6 +1798,7 @@ exit_xfs_fs(void) | |||
1794 | { | 1798 | { |
1795 | vfs_exitquota(); | 1799 | vfs_exitquota(); |
1796 | unregister_filesystem(&xfs_fs_type); | 1800 | unregister_filesystem(&xfs_fs_type); |
1801 | xfs_inode_shrinker_destroy(); | ||
1797 | xfs_sysctl_unregister(); | 1802 | xfs_sysctl_unregister(); |
1798 | xfs_cleanup_procfs(); | 1803 | xfs_cleanup_procfs(); |
1799 | xfs_buf_terminate(); | 1804 | xfs_buf_terminate(); |
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index 6b6b39416ad3..57adf2d60dfc 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
@@ -95,7 +95,8 @@ xfs_inode_ag_walk( | |||
95 | struct xfs_perag *pag, int flags), | 95 | struct xfs_perag *pag, int flags), |
96 | int flags, | 96 | int flags, |
97 | int tag, | 97 | int tag, |
98 | int exclusive) | 98 | int exclusive, |
99 | int *nr_to_scan) | ||
99 | { | 100 | { |
100 | struct xfs_perag *pag = &mp->m_perag[ag]; | 101 | struct xfs_perag *pag = &mp->m_perag[ag]; |
101 | uint32_t first_index; | 102 | uint32_t first_index; |
@@ -135,7 +136,7 @@ restart: | |||
135 | if (error == EFSCORRUPTED) | 136 | if (error == EFSCORRUPTED) |
136 | break; | 137 | break; |
137 | 138 | ||
138 | } while (1); | 139 | } while ((*nr_to_scan)--); |
139 | 140 | ||
140 | if (skipped) { | 141 | if (skipped) { |
141 | delay(1); | 142 | delay(1); |
@@ -153,23 +154,30 @@ xfs_inode_ag_iterator( | |||
153 | struct xfs_perag *pag, int flags), | 154 | struct xfs_perag *pag, int flags), |
154 | int flags, | 155 | int flags, |
155 | int tag, | 156 | int tag, |
156 | int exclusive) | 157 | int exclusive, |
158 | int *nr_to_scan) | ||
157 | { | 159 | { |
158 | int error = 0; | 160 | int error = 0; |
159 | int last_error = 0; | 161 | int last_error = 0; |
160 | xfs_agnumber_t ag; | 162 | xfs_agnumber_t ag; |
163 | int nr; | ||
161 | 164 | ||
165 | nr = nr_to_scan ? *nr_to_scan : INT_MAX; | ||
162 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { | 166 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { |
163 | if (!mp->m_perag[ag].pag_ici_init) | 167 | if (!mp->m_perag[ag].pag_ici_init) |
164 | continue; | 168 | continue; |
165 | error = xfs_inode_ag_walk(mp, ag, execute, flags, tag, | 169 | error = xfs_inode_ag_walk(mp, ag, execute, flags, tag, |
166 | exclusive); | 170 | exclusive, &nr); |
167 | if (error) { | 171 | if (error) { |
168 | last_error = error; | 172 | last_error = error; |
169 | if (error == EFSCORRUPTED) | 173 | if (error == EFSCORRUPTED) |
170 | break; | 174 | break; |
171 | } | 175 | } |
176 | if (nr <= 0) | ||
177 | break; | ||
172 | } | 178 | } |
179 | if (nr_to_scan) | ||
180 | *nr_to_scan = nr; | ||
173 | return XFS_ERROR(last_error); | 181 | return XFS_ERROR(last_error); |
174 | } | 182 | } |
175 | 183 | ||
@@ -289,7 +297,7 @@ xfs_sync_data( | |||
289 | ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0); | 297 | ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0); |
290 | 298 | ||
291 | error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags, | 299 | error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags, |
292 | XFS_ICI_NO_TAG, 0); | 300 | XFS_ICI_NO_TAG, 0, NULL); |
293 | if (error) | 301 | if (error) |
294 | return XFS_ERROR(error); | 302 | return XFS_ERROR(error); |
295 | 303 | ||
@@ -311,7 +319,7 @@ xfs_sync_attr( | |||
311 | ASSERT((flags & ~SYNC_WAIT) == 0); | 319 | ASSERT((flags & ~SYNC_WAIT) == 0); |
312 | 320 | ||
313 | return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags, | 321 | return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags, |
314 | XFS_ICI_NO_TAG, 0); | 322 | XFS_ICI_NO_TAG, 0, NULL); |
315 | } | 323 | } |
316 | 324 | ||
317 | STATIC int | 325 | STATIC int |
@@ -679,6 +687,7 @@ __xfs_inode_set_reclaim_tag( | |||
679 | radix_tree_tag_set(&pag->pag_ici_root, | 687 | radix_tree_tag_set(&pag->pag_ici_root, |
680 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), | 688 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), |
681 | XFS_ICI_RECLAIM_TAG); | 689 | XFS_ICI_RECLAIM_TAG); |
690 | pag->pag_ici_reclaimable++; | ||
682 | } | 691 | } |
683 | 692 | ||
684 | /* | 693 | /* |
@@ -710,6 +719,7 @@ __xfs_inode_clear_reclaim_tag( | |||
710 | { | 719 | { |
711 | radix_tree_tag_clear(&pag->pag_ici_root, | 720 | radix_tree_tag_clear(&pag->pag_ici_root, |
712 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); | 721 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); |
722 | pag->pag_ici_reclaimable--; | ||
713 | } | 723 | } |
714 | 724 | ||
715 | STATIC int | 725 | STATIC int |
@@ -770,5 +780,88 @@ xfs_reclaim_inodes( | |||
770 | int mode) | 780 | int mode) |
771 | { | 781 | { |
772 | return xfs_inode_ag_iterator(mp, xfs_reclaim_inode, mode, | 782 | return xfs_inode_ag_iterator(mp, xfs_reclaim_inode, mode, |
773 | XFS_ICI_RECLAIM_TAG, 1); | 783 | XFS_ICI_RECLAIM_TAG, 1, NULL); |
784 | } | ||
785 | |||
786 | /* | ||
787 | * Shrinker infrastructure. | ||
788 | * | ||
789 | * This is all far more complex than it needs to be. It adds a global list of | ||
790 | * mounts because the shrinkers can only call a global context. We need to make | ||
791 | * the shrinkers pass a context to avoid the need for global state. | ||
792 | */ | ||
793 | static LIST_HEAD(xfs_mount_list); | ||
794 | static struct rw_semaphore xfs_mount_list_lock; | ||
795 | |||
796 | static int | ||
797 | xfs_reclaim_inode_shrink( | ||
798 | int nr_to_scan, | ||
799 | gfp_t gfp_mask) | ||
800 | { | ||
801 | struct xfs_mount *mp; | ||
802 | xfs_agnumber_t ag; | ||
803 | int reclaimable = 0; | ||
804 | |||
805 | if (nr_to_scan) { | ||
806 | if (!(gfp_mask & __GFP_FS)) | ||
807 | return -1; | ||
808 | |||
809 | down_read(&xfs_mount_list_lock); | ||
810 | list_for_each_entry(mp, &xfs_mount_list, m_mplist) { | ||
811 | xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0, | ||
812 | XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan); | ||
813 | if (nr_to_scan <= 0) | ||
814 | break; | ||
815 | } | ||
816 | up_read(&xfs_mount_list_lock); | ||
817 | } | ||
818 | |||
819 | down_read(&xfs_mount_list_lock); | ||
820 | list_for_each_entry(mp, &xfs_mount_list, m_mplist) { | ||
821 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { | ||
822 | |||
823 | if (!mp->m_perag[ag].pag_ici_init) | ||
824 | continue; | ||
825 | reclaimable += mp->m_perag[ag].pag_ici_reclaimable; | ||
826 | } | ||
827 | } | ||
828 | up_read(&xfs_mount_list_lock); | ||
829 | return reclaimable; | ||
830 | } | ||
831 | |||
832 | static struct shrinker xfs_inode_shrinker = { | ||
833 | .shrink = xfs_reclaim_inode_shrink, | ||
834 | .seeks = DEFAULT_SEEKS, | ||
835 | }; | ||
836 | |||
837 | void __init | ||
838 | xfs_inode_shrinker_init(void) | ||
839 | { | ||
840 | init_rwsem(&xfs_mount_list_lock); | ||
841 | register_shrinker(&xfs_inode_shrinker); | ||
842 | } | ||
843 | |||
844 | void | ||
845 | xfs_inode_shrinker_destroy(void) | ||
846 | { | ||
847 | ASSERT(list_empty(&xfs_mount_list)); | ||
848 | unregister_shrinker(&xfs_inode_shrinker); | ||
849 | } | ||
850 | |||
851 | void | ||
852 | xfs_inode_shrinker_register( | ||
853 | struct xfs_mount *mp) | ||
854 | { | ||
855 | down_write(&xfs_mount_list_lock); | ||
856 | list_add_tail(&mp->m_mplist, &xfs_mount_list); | ||
857 | up_write(&xfs_mount_list_lock); | ||
858 | } | ||
859 | |||
860 | void | ||
861 | xfs_inode_shrinker_unregister( | ||
862 | struct xfs_mount *mp) | ||
863 | { | ||
864 | down_write(&xfs_mount_list_lock); | ||
865 | list_del(&mp->m_mplist); | ||
866 | up_write(&xfs_mount_list_lock); | ||
774 | } | 867 | } |
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index ea932b43335d..0b28c13bdf94 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h | |||
@@ -54,6 +54,11 @@ void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag, | |||
54 | int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag); | 54 | int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag); |
55 | int xfs_inode_ag_iterator(struct xfs_mount *mp, | 55 | int xfs_inode_ag_iterator(struct xfs_mount *mp, |
56 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), | 56 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), |
57 | int flags, int tag, int write_lock); | 57 | int flags, int tag, int write_lock, int *nr_to_scan); |
58 | |||
59 | void xfs_inode_shrinker_init(void); | ||
60 | void xfs_inode_shrinker_destroy(void); | ||
61 | void xfs_inode_shrinker_register(struct xfs_mount *mp); | ||
62 | void xfs_inode_shrinker_unregister(struct xfs_mount *mp); | ||
58 | 63 | ||
59 | #endif | 64 | #endif |
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 873e07e29074..145f5963917d 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
@@ -891,7 +891,8 @@ xfs_qm_dqrele_all_inodes( | |||
891 | uint flags) | 891 | uint flags) |
892 | { | 892 | { |
893 | ASSERT(mp->m_quotainfo); | 893 | ASSERT(mp->m_quotainfo); |
894 | xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, XFS_ICI_NO_TAG, 0); | 894 | xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, |
895 | XFS_ICI_NO_TAG, 0, NULL); | ||
895 | } | 896 | } |
896 | 897 | ||
897 | /*------------------------------------------------------------------------*/ | 898 | /*------------------------------------------------------------------------*/ |
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h index 6702bd865811..1182604a16ea 100644 --- a/fs/xfs/xfs_ag.h +++ b/fs/xfs/xfs_ag.h | |||
@@ -229,6 +229,7 @@ typedef struct xfs_perag | |||
229 | int pag_ici_init; /* incore inode cache initialised */ | 229 | int pag_ici_init; /* incore inode cache initialised */ |
230 | rwlock_t pag_ici_lock; /* incore inode lock */ | 230 | rwlock_t pag_ici_lock; /* incore inode lock */ |
231 | struct radix_tree_root pag_ici_root; /* incore inode cache root */ | 231 | struct radix_tree_root pag_ici_root; /* incore inode cache root */ |
232 | int pag_ici_reclaimable; /* reclaimable inodes */ | ||
232 | #endif | 233 | #endif |
233 | } xfs_perag_t; | 234 | } xfs_perag_t; |
234 | 235 | ||
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 0088311d23e7..b20d59eab00a 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -257,6 +257,7 @@ typedef struct xfs_mount { | |||
257 | wait_queue_head_t m_wait_single_sync_task; | 257 | wait_queue_head_t m_wait_single_sync_task; |
258 | __int64_t m_update_flags; /* sb flags we need to update | 258 | __int64_t m_update_flags; /* sb flags we need to update |
259 | on the next remount,rw */ | 259 | on the next remount,rw */ |
260 | struct list_head m_mplist; /* inode shrinker mount list */ | ||
260 | } xfs_mount_t; | 261 | } xfs_mount_t; |
261 | 262 | ||
262 | /* | 263 | /* |