diff options
Diffstat (limited to 'fs')
58 files changed, 768 insertions, 680 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 8ada4c5c5d70..6a82d39dc498 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
@@ -40,7 +40,6 @@ | |||
40 | extern struct file_system_type v9fs_fs_type; | 40 | extern struct file_system_type v9fs_fs_type; |
41 | extern const struct address_space_operations v9fs_addr_operations; | 41 | extern const struct address_space_operations v9fs_addr_operations; |
42 | extern const struct file_operations v9fs_file_operations; | 42 | extern const struct file_operations v9fs_file_operations; |
43 | extern const struct file_operations v9fs_cached_file_operations; | ||
44 | extern const struct file_operations v9fs_dir_operations; | 43 | extern const struct file_operations v9fs_dir_operations; |
45 | extern struct dentry_operations v9fs_dentry_operations; | 44 | extern struct dentry_operations v9fs_dentry_operations; |
46 | extern struct dentry_operations v9fs_cached_dentry_operations; | 45 | extern struct dentry_operations v9fs_cached_dentry_operations; |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 653dfa5b2531..c7b677253843 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -42,6 +42,8 @@ | |||
42 | #include "v9fs_vfs.h" | 42 | #include "v9fs_vfs.h" |
43 | #include "fid.h" | 43 | #include "fid.h" |
44 | 44 | ||
45 | static const struct file_operations v9fs_cached_file_operations; | ||
46 | |||
45 | /** | 47 | /** |
46 | * v9fs_file_open - open a file (or directory) | 48 | * v9fs_file_open - open a file (or directory) |
47 | * @inode: inode to be opened | 49 | * @inode: inode to be opened |
@@ -245,7 +247,7 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
245 | return total; | 247 | return total; |
246 | } | 248 | } |
247 | 249 | ||
248 | const struct file_operations v9fs_cached_file_operations = { | 250 | static const struct file_operations v9fs_cached_file_operations = { |
249 | .llseek = generic_file_llseek, | 251 | .llseek = generic_file_llseek, |
250 | .read = do_sync_read, | 252 | .read = do_sync_read, |
251 | .aio_read = generic_file_aio_read, | 253 | .aio_read = generic_file_aio_read, |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 124a085d1f2e..b01b0a457932 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -415,7 +415,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
415 | file_inode = file->d_inode; | 415 | file_inode = file->d_inode; |
416 | sb = file_inode->i_sb; | 416 | sb = file_inode->i_sb; |
417 | v9ses = v9fs_inode2v9ses(file_inode); | 417 | v9ses = v9fs_inode2v9ses(file_inode); |
418 | v9fid = v9fs_fid_lookup(file); | 418 | v9fid = v9fs_fid_clone(file); |
419 | if(IS_ERR(v9fid)) | 419 | if(IS_ERR(v9fid)) |
420 | return PTR_ERR(v9fid); | 420 | return PTR_ERR(v9fid); |
421 | 421 | ||
@@ -136,7 +136,6 @@ static int aio_setup_ring(struct kioctx *ctx) | |||
136 | 0); | 136 | 0); |
137 | if (IS_ERR((void *)info->mmap_base)) { | 137 | if (IS_ERR((void *)info->mmap_base)) { |
138 | up_write(&ctx->mm->mmap_sem); | 138 | up_write(&ctx->mm->mmap_sem); |
139 | printk("mmap err: %ld\n", -info->mmap_base); | ||
140 | info->mmap_size = 0; | 139 | info->mmap_size = 0; |
141 | aio_free_ring(ctx); | 140 | aio_free_ring(ctx); |
142 | return -EAGAIN; | 141 | return -EAGAIN; |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index b4631046867e..d0e9b3a3905d 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -470,9 +470,6 @@ void autofs4_dentry_release(struct dentry *de) | |||
470 | if (inf) { | 470 | if (inf) { |
471 | struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); | 471 | struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); |
472 | 472 | ||
473 | inf->dentry = NULL; | ||
474 | inf->inode = NULL; | ||
475 | |||
476 | if (sbi) { | 473 | if (sbi) { |
477 | spin_lock(&sbi->rehash_lock); | 474 | spin_lock(&sbi->rehash_lock); |
478 | if (!list_empty(&inf->rehash)) | 475 | if (!list_empty(&inf->rehash)) |
@@ -480,6 +477,9 @@ void autofs4_dentry_release(struct dentry *de) | |||
480 | spin_unlock(&sbi->rehash_lock); | 477 | spin_unlock(&sbi->rehash_lock); |
481 | } | 478 | } |
482 | 479 | ||
480 | inf->dentry = NULL; | ||
481 | inf->inode = NULL; | ||
482 | |||
483 | autofs4_free_ino(inf); | 483 | autofs4_free_ino(inf); |
484 | } | 484 | } |
485 | } | 485 | } |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 51db1182b27e..9cc4f0a8aaae 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -507,7 +507,7 @@ out: | |||
507 | #define INTERPRETER_ELF 2 | 507 | #define INTERPRETER_ELF 2 |
508 | 508 | ||
509 | #ifndef STACK_RND_MASK | 509 | #ifndef STACK_RND_MASK |
510 | #define STACK_RND_MASK 0x7ff /* with 4K pages 8MB of VA */ | 510 | #define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12)) /* 8MB of VA */ |
511 | #endif | 511 | #endif |
512 | 512 | ||
513 | static unsigned long randomize_stack_top(unsigned long stack_top) | 513 | static unsigned long randomize_stack_top(unsigned long stack_top) |
@@ -1704,7 +1704,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
1704 | DUMP_SEEK(PAGE_SIZE); | 1704 | DUMP_SEEK(PAGE_SIZE); |
1705 | } else { | 1705 | } else { |
1706 | if (page == ZERO_PAGE(addr)) { | 1706 | if (page == ZERO_PAGE(addr)) { |
1707 | DUMP_SEEK(PAGE_SIZE); | 1707 | if (!dump_seek(file, PAGE_SIZE)) { |
1708 | page_cache_release(page); | ||
1709 | goto end_coredump; | ||
1710 | } | ||
1708 | } else { | 1711 | } else { |
1709 | void *kaddr; | 1712 | void *kaddr; |
1710 | flush_cache_page(vma, addr, | 1713 | flush_cache_page(vma, addr, |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 5810aa1339fd..f3ddca4a387b 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -179,6 +179,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
179 | int executable_stack; | 179 | int executable_stack; |
180 | int retval, i; | 180 | int retval, i; |
181 | 181 | ||
182 | kdebug("____ LOAD %d ____", current->pid); | ||
183 | |||
182 | memset(&exec_params, 0, sizeof(exec_params)); | 184 | memset(&exec_params, 0, sizeof(exec_params)); |
183 | memset(&interp_params, 0, sizeof(interp_params)); | 185 | memset(&interp_params, 0, sizeof(interp_params)); |
184 | 186 | ||
@@ -941,8 +943,11 @@ static int elf_fdpic_map_file_constdisp_on_uclinux( | |||
941 | 943 | ||
942 | if (mm) { | 944 | if (mm) { |
943 | if (phdr->p_flags & PF_X) { | 945 | if (phdr->p_flags & PF_X) { |
944 | mm->start_code = seg->addr; | 946 | if (!mm->start_code) { |
945 | mm->end_code = seg->addr + phdr->p_memsz; | 947 | mm->start_code = seg->addr; |
948 | mm->end_code = seg->addr + | ||
949 | phdr->p_memsz; | ||
950 | } | ||
946 | } else if (!mm->start_data) { | 951 | } else if (!mm->start_data) { |
947 | mm->start_data = seg->addr; | 952 | mm->start_data = seg->addr; |
948 | #ifndef CONFIG_MMU | 953 | #ifndef CONFIG_MMU |
@@ -1123,8 +1128,10 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, | |||
1123 | 1128 | ||
1124 | if (mm) { | 1129 | if (mm) { |
1125 | if (phdr->p_flags & PF_X) { | 1130 | if (phdr->p_flags & PF_X) { |
1126 | mm->start_code = maddr; | 1131 | if (!mm->start_code) { |
1127 | mm->end_code = maddr + phdr->p_memsz; | 1132 | mm->start_code = maddr; |
1133 | mm->end_code = maddr + phdr->p_memsz; | ||
1134 | } | ||
1128 | } else if (!mm->start_data) { | 1135 | } else if (!mm->start_data) { |
1129 | mm->start_data = maddr; | 1136 | mm->start_data = maddr; |
1130 | mm->end_data = maddr + phdr->p_memsz; | 1137 | mm->end_data = maddr + phdr->p_memsz; |
@@ -1473,8 +1480,8 @@ static int elf_fdpic_dump_segments(struct file *file, struct mm_struct *mm, | |||
1473 | DUMP_SEEK(file->f_pos + PAGE_SIZE); | 1480 | DUMP_SEEK(file->f_pos + PAGE_SIZE); |
1474 | } | 1481 | } |
1475 | else if (page == ZERO_PAGE(addr)) { | 1482 | else if (page == ZERO_PAGE(addr)) { |
1476 | DUMP_SEEK(file->f_pos + PAGE_SIZE); | ||
1477 | page_cache_release(page); | 1483 | page_cache_release(page); |
1484 | DUMP_SEEK(file->f_pos + PAGE_SIZE); | ||
1478 | } | 1485 | } |
1479 | else { | 1486 | else { |
1480 | void *kaddr; | 1487 | void *kaddr; |
diff --git a/fs/char_dev.c b/fs/char_dev.c index 78ced721554d..164a45cdaf5f 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -109,8 +109,6 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, | |||
109 | /* temporary */ | 109 | /* temporary */ |
110 | if (major == 0) { | 110 | if (major == 0) { |
111 | for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { | 111 | for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { |
112 | if (is_lanana_major(i)) | ||
113 | continue; | ||
114 | if (chrdevs[i] == NULL) | 112 | if (chrdevs[i] == NULL) |
115 | break; | 113 | break; |
116 | } | 114 | } |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 6247628bdaed..5d1f4873d701 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -4,6 +4,12 @@ Fix mtime bouncing around from local idea of last write times to remote time. | |||
4 | Fix hang (in i_size_read) when simultaneous size update of same remote file | 4 | Fix hang (in i_size_read) when simultaneous size update of same remote file |
5 | on smp system corrupts sequence number. Do not reread unnecessarily partial page | 5 | on smp system corrupts sequence number. Do not reread unnecessarily partial page |
6 | (which we are about to overwrite anyway) when writing out file opened rw. | 6 | (which we are about to overwrite anyway) when writing out file opened rw. |
7 | When DOS attribute of file on non-Unix server's file changes on the server side | ||
8 | from read-only back to read-write, reflect this change in default file mode | ||
9 | (we had been leaving a file's mode read-only until the inode were reloaded). | ||
10 | Allow setting of attribute back to ATTR_NORMAL (removing readonly dos attribute | ||
11 | when archive dos attribute not set and we are changing mode back to writeable | ||
12 | on server which does not support the Unix Extensions). | ||
7 | 13 | ||
8 | Version 1.47 | 14 | Version 1.47 |
9 | ------------ | 15 | ------------ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 0efdf35aab2c..4d8948e8762c 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -220,7 +220,7 @@ | |||
220 | */ | 220 | */ |
221 | #define CIFS_NO_HANDLE 0xFFFF | 221 | #define CIFS_NO_HANDLE 0xFFFF |
222 | 222 | ||
223 | #define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL | 223 | #define NO_CHANGE_64 cpu_to_le64(0xFFFFFFFFFFFFFFFFULL) |
224 | #define NO_CHANGE_32 0xFFFFFFFFUL | 224 | #define NO_CHANGE_32 0xFFFFFFFFUL |
225 | 225 | ||
226 | /* IPC$ in ASCII */ | 226 | /* IPC$ in ASCII */ |
@@ -1887,7 +1887,13 @@ typedef struct { | |||
1887 | calls including posix open | 1887 | calls including posix open |
1888 | and posix unlink */ | 1888 | and posix unlink */ |
1889 | #ifdef CONFIG_CIFS_POSIX | 1889 | #ifdef CONFIG_CIFS_POSIX |
1890 | #define CIFS_UNIX_CAP_MASK 0x0000003b | 1890 | /* Can not set pathnames cap yet until we send new posix create SMB since |
1891 | otherwise server can treat such handles opened with older ntcreatex | ||
1892 | (by a new client which knows how to send posix path ops) | ||
1893 | as non-posix handles (can affect write behavior with byte range locks. | ||
1894 | We can add back in POSIX_PATH_OPS cap when Posix Create/Mkdir finished */ | ||
1895 | /* #define CIFS_UNIX_CAP_MASK 0x0000003b */ | ||
1896 | #define CIFS_UNIX_CAP_MASK 0x0000001b | ||
1891 | #else | 1897 | #else |
1892 | #define CIFS_UNIX_CAP_MASK 0x00000013 | 1898 | #define CIFS_UNIX_CAP_MASK 0x00000013 |
1893 | #endif /* CONFIG_CIFS_POSIX */ | 1899 | #endif /* CONFIG_CIFS_POSIX */ |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 86b9dbbd8441..f414526e476a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -494,6 +494,12 @@ int cifs_get_inode_info(struct inode **pinode, | |||
494 | mode e.g. 555 */ | 494 | mode e.g. 555 */ |
495 | if (cifsInfo->cifsAttrs & ATTR_READONLY) | 495 | if (cifsInfo->cifsAttrs & ATTR_READONLY) |
496 | inode->i_mode &= ~(S_IWUGO); | 496 | inode->i_mode &= ~(S_IWUGO); |
497 | else if ((inode->i_mode & S_IWUGO) == 0) | ||
498 | /* the ATTR_READONLY flag may have been */ | ||
499 | /* changed on server -- set any w bits */ | ||
500 | /* allowed by mnt_file_mode */ | ||
501 | inode->i_mode |= (S_IWUGO & | ||
502 | cifs_sb->mnt_file_mode); | ||
497 | /* BB add code here - | 503 | /* BB add code here - |
498 | validate if device or weird share or device type? */ | 504 | validate if device or weird share or device type? */ |
499 | } | 505 | } |
@@ -1190,6 +1196,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1190 | struct cifsFileInfo *open_file = NULL; | 1196 | struct cifsFileInfo *open_file = NULL; |
1191 | FILE_BASIC_INFO time_buf; | 1197 | FILE_BASIC_INFO time_buf; |
1192 | int set_time = FALSE; | 1198 | int set_time = FALSE; |
1199 | int set_dosattr = FALSE; | ||
1193 | __u64 mode = 0xFFFFFFFFFFFFFFFFULL; | 1200 | __u64 mode = 0xFFFFFFFFFFFFFFFFULL; |
1194 | __u64 uid = 0xFFFFFFFFFFFFFFFFULL; | 1201 | __u64 uid = 0xFFFFFFFFFFFFFFFFULL; |
1195 | __u64 gid = 0xFFFFFFFFFFFFFFFFULL; | 1202 | __u64 gid = 0xFFFFFFFFFFFFFFFFULL; |
@@ -1326,15 +1333,23 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1326 | else if (attrs->ia_valid & ATTR_MODE) { | 1333 | else if (attrs->ia_valid & ATTR_MODE) { |
1327 | rc = 0; | 1334 | rc = 0; |
1328 | if ((mode & S_IWUGO) == 0) /* not writeable */ { | 1335 | if ((mode & S_IWUGO) == 0) /* not writeable */ { |
1329 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) | 1336 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
1337 | set_dosattr = TRUE; | ||
1330 | time_buf.Attributes = | 1338 | time_buf.Attributes = |
1331 | cpu_to_le32(cifsInode->cifsAttrs | | 1339 | cpu_to_le32(cifsInode->cifsAttrs | |
1332 | ATTR_READONLY); | 1340 | ATTR_READONLY); |
1341 | } | ||
1333 | } else if ((mode & S_IWUGO) == S_IWUGO) { | 1342 | } else if ((mode & S_IWUGO) == S_IWUGO) { |
1334 | if (cifsInode->cifsAttrs & ATTR_READONLY) | 1343 | if (cifsInode->cifsAttrs & ATTR_READONLY) { |
1344 | set_dosattr = TRUE; | ||
1335 | time_buf.Attributes = | 1345 | time_buf.Attributes = |
1336 | cpu_to_le32(cifsInode->cifsAttrs & | 1346 | cpu_to_le32(cifsInode->cifsAttrs & |
1337 | (~ATTR_READONLY)); | 1347 | (~ATTR_READONLY)); |
1348 | /* Windows ignores set to zero */ | ||
1349 | if(time_buf.Attributes == 0) | ||
1350 | time_buf.Attributes |= | ||
1351 | cpu_to_le32(ATTR_NORMAL); | ||
1352 | } | ||
1338 | } | 1353 | } |
1339 | /* BB to be implemented - | 1354 | /* BB to be implemented - |
1340 | via Windows security descriptors or streams */ | 1355 | via Windows security descriptors or streams */ |
@@ -1372,7 +1387,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1372 | } else | 1387 | } else |
1373 | time_buf.ChangeTime = 0; | 1388 | time_buf.ChangeTime = 0; |
1374 | 1389 | ||
1375 | if (set_time || time_buf.Attributes) { | 1390 | if (set_time || set_dosattr) { |
1376 | time_buf.CreationTime = 0; /* do not change */ | 1391 | time_buf.CreationTime = 0; /* do not change */ |
1377 | /* In the future we should experiment - try setting timestamps | 1392 | /* In the future we should experiment - try setting timestamps |
1378 | via Handle (SetFileInfo) instead of by path */ | 1393 | via Handle (SetFileInfo) instead of by path */ |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 44cfb528797d..2a374d5215ab 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -219,6 +219,10 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
219 | tmp_inode->i_mode |= S_IFREG; | 219 | tmp_inode->i_mode |= S_IFREG; |
220 | if (attr & ATTR_READONLY) | 220 | if (attr & ATTR_READONLY) |
221 | tmp_inode->i_mode &= ~(S_IWUGO); | 221 | tmp_inode->i_mode &= ~(S_IWUGO); |
222 | else if ((tmp_inode->i_mode & S_IWUGO) == 0) | ||
223 | /* the ATTR_READONLY flag may have been changed on */ | ||
224 | /* server -- set any w bits allowed by mnt_file_mode */ | ||
225 | tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); | ||
222 | } /* could add code here - to validate if device or weird share type? */ | 226 | } /* could add code here - to validate if device or weird share type? */ |
223 | 227 | ||
224 | /* can not fill in nlink here as in qpathinfo version and Unx search */ | 228 | /* can not fill in nlink here as in qpathinfo version and Unx search */ |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c81c958b3e1d..8b1c5d8bf4ef 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -2553,11 +2553,15 @@ HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) | |||
2553 | HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl) | 2553 | HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl) |
2554 | /* wireless */ | 2554 | /* wireless */ |
2555 | HANDLE_IOCTL(SIOCGIWRANGE, do_wireless_ioctl) | 2555 | HANDLE_IOCTL(SIOCGIWRANGE, do_wireless_ioctl) |
2556 | HANDLE_IOCTL(SIOCGIWPRIV, do_wireless_ioctl) | ||
2557 | HANDLE_IOCTL(SIOCGIWSTATS, do_wireless_ioctl) | ||
2556 | HANDLE_IOCTL(SIOCSIWSPY, do_wireless_ioctl) | 2558 | HANDLE_IOCTL(SIOCSIWSPY, do_wireless_ioctl) |
2557 | HANDLE_IOCTL(SIOCGIWSPY, do_wireless_ioctl) | 2559 | HANDLE_IOCTL(SIOCGIWSPY, do_wireless_ioctl) |
2558 | HANDLE_IOCTL(SIOCSIWTHRSPY, do_wireless_ioctl) | 2560 | HANDLE_IOCTL(SIOCSIWTHRSPY, do_wireless_ioctl) |
2559 | HANDLE_IOCTL(SIOCGIWTHRSPY, do_wireless_ioctl) | 2561 | HANDLE_IOCTL(SIOCGIWTHRSPY, do_wireless_ioctl) |
2562 | HANDLE_IOCTL(SIOCSIWMLME, do_wireless_ioctl) | ||
2560 | HANDLE_IOCTL(SIOCGIWAPLIST, do_wireless_ioctl) | 2563 | HANDLE_IOCTL(SIOCGIWAPLIST, do_wireless_ioctl) |
2564 | HANDLE_IOCTL(SIOCSIWSCAN, do_wireless_ioctl) | ||
2561 | HANDLE_IOCTL(SIOCGIWSCAN, do_wireless_ioctl) | 2565 | HANDLE_IOCTL(SIOCGIWSCAN, do_wireless_ioctl) |
2562 | HANDLE_IOCTL(SIOCSIWESSID, do_wireless_ioctl) | 2566 | HANDLE_IOCTL(SIOCSIWESSID, do_wireless_ioctl) |
2563 | HANDLE_IOCTL(SIOCGIWESSID, do_wireless_ioctl) | 2567 | HANDLE_IOCTL(SIOCGIWESSID, do_wireless_ioctl) |
@@ -2565,6 +2569,11 @@ HANDLE_IOCTL(SIOCSIWNICKN, do_wireless_ioctl) | |||
2565 | HANDLE_IOCTL(SIOCGIWNICKN, do_wireless_ioctl) | 2569 | HANDLE_IOCTL(SIOCGIWNICKN, do_wireless_ioctl) |
2566 | HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ioctl) | 2570 | HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ioctl) |
2567 | HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl) | 2571 | HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl) |
2572 | HANDLE_IOCTL(SIOCSIWGENIE, do_wireless_ioctl) | ||
2573 | HANDLE_IOCTL(SIOCGIWGENIE, do_wireless_ioctl) | ||
2574 | HANDLE_IOCTL(SIOCSIWENCODEEXT, do_wireless_ioctl) | ||
2575 | HANDLE_IOCTL(SIOCGIWENCODEEXT, do_wireless_ioctl) | ||
2576 | HANDLE_IOCTL(SIOCSIWPMKSA, do_wireless_ioctl) | ||
2568 | HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) | 2577 | HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) |
2569 | HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl) | 2578 | HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl) |
2570 | HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl) | 2579 | HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl) |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 34750d5e4ff2..5e6e37e58f36 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -1141,25 +1141,22 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) | |||
1141 | 1141 | ||
1142 | err = -ENOMEM; | 1142 | err = -ENOMEM; |
1143 | dentry = d_alloc(configfs_sb->s_root, &name); | 1143 | dentry = d_alloc(configfs_sb->s_root, &name); |
1144 | if (!dentry) | 1144 | if (dentry) { |
1145 | goto out_release; | 1145 | d_add(dentry, NULL); |
1146 | |||
1147 | d_add(dentry, NULL); | ||
1148 | 1146 | ||
1149 | err = configfs_attach_group(sd->s_element, &group->cg_item, | 1147 | err = configfs_attach_group(sd->s_element, &group->cg_item, |
1150 | dentry); | 1148 | dentry); |
1151 | if (!err) | 1149 | if (err) { |
1152 | dentry = NULL; | 1150 | d_delete(dentry); |
1153 | else | 1151 | dput(dentry); |
1154 | d_delete(dentry); | 1152 | } |
1153 | } | ||
1155 | 1154 | ||
1156 | mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex); | 1155 | mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex); |
1157 | 1156 | ||
1158 | if (dentry) { | 1157 | if (err) { |
1159 | dput(dentry); | 1158 | unlink_group(group); |
1160 | out_release: | 1159 | configfs_release_fs(); |
1161 | unlink_group(group); | ||
1162 | configfs_release_fs(); | ||
1163 | } | 1160 | } |
1164 | 1161 | ||
1165 | return err; | 1162 | return err; |
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index 329efcd3d8c9..cb20b964419f 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c | |||
@@ -78,18 +78,13 @@ struct kmem_cache *ecryptfs_dentry_info_cache; | |||
78 | */ | 78 | */ |
79 | static void ecryptfs_d_release(struct dentry *dentry) | 79 | static void ecryptfs_d_release(struct dentry *dentry) |
80 | { | 80 | { |
81 | struct dentry *lower_dentry; | 81 | if (ecryptfs_dentry_to_private(dentry)) { |
82 | 82 | if (ecryptfs_dentry_to_lower(dentry)) { | |
83 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 83 | mntput(ecryptfs_dentry_to_lower_mnt(dentry)); |
84 | if (ecryptfs_dentry_to_private(dentry)) | 84 | dput(ecryptfs_dentry_to_lower(dentry)); |
85 | } | ||
85 | kmem_cache_free(ecryptfs_dentry_info_cache, | 86 | kmem_cache_free(ecryptfs_dentry_info_cache, |
86 | ecryptfs_dentry_to_private(dentry)); | 87 | ecryptfs_dentry_to_private(dentry)); |
87 | if (lower_dentry) { | ||
88 | struct vfsmount *lower_mnt = | ||
89 | ecryptfs_dentry_to_lower_mnt(dentry); | ||
90 | |||
91 | mntput(lower_mnt); | ||
92 | dput(lower_dentry); | ||
93 | } | 88 | } |
94 | return; | 89 | return; |
95 | } | 90 | } |
@@ -1244,13 +1244,17 @@ EXPORT_SYMBOL(set_binfmt); | |||
1244 | * name into corename, which must have space for at least | 1244 | * name into corename, which must have space for at least |
1245 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. | 1245 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. |
1246 | */ | 1246 | */ |
1247 | static void format_corename(char *corename, const char *pattern, long signr) | 1247 | static int format_corename(char *corename, const char *pattern, long signr) |
1248 | { | 1248 | { |
1249 | const char *pat_ptr = pattern; | 1249 | const char *pat_ptr = pattern; |
1250 | char *out_ptr = corename; | 1250 | char *out_ptr = corename; |
1251 | char *const out_end = corename + CORENAME_MAX_SIZE; | 1251 | char *const out_end = corename + CORENAME_MAX_SIZE; |
1252 | int rc; | 1252 | int rc; |
1253 | int pid_in_pattern = 0; | 1253 | int pid_in_pattern = 0; |
1254 | int ispipe = 0; | ||
1255 | |||
1256 | if (*pattern == '|') | ||
1257 | ispipe = 1; | ||
1254 | 1258 | ||
1255 | /* Repeat as long as we have more pattern to process and more output | 1259 | /* Repeat as long as we have more pattern to process and more output |
1256 | space */ | 1260 | space */ |
@@ -1341,8 +1345,8 @@ static void format_corename(char *corename, const char *pattern, long signr) | |||
1341 | * | 1345 | * |
1342 | * If core_pattern does not include a %p (as is the default) | 1346 | * If core_pattern does not include a %p (as is the default) |
1343 | * and core_uses_pid is set, then .%pid will be appended to | 1347 | * and core_uses_pid is set, then .%pid will be appended to |
1344 | * the filename */ | 1348 | * the filename. Do not do this for piped commands. */ |
1345 | if (!pid_in_pattern | 1349 | if (!ispipe && !pid_in_pattern |
1346 | && (core_uses_pid || atomic_read(¤t->mm->mm_users) != 1)) { | 1350 | && (core_uses_pid || atomic_read(¤t->mm->mm_users) != 1)) { |
1347 | rc = snprintf(out_ptr, out_end - out_ptr, | 1351 | rc = snprintf(out_ptr, out_end - out_ptr, |
1348 | ".%d", current->tgid); | 1352 | ".%d", current->tgid); |
@@ -1350,8 +1354,9 @@ static void format_corename(char *corename, const char *pattern, long signr) | |||
1350 | goto out; | 1354 | goto out; |
1351 | out_ptr += rc; | 1355 | out_ptr += rc; |
1352 | } | 1356 | } |
1353 | out: | 1357 | out: |
1354 | *out_ptr = 0; | 1358 | *out_ptr = 0; |
1359 | return ispipe; | ||
1355 | } | 1360 | } |
1356 | 1361 | ||
1357 | static void zap_process(struct task_struct *start) | 1362 | static void zap_process(struct task_struct *start) |
@@ -1502,16 +1507,15 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1502 | * uses lock_kernel() | 1507 | * uses lock_kernel() |
1503 | */ | 1508 | */ |
1504 | lock_kernel(); | 1509 | lock_kernel(); |
1505 | format_corename(corename, core_pattern, signr); | 1510 | ispipe = format_corename(corename, core_pattern, signr); |
1506 | unlock_kernel(); | 1511 | unlock_kernel(); |
1507 | if (corename[0] == '|') { | 1512 | if (ispipe) { |
1508 | /* SIGPIPE can happen, but it's just never processed */ | 1513 | /* SIGPIPE can happen, but it's just never processed */ |
1509 | if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) { | 1514 | if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) { |
1510 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1515 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
1511 | corename); | 1516 | corename); |
1512 | goto fail_unlock; | 1517 | goto fail_unlock; |
1513 | } | 1518 | } |
1514 | ispipe = 1; | ||
1515 | } else | 1519 | } else |
1516 | file = filp_open(corename, | 1520 | file = filp_open(corename, |
1517 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, | 1521 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 8a824f4ce5c6..a5b150f7e8a2 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -1148,102 +1148,37 @@ static int do_journal_get_write_access(handle_t *handle, | |||
1148 | return ext3_journal_get_write_access(handle, bh); | 1148 | return ext3_journal_get_write_access(handle, bh); |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | /* | ||
1152 | * The idea of this helper function is following: | ||
1153 | * if prepare_write has allocated some blocks, but not all of them, the | ||
1154 | * transaction must include the content of the newly allocated blocks. | ||
1155 | * This content is expected to be set to zeroes by block_prepare_write(). | ||
1156 | * 2006/10/14 SAW | ||
1157 | */ | ||
1158 | static int ext3_prepare_failure(struct file *file, struct page *page, | ||
1159 | unsigned from, unsigned to) | ||
1160 | { | ||
1161 | struct address_space *mapping; | ||
1162 | struct buffer_head *bh, *head, *next; | ||
1163 | unsigned block_start, block_end; | ||
1164 | unsigned blocksize; | ||
1165 | int ret; | ||
1166 | handle_t *handle = ext3_journal_current_handle(); | ||
1167 | |||
1168 | mapping = page->mapping; | ||
1169 | if (ext3_should_writeback_data(mapping->host)) { | ||
1170 | /* optimization: no constraints about data */ | ||
1171 | skip: | ||
1172 | return ext3_journal_stop(handle); | ||
1173 | } | ||
1174 | |||
1175 | head = page_buffers(page); | ||
1176 | blocksize = head->b_size; | ||
1177 | for ( bh = head, block_start = 0; | ||
1178 | bh != head || !block_start; | ||
1179 | block_start = block_end, bh = next) | ||
1180 | { | ||
1181 | next = bh->b_this_page; | ||
1182 | block_end = block_start + blocksize; | ||
1183 | if (block_end <= from) | ||
1184 | continue; | ||
1185 | if (block_start >= to) { | ||
1186 | block_start = to; | ||
1187 | break; | ||
1188 | } | ||
1189 | if (!buffer_mapped(bh)) | ||
1190 | /* prepare_write failed on this bh */ | ||
1191 | break; | ||
1192 | if (ext3_should_journal_data(mapping->host)) { | ||
1193 | ret = do_journal_get_write_access(handle, bh); | ||
1194 | if (ret) { | ||
1195 | ext3_journal_stop(handle); | ||
1196 | return ret; | ||
1197 | } | ||
1198 | } | ||
1199 | /* | ||
1200 | * block_start here becomes the first block where the current iteration | ||
1201 | * of prepare_write failed. | ||
1202 | */ | ||
1203 | } | ||
1204 | if (block_start <= from) | ||
1205 | goto skip; | ||
1206 | |||
1207 | /* commit allocated and zeroed buffers */ | ||
1208 | return mapping->a_ops->commit_write(file, page, from, block_start); | ||
1209 | } | ||
1210 | |||
1211 | static int ext3_prepare_write(struct file *file, struct page *page, | 1151 | static int ext3_prepare_write(struct file *file, struct page *page, |
1212 | unsigned from, unsigned to) | 1152 | unsigned from, unsigned to) |
1213 | { | 1153 | { |
1214 | struct inode *inode = page->mapping->host; | 1154 | struct inode *inode = page->mapping->host; |
1215 | int ret, ret2; | 1155 | int ret, needed_blocks = ext3_writepage_trans_blocks(inode); |
1216 | int needed_blocks = ext3_writepage_trans_blocks(inode); | ||
1217 | handle_t *handle; | 1156 | handle_t *handle; |
1218 | int retries = 0; | 1157 | int retries = 0; |
1219 | 1158 | ||
1220 | retry: | 1159 | retry: |
1221 | handle = ext3_journal_start(inode, needed_blocks); | 1160 | handle = ext3_journal_start(inode, needed_blocks); |
1222 | if (IS_ERR(handle)) | 1161 | if (IS_ERR(handle)) { |
1223 | return PTR_ERR(handle); | 1162 | ret = PTR_ERR(handle); |
1163 | goto out; | ||
1164 | } | ||
1224 | if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) | 1165 | if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) |
1225 | ret = nobh_prepare_write(page, from, to, ext3_get_block); | 1166 | ret = nobh_prepare_write(page, from, to, ext3_get_block); |
1226 | else | 1167 | else |
1227 | ret = block_prepare_write(page, from, to, ext3_get_block); | 1168 | ret = block_prepare_write(page, from, to, ext3_get_block); |
1228 | if (ret) | 1169 | if (ret) |
1229 | goto failure; | 1170 | goto prepare_write_failed; |
1230 | 1171 | ||
1231 | if (ext3_should_journal_data(inode)) { | 1172 | if (ext3_should_journal_data(inode)) { |
1232 | ret = walk_page_buffers(handle, page_buffers(page), | 1173 | ret = walk_page_buffers(handle, page_buffers(page), |
1233 | from, to, NULL, do_journal_get_write_access); | 1174 | from, to, NULL, do_journal_get_write_access); |
1234 | if (ret) | ||
1235 | /* fatal error, just put the handle and return */ | ||
1236 | journal_stop(handle); | ||
1237 | } | 1175 | } |
1238 | return ret; | 1176 | prepare_write_failed: |
1239 | 1177 | if (ret) | |
1240 | failure: | 1178 | ext3_journal_stop(handle); |
1241 | ret2 = ext3_prepare_failure(file, page, from, to); | ||
1242 | if (ret2 < 0) | ||
1243 | return ret2; | ||
1244 | if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) | 1179 | if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) |
1245 | goto retry; | 1180 | goto retry; |
1246 | /* retry number exceeded, or other error like -EDQUOT */ | 1181 | out: |
1247 | return ret; | 1182 | return ret; |
1248 | } | 1183 | } |
1249 | 1184 | ||
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 12f7dda1232c..f58cbb26323e 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c | |||
@@ -495,7 +495,8 @@ ext3_xattr_release_block(handle_t *handle, struct inode *inode, | |||
495 | BHDR(bh)->h_refcount = cpu_to_le32( | 495 | BHDR(bh)->h_refcount = cpu_to_le32( |
496 | le32_to_cpu(BHDR(bh)->h_refcount) - 1); | 496 | le32_to_cpu(BHDR(bh)->h_refcount) - 1); |
497 | error = ext3_journal_dirty_metadata(handle, bh); | 497 | error = ext3_journal_dirty_metadata(handle, bh); |
498 | handle->h_sync = 1; | 498 | if (IS_SYNC(inode)) |
499 | handle->h_sync = 1; | ||
499 | DQUOT_FREE_BLOCK(inode, 1); | 500 | DQUOT_FREE_BLOCK(inode, 1); |
500 | ea_bdebug(bh, "refcount now=%d; releasing", | 501 | ea_bdebug(bh, "refcount now=%d; releasing", |
501 | le32_to_cpu(BHDR(bh)->h_refcount)); | 502 | le32_to_cpu(BHDR(bh)->h_refcount)); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fbff4b9e122a..810b6d6474bf 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1147,102 +1147,37 @@ static int do_journal_get_write_access(handle_t *handle, | |||
1147 | return ext4_journal_get_write_access(handle, bh); | 1147 | return ext4_journal_get_write_access(handle, bh); |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | /* | ||
1151 | * The idea of this helper function is following: | ||
1152 | * if prepare_write has allocated some blocks, but not all of them, the | ||
1153 | * transaction must include the content of the newly allocated blocks. | ||
1154 | * This content is expected to be set to zeroes by block_prepare_write(). | ||
1155 | * 2006/10/14 SAW | ||
1156 | */ | ||
1157 | static int ext4_prepare_failure(struct file *file, struct page *page, | ||
1158 | unsigned from, unsigned to) | ||
1159 | { | ||
1160 | struct address_space *mapping; | ||
1161 | struct buffer_head *bh, *head, *next; | ||
1162 | unsigned block_start, block_end; | ||
1163 | unsigned blocksize; | ||
1164 | int ret; | ||
1165 | handle_t *handle = ext4_journal_current_handle(); | ||
1166 | |||
1167 | mapping = page->mapping; | ||
1168 | if (ext4_should_writeback_data(mapping->host)) { | ||
1169 | /* optimization: no constraints about data */ | ||
1170 | skip: | ||
1171 | return ext4_journal_stop(handle); | ||
1172 | } | ||
1173 | |||
1174 | head = page_buffers(page); | ||
1175 | blocksize = head->b_size; | ||
1176 | for ( bh = head, block_start = 0; | ||
1177 | bh != head || !block_start; | ||
1178 | block_start = block_end, bh = next) | ||
1179 | { | ||
1180 | next = bh->b_this_page; | ||
1181 | block_end = block_start + blocksize; | ||
1182 | if (block_end <= from) | ||
1183 | continue; | ||
1184 | if (block_start >= to) { | ||
1185 | block_start = to; | ||
1186 | break; | ||
1187 | } | ||
1188 | if (!buffer_mapped(bh)) | ||
1189 | /* prepare_write failed on this bh */ | ||
1190 | break; | ||
1191 | if (ext4_should_journal_data(mapping->host)) { | ||
1192 | ret = do_journal_get_write_access(handle, bh); | ||
1193 | if (ret) { | ||
1194 | ext4_journal_stop(handle); | ||
1195 | return ret; | ||
1196 | } | ||
1197 | } | ||
1198 | /* | ||
1199 | * block_start here becomes the first block where the current iteration | ||
1200 | * of prepare_write failed. | ||
1201 | */ | ||
1202 | } | ||
1203 | if (block_start <= from) | ||
1204 | goto skip; | ||
1205 | |||
1206 | /* commit allocated and zeroed buffers */ | ||
1207 | return mapping->a_ops->commit_write(file, page, from, block_start); | ||
1208 | } | ||
1209 | |||
1210 | static int ext4_prepare_write(struct file *file, struct page *page, | 1150 | static int ext4_prepare_write(struct file *file, struct page *page, |
1211 | unsigned from, unsigned to) | 1151 | unsigned from, unsigned to) |
1212 | { | 1152 | { |
1213 | struct inode *inode = page->mapping->host; | 1153 | struct inode *inode = page->mapping->host; |
1214 | int ret, ret2; | 1154 | int ret, needed_blocks = ext4_writepage_trans_blocks(inode); |
1215 | int needed_blocks = ext4_writepage_trans_blocks(inode); | ||
1216 | handle_t *handle; | 1155 | handle_t *handle; |
1217 | int retries = 0; | 1156 | int retries = 0; |
1218 | 1157 | ||
1219 | retry: | 1158 | retry: |
1220 | handle = ext4_journal_start(inode, needed_blocks); | 1159 | handle = ext4_journal_start(inode, needed_blocks); |
1221 | if (IS_ERR(handle)) | 1160 | if (IS_ERR(handle)) { |
1222 | return PTR_ERR(handle); | 1161 | ret = PTR_ERR(handle); |
1162 | goto out; | ||
1163 | } | ||
1223 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) | 1164 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) |
1224 | ret = nobh_prepare_write(page, from, to, ext4_get_block); | 1165 | ret = nobh_prepare_write(page, from, to, ext4_get_block); |
1225 | else | 1166 | else |
1226 | ret = block_prepare_write(page, from, to, ext4_get_block); | 1167 | ret = block_prepare_write(page, from, to, ext4_get_block); |
1227 | if (ret) | 1168 | if (ret) |
1228 | goto failure; | 1169 | goto prepare_write_failed; |
1229 | 1170 | ||
1230 | if (ext4_should_journal_data(inode)) { | 1171 | if (ext4_should_journal_data(inode)) { |
1231 | ret = walk_page_buffers(handle, page_buffers(page), | 1172 | ret = walk_page_buffers(handle, page_buffers(page), |
1232 | from, to, NULL, do_journal_get_write_access); | 1173 | from, to, NULL, do_journal_get_write_access); |
1233 | if (ret) | ||
1234 | /* fatal error, just put the handle and return */ | ||
1235 | ext4_journal_stop(handle); | ||
1236 | } | 1174 | } |
1237 | return ret; | 1175 | prepare_write_failed: |
1238 | 1176 | if (ret) | |
1239 | failure: | 1177 | ext4_journal_stop(handle); |
1240 | ret2 = ext4_prepare_failure(file, page, from, to); | ||
1241 | if (ret2 < 0) | ||
1242 | return ret2; | ||
1243 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) | 1178 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
1244 | goto retry; | 1179 | goto retry; |
1245 | /* retry number exceeded, or other error like -EDQUOT */ | 1180 | out: |
1246 | return ret; | 1181 | return ret; |
1247 | } | 1182 | } |
1248 | 1183 | ||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 406bf61ed510..8890eba1db52 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -195,7 +195,7 @@ static struct dentry_operations fuse_dentry_operations = { | |||
195 | .d_revalidate = fuse_dentry_revalidate, | 195 | .d_revalidate = fuse_dentry_revalidate, |
196 | }; | 196 | }; |
197 | 197 | ||
198 | static int valid_mode(int m) | 198 | int fuse_valid_type(int m) |
199 | { | 199 | { |
200 | return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || | 200 | return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || |
201 | S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); | 201 | S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); |
@@ -248,7 +248,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
248 | fuse_put_request(fc, req); | 248 | fuse_put_request(fc, req); |
249 | /* Zero nodeid is same as -ENOENT, but with valid timeout */ | 249 | /* Zero nodeid is same as -ENOENT, but with valid timeout */ |
250 | if (!err && outarg.nodeid && | 250 | if (!err && outarg.nodeid && |
251 | (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode))) | 251 | (invalid_nodeid(outarg.nodeid) || |
252 | !fuse_valid_type(outarg.attr.mode))) | ||
252 | err = -EIO; | 253 | err = -EIO; |
253 | if (!err && outarg.nodeid) { | 254 | if (!err && outarg.nodeid) { |
254 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 255 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index b98b20de7405..68ae87cbafab 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -552,3 +552,8 @@ int fuse_ctl_add_conn(struct fuse_conn *fc); | |||
552 | * Remove connection from control filesystem | 552 | * Remove connection from control filesystem |
553 | */ | 553 | */ |
554 | void fuse_ctl_remove_conn(struct fuse_conn *fc); | 554 | void fuse_ctl_remove_conn(struct fuse_conn *fc); |
555 | |||
556 | /** | ||
557 | * Is file type valid? | ||
558 | */ | ||
559 | int fuse_valid_type(int m); | ||
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 5ab8e50e7808..608db81219a0 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -330,6 +330,8 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) | |||
330 | case OPT_ROOTMODE: | 330 | case OPT_ROOTMODE: |
331 | if (match_octal(&args[0], &value)) | 331 | if (match_octal(&args[0], &value)) |
332 | return 0; | 332 | return 0; |
333 | if (!fuse_valid_type(value)) | ||
334 | return 0; | ||
333 | d->rootmode = value; | 335 | d->rootmode = value; |
334 | d->rootmode_present = 1; | 336 | d->rootmode_present = 1; |
335 | break; | 337 | break; |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 9baf69773ed1..fd301a910122 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include "hostfs.h" | 20 | #include "hostfs.h" |
21 | #include "kern_util.h" | 21 | #include "kern_util.h" |
22 | #include "kern.h" | 22 | #include "kern.h" |
23 | #include "user_util.h" | ||
24 | #include "init.h" | 23 | #include "init.h" |
25 | 24 | ||
26 | struct hostfs_inode_info { | 25 | struct hostfs_inode_info { |
@@ -939,7 +938,7 @@ static const struct address_space_operations hostfs_link_aops = { | |||
939 | static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) | 938 | static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) |
940 | { | 939 | { |
941 | struct inode *root_inode; | 940 | struct inode *root_inode; |
942 | char *name, *data = d; | 941 | char *host_root_path, *req_root = d; |
943 | int err; | 942 | int err; |
944 | 943 | ||
945 | sb->s_blocksize = 1024; | 944 | sb->s_blocksize = 1024; |
@@ -948,16 +947,16 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) | |||
948 | sb->s_op = &hostfs_sbops; | 947 | sb->s_op = &hostfs_sbops; |
949 | 948 | ||
950 | /* NULL is printed as <NULL> by sprintf: avoid that. */ | 949 | /* NULL is printed as <NULL> by sprintf: avoid that. */ |
951 | if (data == NULL) | 950 | if (req_root == NULL) |
952 | data = ""; | 951 | req_root = ""; |
953 | 952 | ||
954 | err = -ENOMEM; | 953 | err = -ENOMEM; |
955 | name = kmalloc(strlen(root_ino) + 1 | 954 | host_root_path = kmalloc(strlen(root_ino) + 1 |
956 | + strlen(data) + 1, GFP_KERNEL); | 955 | + strlen(req_root) + 1, GFP_KERNEL); |
957 | if(name == NULL) | 956 | if(host_root_path == NULL) |
958 | goto out; | 957 | goto out; |
959 | 958 | ||
960 | sprintf(name, "%s/%s", root_ino, data); | 959 | sprintf(host_root_path, "%s/%s", root_ino, req_root); |
961 | 960 | ||
962 | root_inode = iget(sb, 0); | 961 | root_inode = iget(sb, 0); |
963 | if(root_inode == NULL) | 962 | if(root_inode == NULL) |
@@ -967,10 +966,10 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) | |||
967 | if(err) | 966 | if(err) |
968 | goto out_put; | 967 | goto out_put; |
969 | 968 | ||
970 | HOSTFS_I(root_inode)->host_filename = name; | 969 | HOSTFS_I(root_inode)->host_filename = host_root_path; |
971 | /* Avoid that in the error path, iput(root_inode) frees again name through | 970 | /* Avoid that in the error path, iput(root_inode) frees again |
972 | * hostfs_destroy_inode! */ | 971 | * host_root_path through hostfs_destroy_inode! */ |
973 | name = NULL; | 972 | host_root_path = NULL; |
974 | 973 | ||
975 | err = -ENOMEM; | 974 | err = -ENOMEM; |
976 | sb->s_root = d_alloc_root(root_inode); | 975 | sb->s_root = d_alloc_root(root_inode); |
@@ -990,7 +989,7 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) | |||
990 | out_put: | 989 | out_put: |
991 | iput(root_inode); | 990 | iput(root_inode); |
992 | out_free: | 991 | out_free: |
993 | kfree(name); | 992 | kfree(host_root_path); |
994 | out: | 993 | out: |
995 | return(err); | 994 | return(err); |
996 | } | 995 | } |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 92d8ec859e22..cd3469720cbf 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1684,7 +1684,8 @@ go_ahead: | |||
1684 | * ... prune child dentries and writebacks if needed. | 1684 | * ... prune child dentries and writebacks if needed. |
1685 | */ | 1685 | */ |
1686 | if (atomic_read(&old_dentry->d_count) > 1) { | 1686 | if (atomic_read(&old_dentry->d_count) > 1) { |
1687 | nfs_wb_all(old_inode); | 1687 | if (S_ISREG(old_inode->i_mode)) |
1688 | nfs_wb_all(old_inode); | ||
1688 | shrink_dcache_parent(old_dentry); | 1689 | shrink_dcache_parent(old_dentry); |
1689 | } | 1690 | } |
1690 | nfs_inode_return_delegation(old_inode); | 1691 | nfs_inode_return_delegation(old_inode); |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index b1c98ea39b72..2877744cb606 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -432,10 +432,10 @@ static void nfs_direct_commit_result(struct rpc_task *task, void *calldata) | |||
432 | if (NFS_PROTO(data->inode)->commit_done(task, data) != 0) | 432 | if (NFS_PROTO(data->inode)->commit_done(task, data) != 0) |
433 | return; | 433 | return; |
434 | if (unlikely(task->tk_status < 0)) { | 434 | if (unlikely(task->tk_status < 0)) { |
435 | dreq->error = task->tk_status; | 435 | dprintk("NFS: %5u commit failed with error %d.\n", |
436 | task->tk_pid, task->tk_status); | ||
436 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; | 437 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; |
437 | } | 438 | } else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) { |
438 | if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) { | ||
439 | dprintk("NFS: %5u commit verify failed\n", task->tk_pid); | 439 | dprintk("NFS: %5u commit verify failed\n", task->tk_pid); |
440 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; | 440 | dreq->flags = NFS_ODIRECT_RESCHED_WRITES; |
441 | } | 441 | } |
@@ -531,9 +531,12 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata) | |||
531 | 531 | ||
532 | spin_lock(&dreq->lock); | 532 | spin_lock(&dreq->lock); |
533 | 533 | ||
534 | if (unlikely(dreq->error != 0)) | ||
535 | goto out_unlock; | ||
534 | if (unlikely(status < 0)) { | 536 | if (unlikely(status < 0)) { |
537 | /* An error has occured, so we should not commit */ | ||
538 | dreq->flags = 0; | ||
535 | dreq->error = status; | 539 | dreq->error = status; |
536 | goto out_unlock; | ||
537 | } | 540 | } |
538 | 541 | ||
539 | dreq->count += data->res.count; | 542 | dreq->count += data->res.count; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index af53c02f473b..44aa9b726573 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -341,8 +341,10 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
341 | lock_kernel(); | 341 | lock_kernel(); |
342 | nfs_begin_data_update(inode); | 342 | nfs_begin_data_update(inode); |
343 | /* Write all dirty data */ | 343 | /* Write all dirty data */ |
344 | filemap_write_and_wait(inode->i_mapping); | 344 | if (S_ISREG(inode->i_mode)) { |
345 | nfs_wb_all(inode); | 345 | filemap_write_and_wait(inode->i_mapping); |
346 | nfs_wb_all(inode); | ||
347 | } | ||
346 | /* | 348 | /* |
347 | * Return any delegations if we're going to change ACLs | 349 | * Return any delegations if we're going to change ACLs |
348 | */ | 350 | */ |
@@ -429,7 +431,8 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
429 | int err; | 431 | int err; |
430 | 432 | ||
431 | /* Flush out writes to the server in order to update c/mtime */ | 433 | /* Flush out writes to the server in order to update c/mtime */ |
432 | nfs_sync_mapping_range(inode->i_mapping, 0, 0, FLUSH_NOCOMMIT); | 434 | if (S_ISREG(inode->i_mode)) |
435 | nfs_sync_mapping_range(inode->i_mapping, 0, 0, FLUSH_NOCOMMIT); | ||
433 | 436 | ||
434 | /* | 437 | /* |
435 | * We may force a getattr if the user cares about atime. | 438 | * We may force a getattr if the user cares about atime. |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index bb516a2cfbaf..f1eae44b9a1a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -151,10 +151,10 @@ int __init register_nfs_fs(void) | |||
151 | if (ret < 0) | 151 | if (ret < 0) |
152 | goto error_0; | 152 | goto error_0; |
153 | 153 | ||
154 | #ifdef CONFIG_NFS_V4 | ||
155 | ret = nfs_register_sysctl(); | 154 | ret = nfs_register_sysctl(); |
156 | if (ret < 0) | 155 | if (ret < 0) |
157 | goto error_1; | 156 | goto error_1; |
157 | #ifdef CONFIG_NFS_V4 | ||
158 | ret = register_filesystem(&nfs4_fs_type); | 158 | ret = register_filesystem(&nfs4_fs_type); |
159 | if (ret < 0) | 159 | if (ret < 0) |
160 | goto error_2; | 160 | goto error_2; |
@@ -165,9 +165,9 @@ int __init register_nfs_fs(void) | |||
165 | #ifdef CONFIG_NFS_V4 | 165 | #ifdef CONFIG_NFS_V4 |
166 | error_2: | 166 | error_2: |
167 | nfs_unregister_sysctl(); | 167 | nfs_unregister_sysctl(); |
168 | #endif | ||
168 | error_1: | 169 | error_1: |
169 | unregister_filesystem(&nfs_fs_type); | 170 | unregister_filesystem(&nfs_fs_type); |
170 | #endif | ||
171 | error_0: | 171 | error_0: |
172 | return ret; | 172 | return ret; |
173 | } | 173 | } |
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c index fcdcafbb3293..b62481dabae9 100644 --- a/fs/nfs/sysctl.c +++ b/fs/nfs/sysctl.c | |||
@@ -50,6 +50,14 @@ static ctl_table nfs_cb_sysctls[] = { | |||
50 | .proc_handler = &proc_dointvec_jiffies, | 50 | .proc_handler = &proc_dointvec_jiffies, |
51 | .strategy = &sysctl_jiffies, | 51 | .strategy = &sysctl_jiffies, |
52 | }, | 52 | }, |
53 | { | ||
54 | .ctl_name = CTL_UNNUMBERED, | ||
55 | .procname = "nfs_congestion_kb", | ||
56 | .data = &nfs_congestion_kb, | ||
57 | .maxlen = sizeof(nfs_congestion_kb), | ||
58 | .mode = 0644, | ||
59 | .proc_handler = &proc_dointvec, | ||
60 | }, | ||
53 | { .ctl_name = 0 } | 61 | { .ctl_name = 0 } |
54 | }; | 62 | }; |
55 | 63 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index febdade91670..797558941745 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
13 | #include <linux/file.h> | 13 | #include <linux/file.h> |
14 | #include <linux/writeback.h> | 14 | #include <linux/writeback.h> |
15 | #include <linux/swap.h> | ||
15 | 16 | ||
16 | #include <linux/sunrpc/clnt.h> | 17 | #include <linux/sunrpc/clnt.h> |
17 | #include <linux/nfs_fs.h> | 18 | #include <linux/nfs_fs.h> |
@@ -37,8 +38,6 @@ | |||
37 | static struct nfs_page * nfs_update_request(struct nfs_open_context*, | 38 | static struct nfs_page * nfs_update_request(struct nfs_open_context*, |
38 | struct page *, | 39 | struct page *, |
39 | unsigned int, unsigned int); | 40 | unsigned int, unsigned int); |
40 | static void nfs_mark_request_dirty(struct nfs_page *req); | ||
41 | static int nfs_wait_on_write_congestion(struct address_space *, int); | ||
42 | static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how); | 41 | static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how); |
43 | static const struct rpc_call_ops nfs_write_partial_ops; | 42 | static const struct rpc_call_ops nfs_write_partial_ops; |
44 | static const struct rpc_call_ops nfs_write_full_ops; | 43 | static const struct rpc_call_ops nfs_write_full_ops; |
@@ -48,8 +47,6 @@ static struct kmem_cache *nfs_wdata_cachep; | |||
48 | static mempool_t *nfs_wdata_mempool; | 47 | static mempool_t *nfs_wdata_mempool; |
49 | static mempool_t *nfs_commit_mempool; | 48 | static mempool_t *nfs_commit_mempool; |
50 | 49 | ||
51 | static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion); | ||
52 | |||
53 | struct nfs_write_data *nfs_commit_alloc(void) | 50 | struct nfs_write_data *nfs_commit_alloc(void) |
54 | { | 51 | { |
55 | struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS); | 52 | struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS); |
@@ -211,6 +208,43 @@ static int wb_priority(struct writeback_control *wbc) | |||
211 | } | 208 | } |
212 | 209 | ||
213 | /* | 210 | /* |
211 | * NFS congestion control | ||
212 | */ | ||
213 | |||
214 | int nfs_congestion_kb; | ||
215 | |||
216 | #define NFS_CONGESTION_ON_THRESH (nfs_congestion_kb >> (PAGE_SHIFT-10)) | ||
217 | #define NFS_CONGESTION_OFF_THRESH \ | ||
218 | (NFS_CONGESTION_ON_THRESH - (NFS_CONGESTION_ON_THRESH >> 2)) | ||
219 | |||
220 | static int nfs_set_page_writeback(struct page *page) | ||
221 | { | ||
222 | int ret = test_set_page_writeback(page); | ||
223 | |||
224 | if (!ret) { | ||
225 | struct inode *inode = page->mapping->host; | ||
226 | struct nfs_server *nfss = NFS_SERVER(inode); | ||
227 | |||
228 | if (atomic_inc_return(&nfss->writeback) > | ||
229 | NFS_CONGESTION_ON_THRESH) | ||
230 | set_bdi_congested(&nfss->backing_dev_info, WRITE); | ||
231 | } | ||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | static void nfs_end_page_writeback(struct page *page) | ||
236 | { | ||
237 | struct inode *inode = page->mapping->host; | ||
238 | struct nfs_server *nfss = NFS_SERVER(inode); | ||
239 | |||
240 | end_page_writeback(page); | ||
241 | if (atomic_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) { | ||
242 | clear_bdi_congested(&nfss->backing_dev_info, WRITE); | ||
243 | congestion_end(WRITE); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | /* | ||
214 | * Find an associated nfs write request, and prepare to flush it out | 248 | * Find an associated nfs write request, and prepare to flush it out |
215 | * Returns 1 if there was no write request, or if the request was | 249 | * Returns 1 if there was no write request, or if the request was |
216 | * already tagged by nfs_set_page_dirty.Returns 0 if the request | 250 | * already tagged by nfs_set_page_dirty.Returns 0 if the request |
@@ -220,7 +254,8 @@ static int wb_priority(struct writeback_control *wbc) | |||
220 | static int nfs_page_mark_flush(struct page *page) | 254 | static int nfs_page_mark_flush(struct page *page) |
221 | { | 255 | { |
222 | struct nfs_page *req; | 256 | struct nfs_page *req; |
223 | spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock; | 257 | struct nfs_inode *nfsi = NFS_I(page->mapping->host); |
258 | spinlock_t *req_lock = &nfsi->req_lock; | ||
224 | int ret; | 259 | int ret; |
225 | 260 | ||
226 | spin_lock(req_lock); | 261 | spin_lock(req_lock); |
@@ -244,11 +279,23 @@ static int nfs_page_mark_flush(struct page *page) | |||
244 | return ret; | 279 | return ret; |
245 | spin_lock(req_lock); | 280 | spin_lock(req_lock); |
246 | } | 281 | } |
247 | spin_unlock(req_lock); | 282 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
248 | if (test_and_set_bit(PG_FLUSHING, &req->wb_flags) == 0) { | 283 | /* This request is marked for commit */ |
249 | nfs_mark_request_dirty(req); | 284 | spin_unlock(req_lock); |
250 | set_page_writeback(page); | 285 | nfs_unlock_request(req); |
286 | return 1; | ||
251 | } | 287 | } |
288 | if (nfs_set_page_writeback(page) == 0) { | ||
289 | nfs_list_remove_request(req); | ||
290 | /* add the request to the inode's dirty list. */ | ||
291 | radix_tree_tag_set(&nfsi->nfs_page_tree, | ||
292 | req->wb_index, NFS_PAGE_TAG_DIRTY); | ||
293 | nfs_list_add_request(req, &nfsi->dirty); | ||
294 | nfsi->ndirty++; | ||
295 | spin_unlock(req_lock); | ||
296 | __mark_inode_dirty(page->mapping->host, I_DIRTY_PAGES); | ||
297 | } else | ||
298 | spin_unlock(req_lock); | ||
252 | ret = test_bit(PG_NEED_FLUSH, &req->wb_flags); | 299 | ret = test_bit(PG_NEED_FLUSH, &req->wb_flags); |
253 | nfs_unlock_request(req); | 300 | nfs_unlock_request(req); |
254 | return ret; | 301 | return ret; |
@@ -302,13 +349,8 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) | |||
302 | return err; | 349 | return err; |
303 | } | 350 | } |
304 | 351 | ||
305 | /* | ||
306 | * Note: causes nfs_update_request() to block on the assumption | ||
307 | * that the writeback is generated due to memory pressure. | ||
308 | */ | ||
309 | int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | 352 | int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) |
310 | { | 353 | { |
311 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
312 | struct inode *inode = mapping->host; | 354 | struct inode *inode = mapping->host; |
313 | int err; | 355 | int err; |
314 | 356 | ||
@@ -317,20 +359,12 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
317 | err = generic_writepages(mapping, wbc); | 359 | err = generic_writepages(mapping, wbc); |
318 | if (err) | 360 | if (err) |
319 | return err; | 361 | return err; |
320 | while (test_and_set_bit(BDI_write_congested, &bdi->state) != 0) { | ||
321 | if (wbc->nonblocking) | ||
322 | return 0; | ||
323 | nfs_wait_on_write_congestion(mapping, 0); | ||
324 | } | ||
325 | err = nfs_flush_mapping(mapping, wbc, wb_priority(wbc)); | 362 | err = nfs_flush_mapping(mapping, wbc, wb_priority(wbc)); |
326 | if (err < 0) | 363 | if (err < 0) |
327 | goto out; | 364 | goto out; |
328 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, err); | 365 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, err); |
329 | err = 0; | 366 | err = 0; |
330 | out: | 367 | out: |
331 | clear_bit(BDI_write_congested, &bdi->state); | ||
332 | wake_up_all(&nfs_write_congestion); | ||
333 | congestion_end(WRITE); | ||
334 | return err; | 368 | return err; |
335 | } | 369 | } |
336 | 370 | ||
@@ -354,13 +388,15 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
354 | } | 388 | } |
355 | SetPagePrivate(req->wb_page); | 389 | SetPagePrivate(req->wb_page); |
356 | set_page_private(req->wb_page, (unsigned long)req); | 390 | set_page_private(req->wb_page, (unsigned long)req); |
391 | if (PageDirty(req->wb_page)) | ||
392 | set_bit(PG_NEED_FLUSH, &req->wb_flags); | ||
357 | nfsi->npages++; | 393 | nfsi->npages++; |
358 | atomic_inc(&req->wb_count); | 394 | atomic_inc(&req->wb_count); |
359 | return 0; | 395 | return 0; |
360 | } | 396 | } |
361 | 397 | ||
362 | /* | 398 | /* |
363 | * Insert a write request into an inode | 399 | * Remove a write request from an inode |
364 | */ | 400 | */ |
365 | static void nfs_inode_remove_request(struct nfs_page *req) | 401 | static void nfs_inode_remove_request(struct nfs_page *req) |
366 | { | 402 | { |
@@ -373,6 +409,8 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
373 | set_page_private(req->wb_page, 0); | 409 | set_page_private(req->wb_page, 0); |
374 | ClearPagePrivate(req->wb_page); | 410 | ClearPagePrivate(req->wb_page); |
375 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); | 411 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); |
412 | if (test_and_clear_bit(PG_NEED_FLUSH, &req->wb_flags)) | ||
413 | __set_page_dirty_nobuffers(req->wb_page); | ||
376 | nfsi->npages--; | 414 | nfsi->npages--; |
377 | if (!nfsi->npages) { | 415 | if (!nfsi->npages) { |
378 | spin_unlock(&nfsi->req_lock); | 416 | spin_unlock(&nfsi->req_lock); |
@@ -384,28 +422,9 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
384 | nfs_release_request(req); | 422 | nfs_release_request(req); |
385 | } | 423 | } |
386 | 424 | ||
387 | /* | ||
388 | * Add a request to the inode's dirty list. | ||
389 | */ | ||
390 | static void | ||
391 | nfs_mark_request_dirty(struct nfs_page *req) | ||
392 | { | ||
393 | struct inode *inode = req->wb_context->dentry->d_inode; | ||
394 | struct nfs_inode *nfsi = NFS_I(inode); | ||
395 | |||
396 | spin_lock(&nfsi->req_lock); | ||
397 | radix_tree_tag_set(&nfsi->nfs_page_tree, | ||
398 | req->wb_index, NFS_PAGE_TAG_DIRTY); | ||
399 | nfs_list_add_request(req, &nfsi->dirty); | ||
400 | nfsi->ndirty++; | ||
401 | spin_unlock(&nfsi->req_lock); | ||
402 | __mark_inode_dirty(inode, I_DIRTY_PAGES); | ||
403 | } | ||
404 | |||
405 | static void | 425 | static void |
406 | nfs_redirty_request(struct nfs_page *req) | 426 | nfs_redirty_request(struct nfs_page *req) |
407 | { | 427 | { |
408 | clear_bit(PG_FLUSHING, &req->wb_flags); | ||
409 | __set_page_dirty_nobuffers(req->wb_page); | 428 | __set_page_dirty_nobuffers(req->wb_page); |
410 | } | 429 | } |
411 | 430 | ||
@@ -415,7 +434,11 @@ nfs_redirty_request(struct nfs_page *req) | |||
415 | static inline int | 434 | static inline int |
416 | nfs_dirty_request(struct nfs_page *req) | 435 | nfs_dirty_request(struct nfs_page *req) |
417 | { | 436 | { |
418 | return test_bit(PG_FLUSHING, &req->wb_flags) == 0; | 437 | struct page *page = req->wb_page; |
438 | |||
439 | if (page == NULL || test_bit(PG_NEED_COMMIT, &req->wb_flags)) | ||
440 | return 0; | ||
441 | return !PageWriteback(req->wb_page); | ||
419 | } | 442 | } |
420 | 443 | ||
421 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 444 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
@@ -431,10 +454,48 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
431 | spin_lock(&nfsi->req_lock); | 454 | spin_lock(&nfsi->req_lock); |
432 | nfs_list_add_request(req, &nfsi->commit); | 455 | nfs_list_add_request(req, &nfsi->commit); |
433 | nfsi->ncommit++; | 456 | nfsi->ncommit++; |
457 | set_bit(PG_NEED_COMMIT, &(req)->wb_flags); | ||
434 | spin_unlock(&nfsi->req_lock); | 458 | spin_unlock(&nfsi->req_lock); |
435 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 459 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
436 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 460 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
437 | } | 461 | } |
462 | |||
463 | static inline | ||
464 | int nfs_write_need_commit(struct nfs_write_data *data) | ||
465 | { | ||
466 | return data->verf.committed != NFS_FILE_SYNC; | ||
467 | } | ||
468 | |||
469 | static inline | ||
470 | int nfs_reschedule_unstable_write(struct nfs_page *req) | ||
471 | { | ||
472 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { | ||
473 | nfs_mark_request_commit(req); | ||
474 | return 1; | ||
475 | } | ||
476 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { | ||
477 | nfs_redirty_request(req); | ||
478 | return 1; | ||
479 | } | ||
480 | return 0; | ||
481 | } | ||
482 | #else | ||
483 | static inline void | ||
484 | nfs_mark_request_commit(struct nfs_page *req) | ||
485 | { | ||
486 | } | ||
487 | |||
488 | static inline | ||
489 | int nfs_write_need_commit(struct nfs_write_data *data) | ||
490 | { | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static inline | ||
495 | int nfs_reschedule_unstable_write(struct nfs_page *req) | ||
496 | { | ||
497 | return 0; | ||
498 | } | ||
438 | #endif | 499 | #endif |
439 | 500 | ||
440 | /* | 501 | /* |
@@ -481,6 +542,7 @@ static void nfs_cancel_dirty_list(struct list_head *head) | |||
481 | while(!list_empty(head)) { | 542 | while(!list_empty(head)) { |
482 | req = nfs_list_entry(head->next); | 543 | req = nfs_list_entry(head->next); |
483 | nfs_list_remove_request(req); | 544 | nfs_list_remove_request(req); |
545 | nfs_end_page_writeback(req->wb_page); | ||
484 | nfs_inode_remove_request(req); | 546 | nfs_inode_remove_request(req); |
485 | nfs_clear_page_writeback(req); | 547 | nfs_clear_page_writeback(req); |
486 | } | 548 | } |
@@ -494,6 +556,7 @@ static void nfs_cancel_commit_list(struct list_head *head) | |||
494 | req = nfs_list_entry(head->next); | 556 | req = nfs_list_entry(head->next); |
495 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 557 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
496 | nfs_list_remove_request(req); | 558 | nfs_list_remove_request(req); |
559 | clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); | ||
497 | nfs_inode_remove_request(req); | 560 | nfs_inode_remove_request(req); |
498 | nfs_unlock_request(req); | 561 | nfs_unlock_request(req); |
499 | } | 562 | } |
@@ -531,10 +594,10 @@ static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, un | |||
531 | } | 594 | } |
532 | #endif | 595 | #endif |
533 | 596 | ||
534 | static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr) | 597 | static int nfs_wait_on_write_congestion(struct address_space *mapping) |
535 | { | 598 | { |
599 | struct inode *inode = mapping->host; | ||
536 | struct backing_dev_info *bdi = mapping->backing_dev_info; | 600 | struct backing_dev_info *bdi = mapping->backing_dev_info; |
537 | DEFINE_WAIT(wait); | ||
538 | int ret = 0; | 601 | int ret = 0; |
539 | 602 | ||
540 | might_sleep(); | 603 | might_sleep(); |
@@ -542,31 +605,23 @@ static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr) | |||
542 | if (!bdi_write_congested(bdi)) | 605 | if (!bdi_write_congested(bdi)) |
543 | return 0; | 606 | return 0; |
544 | 607 | ||
545 | nfs_inc_stats(mapping->host, NFSIOS_CONGESTIONWAIT); | 608 | nfs_inc_stats(inode, NFSIOS_CONGESTIONWAIT); |
546 | 609 | ||
547 | if (intr) { | 610 | do { |
548 | struct rpc_clnt *clnt = NFS_CLIENT(mapping->host); | 611 | struct rpc_clnt *clnt = NFS_CLIENT(inode); |
549 | sigset_t oldset; | 612 | sigset_t oldset; |
550 | 613 | ||
551 | rpc_clnt_sigmask(clnt, &oldset); | 614 | rpc_clnt_sigmask(clnt, &oldset); |
552 | prepare_to_wait(&nfs_write_congestion, &wait, TASK_INTERRUPTIBLE); | 615 | ret = congestion_wait_interruptible(WRITE, HZ/10); |
553 | if (bdi_write_congested(bdi)) { | ||
554 | if (signalled()) | ||
555 | ret = -ERESTARTSYS; | ||
556 | else | ||
557 | schedule(); | ||
558 | } | ||
559 | rpc_clnt_sigunmask(clnt, &oldset); | 616 | rpc_clnt_sigunmask(clnt, &oldset); |
560 | } else { | 617 | if (ret == -ERESTARTSYS) |
561 | prepare_to_wait(&nfs_write_congestion, &wait, TASK_UNINTERRUPTIBLE); | 618 | break; |
562 | if (bdi_write_congested(bdi)) | 619 | ret = 0; |
563 | schedule(); | 620 | } while (bdi_write_congested(bdi)); |
564 | } | 621 | |
565 | finish_wait(&nfs_write_congestion, &wait); | ||
566 | return ret; | 622 | return ret; |
567 | } | 623 | } |
568 | 624 | ||
569 | |||
570 | /* | 625 | /* |
571 | * Try to update any existing write request, or create one if there is none. | 626 | * Try to update any existing write request, or create one if there is none. |
572 | * In order to match, the request's credentials must match those of | 627 | * In order to match, the request's credentials must match those of |
@@ -577,14 +632,15 @@ static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr) | |||
577 | static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | 632 | static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, |
578 | struct page *page, unsigned int offset, unsigned int bytes) | 633 | struct page *page, unsigned int offset, unsigned int bytes) |
579 | { | 634 | { |
580 | struct inode *inode = page->mapping->host; | 635 | struct address_space *mapping = page->mapping; |
636 | struct inode *inode = mapping->host; | ||
581 | struct nfs_inode *nfsi = NFS_I(inode); | 637 | struct nfs_inode *nfsi = NFS_I(inode); |
582 | struct nfs_page *req, *new = NULL; | 638 | struct nfs_page *req, *new = NULL; |
583 | unsigned long rqend, end; | 639 | unsigned long rqend, end; |
584 | 640 | ||
585 | end = offset + bytes; | 641 | end = offset + bytes; |
586 | 642 | ||
587 | if (nfs_wait_on_write_congestion(page->mapping, NFS_SERVER(inode)->flags & NFS_MOUNT_INTR)) | 643 | if (nfs_wait_on_write_congestion(mapping)) |
588 | return ERR_PTR(-ERESTARTSYS); | 644 | return ERR_PTR(-ERESTARTSYS); |
589 | for (;;) { | 645 | for (;;) { |
590 | /* Loop over all inode entries and see if we find | 646 | /* Loop over all inode entries and see if we find |
@@ -727,26 +783,12 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
727 | 783 | ||
728 | static void nfs_writepage_release(struct nfs_page *req) | 784 | static void nfs_writepage_release(struct nfs_page *req) |
729 | { | 785 | { |
730 | end_page_writeback(req->wb_page); | ||
731 | 786 | ||
732 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 787 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) { |
733 | if (!PageError(req->wb_page)) { | 788 | nfs_end_page_writeback(req->wb_page); |
734 | if (NFS_NEED_RESCHED(req)) { | 789 | nfs_inode_remove_request(req); |
735 | nfs_redirty_request(req); | 790 | } else |
736 | goto out; | 791 | nfs_end_page_writeback(req->wb_page); |
737 | } else if (NFS_NEED_COMMIT(req)) { | ||
738 | nfs_mark_request_commit(req); | ||
739 | goto out; | ||
740 | } | ||
741 | } | ||
742 | nfs_inode_remove_request(req); | ||
743 | |||
744 | out: | ||
745 | nfs_clear_commit(req); | ||
746 | nfs_clear_reschedule(req); | ||
747 | #else | ||
748 | nfs_inode_remove_request(req); | ||
749 | #endif | ||
750 | nfs_clear_page_writeback(req); | 792 | nfs_clear_page_writeback(req); |
751 | } | 793 | } |
752 | 794 | ||
@@ -879,6 +921,7 @@ out_bad: | |||
879 | nfs_writedata_release(data); | 921 | nfs_writedata_release(data); |
880 | } | 922 | } |
881 | nfs_redirty_request(req); | 923 | nfs_redirty_request(req); |
924 | nfs_end_page_writeback(req->wb_page); | ||
882 | nfs_clear_page_writeback(req); | 925 | nfs_clear_page_writeback(req); |
883 | return -ENOMEM; | 926 | return -ENOMEM; |
884 | } | 927 | } |
@@ -924,6 +967,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, int how) | |||
924 | struct nfs_page *req = nfs_list_entry(head->next); | 967 | struct nfs_page *req = nfs_list_entry(head->next); |
925 | nfs_list_remove_request(req); | 968 | nfs_list_remove_request(req); |
926 | nfs_redirty_request(req); | 969 | nfs_redirty_request(req); |
970 | nfs_end_page_writeback(req->wb_page); | ||
927 | nfs_clear_page_writeback(req); | 971 | nfs_clear_page_writeback(req); |
928 | } | 972 | } |
929 | return -ENOMEM; | 973 | return -ENOMEM; |
@@ -959,6 +1003,7 @@ out_err: | |||
959 | req = nfs_list_entry(head->next); | 1003 | req = nfs_list_entry(head->next); |
960 | nfs_list_remove_request(req); | 1004 | nfs_list_remove_request(req); |
961 | nfs_redirty_request(req); | 1005 | nfs_redirty_request(req); |
1006 | nfs_end_page_writeback(req->wb_page); | ||
962 | nfs_clear_page_writeback(req); | 1007 | nfs_clear_page_writeback(req); |
963 | } | 1008 | } |
964 | return error; | 1009 | return error; |
@@ -986,22 +1031,28 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | |||
986 | nfs_set_pageerror(page); | 1031 | nfs_set_pageerror(page); |
987 | req->wb_context->error = task->tk_status; | 1032 | req->wb_context->error = task->tk_status; |
988 | dprintk(", error = %d\n", task->tk_status); | 1033 | dprintk(", error = %d\n", task->tk_status); |
989 | } else { | 1034 | goto out; |
990 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | ||
991 | if (data->verf.committed < NFS_FILE_SYNC) { | ||
992 | if (!NFS_NEED_COMMIT(req)) { | ||
993 | nfs_defer_commit(req); | ||
994 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | ||
995 | dprintk(" defer commit\n"); | ||
996 | } else if (memcmp(&req->wb_verf, &data->verf, sizeof(req->wb_verf))) { | ||
997 | nfs_defer_reschedule(req); | ||
998 | dprintk(" server reboot detected\n"); | ||
999 | } | ||
1000 | } else | ||
1001 | #endif | ||
1002 | dprintk(" OK\n"); | ||
1003 | } | 1035 | } |
1004 | 1036 | ||
1037 | if (nfs_write_need_commit(data)) { | ||
1038 | spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock; | ||
1039 | |||
1040 | spin_lock(req_lock); | ||
1041 | if (test_bit(PG_NEED_RESCHED, &req->wb_flags)) { | ||
1042 | /* Do nothing we need to resend the writes */ | ||
1043 | } else if (!test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags)) { | ||
1044 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | ||
1045 | dprintk(" defer commit\n"); | ||
1046 | } else if (memcmp(&req->wb_verf, &data->verf, sizeof(req->wb_verf))) { | ||
1047 | set_bit(PG_NEED_RESCHED, &req->wb_flags); | ||
1048 | clear_bit(PG_NEED_COMMIT, &req->wb_flags); | ||
1049 | dprintk(" server reboot detected\n"); | ||
1050 | } | ||
1051 | spin_unlock(req_lock); | ||
1052 | } else | ||
1053 | dprintk(" OK\n"); | ||
1054 | |||
1055 | out: | ||
1005 | if (atomic_dec_and_test(&req->wb_complete)) | 1056 | if (atomic_dec_and_test(&req->wb_complete)) |
1006 | nfs_writepage_release(req); | 1057 | nfs_writepage_release(req); |
1007 | } | 1058 | } |
@@ -1042,25 +1093,21 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) | |||
1042 | if (task->tk_status < 0) { | 1093 | if (task->tk_status < 0) { |
1043 | nfs_set_pageerror(page); | 1094 | nfs_set_pageerror(page); |
1044 | req->wb_context->error = task->tk_status; | 1095 | req->wb_context->error = task->tk_status; |
1045 | end_page_writeback(page); | ||
1046 | nfs_inode_remove_request(req); | ||
1047 | dprintk(", error = %d\n", task->tk_status); | 1096 | dprintk(", error = %d\n", task->tk_status); |
1048 | goto next; | 1097 | goto remove_request; |
1049 | } | 1098 | } |
1050 | end_page_writeback(page); | ||
1051 | 1099 | ||
1052 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1100 | if (nfs_write_need_commit(data)) { |
1053 | if (data->args.stable != NFS_UNSTABLE || data->verf.committed == NFS_FILE_SYNC) { | 1101 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); |
1054 | nfs_inode_remove_request(req); | 1102 | nfs_mark_request_commit(req); |
1055 | dprintk(" OK\n"); | 1103 | nfs_end_page_writeback(page); |
1104 | dprintk(" marked for commit\n"); | ||
1056 | goto next; | 1105 | goto next; |
1057 | } | 1106 | } |
1058 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | 1107 | dprintk(" OK\n"); |
1059 | nfs_mark_request_commit(req); | 1108 | remove_request: |
1060 | dprintk(" marked for commit\n"); | 1109 | nfs_end_page_writeback(page); |
1061 | #else | ||
1062 | nfs_inode_remove_request(req); | 1110 | nfs_inode_remove_request(req); |
1063 | #endif | ||
1064 | next: | 1111 | next: |
1065 | nfs_clear_page_writeback(req); | 1112 | nfs_clear_page_writeback(req); |
1066 | } | 1113 | } |
@@ -1248,6 +1295,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
1248 | while (!list_empty(&data->pages)) { | 1295 | while (!list_empty(&data->pages)) { |
1249 | req = nfs_list_entry(data->pages.next); | 1296 | req = nfs_list_entry(data->pages.next); |
1250 | nfs_list_remove_request(req); | 1297 | nfs_list_remove_request(req); |
1298 | clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); | ||
1251 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 1299 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
1252 | 1300 | ||
1253 | dprintk("NFS: commit (%s/%Ld %d@%Ld)", | 1301 | dprintk("NFS: commit (%s/%Ld %d@%Ld)", |
@@ -1483,15 +1531,22 @@ int nfs_wb_page(struct inode *inode, struct page* page) | |||
1483 | 1531 | ||
1484 | int nfs_set_page_dirty(struct page *page) | 1532 | int nfs_set_page_dirty(struct page *page) |
1485 | { | 1533 | { |
1534 | spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock; | ||
1486 | struct nfs_page *req; | 1535 | struct nfs_page *req; |
1536 | int ret; | ||
1487 | 1537 | ||
1488 | req = nfs_page_find_request(page); | 1538 | spin_lock(req_lock); |
1539 | req = nfs_page_find_request_locked(page); | ||
1489 | if (req != NULL) { | 1540 | if (req != NULL) { |
1490 | /* Mark any existing write requests for flushing */ | 1541 | /* Mark any existing write requests for flushing */ |
1491 | set_bit(PG_NEED_FLUSH, &req->wb_flags); | 1542 | ret = !test_and_set_bit(PG_NEED_FLUSH, &req->wb_flags); |
1543 | spin_unlock(req_lock); | ||
1492 | nfs_release_request(req); | 1544 | nfs_release_request(req); |
1545 | return ret; | ||
1493 | } | 1546 | } |
1494 | return __set_page_dirty_nobuffers(page); | 1547 | ret = __set_page_dirty_nobuffers(page); |
1548 | spin_unlock(req_lock); | ||
1549 | return ret; | ||
1495 | } | 1550 | } |
1496 | 1551 | ||
1497 | 1552 | ||
@@ -1514,6 +1569,26 @@ int __init nfs_init_writepagecache(void) | |||
1514 | if (nfs_commit_mempool == NULL) | 1569 | if (nfs_commit_mempool == NULL) |
1515 | return -ENOMEM; | 1570 | return -ENOMEM; |
1516 | 1571 | ||
1572 | /* | ||
1573 | * NFS congestion size, scale with available memory. | ||
1574 | * | ||
1575 | * 64MB: 8192k | ||
1576 | * 128MB: 11585k | ||
1577 | * 256MB: 16384k | ||
1578 | * 512MB: 23170k | ||
1579 | * 1GB: 32768k | ||
1580 | * 2GB: 46340k | ||
1581 | * 4GB: 65536k | ||
1582 | * 8GB: 92681k | ||
1583 | * 16GB: 131072k | ||
1584 | * | ||
1585 | * This allows larger machines to have larger/more transfers. | ||
1586 | * Limit the default to 256M | ||
1587 | */ | ||
1588 | nfs_congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10); | ||
1589 | if (nfs_congestion_kb > 256*1024) | ||
1590 | nfs_congestion_kb = 256*1024; | ||
1591 | |||
1517 | return 0; | 1592 | return 0; |
1518 | } | 1593 | } |
1519 | 1594 | ||
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 6f677988c71d..7e4bb0af24d7 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
@@ -859,8 +859,8 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, | |||
859 | #define NFS3_ENTRY_BAGGAGE (2 + 1 + 2 + 1) | 859 | #define NFS3_ENTRY_BAGGAGE (2 + 1 + 2 + 1) |
860 | #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2)) | 860 | #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2)) |
861 | static int | 861 | static int |
862 | encode_entry(struct readdir_cd *ccd, const char *name, | 862 | encode_entry(struct readdir_cd *ccd, const char *name, int namlen, |
863 | int namlen, off_t offset, ino_t ino, unsigned int d_type, int plus) | 863 | loff_t offset, ino_t ino, unsigned int d_type, int plus) |
864 | { | 864 | { |
865 | struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, | 865 | struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, |
866 | common); | 866 | common); |
@@ -880,7 +880,7 @@ encode_entry(struct readdir_cd *ccd, const char *name, | |||
880 | *cd->offset1 = htonl(offset64 & 0xffffffff); | 880 | *cd->offset1 = htonl(offset64 & 0xffffffff); |
881 | cd->offset1 = NULL; | 881 | cd->offset1 = NULL; |
882 | } else { | 882 | } else { |
883 | xdr_encode_hyper(cd->offset, (u64) offset); | 883 | xdr_encode_hyper(cd->offset, offset64); |
884 | } | 884 | } |
885 | } | 885 | } |
886 | 886 | ||
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 832673b14587..673a53c014a3 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -228,7 +228,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | |||
228 | struct posix_acl_summary pas; | 228 | struct posix_acl_summary pas; |
229 | unsigned short deny; | 229 | unsigned short deny; |
230 | int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? | 230 | int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? |
231 | NFS4_INHERITANCE_FLAGS : 0); | 231 | NFS4_INHERITANCE_FLAGS | NFS4_ACE_INHERIT_ONLY_ACE : 0); |
232 | 232 | ||
233 | BUG_ON(pacl->a_count < 3); | 233 | BUG_ON(pacl->a_count < 3); |
234 | summarize_posix_acl(pacl, &pas); | 234 | summarize_posix_acl(pacl, &pas); |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9e4067999209..af360705e551 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -750,9 +750,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
750 | status = nfserr_clid_inuse; | 750 | status = nfserr_clid_inuse; |
751 | if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred) | 751 | if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred) |
752 | || conf->cl_addr != sin->sin_addr.s_addr) { | 752 | || conf->cl_addr != sin->sin_addr.s_addr) { |
753 | printk("NFSD: setclientid: string in use by client" | 753 | dprintk("NFSD: setclientid: string in use by client" |
754 | "(clientid %08x/%08x)\n", | 754 | "at %u.%u.%u.%u\n", NIPQUAD(conf->cl_addr)); |
755 | conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id); | ||
756 | goto out; | 755 | goto out; |
757 | } | 756 | } |
758 | } | 757 | } |
@@ -3261,7 +3260,6 @@ __nfs4_state_shutdown(void) | |||
3261 | unhash_delegation(dp); | 3260 | unhash_delegation(dp); |
3262 | } | 3261 | } |
3263 | 3262 | ||
3264 | cancel_delayed_work(&laundromat_work); | ||
3265 | nfsd4_shutdown_recdir(); | 3263 | nfsd4_shutdown_recdir(); |
3266 | nfs4_init = 0; | 3264 | nfs4_init = 0; |
3267 | } | 3265 | } |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index c2660cbfcd96..8d995bcef806 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/stat.h> | 17 | #include <linux/stat.h> |
18 | #include <linux/dcache.h> | 18 | #include <linux/dcache.h> |
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <asm/pgtable.h> | ||
21 | 20 | ||
22 | #include <linux/sunrpc/clnt.h> | 21 | #include <linux/sunrpc/clnt.h> |
23 | #include <linux/sunrpc/svc.h> | 22 | #include <linux/sunrpc/svc.h> |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 93628b02ef5d..875c11443817 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -614,6 +614,27 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, | |||
614 | ocfs2_rw_unlock(inode, 0); | 614 | ocfs2_rw_unlock(inode, 0); |
615 | } | 615 | } |
616 | 616 | ||
617 | /* | ||
618 | * ocfs2_invalidatepage() and ocfs2_releasepage() are shamelessly stolen | ||
619 | * from ext3. PageChecked() bits have been removed as OCFS2 does not | ||
620 | * do journalled data. | ||
621 | */ | ||
622 | static void ocfs2_invalidatepage(struct page *page, unsigned long offset) | ||
623 | { | ||
624 | journal_t *journal = OCFS2_SB(page->mapping->host->i_sb)->journal->j_journal; | ||
625 | |||
626 | journal_invalidatepage(journal, page, offset); | ||
627 | } | ||
628 | |||
629 | static int ocfs2_releasepage(struct page *page, gfp_t wait) | ||
630 | { | ||
631 | journal_t *journal = OCFS2_SB(page->mapping->host->i_sb)->journal->j_journal; | ||
632 | |||
633 | if (!page_has_buffers(page)) | ||
634 | return 0; | ||
635 | return journal_try_to_free_buffers(journal, page, wait); | ||
636 | } | ||
637 | |||
617 | static ssize_t ocfs2_direct_IO(int rw, | 638 | static ssize_t ocfs2_direct_IO(int rw, |
618 | struct kiocb *iocb, | 639 | struct kiocb *iocb, |
619 | const struct iovec *iov, | 640 | const struct iovec *iov, |
@@ -661,5 +682,8 @@ const struct address_space_operations ocfs2_aops = { | |||
661 | .commit_write = ocfs2_commit_write, | 682 | .commit_write = ocfs2_commit_write, |
662 | .bmap = ocfs2_bmap, | 683 | .bmap = ocfs2_bmap, |
663 | .sync_page = block_sync_page, | 684 | .sync_page = block_sync_page, |
664 | .direct_IO = ocfs2_direct_IO | 685 | .direct_IO = ocfs2_direct_IO, |
686 | .invalidatepage = ocfs2_invalidatepage, | ||
687 | .releasepage = ocfs2_releasepage, | ||
688 | .migratepage = buffer_migrate_page, | ||
665 | }; | 689 | }; |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 5a9779bb9236..eba282da500e 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -1234,6 +1234,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, | |||
1234 | const char *page, | 1234 | const char *page, |
1235 | size_t count) | 1235 | size_t count) |
1236 | { | 1236 | { |
1237 | struct task_struct *hb_task; | ||
1237 | long fd; | 1238 | long fd; |
1238 | int sectsize; | 1239 | int sectsize; |
1239 | char *p = (char *)page; | 1240 | char *p = (char *)page; |
@@ -1319,20 +1320,28 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, | |||
1319 | */ | 1320 | */ |
1320 | atomic_set(®->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1); | 1321 | atomic_set(®->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1); |
1321 | 1322 | ||
1322 | reg->hr_task = kthread_run(o2hb_thread, reg, "o2hb-%s", | 1323 | hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s", |
1323 | reg->hr_item.ci_name); | 1324 | reg->hr_item.ci_name); |
1324 | if (IS_ERR(reg->hr_task)) { | 1325 | if (IS_ERR(hb_task)) { |
1325 | ret = PTR_ERR(reg->hr_task); | 1326 | ret = PTR_ERR(hb_task); |
1326 | mlog_errno(ret); | 1327 | mlog_errno(ret); |
1327 | reg->hr_task = NULL; | ||
1328 | goto out; | 1328 | goto out; |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | spin_lock(&o2hb_live_lock); | ||
1332 | reg->hr_task = hb_task; | ||
1333 | spin_unlock(&o2hb_live_lock); | ||
1334 | |||
1331 | ret = wait_event_interruptible(o2hb_steady_queue, | 1335 | ret = wait_event_interruptible(o2hb_steady_queue, |
1332 | atomic_read(®->hr_steady_iterations) == 0); | 1336 | atomic_read(®->hr_steady_iterations) == 0); |
1333 | if (ret) { | 1337 | if (ret) { |
1334 | kthread_stop(reg->hr_task); | 1338 | spin_lock(&o2hb_live_lock); |
1339 | hb_task = reg->hr_task; | ||
1335 | reg->hr_task = NULL; | 1340 | reg->hr_task = NULL; |
1341 | spin_unlock(&o2hb_live_lock); | ||
1342 | |||
1343 | if (hb_task) | ||
1344 | kthread_stop(hb_task); | ||
1336 | goto out; | 1345 | goto out; |
1337 | } | 1346 | } |
1338 | 1347 | ||
@@ -1354,10 +1363,17 @@ out: | |||
1354 | static ssize_t o2hb_region_pid_read(struct o2hb_region *reg, | 1363 | static ssize_t o2hb_region_pid_read(struct o2hb_region *reg, |
1355 | char *page) | 1364 | char *page) |
1356 | { | 1365 | { |
1357 | if (!reg->hr_task) | 1366 | pid_t pid = 0; |
1367 | |||
1368 | spin_lock(&o2hb_live_lock); | ||
1369 | if (reg->hr_task) | ||
1370 | pid = reg->hr_task->pid; | ||
1371 | spin_unlock(&o2hb_live_lock); | ||
1372 | |||
1373 | if (!pid) | ||
1358 | return 0; | 1374 | return 0; |
1359 | 1375 | ||
1360 | return sprintf(page, "%u\n", reg->hr_task->pid); | 1376 | return sprintf(page, "%u\n", pid); |
1361 | } | 1377 | } |
1362 | 1378 | ||
1363 | struct o2hb_region_attribute { | 1379 | struct o2hb_region_attribute { |
@@ -1495,13 +1511,17 @@ out: | |||
1495 | static void o2hb_heartbeat_group_drop_item(struct config_group *group, | 1511 | static void o2hb_heartbeat_group_drop_item(struct config_group *group, |
1496 | struct config_item *item) | 1512 | struct config_item *item) |
1497 | { | 1513 | { |
1514 | struct task_struct *hb_task; | ||
1498 | struct o2hb_region *reg = to_o2hb_region(item); | 1515 | struct o2hb_region *reg = to_o2hb_region(item); |
1499 | 1516 | ||
1500 | /* stop the thread when the user removes the region dir */ | 1517 | /* stop the thread when the user removes the region dir */ |
1501 | if (reg->hr_task) { | 1518 | spin_lock(&o2hb_live_lock); |
1502 | kthread_stop(reg->hr_task); | 1519 | hb_task = reg->hr_task; |
1503 | reg->hr_task = NULL; | 1520 | reg->hr_task = NULL; |
1504 | } | 1521 | spin_unlock(&o2hb_live_lock); |
1522 | |||
1523 | if (hb_task) | ||
1524 | kthread_stop(hb_task); | ||
1505 | 1525 | ||
1506 | config_item_put(item); | 1526 | config_item_put(item); |
1507 | } | 1527 | } |
@@ -1682,7 +1702,7 @@ out: | |||
1682 | } | 1702 | } |
1683 | EXPORT_SYMBOL_GPL(o2hb_register_callback); | 1703 | EXPORT_SYMBOL_GPL(o2hb_register_callback); |
1684 | 1704 | ||
1685 | int o2hb_unregister_callback(struct o2hb_callback_func *hc) | 1705 | void o2hb_unregister_callback(struct o2hb_callback_func *hc) |
1686 | { | 1706 | { |
1687 | BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); | 1707 | BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); |
1688 | 1708 | ||
@@ -1690,15 +1710,13 @@ int o2hb_unregister_callback(struct o2hb_callback_func *hc) | |||
1690 | __builtin_return_address(0), hc); | 1710 | __builtin_return_address(0), hc); |
1691 | 1711 | ||
1692 | if (list_empty(&hc->hc_item)) | 1712 | if (list_empty(&hc->hc_item)) |
1693 | return 0; | 1713 | return; |
1694 | 1714 | ||
1695 | down_write(&o2hb_callback_sem); | 1715 | down_write(&o2hb_callback_sem); |
1696 | 1716 | ||
1697 | list_del_init(&hc->hc_item); | 1717 | list_del_init(&hc->hc_item); |
1698 | 1718 | ||
1699 | up_write(&o2hb_callback_sem); | 1719 | up_write(&o2hb_callback_sem); |
1700 | |||
1701 | return 0; | ||
1702 | } | 1720 | } |
1703 | EXPORT_SYMBOL_GPL(o2hb_unregister_callback); | 1721 | EXPORT_SYMBOL_GPL(o2hb_unregister_callback); |
1704 | 1722 | ||
diff --git a/fs/ocfs2/cluster/heartbeat.h b/fs/ocfs2/cluster/heartbeat.h index cac6223206a9..cc6d40b39771 100644 --- a/fs/ocfs2/cluster/heartbeat.h +++ b/fs/ocfs2/cluster/heartbeat.h | |||
@@ -70,7 +70,7 @@ void o2hb_setup_callback(struct o2hb_callback_func *hc, | |||
70 | void *data, | 70 | void *data, |
71 | int priority); | 71 | int priority); |
72 | int o2hb_register_callback(struct o2hb_callback_func *hc); | 72 | int o2hb_register_callback(struct o2hb_callback_func *hc); |
73 | int o2hb_unregister_callback(struct o2hb_callback_func *hc); | 73 | void o2hb_unregister_callback(struct o2hb_callback_func *hc); |
74 | void o2hb_fill_node_map(unsigned long *map, | 74 | void o2hb_fill_node_map(unsigned long *map, |
75 | unsigned bytes); | 75 | unsigned bytes); |
76 | void o2hb_init(void); | 76 | void o2hb_init(void); |
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 1718215fc018..69caf3e12fea 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
@@ -1638,17 +1638,8 @@ static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num, | |||
1638 | 1638 | ||
1639 | void o2net_unregister_hb_callbacks(void) | 1639 | void o2net_unregister_hb_callbacks(void) |
1640 | { | 1640 | { |
1641 | int ret; | 1641 | o2hb_unregister_callback(&o2net_hb_up); |
1642 | 1642 | o2hb_unregister_callback(&o2net_hb_down); | |
1643 | ret = o2hb_unregister_callback(&o2net_hb_up); | ||
1644 | if (ret < 0) | ||
1645 | mlog(ML_ERROR, "Status return %d unregistering heartbeat up " | ||
1646 | "callback!\n", ret); | ||
1647 | |||
1648 | ret = o2hb_unregister_callback(&o2net_hb_down); | ||
1649 | if (ret < 0) | ||
1650 | mlog(ML_ERROR, "Status return %d unregistering heartbeat down " | ||
1651 | "callback!\n", ret); | ||
1652 | } | 1643 | } |
1653 | 1644 | ||
1654 | int o2net_register_hb_callbacks(void) | 1645 | int o2net_register_hb_callbacks(void) |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 6087c4749fee..c558442a0b44 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -138,8 +138,10 @@ static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm); | |||
138 | 138 | ||
139 | void __dlm_unhash_lockres(struct dlm_lock_resource *lockres) | 139 | void __dlm_unhash_lockres(struct dlm_lock_resource *lockres) |
140 | { | 140 | { |
141 | hlist_del_init(&lockres->hash_node); | 141 | if (!hlist_unhashed(&lockres->hash_node)) { |
142 | dlm_lockres_put(lockres); | 142 | hlist_del_init(&lockres->hash_node); |
143 | dlm_lockres_put(lockres); | ||
144 | } | ||
143 | } | 145 | } |
144 | 146 | ||
145 | void __dlm_insert_lockres(struct dlm_ctxt *dlm, | 147 | void __dlm_insert_lockres(struct dlm_ctxt *dlm, |
@@ -655,6 +657,8 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm) | |||
655 | dlm_kick_thread(dlm, NULL); | 657 | dlm_kick_thread(dlm, NULL); |
656 | 658 | ||
657 | while (dlm_migrate_all_locks(dlm)) { | 659 | while (dlm_migrate_all_locks(dlm)) { |
660 | /* Give dlm_thread time to purge the lockres' */ | ||
661 | msleep(500); | ||
658 | mlog(0, "%s: more migration to do\n", dlm->name); | 662 | mlog(0, "%s: more migration to do\n", dlm->name); |
659 | } | 663 | } |
660 | dlm_mark_domain_leaving(dlm); | 664 | dlm_mark_domain_leaving(dlm); |
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 77e4e6169a0d..6edffca99d98 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
@@ -2424,6 +2424,57 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data) | |||
2424 | dlm_lockres_put(res); | 2424 | dlm_lockres_put(res); |
2425 | } | 2425 | } |
2426 | 2426 | ||
2427 | /* Checks whether the lockres can be migrated. Returns 0 if yes, < 0 | ||
2428 | * if not. If 0, numlocks is set to the number of locks in the lockres. | ||
2429 | */ | ||
2430 | static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm, | ||
2431 | struct dlm_lock_resource *res, | ||
2432 | int *numlocks) | ||
2433 | { | ||
2434 | int ret; | ||
2435 | int i; | ||
2436 | int count = 0; | ||
2437 | struct list_head *queue, *iter; | ||
2438 | struct dlm_lock *lock; | ||
2439 | |||
2440 | assert_spin_locked(&res->spinlock); | ||
2441 | |||
2442 | ret = -EINVAL; | ||
2443 | if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { | ||
2444 | mlog(0, "cannot migrate lockres with unknown owner!\n"); | ||
2445 | goto leave; | ||
2446 | } | ||
2447 | |||
2448 | if (res->owner != dlm->node_num) { | ||
2449 | mlog(0, "cannot migrate lockres this node doesn't own!\n"); | ||
2450 | goto leave; | ||
2451 | } | ||
2452 | |||
2453 | ret = 0; | ||
2454 | queue = &res->granted; | ||
2455 | for (i = 0; i < 3; i++) { | ||
2456 | list_for_each(iter, queue) { | ||
2457 | lock = list_entry(iter, struct dlm_lock, list); | ||
2458 | ++count; | ||
2459 | if (lock->ml.node == dlm->node_num) { | ||
2460 | mlog(0, "found a lock owned by this node still " | ||
2461 | "on the %s queue! will not migrate this " | ||
2462 | "lockres\n", (i == 0 ? "granted" : | ||
2463 | (i == 1 ? "converting" : | ||
2464 | "blocked"))); | ||
2465 | ret = -ENOTEMPTY; | ||
2466 | goto leave; | ||
2467 | } | ||
2468 | } | ||
2469 | queue++; | ||
2470 | } | ||
2471 | |||
2472 | *numlocks = count; | ||
2473 | mlog(0, "migrateable lockres having %d locks\n", *numlocks); | ||
2474 | |||
2475 | leave: | ||
2476 | return ret; | ||
2477 | } | ||
2427 | 2478 | ||
2428 | /* | 2479 | /* |
2429 | * DLM_MIGRATE_LOCKRES | 2480 | * DLM_MIGRATE_LOCKRES |
@@ -2437,14 +2488,12 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, | |||
2437 | struct dlm_master_list_entry *mle = NULL; | 2488 | struct dlm_master_list_entry *mle = NULL; |
2438 | struct dlm_master_list_entry *oldmle = NULL; | 2489 | struct dlm_master_list_entry *oldmle = NULL; |
2439 | struct dlm_migratable_lockres *mres = NULL; | 2490 | struct dlm_migratable_lockres *mres = NULL; |
2440 | int ret = -EINVAL; | 2491 | int ret = 0; |
2441 | const char *name; | 2492 | const char *name; |
2442 | unsigned int namelen; | 2493 | unsigned int namelen; |
2443 | int mle_added = 0; | 2494 | int mle_added = 0; |
2444 | struct list_head *queue, *iter; | 2495 | int numlocks; |
2445 | int i; | 2496 | int wake = 0; |
2446 | struct dlm_lock *lock; | ||
2447 | int empty = 1, wake = 0; | ||
2448 | 2497 | ||
2449 | if (!dlm_grab(dlm)) | 2498 | if (!dlm_grab(dlm)) |
2450 | return -EINVAL; | 2499 | return -EINVAL; |
@@ -2458,42 +2507,16 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, | |||
2458 | * ensure this lockres is a proper candidate for migration | 2507 | * ensure this lockres is a proper candidate for migration |
2459 | */ | 2508 | */ |
2460 | spin_lock(&res->spinlock); | 2509 | spin_lock(&res->spinlock); |
2461 | if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { | 2510 | ret = dlm_is_lockres_migrateable(dlm, res, &numlocks); |
2462 | mlog(0, "cannot migrate lockres with unknown owner!\n"); | 2511 | if (ret < 0) { |
2463 | spin_unlock(&res->spinlock); | ||
2464 | goto leave; | ||
2465 | } | ||
2466 | if (res->owner != dlm->node_num) { | ||
2467 | mlog(0, "cannot migrate lockres this node doesn't own!\n"); | ||
2468 | spin_unlock(&res->spinlock); | 2512 | spin_unlock(&res->spinlock); |
2469 | goto leave; | 2513 | goto leave; |
2470 | } | 2514 | } |
2471 | mlog(0, "checking queues...\n"); | ||
2472 | queue = &res->granted; | ||
2473 | for (i=0; i<3; i++) { | ||
2474 | list_for_each(iter, queue) { | ||
2475 | lock = list_entry (iter, struct dlm_lock, list); | ||
2476 | empty = 0; | ||
2477 | if (lock->ml.node == dlm->node_num) { | ||
2478 | mlog(0, "found a lock owned by this node " | ||
2479 | "still on the %s queue! will not " | ||
2480 | "migrate this lockres\n", | ||
2481 | i==0 ? "granted" : | ||
2482 | (i==1 ? "converting" : "blocked")); | ||
2483 | spin_unlock(&res->spinlock); | ||
2484 | ret = -ENOTEMPTY; | ||
2485 | goto leave; | ||
2486 | } | ||
2487 | } | ||
2488 | queue++; | ||
2489 | } | ||
2490 | mlog(0, "all locks on this lockres are nonlocal. continuing\n"); | ||
2491 | spin_unlock(&res->spinlock); | 2515 | spin_unlock(&res->spinlock); |
2492 | 2516 | ||
2493 | /* no work to do */ | 2517 | /* no work to do */ |
2494 | if (empty) { | 2518 | if (numlocks == 0) { |
2495 | mlog(0, "no locks were found on this lockres! done!\n"); | 2519 | mlog(0, "no locks were found on this lockres! done!\n"); |
2496 | ret = 0; | ||
2497 | goto leave; | 2520 | goto leave; |
2498 | } | 2521 | } |
2499 | 2522 | ||
@@ -2729,15 +2752,26 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) | |||
2729 | { | 2752 | { |
2730 | int ret; | 2753 | int ret; |
2731 | int lock_dropped = 0; | 2754 | int lock_dropped = 0; |
2755 | int numlocks; | ||
2732 | 2756 | ||
2757 | spin_lock(&res->spinlock); | ||
2733 | if (res->owner != dlm->node_num) { | 2758 | if (res->owner != dlm->node_num) { |
2734 | if (!__dlm_lockres_unused(res)) { | 2759 | if (!__dlm_lockres_unused(res)) { |
2735 | mlog(ML_ERROR, "%s:%.*s: this node is not master, " | 2760 | mlog(ML_ERROR, "%s:%.*s: this node is not master, " |
2736 | "trying to free this but locks remain\n", | 2761 | "trying to free this but locks remain\n", |
2737 | dlm->name, res->lockname.len, res->lockname.name); | 2762 | dlm->name, res->lockname.len, res->lockname.name); |
2738 | } | 2763 | } |
2764 | spin_unlock(&res->spinlock); | ||
2765 | goto leave; | ||
2766 | } | ||
2767 | |||
2768 | /* No need to migrate a lockres having no locks */ | ||
2769 | ret = dlm_is_lockres_migrateable(dlm, res, &numlocks); | ||
2770 | if (ret >= 0 && numlocks == 0) { | ||
2771 | spin_unlock(&res->spinlock); | ||
2739 | goto leave; | 2772 | goto leave; |
2740 | } | 2773 | } |
2774 | spin_unlock(&res->spinlock); | ||
2741 | 2775 | ||
2742 | /* Wheee! Migrate lockres here! Will sleep so drop spinlock. */ | 2776 | /* Wheee! Migrate lockres here! Will sleep so drop spinlock. */ |
2743 | spin_unlock(&dlm->spinlock); | 2777 | spin_unlock(&dlm->spinlock); |
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index 8ffa0916eb86..2b264c6ba039 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c | |||
@@ -256,18 +256,14 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm, | |||
256 | break; | 256 | break; |
257 | } | 257 | } |
258 | 258 | ||
259 | mlog(0, "removing lockres %.*s:%p from purgelist\n", | 259 | dlm_lockres_get(lockres); |
260 | lockres->lockname.len, lockres->lockname.name, lockres); | ||
261 | list_del_init(&lockres->purge); | ||
262 | dlm_lockres_put(lockres); | ||
263 | dlm->purge_count--; | ||
264 | 260 | ||
265 | /* This may drop and reacquire the dlm spinlock if it | 261 | /* This may drop and reacquire the dlm spinlock if it |
266 | * has to do migration. */ | 262 | * has to do migration. */ |
267 | mlog(0, "calling dlm_purge_lockres!\n"); | ||
268 | if (dlm_purge_lockres(dlm, lockres)) | 263 | if (dlm_purge_lockres(dlm, lockres)) |
269 | BUG(); | 264 | BUG(); |
270 | mlog(0, "DONE calling dlm_purge_lockres!\n"); | 265 | |
266 | dlm_lockres_put(lockres); | ||
271 | 267 | ||
272 | /* Avoid adding any scheduling latencies */ | 268 | /* Avoid adding any scheduling latencies */ |
273 | cond_resched_lock(&dlm->spinlock); | 269 | cond_resched_lock(&dlm->spinlock); |
diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c index 8fc52d6d0ce7..b25ef63781ba 100644 --- a/fs/ocfs2/heartbeat.c +++ b/fs/ocfs2/heartbeat.c | |||
@@ -164,8 +164,10 @@ int ocfs2_register_hb_callbacks(struct ocfs2_super *osb) | |||
164 | } | 164 | } |
165 | 165 | ||
166 | status = o2hb_register_callback(&osb->osb_hb_up); | 166 | status = o2hb_register_callback(&osb->osb_hb_up); |
167 | if (status < 0) | 167 | if (status < 0) { |
168 | mlog_errno(status); | 168 | mlog_errno(status); |
169 | o2hb_unregister_callback(&osb->osb_hb_down); | ||
170 | } | ||
169 | 171 | ||
170 | bail: | 172 | bail: |
171 | return status; | 173 | return status; |
@@ -173,18 +175,11 @@ bail: | |||
173 | 175 | ||
174 | void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb) | 176 | void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb) |
175 | { | 177 | { |
176 | int status; | ||
177 | |||
178 | if (ocfs2_mount_local(osb)) | 178 | if (ocfs2_mount_local(osb)) |
179 | return; | 179 | return; |
180 | 180 | ||
181 | status = o2hb_unregister_callback(&osb->osb_hb_down); | 181 | o2hb_unregister_callback(&osb->osb_hb_down); |
182 | if (status < 0) | 182 | o2hb_unregister_callback(&osb->osb_hb_up); |
183 | mlog_errno(status); | ||
184 | |||
185 | status = o2hb_unregister_callback(&osb->osb_hb_up); | ||
186 | if (status < 0) | ||
187 | mlog_errno(status); | ||
188 | } | 183 | } |
189 | 184 | ||
190 | void ocfs2_stop_heartbeat(struct ocfs2_super *osb) | 185 | void ocfs2_stop_heartbeat(struct ocfs2_super *osb) |
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig index 74552c60b671..6e8bb66fe619 100644 --- a/fs/partitions/Kconfig +++ b/fs/partitions/Kconfig | |||
@@ -235,5 +235,4 @@ config EFI_PARTITION | |||
235 | select CRC32 | 235 | select CRC32 |
236 | help | 236 | help |
237 | Say Y here if you would like to use hard disks under Linux which | 237 | Say Y here if you would like to use hard disks under Linux which |
238 | were partitioned using EFI GPT. Presently only useful on the | 238 | were partitioned using EFI GPT. |
239 | IA-64 platform. | ||
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index e46d237b10f9..8a7d0035ad7a 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -541,7 +541,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
541 | if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) | 541 | if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) |
542 | return 0; | 542 | return 0; |
543 | if (IS_ERR(state)) /* I/O error reading the partition table */ | 543 | if (IS_ERR(state)) /* I/O error reading the partition table */ |
544 | return PTR_ERR(state); | 544 | return -EIO; |
545 | for (p = 1; p < state->limit; p++) { | 545 | for (p = 1; p < state->limit; p++) { |
546 | sector_t size = state->parts[p].size; | 546 | sector_t size = state->parts[p].size; |
547 | sector_t from = state->parts[p].from; | 547 | sector_t from = state->parts[p].from; |
diff --git a/fs/proc/Makefile b/fs/proc/Makefile index a6b3a8f878f0..bce38e3f06cb 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile | |||
@@ -8,8 +8,9 @@ proc-y := nommu.o task_nommu.o | |||
8 | proc-$(CONFIG_MMU) := mmu.o task_mmu.o | 8 | proc-$(CONFIG_MMU) := mmu.o task_mmu.o |
9 | 9 | ||
10 | proc-y += inode.o root.o base.o generic.o array.o \ | 10 | proc-y += inode.o root.o base.o generic.o array.o \ |
11 | proc_tty.o proc_misc.o proc_sysctl.o | 11 | proc_tty.o proc_misc.o |
12 | 12 | ||
13 | proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o | ||
13 | proc-$(CONFIG_PROC_KCORE) += kcore.o | 14 | proc-$(CONFIG_PROC_KCORE) += kcore.o |
14 | proc-$(CONFIG_PROC_VMCORE) += vmcore.o | 15 | proc-$(CONFIG_PROC_VMCORE) += vmcore.o |
15 | proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o | 16 | proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 01f7769da8e6..989af5e55d1b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1558,29 +1558,20 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, | |||
1558 | size_t count, loff_t *ppos) | 1558 | size_t count, loff_t *ppos) |
1559 | { | 1559 | { |
1560 | struct inode * inode = file->f_path.dentry->d_inode; | 1560 | struct inode * inode = file->f_path.dentry->d_inode; |
1561 | unsigned long page; | 1561 | char *p = NULL; |
1562 | ssize_t length; | 1562 | ssize_t length; |
1563 | struct task_struct *task = get_proc_task(inode); | 1563 | struct task_struct *task = get_proc_task(inode); |
1564 | 1564 | ||
1565 | length = -ESRCH; | ||
1566 | if (!task) | 1565 | if (!task) |
1567 | goto out_no_task; | 1566 | return -ESRCH; |
1568 | |||
1569 | if (count > PAGE_SIZE) | ||
1570 | count = PAGE_SIZE; | ||
1571 | length = -ENOMEM; | ||
1572 | if (!(page = __get_free_page(GFP_KERNEL))) | ||
1573 | goto out; | ||
1574 | 1567 | ||
1575 | length = security_getprocattr(task, | 1568 | length = security_getprocattr(task, |
1576 | (char*)file->f_path.dentry->d_name.name, | 1569 | (char*)file->f_path.dentry->d_name.name, |
1577 | (void*)page, count); | 1570 | &p); |
1578 | if (length >= 0) | ||
1579 | length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); | ||
1580 | free_page(page); | ||
1581 | out: | ||
1582 | put_task_struct(task); | 1571 | put_task_struct(task); |
1583 | out_no_task: | 1572 | if (length > 0) |
1573 | length = simple_read_from_buffer(buf, count, ppos, p, length); | ||
1574 | kfree(p); | ||
1584 | return length; | 1575 | return length; |
1585 | } | 1576 | } |
1586 | 1577 | ||
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index c932aa65e198..f771889183c3 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -11,7 +11,11 @@ | |||
11 | 11 | ||
12 | #include <linux/proc_fs.h> | 12 | #include <linux/proc_fs.h> |
13 | 13 | ||
14 | #ifdef CONFIG_PROC_SYSCTL | ||
14 | extern int proc_sys_init(void); | 15 | extern int proc_sys_init(void); |
16 | #else | ||
17 | static inline void proc_sys_init(void) { } | ||
18 | #endif | ||
15 | 19 | ||
16 | struct vmalloc_info { | 20 | struct vmalloc_info { |
17 | unsigned long used; | 21 | unsigned long used; |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 5834a744c2a9..41f17037f738 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -79,9 +79,7 @@ void __init proc_root_init(void) | |||
79 | proc_device_tree_init(); | 79 | proc_device_tree_init(); |
80 | #endif | 80 | #endif |
81 | proc_bus = proc_mkdir("bus", NULL); | 81 | proc_bus = proc_mkdir("bus", NULL); |
82 | #ifdef CONFIG_SYSCTL | ||
83 | proc_sys_init(); | 82 | proc_sys_init(); |
84 | #endif | ||
85 | } | 83 | } |
86 | 84 | ||
87 | static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat | 85 | static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat |
diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c index b9b423b22a8b..9475557ab499 100644 --- a/fs/reiserfs/item_ops.c +++ b/fs/reiserfs/item_ops.c | |||
@@ -23,7 +23,7 @@ static void sd_decrement_key(struct cpu_key *key) | |||
23 | { | 23 | { |
24 | key->on_disk_key.k_objectid--; | 24 | key->on_disk_key.k_objectid--; |
25 | set_cpu_key_k_type(key, TYPE_ANY); | 25 | set_cpu_key_k_type(key, TYPE_ANY); |
26 | set_cpu_key_k_offset(key, (loff_t) (-1)); | 26 | set_cpu_key_k_offset(key, (loff_t)(~0ULL >> 1)); |
27 | } | 27 | } |
28 | 28 | ||
29 | static int sd_is_left_mergeable(struct reiserfs_key *key, unsigned long bsize) | 29 | static int sd_is_left_mergeable(struct reiserfs_key *key, unsigned long bsize) |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index f01389fd162e..c8178b7b9212 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -54,82 +54,48 @@ | |||
54 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char | 54 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char |
55 | *prefix); | 55 | *prefix); |
56 | 56 | ||
57 | static struct dentry *create_xa_root(struct super_block *sb) | 57 | /* Returns the dentry referring to the root of the extended attribute |
58 | * directory tree. If it has already been retrieved, it is used. If it | ||
59 | * hasn't been created and the flags indicate creation is allowed, we | ||
60 | * attempt to create it. On error, we return a pointer-encoded error. | ||
61 | */ | ||
62 | static struct dentry *get_xa_root(struct super_block *sb, int flags) | ||
58 | { | 63 | { |
59 | struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root); | 64 | struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root); |
60 | struct dentry *xaroot; | 65 | struct dentry *xaroot; |
61 | 66 | ||
62 | /* This needs to be created at mount-time */ | 67 | /* This needs to be created at mount-time */ |
63 | if (!privroot) | 68 | if (!privroot) |
64 | return ERR_PTR(-EOPNOTSUPP); | 69 | return ERR_PTR(-ENODATA); |
65 | 70 | ||
66 | xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); | 71 | mutex_lock(&privroot->d_inode->i_mutex); |
67 | if (IS_ERR(xaroot)) { | 72 | if (REISERFS_SB(sb)->xattr_root) { |
73 | xaroot = dget(REISERFS_SB(sb)->xattr_root); | ||
68 | goto out; | 74 | goto out; |
69 | } else if (!xaroot->d_inode) { | ||
70 | int err; | ||
71 | mutex_lock(&privroot->d_inode->i_mutex); | ||
72 | err = | ||
73 | privroot->d_inode->i_op->mkdir(privroot->d_inode, xaroot, | ||
74 | 0700); | ||
75 | mutex_unlock(&privroot->d_inode->i_mutex); | ||
76 | |||
77 | if (err) { | ||
78 | dput(xaroot); | ||
79 | dput(privroot); | ||
80 | return ERR_PTR(err); | ||
81 | } | ||
82 | REISERFS_SB(sb)->xattr_root = dget(xaroot); | ||
83 | } | 75 | } |
84 | 76 | ||
85 | out: | ||
86 | dput(privroot); | ||
87 | return xaroot; | ||
88 | } | ||
89 | |||
90 | /* This will return a dentry, or error, refering to the xa root directory. | ||
91 | * If the xa root doesn't exist yet, the dentry will be returned without | ||
92 | * an associated inode. This dentry can be used with ->mkdir to create | ||
93 | * the xa directory. */ | ||
94 | static struct dentry *__get_xa_root(struct super_block *s) | ||
95 | { | ||
96 | struct dentry *privroot = dget(REISERFS_SB(s)->priv_root); | ||
97 | struct dentry *xaroot = NULL; | ||
98 | |||
99 | if (IS_ERR(privroot) || !privroot) | ||
100 | return privroot; | ||
101 | |||
102 | xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); | 77 | xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); |
103 | if (IS_ERR(xaroot)) { | 78 | if (IS_ERR(xaroot)) { |
104 | goto out; | 79 | goto out; |
105 | } else if (!xaroot->d_inode) { | 80 | } else if (!xaroot->d_inode) { |
106 | dput(xaroot); | 81 | int err = -ENODATA; |
107 | xaroot = NULL; | 82 | if (flags == 0 || flags & XATTR_CREATE) |
108 | goto out; | 83 | err = privroot->d_inode->i_op->mkdir(privroot->d_inode, |
84 | xaroot, 0700); | ||
85 | if (err) { | ||
86 | dput(xaroot); | ||
87 | xaroot = ERR_PTR(err); | ||
88 | goto out; | ||
89 | } | ||
109 | } | 90 | } |
110 | 91 | REISERFS_SB(sb)->xattr_root = dget(xaroot); | |
111 | REISERFS_SB(s)->xattr_root = dget(xaroot); | ||
112 | 92 | ||
113 | out: | 93 | out: |
94 | mutex_unlock(&privroot->d_inode->i_mutex); | ||
114 | dput(privroot); | 95 | dput(privroot); |
115 | return xaroot; | 96 | return xaroot; |
116 | } | 97 | } |
117 | 98 | ||
118 | /* Returns the dentry (or NULL) referring to the root of the extended | ||
119 | * attribute directory tree. If it has already been retrieved, it is used. | ||
120 | * Otherwise, we attempt to retrieve it from disk. It may also return | ||
121 | * a pointer-encoded error. | ||
122 | */ | ||
123 | static inline struct dentry *get_xa_root(struct super_block *s) | ||
124 | { | ||
125 | struct dentry *dentry = dget(REISERFS_SB(s)->xattr_root); | ||
126 | |||
127 | if (!dentry) | ||
128 | dentry = __get_xa_root(s); | ||
129 | |||
130 | return dentry; | ||
131 | } | ||
132 | |||
133 | /* Opens the directory corresponding to the inode's extended attribute store. | 99 | /* Opens the directory corresponding to the inode's extended attribute store. |
134 | * If flags allow, the tree to the directory may be created. If creation is | 100 | * If flags allow, the tree to the directory may be created. If creation is |
135 | * prohibited, -ENODATA is returned. */ | 101 | * prohibited, -ENODATA is returned. */ |
@@ -138,21 +104,11 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags) | |||
138 | struct dentry *xaroot, *xadir; | 104 | struct dentry *xaroot, *xadir; |
139 | char namebuf[17]; | 105 | char namebuf[17]; |
140 | 106 | ||
141 | xaroot = get_xa_root(inode->i_sb); | 107 | xaroot = get_xa_root(inode->i_sb, flags); |
142 | if (IS_ERR(xaroot)) { | 108 | if (IS_ERR(xaroot)) |
143 | return xaroot; | 109 | return xaroot; |
144 | } else if (!xaroot) { | ||
145 | if (flags == 0 || flags & XATTR_CREATE) { | ||
146 | xaroot = create_xa_root(inode->i_sb); | ||
147 | if (IS_ERR(xaroot)) | ||
148 | return xaroot; | ||
149 | } | ||
150 | if (!xaroot) | ||
151 | return ERR_PTR(-ENODATA); | ||
152 | } | ||
153 | 110 | ||
154 | /* ok, we have xaroot open */ | 111 | /* ok, we have xaroot open */ |
155 | |||
156 | snprintf(namebuf, sizeof(namebuf), "%X.%X", | 112 | snprintf(namebuf, sizeof(namebuf), "%X.%X", |
157 | le32_to_cpu(INODE_PKEY(inode)->k_objectid), | 113 | le32_to_cpu(INODE_PKEY(inode)->k_objectid), |
158 | inode->i_generation); | 114 | inode->i_generation); |
@@ -821,7 +777,7 @@ int reiserfs_delete_xattrs(struct inode *inode) | |||
821 | 777 | ||
822 | /* Leftovers besides . and .. -- that's not good. */ | 778 | /* Leftovers besides . and .. -- that's not good. */ |
823 | if (dir->d_inode->i_nlink <= 2) { | 779 | if (dir->d_inode->i_nlink <= 2) { |
824 | root = get_xa_root(inode->i_sb); | 780 | root = get_xa_root(inode->i_sb, XATTR_REPLACE); |
825 | reiserfs_write_lock_xattrs(inode->i_sb); | 781 | reiserfs_write_lock_xattrs(inode->i_sb); |
826 | err = vfs_rmdir(root->d_inode, dir); | 782 | err = vfs_rmdir(root->d_inode, dir); |
827 | reiserfs_write_unlock_xattrs(inode->i_sb); | 783 | reiserfs_write_unlock_xattrs(inode->i_sb); |
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c index 42261dbdf60f..723f7c667661 100644 --- a/fs/smbfs/request.c +++ b/fs/smbfs/request.c | |||
@@ -181,6 +181,7 @@ static int smb_setup_request(struct smb_request *req) | |||
181 | req->rq_errno = 0; | 181 | req->rq_errno = 0; |
182 | req->rq_fragment = 0; | 182 | req->rq_fragment = 0; |
183 | kfree(req->rq_trans2buffer); | 183 | kfree(req->rq_trans2buffer); |
184 | req->rq_trans2buffer = NULL; | ||
184 | 185 | ||
185 | return 0; | 186 | return 0; |
186 | } | 187 | } |
diff --git a/fs/splice.c b/fs/splice.c index 2fca6ebf4cc2..5428b0ff3b6f 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -576,76 +576,21 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
576 | if (this_len + offset > PAGE_CACHE_SIZE) | 576 | if (this_len + offset > PAGE_CACHE_SIZE) |
577 | this_len = PAGE_CACHE_SIZE - offset; | 577 | this_len = PAGE_CACHE_SIZE - offset; |
578 | 578 | ||
579 | /* | ||
580 | * Reuse buf page, if SPLICE_F_MOVE is set and we are doing a full | ||
581 | * page. | ||
582 | */ | ||
583 | if ((sd->flags & SPLICE_F_MOVE) && this_len == PAGE_CACHE_SIZE) { | ||
584 | /* | ||
585 | * If steal succeeds, buf->page is now pruned from the | ||
586 | * pagecache and we can reuse it. The page will also be | ||
587 | * locked on successful return. | ||
588 | */ | ||
589 | if (buf->ops->steal(pipe, buf)) | ||
590 | goto find_page; | ||
591 | |||
592 | page = buf->page; | ||
593 | if (add_to_page_cache(page, mapping, index, GFP_KERNEL)) { | ||
594 | unlock_page(page); | ||
595 | goto find_page; | ||
596 | } | ||
597 | |||
598 | page_cache_get(page); | ||
599 | |||
600 | if (!(buf->flags & PIPE_BUF_FLAG_LRU)) | ||
601 | lru_cache_add(page); | ||
602 | } else { | ||
603 | find_page: | 579 | find_page: |
604 | page = find_lock_page(mapping, index); | 580 | page = find_lock_page(mapping, index); |
605 | if (!page) { | 581 | if (!page) { |
606 | ret = -ENOMEM; | 582 | ret = -ENOMEM; |
607 | page = page_cache_alloc_cold(mapping); | 583 | page = page_cache_alloc_cold(mapping); |
608 | if (unlikely(!page)) | 584 | if (unlikely(!page)) |
609 | goto out_ret; | 585 | goto out_ret; |
610 | |||
611 | /* | ||
612 | * This will also lock the page | ||
613 | */ | ||
614 | ret = add_to_page_cache_lru(page, mapping, index, | ||
615 | GFP_KERNEL); | ||
616 | if (unlikely(ret)) | ||
617 | goto out; | ||
618 | } | ||
619 | 586 | ||
620 | /* | 587 | /* |
621 | * We get here with the page locked. If the page is also | 588 | * This will also lock the page |
622 | * uptodate, we don't need to do more. If it isn't, we | ||
623 | * may need to bring it in if we are not going to overwrite | ||
624 | * the full page. | ||
625 | */ | 589 | */ |
626 | if (!PageUptodate(page)) { | 590 | ret = add_to_page_cache_lru(page, mapping, index, |
627 | if (this_len < PAGE_CACHE_SIZE) { | 591 | GFP_KERNEL); |
628 | ret = mapping->a_ops->readpage(file, page); | 592 | if (unlikely(ret)) |
629 | if (unlikely(ret)) | 593 | goto out; |
630 | goto out; | ||
631 | |||
632 | lock_page(page); | ||
633 | |||
634 | if (!PageUptodate(page)) { | ||
635 | /* | ||
636 | * Page got invalidated, repeat. | ||
637 | */ | ||
638 | if (!page->mapping) { | ||
639 | unlock_page(page); | ||
640 | page_cache_release(page); | ||
641 | goto find_page; | ||
642 | } | ||
643 | ret = -EIO; | ||
644 | goto out; | ||
645 | } | ||
646 | } else | ||
647 | SetPageUptodate(page); | ||
648 | } | ||
649 | } | 594 | } |
650 | 595 | ||
651 | ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); | 596 | ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); |
@@ -682,18 +627,25 @@ find_page: | |||
682 | } | 627 | } |
683 | 628 | ||
684 | ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len); | 629 | ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len); |
685 | if (!ret) { | 630 | if (ret) { |
631 | if (ret == AOP_TRUNCATED_PAGE) { | ||
632 | page_cache_release(page); | ||
633 | goto find_page; | ||
634 | } | ||
635 | if (ret < 0) | ||
636 | goto out; | ||
686 | /* | 637 | /* |
687 | * Return the number of bytes written and mark page as | 638 | * Partial write has happened, so 'ret' already initialized by |
688 | * accessed, we are now done! | 639 | * number of bytes written, Where is nothing we have to do here. |
689 | */ | 640 | */ |
641 | } else | ||
690 | ret = this_len; | 642 | ret = this_len; |
691 | mark_page_accessed(page); | 643 | /* |
692 | balance_dirty_pages_ratelimited(mapping); | 644 | * Return the number of bytes written and mark page as |
693 | } else if (ret == AOP_TRUNCATED_PAGE) { | 645 | * accessed, we are now done! |
694 | page_cache_release(page); | 646 | */ |
695 | goto find_page; | 647 | mark_page_accessed(page); |
696 | } | 648 | balance_dirty_pages_ratelimited(mapping); |
697 | out: | 649 | out: |
698 | page_cache_release(page); | 650 | page_cache_release(page); |
699 | unlock_page(page); | 651 | unlock_page(page); |
@@ -706,9 +658,9 @@ out_ret: | |||
706 | * key here is the 'actor' worker passed in that actually moves the data | 658 | * key here is the 'actor' worker passed in that actually moves the data |
707 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. | 659 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. |
708 | */ | 660 | */ |
709 | static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | 661 | ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, |
710 | struct file *out, loff_t *ppos, size_t len, | 662 | struct file *out, loff_t *ppos, size_t len, |
711 | unsigned int flags, splice_actor *actor) | 663 | unsigned int flags, splice_actor *actor) |
712 | { | 664 | { |
713 | int ret, do_wakeup, err; | 665 | int ret, do_wakeup, err; |
714 | struct splice_desc sd; | 666 | struct splice_desc sd; |
@@ -802,6 +754,7 @@ static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
802 | 754 | ||
803 | return ret; | 755 | return ret; |
804 | } | 756 | } |
757 | EXPORT_SYMBOL(__splice_from_pipe); | ||
805 | 758 | ||
806 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | 759 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, |
807 | loff_t *ppos, size_t len, unsigned int flags, | 760 | loff_t *ppos, size_t len, unsigned int flags, |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 8d4d839a9d88..fc4633378dc0 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -168,12 +168,12 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
168 | ssize_t retval = 0; | 168 | ssize_t retval = 0; |
169 | 169 | ||
170 | down(&buffer->sem); | 170 | down(&buffer->sem); |
171 | if (buffer->orphaned) { | ||
172 | retval = -ENODEV; | ||
173 | goto out; | ||
174 | } | ||
175 | if (buffer->needs_read_fill) { | 171 | if (buffer->needs_read_fill) { |
176 | if ((retval = fill_read_buffer(file->f_path.dentry,buffer))) | 172 | if (buffer->orphaned) |
173 | retval = -ENODEV; | ||
174 | else | ||
175 | retval = fill_read_buffer(file->f_path.dentry,buffer); | ||
176 | if (retval) | ||
177 | goto out; | 177 | goto out; |
178 | } | 178 | } |
179 | pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", | 179 | pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", |
@@ -629,6 +629,60 @@ void sysfs_remove_file_from_group(struct kobject *kobj, | |||
629 | } | 629 | } |
630 | EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); | 630 | EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); |
631 | 631 | ||
632 | struct sysfs_schedule_callback_struct { | ||
633 | struct kobject *kobj; | ||
634 | void (*func)(void *); | ||
635 | void *data; | ||
636 | struct work_struct work; | ||
637 | }; | ||
638 | |||
639 | static void sysfs_schedule_callback_work(struct work_struct *work) | ||
640 | { | ||
641 | struct sysfs_schedule_callback_struct *ss = container_of(work, | ||
642 | struct sysfs_schedule_callback_struct, work); | ||
643 | |||
644 | (ss->func)(ss->data); | ||
645 | kobject_put(ss->kobj); | ||
646 | kfree(ss); | ||
647 | } | ||
648 | |||
649 | /** | ||
650 | * sysfs_schedule_callback - helper to schedule a callback for a kobject | ||
651 | * @kobj: object we're acting for. | ||
652 | * @func: callback function to invoke later. | ||
653 | * @data: argument to pass to @func. | ||
654 | * | ||
655 | * sysfs attribute methods must not unregister themselves or their parent | ||
656 | * kobject (which would amount to the same thing). Attempts to do so will | ||
657 | * deadlock, since unregistration is mutually exclusive with driver | ||
658 | * callbacks. | ||
659 | * | ||
660 | * Instead methods can call this routine, which will attempt to allocate | ||
661 | * and schedule a workqueue request to call back @func with @data as its | ||
662 | * argument in the workqueue's process context. @kobj will be pinned | ||
663 | * until @func returns. | ||
664 | * | ||
665 | * Returns 0 if the request was submitted, -ENOMEM if storage could not | ||
666 | * be allocated. | ||
667 | */ | ||
668 | int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), | ||
669 | void *data) | ||
670 | { | ||
671 | struct sysfs_schedule_callback_struct *ss; | ||
672 | |||
673 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); | ||
674 | if (!ss) | ||
675 | return -ENOMEM; | ||
676 | kobject_get(kobj); | ||
677 | ss->kobj = kobj; | ||
678 | ss->func = func; | ||
679 | ss->data = data; | ||
680 | INIT_WORK(&ss->work, sysfs_schedule_callback_work); | ||
681 | schedule_work(&ss->work); | ||
682 | return 0; | ||
683 | } | ||
684 | EXPORT_SYMBOL_GPL(sysfs_schedule_callback); | ||
685 | |||
632 | 686 | ||
633 | EXPORT_SYMBOL_GPL(sysfs_create_file); | 687 | EXPORT_SYMBOL_GPL(sysfs_create_file); |
634 | EXPORT_SYMBOL_GPL(sysfs_remove_file); | 688 | EXPORT_SYMBOL_GPL(sysfs_remove_file); |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index ccb7d722c558..4de5c6b89918 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -222,13 +222,17 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd) | |||
222 | 222 | ||
223 | static inline void orphan_all_buffers(struct inode *node) | 223 | static inline void orphan_all_buffers(struct inode *node) |
224 | { | 224 | { |
225 | struct sysfs_buffer_collection *set = node->i_private; | 225 | struct sysfs_buffer_collection *set; |
226 | struct sysfs_buffer *buf; | 226 | struct sysfs_buffer *buf; |
227 | 227 | ||
228 | mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD); | 228 | mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD); |
229 | if (node->i_private) { | 229 | set = node->i_private; |
230 | list_for_each_entry(buf, &set->associates, associates) | 230 | if (set) { |
231 | list_for_each_entry(buf, &set->associates, associates) { | ||
232 | down(&buf->sem); | ||
231 | buf->orphaned = 1; | 233 | buf->orphaned = 1; |
234 | up(&buf->sem); | ||
235 | } | ||
232 | } | 236 | } |
233 | mutex_unlock(&node->i_mutex); | 237 | mutex_unlock(&node->i_mutex); |
234 | } | 238 | } |
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index bcc44084e004..841ac25fd950 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
@@ -244,62 +244,87 @@ failed: | |||
244 | * We can come here from ufs_writepage or ufs_prepare_write, | 244 | * We can come here from ufs_writepage or ufs_prepare_write, |
245 | * locked_page is argument of these functions, so we already lock it. | 245 | * locked_page is argument of these functions, so we already lock it. |
246 | */ | 246 | */ |
247 | static void ufs_change_blocknr(struct inode *inode, unsigned int beg, | 247 | static void ufs_change_blocknr(struct inode *inode, sector_t beg, |
248 | unsigned int count, unsigned int oldb, | 248 | unsigned int count, sector_t oldb, |
249 | unsigned int newb, struct page *locked_page) | 249 | sector_t newb, struct page *locked_page) |
250 | { | 250 | { |
251 | const unsigned mask = (1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1; | 251 | const unsigned blks_per_page = |
252 | 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
253 | const unsigned mask = blks_per_page - 1; | ||
252 | struct address_space * const mapping = inode->i_mapping; | 254 | struct address_space * const mapping = inode->i_mapping; |
253 | pgoff_t index, cur_index; | 255 | pgoff_t index, cur_index, last_index; |
254 | unsigned end, pos, j; | 256 | unsigned pos, j, lblock; |
257 | sector_t end, i; | ||
255 | struct page *page; | 258 | struct page *page; |
256 | struct buffer_head *head, *bh; | 259 | struct buffer_head *head, *bh; |
257 | 260 | ||
258 | UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n", | 261 | UFSD("ENTER, ino %lu, count %u, oldb %llu, newb %llu\n", |
259 | inode->i_ino, count, oldb, newb); | 262 | inode->i_ino, count, |
263 | (unsigned long long)oldb, (unsigned long long)newb); | ||
260 | 264 | ||
261 | BUG_ON(!locked_page); | 265 | BUG_ON(!locked_page); |
262 | BUG_ON(!PageLocked(locked_page)); | 266 | BUG_ON(!PageLocked(locked_page)); |
263 | 267 | ||
264 | cur_index = locked_page->index; | 268 | cur_index = locked_page->index; |
265 | 269 | end = count + beg; | |
266 | for (end = count + beg; beg < end; beg = (beg | mask) + 1) { | 270 | last_index = end >> (PAGE_CACHE_SHIFT - inode->i_blkbits); |
267 | index = beg >> (PAGE_CACHE_SHIFT - inode->i_blkbits); | 271 | for (i = beg; i < end; i = (i | mask) + 1) { |
272 | index = i >> (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
268 | 273 | ||
269 | if (likely(cur_index != index)) { | 274 | if (likely(cur_index != index)) { |
270 | page = ufs_get_locked_page(mapping, index); | 275 | page = ufs_get_locked_page(mapping, index); |
271 | if (!page || IS_ERR(page)) /* it was truncated or EIO */ | 276 | if (!page)/* it was truncated */ |
277 | continue; | ||
278 | if (IS_ERR(page)) {/* or EIO */ | ||
279 | ufs_error(inode->i_sb, __FUNCTION__, | ||
280 | "read of page %llu failed\n", | ||
281 | (unsigned long long)index); | ||
272 | continue; | 282 | continue; |
283 | } | ||
273 | } else | 284 | } else |
274 | page = locked_page; | 285 | page = locked_page; |
275 | 286 | ||
276 | head = page_buffers(page); | 287 | head = page_buffers(page); |
277 | bh = head; | 288 | bh = head; |
278 | pos = beg & mask; | 289 | pos = i & mask; |
279 | for (j = 0; j < pos; ++j) | 290 | for (j = 0; j < pos; ++j) |
280 | bh = bh->b_this_page; | 291 | bh = bh->b_this_page; |
281 | j = 0; | 292 | |
293 | |||
294 | if (unlikely(index == last_index)) | ||
295 | lblock = end & mask; | ||
296 | else | ||
297 | lblock = blks_per_page; | ||
298 | |||
282 | do { | 299 | do { |
283 | if (buffer_mapped(bh)) { | 300 | if (j >= lblock) |
284 | pos = bh->b_blocknr - oldb; | 301 | break; |
285 | if (pos < count) { | 302 | pos = (i - beg) + j; |
286 | UFSD(" change from %llu to %llu\n", | 303 | |
287 | (unsigned long long)pos + oldb, | 304 | if (!buffer_mapped(bh)) |
288 | (unsigned long long)pos + newb); | 305 | map_bh(bh, inode->i_sb, oldb + pos); |
289 | bh->b_blocknr = newb + pos; | 306 | if (!buffer_uptodate(bh)) { |
290 | unmap_underlying_metadata(bh->b_bdev, | 307 | ll_rw_block(READ, 1, &bh); |
291 | bh->b_blocknr); | 308 | wait_on_buffer(bh); |
292 | mark_buffer_dirty(bh); | 309 | if (!buffer_uptodate(bh)) { |
293 | ++j; | 310 | ufs_error(inode->i_sb, __FUNCTION__, |
311 | "read of block failed\n"); | ||
312 | break; | ||
294 | } | 313 | } |
295 | } | 314 | } |
296 | 315 | ||
316 | UFSD(" change from %llu to %llu, pos %u\n", | ||
317 | (unsigned long long)pos + oldb, | ||
318 | (unsigned long long)pos + newb, pos); | ||
319 | |||
320 | bh->b_blocknr = newb + pos; | ||
321 | unmap_underlying_metadata(bh->b_bdev, | ||
322 | bh->b_blocknr); | ||
323 | mark_buffer_dirty(bh); | ||
324 | ++j; | ||
297 | bh = bh->b_this_page; | 325 | bh = bh->b_this_page; |
298 | } while (bh != head); | 326 | } while (bh != head); |
299 | 327 | ||
300 | if (j) | ||
301 | set_page_dirty(page); | ||
302 | |||
303 | if (likely(cur_index != index)) | 328 | if (likely(cur_index != index)) |
304 | ufs_put_locked_page(page); | 329 | ufs_put_locked_page(page); |
305 | } | 330 | } |
@@ -457,8 +482,9 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
457 | if (result) { | 482 | if (result) { |
458 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, | 483 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, |
459 | locked_page != NULL); | 484 | locked_page != NULL); |
460 | ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp, | 485 | ufs_change_blocknr(inode, fragment - oldcount, oldcount, |
461 | result, locked_page); | 486 | uspi->s_sbbase + tmp, |
487 | uspi->s_sbbase + result, locked_page); | ||
462 | ufs_cpu_to_data_ptr(sb, p, result); | 488 | ufs_cpu_to_data_ptr(sb, p, result); |
463 | *err = 0; | 489 | *err = 0; |
464 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); | 490 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); |
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index b868878009b6..c28a8b6f2feb 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c | |||
@@ -343,9 +343,8 @@ cg_found: | |||
343 | lock_buffer(bh); | 343 | lock_buffer(bh); |
344 | ufs2_inode = (struct ufs2_inode *)bh->b_data; | 344 | ufs2_inode = (struct ufs2_inode *)bh->b_data; |
345 | ufs2_inode += ufs_inotofsbo(inode->i_ino); | 345 | ufs2_inode += ufs_inotofsbo(inode->i_ino); |
346 | ufs2_inode->ui_birthtime.tv_sec = | 346 | ufs2_inode->ui_birthtime = cpu_to_fs64(sb, CURRENT_TIME.tv_sec); |
347 | cpu_to_fs32(sb, CURRENT_TIME_SEC.tv_sec); | 347 | ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, CURRENT_TIME.tv_nsec); |
348 | ufs2_inode->ui_birthtime.tv_usec = 0; | ||
349 | mark_buffer_dirty(bh); | 348 | mark_buffer_dirty(bh); |
350 | unlock_buffer(bh); | 349 | unlock_buffer(bh); |
351 | if (sb->s_flags & MS_SYNCHRONOUS) | 350 | if (sb->s_flags & MS_SYNCHRONOUS) |
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index fb34ad03e224..f18b79122fa3 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
@@ -212,7 +212,7 @@ repeat: | |||
212 | brelse (result); | 212 | brelse (result); |
213 | goto repeat; | 213 | goto repeat; |
214 | } else { | 214 | } else { |
215 | *phys = tmp + blockoff; | 215 | *phys = uspi->s_sbbase + tmp + blockoff; |
216 | return NULL; | 216 | return NULL; |
217 | } | 217 | } |
218 | } | 218 | } |
@@ -282,9 +282,9 @@ repeat: | |||
282 | } | 282 | } |
283 | 283 | ||
284 | if (!phys) { | 284 | if (!phys) { |
285 | result = sb_getblk(sb, tmp + blockoff); | 285 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); |
286 | } else { | 286 | } else { |
287 | *phys = tmp + blockoff; | 287 | *phys = uspi->s_sbbase + tmp + blockoff; |
288 | result = NULL; | 288 | result = NULL; |
289 | *err = 0; | 289 | *err = 0; |
290 | *new = 1; | 290 | *new = 1; |
@@ -368,7 +368,7 @@ repeat: | |||
368 | brelse (result); | 368 | brelse (result); |
369 | goto repeat; | 369 | goto repeat; |
370 | } else { | 370 | } else { |
371 | *phys = tmp + blockoff; | 371 | *phys = uspi->s_sbbase + tmp + blockoff; |
372 | goto out; | 372 | goto out; |
373 | } | 373 | } |
374 | } | 374 | } |
@@ -389,9 +389,9 @@ repeat: | |||
389 | 389 | ||
390 | 390 | ||
391 | if (!phys) { | 391 | if (!phys) { |
392 | result = sb_getblk(sb, tmp + blockoff); | 392 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); |
393 | } else { | 393 | } else { |
394 | *phys = tmp + blockoff; | 394 | *phys = uspi->s_sbbase + tmp + blockoff; |
395 | *new = 1; | 395 | *new = 1; |
396 | } | 396 | } |
397 | 397 | ||
@@ -601,7 +601,7 @@ static void ufs_set_inode_ops(struct inode *inode) | |||
601 | ufs_get_inode_dev(inode->i_sb, UFS_I(inode))); | 601 | ufs_get_inode_dev(inode->i_sb, UFS_I(inode))); |
602 | } | 602 | } |
603 | 603 | ||
604 | static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) | 604 | static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) |
605 | { | 605 | { |
606 | struct ufs_inode_info *ufsi = UFS_I(inode); | 606 | struct ufs_inode_info *ufsi = UFS_I(inode); |
607 | struct super_block *sb = inode->i_sb; | 607 | struct super_block *sb = inode->i_sb; |
@@ -613,8 +613,10 @@ static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) | |||
613 | */ | 613 | */ |
614 | inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); | 614 | inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); |
615 | inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink); | 615 | inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink); |
616 | if (inode->i_nlink == 0) | 616 | if (inode->i_nlink == 0) { |
617 | ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); | 617 | ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); |
618 | return -1; | ||
619 | } | ||
618 | 620 | ||
619 | /* | 621 | /* |
620 | * Linux now has 32-bit uid and gid, so we can support EFT. | 622 | * Linux now has 32-bit uid and gid, so we can support EFT. |
@@ -643,9 +645,10 @@ static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) | |||
643 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) | 645 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) |
644 | ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; | 646 | ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; |
645 | } | 647 | } |
648 | return 0; | ||
646 | } | 649 | } |
647 | 650 | ||
648 | static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) | 651 | static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) |
649 | { | 652 | { |
650 | struct ufs_inode_info *ufsi = UFS_I(inode); | 653 | struct ufs_inode_info *ufsi = UFS_I(inode); |
651 | struct super_block *sb = inode->i_sb; | 654 | struct super_block *sb = inode->i_sb; |
@@ -658,8 +661,10 @@ static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) | |||
658 | */ | 661 | */ |
659 | inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode); | 662 | inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode); |
660 | inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink); | 663 | inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink); |
661 | if (inode->i_nlink == 0) | 664 | if (inode->i_nlink == 0) { |
662 | ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); | 665 | ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); |
666 | return -1; | ||
667 | } | ||
663 | 668 | ||
664 | /* | 669 | /* |
665 | * Linux now has 32-bit uid and gid, so we can support EFT. | 670 | * Linux now has 32-bit uid and gid, so we can support EFT. |
@@ -668,12 +673,12 @@ static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) | |||
668 | inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid); | 673 | inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid); |
669 | 674 | ||
670 | inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size); | 675 | inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size); |
671 | inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_atime.tv_sec); | 676 | inode->i_atime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_atime); |
672 | inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_ctime.tv_sec); | 677 | inode->i_ctime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_ctime); |
673 | inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_mtime.tv_sec); | 678 | inode->i_mtime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_mtime); |
674 | inode->i_mtime.tv_nsec = 0; | 679 | inode->i_atime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_atimensec); |
675 | inode->i_atime.tv_nsec = 0; | 680 | inode->i_ctime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_ctimensec); |
676 | inode->i_ctime.tv_nsec = 0; | 681 | inode->i_mtime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_mtimensec); |
677 | inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); | 682 | inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); |
678 | inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen); | 683 | inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen); |
679 | ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); | 684 | ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); |
@@ -690,6 +695,7 @@ static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) | |||
690 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) | 695 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) |
691 | ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; | 696 | ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; |
692 | } | 697 | } |
698 | return 0; | ||
693 | } | 699 | } |
694 | 700 | ||
695 | void ufs_read_inode(struct inode * inode) | 701 | void ufs_read_inode(struct inode * inode) |
@@ -698,6 +704,7 @@ void ufs_read_inode(struct inode * inode) | |||
698 | struct super_block * sb; | 704 | struct super_block * sb; |
699 | struct ufs_sb_private_info * uspi; | 705 | struct ufs_sb_private_info * uspi; |
700 | struct buffer_head * bh; | 706 | struct buffer_head * bh; |
707 | int err; | ||
701 | 708 | ||
702 | UFSD("ENTER, ino %lu\n", inode->i_ino); | 709 | UFSD("ENTER, ino %lu\n", inode->i_ino); |
703 | 710 | ||
@@ -720,14 +727,17 @@ void ufs_read_inode(struct inode * inode) | |||
720 | if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { | 727 | if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { |
721 | struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; | 728 | struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; |
722 | 729 | ||
723 | ufs2_read_inode(inode, | 730 | err = ufs2_read_inode(inode, |
724 | ufs2_inode + ufs_inotofsbo(inode->i_ino)); | 731 | ufs2_inode + ufs_inotofsbo(inode->i_ino)); |
725 | } else { | 732 | } else { |
726 | struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data; | 733 | struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data; |
727 | 734 | ||
728 | ufs1_read_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino)); | 735 | err = ufs1_read_inode(inode, |
736 | ufs_inode + ufs_inotofsbo(inode->i_ino)); | ||
729 | } | 737 | } |
730 | 738 | ||
739 | if (err) | ||
740 | goto bad_inode; | ||
731 | inode->i_version++; | 741 | inode->i_version++; |
732 | ufsi->i_lastfrag = | 742 | ufsi->i_lastfrag = |
733 | (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; | 743 | (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; |
@@ -803,12 +813,12 @@ static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode) | |||
803 | ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid); | 813 | ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid); |
804 | 814 | ||
805 | ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); | 815 | ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); |
806 | ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec); | 816 | ufs_inode->ui_atime = cpu_to_fs64(sb, inode->i_atime.tv_sec); |
807 | ufs_inode->ui_atime.tv_usec = 0; | 817 | ufs_inode->ui_atimensec = cpu_to_fs32(sb, inode->i_atime.tv_nsec); |
808 | ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec); | 818 | ufs_inode->ui_ctime = cpu_to_fs64(sb, inode->i_ctime.tv_sec); |
809 | ufs_inode->ui_ctime.tv_usec = 0; | 819 | ufs_inode->ui_ctimensec = cpu_to_fs32(sb, inode->i_ctime.tv_nsec); |
810 | ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec); | 820 | ufs_inode->ui_mtime = cpu_to_fs64(sb, inode->i_mtime.tv_sec); |
811 | ufs_inode->ui_mtime.tv_usec = 0; | 821 | ufs_inode->ui_mtimensec = cpu_to_fs32(sb, inode->i_mtime.tv_nsec); |
812 | 822 | ||
813 | ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks); | 823 | ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks); |
814 | ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); | 824 | ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); |
@@ -888,6 +898,8 @@ void ufs_delete_inode (struct inode * inode) | |||
888 | loff_t old_i_size; | 898 | loff_t old_i_size; |
889 | 899 | ||
890 | truncate_inode_pages(&inode->i_data, 0); | 900 | truncate_inode_pages(&inode->i_data, 0); |
901 | if (is_bad_inode(inode)) | ||
902 | goto no_delete; | ||
891 | /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ | 903 | /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ |
892 | lock_kernel(); | 904 | lock_kernel(); |
893 | mark_inode_dirty(inode); | 905 | mark_inode_dirty(inode); |
@@ -898,4 +910,7 @@ void ufs_delete_inode (struct inode * inode) | |||
898 | ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n"); | 910 | ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n"); |
899 | ufs_free_inode (inode); | 911 | ufs_free_inode (inode); |
900 | unlock_kernel(); | 912 | unlock_kernel(); |
913 | return; | ||
914 | no_delete: | ||
915 | clear_inode(inode); /* We must guarantee clearing of inode... */ | ||
901 | } | 916 | } |
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 749581fa7729..79c54c85fb58 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c | |||
@@ -74,7 +74,7 @@ static int ufs_trunc_direct(struct inode *inode) | |||
74 | unsigned i, tmp; | 74 | unsigned i, tmp; |
75 | int retry; | 75 | int retry; |
76 | 76 | ||
77 | UFSD("ENTER\n"); | 77 | UFSD("ENTER: ino %lu\n", inode->i_ino); |
78 | 78 | ||
79 | sb = inode->i_sb; | 79 | sb = inode->i_sb; |
80 | uspi = UFS_SB(sb)->s_uspi; | 80 | uspi = UFS_SB(sb)->s_uspi; |
@@ -96,8 +96,8 @@ static int ufs_trunc_direct(struct inode *inode) | |||
96 | block2 = ufs_fragstoblks (frag3); | 96 | block2 = ufs_fragstoblks (frag3); |
97 | } | 97 | } |
98 | 98 | ||
99 | UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu," | 99 | UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu," |
100 | " frag4 %llu\n", | 100 | " frag3 %llu, frag4 %llu\n", inode->i_ino, |
101 | (unsigned long long)frag1, (unsigned long long)frag2, | 101 | (unsigned long long)frag1, (unsigned long long)frag2, |
102 | (unsigned long long)block1, (unsigned long long)block2, | 102 | (unsigned long long)block1, (unsigned long long)block2, |
103 | (unsigned long long)frag3, (unsigned long long)frag4); | 103 | (unsigned long long)frag3, (unsigned long long)frag4); |
@@ -163,7 +163,7 @@ next1: | |||
163 | mark_inode_dirty(inode); | 163 | mark_inode_dirty(inode); |
164 | next3: | 164 | next3: |
165 | 165 | ||
166 | UFSD("EXIT\n"); | 166 | UFSD("EXIT: ino %lu\n", inode->i_ino); |
167 | return retry; | 167 | return retry; |
168 | } | 168 | } |
169 | 169 | ||
@@ -248,7 +248,7 @@ static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p) | |||
248 | } | 248 | } |
249 | ubh_brelse (ind_ubh); | 249 | ubh_brelse (ind_ubh); |
250 | 250 | ||
251 | UFSD("EXIT\n"); | 251 | UFSD("EXIT: ino %lu\n", inode->i_ino); |
252 | 252 | ||
253 | return retry; | 253 | return retry; |
254 | } | 254 | } |
@@ -262,7 +262,7 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) | |||
262 | void *dind; | 262 | void *dind; |
263 | int retry = 0; | 263 | int retry = 0; |
264 | 264 | ||
265 | UFSD("ENTER\n"); | 265 | UFSD("ENTER: ino %lu\n", inode->i_ino); |
266 | 266 | ||
267 | sb = inode->i_sb; | 267 | sb = inode->i_sb; |
268 | uspi = UFS_SB(sb)->s_uspi; | 268 | uspi = UFS_SB(sb)->s_uspi; |
@@ -312,7 +312,7 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) | |||
312 | } | 312 | } |
313 | ubh_brelse (dind_bh); | 313 | ubh_brelse (dind_bh); |
314 | 314 | ||
315 | UFSD("EXIT\n"); | 315 | UFSD("EXIT: ino %lu\n", inode->i_ino); |
316 | 316 | ||
317 | return retry; | 317 | return retry; |
318 | } | 318 | } |
@@ -327,7 +327,7 @@ static int ufs_trunc_tindirect(struct inode *inode) | |||
327 | void *tind, *p; | 327 | void *tind, *p; |
328 | int retry; | 328 | int retry; |
329 | 329 | ||
330 | UFSD("ENTER\n"); | 330 | UFSD("ENTER: ino %lu\n", inode->i_ino); |
331 | 331 | ||
332 | retry = 0; | 332 | retry = 0; |
333 | 333 | ||
@@ -348,7 +348,7 @@ static int ufs_trunc_tindirect(struct inode *inode) | |||
348 | } | 348 | } |
349 | 349 | ||
350 | for (i = tindirect_block ; i < uspi->s_apb ; i++) { | 350 | for (i = tindirect_block ; i < uspi->s_apb ; i++) { |
351 | tind = ubh_get_addr32 (tind_bh, i); | 351 | tind = ubh_get_data_ptr(uspi, tind_bh, i); |
352 | retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + | 352 | retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + |
353 | uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind); | 353 | uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind); |
354 | ubh_mark_buffer_dirty(tind_bh); | 354 | ubh_mark_buffer_dirty(tind_bh); |
@@ -372,19 +372,21 @@ static int ufs_trunc_tindirect(struct inode *inode) | |||
372 | } | 372 | } |
373 | ubh_brelse (tind_bh); | 373 | ubh_brelse (tind_bh); |
374 | 374 | ||
375 | UFSD("EXIT\n"); | 375 | UFSD("EXIT: ino %lu\n", inode->i_ino); |
376 | return retry; | 376 | return retry; |
377 | } | 377 | } |
378 | 378 | ||
379 | static int ufs_alloc_lastblock(struct inode *inode) | 379 | static int ufs_alloc_lastblock(struct inode *inode) |
380 | { | 380 | { |
381 | int err = 0; | 381 | int err = 0; |
382 | struct super_block *sb = inode->i_sb; | ||
382 | struct address_space *mapping = inode->i_mapping; | 383 | struct address_space *mapping = inode->i_mapping; |
383 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; | 384 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
384 | unsigned i, end; | 385 | unsigned i, end; |
385 | sector_t lastfrag; | 386 | sector_t lastfrag; |
386 | struct page *lastpage; | 387 | struct page *lastpage; |
387 | struct buffer_head *bh; | 388 | struct buffer_head *bh; |
389 | u64 phys64; | ||
388 | 390 | ||
389 | lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; | 391 | lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; |
390 | 392 | ||
@@ -424,6 +426,20 @@ static int ufs_alloc_lastblock(struct inode *inode) | |||
424 | set_page_dirty(lastpage); | 426 | set_page_dirty(lastpage); |
425 | } | 427 | } |
426 | 428 | ||
429 | if (lastfrag >= UFS_IND_FRAGMENT) { | ||
430 | end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1; | ||
431 | phys64 = bh->b_blocknr + 1; | ||
432 | for (i = 0; i < end; ++i) { | ||
433 | bh = sb_getblk(sb, i + phys64); | ||
434 | lock_buffer(bh); | ||
435 | memset(bh->b_data, 0, sb->s_blocksize); | ||
436 | set_buffer_uptodate(bh); | ||
437 | mark_buffer_dirty(bh); | ||
438 | unlock_buffer(bh); | ||
439 | sync_dirty_buffer(bh); | ||
440 | brelse(bh); | ||
441 | } | ||
442 | } | ||
427 | out_unlock: | 443 | out_unlock: |
428 | ufs_put_locked_page(lastpage); | 444 | ufs_put_locked_page(lastpage); |
429 | out: | 445 | out: |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index e2bea6a661f0..69e9e80735d2 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -1829,11 +1829,11 @@ xfs_buf_init(void) | |||
1829 | if (!xfs_buf_zone) | 1829 | if (!xfs_buf_zone) |
1830 | goto out_free_trace_buf; | 1830 | goto out_free_trace_buf; |
1831 | 1831 | ||
1832 | xfslogd_workqueue = create_freezeable_workqueue("xfslogd"); | 1832 | xfslogd_workqueue = create_workqueue("xfslogd"); |
1833 | if (!xfslogd_workqueue) | 1833 | if (!xfslogd_workqueue) |
1834 | goto out_free_buf_zone; | 1834 | goto out_free_buf_zone; |
1835 | 1835 | ||
1836 | xfsdatad_workqueue = create_freezeable_workqueue("xfsdatad"); | 1836 | xfsdatad_workqueue = create_workqueue("xfsdatad"); |
1837 | if (!xfsdatad_workqueue) | 1837 | if (!xfsdatad_workqueue) |
1838 | goto out_destroy_xfslogd_workqueue; | 1838 | goto out_destroy_xfslogd_workqueue; |
1839 | 1839 | ||