diff options
Diffstat (limited to 'fs')
60 files changed, 686 insertions, 410 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index eb1cc92cd67d..908e18455413 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
| @@ -110,7 +110,6 @@ struct autofs_sb_info { | |||
| 110 | int sub_version; | 110 | int sub_version; |
| 111 | int min_proto; | 111 | int min_proto; |
| 112 | int max_proto; | 112 | int max_proto; |
| 113 | int compat_daemon; | ||
| 114 | unsigned long exp_timeout; | 113 | unsigned long exp_timeout; |
| 115 | unsigned int type; | 114 | unsigned int type; |
| 116 | int reghost_enabled; | 115 | int reghost_enabled; |
| @@ -270,6 +269,17 @@ int autofs4_fill_super(struct super_block *, void *, int); | |||
| 270 | struct autofs_info *autofs4_new_ino(struct autofs_sb_info *); | 269 | struct autofs_info *autofs4_new_ino(struct autofs_sb_info *); |
| 271 | void autofs4_clean_ino(struct autofs_info *); | 270 | void autofs4_clean_ino(struct autofs_info *); |
| 272 | 271 | ||
| 272 | static inline int autofs_prepare_pipe(struct file *pipe) | ||
| 273 | { | ||
| 274 | if (!pipe->f_op || !pipe->f_op->write) | ||
| 275 | return -EINVAL; | ||
| 276 | if (!S_ISFIFO(pipe->f_dentry->d_inode->i_mode)) | ||
| 277 | return -EINVAL; | ||
| 278 | /* We want a packet pipe */ | ||
| 279 | pipe->f_flags |= O_DIRECT; | ||
| 280 | return 0; | ||
| 281 | } | ||
| 282 | |||
| 273 | /* Queue management functions */ | 283 | /* Queue management functions */ |
| 274 | 284 | ||
| 275 | int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify); | 285 | int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify); |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 9dacb8586701..aa9103f8f01b 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
| @@ -376,7 +376,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, | |||
| 376 | err = -EBADF; | 376 | err = -EBADF; |
| 377 | goto out; | 377 | goto out; |
| 378 | } | 378 | } |
| 379 | if (!pipe->f_op || !pipe->f_op->write) { | 379 | if (autofs_prepare_pipe(pipe) < 0) { |
| 380 | err = -EPIPE; | 380 | err = -EPIPE; |
| 381 | fput(pipe); | 381 | fput(pipe); |
| 382 | goto out; | 382 | goto out; |
| @@ -385,7 +385,6 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, | |||
| 385 | sbi->pipefd = pipefd; | 385 | sbi->pipefd = pipefd; |
| 386 | sbi->pipe = pipe; | 386 | sbi->pipe = pipe; |
| 387 | sbi->catatonic = 0; | 387 | sbi->catatonic = 0; |
| 388 | sbi->compat_daemon = is_compat_task(); | ||
| 389 | } | 388 | } |
| 390 | out: | 389 | out: |
| 391 | mutex_unlock(&sbi->wq_mutex); | 390 | mutex_unlock(&sbi->wq_mutex); |
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index d8dc002e9cc3..6e488ebe7784 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #include <linux/parser.h> | 19 | #include <linux/parser.h> |
| 20 | #include <linux/bitops.h> | 20 | #include <linux/bitops.h> |
| 21 | #include <linux/magic.h> | 21 | #include <linux/magic.h> |
| 22 | #include <linux/compat.h> | ||
| 23 | #include "autofs_i.h" | 22 | #include "autofs_i.h" |
| 24 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 25 | 24 | ||
| @@ -225,7 +224,6 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
| 225 | set_autofs_type_indirect(&sbi->type); | 224 | set_autofs_type_indirect(&sbi->type); |
| 226 | sbi->min_proto = 0; | 225 | sbi->min_proto = 0; |
| 227 | sbi->max_proto = 0; | 226 | sbi->max_proto = 0; |
| 228 | sbi->compat_daemon = is_compat_task(); | ||
| 229 | mutex_init(&sbi->wq_mutex); | 227 | mutex_init(&sbi->wq_mutex); |
| 230 | mutex_init(&sbi->pipe_mutex); | 228 | mutex_init(&sbi->pipe_mutex); |
| 231 | spin_lock_init(&sbi->fs_lock); | 229 | spin_lock_init(&sbi->fs_lock); |
| @@ -292,7 +290,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
| 292 | printk("autofs: could not open pipe file descriptor\n"); | 290 | printk("autofs: could not open pipe file descriptor\n"); |
| 293 | goto fail_dput; | 291 | goto fail_dput; |
| 294 | } | 292 | } |
| 295 | if (!pipe->f_op || !pipe->f_op->write) | 293 | if (autofs_prepare_pipe(pipe) < 0) |
| 296 | goto fail_fput; | 294 | goto fail_fput; |
| 297 | sbi->pipe = pipe; | 295 | sbi->pipe = pipe; |
| 298 | sbi->pipefd = pipefd; | 296 | sbi->pipefd = pipefd; |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 9c098db43344..da8876d38a7b 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
| @@ -91,24 +91,7 @@ static int autofs4_write(struct autofs_sb_info *sbi, | |||
| 91 | 91 | ||
| 92 | return (bytes > 0); | 92 | return (bytes > 0); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | /* | ||
| 96 | * The autofs_v5 packet was misdesigned. | ||
| 97 | * | ||
| 98 | * The packets are identical on x86-32 and x86-64, but have different | ||
| 99 | * alignment. Which means that 'sizeof()' will give different results. | ||
| 100 | * Fix it up for the case of running 32-bit user mode on a 64-bit kernel. | ||
| 101 | */ | ||
| 102 | static noinline size_t autofs_v5_packet_size(struct autofs_sb_info *sbi) | ||
| 103 | { | ||
| 104 | size_t pktsz = sizeof(struct autofs_v5_packet); | ||
| 105 | #if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT) | ||
| 106 | if (sbi->compat_daemon > 0) | ||
| 107 | pktsz -= 4; | ||
| 108 | #endif | ||
| 109 | return pktsz; | ||
| 110 | } | ||
| 111 | |||
| 112 | static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | 95 | static void autofs4_notify_daemon(struct autofs_sb_info *sbi, |
| 113 | struct autofs_wait_queue *wq, | 96 | struct autofs_wait_queue *wq, |
| 114 | int type) | 97 | int type) |
| @@ -172,7 +155,8 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
| 172 | { | 155 | { |
| 173 | struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet; | 156 | struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet; |
| 174 | 157 | ||
| 175 | pktsz = autofs_v5_packet_size(sbi); | 158 | pktsz = sizeof(*packet); |
| 159 | |||
| 176 | packet->wait_queue_token = wq->wait_queue_token; | 160 | packet->wait_queue_token = wq->wait_queue_token; |
| 177 | packet->len = wq->name.len; | 161 | packet->len = wq->name.len; |
| 178 | memcpy(packet->name, wq->name.name, wq->name.len); | 162 | memcpy(packet->name, wq->name.name, wq->name.len); |
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index f4e90748940a..bcec06750232 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "ulist.h" | 22 | #include "ulist.h" |
| 23 | #include "transaction.h" | 23 | #include "transaction.h" |
| 24 | #include "delayed-ref.h" | 24 | #include "delayed-ref.h" |
| 25 | #include "locking.h" | ||
| 25 | 26 | ||
| 26 | /* | 27 | /* |
| 27 | * this structure records all encountered refs on the way up to the root | 28 | * this structure records all encountered refs on the way up to the root |
| @@ -893,18 +894,22 @@ static char *iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | |||
| 893 | s64 bytes_left = size - 1; | 894 | s64 bytes_left = size - 1; |
| 894 | struct extent_buffer *eb = eb_in; | 895 | struct extent_buffer *eb = eb_in; |
| 895 | struct btrfs_key found_key; | 896 | struct btrfs_key found_key; |
| 897 | int leave_spinning = path->leave_spinning; | ||
| 896 | 898 | ||
| 897 | if (bytes_left >= 0) | 899 | if (bytes_left >= 0) |
| 898 | dest[bytes_left] = '\0'; | 900 | dest[bytes_left] = '\0'; |
| 899 | 901 | ||
| 902 | path->leave_spinning = 1; | ||
| 900 | while (1) { | 903 | while (1) { |
| 901 | len = btrfs_inode_ref_name_len(eb, iref); | 904 | len = btrfs_inode_ref_name_len(eb, iref); |
| 902 | bytes_left -= len; | 905 | bytes_left -= len; |
| 903 | if (bytes_left >= 0) | 906 | if (bytes_left >= 0) |
| 904 | read_extent_buffer(eb, dest + bytes_left, | 907 | read_extent_buffer(eb, dest + bytes_left, |
| 905 | (unsigned long)(iref + 1), len); | 908 | (unsigned long)(iref + 1), len); |
| 906 | if (eb != eb_in) | 909 | if (eb != eb_in) { |
| 910 | btrfs_tree_read_unlock_blocking(eb); | ||
| 907 | free_extent_buffer(eb); | 911 | free_extent_buffer(eb); |
| 912 | } | ||
| 908 | ret = inode_ref_info(parent, 0, fs_root, path, &found_key); | 913 | ret = inode_ref_info(parent, 0, fs_root, path, &found_key); |
| 909 | if (ret > 0) | 914 | if (ret > 0) |
| 910 | ret = -ENOENT; | 915 | ret = -ENOENT; |
| @@ -919,8 +924,11 @@ static char *iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | |||
| 919 | slot = path->slots[0]; | 924 | slot = path->slots[0]; |
| 920 | eb = path->nodes[0]; | 925 | eb = path->nodes[0]; |
| 921 | /* make sure we can use eb after releasing the path */ | 926 | /* make sure we can use eb after releasing the path */ |
| 922 | if (eb != eb_in) | 927 | if (eb != eb_in) { |
| 923 | atomic_inc(&eb->refs); | 928 | atomic_inc(&eb->refs); |
| 929 | btrfs_tree_read_lock(eb); | ||
| 930 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | ||
| 931 | } | ||
| 924 | btrfs_release_path(path); | 932 | btrfs_release_path(path); |
| 925 | 933 | ||
| 926 | iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref); | 934 | iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref); |
| @@ -931,6 +939,7 @@ static char *iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | |||
| 931 | } | 939 | } |
| 932 | 940 | ||
| 933 | btrfs_release_path(path); | 941 | btrfs_release_path(path); |
| 942 | path->leave_spinning = leave_spinning; | ||
| 934 | 943 | ||
| 935 | if (ret) | 944 | if (ret) |
| 936 | return ERR_PTR(ret); | 945 | return ERR_PTR(ret); |
| @@ -1247,7 +1256,7 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root, | |||
| 1247 | struct btrfs_path *path, | 1256 | struct btrfs_path *path, |
| 1248 | iterate_irefs_t *iterate, void *ctx) | 1257 | iterate_irefs_t *iterate, void *ctx) |
| 1249 | { | 1258 | { |
| 1250 | int ret; | 1259 | int ret = 0; |
| 1251 | int slot; | 1260 | int slot; |
| 1252 | u32 cur; | 1261 | u32 cur; |
| 1253 | u32 len; | 1262 | u32 len; |
| @@ -1259,7 +1268,8 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root, | |||
| 1259 | struct btrfs_inode_ref *iref; | 1268 | struct btrfs_inode_ref *iref; |
| 1260 | struct btrfs_key found_key; | 1269 | struct btrfs_key found_key; |
| 1261 | 1270 | ||
| 1262 | while (1) { | 1271 | while (!ret) { |
| 1272 | path->leave_spinning = 1; | ||
| 1263 | ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path, | 1273 | ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path, |
| 1264 | &found_key); | 1274 | &found_key); |
| 1265 | if (ret < 0) | 1275 | if (ret < 0) |
| @@ -1275,6 +1285,8 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root, | |||
| 1275 | eb = path->nodes[0]; | 1285 | eb = path->nodes[0]; |
| 1276 | /* make sure we can use eb after releasing the path */ | 1286 | /* make sure we can use eb after releasing the path */ |
| 1277 | atomic_inc(&eb->refs); | 1287 | atomic_inc(&eb->refs); |
| 1288 | btrfs_tree_read_lock(eb); | ||
| 1289 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | ||
| 1278 | btrfs_release_path(path); | 1290 | btrfs_release_path(path); |
| 1279 | 1291 | ||
| 1280 | item = btrfs_item_nr(eb, slot); | 1292 | item = btrfs_item_nr(eb, slot); |
| @@ -1288,13 +1300,12 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root, | |||
| 1288 | (unsigned long long)found_key.objectid, | 1300 | (unsigned long long)found_key.objectid, |
| 1289 | (unsigned long long)fs_root->objectid); | 1301 | (unsigned long long)fs_root->objectid); |
| 1290 | ret = iterate(parent, iref, eb, ctx); | 1302 | ret = iterate(parent, iref, eb, ctx); |
| 1291 | if (ret) { | 1303 | if (ret) |
| 1292 | free_extent_buffer(eb); | ||
| 1293 | break; | 1304 | break; |
| 1294 | } | ||
| 1295 | len = sizeof(*iref) + name_len; | 1305 | len = sizeof(*iref) + name_len; |
| 1296 | iref = (struct btrfs_inode_ref *)((char *)iref + len); | 1306 | iref = (struct btrfs_inode_ref *)((char *)iref + len); |
| 1297 | } | 1307 | } |
| 1308 | btrfs_tree_read_unlock_blocking(eb); | ||
| 1298 | free_extent_buffer(eb); | 1309 | free_extent_buffer(eb); |
| 1299 | } | 1310 | } |
| 1300 | 1311 | ||
| @@ -1414,6 +1425,8 @@ struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, | |||
| 1414 | 1425 | ||
| 1415 | void free_ipath(struct inode_fs_paths *ipath) | 1426 | void free_ipath(struct inode_fs_paths *ipath) |
| 1416 | { | 1427 | { |
| 1428 | if (!ipath) | ||
| 1429 | return; | ||
| 1417 | kfree(ipath->fspath); | 1430 | kfree(ipath->fspath); |
| 1418 | kfree(ipath); | 1431 | kfree(ipath); |
| 1419 | } | 1432 | } |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index e801f226d7e0..4106264fbc65 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -220,10 +220,12 @@ struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) | |||
| 220 | */ | 220 | */ |
| 221 | static void add_root_to_dirty_list(struct btrfs_root *root) | 221 | static void add_root_to_dirty_list(struct btrfs_root *root) |
| 222 | { | 222 | { |
| 223 | spin_lock(&root->fs_info->trans_lock); | ||
| 223 | if (root->track_dirty && list_empty(&root->dirty_list)) { | 224 | if (root->track_dirty && list_empty(&root->dirty_list)) { |
| 224 | list_add(&root->dirty_list, | 225 | list_add(&root->dirty_list, |
| 225 | &root->fs_info->dirty_cowonly_roots); | 226 | &root->fs_info->dirty_cowonly_roots); |
| 226 | } | 227 | } |
| 228 | spin_unlock(&root->fs_info->trans_lock); | ||
| 227 | } | 229 | } |
| 228 | 230 | ||
| 229 | /* | 231 | /* |
| @@ -723,7 +725,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 723 | 725 | ||
| 724 | cur = btrfs_find_tree_block(root, blocknr, blocksize); | 726 | cur = btrfs_find_tree_block(root, blocknr, blocksize); |
| 725 | if (cur) | 727 | if (cur) |
| 726 | uptodate = btrfs_buffer_uptodate(cur, gen); | 728 | uptodate = btrfs_buffer_uptodate(cur, gen, 0); |
| 727 | else | 729 | else |
| 728 | uptodate = 0; | 730 | uptodate = 0; |
| 729 | if (!cur || !uptodate) { | 731 | if (!cur || !uptodate) { |
| @@ -1358,7 +1360,12 @@ static noinline int reada_for_balance(struct btrfs_root *root, | |||
| 1358 | block1 = btrfs_node_blockptr(parent, slot - 1); | 1360 | block1 = btrfs_node_blockptr(parent, slot - 1); |
| 1359 | gen = btrfs_node_ptr_generation(parent, slot - 1); | 1361 | gen = btrfs_node_ptr_generation(parent, slot - 1); |
| 1360 | eb = btrfs_find_tree_block(root, block1, blocksize); | 1362 | eb = btrfs_find_tree_block(root, block1, blocksize); |
| 1361 | if (eb && btrfs_buffer_uptodate(eb, gen)) | 1363 | /* |
| 1364 | * if we get -eagain from btrfs_buffer_uptodate, we | ||
| 1365 | * don't want to return eagain here. That will loop | ||
| 1366 | * forever | ||
| 1367 | */ | ||
| 1368 | if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0) | ||
| 1362 | block1 = 0; | 1369 | block1 = 0; |
| 1363 | free_extent_buffer(eb); | 1370 | free_extent_buffer(eb); |
| 1364 | } | 1371 | } |
| @@ -1366,7 +1373,7 @@ static noinline int reada_for_balance(struct btrfs_root *root, | |||
| 1366 | block2 = btrfs_node_blockptr(parent, slot + 1); | 1373 | block2 = btrfs_node_blockptr(parent, slot + 1); |
| 1367 | gen = btrfs_node_ptr_generation(parent, slot + 1); | 1374 | gen = btrfs_node_ptr_generation(parent, slot + 1); |
| 1368 | eb = btrfs_find_tree_block(root, block2, blocksize); | 1375 | eb = btrfs_find_tree_block(root, block2, blocksize); |
| 1369 | if (eb && btrfs_buffer_uptodate(eb, gen)) | 1376 | if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0) |
| 1370 | block2 = 0; | 1377 | block2 = 0; |
| 1371 | free_extent_buffer(eb); | 1378 | free_extent_buffer(eb); |
| 1372 | } | 1379 | } |
| @@ -1504,8 +1511,9 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
| 1504 | 1511 | ||
| 1505 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); | 1512 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); |
| 1506 | if (tmp) { | 1513 | if (tmp) { |
| 1507 | if (btrfs_buffer_uptodate(tmp, 0)) { | 1514 | /* first we do an atomic uptodate check */ |
| 1508 | if (btrfs_buffer_uptodate(tmp, gen)) { | 1515 | if (btrfs_buffer_uptodate(tmp, 0, 1) > 0) { |
| 1516 | if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) { | ||
| 1509 | /* | 1517 | /* |
| 1510 | * we found an up to date block without | 1518 | * we found an up to date block without |
| 1511 | * sleeping, return | 1519 | * sleeping, return |
| @@ -1523,8 +1531,9 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
| 1523 | free_extent_buffer(tmp); | 1531 | free_extent_buffer(tmp); |
| 1524 | btrfs_set_path_blocking(p); | 1532 | btrfs_set_path_blocking(p); |
| 1525 | 1533 | ||
| 1534 | /* now we're allowed to do a blocking uptodate check */ | ||
| 1526 | tmp = read_tree_block(root, blocknr, blocksize, gen); | 1535 | tmp = read_tree_block(root, blocknr, blocksize, gen); |
| 1527 | if (tmp && btrfs_buffer_uptodate(tmp, gen)) { | 1536 | if (tmp && btrfs_buffer_uptodate(tmp, gen, 0) > 0) { |
| 1528 | *eb_ret = tmp; | 1537 | *eb_ret = tmp; |
| 1529 | return 0; | 1538 | return 0; |
| 1530 | } | 1539 | } |
| @@ -1559,7 +1568,7 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
| 1559 | * and give up so that our caller doesn't loop forever | 1568 | * and give up so that our caller doesn't loop forever |
| 1560 | * on our EAGAINs. | 1569 | * on our EAGAINs. |
| 1561 | */ | 1570 | */ |
| 1562 | if (!btrfs_buffer_uptodate(tmp, 0)) | 1571 | if (!btrfs_buffer_uptodate(tmp, 0, 0)) |
| 1563 | ret = -EIO; | 1572 | ret = -EIO; |
| 1564 | free_extent_buffer(tmp); | 1573 | free_extent_buffer(tmp); |
| 1565 | } | 1574 | } |
| @@ -4043,7 +4052,7 @@ again: | |||
| 4043 | tmp = btrfs_find_tree_block(root, blockptr, | 4052 | tmp = btrfs_find_tree_block(root, blockptr, |
| 4044 | btrfs_level_size(root, level - 1)); | 4053 | btrfs_level_size(root, level - 1)); |
| 4045 | 4054 | ||
| 4046 | if (tmp && btrfs_buffer_uptodate(tmp, gen)) { | 4055 | if (tmp && btrfs_buffer_uptodate(tmp, gen, 1) > 0) { |
| 4047 | free_extent_buffer(tmp); | 4056 | free_extent_buffer(tmp); |
| 4048 | break; | 4057 | break; |
| 4049 | } | 4058 | } |
| @@ -4166,7 +4175,8 @@ next: | |||
| 4166 | struct extent_buffer *cur; | 4175 | struct extent_buffer *cur; |
| 4167 | cur = btrfs_find_tree_block(root, blockptr, | 4176 | cur = btrfs_find_tree_block(root, blockptr, |
| 4168 | btrfs_level_size(root, level - 1)); | 4177 | btrfs_level_size(root, level - 1)); |
| 4169 | if (!cur || !btrfs_buffer_uptodate(cur, gen)) { | 4178 | if (!cur || |
| 4179 | btrfs_buffer_uptodate(cur, gen, 1) <= 0) { | ||
| 4170 | slot++; | 4180 | slot++; |
| 4171 | if (cur) | 4181 | if (cur) |
| 4172 | free_extent_buffer(cur); | 4182 | free_extent_buffer(cur); |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 3f65a812e282..8fd72331d600 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -1078,7 +1078,7 @@ struct btrfs_fs_info { | |||
| 1078 | * is required instead of the faster short fsync log commits | 1078 | * is required instead of the faster short fsync log commits |
| 1079 | */ | 1079 | */ |
| 1080 | u64 last_trans_log_full_commit; | 1080 | u64 last_trans_log_full_commit; |
| 1081 | unsigned long mount_opt:21; | 1081 | unsigned long mount_opt; |
| 1082 | unsigned long compress_type:4; | 1082 | unsigned long compress_type:4; |
| 1083 | u64 max_inline; | 1083 | u64 max_inline; |
| 1084 | u64 alloc_start; | 1084 | u64 alloc_start; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 20196f411206..a7ffc88a7dbe 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -323,7 +323,8 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, | |||
| 323 | * in the wrong place. | 323 | * in the wrong place. |
| 324 | */ | 324 | */ |
| 325 | static int verify_parent_transid(struct extent_io_tree *io_tree, | 325 | static int verify_parent_transid(struct extent_io_tree *io_tree, |
| 326 | struct extent_buffer *eb, u64 parent_transid) | 326 | struct extent_buffer *eb, u64 parent_transid, |
| 327 | int atomic) | ||
| 327 | { | 328 | { |
| 328 | struct extent_state *cached_state = NULL; | 329 | struct extent_state *cached_state = NULL; |
| 329 | int ret; | 330 | int ret; |
| @@ -331,6 +332,9 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
| 331 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) | 332 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) |
| 332 | return 0; | 333 | return 0; |
| 333 | 334 | ||
| 335 | if (atomic) | ||
| 336 | return -EAGAIN; | ||
| 337 | |||
| 334 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, | 338 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, |
| 335 | 0, &cached_state); | 339 | 0, &cached_state); |
| 336 | if (extent_buffer_uptodate(eb) && | 340 | if (extent_buffer_uptodate(eb) && |
| @@ -372,7 +376,8 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, | |||
| 372 | ret = read_extent_buffer_pages(io_tree, eb, start, | 376 | ret = read_extent_buffer_pages(io_tree, eb, start, |
| 373 | WAIT_COMPLETE, | 377 | WAIT_COMPLETE, |
| 374 | btree_get_extent, mirror_num); | 378 | btree_get_extent, mirror_num); |
| 375 | if (!ret && !verify_parent_transid(io_tree, eb, parent_transid)) | 379 | if (!ret && !verify_parent_transid(io_tree, eb, |
| 380 | parent_transid, 0)) | ||
| 376 | break; | 381 | break; |
| 377 | 382 | ||
| 378 | /* | 383 | /* |
| @@ -383,17 +388,16 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, | |||
| 383 | if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) | 388 | if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) |
| 384 | break; | 389 | break; |
| 385 | 390 | ||
| 386 | if (!failed_mirror) { | ||
| 387 | failed = 1; | ||
| 388 | printk(KERN_ERR "failed mirror was %d\n", eb->failed_mirror); | ||
| 389 | failed_mirror = eb->failed_mirror; | ||
| 390 | } | ||
| 391 | |||
| 392 | num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, | 391 | num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, |
| 393 | eb->start, eb->len); | 392 | eb->start, eb->len); |
| 394 | if (num_copies == 1) | 393 | if (num_copies == 1) |
| 395 | break; | 394 | break; |
| 396 | 395 | ||
| 396 | if (!failed_mirror) { | ||
| 397 | failed = 1; | ||
| 398 | failed_mirror = eb->read_mirror; | ||
| 399 | } | ||
| 400 | |||
| 397 | mirror_num++; | 401 | mirror_num++; |
| 398 | if (mirror_num == failed_mirror) | 402 | if (mirror_num == failed_mirror) |
| 399 | mirror_num++; | 403 | mirror_num++; |
| @@ -564,7 +568,7 @@ struct extent_buffer *find_eb_for_page(struct extent_io_tree *tree, | |||
| 564 | } | 568 | } |
| 565 | 569 | ||
| 566 | static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, | 570 | static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, |
| 567 | struct extent_state *state) | 571 | struct extent_state *state, int mirror) |
| 568 | { | 572 | { |
| 569 | struct extent_io_tree *tree; | 573 | struct extent_io_tree *tree; |
| 570 | u64 found_start; | 574 | u64 found_start; |
| @@ -589,6 +593,7 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
| 589 | if (!reads_done) | 593 | if (!reads_done) |
| 590 | goto err; | 594 | goto err; |
| 591 | 595 | ||
| 596 | eb->read_mirror = mirror; | ||
| 592 | if (test_bit(EXTENT_BUFFER_IOERR, &eb->bflags)) { | 597 | if (test_bit(EXTENT_BUFFER_IOERR, &eb->bflags)) { |
| 593 | ret = -EIO; | 598 | ret = -EIO; |
| 594 | goto err; | 599 | goto err; |
| @@ -652,7 +657,7 @@ static int btree_io_failed_hook(struct page *page, int failed_mirror) | |||
| 652 | 657 | ||
| 653 | eb = (struct extent_buffer *)page->private; | 658 | eb = (struct extent_buffer *)page->private; |
| 654 | set_bit(EXTENT_BUFFER_IOERR, &eb->bflags); | 659 | set_bit(EXTENT_BUFFER_IOERR, &eb->bflags); |
| 655 | eb->failed_mirror = failed_mirror; | 660 | eb->read_mirror = failed_mirror; |
| 656 | if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) | 661 | if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) |
| 657 | btree_readahead_hook(root, eb, eb->start, -EIO); | 662 | btree_readahead_hook(root, eb, eb->start, -EIO); |
| 658 | return -EIO; /* we fixed nothing */ | 663 | return -EIO; /* we fixed nothing */ |
| @@ -1202,7 +1207,7 @@ static int __must_check find_and_setup_root(struct btrfs_root *tree_root, | |||
| 1202 | root->commit_root = NULL; | 1207 | root->commit_root = NULL; |
| 1203 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), | 1208 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
| 1204 | blocksize, generation); | 1209 | blocksize, generation); |
| 1205 | if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) { | 1210 | if (!root->node || !btrfs_buffer_uptodate(root->node, generation, 0)) { |
| 1206 | free_extent_buffer(root->node); | 1211 | free_extent_buffer(root->node); |
| 1207 | root->node = NULL; | 1212 | root->node = NULL; |
| 1208 | return -EIO; | 1213 | return -EIO; |
| @@ -2254,9 +2259,9 @@ int open_ctree(struct super_block *sb, | |||
| 2254 | goto fail_sb_buffer; | 2259 | goto fail_sb_buffer; |
| 2255 | } | 2260 | } |
| 2256 | 2261 | ||
| 2257 | if (sectorsize < PAGE_SIZE) { | 2262 | if (sectorsize != PAGE_SIZE) { |
| 2258 | printk(KERN_WARNING "btrfs: Incompatible sector size " | 2263 | printk(KERN_WARNING "btrfs: Incompatible sector size(%lu) " |
| 2259 | "found on %s\n", sb->s_id); | 2264 | "found on %s\n", (unsigned long)sectorsize, sb->s_id); |
| 2260 | goto fail_sb_buffer; | 2265 | goto fail_sb_buffer; |
| 2261 | } | 2266 | } |
| 2262 | 2267 | ||
| @@ -3143,7 +3148,8 @@ int close_ctree(struct btrfs_root *root) | |||
| 3143 | return 0; | 3148 | return 0; |
| 3144 | } | 3149 | } |
| 3145 | 3150 | ||
| 3146 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) | 3151 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, |
| 3152 | int atomic) | ||
| 3147 | { | 3153 | { |
| 3148 | int ret; | 3154 | int ret; |
| 3149 | struct inode *btree_inode = buf->pages[0]->mapping->host; | 3155 | struct inode *btree_inode = buf->pages[0]->mapping->host; |
| @@ -3153,7 +3159,9 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) | |||
| 3153 | return ret; | 3159 | return ret; |
| 3154 | 3160 | ||
| 3155 | ret = verify_parent_transid(&BTRFS_I(btree_inode)->io_tree, buf, | 3161 | ret = verify_parent_transid(&BTRFS_I(btree_inode)->io_tree, buf, |
| 3156 | parent_transid); | 3162 | parent_transid, atomic); |
| 3163 | if (ret == -EAGAIN) | ||
| 3164 | return ret; | ||
| 3157 | return !ret; | 3165 | return !ret; |
| 3158 | } | 3166 | } |
| 3159 | 3167 | ||
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index a7ace1a2dd12..ab1830aaf0ed 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
| @@ -66,7 +66,8 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); | |||
| 66 | void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); | 66 | void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); |
| 67 | void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); | 67 | void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); |
| 68 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf); | 68 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf); |
| 69 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid); | 69 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, |
| 70 | int atomic); | ||
| 70 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf); | 71 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf); |
| 71 | int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid); | 72 | int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid); |
| 72 | u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len); | 73 | u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2b35f8d14bb9..49fd7b66d57b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -2301,6 +2301,7 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans, | |||
| 2301 | 2301 | ||
| 2302 | if (ret) { | 2302 | if (ret) { |
| 2303 | printk(KERN_DEBUG "btrfs: run_delayed_extent_op returned %d\n", ret); | 2303 | printk(KERN_DEBUG "btrfs: run_delayed_extent_op returned %d\n", ret); |
| 2304 | spin_lock(&delayed_refs->lock); | ||
| 2304 | return ret; | 2305 | return ret; |
| 2305 | } | 2306 | } |
| 2306 | 2307 | ||
| @@ -2331,6 +2332,7 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans, | |||
| 2331 | 2332 | ||
| 2332 | if (ret) { | 2333 | if (ret) { |
| 2333 | printk(KERN_DEBUG "btrfs: run_one_delayed_ref returned %d\n", ret); | 2334 | printk(KERN_DEBUG "btrfs: run_one_delayed_ref returned %d\n", ret); |
| 2335 | spin_lock(&delayed_refs->lock); | ||
| 2334 | return ret; | 2336 | return ret; |
| 2335 | } | 2337 | } |
| 2336 | 2338 | ||
| @@ -3769,13 +3771,10 @@ again: | |||
| 3769 | */ | 3771 | */ |
| 3770 | if (current->journal_info) | 3772 | if (current->journal_info) |
| 3771 | return -EAGAIN; | 3773 | return -EAGAIN; |
| 3772 | ret = wait_event_interruptible(space_info->wait, | 3774 | ret = wait_event_killable(space_info->wait, !space_info->flush); |
| 3773 | !space_info->flush); | 3775 | /* Must have been killed, return */ |
| 3774 | /* Must have been interrupted, return */ | 3776 | if (ret) |
| 3775 | if (ret) { | ||
| 3776 | printk(KERN_DEBUG "btrfs: %s returning -EINTR\n", __func__); | ||
| 3777 | return -EINTR; | 3777 | return -EINTR; |
| 3778 | } | ||
| 3779 | 3778 | ||
| 3780 | spin_lock(&space_info->lock); | 3779 | spin_lock(&space_info->lock); |
| 3781 | } | 3780 | } |
| @@ -4215,8 +4214,8 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info) | |||
| 4215 | 4214 | ||
| 4216 | num_bytes = calc_global_metadata_size(fs_info); | 4215 | num_bytes = calc_global_metadata_size(fs_info); |
| 4217 | 4216 | ||
| 4218 | spin_lock(&block_rsv->lock); | ||
| 4219 | spin_lock(&sinfo->lock); | 4217 | spin_lock(&sinfo->lock); |
| 4218 | spin_lock(&block_rsv->lock); | ||
| 4220 | 4219 | ||
| 4221 | block_rsv->size = num_bytes; | 4220 | block_rsv->size = num_bytes; |
| 4222 | 4221 | ||
| @@ -4242,8 +4241,8 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info) | |||
| 4242 | block_rsv->full = 1; | 4241 | block_rsv->full = 1; |
| 4243 | } | 4242 | } |
| 4244 | 4243 | ||
| 4245 | spin_unlock(&sinfo->lock); | ||
| 4246 | spin_unlock(&block_rsv->lock); | 4244 | spin_unlock(&block_rsv->lock); |
| 4245 | spin_unlock(&sinfo->lock); | ||
| 4247 | } | 4246 | } |
| 4248 | 4247 | ||
| 4249 | static void init_global_block_rsv(struct btrfs_fs_info *fs_info) | 4248 | static void init_global_block_rsv(struct btrfs_fs_info *fs_info) |
| @@ -6569,7 +6568,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, | |||
| 6569 | goto skip; | 6568 | goto skip; |
| 6570 | } | 6569 | } |
| 6571 | 6570 | ||
| 6572 | if (!btrfs_buffer_uptodate(next, generation)) { | 6571 | if (!btrfs_buffer_uptodate(next, generation, 0)) { |
| 6573 | btrfs_tree_unlock(next); | 6572 | btrfs_tree_unlock(next); |
| 6574 | free_extent_buffer(next); | 6573 | free_extent_buffer(next); |
| 6575 | next = NULL; | 6574 | next = NULL; |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index cd4b5e400221..c9018a05036e 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -402,20 +402,28 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig, | |||
| 402 | return 0; | 402 | return 0; |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | static struct extent_state *next_state(struct extent_state *state) | ||
| 406 | { | ||
| 407 | struct rb_node *next = rb_next(&state->rb_node); | ||
| 408 | if (next) | ||
| 409 | return rb_entry(next, struct extent_state, rb_node); | ||
| 410 | else | ||
| 411 | return NULL; | ||
| 412 | } | ||
| 413 | |||
| 405 | /* | 414 | /* |
| 406 | * utility function to clear some bits in an extent state struct. | 415 | * utility function to clear some bits in an extent state struct. |
| 407 | * it will optionally wake up any one waiting on this state (wake == 1), or | 416 | * it will optionally wake up any one waiting on this state (wake == 1) |
| 408 | * forcibly remove the state from the tree (delete == 1). | ||
| 409 | * | 417 | * |
| 410 | * If no bits are set on the state struct after clearing things, the | 418 | * If no bits are set on the state struct after clearing things, the |
| 411 | * struct is freed and removed from the tree | 419 | * struct is freed and removed from the tree |
| 412 | */ | 420 | */ |
| 413 | static int clear_state_bit(struct extent_io_tree *tree, | 421 | static struct extent_state *clear_state_bit(struct extent_io_tree *tree, |
| 414 | struct extent_state *state, | 422 | struct extent_state *state, |
| 415 | int *bits, int wake) | 423 | int *bits, int wake) |
| 416 | { | 424 | { |
| 425 | struct extent_state *next; | ||
| 417 | int bits_to_clear = *bits & ~EXTENT_CTLBITS; | 426 | int bits_to_clear = *bits & ~EXTENT_CTLBITS; |
| 418 | int ret = state->state & bits_to_clear; | ||
| 419 | 427 | ||
| 420 | if ((bits_to_clear & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) { | 428 | if ((bits_to_clear & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) { |
| 421 | u64 range = state->end - state->start + 1; | 429 | u64 range = state->end - state->start + 1; |
| @@ -427,6 +435,7 @@ static int clear_state_bit(struct extent_io_tree *tree, | |||
| 427 | if (wake) | 435 | if (wake) |
| 428 | wake_up(&state->wq); | 436 | wake_up(&state->wq); |
| 429 | if (state->state == 0) { | 437 | if (state->state == 0) { |
| 438 | next = next_state(state); | ||
| 430 | if (state->tree) { | 439 | if (state->tree) { |
| 431 | rb_erase(&state->rb_node, &tree->state); | 440 | rb_erase(&state->rb_node, &tree->state); |
| 432 | state->tree = NULL; | 441 | state->tree = NULL; |
| @@ -436,8 +445,9 @@ static int clear_state_bit(struct extent_io_tree *tree, | |||
| 436 | } | 445 | } |
| 437 | } else { | 446 | } else { |
| 438 | merge_state(tree, state); | 447 | merge_state(tree, state); |
| 448 | next = next_state(state); | ||
| 439 | } | 449 | } |
| 440 | return ret; | 450 | return next; |
| 441 | } | 451 | } |
| 442 | 452 | ||
| 443 | static struct extent_state * | 453 | static struct extent_state * |
| @@ -476,7 +486,6 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | |||
| 476 | struct extent_state *state; | 486 | struct extent_state *state; |
| 477 | struct extent_state *cached; | 487 | struct extent_state *cached; |
| 478 | struct extent_state *prealloc = NULL; | 488 | struct extent_state *prealloc = NULL; |
| 479 | struct rb_node *next_node; | ||
| 480 | struct rb_node *node; | 489 | struct rb_node *node; |
| 481 | u64 last_end; | 490 | u64 last_end; |
| 482 | int err; | 491 | int err; |
| @@ -528,14 +537,11 @@ hit_next: | |||
| 528 | WARN_ON(state->end < start); | 537 | WARN_ON(state->end < start); |
| 529 | last_end = state->end; | 538 | last_end = state->end; |
| 530 | 539 | ||
| 531 | if (state->end < end && !need_resched()) | ||
| 532 | next_node = rb_next(&state->rb_node); | ||
| 533 | else | ||
| 534 | next_node = NULL; | ||
| 535 | |||
| 536 | /* the state doesn't have the wanted bits, go ahead */ | 540 | /* the state doesn't have the wanted bits, go ahead */ |
| 537 | if (!(state->state & bits)) | 541 | if (!(state->state & bits)) { |
| 542 | state = next_state(state); | ||
| 538 | goto next; | 543 | goto next; |
| 544 | } | ||
| 539 | 545 | ||
| 540 | /* | 546 | /* |
| 541 | * | ---- desired range ---- | | 547 | * | ---- desired range ---- | |
| @@ -593,16 +599,13 @@ hit_next: | |||
| 593 | goto out; | 599 | goto out; |
| 594 | } | 600 | } |
| 595 | 601 | ||
| 596 | clear_state_bit(tree, state, &bits, wake); | 602 | state = clear_state_bit(tree, state, &bits, wake); |
| 597 | next: | 603 | next: |
| 598 | if (last_end == (u64)-1) | 604 | if (last_end == (u64)-1) |
| 599 | goto out; | 605 | goto out; |
| 600 | start = last_end + 1; | 606 | start = last_end + 1; |
| 601 | if (start <= end && next_node) { | 607 | if (start <= end && state && !need_resched()) |
| 602 | state = rb_entry(next_node, struct extent_state, | ||
| 603 | rb_node); | ||
| 604 | goto hit_next; | 608 | goto hit_next; |
| 605 | } | ||
| 606 | goto search_again; | 609 | goto search_again; |
| 607 | 610 | ||
| 608 | out: | 611 | out: |
| @@ -2301,7 +2304,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
| 2301 | u64 start; | 2304 | u64 start; |
| 2302 | u64 end; | 2305 | u64 end; |
| 2303 | int whole_page; | 2306 | int whole_page; |
| 2304 | int failed_mirror; | 2307 | int mirror; |
| 2305 | int ret; | 2308 | int ret; |
| 2306 | 2309 | ||
| 2307 | if (err) | 2310 | if (err) |
| @@ -2340,20 +2343,18 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
| 2340 | } | 2343 | } |
| 2341 | spin_unlock(&tree->lock); | 2344 | spin_unlock(&tree->lock); |
| 2342 | 2345 | ||
| 2346 | mirror = (int)(unsigned long)bio->bi_bdev; | ||
| 2343 | if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) { | 2347 | if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) { |
| 2344 | ret = tree->ops->readpage_end_io_hook(page, start, end, | 2348 | ret = tree->ops->readpage_end_io_hook(page, start, end, |
| 2345 | state); | 2349 | state, mirror); |
| 2346 | if (ret) | 2350 | if (ret) |
| 2347 | uptodate = 0; | 2351 | uptodate = 0; |
| 2348 | else | 2352 | else |
| 2349 | clean_io_failure(start, page); | 2353 | clean_io_failure(start, page); |
| 2350 | } | 2354 | } |
| 2351 | 2355 | ||
| 2352 | if (!uptodate) | ||
| 2353 | failed_mirror = (int)(unsigned long)bio->bi_bdev; | ||
| 2354 | |||
| 2355 | if (!uptodate && tree->ops && tree->ops->readpage_io_failed_hook) { | 2356 | if (!uptodate && tree->ops && tree->ops->readpage_io_failed_hook) { |
| 2356 | ret = tree->ops->readpage_io_failed_hook(page, failed_mirror); | 2357 | ret = tree->ops->readpage_io_failed_hook(page, mirror); |
| 2357 | if (!ret && !err && | 2358 | if (!ret && !err && |
| 2358 | test_bit(BIO_UPTODATE, &bio->bi_flags)) | 2359 | test_bit(BIO_UPTODATE, &bio->bi_flags)) |
| 2359 | uptodate = 1; | 2360 | uptodate = 1; |
| @@ -2368,8 +2369,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
| 2368 | * can't handle the error it will return -EIO and we | 2369 | * can't handle the error it will return -EIO and we |
| 2369 | * remain responsible for that page. | 2370 | * remain responsible for that page. |
| 2370 | */ | 2371 | */ |
| 2371 | ret = bio_readpage_error(bio, page, start, end, | 2372 | ret = bio_readpage_error(bio, page, start, end, mirror, NULL); |
| 2372 | failed_mirror, NULL); | ||
| 2373 | if (ret == 0) { | 2373 | if (ret == 0) { |
| 2374 | uptodate = | 2374 | uptodate = |
| 2375 | test_bit(BIO_UPTODATE, &bio->bi_flags); | 2375 | test_bit(BIO_UPTODATE, &bio->bi_flags); |
| @@ -4120,6 +4120,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | |||
| 4120 | if (atomic_inc_not_zero(&exists->refs)) { | 4120 | if (atomic_inc_not_zero(&exists->refs)) { |
| 4121 | spin_unlock(&mapping->private_lock); | 4121 | spin_unlock(&mapping->private_lock); |
| 4122 | unlock_page(p); | 4122 | unlock_page(p); |
| 4123 | page_cache_release(p); | ||
| 4123 | mark_extent_buffer_accessed(exists); | 4124 | mark_extent_buffer_accessed(exists); |
| 4124 | goto free_eb; | 4125 | goto free_eb; |
| 4125 | } | 4126 | } |
| @@ -4199,8 +4200,7 @@ free_eb: | |||
| 4199 | unlock_page(eb->pages[i]); | 4200 | unlock_page(eb->pages[i]); |
| 4200 | } | 4201 | } |
| 4201 | 4202 | ||
| 4202 | if (!atomic_dec_and_test(&eb->refs)) | 4203 | WARN_ON(!atomic_dec_and_test(&eb->refs)); |
| 4203 | return exists; | ||
| 4204 | btrfs_release_extent_buffer(eb); | 4204 | btrfs_release_extent_buffer(eb); |
| 4205 | return exists; | 4205 | return exists; |
| 4206 | } | 4206 | } |
| @@ -4462,7 +4462,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, | |||
| 4462 | } | 4462 | } |
| 4463 | 4463 | ||
| 4464 | clear_bit(EXTENT_BUFFER_IOERR, &eb->bflags); | 4464 | clear_bit(EXTENT_BUFFER_IOERR, &eb->bflags); |
| 4465 | eb->failed_mirror = 0; | 4465 | eb->read_mirror = 0; |
| 4466 | atomic_set(&eb->io_pages, num_reads); | 4466 | atomic_set(&eb->io_pages, num_reads); |
| 4467 | for (i = start_i; i < num_pages; i++) { | 4467 | for (i = start_i; i < num_pages; i++) { |
| 4468 | page = extent_buffer_page(eb, i); | 4468 | page = extent_buffer_page(eb, i); |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index faf10eb57f75..b516c3b8dec6 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
| @@ -79,7 +79,7 @@ struct extent_io_ops { | |||
| 79 | u64 start, u64 end, | 79 | u64 start, u64 end, |
| 80 | struct extent_state *state); | 80 | struct extent_state *state); |
| 81 | int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end, | 81 | int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end, |
| 82 | struct extent_state *state); | 82 | struct extent_state *state, int mirror); |
| 83 | int (*writepage_end_io_hook)(struct page *page, u64 start, u64 end, | 83 | int (*writepage_end_io_hook)(struct page *page, u64 start, u64 end, |
| 84 | struct extent_state *state, int uptodate); | 84 | struct extent_state *state, int uptodate); |
| 85 | void (*set_bit_hook)(struct inode *inode, struct extent_state *state, | 85 | void (*set_bit_hook)(struct inode *inode, struct extent_state *state, |
| @@ -135,7 +135,7 @@ struct extent_buffer { | |||
| 135 | spinlock_t refs_lock; | 135 | spinlock_t refs_lock; |
| 136 | atomic_t refs; | 136 | atomic_t refs; |
| 137 | atomic_t io_pages; | 137 | atomic_t io_pages; |
| 138 | int failed_mirror; | 138 | int read_mirror; |
| 139 | struct list_head leak_list; | 139 | struct list_head leak_list; |
| 140 | struct rcu_head rcu_head; | 140 | struct rcu_head rcu_head; |
| 141 | pid_t lock_owner; | 141 | pid_t lock_owner; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index d83260d7498f..53bf2d764bbc 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -567,6 +567,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode, | |||
| 567 | int extent_type; | 567 | int extent_type; |
| 568 | int recow; | 568 | int recow; |
| 569 | int ret; | 569 | int ret; |
| 570 | int modify_tree = -1; | ||
| 570 | 571 | ||
| 571 | if (drop_cache) | 572 | if (drop_cache) |
| 572 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | 573 | btrfs_drop_extent_cache(inode, start, end - 1, 0); |
| @@ -575,10 +576,13 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode, | |||
| 575 | if (!path) | 576 | if (!path) |
| 576 | return -ENOMEM; | 577 | return -ENOMEM; |
| 577 | 578 | ||
| 579 | if (start >= BTRFS_I(inode)->disk_i_size) | ||
| 580 | modify_tree = 0; | ||
| 581 | |||
| 578 | while (1) { | 582 | while (1) { |
| 579 | recow = 0; | 583 | recow = 0; |
| 580 | ret = btrfs_lookup_file_extent(trans, root, path, ino, | 584 | ret = btrfs_lookup_file_extent(trans, root, path, ino, |
| 581 | search_start, -1); | 585 | search_start, modify_tree); |
| 582 | if (ret < 0) | 586 | if (ret < 0) |
| 583 | break; | 587 | break; |
| 584 | if (ret > 0 && path->slots[0] > 0 && search_start == start) { | 588 | if (ret > 0 && path->slots[0] > 0 && search_start == start) { |
| @@ -634,7 +638,8 @@ next_slot: | |||
| 634 | } | 638 | } |
| 635 | 639 | ||
| 636 | search_start = max(key.offset, start); | 640 | search_start = max(key.offset, start); |
| 637 | if (recow) { | 641 | if (recow || !modify_tree) { |
| 642 | modify_tree = -1; | ||
| 638 | btrfs_release_path(path); | 643 | btrfs_release_path(path); |
| 639 | continue; | 644 | continue; |
| 640 | } | 645 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 115bc05e42b0..61b16c641ce0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -1947,7 +1947,7 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end, | |||
| 1947 | * extent_io.c will try to find good copies for us. | 1947 | * extent_io.c will try to find good copies for us. |
| 1948 | */ | 1948 | */ |
| 1949 | static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end, | 1949 | static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end, |
| 1950 | struct extent_state *state) | 1950 | struct extent_state *state, int mirror) |
| 1951 | { | 1951 | { |
| 1952 | size_t offset = start - ((u64)page->index << PAGE_CACHE_SHIFT); | 1952 | size_t offset = start - ((u64)page->index << PAGE_CACHE_SHIFT); |
| 1953 | struct inode *inode = page->mapping->host; | 1953 | struct inode *inode = page->mapping->host; |
| @@ -4069,7 +4069,7 @@ static struct inode *new_simple_dir(struct super_block *s, | |||
| 4069 | BTRFS_I(inode)->dummy_inode = 1; | 4069 | BTRFS_I(inode)->dummy_inode = 1; |
| 4070 | 4070 | ||
| 4071 | inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID; | 4071 | inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID; |
| 4072 | inode->i_op = &simple_dir_inode_operations; | 4072 | inode->i_op = &btrfs_dir_ro_inode_operations; |
| 4073 | inode->i_fop = &simple_dir_operations; | 4073 | inode->i_fop = &simple_dir_operations; |
| 4074 | inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; | 4074 | inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; |
| 4075 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 4075 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
| @@ -4140,14 +4140,18 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | |||
| 4140 | static int btrfs_dentry_delete(const struct dentry *dentry) | 4140 | static int btrfs_dentry_delete(const struct dentry *dentry) |
| 4141 | { | 4141 | { |
| 4142 | struct btrfs_root *root; | 4142 | struct btrfs_root *root; |
| 4143 | struct inode *inode = dentry->d_inode; | ||
| 4143 | 4144 | ||
| 4144 | if (!dentry->d_inode && !IS_ROOT(dentry)) | 4145 | if (!inode && !IS_ROOT(dentry)) |
| 4145 | dentry = dentry->d_parent; | 4146 | inode = dentry->d_parent->d_inode; |
| 4146 | 4147 | ||
| 4147 | if (dentry->d_inode) { | 4148 | if (inode) { |
| 4148 | root = BTRFS_I(dentry->d_inode)->root; | 4149 | root = BTRFS_I(inode)->root; |
| 4149 | if (btrfs_root_refs(&root->root_item) == 0) | 4150 | if (btrfs_root_refs(&root->root_item) == 0) |
| 4150 | return 1; | 4151 | return 1; |
| 4152 | |||
| 4153 | if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) | ||
| 4154 | return 1; | ||
| 4151 | } | 4155 | } |
| 4152 | return 0; | 4156 | return 0; |
| 4153 | } | 4157 | } |
| @@ -4188,7 +4192,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
| 4188 | struct btrfs_path *path; | 4192 | struct btrfs_path *path; |
| 4189 | struct list_head ins_list; | 4193 | struct list_head ins_list; |
| 4190 | struct list_head del_list; | 4194 | struct list_head del_list; |
| 4191 | struct qstr q; | ||
| 4192 | int ret; | 4195 | int ret; |
| 4193 | struct extent_buffer *leaf; | 4196 | struct extent_buffer *leaf; |
| 4194 | int slot; | 4197 | int slot; |
| @@ -4279,7 +4282,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
| 4279 | 4282 | ||
| 4280 | while (di_cur < di_total) { | 4283 | while (di_cur < di_total) { |
| 4281 | struct btrfs_key location; | 4284 | struct btrfs_key location; |
| 4282 | struct dentry *tmp; | ||
| 4283 | 4285 | ||
| 4284 | if (verify_dir_item(root, leaf, di)) | 4286 | if (verify_dir_item(root, leaf, di)) |
| 4285 | break; | 4287 | break; |
| @@ -4300,35 +4302,15 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
| 4300 | d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; | 4302 | d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; |
| 4301 | btrfs_dir_item_key_to_cpu(leaf, di, &location); | 4303 | btrfs_dir_item_key_to_cpu(leaf, di, &location); |
| 4302 | 4304 | ||
| 4303 | q.name = name_ptr; | 4305 | |
| 4304 | q.len = name_len; | ||
| 4305 | q.hash = full_name_hash(q.name, q.len); | ||
| 4306 | tmp = d_lookup(filp->f_dentry, &q); | ||
| 4307 | if (!tmp) { | ||
| 4308 | struct btrfs_key *newkey; | ||
| 4309 | |||
| 4310 | newkey = kzalloc(sizeof(struct btrfs_key), | ||
| 4311 | GFP_NOFS); | ||
| 4312 | if (!newkey) | ||
| 4313 | goto no_dentry; | ||
| 4314 | tmp = d_alloc(filp->f_dentry, &q); | ||
| 4315 | if (!tmp) { | ||
| 4316 | kfree(newkey); | ||
| 4317 | dput(tmp); | ||
| 4318 | goto no_dentry; | ||
| 4319 | } | ||
| 4320 | memcpy(newkey, &location, | ||
| 4321 | sizeof(struct btrfs_key)); | ||
| 4322 | tmp->d_fsdata = newkey; | ||
| 4323 | tmp->d_flags |= DCACHE_NEED_LOOKUP; | ||
| 4324 | d_rehash(tmp); | ||
| 4325 | dput(tmp); | ||
| 4326 | } else { | ||
| 4327 | dput(tmp); | ||
| 4328 | } | ||
| 4329 | no_dentry: | ||
| 4330 | /* is this a reference to our own snapshot? If so | 4306 | /* is this a reference to our own snapshot? If so |
| 4331 | * skip it | 4307 | * skip it. |
| 4308 | * | ||
| 4309 | * In contrast to old kernels, we insert the snapshot's | ||
| 4310 | * dir item and dir index after it has been created, so | ||
| 4311 | * we won't find a reference to our own snapshot. We | ||
| 4312 | * still keep the following code for backward | ||
| 4313 | * compatibility. | ||
| 4332 | */ | 4314 | */ |
| 4333 | if (location.type == BTRFS_ROOT_ITEM_KEY && | 4315 | if (location.type == BTRFS_ROOT_ITEM_KEY && |
| 4334 | location.objectid == root->root_key.objectid) { | 4316 | location.objectid == root->root_key.objectid) { |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 18cc23d164a8..14f8e1faa46e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -2262,7 +2262,10 @@ static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg) | |||
| 2262 | di_args->bytes_used = dev->bytes_used; | 2262 | di_args->bytes_used = dev->bytes_used; |
| 2263 | di_args->total_bytes = dev->total_bytes; | 2263 | di_args->total_bytes = dev->total_bytes; |
| 2264 | memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); | 2264 | memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); |
| 2265 | strncpy(di_args->path, dev->name, sizeof(di_args->path)); | 2265 | if (dev->name) |
| 2266 | strncpy(di_args->path, dev->name, sizeof(di_args->path)); | ||
| 2267 | else | ||
| 2268 | di_args->path[0] = '\0'; | ||
| 2266 | 2269 | ||
| 2267 | out: | 2270 | out: |
| 2268 | if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args))) | 2271 | if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args))) |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 4f69028a68c4..086e6bdae1c4 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
| @@ -252,7 +252,7 @@ struct btrfs_data_container { | |||
| 252 | 252 | ||
| 253 | struct btrfs_ioctl_ino_path_args { | 253 | struct btrfs_ioctl_ino_path_args { |
| 254 | __u64 inum; /* in */ | 254 | __u64 inum; /* in */ |
| 255 | __u32 size; /* in */ | 255 | __u64 size; /* in */ |
| 256 | __u64 reserved[4]; | 256 | __u64 reserved[4]; |
| 257 | /* struct btrfs_data_container *fspath; out */ | 257 | /* struct btrfs_data_container *fspath; out */ |
| 258 | __u64 fspath; /* out */ | 258 | __u64 fspath; /* out */ |
| @@ -260,7 +260,7 @@ struct btrfs_ioctl_ino_path_args { | |||
| 260 | 260 | ||
| 261 | struct btrfs_ioctl_logical_ino_args { | 261 | struct btrfs_ioctl_logical_ino_args { |
| 262 | __u64 logical; /* in */ | 262 | __u64 logical; /* in */ |
| 263 | __u32 size; /* in */ | 263 | __u64 size; /* in */ |
| 264 | __u64 reserved[4]; | 264 | __u64 reserved[4]; |
| 265 | /* struct btrfs_data_container *inodes; out */ | 265 | /* struct btrfs_data_container *inodes; out */ |
| 266 | __u64 inodes; | 266 | __u64 inodes; |
diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c index dc5d33146fdb..ac5d01085884 100644 --- a/fs/btrfs/reada.c +++ b/fs/btrfs/reada.c | |||
| @@ -250,14 +250,12 @@ static struct reada_zone *reada_find_zone(struct btrfs_fs_info *fs_info, | |||
| 250 | struct btrfs_bio *bbio) | 250 | struct btrfs_bio *bbio) |
| 251 | { | 251 | { |
| 252 | int ret; | 252 | int ret; |
| 253 | int looped = 0; | ||
| 254 | struct reada_zone *zone; | 253 | struct reada_zone *zone; |
| 255 | struct btrfs_block_group_cache *cache = NULL; | 254 | struct btrfs_block_group_cache *cache = NULL; |
| 256 | u64 start; | 255 | u64 start; |
| 257 | u64 end; | 256 | u64 end; |
| 258 | int i; | 257 | int i; |
| 259 | 258 | ||
| 260 | again: | ||
| 261 | zone = NULL; | 259 | zone = NULL; |
| 262 | spin_lock(&fs_info->reada_lock); | 260 | spin_lock(&fs_info->reada_lock); |
| 263 | ret = radix_tree_gang_lookup(&dev->reada_zones, (void **)&zone, | 261 | ret = radix_tree_gang_lookup(&dev->reada_zones, (void **)&zone, |
| @@ -274,9 +272,6 @@ again: | |||
| 274 | spin_unlock(&fs_info->reada_lock); | 272 | spin_unlock(&fs_info->reada_lock); |
| 275 | } | 273 | } |
| 276 | 274 | ||
| 277 | if (looped) | ||
| 278 | return NULL; | ||
| 279 | |||
| 280 | cache = btrfs_lookup_block_group(fs_info, logical); | 275 | cache = btrfs_lookup_block_group(fs_info, logical); |
| 281 | if (!cache) | 276 | if (!cache) |
| 282 | return NULL; | 277 | return NULL; |
| @@ -307,13 +302,15 @@ again: | |||
| 307 | ret = radix_tree_insert(&dev->reada_zones, | 302 | ret = radix_tree_insert(&dev->reada_zones, |
| 308 | (unsigned long)(zone->end >> PAGE_CACHE_SHIFT), | 303 | (unsigned long)(zone->end >> PAGE_CACHE_SHIFT), |
| 309 | zone); | 304 | zone); |
| 310 | spin_unlock(&fs_info->reada_lock); | ||
| 311 | 305 | ||
| 312 | if (ret) { | 306 | if (ret == -EEXIST) { |
| 313 | kfree(zone); | 307 | kfree(zone); |
| 314 | looped = 1; | 308 | ret = radix_tree_gang_lookup(&dev->reada_zones, (void **)&zone, |
| 315 | goto again; | 309 | logical >> PAGE_CACHE_SHIFT, 1); |
| 310 | if (ret == 1) | ||
| 311 | kref_get(&zone->refcnt); | ||
| 316 | } | 312 | } |
| 313 | spin_unlock(&fs_info->reada_lock); | ||
| 317 | 314 | ||
| 318 | return zone; | 315 | return zone; |
| 319 | } | 316 | } |
| @@ -323,26 +320,26 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root, | |||
| 323 | struct btrfs_key *top, int level) | 320 | struct btrfs_key *top, int level) |
| 324 | { | 321 | { |
| 325 | int ret; | 322 | int ret; |
| 326 | int looped = 0; | ||
| 327 | struct reada_extent *re = NULL; | 323 | struct reada_extent *re = NULL; |
| 324 | struct reada_extent *re_exist = NULL; | ||
| 328 | struct btrfs_fs_info *fs_info = root->fs_info; | 325 | struct btrfs_fs_info *fs_info = root->fs_info; |
| 329 | struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; | 326 | struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; |
| 330 | struct btrfs_bio *bbio = NULL; | 327 | struct btrfs_bio *bbio = NULL; |
| 331 | struct btrfs_device *dev; | 328 | struct btrfs_device *dev; |
| 329 | struct btrfs_device *prev_dev; | ||
| 332 | u32 blocksize; | 330 | u32 blocksize; |
| 333 | u64 length; | 331 | u64 length; |
| 334 | int nzones = 0; | 332 | int nzones = 0; |
| 335 | int i; | 333 | int i; |
| 336 | unsigned long index = logical >> PAGE_CACHE_SHIFT; | 334 | unsigned long index = logical >> PAGE_CACHE_SHIFT; |
| 337 | 335 | ||
| 338 | again: | ||
| 339 | spin_lock(&fs_info->reada_lock); | 336 | spin_lock(&fs_info->reada_lock); |
| 340 | re = radix_tree_lookup(&fs_info->reada_tree, index); | 337 | re = radix_tree_lookup(&fs_info->reada_tree, index); |
| 341 | if (re) | 338 | if (re) |
| 342 | kref_get(&re->refcnt); | 339 | kref_get(&re->refcnt); |
| 343 | spin_unlock(&fs_info->reada_lock); | 340 | spin_unlock(&fs_info->reada_lock); |
| 344 | 341 | ||
| 345 | if (re || looped) | 342 | if (re) |
| 346 | return re; | 343 | return re; |
| 347 | 344 | ||
| 348 | re = kzalloc(sizeof(*re), GFP_NOFS); | 345 | re = kzalloc(sizeof(*re), GFP_NOFS); |
| @@ -398,16 +395,31 @@ again: | |||
| 398 | /* insert extent in reada_tree + all per-device trees, all or nothing */ | 395 | /* insert extent in reada_tree + all per-device trees, all or nothing */ |
| 399 | spin_lock(&fs_info->reada_lock); | 396 | spin_lock(&fs_info->reada_lock); |
| 400 | ret = radix_tree_insert(&fs_info->reada_tree, index, re); | 397 | ret = radix_tree_insert(&fs_info->reada_tree, index, re); |
| 398 | if (ret == -EEXIST) { | ||
| 399 | re_exist = radix_tree_lookup(&fs_info->reada_tree, index); | ||
| 400 | BUG_ON(!re_exist); | ||
| 401 | kref_get(&re_exist->refcnt); | ||
| 402 | spin_unlock(&fs_info->reada_lock); | ||
| 403 | goto error; | ||
| 404 | } | ||
| 401 | if (ret) { | 405 | if (ret) { |
| 402 | spin_unlock(&fs_info->reada_lock); | 406 | spin_unlock(&fs_info->reada_lock); |
| 403 | if (ret != -ENOMEM) { | ||
| 404 | /* someone inserted the extent in the meantime */ | ||
| 405 | looped = 1; | ||
| 406 | } | ||
| 407 | goto error; | 407 | goto error; |
| 408 | } | 408 | } |
| 409 | prev_dev = NULL; | ||
| 409 | for (i = 0; i < nzones; ++i) { | 410 | for (i = 0; i < nzones; ++i) { |
| 410 | dev = bbio->stripes[i].dev; | 411 | dev = bbio->stripes[i].dev; |
| 412 | if (dev == prev_dev) { | ||
| 413 | /* | ||
| 414 | * in case of DUP, just add the first zone. As both | ||
| 415 | * are on the same device, there's nothing to gain | ||
| 416 | * from adding both. | ||
| 417 | * Also, it wouldn't work, as the tree is per device | ||
| 418 | * and adding would fail with EEXIST | ||
| 419 | */ | ||
| 420 | continue; | ||
| 421 | } | ||
| 422 | prev_dev = dev; | ||
| 411 | ret = radix_tree_insert(&dev->reada_extents, index, re); | 423 | ret = radix_tree_insert(&dev->reada_extents, index, re); |
| 412 | if (ret) { | 424 | if (ret) { |
| 413 | while (--i >= 0) { | 425 | while (--i >= 0) { |
| @@ -450,9 +462,7 @@ error: | |||
| 450 | } | 462 | } |
| 451 | kfree(bbio); | 463 | kfree(bbio); |
| 452 | kfree(re); | 464 | kfree(re); |
| 453 | if (looped) | 465 | return re_exist; |
| 454 | goto again; | ||
| 455 | return NULL; | ||
| 456 | } | 466 | } |
| 457 | 467 | ||
| 458 | static void reada_kref_dummy(struct kref *kr) | 468 | static void reada_kref_dummy(struct kref *kr) |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 017281dbb2a7..646ee21bb035 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
| @@ -1279,7 +1279,9 @@ static int __update_reloc_root(struct btrfs_root *root, int del) | |||
| 1279 | if (rb_node) | 1279 | if (rb_node) |
| 1280 | backref_tree_panic(rb_node, -EEXIST, node->bytenr); | 1280 | backref_tree_panic(rb_node, -EEXIST, node->bytenr); |
| 1281 | } else { | 1281 | } else { |
| 1282 | spin_lock(&root->fs_info->trans_lock); | ||
| 1282 | list_del_init(&root->root_list); | 1283 | list_del_init(&root->root_list); |
| 1284 | spin_unlock(&root->fs_info->trans_lock); | ||
| 1283 | kfree(node); | 1285 | kfree(node); |
| 1284 | } | 1286 | } |
| 1285 | return 0; | 1287 | return 0; |
| @@ -3811,7 +3813,7 @@ restart: | |||
| 3811 | 3813 | ||
| 3812 | ret = btrfs_block_rsv_check(rc->extent_root, rc->block_rsv, 5); | 3814 | ret = btrfs_block_rsv_check(rc->extent_root, rc->block_rsv, 5); |
| 3813 | if (ret < 0) { | 3815 | if (ret < 0) { |
| 3814 | if (ret != -EAGAIN) { | 3816 | if (ret != -ENOSPC) { |
| 3815 | err = ret; | 3817 | err = ret; |
| 3816 | WARN_ON(1); | 3818 | WARN_ON(1); |
| 3817 | break; | 3819 | break; |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index bc015f77f3ea..2f3d6f917fb3 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
| @@ -998,6 +998,7 @@ static int scrub_setup_recheck_block(struct scrub_dev *sdev, | |||
| 998 | page = sblock->pagev + page_index; | 998 | page = sblock->pagev + page_index; |
| 999 | page->logical = logical; | 999 | page->logical = logical; |
| 1000 | page->physical = bbio->stripes[mirror_index].physical; | 1000 | page->physical = bbio->stripes[mirror_index].physical; |
| 1001 | /* for missing devices, bdev is NULL */ | ||
| 1001 | page->bdev = bbio->stripes[mirror_index].dev->bdev; | 1002 | page->bdev = bbio->stripes[mirror_index].dev->bdev; |
| 1002 | page->mirror_num = mirror_index + 1; | 1003 | page->mirror_num = mirror_index + 1; |
| 1003 | page->page = alloc_page(GFP_NOFS); | 1004 | page->page = alloc_page(GFP_NOFS); |
| @@ -1042,6 +1043,12 @@ static int scrub_recheck_block(struct btrfs_fs_info *fs_info, | |||
| 1042 | struct scrub_page *page = sblock->pagev + page_num; | 1043 | struct scrub_page *page = sblock->pagev + page_num; |
| 1043 | DECLARE_COMPLETION_ONSTACK(complete); | 1044 | DECLARE_COMPLETION_ONSTACK(complete); |
| 1044 | 1045 | ||
| 1046 | if (page->bdev == NULL) { | ||
| 1047 | page->io_error = 1; | ||
| 1048 | sblock->no_io_error_seen = 0; | ||
| 1049 | continue; | ||
| 1050 | } | ||
| 1051 | |||
| 1045 | BUG_ON(!page->page); | 1052 | BUG_ON(!page->page); |
| 1046 | bio = bio_alloc(GFP_NOFS, 1); | 1053 | bio = bio_alloc(GFP_NOFS, 1); |
| 1047 | if (!bio) | 1054 | if (!bio) |
| @@ -1257,12 +1264,6 @@ static int scrub_checksum_data(struct scrub_block *sblock) | |||
| 1257 | if (memcmp(csum, on_disk_csum, sdev->csum_size)) | 1264 | if (memcmp(csum, on_disk_csum, sdev->csum_size)) |
| 1258 | fail = 1; | 1265 | fail = 1; |
| 1259 | 1266 | ||
| 1260 | if (fail) { | ||
| 1261 | spin_lock(&sdev->stat_lock); | ||
| 1262 | ++sdev->stat.csum_errors; | ||
| 1263 | spin_unlock(&sdev->stat_lock); | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | return fail; | 1267 | return fail; |
| 1267 | } | 1268 | } |
| 1268 | 1269 | ||
| @@ -1335,15 +1336,6 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
| 1335 | if (memcmp(calculated_csum, on_disk_csum, sdev->csum_size)) | 1336 | if (memcmp(calculated_csum, on_disk_csum, sdev->csum_size)) |
| 1336 | ++crc_fail; | 1337 | ++crc_fail; |
| 1337 | 1338 | ||
| 1338 | if (crc_fail || fail) { | ||
| 1339 | spin_lock(&sdev->stat_lock); | ||
| 1340 | if (crc_fail) | ||
| 1341 | ++sdev->stat.csum_errors; | ||
| 1342 | if (fail) | ||
| 1343 | ++sdev->stat.verify_errors; | ||
| 1344 | spin_unlock(&sdev->stat_lock); | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | return fail || crc_fail; | 1339 | return fail || crc_fail; |
| 1348 | } | 1340 | } |
| 1349 | 1341 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8d5d380f7bdb..c5f8fca4195f 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -815,7 +815,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait) | |||
| 815 | return 0; | 815 | return 0; |
| 816 | } | 816 | } |
| 817 | 817 | ||
| 818 | btrfs_start_delalloc_inodes(root, 0); | ||
| 819 | btrfs_wait_ordered_extents(root, 0, 0); | 818 | btrfs_wait_ordered_extents(root, 0, 0); |
| 820 | 819 | ||
| 821 | trans = btrfs_start_transaction(root, 0); | 820 | trans = btrfs_start_transaction(root, 0); |
| @@ -1148,13 +1147,15 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
| 1148 | if (ret) | 1147 | if (ret) |
| 1149 | goto restore; | 1148 | goto restore; |
| 1150 | } else { | 1149 | } else { |
| 1151 | if (fs_info->fs_devices->rw_devices == 0) | 1150 | if (fs_info->fs_devices->rw_devices == 0) { |
| 1152 | ret = -EACCES; | 1151 | ret = -EACCES; |
| 1153 | goto restore; | 1152 | goto restore; |
| 1153 | } | ||
| 1154 | 1154 | ||
| 1155 | if (btrfs_super_log_root(fs_info->super_copy) != 0) | 1155 | if (btrfs_super_log_root(fs_info->super_copy) != 0) { |
| 1156 | ret = -EINVAL; | 1156 | ret = -EINVAL; |
| 1157 | goto restore; | 1157 | goto restore; |
| 1158 | } | ||
| 1158 | 1159 | ||
| 1159 | ret = btrfs_cleanup_fs_roots(fs_info); | 1160 | ret = btrfs_cleanup_fs_roots(fs_info); |
| 1160 | if (ret) | 1161 | if (ret) |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 11b77a59db62..36422254ef67 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -73,8 +73,10 @@ loop: | |||
| 73 | 73 | ||
| 74 | cur_trans = root->fs_info->running_transaction; | 74 | cur_trans = root->fs_info->running_transaction; |
| 75 | if (cur_trans) { | 75 | if (cur_trans) { |
| 76 | if (cur_trans->aborted) | 76 | if (cur_trans->aborted) { |
| 77 | spin_unlock(&root->fs_info->trans_lock); | ||
| 77 | return cur_trans->aborted; | 78 | return cur_trans->aborted; |
| 79 | } | ||
| 78 | atomic_inc(&cur_trans->use_count); | 80 | atomic_inc(&cur_trans->use_count); |
| 79 | atomic_inc(&cur_trans->num_writers); | 81 | atomic_inc(&cur_trans->num_writers); |
| 80 | cur_trans->num_joined++; | 82 | cur_trans->num_joined++; |
| @@ -1400,6 +1402,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1400 | ret = commit_fs_roots(trans, root); | 1402 | ret = commit_fs_roots(trans, root); |
| 1401 | if (ret) { | 1403 | if (ret) { |
| 1402 | mutex_unlock(&root->fs_info->tree_log_mutex); | 1404 | mutex_unlock(&root->fs_info->tree_log_mutex); |
| 1405 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
| 1403 | goto cleanup_transaction; | 1406 | goto cleanup_transaction; |
| 1404 | } | 1407 | } |
| 1405 | 1408 | ||
| @@ -1411,6 +1414,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1411 | ret = commit_cowonly_roots(trans, root); | 1414 | ret = commit_cowonly_roots(trans, root); |
| 1412 | if (ret) { | 1415 | if (ret) { |
| 1413 | mutex_unlock(&root->fs_info->tree_log_mutex); | 1416 | mutex_unlock(&root->fs_info->tree_log_mutex); |
| 1417 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
| 1414 | goto cleanup_transaction; | 1418 | goto cleanup_transaction; |
| 1415 | } | 1419 | } |
| 1416 | 1420 | ||
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index d017283ae6f5..eb1ae908582c 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -279,7 +279,7 @@ static int process_one_buffer(struct btrfs_root *log, | |||
| 279 | log->fs_info->extent_root, | 279 | log->fs_info->extent_root, |
| 280 | eb->start, eb->len); | 280 | eb->start, eb->len); |
| 281 | 281 | ||
| 282 | if (btrfs_buffer_uptodate(eb, gen)) { | 282 | if (btrfs_buffer_uptodate(eb, gen, 0)) { |
| 283 | if (wc->write) | 283 | if (wc->write) |
| 284 | btrfs_write_tree_block(eb); | 284 | btrfs_write_tree_block(eb); |
| 285 | if (wc->wait) | 285 | if (wc->wait) |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 759d02486d7c..1411b99555a4 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -3324,12 +3324,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
| 3324 | stripe_size = devices_info[ndevs-1].max_avail; | 3324 | stripe_size = devices_info[ndevs-1].max_avail; |
| 3325 | num_stripes = ndevs * dev_stripes; | 3325 | num_stripes = ndevs * dev_stripes; |
| 3326 | 3326 | ||
| 3327 | if (stripe_size * num_stripes > max_chunk_size * ncopies) { | 3327 | if (stripe_size * ndevs > max_chunk_size * ncopies) { |
| 3328 | stripe_size = max_chunk_size * ncopies; | 3328 | stripe_size = max_chunk_size * ncopies; |
| 3329 | do_div(stripe_size, num_stripes); | 3329 | do_div(stripe_size, ndevs); |
| 3330 | } | 3330 | } |
| 3331 | 3331 | ||
| 3332 | do_div(stripe_size, dev_stripes); | 3332 | do_div(stripe_size, dev_stripes); |
| 3333 | |||
| 3334 | /* align to BTRFS_STRIPE_LEN */ | ||
| 3333 | do_div(stripe_size, BTRFS_STRIPE_LEN); | 3335 | do_div(stripe_size, BTRFS_STRIPE_LEN); |
| 3334 | stripe_size *= BTRFS_STRIPE_LEN; | 3336 | stripe_size *= BTRFS_STRIPE_LEN; |
| 3335 | 3337 | ||
| @@ -3805,10 +3807,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
| 3805 | else if (mirror_num) | 3807 | else if (mirror_num) |
| 3806 | stripe_index += mirror_num - 1; | 3808 | stripe_index += mirror_num - 1; |
| 3807 | else { | 3809 | else { |
| 3810 | int old_stripe_index = stripe_index; | ||
| 3808 | stripe_index = find_live_mirror(map, stripe_index, | 3811 | stripe_index = find_live_mirror(map, stripe_index, |
| 3809 | map->sub_stripes, stripe_index + | 3812 | map->sub_stripes, stripe_index + |
| 3810 | current->pid % map->sub_stripes); | 3813 | current->pid % map->sub_stripes); |
| 3811 | mirror_num = stripe_index + 1; | 3814 | mirror_num = stripe_index - old_stripe_index + 1; |
| 3812 | } | 3815 | } |
| 3813 | } else { | 3816 | } else { |
| 3814 | /* | 3817 | /* |
| @@ -4350,8 +4353,10 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid) | |||
| 4350 | 4353 | ||
| 4351 | ret = __btrfs_open_devices(fs_devices, FMODE_READ, | 4354 | ret = __btrfs_open_devices(fs_devices, FMODE_READ, |
| 4352 | root->fs_info->bdev_holder); | 4355 | root->fs_info->bdev_holder); |
| 4353 | if (ret) | 4356 | if (ret) { |
| 4357 | free_fs_devices(fs_devices); | ||
| 4354 | goto out; | 4358 | goto out; |
| 4359 | } | ||
| 4355 | 4360 | ||
| 4356 | if (!fs_devices->seeding) { | 4361 | if (!fs_devices->seeding) { |
| 4357 | __btrfs_close_devices(fs_devices); | 4362 | __btrfs_close_devices(fs_devices); |
diff --git a/fs/buffer.c b/fs/buffer.c index 36d66653b931..351e18ea2e53 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -985,7 +985,6 @@ grow_dev_page(struct block_device *bdev, sector_t block, | |||
| 985 | return page; | 985 | return page; |
| 986 | 986 | ||
| 987 | failed: | 987 | failed: |
| 988 | BUG(); | ||
| 989 | unlock_page(page); | 988 | unlock_page(page); |
| 990 | page_cache_release(page); | 989 | page_cache_release(page); |
| 991 | return NULL; | 990 | return NULL; |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index d34212822444..ca6a3796a33b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -370,13 +370,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
| 370 | (int)(srcaddr->sa_family)); | 370 | (int)(srcaddr->sa_family)); |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); | 373 | seq_printf(s, ",uid=%u", cifs_sb->mnt_uid); |
| 374 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | 374 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
| 375 | seq_printf(s, ",forceuid"); | 375 | seq_printf(s, ",forceuid"); |
| 376 | else | 376 | else |
| 377 | seq_printf(s, ",noforceuid"); | 377 | seq_printf(s, ",noforceuid"); |
| 378 | 378 | ||
| 379 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); | 379 | seq_printf(s, ",gid=%u", cifs_sb->mnt_gid); |
| 380 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | 380 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) |
| 381 | seq_printf(s, ",forcegid"); | 381 | seq_printf(s, ",forcegid"); |
| 382 | else | 382 | else |
| @@ -434,11 +434,15 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
| 434 | seq_printf(s, ",noperm"); | 434 | seq_printf(s, ",noperm"); |
| 435 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) | 435 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) |
| 436 | seq_printf(s, ",strictcache"); | 436 | seq_printf(s, ",strictcache"); |
| 437 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) | ||
| 438 | seq_printf(s, ",backupuid=%u", cifs_sb->mnt_backupuid); | ||
| 439 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) | ||
| 440 | seq_printf(s, ",backupgid=%u", cifs_sb->mnt_backupgid); | ||
| 437 | 441 | ||
| 438 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); | 442 | seq_printf(s, ",rsize=%u", cifs_sb->rsize); |
| 439 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); | 443 | seq_printf(s, ",wsize=%u", cifs_sb->wsize); |
| 440 | /* convert actimeo and display it in seconds */ | 444 | /* convert actimeo and display it in seconds */ |
| 441 | seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); | 445 | seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); |
| 442 | 446 | ||
| 443 | return 0; | 447 | return 0; |
| 444 | } | 448 | } |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index d1389bb33ceb..65365358c976 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -125,5 +125,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
| 125 | extern const struct export_operations cifs_export_ops; | 125 | extern const struct export_operations cifs_export_ops; |
| 126 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ | 126 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ |
| 127 | 127 | ||
| 128 | #define CIFS_VERSION "1.77" | 128 | #define CIFS_VERSION "1.78" |
| 129 | #endif /* _CIFSFS_H */ | 129 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index f52c5ab78f9d..da2f5446fa7a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -4844,8 +4844,12 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | |||
| 4844 | max_len = data_end - temp; | 4844 | max_len = data_end - temp; |
| 4845 | node->node_name = cifs_strndup_from_utf16(temp, max_len, | 4845 | node->node_name = cifs_strndup_from_utf16(temp, max_len, |
| 4846 | is_unicode, nls_codepage); | 4846 | is_unicode, nls_codepage); |
| 4847 | if (!node->node_name) | 4847 | if (!node->node_name) { |
| 4848 | rc = -ENOMEM; | 4848 | rc = -ENOMEM; |
| 4849 | goto parse_DFS_referrals_exit; | ||
| 4850 | } | ||
| 4851 | |||
| 4852 | ref++; | ||
| 4849 | } | 4853 | } |
| 4850 | 4854 | ||
| 4851 | parse_DFS_referrals_exit: | 4855 | parse_DFS_referrals_exit: |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f31dc9ac37b7..5dcc55197fb3 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -215,6 +215,8 @@ static const match_table_t cifs_mount_option_tokens = { | |||
| 215 | 215 | ||
| 216 | { Opt_ignore, "cred" }, | 216 | { Opt_ignore, "cred" }, |
| 217 | { Opt_ignore, "credentials" }, | 217 | { Opt_ignore, "credentials" }, |
| 218 | { Opt_ignore, "cred=%s" }, | ||
| 219 | { Opt_ignore, "credentials=%s" }, | ||
| 218 | { Opt_ignore, "guest" }, | 220 | { Opt_ignore, "guest" }, |
| 219 | { Opt_ignore, "rw" }, | 221 | { Opt_ignore, "rw" }, |
| 220 | { Opt_ignore, "ro" }, | 222 | { Opt_ignore, "ro" }, |
| @@ -2183,6 +2185,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
| 2183 | tcp_ses->session_estab = false; | 2185 | tcp_ses->session_estab = false; |
| 2184 | tcp_ses->sequence_number = 0; | 2186 | tcp_ses->sequence_number = 0; |
| 2185 | tcp_ses->lstrp = jiffies; | 2187 | tcp_ses->lstrp = jiffies; |
| 2188 | spin_lock_init(&tcp_ses->req_lock); | ||
| 2186 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); | 2189 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); |
| 2187 | INIT_LIST_HEAD(&tcp_ses->smb_ses_list); | 2190 | INIT_LIST_HEAD(&tcp_ses->smb_ses_list); |
| 2188 | INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); | 2191 | INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); |
| @@ -3228,10 +3231,6 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
| 3228 | 3231 | ||
| 3229 | cifs_sb->mnt_uid = pvolume_info->linux_uid; | 3232 | cifs_sb->mnt_uid = pvolume_info->linux_uid; |
| 3230 | cifs_sb->mnt_gid = pvolume_info->linux_gid; | 3233 | cifs_sb->mnt_gid = pvolume_info->linux_gid; |
| 3231 | if (pvolume_info->backupuid_specified) | ||
| 3232 | cifs_sb->mnt_backupuid = pvolume_info->backupuid; | ||
| 3233 | if (pvolume_info->backupgid_specified) | ||
| 3234 | cifs_sb->mnt_backupgid = pvolume_info->backupgid; | ||
| 3235 | cifs_sb->mnt_file_mode = pvolume_info->file_mode; | 3234 | cifs_sb->mnt_file_mode = pvolume_info->file_mode; |
| 3236 | cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; | 3235 | cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; |
| 3237 | cFYI(1, "file mode: 0x%hx dir mode: 0x%hx", | 3236 | cFYI(1, "file mode: 0x%hx dir mode: 0x%hx", |
| @@ -3262,10 +3261,14 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
| 3262 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD; | 3261 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD; |
| 3263 | if (pvolume_info->cifs_acl) | 3262 | if (pvolume_info->cifs_acl) |
| 3264 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; | 3263 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; |
| 3265 | if (pvolume_info->backupuid_specified) | 3264 | if (pvolume_info->backupuid_specified) { |
| 3266 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID; | 3265 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID; |
| 3267 | if (pvolume_info->backupgid_specified) | 3266 | cifs_sb->mnt_backupuid = pvolume_info->backupuid; |
| 3267 | } | ||
| 3268 | if (pvolume_info->backupgid_specified) { | ||
| 3268 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID; | 3269 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID; |
| 3270 | cifs_sb->mnt_backupgid = pvolume_info->backupgid; | ||
| 3271 | } | ||
| 3269 | if (pvolume_info->override_uid) | 3272 | if (pvolume_info->override_uid) |
| 3270 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; | 3273 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; |
| 3271 | if (pvolume_info->override_gid) | 3274 | if (pvolume_info->override_gid) |
| @@ -3614,22 +3617,6 @@ cifs_get_volume_info(char *mount_data, const char *devname) | |||
| 3614 | return volume_info; | 3617 | return volume_info; |
| 3615 | } | 3618 | } |
| 3616 | 3619 | ||
| 3617 | /* make sure ra_pages is a multiple of rsize */ | ||
| 3618 | static inline unsigned int | ||
| 3619 | cifs_ra_pages(struct cifs_sb_info *cifs_sb) | ||
| 3620 | { | ||
| 3621 | unsigned int reads; | ||
| 3622 | unsigned int rsize_pages = cifs_sb->rsize / PAGE_CACHE_SIZE; | ||
| 3623 | |||
| 3624 | if (rsize_pages >= default_backing_dev_info.ra_pages) | ||
| 3625 | return default_backing_dev_info.ra_pages; | ||
| 3626 | else if (rsize_pages == 0) | ||
| 3627 | return rsize_pages; | ||
| 3628 | |||
| 3629 | reads = default_backing_dev_info.ra_pages / rsize_pages; | ||
| 3630 | return reads * rsize_pages; | ||
| 3631 | } | ||
| 3632 | |||
| 3633 | int | 3620 | int |
| 3634 | cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) | 3621 | cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) |
| 3635 | { | 3622 | { |
| @@ -3717,7 +3704,7 @@ try_mount_again: | |||
| 3717 | cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info); | 3704 | cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info); |
| 3718 | 3705 | ||
| 3719 | /* tune readahead according to rsize */ | 3706 | /* tune readahead according to rsize */ |
| 3720 | cifs_sb->bdi.ra_pages = cifs_ra_pages(cifs_sb); | 3707 | cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE; |
| 3721 | 3708 | ||
| 3722 | remote_path_check: | 3709 | remote_path_check: |
| 3723 | #ifdef CONFIG_CIFS_DFS_UPCALL | 3710 | #ifdef CONFIG_CIFS_DFS_UPCALL |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index d172c8ed9017..ec4e9a2a12f8 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -668,12 +668,19 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
| 668 | return 0; | 668 | return 0; |
| 669 | else { | 669 | else { |
| 670 | /* | 670 | /* |
| 671 | * Forcibly invalidate automounting directory inodes | 671 | * If the inode wasn't known to be a dfs entry when |
| 672 | * (remote DFS directories) so to have them | 672 | * the dentry was instantiated, such as when created |
| 673 | * instantiated again for automount | 673 | * via ->readdir(), it needs to be set now since the |
| 674 | * attributes will have been updated by | ||
| 675 | * cifs_revalidate_dentry(). | ||
| 674 | */ | 676 | */ |
| 675 | if (IS_AUTOMOUNT(direntry->d_inode)) | 677 | if (IS_AUTOMOUNT(direntry->d_inode) && |
| 676 | return 0; | 678 | !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) { |
| 679 | spin_lock(&direntry->d_lock); | ||
| 680 | direntry->d_flags |= DCACHE_NEED_AUTOMOUNT; | ||
| 681 | spin_unlock(&direntry->d_lock); | ||
| 682 | } | ||
| 683 | |||
| 677 | return 1; | 684 | return 1; |
| 678 | } | 685 | } |
| 679 | } | 686 | } |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index fae765dac934..81725e9286e9 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -2178,7 +2178,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
| 2178 | unsigned long nr_pages, i; | 2178 | unsigned long nr_pages, i; |
| 2179 | size_t copied, len, cur_len; | 2179 | size_t copied, len, cur_len; |
| 2180 | ssize_t total_written = 0; | 2180 | ssize_t total_written = 0; |
| 2181 | loff_t offset = *poffset; | 2181 | loff_t offset; |
| 2182 | struct iov_iter it; | 2182 | struct iov_iter it; |
| 2183 | struct cifsFileInfo *open_file; | 2183 | struct cifsFileInfo *open_file; |
| 2184 | struct cifs_tcon *tcon; | 2184 | struct cifs_tcon *tcon; |
| @@ -2200,6 +2200,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
| 2200 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 2200 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| 2201 | open_file = file->private_data; | 2201 | open_file = file->private_data; |
| 2202 | tcon = tlink_tcon(open_file->tlink); | 2202 | tcon = tlink_tcon(open_file->tlink); |
| 2203 | offset = *poffset; | ||
| 2203 | 2204 | ||
| 2204 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 2205 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
| 2205 | pid = open_file->pid; | 2206 | pid = open_file->pid; |
diff --git a/fs/dcache.c b/fs/dcache.c index b60ddc41d783..b80531c91779 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -141,18 +141,29 @@ int proc_nr_dentry(ctl_table *table, int write, void __user *buffer, | |||
| 141 | * Compare 2 name strings, return 0 if they match, otherwise non-zero. | 141 | * Compare 2 name strings, return 0 if they match, otherwise non-zero. |
| 142 | * The strings are both count bytes long, and count is non-zero. | 142 | * The strings are both count bytes long, and count is non-zero. |
| 143 | */ | 143 | */ |
| 144 | #ifdef CONFIG_DCACHE_WORD_ACCESS | ||
| 145 | |||
| 146 | #include <asm/word-at-a-time.h> | ||
| 147 | /* | ||
| 148 | * NOTE! 'cs' and 'scount' come from a dentry, so it has a | ||
| 149 | * aligned allocation for this particular component. We don't | ||
| 150 | * strictly need the load_unaligned_zeropad() safety, but it | ||
| 151 | * doesn't hurt either. | ||
| 152 | * | ||
| 153 | * In contrast, 'ct' and 'tcount' can be from a pathname, and do | ||
| 154 | * need the careful unaligned handling. | ||
| 155 | */ | ||
| 144 | static inline int dentry_cmp(const unsigned char *cs, size_t scount, | 156 | static inline int dentry_cmp(const unsigned char *cs, size_t scount, |
| 145 | const unsigned char *ct, size_t tcount) | 157 | const unsigned char *ct, size_t tcount) |
| 146 | { | 158 | { |
| 147 | #ifdef CONFIG_DCACHE_WORD_ACCESS | ||
| 148 | unsigned long a,b,mask; | 159 | unsigned long a,b,mask; |
| 149 | 160 | ||
| 150 | if (unlikely(scount != tcount)) | 161 | if (unlikely(scount != tcount)) |
| 151 | return 1; | 162 | return 1; |
| 152 | 163 | ||
| 153 | for (;;) { | 164 | for (;;) { |
| 154 | a = *(unsigned long *)cs; | 165 | a = load_unaligned_zeropad(cs); |
| 155 | b = *(unsigned long *)ct; | 166 | b = load_unaligned_zeropad(ct); |
| 156 | if (tcount < sizeof(unsigned long)) | 167 | if (tcount < sizeof(unsigned long)) |
| 157 | break; | 168 | break; |
| 158 | if (unlikely(a != b)) | 169 | if (unlikely(a != b)) |
| @@ -165,7 +176,13 @@ static inline int dentry_cmp(const unsigned char *cs, size_t scount, | |||
| 165 | } | 176 | } |
| 166 | mask = ~(~0ul << tcount*8); | 177 | mask = ~(~0ul << tcount*8); |
| 167 | return unlikely(!!((a ^ b) & mask)); | 178 | return unlikely(!!((a ^ b) & mask)); |
| 179 | } | ||
| 180 | |||
| 168 | #else | 181 | #else |
| 182 | |||
| 183 | static inline int dentry_cmp(const unsigned char *cs, size_t scount, | ||
| 184 | const unsigned char *ct, size_t tcount) | ||
| 185 | { | ||
| 169 | if (scount != tcount) | 186 | if (scount != tcount) |
| 170 | return 1; | 187 | return 1; |
| 171 | 188 | ||
| @@ -177,9 +194,10 @@ static inline int dentry_cmp(const unsigned char *cs, size_t scount, | |||
| 177 | tcount--; | 194 | tcount--; |
| 178 | } while (tcount); | 195 | } while (tcount); |
| 179 | return 0; | 196 | return 0; |
| 180 | #endif | ||
| 181 | } | 197 | } |
| 182 | 198 | ||
| 199 | #endif | ||
| 200 | |||
| 183 | static void __d_free(struct rcu_head *head) | 201 | static void __d_free(struct rcu_head *head) |
| 184 | { | 202 | { |
| 185 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); | 203 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); |
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index fa5c07d51dcc..4c58d4a3adc4 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
| @@ -1737,6 +1737,18 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now) | |||
| 1737 | return 1; | 1737 | return 1; |
| 1738 | 1738 | ||
| 1739 | /* | 1739 | /* |
| 1740 | * Even if the convert is compat with all granted locks, | ||
| 1741 | * QUECVT forces it behind other locks on the convert queue. | ||
| 1742 | */ | ||
| 1743 | |||
| 1744 | if (now && conv && (lkb->lkb_exflags & DLM_LKF_QUECVT)) { | ||
| 1745 | if (list_empty(&r->res_convertqueue)) | ||
| 1746 | return 1; | ||
| 1747 | else | ||
| 1748 | goto out; | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | /* | ||
| 1740 | * The NOORDER flag is set to avoid the standard vms rules on grant | 1752 | * The NOORDER flag is set to avoid the standard vms rules on grant |
| 1741 | * order. | 1753 | * order. |
| 1742 | */ | 1754 | */ |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 739b0985b398..c0b3c70ee87a 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
| @@ -1663,8 +1663,10 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, | |||
| 1663 | if (op == EPOLL_CTL_ADD) { | 1663 | if (op == EPOLL_CTL_ADD) { |
| 1664 | if (is_file_epoll(tfile)) { | 1664 | if (is_file_epoll(tfile)) { |
| 1665 | error = -ELOOP; | 1665 | error = -ELOOP; |
| 1666 | if (ep_loop_check(ep, tfile) != 0) | 1666 | if (ep_loop_check(ep, tfile) != 0) { |
| 1667 | clear_tfile_check_list(); | ||
| 1667 | goto error_tgt_fput; | 1668 | goto error_tgt_fput; |
| 1669 | } | ||
| 1668 | } else | 1670 | } else |
| 1669 | list_add(&tfile->f_tfile_llink, &tfile_check_list); | 1671 | list_add(&tfile->f_tfile_llink, &tfile_check_list); |
| 1670 | } | 1672 | } |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 6da193564e43..e1fb1d5de58e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -1597,7 +1597,9 @@ static int parse_options(char *options, struct super_block *sb, | |||
| 1597 | unsigned int *journal_ioprio, | 1597 | unsigned int *journal_ioprio, |
| 1598 | int is_remount) | 1598 | int is_remount) |
| 1599 | { | 1599 | { |
| 1600 | #ifdef CONFIG_QUOTA | ||
| 1600 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 1601 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 1602 | #endif | ||
| 1601 | char *p; | 1603 | char *p; |
| 1602 | substring_t args[MAX_OPT_ARGS]; | 1604 | substring_t args[MAX_OPT_ARGS]; |
| 1603 | int token; | 1605 | int token; |
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index f8411bd1b805..5f5e70e047dc 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c | |||
| @@ -200,10 +200,11 @@ static int make_mode(const unsigned int lmstate) | |||
| 200 | return -1; | 200 | return -1; |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | static u32 make_flags(const u32 lkid, const unsigned int gfs_flags, | 203 | static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags, |
| 204 | const int req) | 204 | const int req) |
| 205 | { | 205 | { |
| 206 | u32 lkf = DLM_LKF_VALBLK; | 206 | u32 lkf = DLM_LKF_VALBLK; |
| 207 | u32 lkid = gl->gl_lksb.sb_lkid; | ||
| 207 | 208 | ||
| 208 | if (gfs_flags & LM_FLAG_TRY) | 209 | if (gfs_flags & LM_FLAG_TRY) |
| 209 | lkf |= DLM_LKF_NOQUEUE; | 210 | lkf |= DLM_LKF_NOQUEUE; |
| @@ -227,8 +228,11 @@ static u32 make_flags(const u32 lkid, const unsigned int gfs_flags, | |||
| 227 | BUG(); | 228 | BUG(); |
| 228 | } | 229 | } |
| 229 | 230 | ||
| 230 | if (lkid != 0) | 231 | if (lkid != 0) { |
| 231 | lkf |= DLM_LKF_CONVERT; | 232 | lkf |= DLM_LKF_CONVERT; |
| 233 | if (test_bit(GLF_BLOCKING, &gl->gl_flags)) | ||
| 234 | lkf |= DLM_LKF_QUECVT; | ||
| 235 | } | ||
| 232 | 236 | ||
| 233 | return lkf; | 237 | return lkf; |
| 234 | } | 238 | } |
| @@ -250,7 +254,7 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state, | |||
| 250 | char strname[GDLM_STRNAME_BYTES] = ""; | 254 | char strname[GDLM_STRNAME_BYTES] = ""; |
| 251 | 255 | ||
| 252 | req = make_mode(req_state); | 256 | req = make_mode(req_state); |
| 253 | lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req); | 257 | lkf = make_flags(gl, flags, req); |
| 254 | gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT); | 258 | gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT); |
| 255 | gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); | 259 | gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); |
| 256 | if (gl->gl_lksb.sb_lkid) { | 260 | if (gl->gl_lksb.sb_lkid) { |
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index 4dfbfec357e8..ec2a9c23f0c9 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c | |||
| @@ -366,6 +366,10 @@ int hfsplus_rename_cat(u32 cnid, | |||
| 366 | err = hfs_brec_find(&src_fd); | 366 | err = hfs_brec_find(&src_fd); |
| 367 | if (err) | 367 | if (err) |
| 368 | goto out; | 368 | goto out; |
| 369 | if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) { | ||
| 370 | err = -EIO; | ||
| 371 | goto out; | ||
| 372 | } | ||
| 369 | 373 | ||
| 370 | hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, | 374 | hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, |
| 371 | src_fd.entrylength); | 375 | src_fd.entrylength); |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 88e155f895c6..26b53fb09f68 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
| @@ -150,6 +150,11 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 150 | filp->f_pos++; | 150 | filp->f_pos++; |
| 151 | /* fall through */ | 151 | /* fall through */ |
| 152 | case 1: | 152 | case 1: |
| 153 | if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { | ||
| 154 | err = -EIO; | ||
| 155 | goto out; | ||
| 156 | } | ||
| 157 | |||
| 153 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | 158 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, |
| 154 | fd.entrylength); | 159 | fd.entrylength); |
| 155 | if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { | 160 | if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { |
| @@ -181,6 +186,12 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 181 | err = -EIO; | 186 | err = -EIO; |
| 182 | goto out; | 187 | goto out; |
| 183 | } | 188 | } |
| 189 | |||
| 190 | if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { | ||
| 191 | err = -EIO; | ||
| 192 | goto out; | ||
| 193 | } | ||
| 194 | |||
| 184 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | 195 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, |
| 185 | fd.entrylength); | 196 | fd.entrylength); |
| 186 | type = be16_to_cpu(entry.type); | 197 | type = be16_to_cpu(entry.type); |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 28cf06e4ec84..001ef01d2fe2 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
| @@ -485,6 +485,7 @@ static struct inode *hugetlbfs_get_root(struct super_block *sb, | |||
| 485 | inode->i_fop = &simple_dir_operations; | 485 | inode->i_fop = &simple_dir_operations; |
| 486 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | 486 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ |
| 487 | inc_nlink(inode); | 487 | inc_nlink(inode); |
| 488 | lockdep_annotate_inode_mutex_key(inode); | ||
| 488 | } | 489 | } |
| 489 | return inode; | 490 | return inode; |
| 490 | } | 491 | } |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 806525a7269c..840f70f50792 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -723,7 +723,7 @@ start_journal_io: | |||
| 723 | if (commit_transaction->t_need_data_flush && | 723 | if (commit_transaction->t_need_data_flush && |
| 724 | (journal->j_fs_dev != journal->j_dev) && | 724 | (journal->j_fs_dev != journal->j_dev) && |
| 725 | (journal->j_flags & JBD2_BARRIER)) | 725 | (journal->j_flags & JBD2_BARRIER)) |
| 726 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); | 726 | blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); |
| 727 | 727 | ||
| 728 | /* Done it all: now write the commit record asynchronously. */ | 728 | /* Done it all: now write the commit record asynchronously. */ |
| 729 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | 729 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, |
| @@ -859,7 +859,7 @@ wait_for_iobuf: | |||
| 859 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | 859 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, |
| 860 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) && | 860 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) && |
| 861 | journal->j_flags & JBD2_BARRIER) { | 861 | journal->j_flags & JBD2_BARRIER) { |
| 862 | blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL); | 862 | blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL); |
| 863 | } | 863 | } |
| 864 | 864 | ||
| 865 | if (err) | 865 | if (err) |
diff --git a/fs/namei.c b/fs/namei.c index 0062dd17eb55..c42791914f82 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -1429,7 +1429,7 @@ unsigned int full_name_hash(const unsigned char *name, unsigned int len) | |||
| 1429 | unsigned long hash = 0; | 1429 | unsigned long hash = 0; |
| 1430 | 1430 | ||
| 1431 | for (;;) { | 1431 | for (;;) { |
| 1432 | a = *(unsigned long *)name; | 1432 | a = load_unaligned_zeropad(name); |
| 1433 | if (len < sizeof(unsigned long)) | 1433 | if (len < sizeof(unsigned long)) |
| 1434 | break; | 1434 | break; |
| 1435 | hash += a; | 1435 | hash += a; |
| @@ -1459,7 +1459,7 @@ static inline unsigned long hash_name(const char *name, unsigned int *hashp) | |||
| 1459 | do { | 1459 | do { |
| 1460 | hash = (hash + a) * 9; | 1460 | hash = (hash + a) * 9; |
| 1461 | len += sizeof(unsigned long); | 1461 | len += sizeof(unsigned long); |
| 1462 | a = *(unsigned long *)(name+len); | 1462 | a = load_unaligned_zeropad(name+len); |
| 1463 | /* Do we have any NUL or '/' bytes in this word? */ | 1463 | /* Do we have any NUL or '/' bytes in this word? */ |
| 1464 | mask = has_zero(a) | has_zero(a ^ REPEAT_BYTE('/')); | 1464 | mask = has_zero(a) | has_zero(a ^ REPEAT_BYTE('/')); |
| 1465 | } while (!mask); | 1465 | } while (!mask); |
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 9c94297bb70e..7f6a23f0244e 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
| @@ -38,6 +38,8 @@ | |||
| 38 | #include <linux/buffer_head.h> /* various write calls */ | 38 | #include <linux/buffer_head.h> /* various write calls */ |
| 39 | #include <linux/prefetch.h> | 39 | #include <linux/prefetch.h> |
| 40 | 40 | ||
| 41 | #include "../pnfs.h" | ||
| 42 | #include "../internal.h" | ||
| 41 | #include "blocklayout.h" | 43 | #include "blocklayout.h" |
| 42 | 44 | ||
| 43 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD | 45 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD |
| @@ -868,7 +870,7 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh, | |||
| 868 | * GETDEVICEINFO's maxcount | 870 | * GETDEVICEINFO's maxcount |
| 869 | */ | 871 | */ |
| 870 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | 872 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; |
| 871 | max_pages = max_resp_sz >> PAGE_SHIFT; | 873 | max_pages = nfs_page_array_len(0, max_resp_sz); |
| 872 | dprintk("%s max_resp_sz %u max_pages %d\n", | 874 | dprintk("%s max_resp_sz %u max_pages %d\n", |
| 873 | __func__, max_resp_sz, max_pages); | 875 | __func__, max_resp_sz, max_pages); |
| 874 | 876 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index da7b5e4ff9ec..60f7e4ec842c 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -1729,7 +1729,8 @@ error: | |||
| 1729 | */ | 1729 | */ |
| 1730 | struct nfs_server *nfs_clone_server(struct nfs_server *source, | 1730 | struct nfs_server *nfs_clone_server(struct nfs_server *source, |
| 1731 | struct nfs_fh *fh, | 1731 | struct nfs_fh *fh, |
| 1732 | struct nfs_fattr *fattr) | 1732 | struct nfs_fattr *fattr, |
| 1733 | rpc_authflavor_t flavor) | ||
| 1733 | { | 1734 | { |
| 1734 | struct nfs_server *server; | 1735 | struct nfs_server *server; |
| 1735 | struct nfs_fattr *fattr_fsinfo; | 1736 | struct nfs_fattr *fattr_fsinfo; |
| @@ -1758,7 +1759,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
| 1758 | 1759 | ||
| 1759 | error = nfs_init_server_rpcclient(server, | 1760 | error = nfs_init_server_rpcclient(server, |
| 1760 | source->client->cl_timeout, | 1761 | source->client->cl_timeout, |
| 1761 | source->client->cl_auth->au_flavor); | 1762 | flavor); |
| 1762 | if (error < 0) | 1763 | if (error < 0) |
| 1763 | goto out_free_server; | 1764 | goto out_free_server; |
| 1764 | if (!IS_ERR(source->client_acl)) | 1765 | if (!IS_ERR(source->client_acl)) |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 4aaf0316d76a..8789210c6905 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1429,7 +1429,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
| 1429 | } | 1429 | } |
| 1430 | 1430 | ||
| 1431 | open_flags = nd->intent.open.flags; | 1431 | open_flags = nd->intent.open.flags; |
| 1432 | attr.ia_valid = 0; | 1432 | attr.ia_valid = ATTR_OPEN; |
| 1433 | 1433 | ||
| 1434 | ctx = create_nfs_open_context(dentry, open_flags); | 1434 | ctx = create_nfs_open_context(dentry, open_flags); |
| 1435 | res = ERR_CAST(ctx); | 1435 | res = ERR_CAST(ctx); |
| @@ -1536,7 +1536,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 1536 | if (IS_ERR(ctx)) | 1536 | if (IS_ERR(ctx)) |
| 1537 | goto out; | 1537 | goto out; |
| 1538 | 1538 | ||
| 1539 | attr.ia_valid = 0; | 1539 | attr.ia_valid = ATTR_OPEN; |
| 1540 | if (openflags & O_TRUNC) { | 1540 | if (openflags & O_TRUNC) { |
| 1541 | attr.ia_valid |= ATTR_SIZE; | 1541 | attr.ia_valid |= ATTR_SIZE; |
| 1542 | attr.ia_size = 0; | 1542 | attr.ia_size = 0; |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index b7f348bb618b..ba3019f5934c 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
| @@ -554,12 +554,16 @@ static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | |||
| 554 | struct nfs_client *clp; | 554 | struct nfs_client *clp; |
| 555 | int error = 0; | 555 | int error = 0; |
| 556 | 556 | ||
| 557 | if (!try_module_get(THIS_MODULE)) | ||
| 558 | return 0; | ||
| 559 | |||
| 557 | while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) { | 560 | while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) { |
| 558 | error = __rpc_pipefs_event(clp, event, sb); | 561 | error = __rpc_pipefs_event(clp, event, sb); |
| 559 | nfs_put_client(clp); | 562 | nfs_put_client(clp); |
| 560 | if (error) | 563 | if (error) |
| 561 | break; | 564 | break; |
| 562 | } | 565 | } |
| 566 | module_put(THIS_MODULE); | ||
| 563 | return error; | 567 | return error; |
| 564 | } | 568 | } |
| 565 | 569 | ||
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 2476dc69365f..b777bdaba4c5 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -165,7 +165,8 @@ extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, | |||
| 165 | extern void nfs_free_server(struct nfs_server *server); | 165 | extern void nfs_free_server(struct nfs_server *server); |
| 166 | extern struct nfs_server *nfs_clone_server(struct nfs_server *, | 166 | extern struct nfs_server *nfs_clone_server(struct nfs_server *, |
| 167 | struct nfs_fh *, | 167 | struct nfs_fh *, |
| 168 | struct nfs_fattr *); | 168 | struct nfs_fattr *, |
| 169 | rpc_authflavor_t); | ||
| 169 | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); | 170 | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); |
| 170 | extern int nfs4_check_client_ready(struct nfs_client *clp); | 171 | extern int nfs4_check_client_ready(struct nfs_client *clp); |
| 171 | extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, | 172 | extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, |
| @@ -186,10 +187,10 @@ static inline void nfs_fs_proc_exit(void) | |||
| 186 | 187 | ||
| 187 | /* nfs4namespace.c */ | 188 | /* nfs4namespace.c */ |
| 188 | #ifdef CONFIG_NFS_V4 | 189 | #ifdef CONFIG_NFS_V4 |
| 189 | extern struct vfsmount *nfs_do_refmount(struct dentry *dentry); | 190 | extern struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry); |
| 190 | #else | 191 | #else |
| 191 | static inline | 192 | static inline |
| 192 | struct vfsmount *nfs_do_refmount(struct dentry *dentry) | 193 | struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry) |
| 193 | { | 194 | { |
| 194 | return ERR_PTR(-ENOENT); | 195 | return ERR_PTR(-ENOENT); |
| 195 | } | 196 | } |
| @@ -234,7 +235,6 @@ extern const u32 nfs41_maxwrite_overhead; | |||
| 234 | /* nfs4proc.c */ | 235 | /* nfs4proc.c */ |
| 235 | #ifdef CONFIG_NFS_V4 | 236 | #ifdef CONFIG_NFS_V4 |
| 236 | extern struct rpc_procinfo nfs4_procedures[]; | 237 | extern struct rpc_procinfo nfs4_procedures[]; |
| 237 | void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *); | ||
| 238 | #endif | 238 | #endif |
| 239 | 239 | ||
| 240 | extern int nfs4_init_ds_session(struct nfs_client *clp); | 240 | extern int nfs4_init_ds_session(struct nfs_client *clp); |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 1807866bb3ab..d51868e5683c 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
| @@ -148,66 +148,31 @@ rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors) | |||
| 148 | return pseudoflavor; | 148 | return pseudoflavor; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | static int nfs_negotiate_security(const struct dentry *parent, | 151 | static struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir, |
| 152 | const struct dentry *dentry, | 152 | struct qstr *name, |
| 153 | rpc_authflavor_t *flavor) | 153 | struct nfs_fh *fh, |
| 154 | struct nfs_fattr *fattr) | ||
| 154 | { | 155 | { |
| 155 | struct page *page; | ||
| 156 | struct nfs4_secinfo_flavors *flavors; | ||
| 157 | int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); | ||
| 158 | int ret = -EPERM; | ||
| 159 | |||
| 160 | secinfo = NFS_PROTO(parent->d_inode)->secinfo; | ||
| 161 | if (secinfo != NULL) { | ||
| 162 | page = alloc_page(GFP_KERNEL); | ||
| 163 | if (!page) { | ||
| 164 | ret = -ENOMEM; | ||
| 165 | goto out; | ||
| 166 | } | ||
| 167 | flavors = page_address(page); | ||
| 168 | ret = secinfo(parent->d_inode, &dentry->d_name, flavors); | ||
| 169 | *flavor = nfs_find_best_sec(flavors); | ||
| 170 | put_page(page); | ||
| 171 | } | ||
| 172 | |||
| 173 | out: | ||
| 174 | return ret; | ||
| 175 | } | ||
| 176 | |||
| 177 | static int nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent, | ||
| 178 | struct dentry *dentry, struct path *path, | ||
| 179 | struct nfs_fh *fh, struct nfs_fattr *fattr, | ||
| 180 | rpc_authflavor_t *flavor) | ||
| 181 | { | ||
| 182 | struct rpc_clnt *clone; | ||
| 183 | struct rpc_auth *auth; | ||
| 184 | int err; | 156 | int err; |
| 185 | 157 | ||
| 186 | err = nfs_negotiate_security(parent, path->dentry, flavor); | 158 | if (NFS_PROTO(dir)->version == 4) |
| 187 | if (err < 0) | 159 | return nfs4_proc_lookup_mountpoint(dir, name, fh, fattr); |
| 188 | goto out; | 160 | |
| 189 | clone = rpc_clone_client(server->client); | 161 | err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr); |
| 190 | auth = rpcauth_create(*flavor, clone); | 162 | if (err) |
| 191 | if (!auth) { | 163 | return ERR_PTR(err); |
| 192 | err = -EIO; | 164 | return rpc_clone_client(NFS_SERVER(dir)->client); |
| 193 | goto out_shutdown; | ||
| 194 | } | ||
| 195 | err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode, | ||
| 196 | &path->dentry->d_name, | ||
| 197 | fh, fattr); | ||
| 198 | out_shutdown: | ||
| 199 | rpc_shutdown_client(clone); | ||
| 200 | out: | ||
| 201 | return err; | ||
| 202 | } | 165 | } |
| 203 | #else /* CONFIG_NFS_V4 */ | 166 | #else /* CONFIG_NFS_V4 */ |
| 204 | static inline int nfs_lookup_with_sec(struct nfs_server *server, | 167 | static inline struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir, |
| 205 | struct dentry *parent, struct dentry *dentry, | 168 | struct qstr *name, |
| 206 | struct path *path, struct nfs_fh *fh, | 169 | struct nfs_fh *fh, |
| 207 | struct nfs_fattr *fattr, | 170 | struct nfs_fattr *fattr) |
| 208 | rpc_authflavor_t *flavor) | ||
| 209 | { | 171 | { |
| 210 | return -EPERM; | 172 | int err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr); |
| 173 | if (err) | ||
| 174 | return ERR_PTR(err); | ||
| 175 | return rpc_clone_client(NFS_SERVER(dir)->client); | ||
| 211 | } | 176 | } |
| 212 | #endif /* CONFIG_NFS_V4 */ | 177 | #endif /* CONFIG_NFS_V4 */ |
| 213 | 178 | ||
| @@ -226,12 +191,10 @@ static inline int nfs_lookup_with_sec(struct nfs_server *server, | |||
| 226 | struct vfsmount *nfs_d_automount(struct path *path) | 191 | struct vfsmount *nfs_d_automount(struct path *path) |
| 227 | { | 192 | { |
| 228 | struct vfsmount *mnt; | 193 | struct vfsmount *mnt; |
| 229 | struct nfs_server *server = NFS_SERVER(path->dentry->d_inode); | ||
| 230 | struct dentry *parent; | 194 | struct dentry *parent; |
| 231 | struct nfs_fh *fh = NULL; | 195 | struct nfs_fh *fh = NULL; |
| 232 | struct nfs_fattr *fattr = NULL; | 196 | struct nfs_fattr *fattr = NULL; |
| 233 | int err; | 197 | struct rpc_clnt *client; |
| 234 | rpc_authflavor_t flavor = RPC_AUTH_UNIX; | ||
| 235 | 198 | ||
| 236 | dprintk("--> nfs_d_automount()\n"); | 199 | dprintk("--> nfs_d_automount()\n"); |
| 237 | 200 | ||
| @@ -249,21 +212,19 @@ struct vfsmount *nfs_d_automount(struct path *path) | |||
| 249 | 212 | ||
| 250 | /* Look it up again to get its attributes */ | 213 | /* Look it up again to get its attributes */ |
| 251 | parent = dget_parent(path->dentry); | 214 | parent = dget_parent(path->dentry); |
| 252 | err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, | 215 | client = nfs_lookup_mountpoint(parent->d_inode, &path->dentry->d_name, fh, fattr); |
| 253 | &path->dentry->d_name, | ||
| 254 | fh, fattr); | ||
| 255 | if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL) | ||
| 256 | err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor); | ||
| 257 | dput(parent); | 216 | dput(parent); |
| 258 | if (err != 0) { | 217 | if (IS_ERR(client)) { |
| 259 | mnt = ERR_PTR(err); | 218 | mnt = ERR_CAST(client); |
| 260 | goto out; | 219 | goto out; |
| 261 | } | 220 | } |
| 262 | 221 | ||
| 263 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 222 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
| 264 | mnt = nfs_do_refmount(path->dentry); | 223 | mnt = nfs_do_refmount(client, path->dentry); |
| 265 | else | 224 | else |
| 266 | mnt = nfs_do_submount(path->dentry, fh, fattr, flavor); | 225 | mnt = nfs_do_submount(path->dentry, fh, fattr, client->cl_auth->au_flavor); |
| 226 | rpc_shutdown_client(client); | ||
| 227 | |||
| 267 | if (IS_ERR(mnt)) | 228 | if (IS_ERR(mnt)) |
| 268 | goto out; | 229 | goto out; |
| 269 | 230 | ||
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 97ecc863dd76..8d75021020b3 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
| @@ -59,6 +59,7 @@ struct nfs_unique_id { | |||
| 59 | 59 | ||
| 60 | #define NFS_SEQID_CONFIRMED 1 | 60 | #define NFS_SEQID_CONFIRMED 1 |
| 61 | struct nfs_seqid_counter { | 61 | struct nfs_seqid_counter { |
| 62 | ktime_t create_time; | ||
| 62 | int owner_id; | 63 | int owner_id; |
| 63 | int flags; | 64 | int flags; |
| 64 | u32 counter; | 65 | u32 counter; |
| @@ -204,6 +205,9 @@ struct nfs4_state_maintenance_ops { | |||
| 204 | extern const struct dentry_operations nfs4_dentry_operations; | 205 | extern const struct dentry_operations nfs4_dentry_operations; |
| 205 | extern const struct inode_operations nfs4_dir_inode_operations; | 206 | extern const struct inode_operations nfs4_dir_inode_operations; |
| 206 | 207 | ||
| 208 | /* nfs4namespace.c */ | ||
| 209 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); | ||
| 210 | |||
| 207 | /* nfs4proc.c */ | 211 | /* nfs4proc.c */ |
| 208 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); | 212 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); |
| 209 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); | 213 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); |
| @@ -212,8 +216,11 @@ extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); | |||
| 212 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); | 216 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); |
| 213 | extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc); | 217 | extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc); |
| 214 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); | 218 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); |
| 215 | extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | 219 | extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *, |
| 216 | struct nfs4_fs_locations *fs_locations, struct page *page); | 220 | struct nfs4_fs_locations *, struct page *); |
| 221 | extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *, | ||
| 222 | struct nfs_fh *, struct nfs_fattr *); | ||
| 223 | extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); | ||
| 217 | extern int nfs4_release_lockowner(struct nfs4_lock_state *); | 224 | extern int nfs4_release_lockowner(struct nfs4_lock_state *); |
| 218 | extern const struct xattr_handler *nfs4_xattr_handlers[]; | 225 | extern const struct xattr_handler *nfs4_xattr_handlers[]; |
| 219 | 226 | ||
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index a866bbd2890a..c9cff9adb2d3 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
| @@ -699,7 +699,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_fla | |||
| 699 | * GETDEVICEINFO's maxcount | 699 | * GETDEVICEINFO's maxcount |
| 700 | */ | 700 | */ |
| 701 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | 701 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; |
| 702 | max_pages = max_resp_sz >> PAGE_SHIFT; | 702 | max_pages = nfs_page_array_len(0, max_resp_sz); |
| 703 | dprintk("%s inode %p max_resp_sz %u max_pages %d\n", | 703 | dprintk("%s inode %p max_resp_sz %u max_pages %d\n", |
| 704 | __func__, inode, max_resp_sz, max_pages); | 704 | __func__, inode, max_resp_sz, max_pages); |
| 705 | 705 | ||
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 9c8eca315f43..a7f3dedc4ec7 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
| @@ -52,6 +52,30 @@ Elong: | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | /* | 54 | /* |
| 55 | * return the path component of "<server>:<path>" | ||
| 56 | * nfspath - the "<server>:<path>" string | ||
| 57 | * end - one past the last char that could contain "<server>:" | ||
| 58 | * returns NULL on failure | ||
| 59 | */ | ||
| 60 | static char *nfs_path_component(const char *nfspath, const char *end) | ||
| 61 | { | ||
| 62 | char *p; | ||
| 63 | |||
| 64 | if (*nfspath == '[') { | ||
| 65 | /* parse [] escaped IPv6 addrs */ | ||
| 66 | p = strchr(nfspath, ']'); | ||
| 67 | if (p != NULL && ++p < end && *p == ':') | ||
| 68 | return p + 1; | ||
| 69 | } else { | ||
| 70 | /* otherwise split on first colon */ | ||
| 71 | p = strchr(nfspath, ':'); | ||
| 72 | if (p != NULL && p < end) | ||
| 73 | return p + 1; | ||
| 74 | } | ||
| 75 | return NULL; | ||
| 76 | } | ||
| 77 | |||
| 78 | /* | ||
| 55 | * Determine the mount path as a string | 79 | * Determine the mount path as a string |
| 56 | */ | 80 | */ |
| 57 | static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) | 81 | static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) |
| @@ -59,9 +83,9 @@ static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) | |||
| 59 | char *limit; | 83 | char *limit; |
| 60 | char *path = nfs_path(&limit, dentry, buffer, buflen); | 84 | char *path = nfs_path(&limit, dentry, buffer, buflen); |
| 61 | if (!IS_ERR(path)) { | 85 | if (!IS_ERR(path)) { |
| 62 | char *colon = strchr(path, ':'); | 86 | char *path_component = nfs_path_component(path, limit); |
| 63 | if (colon && colon < limit) | 87 | if (path_component) |
| 64 | path = colon + 1; | 88 | return path_component; |
| 65 | } | 89 | } |
| 66 | return path; | 90 | return path; |
| 67 | } | 91 | } |
| @@ -108,6 +132,58 @@ static size_t nfs_parse_server_name(char *string, size_t len, | |||
| 108 | return ret; | 132 | return ret; |
| 109 | } | 133 | } |
| 110 | 134 | ||
| 135 | static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name) | ||
| 136 | { | ||
| 137 | struct page *page; | ||
| 138 | struct nfs4_secinfo_flavors *flavors; | ||
| 139 | rpc_authflavor_t flavor; | ||
| 140 | int err; | ||
| 141 | |||
| 142 | page = alloc_page(GFP_KERNEL); | ||
| 143 | if (!page) | ||
| 144 | return -ENOMEM; | ||
| 145 | flavors = page_address(page); | ||
| 146 | |||
| 147 | err = nfs4_proc_secinfo(inode, name, flavors); | ||
| 148 | if (err < 0) { | ||
| 149 | flavor = err; | ||
| 150 | goto out; | ||
| 151 | } | ||
| 152 | |||
| 153 | flavor = nfs_find_best_sec(flavors); | ||
| 154 | |||
| 155 | out: | ||
| 156 | put_page(page); | ||
| 157 | return flavor; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* | ||
| 161 | * Please call rpc_shutdown_client() when you are done with this client. | ||
| 162 | */ | ||
| 163 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *clnt, struct inode *inode, | ||
| 164 | struct qstr *name) | ||
| 165 | { | ||
| 166 | struct rpc_clnt *clone; | ||
| 167 | struct rpc_auth *auth; | ||
| 168 | rpc_authflavor_t flavor; | ||
| 169 | |||
| 170 | flavor = nfs4_negotiate_security(inode, name); | ||
| 171 | if (flavor < 0) | ||
| 172 | return ERR_PTR(flavor); | ||
| 173 | |||
| 174 | clone = rpc_clone_client(clnt); | ||
| 175 | if (IS_ERR(clone)) | ||
| 176 | return clone; | ||
| 177 | |||
| 178 | auth = rpcauth_create(flavor, clone); | ||
| 179 | if (!auth) { | ||
| 180 | rpc_shutdown_client(clone); | ||
| 181 | clone = ERR_PTR(-EIO); | ||
| 182 | } | ||
| 183 | |||
| 184 | return clone; | ||
| 185 | } | ||
| 186 | |||
| 111 | static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | 187 | static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, |
| 112 | char *page, char *page2, | 188 | char *page, char *page2, |
| 113 | const struct nfs4_fs_location *location) | 189 | const struct nfs4_fs_location *location) |
| @@ -224,7 +300,7 @@ out: | |||
| 224 | * @dentry - dentry of referral | 300 | * @dentry - dentry of referral |
| 225 | * | 301 | * |
| 226 | */ | 302 | */ |
| 227 | struct vfsmount *nfs_do_refmount(struct dentry *dentry) | 303 | struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry) |
| 228 | { | 304 | { |
| 229 | struct vfsmount *mnt = ERR_PTR(-ENOMEM); | 305 | struct vfsmount *mnt = ERR_PTR(-ENOMEM); |
| 230 | struct dentry *parent; | 306 | struct dentry *parent; |
| @@ -250,7 +326,7 @@ struct vfsmount *nfs_do_refmount(struct dentry *dentry) | |||
| 250 | dprintk("%s: getting locations for %s/%s\n", | 326 | dprintk("%s: getting locations for %s/%s\n", |
| 251 | __func__, parent->d_name.name, dentry->d_name.name); | 327 | __func__, parent->d_name.name, dentry->d_name.name); |
| 252 | 328 | ||
| 253 | err = nfs4_proc_fs_locations(parent->d_inode, &dentry->d_name, fs_locations, page); | 329 | err = nfs4_proc_fs_locations(client, parent->d_inode, &dentry->d_name, fs_locations, page); |
| 254 | dput(parent); | 330 | dput(parent); |
| 255 | if (err != 0 || | 331 | if (err != 0 || |
| 256 | fs_locations->nlocations <= 0 || | 332 | fs_locations->nlocations <= 0 || |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f82bde005a82..99650aaf8937 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -838,7 +838,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
| 838 | p->o_arg.open_flags = flags; | 838 | p->o_arg.open_flags = flags; |
| 839 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); | 839 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); |
| 840 | p->o_arg.clientid = server->nfs_client->cl_clientid; | 840 | p->o_arg.clientid = server->nfs_client->cl_clientid; |
| 841 | p->o_arg.id = sp->so_seqid.owner_id; | 841 | p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time); |
| 842 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; | ||
| 842 | p->o_arg.name = &dentry->d_name; | 843 | p->o_arg.name = &dentry->d_name; |
| 843 | p->o_arg.server = server; | 844 | p->o_arg.server = server; |
| 844 | p->o_arg.bitmask = server->attr_bitmask; | 845 | p->o_arg.bitmask = server->attr_bitmask; |
| @@ -1466,8 +1467,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
| 1466 | goto unlock_no_action; | 1467 | goto unlock_no_action; |
| 1467 | rcu_read_unlock(); | 1468 | rcu_read_unlock(); |
| 1468 | } | 1469 | } |
| 1469 | /* Update sequence id. */ | 1470 | /* Update client id. */ |
| 1470 | data->o_arg.id = sp->so_seqid.owner_id; | ||
| 1471 | data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; | 1471 | data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; |
| 1472 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { | 1472 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { |
| 1473 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; | 1473 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
| @@ -1954,10 +1954,19 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
| 1954 | }; | 1954 | }; |
| 1955 | int err; | 1955 | int err; |
| 1956 | do { | 1956 | do { |
| 1957 | err = nfs4_handle_exception(server, | 1957 | err = _nfs4_do_setattr(inode, cred, fattr, sattr, state); |
| 1958 | _nfs4_do_setattr(inode, cred, fattr, sattr, state), | 1958 | switch (err) { |
| 1959 | &exception); | 1959 | case -NFS4ERR_OPENMODE: |
| 1960 | if (state && !(state->state & FMODE_WRITE)) { | ||
| 1961 | err = -EBADF; | ||
| 1962 | if (sattr->ia_valid & ATTR_OPEN) | ||
| 1963 | err = -EACCES; | ||
| 1964 | goto out; | ||
| 1965 | } | ||
| 1966 | } | ||
| 1967 | err = nfs4_handle_exception(server, err, &exception); | ||
| 1960 | } while (exception.retry); | 1968 | } while (exception.retry); |
| 1969 | out: | ||
| 1961 | return err; | 1970 | return err; |
| 1962 | } | 1971 | } |
| 1963 | 1972 | ||
| @@ -2368,8 +2377,9 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 2368 | * Note that we'll actually follow the referral later when | 2377 | * Note that we'll actually follow the referral later when |
| 2369 | * we detect fsid mismatch in inode revalidation | 2378 | * we detect fsid mismatch in inode revalidation |
| 2370 | */ | 2379 | */ |
| 2371 | static int nfs4_get_referral(struct inode *dir, const struct qstr *name, | 2380 | static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir, |
| 2372 | struct nfs_fattr *fattr, struct nfs_fh *fhandle) | 2381 | const struct qstr *name, struct nfs_fattr *fattr, |
| 2382 | struct nfs_fh *fhandle) | ||
| 2373 | { | 2383 | { |
| 2374 | int status = -ENOMEM; | 2384 | int status = -ENOMEM; |
| 2375 | struct page *page = NULL; | 2385 | struct page *page = NULL; |
| @@ -2382,7 +2392,7 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, | |||
| 2382 | if (locations == NULL) | 2392 | if (locations == NULL) |
| 2383 | goto out; | 2393 | goto out; |
| 2384 | 2394 | ||
| 2385 | status = nfs4_proc_fs_locations(dir, name, locations, page); | 2395 | status = nfs4_proc_fs_locations(client, dir, name, locations, page); |
| 2386 | if (status != 0) | 2396 | if (status != 0) |
| 2387 | goto out; | 2397 | goto out; |
| 2388 | /* Make sure server returned a different fsid for the referral */ | 2398 | /* Make sure server returned a different fsid for the referral */ |
| @@ -2519,39 +2529,84 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | |||
| 2519 | return status; | 2529 | return status; |
| 2520 | } | 2530 | } |
| 2521 | 2531 | ||
| 2522 | void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh) | 2532 | static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr) |
| 2523 | { | 2533 | { |
| 2524 | memset(fh, 0, sizeof(struct nfs_fh)); | ||
| 2525 | fattr->fsid.major = 1; | ||
| 2526 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | | 2534 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | |
| 2527 | NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT; | 2535 | NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_MOUNTPOINT; |
| 2528 | fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; | 2536 | fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; |
| 2529 | fattr->nlink = 2; | 2537 | fattr->nlink = 2; |
| 2530 | } | 2538 | } |
| 2531 | 2539 | ||
| 2532 | static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, | 2540 | static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, |
| 2533 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2541 | struct qstr *name, struct nfs_fh *fhandle, |
| 2542 | struct nfs_fattr *fattr) | ||
| 2534 | { | 2543 | { |
| 2535 | struct nfs4_exception exception = { }; | 2544 | struct nfs4_exception exception = { }; |
| 2545 | struct rpc_clnt *client = *clnt; | ||
| 2536 | int err; | 2546 | int err; |
| 2537 | do { | 2547 | do { |
| 2538 | int status; | 2548 | err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr); |
| 2539 | 2549 | switch (err) { | |
| 2540 | status = _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr); | ||
| 2541 | switch (status) { | ||
| 2542 | case -NFS4ERR_BADNAME: | 2550 | case -NFS4ERR_BADNAME: |
| 2543 | return -ENOENT; | 2551 | err = -ENOENT; |
| 2552 | goto out; | ||
| 2544 | case -NFS4ERR_MOVED: | 2553 | case -NFS4ERR_MOVED: |
| 2545 | return nfs4_get_referral(dir, name, fattr, fhandle); | 2554 | err = nfs4_get_referral(client, dir, name, fattr, fhandle); |
| 2555 | goto out; | ||
| 2546 | case -NFS4ERR_WRONGSEC: | 2556 | case -NFS4ERR_WRONGSEC: |
| 2547 | nfs_fixup_secinfo_attributes(fattr, fhandle); | 2557 | err = -EPERM; |
| 2558 | if (client != *clnt) | ||
| 2559 | goto out; | ||
| 2560 | |||
| 2561 | client = nfs4_create_sec_client(client, dir, name); | ||
| 2562 | if (IS_ERR(client)) | ||
| 2563 | return PTR_ERR(client); | ||
| 2564 | |||
| 2565 | exception.retry = 1; | ||
| 2566 | break; | ||
| 2567 | default: | ||
| 2568 | err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception); | ||
| 2548 | } | 2569 | } |
| 2549 | err = nfs4_handle_exception(NFS_SERVER(dir), | ||
| 2550 | status, &exception); | ||
| 2551 | } while (exception.retry); | 2570 | } while (exception.retry); |
| 2571 | |||
| 2572 | out: | ||
| 2573 | if (err == 0) | ||
| 2574 | *clnt = client; | ||
| 2575 | else if (client != *clnt) | ||
| 2576 | rpc_shutdown_client(client); | ||
| 2577 | |||
| 2552 | return err; | 2578 | return err; |
| 2553 | } | 2579 | } |
| 2554 | 2580 | ||
| 2581 | static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, | ||
| 2582 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | ||
| 2583 | { | ||
| 2584 | int status; | ||
| 2585 | struct rpc_clnt *client = NFS_CLIENT(dir); | ||
| 2586 | |||
| 2587 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr); | ||
| 2588 | if (client != NFS_CLIENT(dir)) { | ||
| 2589 | rpc_shutdown_client(client); | ||
| 2590 | nfs_fixup_secinfo_attributes(fattr); | ||
| 2591 | } | ||
| 2592 | return status; | ||
| 2593 | } | ||
| 2594 | |||
| 2595 | struct rpc_clnt * | ||
| 2596 | nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name, | ||
| 2597 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | ||
| 2598 | { | ||
| 2599 | int status; | ||
| 2600 | struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir)); | ||
| 2601 | |||
| 2602 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr); | ||
| 2603 | if (status < 0) { | ||
| 2604 | rpc_shutdown_client(client); | ||
| 2605 | return ERR_PTR(status); | ||
| 2606 | } | ||
| 2607 | return client; | ||
| 2608 | } | ||
| 2609 | |||
| 2555 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | 2610 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
| 2556 | { | 2611 | { |
| 2557 | struct nfs_server *server = NFS_SERVER(inode); | 2612 | struct nfs_server *server = NFS_SERVER(inode); |
| @@ -3619,16 +3674,16 @@ out: | |||
| 3619 | return ret; | 3674 | return ret; |
| 3620 | } | 3675 | } |
| 3621 | 3676 | ||
| 3622 | static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len) | 3677 | static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) |
| 3623 | { | 3678 | { |
| 3624 | struct nfs4_cached_acl *acl; | 3679 | struct nfs4_cached_acl *acl; |
| 3625 | 3680 | ||
| 3626 | if (buf && acl_len <= PAGE_SIZE) { | 3681 | if (pages && acl_len <= PAGE_SIZE) { |
| 3627 | acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); | 3682 | acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); |
| 3628 | if (acl == NULL) | 3683 | if (acl == NULL) |
| 3629 | goto out; | 3684 | goto out; |
| 3630 | acl->cached = 1; | 3685 | acl->cached = 1; |
| 3631 | memcpy(acl->data, buf, acl_len); | 3686 | _copy_from_pages(acl->data, pages, pgbase, acl_len); |
| 3632 | } else { | 3687 | } else { |
| 3633 | acl = kmalloc(sizeof(*acl), GFP_KERNEL); | 3688 | acl = kmalloc(sizeof(*acl), GFP_KERNEL); |
| 3634 | if (acl == NULL) | 3689 | if (acl == NULL) |
| @@ -3661,7 +3716,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
| 3661 | struct nfs_getaclres res = { | 3716 | struct nfs_getaclres res = { |
| 3662 | .acl_len = buflen, | 3717 | .acl_len = buflen, |
| 3663 | }; | 3718 | }; |
| 3664 | void *resp_buf; | ||
| 3665 | struct rpc_message msg = { | 3719 | struct rpc_message msg = { |
| 3666 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], | 3720 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], |
| 3667 | .rpc_argp = &args, | 3721 | .rpc_argp = &args, |
| @@ -3675,24 +3729,27 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
| 3675 | if (npages == 0) | 3729 | if (npages == 0) |
| 3676 | npages = 1; | 3730 | npages = 1; |
| 3677 | 3731 | ||
| 3732 | /* Add an extra page to handle the bitmap returned */ | ||
| 3733 | npages++; | ||
| 3734 | |||
| 3678 | for (i = 0; i < npages; i++) { | 3735 | for (i = 0; i < npages; i++) { |
| 3679 | pages[i] = alloc_page(GFP_KERNEL); | 3736 | pages[i] = alloc_page(GFP_KERNEL); |
| 3680 | if (!pages[i]) | 3737 | if (!pages[i]) |
| 3681 | goto out_free; | 3738 | goto out_free; |
| 3682 | } | 3739 | } |
| 3683 | if (npages > 1) { | 3740 | |
| 3684 | /* for decoding across pages */ | 3741 | /* for decoding across pages */ |
| 3685 | res.acl_scratch = alloc_page(GFP_KERNEL); | 3742 | res.acl_scratch = alloc_page(GFP_KERNEL); |
| 3686 | if (!res.acl_scratch) | 3743 | if (!res.acl_scratch) |
| 3687 | goto out_free; | 3744 | goto out_free; |
| 3688 | } | 3745 | |
| 3689 | args.acl_len = npages * PAGE_SIZE; | 3746 | args.acl_len = npages * PAGE_SIZE; |
| 3690 | args.acl_pgbase = 0; | 3747 | args.acl_pgbase = 0; |
| 3748 | |||
| 3691 | /* Let decode_getfacl know not to fail if the ACL data is larger than | 3749 | /* Let decode_getfacl know not to fail if the ACL data is larger than |
| 3692 | * the page we send as a guess */ | 3750 | * the page we send as a guess */ |
| 3693 | if (buf == NULL) | 3751 | if (buf == NULL) |
| 3694 | res.acl_flags |= NFS4_ACL_LEN_REQUEST; | 3752 | res.acl_flags |= NFS4_ACL_LEN_REQUEST; |
| 3695 | resp_buf = page_address(pages[0]); | ||
| 3696 | 3753 | ||
| 3697 | dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", | 3754 | dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", |
| 3698 | __func__, buf, buflen, npages, args.acl_len); | 3755 | __func__, buf, buflen, npages, args.acl_len); |
| @@ -3703,9 +3760,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
| 3703 | 3760 | ||
| 3704 | acl_len = res.acl_len - res.acl_data_offset; | 3761 | acl_len = res.acl_len - res.acl_data_offset; |
| 3705 | if (acl_len > args.acl_len) | 3762 | if (acl_len > args.acl_len) |
| 3706 | nfs4_write_cached_acl(inode, NULL, acl_len); | 3763 | nfs4_write_cached_acl(inode, NULL, 0, acl_len); |
| 3707 | else | 3764 | else |
| 3708 | nfs4_write_cached_acl(inode, resp_buf + res.acl_data_offset, | 3765 | nfs4_write_cached_acl(inode, pages, res.acl_data_offset, |
| 3709 | acl_len); | 3766 | acl_len); |
| 3710 | if (buf) { | 3767 | if (buf) { |
| 3711 | ret = -ERANGE; | 3768 | ret = -ERANGE; |
| @@ -4558,7 +4615,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
| 4558 | static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) | 4615 | static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) |
| 4559 | { | 4616 | { |
| 4560 | struct nfs_server *server = NFS_SERVER(state->inode); | 4617 | struct nfs_server *server = NFS_SERVER(state->inode); |
| 4561 | struct nfs4_exception exception = { }; | 4618 | struct nfs4_exception exception = { |
| 4619 | .inode = state->inode, | ||
| 4620 | }; | ||
| 4562 | int err; | 4621 | int err; |
| 4563 | 4622 | ||
| 4564 | do { | 4623 | do { |
| @@ -4576,7 +4635,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request | |||
| 4576 | static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) | 4635 | static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) |
| 4577 | { | 4636 | { |
| 4578 | struct nfs_server *server = NFS_SERVER(state->inode); | 4637 | struct nfs_server *server = NFS_SERVER(state->inode); |
| 4579 | struct nfs4_exception exception = { }; | 4638 | struct nfs4_exception exception = { |
| 4639 | .inode = state->inode, | ||
| 4640 | }; | ||
| 4580 | int err; | 4641 | int err; |
| 4581 | 4642 | ||
| 4582 | err = nfs4_set_lock_state(state, request); | 4643 | err = nfs4_set_lock_state(state, request); |
| @@ -4676,6 +4737,7 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock * | |||
| 4676 | { | 4737 | { |
| 4677 | struct nfs4_exception exception = { | 4738 | struct nfs4_exception exception = { |
| 4678 | .state = state, | 4739 | .state = state, |
| 4740 | .inode = state->inode, | ||
| 4679 | }; | 4741 | }; |
| 4680 | int err; | 4742 | int err; |
| 4681 | 4743 | ||
| @@ -4721,6 +4783,20 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request) | |||
| 4721 | 4783 | ||
| 4722 | if (state == NULL) | 4784 | if (state == NULL) |
| 4723 | return -ENOLCK; | 4785 | return -ENOLCK; |
| 4786 | /* | ||
| 4787 | * Don't rely on the VFS having checked the file open mode, | ||
| 4788 | * since it won't do this for flock() locks. | ||
| 4789 | */ | ||
| 4790 | switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) { | ||
| 4791 | case F_RDLCK: | ||
| 4792 | if (!(filp->f_mode & FMODE_READ)) | ||
| 4793 | return -EBADF; | ||
| 4794 | break; | ||
| 4795 | case F_WRLCK: | ||
| 4796 | if (!(filp->f_mode & FMODE_WRITE)) | ||
| 4797 | return -EBADF; | ||
| 4798 | } | ||
| 4799 | |||
| 4724 | do { | 4800 | do { |
| 4725 | status = nfs4_proc_setlk(state, cmd, request); | 4801 | status = nfs4_proc_setlk(state, cmd, request); |
| 4726 | if ((status != -EAGAIN) || IS_SETLK(cmd)) | 4802 | if ((status != -EAGAIN) || IS_SETLK(cmd)) |
| @@ -4891,8 +4967,10 @@ static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) | |||
| 4891 | fattr->nlink = 2; | 4967 | fattr->nlink = 2; |
| 4892 | } | 4968 | } |
| 4893 | 4969 | ||
| 4894 | int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | 4970 | static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, |
| 4895 | struct nfs4_fs_locations *fs_locations, struct page *page) | 4971 | const struct qstr *name, |
| 4972 | struct nfs4_fs_locations *fs_locations, | ||
| 4973 | struct page *page) | ||
| 4896 | { | 4974 | { |
| 4897 | struct nfs_server *server = NFS_SERVER(dir); | 4975 | struct nfs_server *server = NFS_SERVER(dir); |
| 4898 | u32 bitmask[2] = { | 4976 | u32 bitmask[2] = { |
| @@ -4926,11 +5004,26 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
| 4926 | nfs_fattr_init(&fs_locations->fattr); | 5004 | nfs_fattr_init(&fs_locations->fattr); |
| 4927 | fs_locations->server = server; | 5005 | fs_locations->server = server; |
| 4928 | fs_locations->nlocations = 0; | 5006 | fs_locations->nlocations = 0; |
| 4929 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 5007 | status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0); |
| 4930 | dprintk("%s: returned status = %d\n", __func__, status); | 5008 | dprintk("%s: returned status = %d\n", __func__, status); |
| 4931 | return status; | 5009 | return status; |
| 4932 | } | 5010 | } |
| 4933 | 5011 | ||
| 5012 | int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | ||
| 5013 | const struct qstr *name, | ||
| 5014 | struct nfs4_fs_locations *fs_locations, | ||
| 5015 | struct page *page) | ||
| 5016 | { | ||
| 5017 | struct nfs4_exception exception = { }; | ||
| 5018 | int err; | ||
| 5019 | do { | ||
| 5020 | err = nfs4_handle_exception(NFS_SERVER(dir), | ||
| 5021 | _nfs4_proc_fs_locations(client, dir, name, fs_locations, page), | ||
| 5022 | &exception); | ||
| 5023 | } while (exception.retry); | ||
| 5024 | return err; | ||
| 5025 | } | ||
| 5026 | |||
| 4934 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) | 5027 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) |
| 4935 | { | 5028 | { |
| 4936 | int status; | 5029 | int status; |
| @@ -4953,8 +5046,8 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct | |||
| 4953 | return status; | 5046 | return status; |
| 4954 | } | 5047 | } |
| 4955 | 5048 | ||
| 4956 | static int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, | 5049 | int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, |
| 4957 | struct nfs4_secinfo_flavors *flavors) | 5050 | struct nfs4_secinfo_flavors *flavors) |
| 4958 | { | 5051 | { |
| 4959 | struct nfs4_exception exception = { }; | 5052 | struct nfs4_exception exception = { }; |
| 4960 | int err; | 5053 | int err; |
| @@ -5029,10 +5122,9 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
| 5029 | nfs4_construct_boot_verifier(clp, &verifier); | 5122 | nfs4_construct_boot_verifier(clp, &verifier); |
| 5030 | 5123 | ||
| 5031 | args.id_len = scnprintf(args.id, sizeof(args.id), | 5124 | args.id_len = scnprintf(args.id, sizeof(args.id), |
| 5032 | "%s/%s.%s/%u", | 5125 | "%s/%s/%u", |
| 5033 | clp->cl_ipaddr, | 5126 | clp->cl_ipaddr, |
| 5034 | init_utsname()->nodename, | 5127 | clp->cl_rpcclient->cl_nodename, |
| 5035 | init_utsname()->domainname, | ||
| 5036 | clp->cl_rpcclient->cl_auth->au_flavor); | 5128 | clp->cl_rpcclient->cl_auth->au_flavor); |
| 5037 | 5129 | ||
| 5038 | res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL); | 5130 | res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 0f43414eb25a..7f0fcfc1fe9d 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -393,6 +393,7 @@ nfs4_remove_state_owner_locked(struct nfs4_state_owner *sp) | |||
| 393 | static void | 393 | static void |
| 394 | nfs4_init_seqid_counter(struct nfs_seqid_counter *sc) | 394 | nfs4_init_seqid_counter(struct nfs_seqid_counter *sc) |
| 395 | { | 395 | { |
| 396 | sc->create_time = ktime_get(); | ||
| 396 | sc->flags = 0; | 397 | sc->flags = 0; |
| 397 | sc->counter = 0; | 398 | sc->counter = 0; |
| 398 | spin_lock_init(&sc->lock); | 399 | spin_lock_init(&sc->lock); |
| @@ -434,13 +435,17 @@ nfs4_alloc_state_owner(struct nfs_server *server, | |||
| 434 | static void | 435 | static void |
| 435 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) | 436 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) |
| 436 | { | 437 | { |
| 437 | if (!RB_EMPTY_NODE(&sp->so_server_node)) { | 438 | struct rb_node *rb_node = &sp->so_server_node; |
| 439 | |||
| 440 | if (!RB_EMPTY_NODE(rb_node)) { | ||
| 438 | struct nfs_server *server = sp->so_server; | 441 | struct nfs_server *server = sp->so_server; |
| 439 | struct nfs_client *clp = server->nfs_client; | 442 | struct nfs_client *clp = server->nfs_client; |
| 440 | 443 | ||
| 441 | spin_lock(&clp->cl_lock); | 444 | spin_lock(&clp->cl_lock); |
| 442 | rb_erase(&sp->so_server_node, &server->state_owners); | 445 | if (!RB_EMPTY_NODE(rb_node)) { |
| 443 | RB_CLEAR_NODE(&sp->so_server_node); | 446 | rb_erase(rb_node, &server->state_owners); |
| 447 | RB_CLEAR_NODE(rb_node); | ||
| 448 | } | ||
| 444 | spin_unlock(&clp->cl_lock); | 449 | spin_unlock(&clp->cl_lock); |
| 445 | } | 450 | } |
| 446 | } | 451 | } |
| @@ -516,6 +521,14 @@ out: | |||
| 516 | /** | 521 | /** |
| 517 | * nfs4_put_state_owner - Release a nfs4_state_owner | 522 | * nfs4_put_state_owner - Release a nfs4_state_owner |
| 518 | * @sp: state owner data to release | 523 | * @sp: state owner data to release |
| 524 | * | ||
| 525 | * Note that we keep released state owners on an LRU | ||
| 526 | * list. | ||
| 527 | * This caches valid state owners so that they can be | ||
| 528 | * reused, to avoid the OPEN_CONFIRM on minor version 0. | ||
| 529 | * It also pins the uniquifier of dropped state owners for | ||
| 530 | * a while, to ensure that those state owner names are | ||
| 531 | * never reused. | ||
| 519 | */ | 532 | */ |
| 520 | void nfs4_put_state_owner(struct nfs4_state_owner *sp) | 533 | void nfs4_put_state_owner(struct nfs4_state_owner *sp) |
| 521 | { | 534 | { |
| @@ -525,15 +538,9 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp) | |||
| 525 | if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) | 538 | if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) |
| 526 | return; | 539 | return; |
| 527 | 540 | ||
| 528 | if (!RB_EMPTY_NODE(&sp->so_server_node)) { | 541 | sp->so_expires = jiffies; |
| 529 | sp->so_expires = jiffies; | 542 | list_add_tail(&sp->so_lru, &server->state_owners_lru); |
| 530 | list_add_tail(&sp->so_lru, &server->state_owners_lru); | 543 | spin_unlock(&clp->cl_lock); |
| 531 | spin_unlock(&clp->cl_lock); | ||
| 532 | } else { | ||
| 533 | nfs4_remove_state_owner_locked(sp); | ||
| 534 | spin_unlock(&clp->cl_lock); | ||
| 535 | nfs4_free_state_owner(sp); | ||
| 536 | } | ||
| 537 | } | 544 | } |
| 538 | 545 | ||
| 539 | /** | 546 | /** |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c74fdb114b48..c54aae364bee 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -74,7 +74,7 @@ static int nfs4_stat_to_errno(int); | |||
| 74 | /* lock,open owner id: | 74 | /* lock,open owner id: |
| 75 | * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) | 75 | * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) |
| 76 | */ | 76 | */ |
| 77 | #define open_owner_id_maxsz (1 + 1 + 4) | 77 | #define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2) |
| 78 | #define lock_owner_id_maxsz (1 + 1 + 4) | 78 | #define lock_owner_id_maxsz (1 + 1 + 4) |
| 79 | #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 79 | #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
| 80 | #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) | 80 | #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) |
| @@ -1340,12 +1340,13 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena | |||
| 1340 | */ | 1340 | */ |
| 1341 | encode_nfs4_seqid(xdr, arg->seqid); | 1341 | encode_nfs4_seqid(xdr, arg->seqid); |
| 1342 | encode_share_access(xdr, arg->fmode); | 1342 | encode_share_access(xdr, arg->fmode); |
| 1343 | p = reserve_space(xdr, 32); | 1343 | p = reserve_space(xdr, 36); |
| 1344 | p = xdr_encode_hyper(p, arg->clientid); | 1344 | p = xdr_encode_hyper(p, arg->clientid); |
| 1345 | *p++ = cpu_to_be32(20); | 1345 | *p++ = cpu_to_be32(24); |
| 1346 | p = xdr_encode_opaque_fixed(p, "open id:", 8); | 1346 | p = xdr_encode_opaque_fixed(p, "open id:", 8); |
| 1347 | *p++ = cpu_to_be32(arg->server->s_dev); | 1347 | *p++ = cpu_to_be32(arg->server->s_dev); |
| 1348 | xdr_encode_hyper(p, arg->id); | 1348 | *p++ = cpu_to_be32(arg->id.uniquifier); |
| 1349 | xdr_encode_hyper(p, arg->id.create_time); | ||
| 1349 | } | 1350 | } |
| 1350 | 1351 | ||
| 1351 | static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) | 1352 | static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) |
| @@ -4257,8 +4258,6 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
| 4257 | status = decode_attr_error(xdr, bitmap, &err); | 4258 | status = decode_attr_error(xdr, bitmap, &err); |
| 4258 | if (status < 0) | 4259 | if (status < 0) |
| 4259 | goto xdr_error; | 4260 | goto xdr_error; |
| 4260 | if (err == -NFS4ERR_WRONGSEC) | ||
| 4261 | nfs_fixup_secinfo_attributes(fattr, fh); | ||
| 4262 | 4261 | ||
| 4263 | status = decode_attr_filehandle(xdr, bitmap, fh); | 4262 | status = decode_attr_filehandle(xdr, bitmap, fh); |
| 4264 | if (status < 0) | 4263 | if (status < 0) |
| @@ -4901,11 +4900,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
| 4901 | bitmap[3] = {0}; | 4900 | bitmap[3] = {0}; |
| 4902 | struct kvec *iov = req->rq_rcv_buf.head; | 4901 | struct kvec *iov = req->rq_rcv_buf.head; |
| 4903 | int status; | 4902 | int status; |
| 4903 | size_t page_len = xdr->buf->page_len; | ||
| 4904 | 4904 | ||
| 4905 | res->acl_len = 0; | 4905 | res->acl_len = 0; |
| 4906 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4906 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
| 4907 | goto out; | 4907 | goto out; |
| 4908 | |||
| 4908 | bm_p = xdr->p; | 4909 | bm_p = xdr->p; |
| 4910 | res->acl_data_offset = be32_to_cpup(bm_p) + 2; | ||
| 4911 | res->acl_data_offset <<= 2; | ||
| 4912 | /* Check if the acl data starts beyond the allocated buffer */ | ||
| 4913 | if (res->acl_data_offset > page_len) | ||
| 4914 | return -ERANGE; | ||
| 4915 | |||
| 4909 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | 4916 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
| 4910 | goto out; | 4917 | goto out; |
| 4911 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) | 4918 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) |
| @@ -4915,28 +4922,24 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
| 4915 | return -EIO; | 4922 | return -EIO; |
| 4916 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { | 4923 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { |
| 4917 | size_t hdrlen; | 4924 | size_t hdrlen; |
| 4918 | u32 recvd; | ||
| 4919 | 4925 | ||
| 4920 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words | 4926 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words |
| 4921 | * are stored with the acl data to handle the problem of | 4927 | * are stored with the acl data to handle the problem of |
| 4922 | * variable length bitmaps.*/ | 4928 | * variable length bitmaps.*/ |
| 4923 | xdr->p = bm_p; | 4929 | xdr->p = bm_p; |
| 4924 | res->acl_data_offset = be32_to_cpup(bm_p) + 2; | ||
| 4925 | res->acl_data_offset <<= 2; | ||
| 4926 | 4930 | ||
| 4927 | /* We ignore &savep and don't do consistency checks on | 4931 | /* We ignore &savep and don't do consistency checks on |
| 4928 | * the attr length. Let userspace figure it out.... */ | 4932 | * the attr length. Let userspace figure it out.... */ |
| 4929 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; | 4933 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; |
| 4930 | attrlen += res->acl_data_offset; | 4934 | attrlen += res->acl_data_offset; |
| 4931 | recvd = req->rq_rcv_buf.len - hdrlen; | 4935 | if (attrlen > page_len) { |
| 4932 | if (attrlen > recvd) { | ||
| 4933 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { | 4936 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { |
| 4934 | /* getxattr interface called with a NULL buf */ | 4937 | /* getxattr interface called with a NULL buf */ |
| 4935 | res->acl_len = attrlen; | 4938 | res->acl_len = attrlen; |
| 4936 | goto out; | 4939 | goto out; |
| 4937 | } | 4940 | } |
| 4938 | dprintk("NFS: acl reply: attrlen %u > recvd %u\n", | 4941 | dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", |
| 4939 | attrlen, recvd); | 4942 | attrlen, page_len); |
| 4940 | return -EINVAL; | 4943 | return -EINVAL; |
| 4941 | } | 4944 | } |
| 4942 | xdr_read_pages(xdr, attrlen); | 4945 | xdr_read_pages(xdr, attrlen); |
| @@ -5089,16 +5092,13 @@ out_err: | |||
| 5089 | return -EINVAL; | 5092 | return -EINVAL; |
| 5090 | } | 5093 | } |
| 5091 | 5094 | ||
| 5092 | static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | 5095 | static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) |
| 5093 | { | 5096 | { |
| 5094 | struct nfs4_secinfo_flavor *sec_flavor; | 5097 | struct nfs4_secinfo_flavor *sec_flavor; |
| 5095 | int status; | 5098 | int status; |
| 5096 | __be32 *p; | 5099 | __be32 *p; |
| 5097 | int i, num_flavors; | 5100 | int i, num_flavors; |
| 5098 | 5101 | ||
| 5099 | status = decode_op_hdr(xdr, OP_SECINFO); | ||
| 5100 | if (status) | ||
| 5101 | goto out; | ||
| 5102 | p = xdr_inline_decode(xdr, 4); | 5102 | p = xdr_inline_decode(xdr, 4); |
| 5103 | if (unlikely(!p)) | 5103 | if (unlikely(!p)) |
| 5104 | goto out_overflow; | 5104 | goto out_overflow; |
| @@ -5124,6 +5124,7 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |||
| 5124 | res->flavors->num_flavors++; | 5124 | res->flavors->num_flavors++; |
| 5125 | } | 5125 | } |
| 5126 | 5126 | ||
| 5127 | status = 0; | ||
| 5127 | out: | 5128 | out: |
| 5128 | return status; | 5129 | return status; |
| 5129 | out_overflow: | 5130 | out_overflow: |
| @@ -5131,7 +5132,23 @@ out_overflow: | |||
| 5131 | return -EIO; | 5132 | return -EIO; |
| 5132 | } | 5133 | } |
| 5133 | 5134 | ||
| 5135 | static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | ||
| 5136 | { | ||
| 5137 | int status = decode_op_hdr(xdr, OP_SECINFO); | ||
| 5138 | if (status) | ||
| 5139 | return status; | ||
| 5140 | return decode_secinfo_common(xdr, res); | ||
| 5141 | } | ||
| 5142 | |||
| 5134 | #if defined(CONFIG_NFS_V4_1) | 5143 | #if defined(CONFIG_NFS_V4_1) |
| 5144 | static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | ||
| 5145 | { | ||
| 5146 | int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME); | ||
| 5147 | if (status) | ||
| 5148 | return status; | ||
| 5149 | return decode_secinfo_common(xdr, res); | ||
| 5150 | } | ||
| 5151 | |||
| 5135 | static int decode_exchange_id(struct xdr_stream *xdr, | 5152 | static int decode_exchange_id(struct xdr_stream *xdr, |
| 5136 | struct nfs41_exchange_id_res *res) | 5153 | struct nfs41_exchange_id_res *res) |
| 5137 | { | 5154 | { |
| @@ -6816,7 +6833,7 @@ static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp, | |||
| 6816 | status = decode_putrootfh(xdr); | 6833 | status = decode_putrootfh(xdr); |
| 6817 | if (status) | 6834 | if (status) |
| 6818 | goto out; | 6835 | goto out; |
| 6819 | status = decode_secinfo(xdr, res); | 6836 | status = decode_secinfo_no_name(xdr, res); |
| 6820 | out: | 6837 | out: |
| 6821 | return status; | 6838 | return status; |
| 6822 | } | 6839 | } |
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index 8d45f1c318ce..595c5fc21a19 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
| @@ -604,7 +604,6 @@ int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay, | |||
| 604 | { | 604 | { |
| 605 | struct objlayout_deviceinfo *odi; | 605 | struct objlayout_deviceinfo *odi; |
| 606 | struct pnfs_device pd; | 606 | struct pnfs_device pd; |
| 607 | struct super_block *sb; | ||
| 608 | struct page *page, **pages; | 607 | struct page *page, **pages; |
| 609 | u32 *p; | 608 | u32 *p; |
| 610 | int err; | 609 | int err; |
| @@ -623,7 +622,6 @@ int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay, | |||
| 623 | pd.pglen = PAGE_SIZE; | 622 | pd.pglen = PAGE_SIZE; |
| 624 | pd.mincount = 0; | 623 | pd.mincount = 0; |
| 625 | 624 | ||
| 626 | sb = pnfslay->plh_inode->i_sb; | ||
| 627 | err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd); | 625 | err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd); |
| 628 | dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err); | 626 | dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err); |
| 629 | if (err) | 627 | if (err) |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index b5d451586943..38512bcd2e98 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -587,7 +587,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
| 587 | 587 | ||
| 588 | /* allocate pages for xdr post processing */ | 588 | /* allocate pages for xdr post processing */ |
| 589 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | 589 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; |
| 590 | max_pages = max_resp_sz >> PAGE_SHIFT; | 590 | max_pages = nfs_page_array_len(0, max_resp_sz); |
| 591 | 591 | ||
| 592 | pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); | 592 | pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); |
| 593 | if (!pages) | 593 | if (!pages) |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 9a0e8ef4a409..0a4be28c2ea3 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
| @@ -322,7 +322,7 @@ out_bad: | |||
| 322 | while (!list_empty(res)) { | 322 | while (!list_empty(res)) { |
| 323 | data = list_entry(res->next, struct nfs_read_data, list); | 323 | data = list_entry(res->next, struct nfs_read_data, list); |
| 324 | list_del(&data->list); | 324 | list_del(&data->list); |
| 325 | nfs_readdata_free(data); | 325 | nfs_readdata_release(data); |
| 326 | } | 326 | } |
| 327 | nfs_readpage_release(req); | 327 | nfs_readpage_release(req); |
| 328 | return -ENOMEM; | 328 | return -ENOMEM; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 37412f706b32..4ac7fca7e4bf 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -2428,7 +2428,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, | |||
| 2428 | dprintk("--> nfs_xdev_mount()\n"); | 2428 | dprintk("--> nfs_xdev_mount()\n"); |
| 2429 | 2429 | ||
| 2430 | /* create a new volume representation */ | 2430 | /* create a new volume representation */ |
| 2431 | server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); | 2431 | server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); |
| 2432 | if (IS_ERR(server)) { | 2432 | if (IS_ERR(server)) { |
| 2433 | error = PTR_ERR(server); | 2433 | error = PTR_ERR(server); |
| 2434 | goto out_err_noserver; | 2434 | goto out_err_noserver; |
| @@ -2767,11 +2767,15 @@ static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type, | |||
| 2767 | char *root_devname; | 2767 | char *root_devname; |
| 2768 | size_t len; | 2768 | size_t len; |
| 2769 | 2769 | ||
| 2770 | len = strlen(hostname) + 3; | 2770 | len = strlen(hostname) + 5; |
| 2771 | root_devname = kmalloc(len, GFP_KERNEL); | 2771 | root_devname = kmalloc(len, GFP_KERNEL); |
| 2772 | if (root_devname == NULL) | 2772 | if (root_devname == NULL) |
| 2773 | return ERR_PTR(-ENOMEM); | 2773 | return ERR_PTR(-ENOMEM); |
| 2774 | snprintf(root_devname, len, "%s:/", hostname); | 2774 | /* Does hostname needs to be enclosed in brackets? */ |
| 2775 | if (strchr(hostname, ':')) | ||
| 2776 | snprintf(root_devname, len, "[%s]:/", hostname); | ||
| 2777 | else | ||
| 2778 | snprintf(root_devname, len, "%s:/", hostname); | ||
| 2775 | root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data); | 2779 | root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data); |
| 2776 | kfree(root_devname); | 2780 | kfree(root_devname); |
| 2777 | return root_mnt; | 2781 | return root_mnt; |
| @@ -2951,7 +2955,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags, | |||
| 2951 | dprintk("--> nfs4_xdev_mount()\n"); | 2955 | dprintk("--> nfs4_xdev_mount()\n"); |
| 2952 | 2956 | ||
| 2953 | /* create a new volume representation */ | 2957 | /* create a new volume representation */ |
| 2954 | server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); | 2958 | server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); |
| 2955 | if (IS_ERR(server)) { | 2959 | if (IS_ERR(server)) { |
| 2956 | error = PTR_ERR(server); | 2960 | error = PTR_ERR(server); |
| 2957 | goto out_err_noserver; | 2961 | goto out_err_noserver; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 2c68818f68ac..c07462320f6b 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -682,7 +682,8 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, | |||
| 682 | req->wb_bytes = rqend - req->wb_offset; | 682 | req->wb_bytes = rqend - req->wb_offset; |
| 683 | out_unlock: | 683 | out_unlock: |
| 684 | spin_unlock(&inode->i_lock); | 684 | spin_unlock(&inode->i_lock); |
| 685 | nfs_clear_request_commit(req); | 685 | if (req) |
| 686 | nfs_clear_request_commit(req); | ||
| 686 | return req; | 687 | return req; |
| 687 | out_flushme: | 688 | out_flushme: |
| 688 | spin_unlock(&inode->i_lock); | 689 | spin_unlock(&inode->i_lock); |
| @@ -1018,7 +1019,7 @@ out_bad: | |||
| 1018 | while (!list_empty(res)) { | 1019 | while (!list_empty(res)) { |
| 1019 | data = list_entry(res->next, struct nfs_write_data, list); | 1020 | data = list_entry(res->next, struct nfs_write_data, list); |
| 1020 | list_del(&data->list); | 1021 | list_del(&data->list); |
| 1021 | nfs_writedata_free(data); | 1022 | nfs_writedata_release(data); |
| 1022 | } | 1023 | } |
| 1023 | nfs_redirty_request(req); | 1024 | nfs_redirty_request(req); |
| 1024 | return -ENOMEM; | 1025 | return -ENOMEM; |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 4767429264a2..ed3f9206a0ee 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
| @@ -577,7 +577,7 @@ cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
| 577 | struct cld_net *cn = nn->cld_net; | 577 | struct cld_net *cn = nn->cld_net; |
| 578 | 578 | ||
| 579 | if (mlen != sizeof(*cmsg)) { | 579 | if (mlen != sizeof(*cmsg)) { |
| 580 | dprintk("%s: got %lu bytes, expected %lu\n", __func__, mlen, | 580 | dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen, |
| 581 | sizeof(*cmsg)); | 581 | sizeof(*cmsg)); |
| 582 | return -EINVAL; | 582 | return -EINVAL; |
| 583 | } | 583 | } |
| @@ -346,6 +346,16 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { | |||
| 346 | .get = generic_pipe_buf_get, | 346 | .get = generic_pipe_buf_get, |
| 347 | }; | 347 | }; |
| 348 | 348 | ||
| 349 | static const struct pipe_buf_operations packet_pipe_buf_ops = { | ||
| 350 | .can_merge = 0, | ||
| 351 | .map = generic_pipe_buf_map, | ||
| 352 | .unmap = generic_pipe_buf_unmap, | ||
| 353 | .confirm = generic_pipe_buf_confirm, | ||
| 354 | .release = anon_pipe_buf_release, | ||
| 355 | .steal = generic_pipe_buf_steal, | ||
| 356 | .get = generic_pipe_buf_get, | ||
| 357 | }; | ||
| 358 | |||
| 349 | static ssize_t | 359 | static ssize_t |
| 350 | pipe_read(struct kiocb *iocb, const struct iovec *_iov, | 360 | pipe_read(struct kiocb *iocb, const struct iovec *_iov, |
| 351 | unsigned long nr_segs, loff_t pos) | 361 | unsigned long nr_segs, loff_t pos) |
| @@ -407,6 +417,13 @@ redo: | |||
| 407 | ret += chars; | 417 | ret += chars; |
| 408 | buf->offset += chars; | 418 | buf->offset += chars; |
| 409 | buf->len -= chars; | 419 | buf->len -= chars; |
| 420 | |||
| 421 | /* Was it a packet buffer? Clean up and exit */ | ||
| 422 | if (buf->flags & PIPE_BUF_FLAG_PACKET) { | ||
| 423 | total_len = chars; | ||
| 424 | buf->len = 0; | ||
| 425 | } | ||
| 426 | |||
| 410 | if (!buf->len) { | 427 | if (!buf->len) { |
| 411 | buf->ops = NULL; | 428 | buf->ops = NULL; |
| 412 | ops->release(pipe, buf); | 429 | ops->release(pipe, buf); |
| @@ -459,6 +476,11 @@ redo: | |||
| 459 | return ret; | 476 | return ret; |
| 460 | } | 477 | } |
| 461 | 478 | ||
| 479 | static inline int is_packetized(struct file *file) | ||
| 480 | { | ||
| 481 | return (file->f_flags & O_DIRECT) != 0; | ||
| 482 | } | ||
| 483 | |||
| 462 | static ssize_t | 484 | static ssize_t |
| 463 | pipe_write(struct kiocb *iocb, const struct iovec *_iov, | 485 | pipe_write(struct kiocb *iocb, const struct iovec *_iov, |
| 464 | unsigned long nr_segs, loff_t ppos) | 486 | unsigned long nr_segs, loff_t ppos) |
| @@ -593,6 +615,11 @@ redo2: | |||
| 593 | buf->ops = &anon_pipe_buf_ops; | 615 | buf->ops = &anon_pipe_buf_ops; |
| 594 | buf->offset = 0; | 616 | buf->offset = 0; |
| 595 | buf->len = chars; | 617 | buf->len = chars; |
| 618 | buf->flags = 0; | ||
| 619 | if (is_packetized(filp)) { | ||
| 620 | buf->ops = &packet_pipe_buf_ops; | ||
| 621 | buf->flags = PIPE_BUF_FLAG_PACKET; | ||
| 622 | } | ||
| 596 | pipe->nrbufs = ++bufs; | 623 | pipe->nrbufs = ++bufs; |
| 597 | pipe->tmp_page = NULL; | 624 | pipe->tmp_page = NULL; |
| 598 | 625 | ||
| @@ -1013,7 +1040,7 @@ struct file *create_write_pipe(int flags) | |||
| 1013 | goto err_dentry; | 1040 | goto err_dentry; |
| 1014 | f->f_mapping = inode->i_mapping; | 1041 | f->f_mapping = inode->i_mapping; |
| 1015 | 1042 | ||
| 1016 | f->f_flags = O_WRONLY | (flags & O_NONBLOCK); | 1043 | f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)); |
| 1017 | f->f_version = 0; | 1044 | f->f_version = 0; |
| 1018 | 1045 | ||
| 1019 | return f; | 1046 | return f; |
| @@ -1057,7 +1084,7 @@ int do_pipe_flags(int *fd, int flags) | |||
| 1057 | int error; | 1084 | int error; |
| 1058 | int fdw, fdr; | 1085 | int fdw, fdr; |
| 1059 | 1086 | ||
| 1060 | if (flags & ~(O_CLOEXEC | O_NONBLOCK)) | 1087 | if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT)) |
| 1061 | return -EINVAL; | 1088 | return -EINVAL; |
| 1062 | 1089 | ||
| 1063 | fw = create_write_pipe(flags); | 1090 | fw = create_write_pipe(flags); |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 2b9a7607cbd5..2d60492d6df8 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -597,9 +597,6 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, | |||
| 597 | if (!page) | 597 | if (!page) |
| 598 | continue; | 598 | continue; |
| 599 | 599 | ||
| 600 | if (PageReserved(page)) | ||
| 601 | continue; | ||
| 602 | |||
| 603 | /* Clear accessed and referenced bits. */ | 600 | /* Clear accessed and referenced bits. */ |
| 604 | ptep_test_and_clear_young(vma, addr, pte); | 601 | ptep_test_and_clear_young(vma, addr, pte); |
| 605 | ClearPageReferenced(page); | 602 | ClearPageReferenced(page); |
