diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2009-08-05 17:56:54 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rjw@sisk.pl> | 2009-08-05 17:56:54 -0400 |
| commit | c00aafcd4977769e8728292302ddbbb8b1082fab (patch) | |
| tree | 5766bcfbfd7b24816b54298b8ef34054f8cf0fae /fs | |
| parent | 2e6713c7662cc5ebc7346b033c404cb2f708fd51 (diff) | |
| parent | 90bc1a658a53f8832ee799685703977a450e5af9 (diff) | |
Merge branch 'master' into for-linus
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 11 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 22 | ||||
| -rw-r--r-- | fs/btrfs/transaction.h | 1 | ||||
| -rw-r--r-- | fs/cifs/CHANGES | 7 | ||||
| -rw-r--r-- | fs/cifs/README | 25 | ||||
| -rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 12 | ||||
| -rw-r--r-- | fs/cifs/cifs_unicode.c | 2 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 4 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 55 | ||||
| -rw-r--r-- | fs/gfs2/aops.c | 39 | ||||
| -rw-r--r-- | fs/gfs2/glock.c | 138 | ||||
| -rw-r--r-- | fs/gfs2/glock.h | 3 | ||||
| -rw-r--r-- | fs/gfs2/glops.c | 21 | ||||
| -rw-r--r-- | fs/gfs2/incore.h | 2 | ||||
| -rw-r--r-- | fs/gfs2/rgrp.c | 23 | ||||
| -rw-r--r-- | fs/gfs2/super.c | 40 | ||||
| -rw-r--r-- | fs/gfs2/super.h | 4 | ||||
| -rw-r--r-- | fs/nilfs2/mdt.c | 4 | ||||
| -rw-r--r-- | fs/nilfs2/segment.c | 16 | ||||
| -rw-r--r-- | fs/quota/dquot.c | 7 | ||||
| -rw-r--r-- | fs/udf/super.c | 12 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 8 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 4 |
25 files changed, 340 insertions, 126 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 215ef8cae82..837435ce84c 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -825,6 +825,7 @@ struct btrfs_fs_info { | |||
| 825 | struct mutex drop_mutex; | 825 | struct mutex drop_mutex; |
| 826 | struct mutex volume_mutex; | 826 | struct mutex volume_mutex; |
| 827 | struct mutex tree_reloc_mutex; | 827 | struct mutex tree_reloc_mutex; |
| 828 | struct rw_semaphore extent_commit_sem; | ||
| 828 | 829 | ||
| 829 | /* | 830 | /* |
| 830 | * this protects the ordered operations list only while we are | 831 | * this protects the ordered operations list only while we are |
| @@ -959,9 +960,6 @@ struct btrfs_root { | |||
| 959 | /* the node lock is held while changing the node pointer */ | 960 | /* the node lock is held while changing the node pointer */ |
| 960 | spinlock_t node_lock; | 961 | spinlock_t node_lock; |
| 961 | 962 | ||
| 962 | /* taken when updating the commit root */ | ||
| 963 | struct rw_semaphore commit_root_sem; | ||
| 964 | |||
| 965 | struct extent_buffer *commit_root; | 963 | struct extent_buffer *commit_root; |
| 966 | struct btrfs_root *log_root; | 964 | struct btrfs_root *log_root; |
| 967 | struct btrfs_root *reloc_root; | 965 | struct btrfs_root *reloc_root; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7dcaa813886..e83be2e4602 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -909,7 +909,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
| 909 | spin_lock_init(&root->inode_lock); | 909 | spin_lock_init(&root->inode_lock); |
| 910 | mutex_init(&root->objectid_mutex); | 910 | mutex_init(&root->objectid_mutex); |
| 911 | mutex_init(&root->log_mutex); | 911 | mutex_init(&root->log_mutex); |
| 912 | init_rwsem(&root->commit_root_sem); | ||
| 913 | init_waitqueue_head(&root->log_writer_wait); | 912 | init_waitqueue_head(&root->log_writer_wait); |
| 914 | init_waitqueue_head(&root->log_commit_wait[0]); | 913 | init_waitqueue_head(&root->log_commit_wait[0]); |
| 915 | init_waitqueue_head(&root->log_commit_wait[1]); | 914 | init_waitqueue_head(&root->log_commit_wait[1]); |
| @@ -1640,6 +1639,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1640 | mutex_init(&fs_info->cleaner_mutex); | 1639 | mutex_init(&fs_info->cleaner_mutex); |
| 1641 | mutex_init(&fs_info->volume_mutex); | 1640 | mutex_init(&fs_info->volume_mutex); |
| 1642 | mutex_init(&fs_info->tree_reloc_mutex); | 1641 | mutex_init(&fs_info->tree_reloc_mutex); |
| 1642 | init_rwsem(&fs_info->extent_commit_sem); | ||
| 1643 | 1643 | ||
| 1644 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); | 1644 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); |
| 1645 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); | 1645 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index fadf69a2764..dc84daee6bc 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -267,7 +267,7 @@ static int caching_kthread(void *data) | |||
| 267 | last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); | 267 | last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); |
| 268 | again: | 268 | again: |
| 269 | /* need to make sure the commit_root doesn't disappear */ | 269 | /* need to make sure the commit_root doesn't disappear */ |
| 270 | down_read(&fs_info->extent_root->commit_root_sem); | 270 | down_read(&fs_info->extent_commit_sem); |
| 271 | 271 | ||
| 272 | /* | 272 | /* |
| 273 | * We don't want to deadlock with somebody trying to allocate a new | 273 | * We don't want to deadlock with somebody trying to allocate a new |
| @@ -302,10 +302,11 @@ again: | |||
| 302 | else if (ret) | 302 | else if (ret) |
| 303 | break; | 303 | break; |
| 304 | 304 | ||
| 305 | if (need_resched()) { | 305 | if (need_resched() || |
| 306 | btrfs_transaction_in_commit(fs_info)) { | ||
| 306 | btrfs_release_path(fs_info->extent_root, path); | 307 | btrfs_release_path(fs_info->extent_root, path); |
| 307 | up_read(&fs_info->extent_root->commit_root_sem); | 308 | up_read(&fs_info->extent_commit_sem); |
| 308 | cond_resched(); | 309 | schedule_timeout(1); |
| 309 | goto again; | 310 | goto again; |
| 310 | } | 311 | } |
| 311 | 312 | ||
| @@ -345,7 +346,7 @@ next: | |||
| 345 | 346 | ||
| 346 | err: | 347 | err: |
| 347 | btrfs_free_path(path); | 348 | btrfs_free_path(path); |
| 348 | up_read(&fs_info->extent_root->commit_root_sem); | 349 | up_read(&fs_info->extent_commit_sem); |
| 349 | atomic_dec(&block_group->space_info->caching_threads); | 350 | atomic_dec(&block_group->space_info->caching_threads); |
| 350 | wake_up(&block_group->caching_q); | 351 | wake_up(&block_group->caching_q); |
| 351 | 352 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index e51d2bc532f..cdbb5022da5 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -42,10 +42,8 @@ static noinline void put_transaction(struct btrfs_transaction *transaction) | |||
| 42 | 42 | ||
| 43 | static noinline void switch_commit_root(struct btrfs_root *root) | 43 | static noinline void switch_commit_root(struct btrfs_root *root) |
| 44 | { | 44 | { |
| 45 | down_write(&root->commit_root_sem); | ||
| 46 | free_extent_buffer(root->commit_root); | 45 | free_extent_buffer(root->commit_root); |
| 47 | root->commit_root = btrfs_root_node(root); | 46 | root->commit_root = btrfs_root_node(root); |
| 48 | up_write(&root->commit_root_sem); | ||
| 49 | } | 47 | } |
| 50 | 48 | ||
| 51 | /* | 49 | /* |
| @@ -466,7 +464,10 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
| 466 | ret = btrfs_write_dirty_block_groups(trans, root); | 464 | ret = btrfs_write_dirty_block_groups(trans, root); |
| 467 | BUG_ON(ret); | 465 | BUG_ON(ret); |
| 468 | } | 466 | } |
| 469 | switch_commit_root(root); | 467 | |
| 468 | if (root != root->fs_info->extent_root) | ||
| 469 | switch_commit_root(root); | ||
| 470 | |||
| 470 | return 0; | 471 | return 0; |
| 471 | } | 472 | } |
| 472 | 473 | ||
| @@ -499,6 +500,11 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
| 499 | 500 | ||
| 500 | update_cowonly_root(trans, root); | 501 | update_cowonly_root(trans, root); |
| 501 | } | 502 | } |
| 503 | |||
| 504 | down_write(&fs_info->extent_commit_sem); | ||
| 505 | switch_commit_root(fs_info->extent_root); | ||
| 506 | up_write(&fs_info->extent_commit_sem); | ||
| 507 | |||
| 502 | return 0; | 508 | return 0; |
| 503 | } | 509 | } |
| 504 | 510 | ||
| @@ -851,6 +857,16 @@ static void update_super_roots(struct btrfs_root *root) | |||
| 851 | super->root_level = root_item->level; | 857 | super->root_level = root_item->level; |
| 852 | } | 858 | } |
| 853 | 859 | ||
| 860 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info) | ||
| 861 | { | ||
| 862 | int ret = 0; | ||
| 863 | spin_lock(&info->new_trans_lock); | ||
| 864 | if (info->running_transaction) | ||
| 865 | ret = info->running_transaction->in_commit; | ||
| 866 | spin_unlock(&info->new_trans_lock); | ||
| 867 | return ret; | ||
| 868 | } | ||
| 869 | |||
| 854 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 870 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, |
| 855 | struct btrfs_root *root) | 871 | struct btrfs_root *root) |
| 856 | { | 872 | { |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 961c3ee5a2e..663c6740491 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
| @@ -107,4 +107,5 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, | |||
| 107 | struct btrfs_root *root); | 107 | struct btrfs_root *root); |
| 108 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | 108 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, |
| 109 | struct extent_io_tree *dirty_pages); | 109 | struct extent_io_tree *dirty_pages); |
| 110 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info); | ||
| 110 | #endif | 111 | #endif |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 92888aa9074..e85b1e4389e 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
| @@ -1,3 +1,10 @@ | |||
| 1 | Version 1.60 | ||
| 2 | ------------- | ||
| 3 | Fix memory leak in reconnect. Fix oops in DFS mount error path. | ||
| 4 | Set s_maxbytes to smaller (the max that vfs can handle) so that | ||
| 5 | sendfile will now work over cifs mounts again. Add noforcegid | ||
| 6 | and noforceuid mount parameters. | ||
| 7 | |||
| 1 | Version 1.59 | 8 | Version 1.59 |
| 2 | ------------ | 9 | ------------ |
| 3 | Client uses server inode numbers (which are persistent) rather than | 10 | Client uses server inode numbers (which are persistent) rather than |
diff --git a/fs/cifs/README b/fs/cifs/README index ad92921dbde..79c1a93400b 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
| @@ -262,11 +262,11 @@ A partial list of the supported mount options follows: | |||
| 262 | mount. | 262 | mount. |
| 263 | domain Set the SMB/CIFS workgroup name prepended to the | 263 | domain Set the SMB/CIFS workgroup name prepended to the |
| 264 | username during CIFS session establishment | 264 | username during CIFS session establishment |
| 265 | forceuid Set the default uid for inodes based on the uid | 265 | forceuid Set the default uid for inodes to the uid |
| 266 | passed in. For mounts to servers | 266 | passed in on mount. For mounts to servers |
| 267 | which do support the CIFS Unix extensions, such as a | 267 | which do support the CIFS Unix extensions, such as a |
| 268 | properly configured Samba server, the server provides | 268 | properly configured Samba server, the server provides |
| 269 | the uid, gid and mode so this parameter should not be | 269 | the uid, gid and mode so this parameter should not be |
| 270 | specified unless the server and clients uid and gid | 270 | specified unless the server and clients uid and gid |
| 271 | numbering differ. If the server and client are in the | 271 | numbering differ. If the server and client are in the |
| 272 | same domain (e.g. running winbind or nss_ldap) and | 272 | same domain (e.g. running winbind or nss_ldap) and |
| @@ -278,11 +278,7 @@ A partial list of the supported mount options follows: | |||
| 278 | of existing files will be the uid (gid) of the person | 278 | of existing files will be the uid (gid) of the person |
| 279 | who executed the mount (root, except when mount.cifs | 279 | who executed the mount (root, except when mount.cifs |
| 280 | is configured setuid for user mounts) unless the "uid=" | 280 | is configured setuid for user mounts) unless the "uid=" |
| 281 | (gid) mount option is specified. For the uid (gid) of newly | 281 | (gid) mount option is specified. Also note that permission |
| 282 | created files and directories, ie files created since | ||
| 283 | the last mount of the server share, the expected uid | ||
| 284 | (gid) is cached as long as the inode remains in | ||
| 285 | memory on the client. Also note that permission | ||
| 286 | checks (authorization checks) on accesses to a file occur | 282 | checks (authorization checks) on accesses to a file occur |
| 287 | at the server, but there are cases in which an administrator | 283 | at the server, but there are cases in which an administrator |
| 288 | may want to restrict at the client as well. For those | 284 | may want to restrict at the client as well. For those |
| @@ -290,12 +286,15 @@ A partial list of the supported mount options follows: | |||
| 290 | (such as Windows), permissions can also be checked at the | 286 | (such as Windows), permissions can also be checked at the |
| 291 | client, and a crude form of client side permission checking | 287 | client, and a crude form of client side permission checking |
| 292 | can be enabled by specifying file_mode and dir_mode on | 288 | can be enabled by specifying file_mode and dir_mode on |
| 293 | the client. Note that the mount.cifs helper must be | 289 | the client. (default) |
| 294 | at version 1.10 or higher to support specifying the uid | 290 | forcegid (similar to above but for the groupid instead of uid) (default) |
| 295 | (or gid) in non-numeric form. | 291 | noforceuid Fill in file owner information (uid) by requesting it from |
| 296 | forcegid (similar to above but for the groupid instead of uid) | 292 | the server if possible. With this option, the value given in |
| 293 | the uid= option (on mount) will only be used if the server | ||
| 294 | can not support returning uids on inodes. | ||
| 295 | noforcegid (similar to above but for the group owner, gid, instead of uid) | ||
| 297 | uid Set the default uid for inodes, and indicate to the | 296 | uid Set the default uid for inodes, and indicate to the |
| 298 | cifs kernel driver which local user mounted . If the server | 297 | cifs kernel driver which local user mounted. If the server |
| 299 | supports the unix extensions the default uid is | 298 | supports the unix extensions the default uid is |
| 300 | not used to fill in the owner fields of inodes (files) | 299 | not used to fill in the owner fields of inodes (files) |
| 301 | unless the "forceuid" parameter is specified. | 300 | unless the "forceuid" parameter is specified. |
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 3bb11be8b6a..606912d8f2a 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
| @@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(void) | |||
| 55 | * i.e. strips from UNC trailing path that is not part of share | 55 | * i.e. strips from UNC trailing path that is not part of share |
| 56 | * name and fixup missing '\' in the begining of DFS node refferal | 56 | * name and fixup missing '\' in the begining of DFS node refferal |
| 57 | * if neccessary. | 57 | * if neccessary. |
| 58 | * Returns pointer to share name on success or NULL on error. | 58 | * Returns pointer to share name on success or ERR_PTR on error. |
| 59 | * Caller is responsible for freeing returned string. | 59 | * Caller is responsible for freeing returned string. |
| 60 | */ | 60 | */ |
| 61 | static char *cifs_get_share_name(const char *node_name) | 61 | static char *cifs_get_share_name(const char *node_name) |
| @@ -68,7 +68,7 @@ static char *cifs_get_share_name(const char *node_name) | |||
| 68 | UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, | 68 | UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, |
| 69 | GFP_KERNEL); | 69 | GFP_KERNEL); |
| 70 | if (!UNC) | 70 | if (!UNC) |
| 71 | return NULL; | 71 | return ERR_PTR(-ENOMEM); |
| 72 | 72 | ||
| 73 | /* get share name and server name */ | 73 | /* get share name and server name */ |
| 74 | if (node_name[1] != '\\') { | 74 | if (node_name[1] != '\\') { |
| @@ -87,7 +87,7 @@ static char *cifs_get_share_name(const char *node_name) | |||
| 87 | cERROR(1, ("%s: no server name end in node name: %s", | 87 | cERROR(1, ("%s: no server name end in node name: %s", |
| 88 | __func__, node_name)); | 88 | __func__, node_name)); |
| 89 | kfree(UNC); | 89 | kfree(UNC); |
| 90 | return NULL; | 90 | return ERR_PTR(-EINVAL); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | /* find sharename end */ | 93 | /* find sharename end */ |
| @@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata, | |||
| 133 | return ERR_PTR(-EINVAL); | 133 | return ERR_PTR(-EINVAL); |
| 134 | 134 | ||
| 135 | *devname = cifs_get_share_name(ref->node_name); | 135 | *devname = cifs_get_share_name(ref->node_name); |
| 136 | if (IS_ERR(*devname)) { | ||
| 137 | rc = PTR_ERR(*devname); | ||
| 138 | *devname = NULL; | ||
| 139 | goto compose_mount_options_err; | ||
| 140 | } | ||
| 141 | |||
| 136 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); | 142 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); |
| 137 | if (rc != 0) { | 143 | if (rc != 0) { |
| 138 | cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", | 144 | cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", |
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 60e3c4253de..714a542cbaf 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
| @@ -44,7 +44,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
| 44 | int maxwords = maxbytes / 2; | 44 | int maxwords = maxbytes / 2; |
| 45 | char tmp[NLS_MAX_CHARSET_SIZE]; | 45 | char tmp[NLS_MAX_CHARSET_SIZE]; |
| 46 | 46 | ||
| 47 | for (i = 0; from[i] && i < maxwords; i++) { | 47 | for (i = 0; i < maxwords && from[i]; i++) { |
| 48 | charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, | 48 | charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, |
| 49 | NLS_MAX_CHARSET_SIZE); | 49 | NLS_MAX_CHARSET_SIZE); |
| 50 | if (charlen > 0) | 50 | if (charlen > 0) |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 44f30504b82..84b75253b05 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -376,10 +376,14 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
| 376 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); | 376 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); |
| 377 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | 377 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
| 378 | seq_printf(s, ",forceuid"); | 378 | seq_printf(s, ",forceuid"); |
| 379 | else | ||
| 380 | seq_printf(s, ",noforceuid"); | ||
| 379 | 381 | ||
| 380 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); | 382 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); |
| 381 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | 383 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) |
| 382 | seq_printf(s, ",forcegid"); | 384 | seq_printf(s, ",forcegid"); |
| 385 | else | ||
| 386 | seq_printf(s, ",noforcegid"); | ||
| 383 | 387 | ||
| 384 | cifs_show_address(s, tcon->ses->server); | 388 | cifs_show_address(s, tcon->ses->server); |
| 385 | 389 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index fc44d316d0b..1f3345d7fa7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -803,6 +803,10 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 803 | char *data; | 803 | char *data; |
| 804 | unsigned int temp_len, i, j; | 804 | unsigned int temp_len, i, j; |
| 805 | char separator[2]; | 805 | char separator[2]; |
| 806 | short int override_uid = -1; | ||
| 807 | short int override_gid = -1; | ||
| 808 | bool uid_specified = false; | ||
| 809 | bool gid_specified = false; | ||
| 806 | 810 | ||
| 807 | separator[0] = ','; | 811 | separator[0] = ','; |
| 808 | separator[1] = 0; | 812 | separator[1] = 0; |
| @@ -1093,18 +1097,20 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1093 | "too long.\n"); | 1097 | "too long.\n"); |
| 1094 | return 1; | 1098 | return 1; |
| 1095 | } | 1099 | } |
| 1096 | } else if (strnicmp(data, "uid", 3) == 0) { | 1100 | } else if (!strnicmp(data, "uid", 3) && value && *value) { |
| 1097 | if (value && *value) | 1101 | vol->linux_uid = simple_strtoul(value, &value, 0); |
| 1098 | vol->linux_uid = | 1102 | uid_specified = true; |
| 1099 | simple_strtoul(value, &value, 0); | 1103 | } else if (!strnicmp(data, "forceuid", 8)) { |
| 1100 | } else if (strnicmp(data, "forceuid", 8) == 0) { | 1104 | override_uid = 1; |
| 1101 | vol->override_uid = 1; | 1105 | } else if (!strnicmp(data, "noforceuid", 10)) { |
| 1102 | } else if (strnicmp(data, "gid", 3) == 0) { | 1106 | override_uid = 0; |
| 1103 | if (value && *value) | 1107 | } else if (!strnicmp(data, "gid", 3) && value && *value) { |
| 1104 | vol->linux_gid = | 1108 | vol->linux_gid = simple_strtoul(value, &value, 0); |
| 1105 | simple_strtoul(value, &value, 0); | 1109 | gid_specified = true; |
| 1106 | } else if (strnicmp(data, "forcegid", 8) == 0) { | 1110 | } else if (!strnicmp(data, "forcegid", 8)) { |
| 1107 | vol->override_gid = 1; | 1111 | override_gid = 1; |
| 1112 | } else if (!strnicmp(data, "noforcegid", 10)) { | ||
| 1113 | override_gid = 0; | ||
| 1108 | } else if (strnicmp(data, "file_mode", 4) == 0) { | 1114 | } else if (strnicmp(data, "file_mode", 4) == 0) { |
| 1109 | if (value && *value) { | 1115 | if (value && *value) { |
| 1110 | vol->file_mode = | 1116 | vol->file_mode = |
| @@ -1355,6 +1361,18 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1355 | if (vol->UNCip == NULL) | 1361 | if (vol->UNCip == NULL) |
| 1356 | vol->UNCip = &vol->UNC[2]; | 1362 | vol->UNCip = &vol->UNC[2]; |
| 1357 | 1363 | ||
| 1364 | if (uid_specified) | ||
| 1365 | vol->override_uid = override_uid; | ||
| 1366 | else if (override_uid == 1) | ||
| 1367 | printk(KERN_NOTICE "CIFS: ignoring forceuid mount option " | ||
| 1368 | "specified with no uid= option.\n"); | ||
| 1369 | |||
| 1370 | if (gid_specified) | ||
| 1371 | vol->override_gid = override_gid; | ||
| 1372 | else if (override_gid == 1) | ||
| 1373 | printk(KERN_NOTICE "CIFS: ignoring forcegid mount option " | ||
| 1374 | "specified with no gid= option.\n"); | ||
| 1375 | |||
| 1358 | return 0; | 1376 | return 0; |
| 1359 | } | 1377 | } |
| 1360 | 1378 | ||
| @@ -2544,11 +2562,20 @@ remote_path_check: | |||
| 2544 | 2562 | ||
| 2545 | if (mount_data != mount_data_global) | 2563 | if (mount_data != mount_data_global) |
| 2546 | kfree(mount_data); | 2564 | kfree(mount_data); |
| 2565 | |||
| 2547 | mount_data = cifs_compose_mount_options( | 2566 | mount_data = cifs_compose_mount_options( |
| 2548 | cifs_sb->mountdata, full_path + 1, | 2567 | cifs_sb->mountdata, full_path + 1, |
| 2549 | referrals, &fake_devname); | 2568 | referrals, &fake_devname); |
| 2550 | kfree(fake_devname); | 2569 | |
| 2551 | free_dfs_info_array(referrals, num_referrals); | 2570 | free_dfs_info_array(referrals, num_referrals); |
| 2571 | kfree(fake_devname); | ||
| 2572 | kfree(full_path); | ||
| 2573 | |||
| 2574 | if (IS_ERR(mount_data)) { | ||
| 2575 | rc = PTR_ERR(mount_data); | ||
| 2576 | mount_data = NULL; | ||
| 2577 | goto mount_fail_check; | ||
| 2578 | } | ||
| 2552 | 2579 | ||
| 2553 | if (tcon) | 2580 | if (tcon) |
| 2554 | cifs_put_tcon(tcon); | 2581 | cifs_put_tcon(tcon); |
| @@ -2556,8 +2583,6 @@ remote_path_check: | |||
| 2556 | cifs_put_smb_ses(pSesInfo); | 2583 | cifs_put_smb_ses(pSesInfo); |
| 2557 | 2584 | ||
| 2558 | cleanup_volume_info(&volume_info); | 2585 | cleanup_volume_info(&volume_info); |
| 2559 | FreeXid(xid); | ||
| 2560 | kfree(full_path); | ||
| 2561 | referral_walks_count++; | 2586 | referral_walks_count++; |
| 2562 | goto try_mount_again; | 2587 | goto try_mount_again; |
| 2563 | } | 2588 | } |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 03ebb439ace..7ebae9a4ecc 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
| @@ -624,6 +624,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 624 | { | 624 | { |
| 625 | struct gfs2_inode *ip = GFS2_I(mapping->host); | 625 | struct gfs2_inode *ip = GFS2_I(mapping->host); |
| 626 | struct gfs2_sbd *sdp = GFS2_SB(mapping->host); | 626 | struct gfs2_sbd *sdp = GFS2_SB(mapping->host); |
| 627 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 627 | unsigned int data_blocks = 0, ind_blocks = 0, rblocks; | 628 | unsigned int data_blocks = 0, ind_blocks = 0, rblocks; |
| 628 | int alloc_required; | 629 | int alloc_required; |
| 629 | int error = 0; | 630 | int error = 0; |
| @@ -637,6 +638,14 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 637 | error = gfs2_glock_nq(&ip->i_gh); | 638 | error = gfs2_glock_nq(&ip->i_gh); |
| 638 | if (unlikely(error)) | 639 | if (unlikely(error)) |
| 639 | goto out_uninit; | 640 | goto out_uninit; |
| 641 | if (&ip->i_inode == sdp->sd_rindex) { | ||
| 642 | error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, | ||
| 643 | GL_NOCACHE, &m_ip->i_gh); | ||
| 644 | if (unlikely(error)) { | ||
| 645 | gfs2_glock_dq(&ip->i_gh); | ||
| 646 | goto out_uninit; | ||
| 647 | } | ||
| 648 | } | ||
| 640 | 649 | ||
| 641 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); | 650 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); |
| 642 | if (error) | 651 | if (error) |
| @@ -667,6 +676,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 667 | rblocks += data_blocks ? data_blocks : 1; | 676 | rblocks += data_blocks ? data_blocks : 1; |
| 668 | if (ind_blocks || data_blocks) | 677 | if (ind_blocks || data_blocks) |
| 669 | rblocks += RES_STATFS + RES_QUOTA; | 678 | rblocks += RES_STATFS + RES_QUOTA; |
| 679 | if (&ip->i_inode == sdp->sd_rindex) | ||
| 680 | rblocks += 2 * RES_STATFS; | ||
| 670 | 681 | ||
| 671 | error = gfs2_trans_begin(sdp, rblocks, | 682 | error = gfs2_trans_begin(sdp, rblocks, |
| 672 | PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); | 683 | PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); |
| @@ -712,6 +723,10 @@ out_alloc_put: | |||
| 712 | gfs2_alloc_put(ip); | 723 | gfs2_alloc_put(ip); |
| 713 | } | 724 | } |
| 714 | out_unlock: | 725 | out_unlock: |
| 726 | if (&ip->i_inode == sdp->sd_rindex) { | ||
| 727 | gfs2_glock_dq(&m_ip->i_gh); | ||
| 728 | gfs2_holder_uninit(&m_ip->i_gh); | ||
| 729 | } | ||
| 715 | gfs2_glock_dq(&ip->i_gh); | 730 | gfs2_glock_dq(&ip->i_gh); |
| 716 | out_uninit: | 731 | out_uninit: |
| 717 | gfs2_holder_uninit(&ip->i_gh); | 732 | gfs2_holder_uninit(&ip->i_gh); |
| @@ -725,14 +740,21 @@ out_uninit: | |||
| 725 | static void adjust_fs_space(struct inode *inode) | 740 | static void adjust_fs_space(struct inode *inode) |
| 726 | { | 741 | { |
| 727 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | 742 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; |
| 743 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 744 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | ||
| 728 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | 745 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; |
| 729 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | 746 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; |
| 747 | struct buffer_head *m_bh, *l_bh; | ||
| 730 | u64 fs_total, new_free; | 748 | u64 fs_total, new_free; |
| 731 | 749 | ||
| 732 | /* Total up the file system space, according to the latest rindex. */ | 750 | /* Total up the file system space, according to the latest rindex. */ |
| 733 | fs_total = gfs2_ri_total(sdp); | 751 | fs_total = gfs2_ri_total(sdp); |
| 752 | if (gfs2_meta_inode_buffer(m_ip, &m_bh) != 0) | ||
| 753 | return; | ||
| 734 | 754 | ||
| 735 | spin_lock(&sdp->sd_statfs_spin); | 755 | spin_lock(&sdp->sd_statfs_spin); |
| 756 | gfs2_statfs_change_in(m_sc, m_bh->b_data + | ||
| 757 | sizeof(struct gfs2_dinode)); | ||
| 736 | if (fs_total > (m_sc->sc_total + l_sc->sc_total)) | 758 | if (fs_total > (m_sc->sc_total + l_sc->sc_total)) |
| 737 | new_free = fs_total - (m_sc->sc_total + l_sc->sc_total); | 759 | new_free = fs_total - (m_sc->sc_total + l_sc->sc_total); |
| 738 | else | 760 | else |
| @@ -741,6 +763,13 @@ static void adjust_fs_space(struct inode *inode) | |||
| 741 | fs_warn(sdp, "File system extended by %llu blocks.\n", | 763 | fs_warn(sdp, "File system extended by %llu blocks.\n", |
| 742 | (unsigned long long)new_free); | 764 | (unsigned long long)new_free); |
| 743 | gfs2_statfs_change(sdp, new_free, new_free, 0); | 765 | gfs2_statfs_change(sdp, new_free, new_free, 0); |
| 766 | |||
| 767 | if (gfs2_meta_inode_buffer(l_ip, &l_bh) != 0) | ||
| 768 | goto out; | ||
| 769 | update_statfs(sdp, m_bh, l_bh); | ||
| 770 | brelse(l_bh); | ||
| 771 | out: | ||
| 772 | brelse(m_bh); | ||
| 744 | } | 773 | } |
| 745 | 774 | ||
| 746 | /** | 775 | /** |
| @@ -763,6 +792,7 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, | |||
| 763 | { | 792 | { |
| 764 | struct gfs2_inode *ip = GFS2_I(inode); | 793 | struct gfs2_inode *ip = GFS2_I(inode); |
| 765 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 794 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
| 795 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 766 | u64 to = pos + copied; | 796 | u64 to = pos + copied; |
| 767 | void *kaddr; | 797 | void *kaddr; |
| 768 | unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); | 798 | unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); |
| @@ -794,6 +824,10 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, | |||
| 794 | 824 | ||
| 795 | brelse(dibh); | 825 | brelse(dibh); |
| 796 | gfs2_trans_end(sdp); | 826 | gfs2_trans_end(sdp); |
| 827 | if (inode == sdp->sd_rindex) { | ||
| 828 | gfs2_glock_dq(&m_ip->i_gh); | ||
| 829 | gfs2_holder_uninit(&m_ip->i_gh); | ||
| 830 | } | ||
| 797 | gfs2_glock_dq(&ip->i_gh); | 831 | gfs2_glock_dq(&ip->i_gh); |
| 798 | gfs2_holder_uninit(&ip->i_gh); | 832 | gfs2_holder_uninit(&ip->i_gh); |
| 799 | return copied; | 833 | return copied; |
| @@ -823,6 +857,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
| 823 | struct inode *inode = page->mapping->host; | 857 | struct inode *inode = page->mapping->host; |
| 824 | struct gfs2_inode *ip = GFS2_I(inode); | 858 | struct gfs2_inode *ip = GFS2_I(inode); |
| 825 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 859 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
| 860 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 826 | struct buffer_head *dibh; | 861 | struct buffer_head *dibh; |
| 827 | struct gfs2_alloc *al = ip->i_alloc; | 862 | struct gfs2_alloc *al = ip->i_alloc; |
| 828 | unsigned int from = pos & (PAGE_CACHE_SIZE - 1); | 863 | unsigned int from = pos & (PAGE_CACHE_SIZE - 1); |
| @@ -865,6 +900,10 @@ failed: | |||
| 865 | gfs2_quota_unlock(ip); | 900 | gfs2_quota_unlock(ip); |
| 866 | gfs2_alloc_put(ip); | 901 | gfs2_alloc_put(ip); |
| 867 | } | 902 | } |
| 903 | if (inode == sdp->sd_rindex) { | ||
| 904 | gfs2_glock_dq(&m_ip->i_gh); | ||
| 905 | gfs2_holder_uninit(&m_ip->i_gh); | ||
| 906 | } | ||
| 868 | gfs2_glock_dq(&ip->i_gh); | 907 | gfs2_glock_dq(&ip->i_gh); |
| 869 | gfs2_holder_uninit(&ip->i_gh); | 908 | gfs2_holder_uninit(&ip->i_gh); |
| 870 | return ret; | 909 | return ret; |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 297421c0427..8b674b1f3a5 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
| @@ -63,6 +63,7 @@ static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int | |||
| 63 | static DECLARE_RWSEM(gfs2_umount_flush_sem); | 63 | static DECLARE_RWSEM(gfs2_umount_flush_sem); |
| 64 | static struct dentry *gfs2_root; | 64 | static struct dentry *gfs2_root; |
| 65 | static struct workqueue_struct *glock_workqueue; | 65 | static struct workqueue_struct *glock_workqueue; |
| 66 | struct workqueue_struct *gfs2_delete_workqueue; | ||
| 66 | static LIST_HEAD(lru_list); | 67 | static LIST_HEAD(lru_list); |
| 67 | static atomic_t lru_count = ATOMIC_INIT(0); | 68 | static atomic_t lru_count = ATOMIC_INIT(0); |
| 68 | static DEFINE_SPINLOCK(lru_lock); | 69 | static DEFINE_SPINLOCK(lru_lock); |
| @@ -167,13 +168,33 @@ static void glock_free(struct gfs2_glock *gl) | |||
| 167 | * | 168 | * |
| 168 | */ | 169 | */ |
| 169 | 170 | ||
| 170 | static void gfs2_glock_hold(struct gfs2_glock *gl) | 171 | void gfs2_glock_hold(struct gfs2_glock *gl) |
| 171 | { | 172 | { |
| 172 | GLOCK_BUG_ON(gl, atomic_read(&gl->gl_ref) == 0); | 173 | GLOCK_BUG_ON(gl, atomic_read(&gl->gl_ref) == 0); |
| 173 | atomic_inc(&gl->gl_ref); | 174 | atomic_inc(&gl->gl_ref); |
| 174 | } | 175 | } |
| 175 | 176 | ||
| 176 | /** | 177 | /** |
| 178 | * demote_ok - Check to see if it's ok to unlock a glock | ||
| 179 | * @gl: the glock | ||
| 180 | * | ||
| 181 | * Returns: 1 if it's ok | ||
| 182 | */ | ||
| 183 | |||
| 184 | static int demote_ok(const struct gfs2_glock *gl) | ||
| 185 | { | ||
| 186 | const struct gfs2_glock_operations *glops = gl->gl_ops; | ||
| 187 | |||
| 188 | if (gl->gl_state == LM_ST_UNLOCKED) | ||
| 189 | return 0; | ||
| 190 | if (!list_empty(&gl->gl_holders)) | ||
| 191 | return 0; | ||
| 192 | if (glops->go_demote_ok) | ||
| 193 | return glops->go_demote_ok(gl); | ||
| 194 | return 1; | ||
| 195 | } | ||
| 196 | |||
| 197 | /** | ||
| 177 | * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list | 198 | * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list |
| 178 | * @gl: the glock | 199 | * @gl: the glock |
| 179 | * | 200 | * |
| @@ -181,8 +202,13 @@ static void gfs2_glock_hold(struct gfs2_glock *gl) | |||
| 181 | 202 | ||
| 182 | static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) | 203 | static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) |
| 183 | { | 204 | { |
| 205 | int may_reclaim; | ||
| 206 | may_reclaim = (demote_ok(gl) && | ||
| 207 | (atomic_read(&gl->gl_ref) == 1 || | ||
| 208 | (gl->gl_name.ln_type == LM_TYPE_INODE && | ||
| 209 | atomic_read(&gl->gl_ref) <= 2))); | ||
| 184 | spin_lock(&lru_lock); | 210 | spin_lock(&lru_lock); |
| 185 | if (list_empty(&gl->gl_lru) && gl->gl_state != LM_ST_UNLOCKED) { | 211 | if (list_empty(&gl->gl_lru) && may_reclaim) { |
| 186 | list_add_tail(&gl->gl_lru, &lru_list); | 212 | list_add_tail(&gl->gl_lru, &lru_list); |
| 187 | atomic_inc(&lru_count); | 213 | atomic_inc(&lru_count); |
| 188 | } | 214 | } |
| @@ -190,6 +216,21 @@ static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) | |||
| 190 | } | 216 | } |
| 191 | 217 | ||
| 192 | /** | 218 | /** |
| 219 | * gfs2_glock_put_nolock() - Decrement reference count on glock | ||
| 220 | * @gl: The glock to put | ||
| 221 | * | ||
| 222 | * This function should only be used if the caller has its own reference | ||
| 223 | * to the glock, in addition to the one it is dropping. | ||
| 224 | */ | ||
| 225 | |||
| 226 | void gfs2_glock_put_nolock(struct gfs2_glock *gl) | ||
| 227 | { | ||
| 228 | if (atomic_dec_and_test(&gl->gl_ref)) | ||
| 229 | GLOCK_BUG_ON(gl, 1); | ||
| 230 | gfs2_glock_schedule_for_reclaim(gl); | ||
| 231 | } | ||
| 232 | |||
| 233 | /** | ||
| 193 | * gfs2_glock_put() - Decrement reference count on glock | 234 | * gfs2_glock_put() - Decrement reference count on glock |
| 194 | * @gl: The glock to put | 235 | * @gl: The glock to put |
| 195 | * | 236 | * |
| @@ -214,9 +255,9 @@ int gfs2_glock_put(struct gfs2_glock *gl) | |||
| 214 | rv = 1; | 255 | rv = 1; |
| 215 | goto out; | 256 | goto out; |
| 216 | } | 257 | } |
| 217 | /* 1 for being hashed, 1 for having state != LM_ST_UNLOCKED */ | 258 | spin_lock(&gl->gl_spin); |
| 218 | if (atomic_read(&gl->gl_ref) == 2) | 259 | gfs2_glock_schedule_for_reclaim(gl); |
| 219 | gfs2_glock_schedule_for_reclaim(gl); | 260 | spin_unlock(&gl->gl_spin); |
| 220 | write_unlock(gl_lock_addr(gl->gl_hash)); | 261 | write_unlock(gl_lock_addr(gl->gl_hash)); |
| 221 | out: | 262 | out: |
| 222 | return rv; | 263 | return rv; |
| @@ -398,7 +439,7 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state) | |||
| 398 | if (held2) | 439 | if (held2) |
| 399 | gfs2_glock_hold(gl); | 440 | gfs2_glock_hold(gl); |
| 400 | else | 441 | else |
| 401 | gfs2_glock_put(gl); | 442 | gfs2_glock_put_nolock(gl); |
| 402 | } | 443 | } |
| 403 | 444 | ||
| 404 | gl->gl_state = new_state; | 445 | gl->gl_state = new_state; |
| @@ -633,12 +674,35 @@ out: | |||
| 633 | out_sched: | 674 | out_sched: |
| 634 | gfs2_glock_hold(gl); | 675 | gfs2_glock_hold(gl); |
| 635 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 676 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
| 636 | gfs2_glock_put(gl); | 677 | gfs2_glock_put_nolock(gl); |
| 637 | out_unlock: | 678 | out_unlock: |
| 638 | clear_bit(GLF_LOCK, &gl->gl_flags); | 679 | clear_bit(GLF_LOCK, &gl->gl_flags); |
| 639 | goto out; | 680 | goto out; |
| 640 | } | 681 | } |
| 641 | 682 | ||
| 683 | static void delete_work_func(struct work_struct *work) | ||
| 684 | { | ||
| 685 | struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete); | ||
| 686 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
| 687 | struct gfs2_inode *ip = NULL; | ||
| 688 | struct inode *inode; | ||
| 689 | u64 no_addr = 0; | ||
| 690 | |||
| 691 | spin_lock(&gl->gl_spin); | ||
| 692 | ip = (struct gfs2_inode *)gl->gl_object; | ||
| 693 | if (ip) | ||
| 694 | no_addr = ip->i_no_addr; | ||
| 695 | spin_unlock(&gl->gl_spin); | ||
| 696 | if (ip) { | ||
| 697 | inode = gfs2_ilookup(sdp->sd_vfs, no_addr); | ||
| 698 | if (inode) { | ||
| 699 | d_prune_aliases(inode); | ||
| 700 | iput(inode); | ||
| 701 | } | ||
| 702 | } | ||
| 703 | gfs2_glock_put(gl); | ||
| 704 | } | ||
| 705 | |||
| 642 | static void glock_work_func(struct work_struct *work) | 706 | static void glock_work_func(struct work_struct *work) |
| 643 | { | 707 | { |
| 644 | unsigned long delay = 0; | 708 | unsigned long delay = 0; |
| @@ -717,6 +781,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 717 | gl->gl_sbd = sdp; | 781 | gl->gl_sbd = sdp; |
| 718 | gl->gl_aspace = NULL; | 782 | gl->gl_aspace = NULL; |
| 719 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); | 783 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); |
| 784 | INIT_WORK(&gl->gl_delete, delete_work_func); | ||
| 720 | 785 | ||
| 721 | /* If this glock protects actual on-disk data or metadata blocks, | 786 | /* If this glock protects actual on-disk data or metadata blocks, |
| 722 | create a VFS inode to manage the pages/buffers holding them. */ | 787 | create a VFS inode to manage the pages/buffers holding them. */ |
| @@ -858,6 +923,8 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state, | |||
| 858 | gl->gl_demote_state != state) { | 923 | gl->gl_demote_state != state) { |
| 859 | gl->gl_demote_state = LM_ST_UNLOCKED; | 924 | gl->gl_demote_state = LM_ST_UNLOCKED; |
| 860 | } | 925 | } |
| 926 | if (gl->gl_ops->go_callback) | ||
| 927 | gl->gl_ops->go_callback(gl); | ||
| 861 | trace_gfs2_demote_rq(gl); | 928 | trace_gfs2_demote_rq(gl); |
| 862 | } | 929 | } |
| 863 | 930 | ||
| @@ -1274,33 +1341,12 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret) | |||
| 1274 | gfs2_glock_put(gl); | 1341 | gfs2_glock_put(gl); |
| 1275 | } | 1342 | } |
| 1276 | 1343 | ||
| 1277 | /** | ||
| 1278 | * demote_ok - Check to see if it's ok to unlock a glock | ||
| 1279 | * @gl: the glock | ||
| 1280 | * | ||
| 1281 | * Returns: 1 if it's ok | ||
| 1282 | */ | ||
| 1283 | |||
| 1284 | static int demote_ok(const struct gfs2_glock *gl) | ||
| 1285 | { | ||
| 1286 | const struct gfs2_glock_operations *glops = gl->gl_ops; | ||
| 1287 | |||
| 1288 | if (gl->gl_state == LM_ST_UNLOCKED) | ||
| 1289 | return 0; | ||
| 1290 | if (!list_empty(&gl->gl_holders)) | ||
| 1291 | return 0; | ||
| 1292 | if (glops->go_demote_ok) | ||
| 1293 | return glops->go_demote_ok(gl); | ||
| 1294 | return 1; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | 1344 | ||
| 1298 | static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) | 1345 | static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) |
| 1299 | { | 1346 | { |
| 1300 | struct gfs2_glock *gl; | 1347 | struct gfs2_glock *gl; |
| 1301 | int may_demote; | 1348 | int may_demote; |
| 1302 | int nr_skipped = 0; | 1349 | int nr_skipped = 0; |
| 1303 | int got_ref = 0; | ||
| 1304 | LIST_HEAD(skipped); | 1350 | LIST_HEAD(skipped); |
| 1305 | 1351 | ||
| 1306 | if (nr == 0) | 1352 | if (nr == 0) |
| @@ -1315,37 +1361,29 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) | |||
| 1315 | list_del_init(&gl->gl_lru); | 1361 | list_del_init(&gl->gl_lru); |
| 1316 | atomic_dec(&lru_count); | 1362 | atomic_dec(&lru_count); |
| 1317 | 1363 | ||
| 1364 | /* Check if glock is about to be freed */ | ||
| 1365 | if (atomic_read(&gl->gl_ref) == 0) | ||
| 1366 | continue; | ||
| 1367 | |||
| 1318 | /* Test for being demotable */ | 1368 | /* Test for being demotable */ |
| 1319 | if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { | 1369 | if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { |
| 1320 | gfs2_glock_hold(gl); | 1370 | gfs2_glock_hold(gl); |
| 1321 | got_ref = 1; | ||
| 1322 | spin_unlock(&lru_lock); | 1371 | spin_unlock(&lru_lock); |
| 1323 | spin_lock(&gl->gl_spin); | 1372 | spin_lock(&gl->gl_spin); |
| 1324 | may_demote = demote_ok(gl); | 1373 | may_demote = demote_ok(gl); |
| 1325 | spin_unlock(&gl->gl_spin); | ||
| 1326 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
| 1327 | if (may_demote) { | 1374 | if (may_demote) { |
| 1328 | handle_callback(gl, LM_ST_UNLOCKED, 0); | 1375 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
| 1329 | nr--; | 1376 | nr--; |
| 1330 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | ||
| 1331 | gfs2_glock_put(gl); | ||
| 1332 | got_ref = 0; | ||
| 1333 | } | 1377 | } |
| 1378 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | ||
| 1379 | gfs2_glock_put_nolock(gl); | ||
| 1380 | spin_unlock(&gl->gl_spin); | ||
| 1381 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
| 1334 | spin_lock(&lru_lock); | 1382 | spin_lock(&lru_lock); |
| 1335 | if (may_demote) | 1383 | continue; |
| 1336 | continue; | ||
| 1337 | } | ||
| 1338 | if (list_empty(&gl->gl_lru) && | ||
| 1339 | (atomic_read(&gl->gl_ref) <= (2 + got_ref))) { | ||
| 1340 | nr_skipped++; | ||
| 1341 | list_add(&gl->gl_lru, &skipped); | ||
| 1342 | } | ||
| 1343 | if (got_ref) { | ||
| 1344 | spin_unlock(&lru_lock); | ||
| 1345 | gfs2_glock_put(gl); | ||
| 1346 | spin_lock(&lru_lock); | ||
| 1347 | got_ref = 0; | ||
| 1348 | } | 1384 | } |
| 1385 | nr_skipped++; | ||
| 1386 | list_add(&gl->gl_lru, &skipped); | ||
| 1349 | } | 1387 | } |
| 1350 | list_splice(&skipped, &lru_list); | 1388 | list_splice(&skipped, &lru_list); |
| 1351 | atomic_add(nr_skipped, &lru_count); | 1389 | atomic_add(nr_skipped, &lru_count); |
| @@ -1727,6 +1765,11 @@ int __init gfs2_glock_init(void) | |||
| 1727 | glock_workqueue = create_workqueue("glock_workqueue"); | 1765 | glock_workqueue = create_workqueue("glock_workqueue"); |
| 1728 | if (IS_ERR(glock_workqueue)) | 1766 | if (IS_ERR(glock_workqueue)) |
| 1729 | return PTR_ERR(glock_workqueue); | 1767 | return PTR_ERR(glock_workqueue); |
| 1768 | gfs2_delete_workqueue = create_workqueue("delete_workqueue"); | ||
| 1769 | if (IS_ERR(gfs2_delete_workqueue)) { | ||
| 1770 | destroy_workqueue(glock_workqueue); | ||
| 1771 | return PTR_ERR(gfs2_delete_workqueue); | ||
| 1772 | } | ||
| 1730 | 1773 | ||
| 1731 | register_shrinker(&glock_shrinker); | 1774 | register_shrinker(&glock_shrinker); |
| 1732 | 1775 | ||
| @@ -1737,6 +1780,7 @@ void gfs2_glock_exit(void) | |||
| 1737 | { | 1780 | { |
| 1738 | unregister_shrinker(&glock_shrinker); | 1781 | unregister_shrinker(&glock_shrinker); |
| 1739 | destroy_workqueue(glock_workqueue); | 1782 | destroy_workqueue(glock_workqueue); |
| 1783 | destroy_workqueue(gfs2_delete_workqueue); | ||
| 1740 | } | 1784 | } |
| 1741 | 1785 | ||
| 1742 | static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi) | 1786 | static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi) |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index a602a28f6f0..c609894ec0d 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
| @@ -143,6 +143,7 @@ struct lm_lockops { | |||
| 143 | 143 | ||
| 144 | #define GLR_TRYFAILED 13 | 144 | #define GLR_TRYFAILED 13 |
| 145 | 145 | ||
| 146 | extern struct workqueue_struct *gfs2_delete_workqueue; | ||
| 146 | static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) | 147 | static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) |
| 147 | { | 148 | { |
| 148 | struct gfs2_holder *gh; | 149 | struct gfs2_holder *gh; |
| @@ -191,6 +192,8 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl) | |||
| 191 | int gfs2_glock_get(struct gfs2_sbd *sdp, | 192 | int gfs2_glock_get(struct gfs2_sbd *sdp, |
| 192 | u64 number, const struct gfs2_glock_operations *glops, | 193 | u64 number, const struct gfs2_glock_operations *glops, |
| 193 | int create, struct gfs2_glock **glp); | 194 | int create, struct gfs2_glock **glp); |
| 195 | void gfs2_glock_hold(struct gfs2_glock *gl); | ||
| 196 | void gfs2_glock_put_nolock(struct gfs2_glock *gl); | ||
| 194 | int gfs2_glock_put(struct gfs2_glock *gl); | 197 | int gfs2_glock_put(struct gfs2_glock *gl); |
| 195 | void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, | 198 | void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, |
| 196 | struct gfs2_holder *gh); | 199 | struct gfs2_holder *gh); |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index d5e4ab155ca..6985eef06c3 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
| @@ -323,6 +323,7 @@ static void trans_go_sync(struct gfs2_glock *gl) | |||
| 323 | 323 | ||
| 324 | if (gl->gl_state != LM_ST_UNLOCKED && | 324 | if (gl->gl_state != LM_ST_UNLOCKED && |
| 325 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { | 325 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { |
| 326 | flush_workqueue(gfs2_delete_workqueue); | ||
| 326 | gfs2_meta_syncfs(sdp); | 327 | gfs2_meta_syncfs(sdp); |
| 327 | gfs2_log_shutdown(sdp); | 328 | gfs2_log_shutdown(sdp); |
| 328 | } | 329 | } |
| @@ -372,6 +373,25 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl) | |||
| 372 | return 0; | 373 | return 0; |
| 373 | } | 374 | } |
| 374 | 375 | ||
| 376 | /** | ||
| 377 | * iopen_go_callback - schedule the dcache entry for the inode to be deleted | ||
| 378 | * @gl: the glock | ||
| 379 | * | ||
| 380 | * gl_spin lock is held while calling this | ||
| 381 | */ | ||
| 382 | static void iopen_go_callback(struct gfs2_glock *gl) | ||
| 383 | { | ||
| 384 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; | ||
| 385 | |||
| 386 | if (gl->gl_demote_state == LM_ST_UNLOCKED && | ||
| 387 | gl->gl_state == LM_ST_SHARED && | ||
| 388 | ip && test_bit(GIF_USER, &ip->i_flags)) { | ||
| 389 | gfs2_glock_hold(gl); | ||
| 390 | if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) | ||
| 391 | gfs2_glock_put_nolock(gl); | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 375 | const struct gfs2_glock_operations gfs2_meta_glops = { | 395 | const struct gfs2_glock_operations gfs2_meta_glops = { |
| 376 | .go_type = LM_TYPE_META, | 396 | .go_type = LM_TYPE_META, |
| 377 | }; | 397 | }; |
| @@ -406,6 +426,7 @@ const struct gfs2_glock_operations gfs2_trans_glops = { | |||
| 406 | 426 | ||
| 407 | const struct gfs2_glock_operations gfs2_iopen_glops = { | 427 | const struct gfs2_glock_operations gfs2_iopen_glops = { |
| 408 | .go_type = LM_TYPE_IOPEN, | 428 | .go_type = LM_TYPE_IOPEN, |
| 429 | .go_callback = iopen_go_callback, | ||
| 409 | }; | 430 | }; |
| 410 | 431 | ||
| 411 | const struct gfs2_glock_operations gfs2_flock_glops = { | 432 | const struct gfs2_glock_operations gfs2_flock_glops = { |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 225347fbff3..61801ada36f 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
| @@ -159,6 +159,7 @@ struct gfs2_glock_operations { | |||
| 159 | int (*go_lock) (struct gfs2_holder *gh); | 159 | int (*go_lock) (struct gfs2_holder *gh); |
| 160 | void (*go_unlock) (struct gfs2_holder *gh); | 160 | void (*go_unlock) (struct gfs2_holder *gh); |
| 161 | int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl); | 161 | int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl); |
| 162 | void (*go_callback) (struct gfs2_glock *gl); | ||
| 162 | const int go_type; | 163 | const int go_type; |
| 163 | const unsigned long go_min_hold_time; | 164 | const unsigned long go_min_hold_time; |
| 164 | }; | 165 | }; |
| @@ -228,6 +229,7 @@ struct gfs2_glock { | |||
| 228 | struct list_head gl_ail_list; | 229 | struct list_head gl_ail_list; |
| 229 | atomic_t gl_ail_count; | 230 | atomic_t gl_ail_count; |
| 230 | struct delayed_work gl_work; | 231 | struct delayed_work gl_work; |
| 232 | struct work_struct gl_delete; | ||
| 231 | }; | 233 | }; |
| 232 | 234 | ||
| 233 | #define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */ | 235 | #define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */ |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index daa4ae341a2..fba795798d3 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
| @@ -285,27 +285,19 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) | |||
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | tmp = rgd->rd_data - rgd->rd_free - rgd->rd_dinodes; | 287 | tmp = rgd->rd_data - rgd->rd_free - rgd->rd_dinodes; |
| 288 | if (count[1] + count[2] != tmp) { | 288 | if (count[1] != tmp) { |
| 289 | if (gfs2_consist_rgrpd(rgd)) | 289 | if (gfs2_consist_rgrpd(rgd)) |
| 290 | fs_err(sdp, "used data mismatch: %u != %u\n", | 290 | fs_err(sdp, "used data mismatch: %u != %u\n", |
| 291 | count[1], tmp); | 291 | count[1], tmp); |
| 292 | return; | 292 | return; |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | if (count[3] != rgd->rd_dinodes) { | 295 | if (count[2] + count[3] != rgd->rd_dinodes) { |
| 296 | if (gfs2_consist_rgrpd(rgd)) | 296 | if (gfs2_consist_rgrpd(rgd)) |
| 297 | fs_err(sdp, "used metadata mismatch: %u != %u\n", | 297 | fs_err(sdp, "used metadata mismatch: %u != %u\n", |
| 298 | count[3], rgd->rd_dinodes); | 298 | count[2] + count[3], rgd->rd_dinodes); |
| 299 | return; | 299 | return; |
| 300 | } | 300 | } |
| 301 | |||
| 302 | if (count[2] > count[3]) { | ||
| 303 | if (gfs2_consist_rgrpd(rgd)) | ||
| 304 | fs_err(sdp, "unlinked inodes > inodes: %u\n", | ||
| 305 | count[2]); | ||
| 306 | return; | ||
| 307 | } | ||
| 308 | |||
| 309 | } | 301 | } |
| 310 | 302 | ||
| 311 | static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block) | 303 | static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block) |
| @@ -961,7 +953,8 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) | |||
| 961 | * Returns: The inode, if one has been found | 953 | * Returns: The inode, if one has been found |
| 962 | */ | 954 | */ |
| 963 | 955 | ||
| 964 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | 956 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, |
| 957 | u64 skip) | ||
| 965 | { | 958 | { |
| 966 | struct inode *inode; | 959 | struct inode *inode; |
| 967 | u32 goal = 0, block; | 960 | u32 goal = 0, block; |
| @@ -985,6 +978,8 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | |||
| 985 | goal++; | 978 | goal++; |
| 986 | if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) | 979 | if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) |
| 987 | continue; | 980 | continue; |
| 981 | if (no_addr == skip) | ||
| 982 | continue; | ||
| 988 | *last_unlinked = no_addr; | 983 | *last_unlinked = no_addr; |
| 989 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, | 984 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, |
| 990 | no_addr, -1, 1); | 985 | no_addr, -1, 1); |
| @@ -1104,7 +1099,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
| 1104 | if (try_rgrp_fit(rgd, al)) | 1099 | if (try_rgrp_fit(rgd, al)) |
| 1105 | goto out; | 1100 | goto out; |
| 1106 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1101 | if (rgd->rd_flags & GFS2_RDF_CHECK) |
| 1107 | inode = try_rgrp_unlink(rgd, last_unlinked); | 1102 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); |
| 1108 | if (!rg_locked) | 1103 | if (!rg_locked) |
| 1109 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1104 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
| 1110 | if (inode) | 1105 | if (inode) |
| @@ -1138,7 +1133,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
| 1138 | if (try_rgrp_fit(rgd, al)) | 1133 | if (try_rgrp_fit(rgd, al)) |
| 1139 | goto out; | 1134 | goto out; |
| 1140 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1135 | if (rgd->rd_flags & GFS2_RDF_CHECK) |
| 1141 | inode = try_rgrp_unlink(rgd, last_unlinked); | 1136 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); |
| 1142 | if (!rg_locked) | 1137 | if (!rg_locked) |
| 1143 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1138 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
| 1144 | if (inode) | 1139 | if (inode) |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0a680133647..f522bb01797 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
| @@ -353,7 +353,7 @@ fail: | |||
| 353 | return error; | 353 | return error; |
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) | 356 | void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) |
| 357 | { | 357 | { |
| 358 | const struct gfs2_statfs_change *str = buf; | 358 | const struct gfs2_statfs_change *str = buf; |
| 359 | 359 | ||
| @@ -441,6 +441,29 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | |||
| 441 | brelse(l_bh); | 441 | brelse(l_bh); |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | ||
| 445 | struct buffer_head *l_bh) | ||
| 446 | { | ||
| 447 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 448 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | ||
| 449 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
| 450 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
| 451 | |||
| 452 | gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); | ||
| 453 | |||
| 454 | spin_lock(&sdp->sd_statfs_spin); | ||
| 455 | m_sc->sc_total += l_sc->sc_total; | ||
| 456 | m_sc->sc_free += l_sc->sc_free; | ||
| 457 | m_sc->sc_dinodes += l_sc->sc_dinodes; | ||
| 458 | memset(l_sc, 0, sizeof(struct gfs2_statfs_change)); | ||
| 459 | memset(l_bh->b_data + sizeof(struct gfs2_dinode), | ||
| 460 | 0, sizeof(struct gfs2_statfs_change)); | ||
| 461 | spin_unlock(&sdp->sd_statfs_spin); | ||
| 462 | |||
| 463 | gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1); | ||
| 464 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | ||
| 465 | } | ||
| 466 | |||
| 444 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) | 467 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) |
| 445 | { | 468 | { |
| 446 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | 469 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); |
| @@ -477,19 +500,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp) | |||
| 477 | if (error) | 500 | if (error) |
| 478 | goto out_bh2; | 501 | goto out_bh2; |
| 479 | 502 | ||
| 480 | gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); | 503 | update_statfs(sdp, m_bh, l_bh); |
| 481 | |||
| 482 | spin_lock(&sdp->sd_statfs_spin); | ||
| 483 | m_sc->sc_total += l_sc->sc_total; | ||
| 484 | m_sc->sc_free += l_sc->sc_free; | ||
| 485 | m_sc->sc_dinodes += l_sc->sc_dinodes; | ||
| 486 | memset(l_sc, 0, sizeof(struct gfs2_statfs_change)); | ||
| 487 | memset(l_bh->b_data + sizeof(struct gfs2_dinode), | ||
| 488 | 0, sizeof(struct gfs2_statfs_change)); | ||
| 489 | spin_unlock(&sdp->sd_statfs_spin); | ||
| 490 | |||
| 491 | gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1); | ||
| 492 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | ||
| 493 | 504 | ||
| 494 | gfs2_trans_end(sdp); | 505 | gfs2_trans_end(sdp); |
| 495 | 506 | ||
| @@ -680,6 +691,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
| 680 | struct gfs2_holder t_gh; | 691 | struct gfs2_holder t_gh; |
| 681 | int error; | 692 | int error; |
| 682 | 693 | ||
| 694 | flush_workqueue(gfs2_delete_workqueue); | ||
| 683 | gfs2_quota_sync(sdp); | 695 | gfs2_quota_sync(sdp); |
| 684 | gfs2_statfs_sync(sdp); | 696 | gfs2_statfs_sync(sdp); |
| 685 | 697 | ||
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index b56413e3e40..22e0417ed99 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h | |||
| @@ -40,6 +40,10 @@ extern int gfs2_make_fs_rw(struct gfs2_sbd *sdp); | |||
| 40 | extern int gfs2_statfs_init(struct gfs2_sbd *sdp); | 40 | extern int gfs2_statfs_init(struct gfs2_sbd *sdp); |
| 41 | extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | 41 | extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, |
| 42 | s64 dinodes); | 42 | s64 dinodes); |
| 43 | extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, | ||
| 44 | const void *buf); | ||
| 45 | extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | ||
| 46 | struct buffer_head *l_bh); | ||
| 43 | extern int gfs2_statfs_sync(struct gfs2_sbd *sdp); | 47 | extern int gfs2_statfs_sync(struct gfs2_sbd *sdp); |
| 44 | 48 | ||
| 45 | extern int gfs2_freeze_fs(struct gfs2_sbd *sdp); | 49 | extern int gfs2_freeze_fs(struct gfs2_sbd *sdp); |
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 3d3ddb3f517..2dfd47714ae 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
| @@ -412,8 +412,10 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) | |||
| 412 | return 0; /* Do not request flush for shadow page cache */ | 412 | return 0; /* Do not request flush for shadow page cache */ |
| 413 | if (!sb) { | 413 | if (!sb) { |
| 414 | writer = nilfs_get_writer(NILFS_MDT(inode)->mi_nilfs); | 414 | writer = nilfs_get_writer(NILFS_MDT(inode)->mi_nilfs); |
| 415 | if (!writer) | 415 | if (!writer) { |
| 416 | nilfs_put_writer(NILFS_MDT(inode)->mi_nilfs); | ||
| 416 | return -EROFS; | 417 | return -EROFS; |
| 418 | } | ||
| 417 | sb = writer->s_super; | 419 | sb = writer->s_super; |
| 418 | } | 420 | } |
| 419 | 421 | ||
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 8b5e4778cf2..51ff3d0a4ee 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -1859,12 +1859,26 @@ static void nilfs_end_page_io(struct page *page, int err) | |||
| 1859 | if (!page) | 1859 | if (!page) |
| 1860 | return; | 1860 | return; |
| 1861 | 1861 | ||
| 1862 | if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page)) | 1862 | if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page)) { |
| 1863 | /* | 1863 | /* |
| 1864 | * For b-tree node pages, this function may be called twice | 1864 | * For b-tree node pages, this function may be called twice |
| 1865 | * or more because they might be split in a segment. | 1865 | * or more because they might be split in a segment. |
| 1866 | */ | 1866 | */ |
| 1867 | if (PageDirty(page)) { | ||
| 1868 | /* | ||
| 1869 | * For pages holding split b-tree node buffers, dirty | ||
| 1870 | * flag on the buffers may be cleared discretely. | ||
| 1871 | * In that case, the page is once redirtied for | ||
| 1872 | * remaining buffers, and it must be cancelled if | ||
| 1873 | * all the buffers get cleaned later. | ||
| 1874 | */ | ||
| 1875 | lock_page(page); | ||
| 1876 | if (nilfs_page_buffers_clean(page)) | ||
| 1877 | __nilfs_clear_page_dirty(page); | ||
| 1878 | unlock_page(page); | ||
| 1879 | } | ||
| 1867 | return; | 1880 | return; |
| 1881 | } | ||
| 1868 | 1882 | ||
| 1869 | __nilfs_end_page_io(page, err); | 1883 | __nilfs_end_page_io(page, err); |
| 1870 | } | 1884 | } |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 70f36c043d6..38f7bd559f3 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
| @@ -2043,7 +2043,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
| 2043 | invalidate_bdev(sb->s_bdev); | 2043 | invalidate_bdev(sb->s_bdev); |
| 2044 | } | 2044 | } |
| 2045 | mutex_lock(&dqopt->dqonoff_mutex); | 2045 | mutex_lock(&dqopt->dqonoff_mutex); |
| 2046 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | ||
| 2047 | if (sb_has_quota_loaded(sb, type)) { | 2046 | if (sb_has_quota_loaded(sb, type)) { |
| 2048 | error = -EBUSY; | 2047 | error = -EBUSY; |
| 2049 | goto out_lock; | 2048 | goto out_lock; |
| @@ -2054,9 +2053,11 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
| 2054 | * possible) Also nobody should write to the file - we use | 2053 | * possible) Also nobody should write to the file - we use |
| 2055 | * special IO operations which ignore the immutable bit. */ | 2054 | * special IO operations which ignore the immutable bit. */ |
| 2056 | down_write(&dqopt->dqptr_sem); | 2055 | down_write(&dqopt->dqptr_sem); |
| 2056 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | ||
| 2057 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | | 2057 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | |
| 2058 | S_NOQUOTA); | 2058 | S_NOQUOTA); |
| 2059 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; | 2059 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; |
| 2060 | mutex_unlock(&inode->i_mutex); | ||
| 2060 | up_write(&dqopt->dqptr_sem); | 2061 | up_write(&dqopt->dqptr_sem); |
| 2061 | sb->dq_op->drop(inode); | 2062 | sb->dq_op->drop(inode); |
| 2062 | } | 2063 | } |
| @@ -2080,7 +2081,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
| 2080 | goto out_file_init; | 2081 | goto out_file_init; |
| 2081 | } | 2082 | } |
| 2082 | mutex_unlock(&dqopt->dqio_mutex); | 2083 | mutex_unlock(&dqopt->dqio_mutex); |
| 2083 | mutex_unlock(&inode->i_mutex); | ||
| 2084 | spin_lock(&dq_state_lock); | 2084 | spin_lock(&dq_state_lock); |
| 2085 | dqopt->flags |= dquot_state_flag(flags, type); | 2085 | dqopt->flags |= dquot_state_flag(flags, type); |
| 2086 | spin_unlock(&dq_state_lock); | 2086 | spin_unlock(&dq_state_lock); |
| @@ -2096,13 +2096,14 @@ out_file_init: | |||
| 2096 | out_lock: | 2096 | out_lock: |
| 2097 | if (oldflags != -1) { | 2097 | if (oldflags != -1) { |
| 2098 | down_write(&dqopt->dqptr_sem); | 2098 | down_write(&dqopt->dqptr_sem); |
| 2099 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | ||
| 2099 | /* Set the flags back (in the case of accidental quotaon() | 2100 | /* Set the flags back (in the case of accidental quotaon() |
| 2100 | * on a wrong file we don't want to mess up the flags) */ | 2101 | * on a wrong file we don't want to mess up the flags) */ |
| 2101 | inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE); | 2102 | inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE); |
| 2102 | inode->i_flags |= oldflags; | 2103 | inode->i_flags |= oldflags; |
| 2104 | mutex_unlock(&inode->i_mutex); | ||
| 2103 | up_write(&dqopt->dqptr_sem); | 2105 | up_write(&dqopt->dqptr_sem); |
| 2104 | } | 2106 | } |
| 2105 | mutex_unlock(&inode->i_mutex); | ||
| 2106 | mutex_unlock(&dqopt->dqonoff_mutex); | 2107 | mutex_unlock(&dqopt->dqonoff_mutex); |
| 2107 | out_fmt: | 2108 | out_fmt: |
| 2108 | put_quota_format(fmt); | 2109 | put_quota_format(fmt); |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 6832135159b..9d1b8c2e6c4 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
| @@ -1087,11 +1087,23 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | |||
| 1087 | struct udf_inode_info *vati; | 1087 | struct udf_inode_info *vati; |
| 1088 | uint32_t pos; | 1088 | uint32_t pos; |
| 1089 | struct virtualAllocationTable20 *vat20; | 1089 | struct virtualAllocationTable20 *vat20; |
| 1090 | sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; | ||
| 1090 | 1091 | ||
| 1091 | /* VAT file entry is in the last recorded block */ | 1092 | /* VAT file entry is in the last recorded block */ |
| 1092 | ino.partitionReferenceNum = type1_index; | 1093 | ino.partitionReferenceNum = type1_index; |
| 1093 | ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; | 1094 | ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; |
| 1094 | sbi->s_vat_inode = udf_iget(sb, &ino); | 1095 | sbi->s_vat_inode = udf_iget(sb, &ino); |
| 1096 | if (!sbi->s_vat_inode && | ||
| 1097 | sbi->s_last_block != blocks - 1) { | ||
| 1098 | printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" | ||
| 1099 | " last recorded block (%lu), retrying with the last " | ||
| 1100 | "block of the device (%lu).\n", | ||
| 1101 | (unsigned long)sbi->s_last_block, | ||
| 1102 | (unsigned long)blocks - 1); | ||
| 1103 | ino.partitionReferenceNum = type1_index; | ||
| 1104 | ino.logicalBlockNum = blocks - 1 - map->s_partition_root; | ||
| 1105 | sbi->s_vat_inode = udf_iget(sb, &ino); | ||
| 1106 | } | ||
| 1095 | if (!sbi->s_vat_inode) | 1107 | if (!sbi->s_vat_inode) |
| 1096 | return 1; | 1108 | return 1; |
| 1097 | 1109 | ||
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 7ec89fc05b2..aecf2519db7 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
| @@ -1268,6 +1268,14 @@ xfs_vm_writepage( | |||
| 1268 | if (!page_has_buffers(page)) | 1268 | if (!page_has_buffers(page)) |
| 1269 | create_empty_buffers(page, 1 << inode->i_blkbits, 0); | 1269 | create_empty_buffers(page, 1 << inode->i_blkbits, 0); |
| 1270 | 1270 | ||
| 1271 | |||
| 1272 | /* | ||
| 1273 | * VM calculation for nr_to_write seems off. Bump it way | ||
| 1274 | * up, this gets simple streaming writes zippy again. | ||
| 1275 | * To be reviewed again after Jens' writeback changes. | ||
| 1276 | */ | ||
| 1277 | wbc->nr_to_write *= 4; | ||
| 1278 | |||
| 1271 | /* | 1279 | /* |
| 1272 | * Convert delayed allocate, unwritten or unmapped space | 1280 | * Convert delayed allocate, unwritten or unmapped space |
| 1273 | * to real space and flush out to disk. | 1281 | * to real space and flush out to disk. |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 58973bb4603..8070b34cc28 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
| @@ -680,8 +680,8 @@ xfs_vn_fiemap( | |||
| 680 | else | 680 | else |
| 681 | bm.bmv_length = BTOBB(length); | 681 | bm.bmv_length = BTOBB(length); |
| 682 | 682 | ||
| 683 | /* our formatter will tell xfs_getbmap when to stop. */ | 683 | /* We add one because in getbmap world count includes the header */ |
| 684 | bm.bmv_count = MAXEXTNUM; | 684 | bm.bmv_count = fieinfo->fi_extents_max + 1; |
| 685 | bm.bmv_iflags = BMV_IF_PREALLOC; | 685 | bm.bmv_iflags = BMV_IF_PREALLOC; |
| 686 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) | 686 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) |
| 687 | bm.bmv_iflags |= BMV_IF_ATTRFORK; | 687 | bm.bmv_iflags |= BMV_IF_ATTRFORK; |
